From 6bf3f7ded400c925dd66df2c2612c095d447c7b0 Mon Sep 17 00:00:00 2001 From: Simon Welsh Date: Sat, 29 Oct 2011 13:34:11 +1300 Subject: [PATCH] Switches MySQLDatabase to use the MySQLi class rather than the mysql_* functions. --- model/MySQLDatabase.php | 139 ++++++++++++++++++++++++---------------- 1 file changed, 83 insertions(+), 56 deletions(-) diff --git a/model/MySQLDatabase.php b/model/MySQLDatabase.php index ed85f8344..535c740a7 100644 --- a/model/MySQLDatabase.php +++ b/model/MySQLDatabase.php @@ -28,7 +28,7 @@ class MySQLDatabase extends SS_Database { private static $connection_charset = null; - private $supportsTransactions=false; + private $supportsTransactions = true; /** * Sets the character set for the MySQL database connection. @@ -54,22 +54,22 @@ class MySQLDatabase extends SS_Database { * - timezone: (optional) The timezone offset. For example: +12:00, "Pacific/Auckland", or "SYSTEM" */ public function __construct($parameters) { - $this->dbConn = mysql_connect($parameters['server'], $parameters['username'], $parameters['password'], true); + $this->dbConn = new MySQLi($parameters['server'], $parameters['username'], $parameters['password']); + + if($this->dbConn->connect_error) { + $this->databaseError("Couldn't connect to MySQL database | " . $this->dbConn->connect_error); + } + + $this->query("SET sql_mode = 'ANSI'"); if(self::$connection_charset) { - $this->query("SET CHARACTER SET '" . self::$connection_charset . "'"); - $this->query("SET NAMES '" . self::$connection_charset . "'"); + $this->dbConn->set_charset(self::$connection_charset); } - $this->active = mysql_select_db($parameters['database'], $this->dbConn); + $this->active = $this->dbConn->select_db($parameters['database']); $this->database = $parameters['database']; - if(!$this->dbConn) { - $this->databaseError("Couldn't connect to MySQL database"); - } - if(isset($parameters['timezone'])) $this->query(sprintf("SET SESSION time_zone = '%s'", $parameters['timezone'])); - $this->query("SET sql_mode = 'ANSI'"); } /** @@ -84,7 +84,7 @@ class MySQLDatabase extends SS_Database { * @return boolean */ public function supportsCollations() { - return $this->getVersion() >= 4.1; + return true; } /** @@ -92,7 +92,7 @@ class MySQLDatabase extends SS_Database { * @return string */ public function getVersion() { - return mysql_get_server_info($this->dbConn); + return $this->dbConn->server_info; } /** @@ -113,19 +113,19 @@ class MySQLDatabase extends SS_Database { $starttime = microtime(true); } - $handle = mysql_query($sql, $this->dbConn); + $handle = $this->dbConn->query($sql); if(isset($_REQUEST['showqueries'])) { $endtime = round(microtime(true) - $starttime,4); Debug::message("\n$sql\n{$endtime}ms\n", false); } - if(!$handle && $errorLevel) $this->databaseError("Couldn't run query: $sql | " . mysql_error($this->dbConn), $errorLevel); + if(!$handle && $errorLevel) $this->databaseError("Couldn't run query: $sql | " . $this->dbConn->error, $errorLevel); return new MySQLQuery($this, $handle); } public function getGeneratedID($table) { - return mysql_insert_id($this->dbConn); + return $this->dbConn->insert_id; } public function isActive() { @@ -133,15 +133,13 @@ class MySQLDatabase extends SS_Database { } public function createDatabase() { - $this->query("CREATE DATABASE `$this->database`"); - $this->query("USE `$this->database`"); + $this->query("CREATE DATABASE \"$this->database\""); + $this->query("USE \"$this->database\""); $this->tableList = $this->fieldList = $this->indexList = null; - if(mysql_select_db($this->database, $this->dbConn)) { - $this->active = true; - return true; - } + $this->active = $this->dbConn->select_db($this->database); + return $this->active; } /** @@ -173,10 +171,12 @@ class MySQLDatabase extends SS_Database { */ public function selectDatabase($dbname) { $this->database = $dbname; - if($this->databaseExists($this->database)) { - if(mysql_select_db($this->database, $this->dbConn)) $this->active = true; - } $this->tableList = $this->fieldList = $this->indexList = null; + $this->active = false; + if($this->databaseExists($this->database)) { + $this->active = $this->dbConn->select_db($this->database); + } + return $this->active; } /** @@ -206,9 +206,15 @@ class MySQLDatabase extends SS_Database { */ public function createTable($table, $fields = null, $indexes = null, $options = null, $advancedOptions = null) { $fieldSchemas = $indexSchemas = ""; - - $addOptions = empty($options[get_class($this)]) ? "ENGINE=MyISAM" : $options[get_class($this)]; - + + if(!empty($options[get_class($this)])) { + $addOptions = $options[get_class($this)]; + } elseif(!empty($options[get_parent_class($this)])) { + $addOptions = $options[get_parent_class($this)]; + } else { + $addOptions = "ENGINE=InnoDB"; + } + if(!isset($fields['ID'])) $fields['ID'] = "int(11) not null auto_increment"; if($fields) foreach($fields as $k => $v) $fieldSchemas .= "\"$k\" $v,\n"; if($indexes) foreach($indexes as $k => $v) $indexSchemas .= $this->getIndexSqlDefinition($k, $v) . ",\n"; @@ -221,7 +227,7 @@ class MySQLDatabase extends SS_Database { $indexSchemas primary key (ID) ) {$addOptions}"); - + return $table; } @@ -235,6 +241,13 @@ class MySQLDatabase extends SS_Database { * @param $alteredOptions */ public function alterTable($tableName, $newFields = null, $newIndexes = null, $alteredFields = null, $alteredIndexes = null, $alteredOptions = null, $advancedOptions = null) { + if($this->isView($tableName)) { + DB::alteration_message( + sprintf("Table %s not changed as it is a view", $tableName), + "changed" + ); + return; + } $fieldSchemas = $indexSchemas = ""; $alterList = array(); @@ -257,7 +270,12 @@ class MySQLDatabase extends SS_Database { ); } } - + + public function isView($tableName) { + $info = $this->query("SHOW /*!50002 FULL*/ TABLES LIKE '$tableName'")->record(); + return $info && strtoupper($info['Table_type']) == 'VIEW'; + } + public function renameTable($oldTableName, $newTableName) { $this->query("ALTER TABLE \"$oldTableName\" RENAME \"$newTableName\""); } @@ -513,7 +531,7 @@ class MySQLDatabase extends SS_Database { * @return int */ public function affectedRows() { - return mysql_affected_rows($this->dbConn); + return $this->dbConn->affected_rows; } function databaseError($msg, $errorLevel = E_USER_ERROR) { @@ -575,7 +593,8 @@ class MySQLDatabase extends SS_Database { $defaultValue = ''; if(isset($values['default']) && is_numeric($values['default'])) { - $defaultValue = ' default ' . $values['default']; + $decs = strpos($precision, ',') !== false ? (int)substr($precision, strpos($precision, ',')+1) : 0; + $defaultValue = ' default ' . number_format($values['default'], $decs, '.', ''); } return 'decimal(' . $precision . ') not null' . $defaultValue; @@ -877,7 +896,7 @@ class MySQLDatabase extends SS_Database { * This will return text which has been escaped in a database-friendly manner. */ function addslashes($value){ - return mysql_real_escape_string($value, $this->dbConn); + return $this->dbConn->real_escape_string($value); } /* @@ -931,14 +950,23 @@ class MySQLDatabase extends SS_Database { * See http://developer.postgresql.org/pgdocs/postgres/sql-set-transaction.html for details on transaction isolation options */ public function transactionStart($transaction_mode=false, $session_characteristics=false){ - //Transactions not set up for MySQL yet + // This sets the isolation level for the NEXT transaction, not the current one. + if($transaction_mode) { + $this->query('SET TRANSACTION ' . $transaction_mode . ';'); + } + + $this->query('START TRANSACTION;'); + + if($session_characteristics) { + $this->query('SET SESSION TRANSACTION ' . $session_characteristics . ';'); + } } /* * Create a savepoint that you can jump back to if you encounter problems */ public function transactionSavepoint($savepoint){ - //Transactions not set up for MySQL yet + $this->query("SAVEPOINT $savepoint;"); } /* @@ -946,15 +974,19 @@ class MySQLDatabase extends SS_Database { * If you encounter a problem at any point during a transaction, you may * need to rollback that particular query, or return to a savepoint */ - public function transactionRollback($savepoint=false){ - //Transactions not set up for MySQL yet + public function transactionRollback($savepoint = false){ + if($savepoint) { + $this->query('ROLLBACK TO ' . $savepoint . ';'); + } else { + $this->query('ROLLBACK'); + } } /* * Commit everything inside this transaction so far */ - public function transactionEnd(){ - //Transactions not set up for MySQL yet + public function transactionEnd($chain = false){ + $this->query('COMMIT AND ' . ($chain ? '' : 'NO ') . 'CHAIN;'); } /** @@ -1098,26 +1130,25 @@ class MySQLQuery extends SS_Query { } public function __destruct() { - if(is_resource($this->handle)) mysql_free_result($this->handle); + if(is_object($this->handle)) $this->handle->free(); } - + public function seek($row) { - return is_resource($this->handle) ? mysql_data_seek($this->handle, $row) : false; + if(is_object($this->handle)) return $this->handle->data_seek($row); } - + public function numRecords() { - return is_resource($this->handle) ? mysql_num_rows($this->handle) : false; + if(is_object($this->handle)) return $this->handle->num_rows; } - + public function nextRecord() { - // Coalesce rather than replace common fields. - if(is_resource($this->handle) && $data = mysql_fetch_row($this->handle)) { - foreach($data as $columnIdx => $value) { - $columnName = mysql_field_name($this->handle, $columnIdx); - // $value || !$ouput[$columnName] means that the *last* occurring value is shown - // !$ouput[$columnName] means that the *first* occurring value is shown - if(isset($value) || !isset($output[$columnName])) { - $output[$columnName] = $value; + if(is_object($this->handle) && $data = $this->handle->fetch_row()) { + $output = array(); + $this->handle->field_seek(0); + while($field = $this->handle->fetch_field()) { + $columnName = $field->name; + if(isset($data[$this->handle->current_field-1]) || !isset($output[$columnName])) { + $output[$columnName] = $data[$this->handle->current_field-1]; } } return $output; @@ -1125,8 +1156,4 @@ class MySQLQuery extends SS_Query { return false; } } - - } - -?>