Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php// vim: set et ts=4 sw=4 fdm=marker:// +----------------------------------------------------------------------+// | 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: mysql.php,v 1.80.4.18 2004/04/22 11:31:56 lsmith Exp $//require_once('MDB/Common.php');/*** MDB MySQL driver** Notes:* - The decimal type fields are emulated with integer fields.** @package MDB* @category Database* @author Lukas Smith <smith@backendmedia.com>*/class MDB_mysql extends MDB_Common{// {{{ propertiesvar $connection = 0;var $connected_host;var $connected_user;var $connected_password;var $connected_port;var $opened_persistent = '';var $escape_quotes = "\\";var $decimal_factor = 1.0;var $highest_fetched_row = array();var $columns = array();// MySQL specific class variablevar $default_table_type = '';var $fixed_float = 0;var $dummy_primary_key = 'dummy_primary_key';// }}}// {{{ constructor/*** Constructor*/function MDB_mysql(){$this->MDB_Common();$this->phptype = 'mysql';$this->dbsyntax = 'mysql';$this->supported['Sequences'] = 1;$this->supported['Indexes'] = 1;$this->supported['AffectedRows'] = 1;$this->supported['Summaryfunctions'] = 1;$this->supported['OrderByText'] = 1;$this->supported['CurrId'] = 1;$this->supported['SelectRowRanges'] = 1;$this->supported['LOBs'] = 1;$this->supported['Replace'] = 1;$this->supported['SubSelects'] = 0;$this->supported['Transactions'] = 0;$this->decimal_factor = pow(10.0, $this->decimal_places);$this->options['DefaultTableType'] = FALSE;$this->options['fixed_float'] = FALSE;$this->errorcode_map = array(1004 => MDB_ERROR_CANNOT_CREATE,1005 => MDB_ERROR_CANNOT_CREATE,1006 => MDB_ERROR_CANNOT_CREATE,1007 => MDB_ERROR_ALREADY_EXISTS,1008 => MDB_ERROR_CANNOT_DROP,1022 => MDB_ERROR_ALREADY_EXISTS,1046 => MDB_ERROR_NODBSELECTED,1050 => MDB_ERROR_ALREADY_EXISTS,1051 => MDB_ERROR_NOSUCHTABLE,1054 => MDB_ERROR_NOSUCHFIELD,1062 => MDB_ERROR_ALREADY_EXISTS,1064 => MDB_ERROR_SYNTAX,1100 => MDB_ERROR_NOT_LOCKED,1136 => MDB_ERROR_VALUE_COUNT_ON_ROW,1146 => MDB_ERROR_NOSUCHTABLE,1048 => MDB_ERROR_CONSTRAINT,1213 => MDB_ERROR_DEADLOCK,1216 => MDB_ERROR_CONSTRAINT,);}// }}}// {{{ errorNative()/*** Get the native error code of the last error (if any) that* occured on the current connection.** @access public** @return int native MySQL error code*/function errorNative(){return(@mysql_errno($this->connection));}// }}}// {{{ mysqlRaiseError()/*** This method is used to communicate an error and invoke error* callbacks etc. Basically a wrapper for MDB::raiseError* that checks for native error msgs.** @param integer $errno error code* @param string $message userinfo message* @return object a PEAR error object* @access public* @see PEAR_Error*/function mysqlRaiseError($errno = NULL, $message = NULL){if ($errno == NULL) {if ($this->connection) {$errno = @mysql_errno($this->connection);} else {$errno = @mysql_errno();}}if ($this->connection) {$error = @mysql_errno($this->connection);} else {$error = @mysql_error();}return($this->raiseError($this->errorCode($errno), NULL, NULL,$message, $error));}// }}}// {{{ quoteIdentifier()/*** Quote a string so it can be safely used as a table or column name** Quoting style depends on which database driver is being used.** MySQL can't handle the backtick character (<kbd>`</kbd>) in* table or column names.** @param string $str identifier name to be quoted** @return string quoted identifier string** @access public* @internal*/function quoteIdentifier($str){return '`' . $str . '`';}// }}}// {{{ 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.** @access public** @return mixed MDB_OK on success, a MDB error on failure*/function autoCommit($auto_commit){$this->debug("AutoCommit: ".($auto_commit ? "On" : "Off"));if (!isset($this->supported['Transactions'])) {return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,'Auto-commit transactions: transactions are not in use'));}if ($this->auto_commit == $auto_commit) {return(MDB_OK);}if ($this->connection) {if ($auto_commit) {$result = $this->query('COMMIT');if (MDB::isError($result)) {return($result);}$result = $this->query('SET AUTOCOMMIT = 1');if (MDB::isError($result)) {return($result);}} else {$result = $this->query('SET AUTOCOMMIT = 0');if (MDB::isError($result)) {return($result);}}}$this->auto_commit = $auto_commit;$this->in_transaction = !$auto_commit;return(MDB_OK);}// }}}// {{{ 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.** @access public** @return mixed MDB_OK on success, a MDB error on failure*/function commit(){$this->debug("Commit Transaction");if (!isset($this->supported['Transactions'])) {return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,'Commit transactions: transactions are not in use'));}if ($this->auto_commit) {return($this->raiseError(MDB_ERROR, NULL, NULL,'Commit transactions: transaction changes are being auto commited'));}return($this->query('COMMIT'));}// }}}// {{{ 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.** @access public** @return mixed MDB_OK on success, a MDB error on failure*/function rollback(){$this->debug("Rollback Transaction");if (!isset($this->supported['Transactions'])) {return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,'Rollback transactions: transactions are not in use'));}if ($this->auto_commit) {return($this->raiseError(MDB_ERROR, NULL, NULL,'Rollback transactions: transactions can not be rolled back when changes are auto commited'));}return($this->query('ROLLBACK'));}// }}}// {{{ connect()/*** Connect to the database** @return TRUE on success, MDB_Error on failure**/function connect(){$port = (isset($this->port) ? $this->port : '');if($this->connection != 0) {if (!strcmp($this->connected_host, $this->host)&& !strcmp($this->connected_user, $this->user)&& !strcmp($this->connected_password, $this->password)&& !strcmp($this->connected_port, $port)&& $this->opened_persistent == $this->options['persistent']){return(MDB_OK);}@mysql_close($this->connection);$this->connection = 0;$this->affected_rows = -1;}if(!PEAR::loadExtension($this->phptype)) {return(PEAR::raiseError(NULL, MDB_ERROR_NOT_FOUND,NULL, NULL, 'extension '.$this->phptype.' is not compiled into PHP','MDB_Error', TRUE));}$UseTransactions = $this->getOption('UseTransactions');if(!MDB::isError($UseTransactions) && $UseTransactions) {$this->supported['Transactions'] = 1;$this->default_table_type = 'BDB';} else {$this->supported['Transactions'] = 0;$this->default_table_type = '';}$DefaultTableType = $this->getOption('DefaultTableType');if(!MDB::isError($DefaultTableType) && $DefaultTableType) {switch($this->default_table_type = strtoupper($DefaultTableType)) {case 'BERKELEYDB':$this->default_table_type = 'BDB';case 'BDB':case 'INNODB':case 'GEMINI':break;case 'HEAP':case 'ISAM':case 'MERGE':case 'MRG_MYISAM':case 'MYISAM':if(isset($this->supported['Transactions'])) {$this->warnings[] = $DefaultTableType.' is not a transaction-safe default table type';}break;default:$this->warnings[] = $DefaultTableType.' is not a supported default table type';}}$this->fixed_float = 30;$function = ($this->options['persistent'] ? 'mysql_pconnect' : 'mysql_connect');if (!function_exists($function)) {return($this->raiseError(MDB_ERROR_UNSUPPORTED));}@ini_set('track_errors', TRUE);$this->connection = @$function($this->host.(!strcmp($port,'') ? '' : ':'.$port),$this->user, $this->password);@ini_restore('track_errors');if ($this->connection <= 0) {return($this->raiseError(MDB_ERROR_CONNECT_FAILED, NULL, NULL,$php_errormsg));}if (isset($this->options['fixedfloat'])) {$this->fixed_float = $this->options['fixedfloat'];} else {if (($result = @mysql_query('SELECT VERSION()', $this->connection))) {$version = explode('.', @mysql_result($result,0,0));$major = intval($version[0]);$minor = intval($version[1]);$revision = intval($version[2]);if ($major > 3 || ($major == 3 && $minor >= 23&& ($minor > 23 || $revision >= 6))){$this->fixed_float = 0;}@mysql_free_result($result);}}if (isset($this->supported['Transactions']) && !$this->auto_commit) {if (!@mysql_query('SET AUTOCOMMIT = 0', $this->connection)) {@mysql_close($this->connection);$this->connection = 0;$this->affected_rows = -1;return($this->raiseError());}$this->in_transaction = TRUE;}$this->connected_host = $this->host;$this->connected_user = $this->user;$this->connected_password = $this->password;$this->connected_port = $port;$this->opened_persistent = $this->getoption('persistent');return(MDB_OK);}// }}}// {{{ _close()/*** all the RDBMS specific things needed close a DB connection** @return boolean* @access private**/function _close(){if ($this->connection != 0) {if (isset($this->supported['Transactions']) && !$this->auto_commit) {$result = $this->autoCommit(TRUE);}@mysql_close($this->connection);$this->connection = 0;$this->affected_rows = -1;if (isset($result) && MDB::isError($result)) {return($result);}unset($GLOBALS['_MDB_databases'][$this->database]);return(TRUE);}return(FALSE);}// }}}// {{{ query()/*** Send a query to the database and return any results** @access public** @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*/function query($query, $types = NULL){$this->debug("Query: $query");$ismanip = MDB::isManip($query);$this->last_query = $query;$first = $this->first_selected_row;$limit = $this->selected_row_limit;$this->first_selected_row = $this->selected_row_limit = 0;$result = $this->connect();if (MDB::isError($result)) {return($result);}if($limit > 0) {if ($ismanip) {$query .= " LIMIT $limit";} else {$query .= " LIMIT $first,$limit";}}if ($this->database_name) {if(!@mysql_select_db($this->database_name, $this->connection)) {return($this->mysqlRaiseError());}}if ($result = @mysql_query($query, $this->connection)) {if ($ismanip) {$this->affected_rows = @mysql_affected_rows($this->connection);return(MDB_OK);} else {$result_value = intval($result);$this->highest_fetched_row[$result_value] = -1;if ($types != NULL) {if (!is_array($types)) {$types = array($types);}if (MDB::isError($err = $this->setResultTypes($result, $types))) {$this->freeResult($result);return($err);}}return($result);}}return($this->mysqlRaiseError());}// }}}// {{{ subSelect()/*** simple subselect emulation for Mysql** @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);}$col = $this->queryCol($query);if (MDB::isError($col)) {return($col);}if(!is_array($col) || count($col) == 0) {return 'NULL';}if($quote) {for($i = 0, $j = count($col); $i < $j; ++$i) {$col[$i] = $this->getTextValue($col[$i]);}}return(implode(', ', $col));}// }}}// {{{ 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* practically 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.** @access public** @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*/function replace($table, $fields){$count = count($fields);for($keys = 0, $query = $values = '',reset($fields), $field = 0;$field<$count;next($fields), $field++){$name = key($fields);if ($field > 0) {$query .= ',';$values .= ',';}$query .= $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,$name.': key values may not be NULL'));}$keys++;}}if ($keys == 0) {return($this->raiseError(MDB_ERROR_CANNOT_REPLACE, NULL, NULL,'not specified which fields are keys'));}return($this->query("REPLACE INTO $table ($query) VALUES ($values)"));}// }}}// {{{ getColumnNames()/*** Retrieve the names of columns returned by the DBMS in a query result.** @param resource $result result identifier* @return mixed an associative array variable* that will hold 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){$result_value = intval($result);if (!isset($this->highest_fetched_row[$result_value])) {return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,'Get column names: it was specified an inexisting result set'));}if (!isset($this->columns[$result_value])) {$this->columns[$result_value] = array();$columns = @mysql_num_fields($result);for($column = 0; $column < $columns; $column++) {$field_name = @mysql_field_name($result, $column);if ($this->options['optimize'] == 'portability') {$field_name = strtolower($field_name);}$this->columns[$result_value][$field_name] = $column;}}return($this->columns[$result_value]);}// }}}// {{{ numCols()/*** Count the number of columns returned by the DBMS in a query result.** @param resource $result result identifier* @access public* @return mixed integer value with the number of columns, a MDB error* on failure*/function numCols($result){$result_value = intval($result);if (!isset($this->highest_fetched_row[$result_value])) {return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,'numCols: it was specified an inexisting result set'));}return(@mysql_num_fields($result));}// }}}// {{{ 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){$result_value = intval($result);if (!isset($this->highest_fetched_row[$result_value])) {return($this->raiseError(MDB_ERROR, NULL, NULL,'End of result: attempted to check the end of an unknown result'));}return($this->highest_fetched_row[$result_value] >= $this->numRows($result)-1);}// }}}// {{{ 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){$result_value = intval($result);$this->highest_fetched_row[$result_value] =max($this->highest_fetched_row[$result_value], $row);$res = @mysql_result($result, $row, $field);if ($res === FALSE && $res != NULL) {return($this->mysqlRaiseError());}return($res);}// }}}// {{{ 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->fetchLob($result, $row, $field));}// }}}// {{{ 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->fetchLob($result, $row, $field));}// }}}// {{{ 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* @access public*/function convertResult($value, $type){switch($type) {case MDB_TYPE_DECIMAL:return(sprintf('%.'.$this->decimal_places.'f', doubleval($value)/$this->decimal_factor));default:return($this->_baseConvertResult($value, $type));}}// }}}// {{{ 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(@mysql_num_rows($result));}// }}}// {{{ 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){$result_value = intval($result);if(isset($this->highest_fetched_row[$result_value])) {unset($this->highest_fetched_row[$result_value]);}if(isset($this->columns[$result_value])) {unset($this->columns[$result_value]);}if(isset($this->result_types[$result_value])) {unset($this->result_types[$result_value]);}return(@mysql_free_result($result));}// }}}// {{{ 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){return("$name INT".(isset($field['unsigned']) ? ' UNSIGNED' : '').(isset($field['default']) ? ' DEFAULT '.$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){if (isset($field['length'])) {$length = $field['length'];if ($length <= 255) {$type = 'TINYTEXT';} else {if ($length <= 65535) {$type = 'TEXT';} else {if ($length <= 16777215) {$type = 'MEDIUMTEXT';} else {$type = 'LONGTEXT';}}}} else {$type = 'LONGTEXT';}return("$name $type".(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){if (isset($field['length'])) {$length = $field['length'];if ($length <= 255) {$type = 'TINYBLOB';} else {if ($length <= 65535) {$type = 'BLOB';} else {if ($length <= 16777215) {$type = 'MEDIUMBLOB';} else {$type = 'LONGBLOB';}}}}else {$type = 'LONGBLOB';}return("$name $type".(isset($field['notnull']) ? ' NOT NULL' : ''));}// }}}// {{{ getDateDeclaration()/*** Obtain DBMS specific SQL code portion needed to declare an 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 DATE".(isset($field['default']) ? " DEFAULT '".$field['default']."'" : '').(isset($field['notnull']) ? ' NOT NULL' : ''));}// }}}// {{{ getTimestampDeclaration()/*** Obtain DBMS specific SQL code portion needed to declare an timestamp* 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* Time stamp 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 DATETIME".(isset($field['default']) ? " DEFAULT '".$field['default']."'" : '').(isset($field['notnull']) ? ' NOT NULL' : ''));}// }}}// {{{ getTimeDeclaration()/*** Obtain DBMS specific SQL code portion needed to declare an time 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* 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 TIME".(isset($field['default']) ? " DEFAULT '".$field['default']."'" : '').(isset($field['notnull']) ? ' NOT NULL' : ''));}// }}}// {{{ getFloatDeclaration()/*** Obtain DBMS specific SQL code portion needed to declare an 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* 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 getFloatDeclaration($name, $field){if (isset($this->options['fixedfloat'])) {$this->fixed_float = $this->options['fixedfloat'];} else {if ($this->connection == 0) {// XXX needs more checking$this->connect();}}return("$name DOUBLE".($this->fixed_float ?'('.($this->fixed_float + 2).','.$this->fixed_float.')' : '').(isset($field['default']) ?' DEFAULT '.$this->getFloatValue($field['default']) : '').(isset($field['notnull']) ? ' NOT NULL' : ''));}// }}}// {{{ getDecimalDeclaration()/*** Obtain DBMS specific SQL code portion needed to declare an 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* 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 getDecimalDeclaration($name, $field){return("$name BIGINT".(isset($field['default']) ?' DEFAULT '.$this->getDecimalValue($field['default']) : '').(isset($field['notnull']) ? ' NOT NULL' : ''));}// }}}// {{{ 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){$value = "'";while(!$this->endOfLob($clob)) {if (MDB::isError($result = $this->readLob($clob, $data, $this->options['lob_buffer_length']))) {return($result);}$value .= $this->_quote($data);}$value .= "'";return($value);}// }}}// {{{ freeClobValue()/*** free a character large object** @param resource $prepared_query query handle from prepare()* @param string $clob* @return MDB_OK* @access public*/function freeClobValue($prepared_query, $clob){unset($this->lobs[$clob]);return(MDB_OK);}// }}}// {{{ 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){$value = "'";while(!$this->endOfLob($blob)) {if (MDB::isError($result = $this->readLob($blob, $data, $this->options['lob_buffer_length']))) {return($result);}$value .= addslashes($data);}$value .= "'";return($value);}// }}}// {{{ freeBlobValue()/*** free a binary large object** @param resource $prepared_query query handle from prepare()* @param string $blob* @return MDB_OK* @access public*/function freeBlobValue($prepared_query, $blob){unset($this->lobs[$blob]);return(MDB_OK);}// }}}// {{{ 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' : (float)$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' : strval(round(doubleval($value)*$this->decimal_factor)));}// }}}// {{{ 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 = TRUE){$sequence_name = $this->getSequenceName($seq_name);$this->expectError(MDB_ERROR_NOSUCHTABLE);$result = $this->query("INSERT INTO $sequence_name (".$this->options['sequence_col_name'].") VALUES (NULL)");$this->popExpect();if ($ondemand && MDB::isError($result) &&$result->getCode() == MDB_ERROR_NOSUCHTABLE){// Since we are create the sequence on demand// we know the first id = 1 so initialize the// sequence at 2$result = $this->createSequence($seq_name, 2);if (MDB::isError($result)) {return($this->raiseError(MDB_ERROR, NULL, NULL,'Next ID: on demand sequence could not be created'));} else {// First ID of a newly created sequence is 1return(1);}}$value = intval(@mysql_insert_id($this->connection));$res = $this->query("DELETE FROM $sequence_name WHERE ".$this->options['sequence_col_name']." < $value");if (MDB::isError($res)) {$this->warnings[] = 'Next ID: could not delete previous sequence table values';}return($value);}// }}}// {{{ 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){$sequence_name = $this->getSequenceName($seq_name);$result = $this->query("SELECT MAX(".$this->options['sequence_col_name'].") FROM $sequence_name", 'integer');if (MDB::isError($result)) {return($result);}return($this->fetchOne($result));}// }}}// {{{ fetchInto()/*** Fetch a row and insert the data into an existing array.** @param resource $result result identifier* @param int $fetchmode how the array data should be indexed* @param int $rownum the row number to fetch* @return int data array on success, a MDB error on failure* @access public*/function fetchInto($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rownum = NULL){$result_value = intval($result);if ($rownum == NULL) {++$this->highest_fetched_row[$result_value];} else {if (!@mysql_data_seek($result, $rownum)) {return(NULL);}$this->highest_fetched_row[$result_value] =max($this->highest_fetched_row[$result_value], $rownum);}if ($fetchmode == MDB_FETCHMODE_DEFAULT) {$fetchmode = $this->fetchmode;}if ($fetchmode & MDB_FETCHMODE_ASSOC) {$row = @mysql_fetch_assoc($result);if (is_array($row) && $this->options['optimize'] == 'portability') {$row = array_change_key_case($row, CASE_LOWER);}} else {$row = @mysql_fetch_row($result);}if (!$row) {if($this->options['autofree']) {$this->freeResult($result);}return(NULL);}if (isset($this->result_types[$result_value])) {$row = $this->convertResultRow($result, $row);}return($row);}// }}}// {{{ nextResult()/*** Move the internal mysql result pointer to the next available result* Currently not supported** @param a valid result resource* @return true if a result is available otherwise return false* @access public*/function nextResult($result){return(FALSE);}// }}}// {{{ 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) {$count = 0;$id = 0;$res = array();/** depending on $mode, metadata returns the following values:** - mode is false (default):* $result[]:* [0]['table'] table name* [0]['name'] field name* [0]['type'] field type* [0]['len'] field length* [0]['flags'] field flags** - mode is MDB_TABLEINFO_ORDER* $result[]:* ['num_fields'] number of metadata records* [0]['table'] table name* [0]['name'] field name* [0]['type'] field type* [0]['len'] field length* [0]['flags'] field flags* ['order'][field name] index of field named "field name"* The last one is used, if you have a field name, but no index.* Test: if (isset($result['meta']['myfield'])) { ...** - mode is MDB_TABLEINFO_ORDERTABLE* the same as above. but additionally* ['ordertable'][table name][field name] index of field* named 'field name'** this is, because if you have fields from different* tables with the same field name * they override each* other with MDB_TABLEINFO_ORDER** you can combine MDB_TABLEINFO_ORDER and* MDB_TABLEINFO_ORDERTABLE with MDB_TABLEINFO_ORDER |* MDB_TABLEINFO_ORDERTABLE * or with MDB_TABLEINFO_FULL*/// if $result is a string, then we want information about a// table without a resultsetif (is_string($result)) {if (MDB::isError($connect = $this->connect())) {return $connect;}$id = @mysql_list_fields($this->database_name,$result, $this->connection);if (empty($id)) {return($this->mysqlRaiseError());}} else { // else we want information about a resultset$id = $result;if (empty($id)) {return($this->mysqlRaiseError());}}$count = @mysql_num_fields($id);// made this IF due to performance (one if is faster than $count if's)if (empty($mode)) {for ($i = 0, $j = 0; $i<$count; $i++) {$name = @mysql_field_name($id, $i);if ($name != 'dummy_primary_key') {$res[$j]['table'] = @mysql_field_table($id, $i);$res[$j]['name'] = $name;$res[$j]['type'] = @mysql_field_type($id, $i);$res[$j]['len'] = @mysql_field_len($id, $i);$res[$j]['flags'] = @mysql_field_flags($id, $i);$j++;}}} else { // full$res['num_fields'] = $count;for ($i = 0; $i<$count; $i++) {$name = @mysql_field_name($id, $i);if ($name != 'dummy_primary_key') {$res[$j]['table'] = @mysql_field_table($id, $i);$res[$j]['name'] = $name;$res[$j]['type'] = @mysql_field_type($id, $i);$res[$j]['len'] = @mysql_field_len($id, $i);$res[$j]['flags'] = @mysql_field_flags($id, $i);if ($mode & MDB_TABLEINFO_ORDER) {// note sure if this should be $i or $j$res['order'][$res[$j]['name']] = $i;}if ($mode & MDB_TABLEINFO_ORDERTABLE) {$res['ordertable'][$res[$j]['table']][$res[$j]['name']] = $j;}$j++;}}}// free the result only if we were called on a tableif (is_string($result)) {@mysql_free_result($id);}return($res);}}?>