charset = $options['charset']; // Finalize initialisation. parent::__construct($options); } /** * Connects to the database if needed. * * @return void Returns void if the database connected successfully. * * @since 1.0 * @throws \RuntimeException */ public function connect() { parent::connect(); $this->connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $this->connection->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true); } /** * Test to see if the MySQL connector is available. * * @return boolean True on success, false otherwise. * * @since 1.0 */ public static function isSupported() { return in_array('mysql', \PDO::getAvailableDrivers()); } /** * Drops a table from the database. * * @param string $tableName The name of the database table to drop. * @param boolean $ifExists Optionally specify that the table must exist before it is dropped. * * @return MysqlDriver Returns this object to support chaining. * * @since 1.0 * @throws \RuntimeException */ public function dropTable($tableName, $ifExists = true) { $this->connect(); $query = $this->getQuery(true); $query->setQuery('DROP TABLE ' . ($ifExists ? 'IF EXISTS ' : '') . $this->quoteName($tableName)); $this->setQuery($query); $this->execute(); return $this; } /** * Select a database for use. * * @param string $database The name of the database to select for use. * * @return boolean True if the database was successfully selected. * * @since 1.0 * @throws \RuntimeException */ public function select($database) { $this->connect(); $this->setQuery('USE ' . $this->quoteName($database)); $this->execute(); return $this; } /** * Method to get the database collation in use by sampling a text field of a table in the database. * * @return mixed The collation in use by the database (string) or boolean false if not supported. * * @since 1.0 * @throws \RuntimeException */ public function getCollation() { $this->connect(); $tables = $this->getTableList(); $this->setQuery('SHOW FULL COLUMNS FROM ' . $tables[0]); $array = $this->loadAssocList(); foreach ($array as $field) { if (!is_null($field['Collation'])) { return $field['Collation']; } } return null; } /** * Shows the table CREATE statement that creates the given tables. * * @param mixed $tables A table name or a list of table names. * * @return array A list of the create SQL for the tables. * * @since 1.0 * @throws \RuntimeException */ public function getTableCreate($tables) { $this->connect(); // Initialise variables. $result = array(); // Sanitize input to an array and iterate over the list. settype($tables, 'array'); foreach ($tables as $table) { $this->setQuery('SHOW CREATE TABLE ' . $this->quoteName($table)); $row = $this->loadRow(); // Populate the result array based on the create statements. $result[$table] = $row[1]; } return $result; } /** * Retrieves field information about a given table. * * @param string $table The name of the database table. * @param boolean $typeOnly True to only return field types. * * @return array An array of fields for the database table. * * @since 1.0 * @throws \RuntimeException */ public function getTableColumns($table, $typeOnly = true) { $this->connect(); $result = array(); // Set the query to get the table fields statement. $this->setQuery('SHOW FULL COLUMNS FROM ' . $this->quoteName($table)); $fields = $this->loadObjectList(); // If we only want the type as the value add just that to the list. if ($typeOnly) { foreach ($fields as $field) { $result[$field->Field] = preg_replace("/[(0-9)]/", '', $field->Type); } } // If we want the whole field data object add that to the list. else { foreach ($fields as $field) { $result[$field->Field] = $field; } } return $result; } /** * Get the details list of keys for a table. * * @param string $table The name of the table. * * @return array An array of the column specification for the table. * * @since 1.0 * @throws \RuntimeException */ public function getTableKeys($table) { $this->connect(); // Get the details columns information. $this->setQuery('SHOW KEYS FROM ' . $this->quoteName($table)); $keys = $this->loadObjectList(); return $keys; } /** * Method to get an array of all tables in the database. * * @return array An array of all the tables in the database. * * @since 1.0 * @throws \RuntimeException */ public function getTableList() { $this->connect(); // Set the query to get the tables statement. $this->setQuery('SHOW TABLES'); $tables = $this->loadColumn(); return $tables; } /** * Get the version of the database connector. * * @return string The database connector version. * * @since 1.0 */ public function getVersion() { $this->connect(); return $this->getOption(\PDO::ATTR_SERVER_VERSION); } /** * Locks a table in the database. * * @param string $table The name of the table to unlock. * * @return MysqlDriver Returns this object to support chaining. * * @since 1.0 * @throws \RuntimeException */ public function lockTable($table) { $query = $this->getQuery(true); $this->setQuery('LOCK TABLES ' . $this->quoteName($table) . ' WRITE'); $this->setQuery($query)->execute(); return $this; } /** * Renames a table in the database. * * @param string $oldTable The name of the table to be renamed * @param string $newTable The new name for the table. * @param string $backup Not used by MySQL. * @param string $prefix Not used by MySQL. * * @return MysqlDriver Returns this object to support chaining. * * @since 1.0 * @throws \RuntimeException */ public function renameTable($oldTable, $newTable, $backup = null, $prefix = null) { $this->setQuery('RENAME TABLE ' . $this->quoteName($oldTable) . ' TO ' . $this->quoteName($newTable)); $this->execute(); return $this; } /** * Method to escape a string for usage in an SQL statement. * * Oracle escaping reference: * http://www.orafaq.com/wiki/SQL_FAQ#How_does_one_escape_special_characters_when_writing_SQL_queries.3F * * SQLite escaping notes: * http://www.sqlite.org/faq.html#q14 * * Method body is as implemented by the Zend Framework * * Note: Using query objects with bound variables is * preferable to the below. * * @param string $text The string to be escaped. * @param boolean $extra Unused optional parameter to provide extra escaping. * * @return string The escaped string. * * @since 1.0 */ public function escape($text, $extra = false) { $this->connect(); if (is_int($text) || is_float($text)) { return $text; } $result = substr($this->connection->quote($text), 1, -1); if ($extra) { $result = addcslashes($result, '%_'); } return $result; } /** * Unlocks tables in the database. * * @return MysqlDriver Returns this object to support chaining. * * @since 1.0 * @throws \RuntimeException */ public function unlockTables() { $this->setQuery('UNLOCK TABLES')->execute(); return $this; } /** * Method to commit a transaction. * * @param boolean $toSavepoint If true, commit to the last savepoint. * * @return void * * @since 1.0 * @throws \RuntimeException */ public function transactionCommit($toSavepoint = false) { $this->connect(); if (!$toSavepoint || $this->transactionDepth <= 1) { parent::transactionCommit($toSavepoint); } else { $this->transactionDepth--; } } /** * Method to roll back a transaction. * * @param boolean $toSavepoint If true, rollback to the last savepoint. * * @return void * * @since 1.0 * @throws \RuntimeException */ public function transactionRollback($toSavepoint = false) { $this->connect(); if (!$toSavepoint || $this->transactionDepth <= 1) { parent::transactionRollback($toSavepoint); } else { $savepoint = 'SP_' . ($this->transactionDepth - 1); $this->setQuery('ROLLBACK TO SAVEPOINT ' . $this->quoteName($savepoint)); if ($this->execute()) { $this->transactionDepth--; } } } /** * Method to initialize a transaction. * * @param boolean $asSavepoint If true and a transaction is already active, a savepoint will be created. * * @return void * * @since 1.0 * @throws \RuntimeException */ public function transactionStart($asSavepoint = false) { $this->connect(); if (!$asSavepoint || !$this->transactionDepth) { parent::transactionStart($asSavepoint); } else { $savepoint = 'SP_' . $this->transactionDepth; $this->setQuery('SAVEPOINT ' . $this->quoteName($savepoint)); if ($this->execute()) { $this->transactionDepth++; } } } }