%PDF- %PDF-
Direktori : /home1/lightco1/public_html/lightingrepublic.com.au/libraries/koowa/database/adapter/ |
Current File : //home1/lightco1/public_html/lightingrepublic.com.au/libraries/koowa/database/adapter/mysqli.php |
<?php /** * @version $Id$ * @package Koowa_Database * @subpackage Adapter * @copyright Copyright (C) 2007 - 2012 Johan Janssens. All rights reserved. * @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> * @link http://www.nooku.org */ /** * Mysqli Database Adapter * * @author Johan Janssens <johan@nooku.org> * @package Koowa_Database * @subpackage Adapter */ class KDatabaseAdapterMysqli extends KDatabaseAdapterAbstract { /** * Quote for named objects * * @var string */ protected $_name_quote = '`'; /** * Map of native MySQL types to generic types used when reading * table column information. * * @var array */ protected $_typemap = array( // numeric 'smallint' => 'int', 'int' => 'int', 'integer' => 'int', 'bigint' => 'int', 'mediumint' => 'int', 'smallint' => 'int', 'tinyint' => 'int', 'numeric' => 'numeric', 'dec' => 'numeric', 'decimal' => 'numeric', 'float' => 'float' , 'double' => 'float' , 'real' => 'float' , // boolean 'bool' => 'boolean', 'boolean' => 'boolean', // date & time 'date' => 'date' , 'time' => 'time' , 'datetime' => 'timestamp', 'timestamp' => 'int' , 'year' => 'int' , // string 'national char' => 'string', 'nchar' => 'string', 'char' => 'string', 'binary' => 'string', 'national varchar' => 'string', 'nvarchar' => 'string', 'varchar' => 'string', 'varbinary' => 'string', 'text' => 'string', 'mediumtext' => 'string', 'tinytext' => 'string', 'longtext' => 'string', // blob 'blob' => 'raw', 'tinyblob' => 'raw', 'mediumblob' => 'raw', 'longtext' => 'raw', 'longblob' => 'raw', //other 'set' => 'string', 'enum' => 'string', ); /** * The database name of the active connection * * @var string */ protected $_database; /** * Initializes the options for the object * * Called from {@link __construct()} as a first step of object instantiation. * * @param object An optional KConfig object with configuration options. * @return void */ protected function _initialize(KConfig $config) { $config->append(array( 'options' => array( 'host' => ini_get('mysqli.default_host'), 'username' => ini_get('mysqli.default_user'), 'password' => ini_get('mysqli.default_pw'), 'database' => '', 'port' => ini_get("mysqli.default_port"), 'socket' => ini_get("mysqli.default_socket") ) )); parent::_initialize($config); } /** * Connect to the db * * @return KDatabaseAdapterMysqli */ public function connect() { $oldErrorReporting = error_reporting(0); $mysqli = new mysqli( $this->_options->host, $this->_options->username, $this->_options->password, $this->_options->database, $this->_options->port, $this->_options->socket ); error_reporting($oldErrorReporting); if (mysqli_connect_errno()) { throw new KDatabaseAdapterException('Connect failed: (' . mysqli_connect_errno() . ') ' . mysqli_connect_error(), mysqli_connect_errno()); } // If supported, request real datatypes from MySQL instead of returning everything as a string. if (defined('MYSQLI_OPT_INT_AND_FLOAT_NATIVE')) { $mysqli->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true); } $this->_connection = $mysqli; $this->_connected = true; $this->_database = $this->_options->database; return $this; } /** * Disconnect from db * * @return KDatabaseAdapterMysqli */ public function disconnect() { if ($this->isConnected()) { $this->_connection->close(); $this->_connection = null; $this->_connected = false; } return $this; } /** * Check if the connection is active * * @return boolean */ public function isConnected() { return ($this->_connection instanceof MySQLi) && @$this->_connection->ping(); } /** * Set the connection * * @param resource The connection resource * @return KDatabaseAdapterAbstract * @throws KDatabaseAdapterException If the resource is not an MySQLi instance */ public function setConnection($resource) { if(!($resource instanceof MySQLi)) { throw new KDatabaseAdapterException('Not a MySQLi connection'); } $this->_connection = $resource; return $this; } /** * Get the database name * * @return string The database name */ public function getDatabase() { if(!isset($this->_database)) { $this->_database = $this->select("SELECT DATABASE()", KDatabase::FETCH_FIELD); } return $this->_database; } /** * Set the database name * * @param string The database name * @return KDatabaseAdapterAbstract */ public function setDatabase($database) { if(!$this->_connection->select_db($database)) { throw new KDatabaseException('Could not connect with database : '.$database); } $this->_database = $database; return $this; } /** * Retrieves the table schema information about the given table * * @param string A table name or a list of table names * @return KDatabaseSchemaTable */ public function getTableSchema($table) { if(!isset($this->_table_schema[$table])) { $this->_table_schema[$table] = $this->_fetchTableInfo($table); $this->_table_schema[$table]->indexes = $this->_fetchTableIndexes($table); $this->_table_schema[$table]->columns = $this->_fetchTableColumns($table); } return $this->_table_schema[$table]; } /** * Lock a table. * * @param string Base name of the table. * @param string Real name of the table. * @return boolean True on success, false otherwise. */ public function lockTable($base, $name) { $query = 'LOCK TABLES '.$this->quoteName($this->getTableNeedle().$base).' WRITE'; if($base != $name) { $query .= ', '.$this->quoteName($this->getTableNeedle().$name).' READ'; } // Create commandchain context. $context = $this->getCommandContext(); $context->table = $base; $context->query = $query; if($this->getCommandChain()->run('before.locktable', $context) !== false) { $context->result = $this->execute($context->query, KDatabase::RESULT_USE); $this->getCommandChain()->run('after.locktable', $context); } return $context->result; } /** * Unlock a table. * * @return boolean True on success, false otherwise. */ public function unlockTable() { $query = 'UNLOCK TABLES'; // Create commandchain context. $context = $this->getCommandContext(); $context->table = $base; $context->query = $query; if($this->getCommandChain()->run('before.unlocktable', $context) !== false) { $context->result = $this->execute($context->query, KDatabase::RESULT_USE); $this->getCommandChain()->run('after.unlocktable', $context); } return $context->result; } /** * Fetch the first field of the first row * * @param mysqli_result The result object. A result set identifier returned by the select() function * @param integer The index to use * @return The value returned in the query or null if the query failed. */ protected function _fetchField($result, $key = 0) { $return = null; if($row = $result->fetch_row( )) { $return = $row[(int)$key]; } $result->free(); return $return; } /** * Fetch an array of single field results * * * @param mysqli_result The result object. A result set identifier returned by the select() function * @param integer The index to use * @return array A sequential array of returned rows. */ protected function _fetchFieldList($result, $key = 0) { $array = array(); while ($row = $result->fetch_row( )) { $array[] = $row[(int)$key]; } $result->free(); return $array; } /** * Fetch the first row of a result set as an associative array * * @param mysqli_result The result object. A result set identifier returned by the select() function * @return array */ protected function _fetchArray($result) { $array = $result->fetch_assoc( ); $result->free(); return $array; } /** * Fetch all result rows of a result set as an array of associative arrays * * If <var>key</var> is not empty then the returned array is indexed by the value * of the database key. Returns <var>null</var> if the query fails. * * @param mysqli_result The result object. A result set identifier returned by the select() function * @param string The column name of the index to use * @return array If key is empty as sequential list of returned records. */ protected function _fetchArrayList($result, $key = '') { $array = array(); while ($row = $result->fetch_assoc( )) { if ($key) { $array[$row[$key]] = $row; } else { $array[] = $row; } } $result->free(); return $array; } /** * Fetch the first row of a result set as an object * * @param mysqli_result The result object. A result set identifier returned by the select() function * @param object */ protected function _fetchObject($result) { $object = $result->fetch_object( ); $result->free(); return $object; } /** * Fetch all rows of a result set as an array of objects * * If <var>key</var> is not empty then the returned array is indexed by the value * of the database key. Returns <var>null</var> if the query fails. * * @param mysqli_result The result object. A result set identifier returned by the select() function * @param string The column name of the index to use * @return array If <var>key</var> is empty as sequential array of returned rows. */ protected function _fetchObjectList($result, $key='') { $array = array(); while ($row = $result->fetch_object( )) { if ($key) { $array[$row->$key] = $row; } else { $array[] = $row; } } $result->free(); return $array; } /** * Safely quotes a value for an SQL statement. * * @param mixed The value to quote * @return string An SQL-safe quoted value */ protected function _quoteValue($value) { $value = '\''.mysqli_real_escape_string( $this->_connection, $value ).'\''; return $value; } /** * Retrieves the table schema information about the given tables * * @param array|string A table name or a list of table names * @return DatabaseSchemaTable or NULL if the table doesn't exist */ protected function _fetchTableInfo($table) { $result = null; $sql = $this->quoteValue($this->getTableNeedle().$table); if($info = $this->show( 'SHOW TABLE STATUS LIKE '.$sql, KDatabase::FETCH_OBJECT )) { //Parse the table raw schema data $result = $this->_parseTableInfo($info); } return $result; } /** * Retrieves the column schema information about the given table * * @param string A table name * @return array An array of columns */ protected function _fetchTableColumns($table) { $result = array(); $sql = $this->quoteName($this->getTableNeedle().$table); if($columns = $this->show( 'SHOW FULL COLUMNS FROM '.$sql, KDatabase::FETCH_OBJECT_LIST)) { foreach($columns as $column) { //Set the table name in the raw info (MySQL doesn't add this) $column->Table = $table; //Parse the column raw schema data $column = $this->_parseColumnInfo($column, $table); $result[$column->name] = $column; } } return $result; } /** * Retrieves the index information about the given table * * @param string A table name * @return array An associative array of indexes by index name */ protected function _fetchTableIndexes($table) { $result = array(); $sql = $this->quoteName($this->getTableNeedle().$table); if($indexes = $this->show('SHOW INDEX FROM '.$sql , KDatabase::FETCH_OBJECT_LIST)) { foreach ($indexes as $index) { $result[$index->Key_name][$index->Seq_in_index] = $index; } } return $result; } /** * Parse the raw table schema information * * @param object The raw table schema information * @return KDatabaseSchemaTable */ protected function _parseTableInfo($info) { $table = new KDatabaseSchemaTable; $table->name = $info->Name; $table->engine = $info->Engine; $table->type = $info->Comment == 'VIEW' ? 'VIEW' : 'BASE'; $table->length = $info->Data_length; $table->autoinc = $info->Auto_increment; $table->collation = $info->Collation; $table->behaviors = array(); $table->description = $info->Comment != 'VIEW' ? $info->Comment : ''; return $table; } /** * Parse the raw column schema information * * @param object The raw column schema information * @return KDatabaseSchemaColumn */ protected function _parseColumnInfo($info) { //Parse the filter information from the comment $filter = array(); preg_match('#@Filter\("(.*)"\)#Ui', $info->Comment, $filter); list($type, $length, $scope) = $this->_parseColumnType($info->Type); $column = $this->getService('koowa:database.schema.column'); $column->name = $info->Field; $column->type = $type; $column->length = ($length ? $length : null); $column->scope = ($scope ? (int) $scope : null); $column->default = $info->Default; $column->required = (bool) ($info->Null != 'YES'); $column->primary = (bool) ($info->Key == 'PRI'); $column->unique = (bool) ($info->Key == 'UNI' || $info->Key == 'PRI'); $column->autoinc = (bool) (strpos($info->Extra, 'auto_increment') !== false); $column->filter = isset($filter[1]) ? explode(',', $filter[1]) : $this->_typemap[$type]; // Don't keep "size" for integers if (substr($type, -3) == 'int') { $column->length = null; } // Get the related fields if the column is primary key or part of a unqiue multi column index if($indexes = $this->_table_schema[$info->Table]->indexes) { foreach($indexes as $index) { //We only deal with composite-unique indexes if(count($index) > 1 && !$index[1]->Non_unique) { $fields = array(); foreach($index as $field) { $fields[$field->Column_name] = $field->Column_name; } if(array_key_exists($column->name, $fields)) { unset($fields[$column->name]); $column->related = array_values($fields); $column->unique = true; break; } } } } return $column; } /** * Given a raw column specification, parse into datatype, length, and decimal scope. * * @param string The column specification; for example, * "VARCHAR(255)" or "NUMERIC(10,2)" or "float(6,2) UNSIGNED" or ENUM('yes','no','maybe') * * @return array A sequential array of the column type, size, and scope. */ protected function _parseColumnType($spec) { $spec = strtolower($spec); $type = null; $length = null; $scope = null; // find the type first $type = strtok($spec, '( '); // find the parens, if any if (false !== ($pos = strpos($spec, '('))) { // there were parens, so there's at least a length // remove parens to get the size. $length = trim(substr(strtok($spec, ' '), $pos), '()'); if($type != 'enum' && $type != 'set') { // A comma in the size indicates a scope. $pos = strpos($length, ','); if ($pos !== false) { $scope = substr($length, $pos + 1); $length = substr($length, 0, $pos); } } else $length = explode(',', str_replace("'", "", $length)); } return array($type, $length, $scope); } }