<?php
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox, |
// | Stig. S. Bakken, Lukas Smith |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | MDB is a merge of PEAR DB and Metabases that provides a unified DB |
// | API as well as database abstraction for PHP applications. |
// | This LICENSE is in the BSD license style. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | |
// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken, |
// | Lukas Smith nor the names of his contributors may be used to endorse |
// | or promote products derived from this software without specific prior|
// | written permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Lukas Smith <smith@backendmedia.com> |
// +----------------------------------------------------------------------+
//
// $Id: Common.php,v 1.114.4.22 2004/04/08 19:11:58 lsmith Exp $
/**
* @package MDB
* @author Lukas Smith <smith@backendmedia.com>
*/
// }}}
// {{{ MDB_defaultDebugOutput()
/**
* default debug output handler
*
* @param object $db reference to an MDB database object
* @param string $message message that should be appended to the debug
* variable
* @return string the corresponding error message, of FALSE
* if the error code was unknown
* @access public
*/
function MDB_defaultDebugOutput(&$db, $message)
{
$db->debug_output .= $db->database . " $message" . $db->getOption('log_line_break');
}
/**
* MDB_Common: Base class that is extended by each MDB driver
*
* @package MDB
* @category Database
* @author Lukas Smith <smith@backendmedia.com>
*/
class MDB_Common extends PEAR
{
// {{{ properties
/**
* index of the MDB object withing the global $_MDB_databases array
* @var integer
* @access private
*/
var $database = 0;
/**
* @var string
* @access private
*/
var $host = '';
/**
* @var string
* @access private
*/
var $port = '';
/**
* @var string
* @access private
*/
var $user = '';
/**
* @var string
* @access private
*/
var $password = '';
/**
* @var string
* @access private
*/
var $database_name = '';
/**
* @var array
* @access private
*/
var $supported = array();
/**
* $options["persistent"] -> boolean persistent connection true|false?
* $options["debug"] -> integer numeric debug level
* $options["autofree"] -> boolean
* $options["lob_buffer_length"] -> integer LOB buffer length
* $options["log_line_break"] -> string line-break format
* $options["seqname_format"] -> string pattern for sequence name
* $options["includelob"] -> boolean
* $options["includemanager"] -> boolean
* $options["UseTransactions"] -> boolean
* $options["optimize"] -> string 'performance' or 'portability'
* @var array
* @access private
*/
var $options = array(
'persistent' => FALSE,
'debug' => FALSE,
'autofree' => FALSE,
'lob_buffer_length' => 8192,
'log_line_break' => "\n",
'seqname_format' => '%s_seq',
'sequence_col_name' => 'sequence',
'includelob' => FALSE,
'includemanager' => FALSE,
'UseTransactions' => FALSE,
'optimize' => 'performance',
);
/**
* @var string
* @access private
*/
var $escape_quotes = '';
/**
* @var integer
* @access private
*/
var $decimal_places = 2;
/**
* @var string
* @access private
*/
var $manager_included_constant = '';
/**
* @var string
* @access private
*/
var $manager_include = '';
/**
* @var string
* @access private
*/
var $manager_class_name = '';
/**
* @var object
* @access private
*/
var $manager;
/**
* @var array
* @access private
*/
var $warnings = array();
/**
* @var string
* @access private
*/
var $debug = '';
/**
* @var string
* @access private
*/
var $debug_output = '';
/**
* @var boolean
* @access private
*/
var $pass_debug_handle = FALSE;
/**
* @var boolean
* @access private
*/
var $auto_commit = TRUE;
/**
* @var boolean
* @access private
*/
var $in_transaction = FALSE;
/**
* @var integer
* @access private
*/
var $first_selected_row = 0;
/**
* @var integer
* @access private
*/
var $selected_row_limit = 0;
/**
* DB type (mysql, oci8, odbc etc.)
* @var string
* @access private
*/
var $type;
/**
* @var array
* @access private
*/
var $prepared_queries = array();
/**
* @var array
* @access private
*/
var $result_types;
/**
* @var string
* @access private
*/
var $last_query = '';
/**
* @var integer
* @access private
*/
var $fetchmode = MDB_FETCHMODE_ORDERED;
/**
* @var integer
* @access private
*/
var $affected_rows = -1;
/**
* @var array
* @access private
*/
var $lobs = array();
/**
* @var array
* @access private
*/
var $clobs = array();
/**
* @var array
* @access private
*/
var $blobs = array();
// }}}
// {{{ constructor
/**
* Constructor
*/
function MDB_Common()
{
$database = count($GLOBALS['_MDB_databases']) + 1;
$GLOBALS['_MDB_databases'][$database] = &$this;
$this->database = $database;
$this->PEAR('MDB_Error');
$this->supported = array();
$this->errorcode_map = array();
$this->fetchmode = MDB_FETCHMODE_ORDERED;
}
// }}}
// {{{ __toString()
/**
* String conversation
*
* @return string
* @access public
*/
function __toString()
{
$info = get_class($this);
$info .= ': (phptype = ' . $this->phptype . ', dbsyntax = ' . $this->dbsyntax . ')';
if ($this->connection) {
$info .= ' [connected]';
}
return($info);
}
// }}}
// {{{ errorCode()
/**
* Map native error codes to MDB's portable ones. Requires that
* the DB implementation's constructor fills in the $errorcode_map
* property.
*
* @param mixed $nativecode the native error code, as returned by the
* backend database extension (string or integer)
* @return int a portable MDB error code, or FALSE if this MDB
* implementation has no mapping for the given error code.
* @access public
*/
function errorCode($nativecode)
{
if (isset($this->errorcode_map[$nativecode])) {
return($this->errorcode_map[$nativecode]);
}
// Fall back to MDB_ERROR if there was no mapping.
return(MDB_ERROR);
}
// }}}
// {{{ errorMessage()
/**
* Map a MDB error code to a textual message. This is actually
* just a wrapper for MDB::errorMessage().
*
* @param integer $dbcode the MDB error code
* @return string the corresponding error message, of FALSE
* if the error code was unknown
* @access public
*/
function errorMessage($dbcode)
{
return(MDB::errorMessage($this->errorcode_map[$dbcode]));
}
// }}}
// {{{ raiseError()
/**
* This method is used to communicate an error and invoke error
* callbacks etc. Basically a wrapper for PEAR::raiseError
* without the message string.
*
* @param mixed $code integer error code, or a PEAR error object (all
* other parameters are ignored if this parameter is an object
* @param int $mode error mode, see PEAR_Error docs
* @param mixed $options If error mode is PEAR_ERROR_TRIGGER, this is the
* error level (E_USER_NOTICE etc). If error mode is
* PEAR_ERROR_CALLBACK, this is the callback function, either as a
* function name, or as an array of an object and method name. For
* other error modes this parameter is ignored.
* @param string $userinfo Extra debug information. Defaults to the last
* query and native error code.
* @param mixed $nativecode Native error code, integer or string depending
* the backend.
* @return object a PEAR error object
* @access public
* @see PEAR_Error
*/
function &raiseError($code = MDB_ERROR, $mode = NULL, $options = NULL,
$userinfo = NULL, $nativecode = NULL)
{
// The error is yet a MDB error object
if (is_object($code)) {
// because we the static PEAR::raiseError, our global
// handler should be used if it is set
if ($mode === null && !empty($this->_default_error_mode)) {
$mode = $this->_default_error_mode;
$options = $this->_default_error_options;
}
$err = PEAR::raiseError($code, NULL, $mode, $options, NULL, NULL, TRUE);
return($err);
}
if ($userinfo === NULL) {
$userinfo = $this->last_query;
}
if ($nativecode) {
$userinfo .= ' [nativecode=' . trim($nativecode) . ']';
}
$err = PEAR::raiseError(NULL, $code, $mode, $options, $userinfo, 'MDB_Error', TRUE);
return($err);
}
// }}}
// {{{ errorNative()
/**
* returns an errormessage, provides by the database
*
* @return mixed MDB_Error or message
* @access public
*/
function errorNative()
{
return($this->raiseError(MDB_ERROR_NOT_CAPABLE));
}
// }}}
// {{{ resetWarnings()
/**
* reset the warning array
*
* @access public
*/
function resetWarnings()
{
$this->warnings = array();
}
// }}}
// {{{ getWarnings()
/**
* get all warnings in reverse order.
* This means that the last warning is the first element in the array
*
* @return array with warnings
* @access public
* @see resetWarnings()
*/
function getWarnings()
{
return array_reverse($this->warnings);
}
// }}}
// {{{ setOption()
/**
* set the option for the db class
*
* @param string $option option name
* @param mixed $value value for the option
* @return mixed MDB_OK or MDB_Error
* @access public
*/
function setOption($option, $value)
{
if (isset($this->options[$option])) {
$this->options[$option] = $value;
return MDB_OK;
}
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, "unknown option $option"));
}
// }}}
// {{{ getOption()
/**
* returns the value of an option
*
* @param string $option option name
* @return mixed the option value or error object
* @access public
*/
function getOption($option)
{
if (isset($this->options[$option])) {
return($this->options[$option]);
}
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, "unknown option $option"));
}
// }}}
// {{{ captureDebugOutput()
/**
* set a debug handler
*
* @param string $capture name of the function that should be used in
* debug()
* @access public
* @see debug()
*/
function captureDebugOutput($capture)
{
$this->pass_debug_handle = $capture;
$this->debug = ($capture ? 'MDB_defaultDebugOutput' : '');
}
// }}}
// {{{ debug()
/**
* set a debug message
*
* @param string $message Message with information for the user.
* @access public
*/
function debug($message)
{
if (strcmp($function = $this->debug, '')) {
if ($this->pass_debug_handle) {
$function($this, $message);
} else {
$function($message);
}
}
}
// }}}
// {{{ debugOutput()
/**
* output debug info
*
* @return string content of the debug_output class variable
* @access public
*/
function debugOutput()
{
return($this->debug_output);
}
// }}}
// {{{ setError() (deprecated)
/**
* set an error (deprecated)
*
* @param string $scope Scope of the error message
* (usually the method tht caused the error)
* @param string $message Message with information for the user.
* @return boolean FALSE
* @access private
*/
function setError($scope, $message)
{
$this->last_error = $message;
$this->debug($scope . ': ' . $message);
if (($function = $this->error_handler) != '') {
$error = array(
'Scope' => $scope,
'Message' => $message
);
$function($this, $error);
}
return(0);
}
// }}}
// {{{ setErrorHandler() (deprecated)
/**
* Specify a function that is called when an error occurs.
*
* @param string $function Name of the function that will be called on
* error. If an empty string is specified, no handler function is
* called on error. The error handler function receives two arguments.
* The first argument a reference to the driver class object that
* triggered the error.
*
* The second argument is a reference to an associative array that
* provides details about the error that occured. These details provide
* more information than it is returned by the MetabaseError function.
*
* These are the currently supported error detail entries:
*
* Scope
* String that indicates the scope of the driver object class
* within which the error occured.
*
* Message
* Error message as is returned by the MetabaseError function.
* @return string name of last function
* @access public
*/
function setErrorHandler($function)
{
$last_function = $this->error_handler;
$this->error_handler = $function;
return($last_function);
}
// }}}
// {{{ error() (deprecated)
/**
* Retrieve the error message text associated with the last operation that
* failed. Some functions may fail but they do not return the reason that
* makes them to fail. This function is meant to retrieve a textual
* description of the failure cause.
*
* @return string the error message text associated with the last failure.
* @access public
*/
function error()
{
return($this->last_error);
}
// }}}
// {{{ _quote()
/**
* Quotes a string so it can be safely used in a query. It will quote
* the text so it can safely be used within a query.
*
* @param string $text the input string to quote
* @return string quoted string
* @access private
*/
function _quote($text)
{
if (strcmp($this->escape_quotes, "'")) {
$text = str_replace($this->escape_quotes, $this->escape_quotes . $this->escape_quotes, $text);
}
return str_replace("'", $this->escape_quotes . "'", $text);
}
// }}}
// {{{ quoteIdentifier()
/**
* Quote a string so it can be safely used as a table or column name
*
* Delimiting style depends on which database driver is being used.
*
* NOTE: just because you CAN use delimited identifiers doesn't mean
* you SHOULD use them. In general, they end up causing way more
* problems than they solve.
*
* Portability is broken by using the following characters inside
* delimited identifiers:
* + backtick (<kbd>`</kbd>) -- due to MySQL
* + double quote (<kbd>"</kbd>) -- due to Oracle
* + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access
*
* Delimited identifiers are known to generally work correctly under
* the following drivers:
* + mssql
* + mysql
* + mysqli
* + oci8
* + odbc(access)
* + odbc(db2)
* + pgsql
* + sqlite
* + sybase
*
* InterBase doesn't seem to be able to use delimited identifiers
* via PHP 4. They work fine under PHP 5.
*
* @param string $str identifier name to be quoted
*
* @return string quoted identifier string
*
* @access public
*/
function quoteIdentifier($str)
{
return '"' . str_replace('"', '""', $str) . '"';
}
// }}}
// {{{ _loadModule()
/**
* loads an module
*
* @param string $scope information about what method is being loaded,
* that is used for error messages
* @param string $module name of the module that should be loaded
* (only used for error messages)
* @param string $included_constant name of the constant that should be
* defined when the module has been loaded
* @param string $include name of the script that includes the module
* @access private
*/
function _loadModule($scope, $module, $included_constant, $include)
{
if (strlen($included_constant) == 0 || !defined($included_constant)) {
if($include) {
$include = 'MDB/Modules/'.$include;
if(MDB::isError($debug = $this->getOption('debug')) || $debug > 2) {
include_once($include);
} else {
@include_once($include);
}
} else {
return($this->raiseError(MDB_ERROR_LOADMODULE, NULL, NULL,
$scope . ': it was not specified an existing ' . $module . ' file (' . $include . ')'));
}
}
return(MDB_OK);
}
// }}}
// {{{ loadLob()
/**
* loads the LOB module
*
* @param string $scope information about what method is being loaded,
* that is used for error messages
* @access public
*/
function loadLob($scope = '')
{
if (defined('MDB_LOB_INCLUDED')) {
return(MDB_OK);
}
$result = $this->_loadModule($scope, 'LOB',
'MDB_LOB_INCLUDED', 'LOB.php');
if (MDB::isError($result)) {
return($result);
}
return(MDB_OK);
}
// }}}
// {{{ loadManager()
/**
* loads the Manager module
*
* @param string $scope information about what method is being loaded,
* that is used for error messages
* @access public
*/
function loadManager($scope = '')
{
if (isset($this->manager) && is_object($this->manager)) {
return(MDB_OK);
}
$result = $this->_loadModule($scope, 'Manager',
'MDB_MANAGER_'.strtoupper($this->phptype).'_INCLUDED',
'Manager/'.$this->phptype.'.php');
if (MDB::isError($result)) {
return($result);
}
$class_name = 'MDB_Manager_'.$this->dbsyntax;
if (!class_exists($class_name)) {
return($this->raiseError(MDB_ERROR_LOADMODULE, NULL, NULL,
'Unable to load extension'));
}
@$this->manager = new $class_name;
return(MDB_OK);
}
// }}}
// {{{ autoCommit()
/**
* Define whether database changes done on the database be automatically
* committed. This function may also implicitly start or end a transaction.
*
* @param boolean $auto_commit flag that indicates whether the database
* changes should be committed right after executing every query
* statement. If this argument is 0 a transaction implicitly started.
* Otherwise, if a transaction is in progress it is ended by committing
* any database changes that were pending.
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function autoCommit($auto_commit)
{
$this->debug('AutoCommit: ' . ($auto_commit ? 'On' : 'Off'));
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
'Auto-commit transactions: transactions are not supported'));
}
// }}}
// {{{ commit()
/**
* Commit the database changes done during a transaction that is in
* progress. This function may only be called when auto-committing is
* disabled, otherwise it will fail. Therefore, a new transaction is
* implicitly started after committing the pending changes.
*
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function commit()
{
$this->debug('Commit Transaction');
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
'Commit transaction: commiting transactions are not supported'));
}
// }}}
// {{{ rollback()
/**
* Cancel any database changes done during a transaction that is in
* progress. This function may only be called when auto-committing is
* disabled, otherwise it will fail. Therefore, a new transaction is
* implicitly started after canceling the pending changes.
*
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function rollback()
{
$this->debug('Rollback Transaction');
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
'Rollback transaction: rolling back transactions are not supported'));
}
// }}}
// {{{ disconnect()
/**
* Log out and disconnect from the database.
*
* @return mixed TRUE on success, FALSE if not connected and error
* object on error
* @access public
*/
function disconnect()
{
if ($this->in_transaction && !MDB::isError($this->rollback()) && !MDB::isError($this->autoCommit(TRUE))) {
$this->in_transaction = FALSE;
}
return($this->_close());
}
// }}}
// {{{ _close()
/**
* all the RDBMS specific things needed to close a DB connection
*
* @access private
*/
function _close()
{
unset($GLOBALS['_MDB_databases'][$this->database]);
}
// }}}
// {{{ setDatabase()
/**
* Select a different database
*
* @param string $name name of the database that should be selected
* @return string name of the database previously connected to
* @access public
*/
function setDatabase($name)
{
$previous_database_name = $this->database_name;
$this->database_name = $name;
return($previous_database_name);
}
// }}}
// {{{ setDSN()
/**
* set the DSN
*
* @param mixed $dsninfo DSN string or array
* @return MDB_OK
* @access public
*/
function setDSN($dsn)
{
$dsninfo = MDB::parseDSN($dsn);
if(isset($dsninfo['hostspec'])) {
$this->host = $dsninfo['hostspec'];
}
if(isset($dsninfo['port'])) {
$this->port = $dsninfo['port'];
}
if(isset($dsninfo['username'])) {
$this->user = $dsninfo['username'];
}
if(isset($dsninfo['password'])) {
$this->password = $dsninfo['password'];
}
if(isset($dsninfo['database'])) {
$this->database_name = $dsninfo['database'];
}
return(MDB_OK);
}
// }}}
// {{{ getDSN()
/**
* return the DSN as a string
*
* @param string $type type to return
* @return mixed DSN in the chosen type
* @access public
*/
function getDSN($type = 'string')
{
switch($type) {
case 'array':
$dsn = array(
'phptype' => $this->phptype,
'username' => $this->user,
'password' => $this->password,
'hostspec' => $this->host,
'database' => $this->database_name
);
break;
default:
$dsn = $this->phptype.'://'.$this->user.':'
.$this->password.'@'.$this->host
.($this->port ? (':'.$this->port) : '')
.'/'.$this->database_name;
break;
}
return($dsn);
}
// }}}
// {{{ createDatabase()
/**
* create a new database
*
* @param string $name name of the database that should be created
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function createDatabase($name)
{
$result = $this->loadManager('Create database');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->createDatabase($this, $name));
}
// }}}
// {{{ dropDatabase()
/**
* drop an existing database
*
* @param string $name name of the database that should be dropped
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function dropDatabase($name)
{
$result = $this->loadManager('Drop database');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->dropDatabase($this, $name));
}
// }}}
// {{{ createTable()
/**
* create a new table
*
* @param string $name Name of the database that should be created
* @param array $fields Associative array that contains the definition of
* each field of the new table. The indexes of the array entries are
* the names of the fields of the table an the array entry values are
* associative arrays like those that are meant to be passed with the
* field definitions to get[Type]Declaration() functions.
*
* Example
* array(
* 'id' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* 'notnull' => 1
* 'default' => 0
* ),
* 'name' => array(
* 'type' => 'text',
* 'length' => 12
* ),
* 'password' => array(
* 'type' => 'text',
* 'length' => 12
* )
* );
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function createTable($name, $fields)
{
$result = $this->loadManager('Create table');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->createTable($this, $name, $fields));
}
// }}}
// {{{ dropTable()
/**
* drop an existing table
*
* @param string $name name of the table that should be dropped
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function dropTable($name)
{
$result = $this->loadManager('Drop table');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->dropTable($this, $name));
}
// }}}
// {{{ alterTable()
/**
* alter an existing table
*
* @param string $name name of the table that is intended to be changed.
* @param array $changes associative array that contains the details of
* each type of change that is intended to be performed. The types of
* changes that are currently supported are defined as follows:
*
* name
* New name for the table.
*
* AddedFields
* Associative array with the names of fields to be added as indexes of
* the array. The value of each entry of the array should be set to
* another associative array with the properties of the fields to be
* added. The properties of the fields should be the same as defined by
* the Metabase parser.
*
* Additionally, there should be an entry named Declaration that is
* expected to contain the portion of the field declaration already in
* DBMS specific SQL code as it is used in the CREATE TABLE statement.
*
* RemovedFields
* Associative array with the names of fields to be removed as indexes of
* the array. Currently the values assigned to each entry are ignored. An
* empty array should be used for future compatibility.
*
* RenamedFields
* Associative array with the names of fields to be renamed as indexes of
* the array. The value of each entry of the array should be set to another
* associative array with the entry named name with the new field name and
* the entry named Declaration that is expected to contain the portion of
* the field declaration already in DBMS specific SQL code as it is used
* in the CREATE TABLE statement.
*
* ChangedFields
* Associative array with the names of the fields to be changed as indexes
* of the array. Keep in mind that if it is intended to change either the
* name of a field and any other properties, the ChangedFields array
* entries should have the new names of the fields as array indexes.
*
* The value of each entry of the array should be set to another
* associative array with the properties of the fields to that are meant
* to be changed as array entries. These entries should be assigned to the
* new values of the respective properties. The properties of the fields
* should be the* same as defined by the Metabase parser.
*
* If the default property is meant to be added, removed or changed, there
* should also be an entry with index ChangedDefault assigned to 1.
* Similarly, if the notnull constraint is to be added or removed, there
* should also be an entry with index ChangedNotNull assigned to 1.
*
* Additionally, there should be an entry named Declaration that is
* expected to contain the portion of the field changed declaration
* already in DBMS specific SQL code as it is used in the CREATE TABLE
* statement.
*
* Example
* array(
* 'name' => 'userlist',
* 'AddedFields' => array(
* 'quota' => array(
* 'type' => 'integer',
* 'unsigned' => 1,
* 'Declaration' => 'quota INT'
* )
* ),
* 'RemovedFields' => array(
* 'file_limit' => array(),
* 'time_limit' => array()
* ),
* 'ChangedFields' => array(
* 'gender' => array(
* 'default' => 'M',
* 'ChangeDefault' => 1,
* 'Declaration' => "gender CHAR(1) DEFAULT 'M'"
* )
* ),
* 'RenamedFields' => array(
* 'sex' => array(
* 'name' => 'gender',
* 'Declaration' => "gender CHAR(1) DEFAULT 'M'"
* )
* )
* )
*
* @param boolean $check indicates whether the function should just check
* if the DBMS driver can perform the requested table alterations if
* the value is TRUE or actually perform them otherwise.
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function alterTable($name, $changes, $check)
{
$result = $this->loadManager('Alter table');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->alterTable($this, $name, $changes, $check));
}
// }}}
// {{{ listDatabases()
/**
* list all databases
*
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function listDatabases()
{
$result = $this->loadManager('List databases');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->listDatabases($this));
}
// }}}
// {{{ listUsers()
/**
* list all users
*
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function listUsers()
{
$result = $this->loadManager('List users');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->listUsers($this));
}
// }}}
// {{{ listViews()
/**
* list all viewes in the current database
*
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function listViews()
{
$result = $this->loadManager('List views');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->listViews($this));
}
// }}}
// {{{ listFunctions()
/**
* list all functions in the current database
*
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function listFunctions()
{
$result = $this->loadManager('List functions');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->listFunctions($this));
}
// }}}
// {{{ listTables()
/**
* list all tables in the current database
*
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function listTables()
{
$result = $this->loadManager('List tables');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->listTables($this));
}
// }}}
// {{{ listTableFields()
/**
* list all fields in a tables in the current database
*
* @param string $table name of table that should be used in method
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function listTableFields($table)
{
$result = $this->loadManager('List table fields');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->listTableFields($this, $table));
}
// }}}
// {{{ getTableFieldDefinition()
/**
* get the stucture of a field into an array
*
* @param string $table name of table that should be used in method
* @param string $fields name of field that should be used in method
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function getTableFieldDefinition($table, $field)
{
$result = $this->loadManager('Get table field definition');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->getTableFieldDefinition($this, $table, $field));
}
// }}}
// {{{ getFieldDeclaration()
/**
* get declaration of a field
*
* @param string $field_name name of the field to be created
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* default
* Boolean value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to NULL.
* @return mixed string on success, a MDB error on failure
* @access public
*/
function getFieldDeclaration($field_name, $field)
{
$result = $this->loadManager('Get table field definition');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->getFieldDeclaration($this, $field_name, $field));
}
// }}}
// {{{ getFieldDeclarationList()
/**
* get declaration of a number of field in bulk
*
* @param string $fields a multidimensional associative array.
* The first dimension determines the field name, while the second
* dimension is keyed with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* default
* Boolean value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to NULL.
*
* default
* Boolean value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to NULL.
* @return mixed string on success, a MDB error on failure
* @access public
*/
function getFieldDeclarationList($fields)
{
$result = $this->loadManager('Get table field list');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->getFieldDeclarationList($this, $fields));
}
// }}}
// {{{ _isSequenceName()
/**
* list all tables in the current database
*
* @param string $sqn string that containts name of a potential sequence
* @return mixed name of the sequence if $sqn is a name of a sequence, else FALSE
* @access private
*/
function _isSequenceName($sqn)
{
$result = $this->loadManager('is sequence name');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->_isSequenceName($this, $sqn));
}
// }}}
// {{{ createIndex()
/**
* get the stucture of a field into an array
*
* @param string $table name of the table on which the index is to be
* created
* @param string $name name of the index to be created
* @param array $definition associative array that defines properties of
* the index to be created. Currently, only one property named FIELDS
* is supported. This property is also an associative with the names
* of the index fields as array indexes. Each entry of this array is
* set to another type of associative array that specifies properties
* of the index that are specific to each field.
*
* Currently, only the sorting property is supported. It should be
* used to define the sorting direction of the index. It may be set
* to either ascending or descending. Not all DBMS support index
* sorting direction configuration. The DBMS drivers of those that do
* not support it ignore this property. Use the function support() to
* determine whether the DBMS driver can manage indexes.
*
* Example
* array(
* 'FIELDS' => array(
* 'user_name' => array(
* 'sorting' => 'ascending'
* ),
* 'last_login' => array()
* )
* )
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function createIndex($table, $name, $definition)
{
$result = $this->loadManager('Create index');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->createIndex($this, $table, $name, $definition));
}
// }}}
// {{{ dropIndex()
/**
* drop existing index
*
* @param string $table name of table that should be used in method
* @param string $name name of the index to be dropped
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function dropIndex($table, $name)
{
$result = $this->loadManager('Drop index');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->dropIndex($this, $table , $name));
}
// }}}
// {{{ listTableIndexes()
/**
* list all indexes in a table
*
* @param string $table name of table that should be used in method
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function listTableIndexes($table)
{
$result = $this->loadManager('List table index');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->listTableIndexes($this, $table));
}
// }}}
// {{{ getTableIndexDefinition()
/**
* get the stucture of an index into an array
*
* @param string $table name of table that should be used in method
* @param string $index name of index that should be used in method
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function getTableIndexDefinition($table, $index)
{
$result = $this->loadManager('Get table index definition');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->getTableIndexDefinition($this, $table, $index));
}
// }}}
// {{{ createSequence()
/**
* create sequence
*
* @param string $name name of the sequence to be created
* @param string $start start value of the sequence; default is 1
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function createSequence($name, $start = 1)
{
$result = $this->loadManager('Create sequence');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->createSequence($this, $name, $start));
}
// }}}
// {{{ dropSequence()
/**
* drop existing sequence
*
* @param string $name name of the sequence to be dropped
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function dropSequence($name)
{
$result = $this->loadManager('Drop sequence');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->dropSequence($this, $name));
}
// }}}
// {{{ listSequences()
/**
* list all tables in the current database
*
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function listSequences()
{
$result = $this->loadManager('List sequences');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->listSequences($this));
}
// }}}
// {{{ getSequenceDefinition()
/**
* get the stucture of a sequence into an array
*
* @param string $sequence name of sequence that should be used in method
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function getSequenceDefinition($sequence)
{
$result = $this->loadManager('Get sequence definition');
if (MDB::isError($result)) {
return($result);
}
return($this->manager->getSequenceDefinition($this, $sequence));
}
// }}}
// {{{ query()
/**
* Send a query to the database and return any results
*
* @param string $query the SQL query
* @param mixed $types array that contains the types of the columns in
* the result set
* @return mixed a result handle or MDB_OK on success, a MDB error on failure
* @access public
*/
function query($query, $types = NULL)
{
$this->debug("Query: $query");
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Query: database queries are not implemented'));
}
// }}}
// {{{ setSelectedRowRange()
/**
* set the range of the next query
*
* @param string $first first row to select
* @param string $limit number of rows to select
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function setSelectedRowRange($first, $limit)
{
if (!isset($this->supported['SelectRowRanges'])) {
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
'Set selected row range: selecting row ranges is not supported by this driver'));
}
$first = (int)$first;
if ($first < 0) {
return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
'Set selected row range: it was not specified a valid first selected range row'));
}
$limit = (int)$limit;
if ($limit < 1) {
return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
'Set selected row range: it was not specified a valid selected range row limit'));
}
$this->first_selected_row = $first;
$this->selected_row_limit = $limit;
return(MDB_OK);
}
// }}}
// {{{ limitQuery()
/**
* Generates a limited query
*
* @param string $query query
* @param mixed $types array that contains the types of the columns in
* the result set
* @param integer $from the row to start to fetching
* @param integer $count the numbers of rows to fetch
* @return mixed a valid ressource pointer or a MDB_Error
* @access public
*/
function limitQuery($query, $types = NULL, $from, $count)
{
$result = $this->setSelectedRowRange($from, $count);
if (MDB::isError($result)) {
return($result);
}
return($this->query($query, $types));
}
// }}}
// {{{ subSelect()
/**
* simple subselect emulation: leaves the query untouched for all RDBMS
* that support subselects
*
* @access public
*
* @param string $query the SQL query for the subselect that may only
* return a column
* @param string $quote determines if the data needs to be quoted before
* being returned
*
* @return string the query
*/
function subSelect($query, $quote = FALSE)
{
if ($this->supported['SubSelects'] == 1) {
return($query);
}
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Subselect: subselect not implemented'));
}
// }}}
// {{{ replace()
/**
* Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
* query, except that if there is already a row in the table with the same
* key field values, the REPLACE query just updates its values instead of
* inserting a new row.
*
* The REPLACE type of query does not make part of the SQL standards. Since
* pratically only MySQL implements it natively, this type of query is
* emulated through this method for other DBMS using standard types of
* queries inside a transaction to assure the atomicity of the operation.
*
* @param string $table name of the table on which the REPLACE query will
* be executed.
* @param array $fields associative array that describes the fields and the
* values that will be inserted or updated in the specified table. The
* indexes of the array are the names of all the fields of the table.
* The values of the array are also associative arrays that describe
* the values and other properties of the table fields.
*
* Here follows a list of field properties that need to be specified:
*
* Value
* Value to be assigned to the specified field. This value may be
* of specified in database independent type format as this
* function can perform the necessary datatype conversions.
*
* Default: this property is required unless the Null property is
* set to 1.
*
* Type
* Name of the type of the field. Currently, all types Metabase
* are supported except for clob and blob.
*
* Default: no type conversion
*
* Null
* Boolean property that indicates that the value for this field
* should be set to NULL.
*
* The default value for fields missing in INSERT queries may be
* specified the definition of a table. Often, the default value
* is already NULL, but since the REPLACE may be emulated using
* an UPDATE query, make sure that all fields of the table are
* listed in this function argument array.
*
* Default: 0
*
* Key
* Boolean property that indicates that this field should be
* handled as a primary key or at least as part of the compound
* unique index of the table that will determine the row that will
* updated if it exists or inserted a new row otherwise.
*
* This function will fail if no key field is specified or if the
* value of a key field is set to NULL because fields that are
* part of unique index they may not be NULL.
*
* Default: 0
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function replace($table, $fields)
{
if (!$this->supported['Replace']) {
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Replace: replace query is not supported'));
}
$count = count($fields);
for($keys = 0, $condition = $insert = $values = '', reset($fields), $field = 0;
$field < $count;
next($fields), $field++)
{
$name = key($fields);
if ($field > 0) {
$insert .= ', ';
$values .= ', ';
}
$insert .= $name;
if (isset($fields[$name]['Null']) && $fields[$name]['Null']) {
$value = 'NULL';
} else {
if(isset($fields[$name]['Type'])) {
switch ($fields[$name]['Type']) {
case 'text':
$value = $this->getTextValue($fields[$name]['Value']);
break;
case 'boolean':
$value = $this->getBooleanValue($fields[$name]['Value']);
break;
case 'integer':
$value = $this->getIntegerValue($fields[$name]['Value']);
break;
case 'decimal':
$value = $this->getDecimalValue($fields[$name]['Value']);
break;
case 'float':
$value = $this->getFloatValue($fields[$name]['Value']);
break;
case 'date':
$value = $this->getDateValue($fields[$name]['Value']);
break;
case 'time':
$value = $this->getTimeValue($fields[$name]['Value']);
break;
case 'timestamp':
$value = $this->getTimestampValue($fields[$name]['Value']);
break;
default:
return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL,
'no supported type for field "' . $name . '" specified'));
}
} else {
$value = $fields[$name]['Value'];
}
}
$values .= $value;
if (isset($fields[$name]['Key']) && $fields[$name]['Key']) {
if ($value === 'NULL') {
return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL,
'key values may not be NULL'));
}
$condition .= ($keys ? ' AND ' : ' WHERE ') . $name . '=' . $value;
$keys++;
}
}
if ($keys == 0) {
return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL,
'not specified which fields are keys'));
}
$in_transaction = $this->in_transaction;
if (!$in_transaction && MDB::isError($result = $this->autoCommit(FALSE))) {
return($result);
}
$success = $this->query("DELETE FROM $table$condition");
if (!MDB::isError($success)) {
$affected_rows = $this->affected_rows;
$success = $this->query("INSERT INTO $table ($insert) VALUES ($values)");
$affected_rows += $this->affected_rows;
}
if (!$in_transaction) {
if (!MDB::isError($success)) {
if (!MDB::isError($success = $this->commit())
&& !MDB::isError($success = $this->autoCommit(TRUE))
&& isset($this->supported['AffectedRows'])
) {
$this->affected_rows = $affected_rows;
}
} else {
$this->rollback();
$this->autoCommit(TRUE);
}
}
return($success);
}
// }}}
// {{{ prepareQuery()
/**
* Prepares a query for multiple execution with execute().
* With some database backends, this is emulated.
* prepareQuery() requires a generic query as string like
* 'INSERT INTO numbers VALUES(?,?,?)'. The ? are wildcards.
* Types of wildcards:
* ? - a quoted scalar value, i.e. strings, integers
*
* @param string $ the query to prepare
* @return mixed resource handle for the prepared query on success, a DB
* error on failure
* @access public
* @see execute
*/
function prepareQuery($query)
{
$this->debug("PrepareQuery: $query");
$positions = array();
for($position = 0;
$position < strlen($query) && is_integer($question = strpos($query, '?', $position));
) {
if (is_integer($quote = strpos($query, "'", $position))
&& $quote < $question
) {
if (!is_integer($end_quote = strpos($query, "'", $quote + 1))) {
return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
'Prepare query: query with an unterminated text string specified'));
}
switch ($this->escape_quotes) {
case '':
case "'":
$position = $end_quote + 1;
break;
default:
if ($end_quote == $quote + 1) {
$position = $end_quote + 1;
} else {
if ($query[$end_quote-1] == $this->escape_quotes) {
$position = $end_quote;
} else {
$position = $end_quote + 1;
}
}
break;
}
} else {
$positions[] = $question;
$position = $question + 1;
}
}
$this->prepared_queries[] = array(
'Query' => $query,
'Positions' => $positions,
'Values' => array(),
'Types' => array()
);
$prepared_query = count($this->prepared_queries);
if ($this->selected_row_limit > 0) {
$this->prepared_queries[$prepared_query-1]['First'] = $this->first_selected_row;
$this->prepared_queries[$prepared_query-1]['Limit'] = $this->selected_row_limit;
}
return($prepared_query);
}
// }}}
// {{{ _validatePreparedQuery()
/**
* validate that a handle is infact a prepared query
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @access private
*/
function _validatePreparedQuery($prepared_query)
{
if ($prepared_query < 1 || $prepared_query > count($this->prepared_queries)) {
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
'Validate prepared query: invalid prepared query'));
}
if (gettype($this->prepared_queries[$prepared_query-1]) != 'array') {
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
'Validate prepared query: prepared query was already freed'));
}
return(MDB_OK);
}
// }}}
// {{{ freePreparedQuery()
/**
* Release resources allocated for the specified prepared query.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function freePreparedQuery($prepared_query)
{
$result = $this->_validatePreparedQuery($prepared_query);
if (MDB::isError($result)) {
return($result);
}
$this->prepared_queries[$prepared_query-1] = '';
return(MDB_OK);
}
// }}}
// {{{ _executePreparedQuery()
/**
* Execute a prepared query statement.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @param string $query query to be executed
* @param array $types array that contains the types of the columns in
* the result set
* @return mixed a result handle or MDB_OK on success, a MDB error on failure
* @access private
*/
function _executePreparedQuery($prepared_query, $query, $types = NULL)
{
return($this->query($query, $types));
}
// }}}
// {{{ executeQuery()
/**
* Execute a prepared query statement.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @param array $types array that contains the types of the columns in the
* result set
* @return mixed a result handle or MDB_OK on success, a MDB error on failure
* @access public
*/
function executeQuery($prepared_query, $types = NULL)
{
$result = $this->_validatePreparedQuery($prepared_query);
if (MDB::isError($result)) {
return($result);
}
$index = $prepared_query-1;
$success = MDB_OK;
$this->clobs[$prepared_query] = $this->blobs[$prepared_query] = array();
$query = '';
for($last_position = $position = 0;
$position < count($this->prepared_queries[$index]['Positions']);
$position++) {
if (!isset($this->prepared_queries[$index]['Values'][$position])) {
return($this->raiseError(MDB_ERROR_NEED_MORE_DATA, NULL, NULL,
'Execute query: it was not defined query argument '.($position + 1)));
}
$current_position = $this->prepared_queries[$index]['Positions'][$position];
$query .= substr($this->prepared_queries[$index]['Query'], $last_position, $current_position - $last_position);
$value = $this->prepared_queries[$index]['Values'][$position];
if ($this->prepared_queries[$index]['IsNULL'][$position]) {
$query .= $value;
} else {
switch ($this->prepared_queries[$index]['Types'][$position]) {
case 'clob':
if (!MDB::isError($success = $this->getClobValue($prepared_query, $position + 1, $value))) {
$this->clobs[$prepared_query][$position + 1] = $success;
$query .= $this->clobs[$prepared_query][$position + 1];
}
break;
case 'blob':
if (!MDB::isError($success = $this->getBlobValue($prepared_query, $position + 1, $value))) {
$this->blobs[$prepared_query][$position + 1] = $success;
$query .= $this->blobs[$prepared_query][$position + 1];
}
break;
default:
$query .= $value;
break;
}
}
$last_position = $current_position + 1;
}
if (!MDB::isError($success)) {
$query .= substr($this->prepared_queries[$index]['Query'], $last_position);
if ($this->selected_row_limit > 0) {
$this->prepared_queries[$index]['First'] = $this->first_selected_row;
$this->prepared_queries[$index]['Limit'] = $this->selected_row_limit;
}
if (isset($this->prepared_queries[$index]['Limit'])
&& $this->prepared_queries[$index]['Limit'] > 0
) {
$this->first_selected_row = $this->prepared_queries[$index]['First'];
$this->selected_row_limit = $this->prepared_queries[$index]['Limit'];
} else {
$this->first_selected_row = $this->selected_row_limit = 0;
}
$success = $this->_executePreparedQuery($prepared_query, $query, $types);
}
for(reset($this->clobs[$prepared_query]), $clob = 0;
$clob < count($this->clobs[$prepared_query]);
$clob++, next($this->clobs[$prepared_query])) {
$this->freeClobValue($prepared_query, key($this->clobs[$prepared_query]), $this->clobs[$prepared_query][key($this->clobs[$prepared_query])], $success);
}
unset($this->clobs[$prepared_query]);
for(reset($this->blobs[$prepared_query]), $blob = 0;
$blob < count($this->blobs[$prepared_query]);
$blob++, next($this->blobs[$prepared_query])) {
$this->freeBlobValue($prepared_query, key($this->blobs[$prepared_query]), $this->blobs[$prepared_query][key($this->blobs[$prepared_query])], $success);
}
unset($this->blobs[$prepared_query]);
return($success);
}
// }}}
// {{{ execute()
/**
* Executes a prepared SQL query
* With execute() the generic query of prepare is assigned with the given
* data array. The values of the array inserted into the query in the same
* order like the array order
*
* @param resource $prepared_query query handle from prepare()
* @param array $types array that contains the types of the columns in
* the result set
* @param array $params numeric array containing the data to insert into
* the query
* @param array $param_types array that contains the types of the values
* defined in $params
* @return mixed a new result handle or a MDB_Error when fail
* @access public
* @see prepare()
*/
function execute($prepared_query, $types = NULL, $params = FALSE, $param_types = NULL)
{
$this->setParamArray($prepared_query, $params, $param_types);
return($this->executeQuery($prepared_query, $types));
}
// }}}
// {{{ executeMultiple()
/**
* This function does several execute() calls on the same statement handle.
* $params must be an array indexed numerically from 0, one execute call is
* done for every 'row' in the array.
*
* If an error occurs during execute(), executeMultiple() does not execute
* the unfinished rows, but rather returns that error.
*
* @param resource $stmt query handle from prepare()
* @param array $types array that contains the types of the columns in
* the result set
* @param array $params numeric array containing the
* data to insert into the query
* @param array $parAM_types array that contains the types of the values
* defined in $params
* @return mixed a result handle or MDB_OK on success, a MDB error on failure
* @access public
* @see prepare(), execute()
*/
function executeMultiple($prepared_query, $types = NULL, $params, $param_types = NULL)
{
for($i = 0, $j = count($params); $i < $j; $i++) {
$result = $this->execute($prepared_query, $types, $params[$i], $param_types);
if (MDB::isError($result)) {
return($result);
}
}
return(MDB_OK);
}
// }}}
// {{{ setParam()
/**
* Set the value of a parameter of a prepared query.
*
* @param int $prepared_query argument is a handle that was returned
* by the function prepareQuery()
* @param int $parameter the order number of the parameter in the query
* statement. The order number of the first parameter is 1.
* @param string $type designation of the type of the parameter to be set.
* The designation of the currently supported types is as follows:
* text, boolean, integer, decimal, float, date, time, timestamp,
* clob, blob
* @param mixed $value value that is meant to be assigned to specified
* parameter. The type of the value depends on the $type argument.
* @param boolean $is_null flag that indicates whether whether the
* parameter is a NULL
* @param string $field name of the field that is meant to be assigned
* with this parameter value when it is of type clob or blob
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function setParam($prepared_query, $parameter, $type, $value, $is_null = 0, $field = '')
{
$result = $this->_validatePreparedQuery($prepared_query);
if (MDB::isError($result)) {
return($result);
}
$index = $prepared_query - 1;
if ($parameter < 1 || $parameter > count($this->prepared_queries[$index]['Positions'])) {
return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
'Query set: it was not specified a valid argument number'));
}
$this->prepared_queries[$index]['Values'][$parameter-1] = $value;
$this->prepared_queries[$index]['Types'][$parameter-1] = $type;
$this->prepared_queries[$index]['Fields'][$parameter-1] = $field;
$this->prepared_queries[$index]['IsNULL'][$parameter-1] = $is_null;
return(MDB_OK);
}
// }}}
// {{{ setParamArray()
/**
* Set the values of multiple a parameter of a prepared query in bulk.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @param array $params array thats specifies all necessary infromation
* for setParam() the array elements must use keys corresponding to
* the number of the position of the parameter.
* @param array $types array thats specifies the types of the fields
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
* @see setParam()
*/
function setParamArray($prepared_query, $params, $types = NULL)
{
if (is_array($types)) {
if (count($params) != count($types)) {
return $this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
'setParamArray: the number of given types ('.count($types).')'
.'is not corresponding to the number of given parameters ('.count($params).')');
}
for($i = 0, $j = count($params); $i < $j; ++$i) {
switch ($types[$i]) {
case 'NULL':
$success = $this->setParam($prepared_query, $i + 1, $params[$i][0], 'NULL', 1, '');
break;
case 'text':
$success = $this->setParam($prepared_query, $i + 1, 'text', $this->getTextValue($params[$i]));
break;
case 'clob':
$success = $this->setParam($prepared_query, $i + 1, 'clob', $params[$i][0], 0, $params[$i][1]);
break;
case 'blob':
$success = $this->setParam($prepared_query, $i + 1, 'blob', $params[$i][0], 0, $params[$i][1]);
break;
case 'integer':
$success = $this->setParam($prepared_query, $i + 1, 'integer', $this->getIntegerValue($params[$i]));
break;
case 'boolean':
$success = $this->setParam($prepared_query, $i + 1, 'boolean', $this->getBooleanValue($params[$i]));
break;
case 'date':
$success = $this->setParam($prepared_query, $i + 1, 'date', $this->getDateValue($params[$i]));
break;
case 'timestamp':
$success = $this->setParam($prepared_query, $i + 1, 'timestamp', $this->getTimestampValue($params[$i]));
break;
case 'time':
$success = $this->setParam($prepared_query, $i + 1, 'time', $this->getTimeValue($params[$i]));
break;
case 'float':
$success = $this->setParam($prepared_query, $i + 1, 'float', $this->getFloatValue($params[$i]));
break;
case 'decimal':
$success = $this->setParam($prepared_query, $i + 1, 'decimal', $this->getDecimalValue($params[$i]));
break;
default:
$success = $this->setParam($prepared_query, $i + 1, 'text', $this->getTextValue($params[$i]));
break;
}
if (MDB::isError($success)) {
return($success);
}
}
} else {
for($i = 0, $j = count($params); $i < $j; ++$i) {
$success = $this->setParam($prepared_query, $i + 1, 'text', $this->getTextValue($params[$i]));
if (MDB::isError($success)) {
return($success);
}
}
}
return(MDB_OK);
}
// }}}
// {{{ setParamNull()
/**
* Set the value of a parameter of a prepared query to NULL.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @param int $parameter order number of the parameter in the query
* statement. The order number of the first parameter is 1.
* @param string $type designation of the type of the parameter to be set.
* The designation of the currently supported types is list in the
* usage of the function setParam()
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
* @see setParam()
*/
function setParamNull($prepared_query, $parameter, $type)
{
return($this->setParam($prepared_query, $parameter, $type, 'NULL', 1, ''));
}
// }}}
// {{{ setParamText()
/**
* Set a parameter of a prepared query with a text value.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @param int $parameter order number of the parameter in the query
* statement. The order number of the first parameter is 1.
* @param string $value text value that is meant to be assigned to
* specified parameter.
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
* @see setParam()
*/
function setParamText($prepared_query, $parameter, $value)
{
return($this->setParam($prepared_query, $parameter, 'text', $this->getTextValue($value)));
}
// }}}
// {{{ setParamClob()
/**
* Set a parameter of a prepared query with a character large object value.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @param int $parameter order number of the parameter in the query
* statement. The order number of the first parameter is 1.
* @param int $value handle of large object created with createLOB()
* function from which it will be read the data value that is meant
* to be assigned to specified parameter.
* @param string $field name of the field of a INSERT or UPDATE query to
* which it will be assigned the value to specified parameter.
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
* @see setParam()
*/
function setParamClob($prepared_query, $parameter, $value, $field)
{
return($this->setParam($prepared_query, $parameter, 'clob', $value, 0, $field));
}
// }}}
// {{{ setParamBlob()
/**
* Set a parameter of a prepared query with a binary large object value.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @param int $parameter order number of the parameter in the query
* statement. The order number of the first parameter is 1.
* @param int $value handle of large object created with createLOB()
* function from which it will be read the data value that is meant
* to be assigned to specified parameter.
* @param string $field name of the field of a INSERT or UPDATE query to
* which it will be assigned the value to specified parameter.
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
* @see setParam()
*/
function setParamBlob($prepared_query, $parameter, $value, $field)
{
return($this->setParam($prepared_query, $parameter, 'blob', $value, 0, $field));
}
// }}}
// {{{ setParamInteger()
/**
* Set a parameter of a prepared query with a text value.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @param int $parameter order number of the parameter in the query
* statement. The order number of the first parameter is 1.
* @param int $value an integer value that is meant to be assigned to
* specified parameter.
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
* @see setParam()
*/
function setParamInteger($prepared_query, $parameter, $value)
{
return($this->setParam($prepared_query, $parameter, 'integer', $this->getIntegerValue($value)));
}
// }}}
// {{{ setParamBoolean()
/**
* Set a parameter of a prepared query with a boolean value.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @param int $parameter order number of the parameter in the query
* statement. The order number of the first parameter is 1.
* @param boolean $value boolean value that is meant to be assigned to
* specified parameter.
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
* @see setParam()
*/
function setParamBoolean($prepared_query, $parameter, $value)
{
return($this->setParam($prepared_query, $parameter, 'boolean', $this->getBooleanValue($value)));
}
// }}}
// {{{ setParamDate()
/**
* Set a parameter of a prepared query with a date value.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @param int $parameter order number of the parameter in the query
* statement. The order number of the first parameter is 1.
* @param string $value date value that is meant to be assigned to
* specified parameter.
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
* @see setParam()
*/
function setParamDate($prepared_query, $parameter, $value)
{
return($this->setParam($prepared_query, $parameter, 'date', $this->getDateValue($value)));
}
// }}}
// {{{ setParamTimestamp()
/**
* Set a parameter of a prepared query with a time stamp value.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @param int $parameter order number of the parameter in the query
* statement. The order number of the first parameter is 1.
* @param string $value time stamp value that is meant to be assigned to
* specified parameter.
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
* @see setParam()
*/
function setParamTimestamp($prepared_query, $parameter, $value)
{
return($this->setParam($prepared_query, $parameter, 'timestamp', $this->getTimestampValue($value)));
}
// }}}
// {{{ setParamTime()
/**
* Set a parameter of a prepared query with a time value.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @param int $parameter order number of the parameter in the query
* statement. The order number of the first parameter is 1.
* @param string $value time value that is meant to be assigned to
* specified parameter.
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
* @see setParam()
*/
function setParamTime($prepared_query, $parameter, $value)
{
return($this->setParam($prepared_query, $parameter, 'time', $this->getTimeValue($value)));
}
// }}}
// {{{ setParamFloat()
/**
* Set a parameter of a prepared query with a float value.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @param int $parameter order number of the parameter in the query
* statement. The order number of the first parameter is 1.
* @param string $value float value that is meant to be assigned to
* specified parameter.
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
* @see setParam()
*/
function setParamFloat($prepared_query, $parameter, $value)
{
return($this->setParam($prepared_query, $parameter, 'float', $this->getFloatValue($value)));
}
// }}}
// {{{ setParamDecimal()
/**
* Set a parameter of a prepared query with a decimal value.
*
* @param int $prepared_query argument is a handle that was returned by
* the function prepareQuery()
* @param int $parameter order number of the parameter in the query
* statement. The order number of the first parameter is 1.
* @param string $value decimal value that is meant to be assigned to
* specified parameter.
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
* @see setParam()
*/
function setParamDecimal($prepared_query, $parameter, $value)
{
return($this->setParam($prepared_query, $parameter, 'decimal', $this->getDecimalValue($value)));
}
// }}}
// {{{ setResultTypes()
/**
* Define the list of types to be associated with the columns of a given
* result set.
*
* This function may be called before invoking fetchInto(), fetchOne(),
* fetchRow(), fetchCol() and fetchAll() so that the necessary data type
* conversions are performed on the data to be retrieved by them. If this
* function is not called, the type of all result set columns is assumed
* to be text, thus leading to not perform any conversions.
*
* @param resource $result result identifier
* @param string $types array variable that lists the
* data types to be expected in the result set columns. If this array
* contains less types than the number of columns that are returned
* in the result set, the remaining columns are assumed to be of the
* type text. Currently, the types clob and blob are not fully
* supported.
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function setResultTypes($result, $types)
{
$result_value = intval($result);
if (isset($this->result_types[$result_value])) {
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
'Set result types: attempted to redefine the types of the columns of a result set'));
}
$columns = $this->numCols($result);
if (MDB::isError($columns)) {
return($columns);
}
if ($columns < count($types)) {
return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
'Set result types: it were specified more result types (' . count($types) . ') than result columns (' . $columns . ')'));
}
$valid_types = array(
'text' => MDB_TYPE_TEXT,
'boolean' => MDB_TYPE_BOOLEAN,
'integer' => MDB_TYPE_INTEGER,
'decimal' => MDB_TYPE_DECIMAL,
'float' => MDB_TYPE_FLOAT,
'date' => MDB_TYPE_DATE,
'time' => MDB_TYPE_TIME,
'timestamp' => MDB_TYPE_TIMESTAMP,
'clob' => MDB_TYPE_CLOB,
'blob' => MDB_TYPE_BLOB
);
for($column = 0; $column < count($types); $column++) {
if (!isset($valid_types[$types[$column]])) {
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
'Set result types: ' . $types[$column] . ' is not a supported column type'));
}
$this->result_types[$result_value][$column] = $valid_types[$types[$column]];
}
while ($column < $columns) {
$this->result_types[$result_value][$column] = MDB_TYPE_TEXT;
$column++;
}
return(MDB_OK);
}
// }}}
// {{{ affectedRows()
/**
* returns the affected rows of a query
*
* @return mixed MDB_Error or number of rows
* @access public
*/
function affectedRows()
{
if ($this->affected_rows == -1) {
return($this->raiseError(MDB_ERROR_NEED_MORE_DATA));
}
return($this->affected_rows);
}
// }}}
// {{{ getColumnNames()
/**
* Retrieve the names of columns returned by the DBMS in a query result.
*
* @param resource $result result identifier
* @return mixed associative array variable
* that holds the names of columns. The indexes of the array are
* the column names mapped to lower case and the values are the
* respective numbers of the columns starting from 0. Some DBMS may
* not return any columns when the result set does not contain any
* rows.
* a MDB error on failure
* @access public
*/
function getColumnNames($result)
{
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
'Get column names: obtaining result column names is not implemented'));
}
// }}}
// {{{ numCols()
/**
* Count the number of columns returned by the DBMS in a query result.
*
* @param resource $result result identifier
* @return mixed integer value with the number of columns, a MDB error
* on failure
* @access public
*/
function numCols($result)
{
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
'Number of columns: obtaining the number of result columns is not implemented'));
}
// }}}
// {{{ endOfResult()
/**
* check if the end of the result set has been reached
*
* @param resource $result result identifier
* @return mixed TRUE or FALSE on sucess, a MDB error on failure
* @access public
*/
function endOfResult($result)
{
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
'End of result: end of result method not implemented'));
}
// }}}
// {{{ setFetchMode()
/**
* Sets which fetch mode should be used by default on queries
* on this connection.
*
* @param integer $fetchmode MDB_FETCHMODE_ORDERED or MDB_FETCHMODE_ASSOC,
* possibly bit-wise OR'ed with MDB_FETCHMODE_FLIPPED.
* @access public
* @see MDB_FETCHMODE_ORDERED
* @see MDB_FETCHMODE_ASSOC
* @see MDB_FETCHMODE_FLIPPED
*/
function setFetchMode($fetchmode)
{
switch ($fetchmode) {
case MDB_FETCHMODE_ORDERED:
case MDB_FETCHMODE_ASSOC:
$this->fetchmode = $fetchmode;
break;
default:
return($this->raiseError('invalid fetchmode mode'));
}
}
// }}}
// {{{ fetch()
/**
* fetch value from a result set
*
* @param resource $result result identifier
* @param int $row number of the row where the data can be found
* @param int $field field number where the data can be found
* @return mixed string on success, a MDB error on failure
* @access public
*/
function fetch($result, $row, $field)
{
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
'Fetch: fetch result method not implemented'));
}
// }}}
// {{{ fetchLob()
/**
* fetch a lob value from a result set
*
* @param resource $result result identifier
* @param int $row number of the row where the data can be found
* @param int $field field number where the data can be found
* @return mixed string on success, a MDB error on failure
* @access public
*/
function fetchLob($result, $row, $field)
{
$lob = count($this->lobs) + 1;
$this->lobs[$lob] = array(
'Result' => $result,
'Row' => $row,
'Field' => $field,
'Position' => 0
);
$dst_lob = array(
'Database' => $this,
'Error' => '',
'Type' => 'resultlob',
'ResultLOB' => $lob
);
if (MDB::isError($lob = $this->createLob($dst_lob))) {
return($this->raiseError(MDB_ERROR, NULL, NULL,
'Fetch LOB result: ' . $dst_lob['Error']));
}
return($lob);
}
// }}}
// {{{ _retrieveLob()
/**
* fetch a float value from a result set
*
* @param int $lob handle to a lob created by the createLob() function
* @return mixed MDB_OK on success, a MDB error on failure
* @access private
*/
function _retrieveLob($lob)
{
if (!isset($this->lobs[$lob])) {
return($this->raiseError(MDB_ERROR_NEED_MORE_DATA, NULL, NULL,
'Fetch LOB result: it was not specified a valid lob'));
}
if (!isset($this->lobs[$lob]['Value'])) {
$this->lobs[$lob]['Value'] = $this->fetch($this->lobs[$lob]['Result'], $this->lobs[$lob]['Row'], $this->lobs[$lob]['Field']);
}
return(MDB_OK);
}
// }}}
// {{{ endOfResultLob()
/**
* Determine whether it was reached the end of the large object and
* therefore there is no more data to be read for the its input stream.
*
* @param int $lob handle to a lob created by the createLob() function
* @return mixed TRUE or FALSE on success, a MDB error on failure
* @access public
*/
function endOfResultLob($lob)
{
$result = $this->_retrieveLob($lob);
if (MDB::isError($result)) {
return($result);
}
return($this->lobs[$lob]['Position'] >= strlen($this->lobs[$lob]['Value']));
}
// }}}
// {{{ _readResultLob()
/**
* Read data from large object input stream.
*
* @param int $lob handle to a lob created by the createLob() function
* @param blob $data reference to a variable that will hold data to be
* read from the large object input stream
* @param int $length integer value that indicates the largest ammount of
* data to be read from the large object input stream.
* @return mixed length on success, a MDB error on failure
* @access private
*/
function _readResultLob($lob, &$data, $length)
{
$result = $this->_retrieveLob($lob);
if (MDB::isError($result)) {
return($result);
}
$length = min($length, strlen($this->lobs[$lob]['Value']) - $this->lobs[$lob]['Position']);
$data = substr($this->lobs[$lob]['Value'], $this->lobs[$lob]['Position'], $length);
$this->lobs[$lob]['Position'] += $length;
return($length);
}
// }}}
// {{{ _destroyResultLob()
/**
* Free any resources allocated during the lifetime of the large object
* handler object.
*
* @param int $lob handle to a lob created by the createLob() function
* @access private
*/
function _destroyResultLob($lob)
{
if (isset($this->lobs[$lob])) {
$this->lobs[$lob] = '';
}
}
// }}}
// {{{ fetchClob()
/**
* fetch a clob value from a result set
*
* @param resource $result result identifier
* @param int $row number of the row where the data can be found
* @param int $field field number where the data can be found
* @return mixed content of the specified data cell, a MDB error on failure,
* a MDB error on failure
* @access public
*/
function fetchClob($result, $row, $field)
{
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
'fetch clob result method is not implemented'));
}
// }}}
// {{{ fetchBlob()
/**
* fetch a blob value from a result set
*
* @param resource $result result identifier
* @param int $row number of the row where the data can be found
* @param int $field field number where the data can be found
* @return mixed content of the specified data cell, a MDB error on failure
* @access public
*/
function fetchBlob($result, $row, $field)
{
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
'fetch blob result method is not implemented'));
}
// }}}
// {{{ resultIsNull()
/**
* Determine whether the value of a query result located in given row and
* field is a NULL.
*
* @param resource $result result identifier
* @param int $row number of the row where the data can be found
* @param int $field field number where the data can be found
* @return mixed TRUE or FALSE on success, a MDB error on failure
* @access public
*/
function resultIsNull($result, $row, $field)
{
$result = $this->fetch($result, $row, $field);
if (MDB::isError($result)) {
return($result);
}
return(!isset($result));
}
// }}}
// {{{ _baseConvertResult()
/**
* general type conversion method
*
* @param mixed $value refernce to a value to be converted
* @param int $type constant that specifies which type to convert to
* @return object a MDB error on failure
* @access private
*/
function _baseConvertResult($value, $type)
{
switch ($type) {
case MDB_TYPE_TEXT:
return($value);
case MDB_TYPE_BLOB:
return($value);
case MDB_TYPE_CLOB:
return($value);
case MDB_TYPE_INTEGER:
return(intval($value));
case MDB_TYPE_BOOLEAN:
return ($value == 'Y') ? TRUE : FALSE;
case MDB_TYPE_DECIMAL:
return($value);
case MDB_TYPE_FLOAT:
return(doubleval($value));
case MDB_TYPE_DATE:
return($value);
case MDB_TYPE_TIME:
return($value);
case MDB_TYPE_TIMESTAMP:
return($value);
case MDB_TYPE_CLOB:
return($value);
case MDB_TYPE_BLOB:
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
'BaseConvertResult: attempt to convert result value to an unsupported type ' . $type));
default:
return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
'BaseConvertResult: attempt to convert result value to an unknown type ' . $type));
}
}
// }}}
// {{{ convertResult()
/**
* convert a value to a RDBMS indepdenant MDB type
*
* @param mixed $value value to be converted
* @param int $type constant that specifies which type to convert to
* @return mixed converted value or a MDB error on failure
* @access public
*/
function convertResult($value, $type)
{
return($this->_baseConvertResult($value, $type));
}
// }}}
// {{{ convertResultRow()
/**
* convert a result row
*
* @param resource $result result identifier
* @param array $row array with data
* @return mixed MDB_OK on success, a MDB error on failure
* @access public
*/
function convertResultRow($result, $row)
{
$result_value = intval($result);
if (isset($this->result_types[$result_value])) {
$current_column = -1;
foreach($row as $key => $column) {
++$current_column;
if (!isset($this->result_types[$result_value][$current_column])
||!isset($column)
) {
continue;
}
switch ($type = $this->result_types[$result_value][$current_column]) {
case MDB_TYPE_TEXT:
case MDB_TYPE_BLOB:
case MDB_TYPE_CLOB:
break;
case MDB_TYPE_INTEGER:
$row[$key] = intval($row[$key]);
break;
default:
$value = $this->convertResult($row[$key], $type);
if (MDB::isError($value)) {
return $value;
}
$row[$key] = $value;
break;
}
}
}
return ($row);
}
// }}}
// {{{ fetchDate()
/**
* fetch a date value from a result set
*
* @param resource $result result identifier
* @param int $row number of the row where the data can be found
* @param int $field field number where the data can be found
* @return mixed content of the specified data cell, a MDB error on failure
* @access public
*/
function fetchDate($result, $row, $field)
{
$value = $this->fetch($result, $row, $field);
return($this->convertResult($value, MDB_TYPE_DATE));
}
// }}}
// {{{ fetchTimestamp()
/**
* fetch a timestamp value from a result set
*
* @param resource $result result identifier
* @param int $row number of the row where the data can be found
* @param int $field field number where the data can be found
* @return mixed content of the specified data cell, a MDB error on failure
* @access public
*/
function fetchTimestamp($result, $row, $field)
{
$value = $this->fetch($result, $row, $field);
return($this->convertResult($value, MDB_TYPE_TIMESTAMP));
}
// }}}
// {{{ fetchTime()
/**
* fetch a time value from a result set
*
* @param resource $result result identifier
* @param int $row number of the row where the data can be found
* @param int $field field number where the data can be found
* @return mixed content of the specified data cell, a MDB error on failure
* @access public
*/
function fetchTime($result, $row, $field)
{
$value = $this->fetch($result, $row, $field);
return($this->convertResult($value, MDB_TYPE_TIME));
}
// }}}
// {{{ fetchBoolean()
/**
* fetch a boolean value from a result set
*
* @param resource $result result identifier
* @param int $row number of the row where the data can be found
* @param int $field field number where the data can be found
* @return mixed content of the specified data cell, a MDB error on failure
* @access public
*/
function fetchBoolean($result, $row, $field)
{
$value = $this->fetch($result, $row, $field);
return($this->convertResult($value, MDB_TYPE_BOOLEAN));
}
// }}}
// {{{ fetchFloat()
/**
* fetch a float value from a result set
*
* @param resource $result result identifier
* @param int $row number of the row where the data can be found
* @param int $field field number where the data can be found
* @return mixed content of the specified data cell, a MDB error on failure
* @access public
*/
function fetchFloat($result, $row, $field)
{
$value = $this->fetch($result, $row, $field);
return($this->convertResult($value, MDB_TYPE_FLOAT));
}
// }}}
// {{{ fetchDecimal()
/**
* fetch a decimal value from a result set
*
* @param resource $result result identifier
* @param int $row number of the row where the data can be found
* @param int $field field number where the data can be found
* @return mixed content of the specified data cell, a MDB error on failure
* @access public
*/
function fetchDecimal($result, $row, $field)
{
$value = $this->fetch($result, $row, $field);
return($this->convertResult($value, MDB_TYPE_DECIMAL));
}
// }}}
// {{{ numRows()
/**
* returns the number of rows in a result object
*
* @param ressource $result a valid result ressouce pointer
* @return mixed MDB_Error or the number of rows
* @access public
*/
function numRows($result)
{
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Num Rows: number of rows method not implemented'));
}
// }}}
// {{{ freeResult()
/**
* Free the internal resources associated with $result.
*
* @param $result result identifier
* @return boolean TRUE on success, FALSE if $result is invalid
* @access public
*/
function freeResult($result)
{
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL, 'Free Result: free result method not implemented'));
}
// }}}
// {{{ getIntegerDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an integer type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* unsigned
* Boolean flag that indicates whether the field should be
* declared as unsigned integer if possible.
*
* default
* Integer value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to NULL.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getIntegerDeclaration($name, $field)
{
if (isset($field['unsigned'])) {
$this->warnings[] = "unsigned integer field \"$name\" is being
declared as signed integer";
}
return("$name INT" . (isset($field['default']) ? ' DEFAULT ' . $field['default'] : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
}
// }}}
// {{{ getTextDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an text type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the text
* field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* default
* Text value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to NULL.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getTextDeclaration($name, $field)
{
return((isset($field['length']) ? "$name CHAR (" . $field['length'] . ')' : "$name TEXT") . (isset($field['default']) ? ' DEFAULT ' . $this->getTextValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
}
// }}}
// {{{ getClobDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an character
* large object type field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the large
* object field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to NULL.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getClobDeclaration($name, $field)
{
return((isset($field['length']) ? "$name CHAR (" . $field['length'] . ')' : "$name TEXT") . (isset($field['default']) ? ' DEFAULT ' . $this->getTextValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
}
// }}}
// {{{ getBlobDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare an binary large
* object type field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* length
* Integer value that determines the maximum length of the large
* object field. If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to NULL.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getBlobDeclaration($name, $field)
{
return((isset($field['length']) ? "$name CHAR (" . $field['length'] . ')' : "$name TEXT") . (isset($field['default']) ? ' DEFAULT ' . $this->getTextValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
}
// }}}
// {{{ getBooleanDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare a boolean type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* default
* Boolean value to be used as default for this field.
*
* notnullL
* Boolean flag that indicates whether this field is constrained
* to not be set to NULL.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getBooleanDeclaration($name, $field)
{
return("$name CHAR (1)" . (isset($field['default']) ? ' DEFAULT ' . $this->getBooleanValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
}
// }}}
// {{{ getDateDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare a date type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* default
* Date value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to NULL.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getDateDeclaration($name, $field)
{
return("$name CHAR (" . strlen("YYYY-MM-DD") . ")" . (isset($field['default']) ? ' DEFAULT ' . $this->getDateValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
}
// }}}
// {{{ getTimestampDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare a timestamp
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* default
* Timestamp value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to NULL.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getTimestampDeclaration($name, $field)
{
return("$name CHAR (" . strlen("YYYY-MM-DD HH:MM:SS") . ")" . (isset($field['default']) ? ' DEFAULT ' . $this->getTimestampValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
}
// }}}
// {{{ getTimeDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare a time
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* default
* Time value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to NULL.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getTimeDeclaration($name, $field)
{
return("$name CHAR (" . strlen("HH:MM:SS") . ")" . (isset($field['default']) ? ' DEFAULT ' . $this->getTimeValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
}
// }}}
// {{{ getFloatDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare a float type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* default
* Float value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to NULL.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getFloatDeclaration($name, $field)
{
return("$name TEXT " . (isset($field['default']) ? ' DEFAULT ' . $this->getFloatValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
}
// }}}
// {{{ getDecimalDeclaration()
/**
* Obtain DBMS specific SQL code portion needed to declare a decimal type
* field to be used in statements like CREATE TABLE.
*
* @param string $name name the field to be declared.
* @param string $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows:
*
* default
* Decimal value to be used as default for this field.
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to NULL.
* @return string DBMS specific SQL code portion that should be used to
* declare the specified field.
* @access public
*/
function getDecimalDeclaration($name, $field)
{
return("$name TEXT " . (isset($field['default']) ? ' DEFAULT ' . $this->getDecimalValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
}
// }}}
// {{{ getIntegerValue()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param string $value text string value that is intended to be converted.
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access public
*/
function getIntegerValue($value)
{
return(($value === NULL) ? 'NULL' : (int)$value);
}
// }}}
// {{{ getTextValue()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param string $value text string value that is intended to be converted.
* @return string text string that already contains any DBMS specific
* escaped character sequences.
* @access public
*/
function getTextValue($value)
{
return(($value === NULL) ? 'NULL' : "'".$this->_quote($value)."'");
}
// }}}
// {{{ getClobValue()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param resource $prepared_query query handle from prepare()
* @param $parameter
* @param $clob
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access public
*/
function getClobValue($prepared_query, $parameter, $clob)
{
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
'Get CLOB field value: prepared queries with values of type "clob" are not yet supported'));
}
// }}}
// {{{ freeClobValue()
/**
* free a character large object
*
* @param resource $prepared_query query handle from prepare()
* @param string $blob
* @param string $value
* @access public
*/
function freeClobValue($prepared_query, $clob, &$value)
{
}
// }}}
// {{{ getBlobValue()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param resource $prepared_query query handle from prepare()
* @param $parameter
* @param $blob
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access public
*/
function getBlobValue($prepared_query, $parameter, $blob)
{
return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
'Get BLOB field value: prepared queries with values of type "blob" are not yet supported'));
}
// }}}
// {{{ freeBlobValue()
/**
* free a binary large object
*
* @param resource $prepared_query query handle from prepare()
* @param string $blob
* @param string $value
* @access public
*/
function freeBlobValue($prepared_query, $blob, &$value)
{
}
// }}}
// {{{ getBooleanValue()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param string $value text string value that is intended to be converted.
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access public
*/
function getBooleanValue($value)
{
return(($value === NULL) ? 'NULL' : ($value ? "'Y'" : "'N'"));
}
// }}}
// {{{ getDateValue()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param string $value text string value that is intended to be converted.
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access public
*/
function getDateValue($value)
{
return(($value === NULL) ? 'NULL' : "'$value'");
}
// }}}
// {{{ getTimestampValue()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param string $value text string value that is intended to be converted.
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access public
*/
function getTimestampValue($value)
{
return(($value === NULL) ? 'NULL' : "'$value'");
}
// }}}
// {{{ getTimeValue()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param string $value text string value that is intended to be converted.
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access public
*/
function getTimeValue($value)
{
return(($value === NULL) ? 'NULL' : "'$value'");
}
// }}}
// {{{ getFloatValue()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param string $value text string value that is intended to be converted.
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access public
*/
function getFloatValue($value)
{
return(($value === NULL) ? 'NULL' : "'$value'");
}
// }}}
// {{{ getDecimalValue()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param string $value text string value that is intended to be converted.
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access public
*/
function getDecimalValue($value)
{
return(($value === NULL) ? 'NULL' : "'$value'");
}
// }}}
// {{{ getValue()
/**
* Convert a text value into a DBMS specific format that is suitable to
* compose query statements.
*
* @param string $type type to which the value should be converted to
* @param string $value text string value that is intended to be converted.
* @return string text string that represents the given argument value in
* a DBMS specific format.
* @access public
*/
function getValue($type, $value)
{
if (empty($type)) {
return($this->raiseError(MDB_ERROR_SYNTAX, NULL, NULL,
'getValue: called without type to convert to'));
}
if (method_exists($this,"get{$type}Value")) {
return $this->{"get{$type}Value"}($value);
}
return $value;
}
// }}}
// {{{ support()
/**
* Tell whether a DB implementation or its backend extension
* supports a given feature.
*
* @param string $feature name of the feature (see the MDB class doc)
* @return boolean whether this DB implementation supports $feature
* @access public
*/
function support($feature)
{
return(isset($this->supported[$feature]) && $this->supported[$feature]);
}
// }}}
// {{{ getSequenceName()
/**
* adds sequence name formating to a sequence name
*
* @param string $sqn name of the sequence
* @return string formatted sequence name
* @access public
*/
function getSequenceName($sqn)
{
return sprintf($this->options['seqname_format'],
preg_replace('/[^a-z0-9_]/i', '_', $sqn));
}
// }}}
// {{{ nextId()
/**
* returns the next free id of a sequence
*
* @param string $seq_name name of the sequence
* @param boolean $ondemand when TRUE the seqence is
* automatic created, if it
* not exists
* @return mixed MDB_Error or id
* @access public
*/
function nextId($seq_name, $ondemand = FALSE)
{
return($this->raiseError(MDB_ERROR_NOT_CAPABLE, NULL, NULL,
'Next Sequence: getting next sequence value not supported'));
}
// }}}
// {{{ currId()
/**
* returns the current id of a sequence
*
* @param string $seq_name name of the sequence
* @return mixed MDB_Error or id
* @access public
*/
function currId($seq_name)
{
$this->warnings[] = 'database does not support getting current
sequence value, the sequence value was incremented';
$this->expectError(MDB_ERROR_NOT_CAPABLE);
$id = $this->nextId($seq_name);
$this->popExpect(MDB_ERROR_NOT_CAPABLE);
if (MDB::isError($id)) {
if ($id->getCode() == MDB_ERROR_NOT_CAPABLE) {
return($this->raiseError(MDB_ERROR_NOT_CAPABLE, NULL, NULL,
'Current Sequence: getting current sequence value not supported'));
}
return($id);
}
return($id);
}
// }}}
// {{{ fetchInto()
/**
* Fetch a row and return data in an array.
*
* @param resource $result result identifier
* @param int $fetchmode ignored
* @param int $rownum the row number to fetch
* @return mixed data array or NULL on success, a MDB error on failure
* @access public
*/
function fetchInto($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rownum = NULL)
{
$result_value = intval($result);
if (MDB::isError($this->endOfResult($result))) {
$this->freeResult($result);
$result = $this->raiseError(MDB_ERROR_NEED_MORE_DATA, NULL, NULL,
'Fetch field: result set is empty');
}
if ($rownum == NULL) {
++$this->highest_fetched_row[$result_value];
$rownum = $this->highest_fetched_row[$result_value];
} else {
$this->highest_fetched_row[$result_value] =
max($this->highest_fetched_row[$result_value], $row);
}
if ($fetchmode == MDB_FETCHMODE_DEFAULT) {
$fetchmode = $this->fetchmode;
}
$columns = $this->numCols($result);
if (MDB::isError($columns)) {
return($columns);
}
if ($fetchmode & MDB_FETCHMODE_ASSOC) {
$column_names = $this->getColumnNames($result);
}
for($column = 0; $column < $columns; $column++) {
if (!$this->resultIsNull($result, $rownum, $column)) {
$value = $this->fetch($result, $rownum, $column);
if ($value === FALSE) {
if ($this->options['autofree']) {
$this->freeResult($result);
}
return(NULL);
} elseif (MDB::isError($value)) {
if ($value->getMessage() == '') {
if ($this->options['autofree']) {
$this->freeResult($result);
}
return(NULL);
} else {
return($value);
}
}
}
$row[$column] = $value;
}
if ($fetchmode & MDB_FETCHMODE_ASSOC) {
$row = array_combine($column_names, $row);
if (is_array($row) && $this->options['optimize'] == 'portability') {
$row = array_change_key_case($row, CASE_LOWER);
}
}
if (isset($this->result_types[$result_value])) {
$row = $this->convertResultRow($result, $row);
}
return($row);
}
// }}}
// {{{ fetchOne()
/**
* Fetch and return a field of data (it uses fetchInto for that)
*
* @param resource $result result identifier
* @return mixed data on success, a MDB error on failure
* @access public
*/
function fetchOne($result)
{
$row = $this->fetchInto($result, MDB_FETCHMODE_ORDERED);
if (!$this->options['autofree'] || $row != NULL) {
$this->freeResult($result);
}
if (is_array($row)) {
return($row[0]);
}
return($row);
}
// }}}
// {{{ fetchRow()
/**
* Fetch and return a row of data (it uses fetchInto for that)
*
* @param resource $result result identifier
* @param int $fetchmode how the array data should be indexed
* @param int $rownum the row number to fetch
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function fetchRow($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rownum = NULL)
{
$row = $this->fetchInto($result, $fetchmode, $rownum);
if (!$this->options['autofree'] || $row != NULL) {
$this->freeResult($result);
}
return($row);
}
// }}}
// {{{ fetchCol()
/**
* Fetch and return a column of data (it uses fetchInto for that)
*
* @param resource $result result identifier
* @param int $colnum the row number to fetch
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function fetchCol($result, $colnum = 0)
{
$fetchmode = is_numeric($colnum) ? MDB_FETCHMODE_ORDERED : MDB_FETCHMODE_ASSOC;
$column = array();
$row = $this->fetchInto($result, $fetchmode);
if (is_array($row)) {
if (!array_key_exists($colnum, $row)) {
return($this->raiseError(MDB_ERROR_TRUNCATED));
}
do {
$column[] = $row[$colnum];
} while (is_array($row = $this->fetchInto($result, $fetchmode)));
}
if (!$this->options['autofree']) {
$this->freeResult($result);
}
if (MDB::isError($row)) {
return($row);
}
return($column);
}
// }}}
// {{{ fetchAll()
/**
* Fetch and return a column of data (it uses fetchInto for that)
*
* @param resource $result result identifier
* @param int $fetchmode how the array data should be indexed
* @param boolean $rekey if set to TRUE, the $all will have the first
* column as its first dimension
* @param boolean $force_array used only when the query returns exactly
* two columns. If TRUE, the values of the returned array will be
* one-element arrays instead of scalars.
* @param boolean $group if TRUE, the values of the returned array is
* wrapped in another array. If the same key value (in the first
* column) repeats itself, the values will be appended to this array
* instead of overwriting the existing values.
* @return mixed data array on success, a MDB error on failure
* @access public
* @see getAssoc()
*/
function fetchAll($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rekey = FALSE, $force_array = FALSE, $group = FALSE)
{
if ($rekey) {
$cols = $this->numCols($result);
if (MDB::isError($cols)) {
return($cols);
}
if ($cols < 2) {
return($this->raiseError(MDB_ERROR_TRUNCATED));
}
}
$all = array();
while (is_array($row = $this->fetchInto($result, $fetchmode))) {
if ($rekey) {
if ($fetchmode & MDB_FETCHMODE_ASSOC) {
$key = reset($row);
unset($row[key($row)]);
} else {
$key = array_shift($row);
}
if (!$force_array && count($row) == 1) {
$row = array_shift($row);
}
if ($group) {
$all[$key][] = $row;
} else {
$all[$key] = $row;
}
} else {
if ($fetchmode & MDB_FETCHMODE_FLIPPED) {
foreach ($row as $key => $val) {
$all[$key][] = $val;
}
} else {
$all[] = $row;
}
}
}
if (!$this->options['autofree']) {
$this->freeResult($result);
}
if (MDB::isError($row)) {
return($row);
}
return($all);
}
// }}}
// {{{ queryOne()
/**
* Execute the specified query, fetch the value from the first column of
* the first row of the result set and then frees
* the result set.
*
* @param string $query the SELECT query statement to be executed.
* @param string $type optional argument that specifies the expected
* datatype of the result set field, so that an eventual conversion
* may be performed. The default datatype is text, meaning that no
* conversion is performed
* @return mixed field value on success, a MDB error on failure
* @access public
*/
function queryOne($query, $type = NULL)
{
if ($type != NULL) {
$type = array($type);
}
$result = $this->query($query, $type);
if (MDB::isError($result)) {
return($result);
}
return($this->fetchOne($result));
}
// }}}
// {{{ queryRow()
/**
* Execute the specified query, fetch the values from the first
* row of the result set into an array and then frees
* the result set.
*
* @param string $query the SELECT query statement to be executed.
* @param array $types optional array argument that specifies a list of
* expected datatypes of the result set columns, so that the eventual
* conversions may be performed. The default list of datatypes is
* empty, meaning that no conversion is performed.
* @param int $fetchmode how the array data should be indexed
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function queryRow($query, $types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT)
{
$result = $this->query($query, $types);
if (MDB::isError($result)) {
return($result);
}
return($this->fetchRow($result, $fetchmode));
}
// }}}
// {{{ queryCol()
/**
* Execute the specified query, fetch the value from the first column of
* each row of the result set into an array and then frees the result set.
*
* @param string $query the SELECT query statement to be executed.
* @param string $type optional argument that specifies the expected
* datatype of the result set field, so that an eventual conversion
* may be performed. The default datatype is text, meaning that no
* conversion is performed
* @param int $colnum the row number to fetch
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function queryCol($query, $type = NULL, $colnum = 0)
{
if ($type != NULL) {
$type = array($type);
}
$result = $this->query($query, $type);
if (MDB::isError($result)) {
return($result);
}
return($this->fetchCol($result, $colnum));
}
// }}}
// {{{ queryAll()
/**
* Execute the specified query, fetch all the rows of the result set into
* a two dimensional array and then frees the result set.
*
* @param string $query the SELECT query statement to be executed.
* @param array $types optional array argument that specifies a list of
* expected datatypes of the result set columns, so that the eventual
* conversions may be performed. The default list of datatypes is
* empty, meaning that no conversion is performed.
* @param int $fetchmode how the array data should be indexed
* @param boolean $rekey if set to TRUE, the $all will have the first
* column as its first dimension
* @param boolean $force_array used only when the query returns exactly
* two columns. If TRUE, the values of the returned array will be
* one-element arrays instead of scalars.
* @param boolean $group if TRUE, the values of the returned array is
* wrapped in another array. If the same key value (in the first
* column) repeats itself, the values will be appended to this array
* instead of overwriting the existing values.
* @return mixed data array on success, a MDB error on failure
* @access public
*/
function queryAll($query, $types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT,
$rekey = FALSE, $force_array = FALSE, $group = FALSE)
{
if (MDB::isError($result = $this->query($query, $types))) {
return($result);
}
return($this->fetchAll($result, $fetchmode, $rekey, $force_array, $group));
}
// }}}
// {{{ getOne()
/**
* Fetch the first column of the first row of data returned from
* a query. Takes care of doing the query and freeing the results
* when finished.
*
* @param string $query the SQL query
* @param string $type string that contains the type of the column in the
* result set
* @param array $params if supplied, prepare/execute will be used
* with this array as execute parameters
* @param array $param_types array that contains the types of the values
* defined in $params
* @return mixed MDB_Error or the returned value of the query
* @access public
*/
function getOne($query, $type = NULL, $params = array(), $param_types = NULL)
{
if ($type != NULL) {
$type = array($type);
}
settype($params, 'array');
if (count($params) > 0) {
$prepared_query = $this->prepareQuery($query);
if (MDB::isError($prepared_query)) {
return($prepared_query);
}
$this->setParamArray($prepared_query, $params, $param_types);
$result = $this->executeQuery($prepared_query, $type);
} else {
$result = $this->query($query, $type);
}
if (MDB::isError($result)) {
return($result);
}
$value = $this->fetchOne($result, MDB_FETCHMODE_ORDERED);
if (MDB::isError($value)) {
return($value);
}
if (isset($prepared_query)) {
$result = $this->freePreparedQuery($prepared_query);
if (MDB::isError($result)) {
return($result);
}
}
return($value);
}
// }}}
// {{{ getRow()
/**
* Fetch the first row of data returned from a query. Takes care
* of doing the query and freeing the results when finished.
*
* @param string $query the SQL query
* @param array $types array that contains the types of the columns in
* the result set
* @param array $params array if supplied, prepare/execute will be used
* with this array as execute parameters
* @param array $param_types array that contains the types of the values
* defined in $params
* @param integer $fetchmode the fetch mode to use
* @return array the first row of results as an array indexed from
* 0, or a MDB error code.
* @access public
*/
function getRow($query, $types = NULL, $params = array(), $param_types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT)
{
settype($params, 'array');
if (count($params) > 0) {
$prepared_query = $this->prepareQuery($query);
if (MDB::isError($prepared_query)) {
return($prepared_query);
}
$this->setParamArray($prepared_query, $params, $param_types);
$result = $this->executeQuery($prepared_query, $types);
} else {
$result = $this->query($query, $types);
}
if (MDB::isError($result)) {
return($result);
}
$row = $this->fetchRow($result, $fetchmode);
if (MDB::isError($row)) {
return($row);
}
if (isset($prepared_query)) {
$result = $this->freePreparedQuery($prepared_query);
if (MDB::isError($result)) {
return($result);
}
}
return($row);
}
// }}}
// {{{ getCol()
/**
* Fetch a single column from a result set and return it as an
* indexed array.
*
* @param string $query the SQL query
* @param string $type string that contains the type of the column in the
* result set
* @param array $params array if supplied, prepare/execute will be used
* with this array as execute parameters
* @param array $param_types array that contains the types of the values
* defined in $params
* @param mixed $colnum which column to return(integer [column number,
* starting at 0] or string [column name])
* @return array an indexed array with the data from the first
* row at index 0, or a MDB error code.
* @access public
*/
function getCol($query, $type = NULL, $params = array(), $param_types = NULL, $colnum = 0)
{
if ($type != NULL) {
$type = array($type);
}
settype($params, 'array');
if (count($params) > 0) {
$prepared_query = $this->prepareQuery($query);
if (MDB::isError($prepared_query)) {
return($prepared_query);
}
$this->setParamArray($prepared_query, $params, $param_types);
$result = $this->executeQuery($prepared_query, $type);
} else {
$result = $this->query($query, $type);
}
if (MDB::isError($result)) {
return($result);
}
$col = $this->fetchCol($result, $colnum);
if (MDB::isError($col)) {
return($col);
}
if (isset($prepared_query)) {
$result = $this->freePreparedQuery($prepared_query);
if (MDB::isError($result)) {
return($result);
}
}
return($col);
}
// }}}
// {{{ getAssoc()
/**
* Fetch the entire result set of a query and return it as an
* associative array using the first column as the key.
*
* If the result set contains more than two columns, the value
* will be an array of the values from column 2-n. If the result
* set contains only two columns, the returned value will be a
* scalar with the value of the second column (unless forced to an
* array with the $force_array parameter). A MDB error code is
* returned on errors. If the result set contains fewer than two
* columns, a MDB_ERROR_TRUNCATED error is returned.
*
* For example, if the table 'mytable' contains:
*
* ID TEXT DATE
* --------------------------------
* 1 'one' 944679408
* 2 'two' 944679408
* 3 'three' 944679408
*
* Then the call getAssoc('SELECT id,text FROM mytable') returns:
* array(
* '1' => 'one',
* '2' => 'two',
* '3' => 'three',
* )
*
* ...while the call getAssoc('SELECT id,text,date FROM mytable') returns:
* array(
* '1' => array('one', '944679408'),
* '2' => array('two', '944679408'),
* '3' => array('three', '944679408')
* )
*
* If the more than one row occurs with the same value in the
* first column, the last row overwrites all previous ones by
* default. Use the $group parameter if you don't want to
* overwrite like this. Example:
*
* getAssoc('SELECT category,id,name FROM mytable', NULL, NULL
* MDB_FETCHMODE_ASSOC, FALSE, TRUE) returns:
* array(
* '1' => array(array('id' => '4', 'name' => 'number four'),
* array('id' => '6', 'name' => 'number six')
* ),
* '9' => array(array('id' => '4', 'name' => 'number four'),
* array('id' => '6', 'name' => 'number six')
* )
* )
*
* Keep in mind that database functions in PHP usually return string
* values for results regardless of the database's internal type.
*
* @param string $query the SQL query
* @param array $types array that contains the types of the columns in
* the result set
* @param array $params array if supplied, prepare/execute will be used
* with this array as execute parameters
* @param array $param_types array that contains the types of the values
* defined in $params
* @param boolean $force_array used only when the query returns
* exactly two columns. If TRUE, the values of the returned array
* will be one-element arrays instead of scalars.
* @param boolean $group if TRUE, the values of the returned array
* is wrapped in another array. If the same key value (in the first
* column) repeats itself, the values will be appended to this array
* instead of overwriting the existing values.
* @return array associative array with results from the query.
* @access public
*/
function getAssoc($query, $types = NULL, $params = array(), $param_types = NULL,
$fetchmode = MDB_FETCHMODE_ORDERED, $force_array = FALSE, $group = FALSE)
{
settype($params, 'array');
if (count($params) > 0) {
$prepared_query = $this->prepareQuery($query);
if (MDB::isError($prepared_query)) {
return($prepared_query);
}
$this->setParamArray($prepared_query, $params, $param_types);
$result = $this->executeQuery($prepared_query, $types);
} else {
$result = $this->query($query, $types);
}
if (MDB::isError($result)) {
return($result);
}
$all = $this->fetchAll($result, $fetchmode, TRUE, $force_array, $group);
if (MDB::isError($all)) {
return($all);
}
if (isset($prepared_query)) {
$result = $this->freePreparedQuery($prepared_query);
if (MDB::isError($result)) {
return($result);
}
}
return($all);
}
// }}}
// {{{ getAll()
/**
* Fetch all the rows returned from a query.
*
* @param string $query the SQL query
* @param array $types array that contains the types of the columns in
* the result set
* @param array $params array if supplied, prepare/execute will be used
* with this array as execute parameters
* @param array $param_types array that contains the types of the values
* defined in $params
* @param integer $fetchmode the fetch mode to use
* @return array an nested array, or a MDB error
* @access public
*/
function getAll($query, $types = NULL, $params = array(), $param_types = NULL, $fetchmode = MDB_FETCHMODE_DEFAULT)
{
settype($params, 'array');
if (count($params) > 0) {
$prepared_query = $this->prepareQuery($query);
if (MDB::isError($prepared_query)) {
return($prepared_query);
}
$this->setParamArray($prepared_query, $params, $param_types);
$result = $this->executeQuery($prepared_query, $types);
} else {
$result = $this->query($query, $types);
}
if (MDB::isError($result)) {
return($result);
}
$all = $this->fetchAll($result, $fetchmode);
if (MDB::isError($all)) {
return($all);
}
if (isset($prepared_query)) {
$result = $this->freePreparedQuery($prepared_query);
if (MDB::isError($result)) {
return($result);
}
}
return($all);
}
// }}}
// {{{ tableInfo()
/**
* returns meta data about the result set
*
* @param resource $result result identifier
* @param mixed $mode depends on implementation
* @return array an nested array, or a MDB error
* @access public
*/
function tableInfo($result, $mode = NULL)
{
return($this->raiseError(MDB_ERROR_NOT_CAPABLE));
}
// }}}
// {{{ createLob()
/**
* Create a handler object of a specified class with functions to
* retrieve data from a large object data stream.
*
* @param array $arguments An associative array with parameters to create
* the handler object. The array indexes are the names of
* the parameters and the array values are the respective
* parameter values.
*
* Some parameters are specific of the class of each type
* of handler object that is created. The following
* parameters are common to all handler object classes:
*
* Type
*
* Name of the type of the built-in supported class
* that will be used to create the handler object.
* There are currently four built-in types of handler
* object classes: data, resultlob, inputfile and
* outputfile.
*
* The data handler class is the default class. It
* simply reads data from a given data string.
*
* The resultlob handler class is meant to read data
* from a large object retrieved from a query result.
* This class is not used directly by applications.
*
* The inputfile handler class is meant to read data
* from a file to use in prepared queries with large
* object field parameters.
*
* The outputfile handler class is meant to write to
* a file data from result columns with large object
* fields. The functions to read from this type of
* large object do not return any data. Instead, the
* data is just written to the output file with the
* data retrieved from a specified large object handle.
*
* Class
*
* Name of the class of the handler object that will be
* created if the Type argument is not specified. This
* argument should be used when you need to specify a
* custom handler class.
*
* Database
*
* Database object as returned by MDB::connect.
* This is an option argument needed by some handler
* classes like resultlob.
*
* The following arguments are specific of the inputfile
* handler class:
*
* File
*
* Integer handle value of a file already opened
* for writing.
*
* FileName
*
* Name of a file to be opened for writing if the
* File argument is not specified.
*
* The following arguments are specific of the outputfile
* handler class:
*
* File
*
* Integer handle value of a file already opened
* for writing.
*
* FileName
*
* Name of a file to be opened for writing if the
* File argument is not specified.
*
* BufferLength
*
* Integer value that specifies the length of a
* buffer that will be used to read from the
* specified large object.
*
* LOB
*
* Integer handle value that specifies a large
* object from which the data to be stored in the
* output file will be written.
*
* Result
*
* Integer handle value as returned by the function
* MDB::query() or MDB::executeQuery() that specifies
* the result set that contains the large object value
* to be retrieved. If the LOB argument is specified,
* this argument is ignored.
*
* Row
*
* Integer value that specifies the number of the
* row of the result set that contains the large
* object value to be retrieved. If the LOB
* argument is specified, this argument is ignored.
*
* Field
*
* Integer or string value that specifies the
* number or the name of the column of the result
* set that contains the large object value to be
* retrieved. If the LOB argument is specified,
* this argument is ignored.
*
* Binary
*
* Boolean value that specifies whether the large
* object column to be retrieved is of binary type
* (blob) or otherwise is of character type (clob).
* If the LOB argument is specified, this argument
* is ignored.
*
* The following argument is specific of the data
* handler class:
*
* Data
*
* String of data that will be returned by the class
* when it requested with the readLOB() method.
*
* The following argument is specific of the resultlob
* handler class:
*
* ResultLOB
*
* Integer handle value of a large object result
* row field.
* @return integer handle value that should be passed as argument insubsequent
* calls to functions that retrieve data from the large object input stream.
* @access public
*/
function createLob($arguments)
{
$result = $this->loadLob('Create LOB');
if (MDB::isError($result)) {
return($result);
}
$class_name = 'MDB_LOB';
if (isset($arguments['Type'])) {
switch ($arguments['Type']) {
case 'data':
break;
case 'resultlob':
$class_name = 'MDB_LOB_Result';
break;
case 'inputfile':
$class_name = 'MDB_LOB_Input_File';
break;
case 'outputfile':
$class_name = 'MDB_LOB_Output_File';
break;
default:
if (isset($arguments['Error'])) {
$arguments['Error'] = $arguments['Type'] . ' is not a valid type of large object';
}
return($this->raiseError());
}
} else {
if (isset($arguments['Class'])) {
$class = $arguments['Class'];
}
}
$lob = count($GLOBALS['_MDB_lobs']) + 1;
$GLOBALS['_MDB_lobs'][$lob] = &new $class_name;
if (isset($arguments['Database'])) {
$GLOBALS['_MDB_lobs'][$lob]->database = $arguments['Database'];
} else {
$GLOBALS['_MDB_lobs'][$lob]->database = &$this;
}
if (MDB::isError($result = $GLOBALS['_MDB_lobs'][$lob]->create($arguments))) {
$GLOBALS['_MDB_lobs'][$lob]->database->destroyLob($lob);
return($result);
}
return($lob);
}
// }}}
// {{{ readLob()
/**
* Read data from large object input stream.
*
* @param integer $lob argument handle that is returned by the
* MDB::createLob() method.
* @param string $data reference to a variable that will hold data
* to be read from the large object input stream
* @param integer $length value that indicates the largest ammount ofdata
* to be read from the large object input stream.
* @return mixed the effective number of bytes read from the large object
* input stream on sucess or an MDB error object.
* @access public
* @see endOfLob()
*/
function readLob($lob, &$data, $length)
{
return($GLOBALS['_MDB_lobs'][$lob]->readLob($data, $length));
}
// }}}
// {{{ endOfLob()
/**
* Determine whether it was reached the end of the large object and
* therefore there is no more data to be read for the its input stream.
*
* @param integer $lob argument handle that is returned by the
* MDB::createLob() method.
* @access public
* @return boolean flag that indicates whether it was reached the end of the large object input stream
*/
function endOfLob($lob)
{
return($GLOBALS['_MDB_lobs'][$lob]->endOfLob());
}
// }}}
// {{{ destroyLob()
/**
* Free any resources allocated during the lifetime of the large object
* handler object.
*
* @param integer $lob argument handle that is returned by the
* MDB::createLob() method.
* @access public
*/
function destroyLob($lob)
{
$GLOBALS['_MDB_lobs'][$lob]->destroy();
unset($GLOBALS['_MDB_lobs'][$lob]);
}
// }}}
// {{{ Destructor
/**
* this function closes open transactions to be executed at shutdown
*
* @access private
*/
function _MDB_Common()
{
if ($this->in_transaction && !MDB::isError($this->rollback())) {
$this->autoCommit(TRUE);
}
}
};
?>
Copyright 2K16 - 2K18 Indonesian Hacker Rulez