From b55f9854e770ba7c37e0e1914c8570c856cbecf3 Mon Sep 17 00:00:00 2001 From: Meik Sievertsen Date: Mon, 19 Jan 2009 16:07:17 +0000 Subject: [PATCH] update mysql DBAL to be supported now too git-svn-id: file:///svn/phpbb/trunk@9280 89ea8834-ac86-4346-8a33-228a782c2dd0 --- phpBB/includes/db/db_tools.php | 449 ++++++++------------------------- phpBB/includes/db/mysql.php | 378 ++++++++++++--------------- phpBB/includes/db/mysqli.php | 133 +++++++--- 3 files changed, 363 insertions(+), 597 deletions(-) diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index b19680a14c..e57063534e 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -18,314 +18,66 @@ if (!defined('IN_PHPBB')) /** * Database Tools for handling cross-db actions such as altering columns, etc. -* Currently not supported is returning SQL for creating tables. * * @package dbal -* @note currently not used within phpBB3, but may be utilized later. */ class phpbb_db_tools { + /** + * @var object DB object + */ public $db = NULL; - public $dbms_type_map = array( - 'mysql' => array( - 'INT:' => 'int(%d)', - 'BINT' => 'bigint(20)', - 'UINT' => 'mediumint(8) UNSIGNED', - 'UINT:' => 'int(%d) UNSIGNED', - 'TINT:' => 'tinyint(%d)', - 'USINT' => 'smallint(4) UNSIGNED', - 'BOOL' => 'tinyint(1) UNSIGNED', - 'VCHAR' => 'varchar(255)', - 'VCHAR:' => 'varchar(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'text', - 'XSTEXT_UNI'=> 'varchar(100)', - 'STEXT' => 'text', - 'STEXT_UNI' => 'varchar(255)', - 'TEXT' => 'text', - 'TEXT_UNI' => 'text', - 'MTEXT' => 'mediumtext', - 'MTEXT_UNI' => 'mediumtext', - 'TIMESTAMP' => 'int(11) UNSIGNED', - 'DECIMAL' => 'decimal(5,2)', - 'DECIMAL:' => 'decimal(%d,2)', - 'PDECIMAL' => 'decimal(6,3)', - 'PDECIMAL:' => 'decimal(%d,3)', - 'VCHAR_UNI' => 'varchar(255)', - 'VCHAR_UNI:'=> 'varchar(%d)', - 'VARBINARY' => 'varbinary(255)', - ), - - 'firebird' => array( - 'INT:' => 'INTEGER', - 'BINT' => 'DOUBLE PRECISION', - 'UINT' => 'INTEGER', - 'UINT:' => 'INTEGER', - 'TINT:' => 'INTEGER', - 'USINT' => 'INTEGER', - 'BOOL' => 'INTEGER', - 'VCHAR' => 'VARCHAR(255) CHARACTER SET NONE', - 'VCHAR:' => 'VARCHAR(%d) CHARACTER SET NONE', - 'CHAR:' => 'CHAR(%d) CHARACTER SET NONE', - 'XSTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'STEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'TEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'MTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'XSTEXT_UNI'=> 'VARCHAR(100) CHARACTER SET UTF8', - 'STEXT_UNI' => 'VARCHAR(255) CHARACTER SET UTF8', - 'TEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8', - 'MTEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8', - 'TIMESTAMP' => 'INTEGER', - 'DECIMAL' => 'DOUBLE PRECISION', - 'DECIMAL:' => 'DOUBLE PRECISION', - 'PDECIMAL' => 'DOUBLE PRECISION', - 'PDECIMAL:' => 'DOUBLE PRECISION', - 'VCHAR_UNI' => 'VARCHAR(255) CHARACTER SET UTF8', - 'VCHAR_UNI:'=> 'VARCHAR(%d) CHARACTER SET UTF8', - 'VARBINARY' => 'CHAR(255) CHARACTER SET NONE', - ), - - 'mssql' => array( - 'INT:' => '[int]', - 'BINT' => '[float]', - 'UINT' => '[int]', - 'UINT:' => '[int]', - 'TINT:' => '[int]', - 'USINT' => '[int]', - 'BOOL' => '[int]', - 'VCHAR' => '[varchar] (255)', - 'VCHAR:' => '[varchar] (%d)', - 'CHAR:' => '[char] (%d)', - 'XSTEXT' => '[varchar] (1000)', - 'STEXT' => '[varchar] (3000)', - 'TEXT' => '[varchar] (8000)', - 'MTEXT' => '[text]', - 'XSTEXT_UNI'=> '[varchar] (100)', - 'STEXT_UNI' => '[varchar] (255)', - 'TEXT_UNI' => '[varchar] (4000)', - 'MTEXT_UNI' => '[text]', - 'TIMESTAMP' => '[int]', - 'DECIMAL' => '[float]', - 'DECIMAL:' => '[float]', - 'PDECIMAL' => '[float]', - 'PDECIMAL:' => '[float]', - 'VCHAR_UNI' => '[varchar] (255)', - 'VCHAR_UNI:'=> '[varchar] (%d)', - 'VARBINARY' => '[varchar] (255)', - ), - - 'oracle' => array( - 'INT:' => 'number(%d)', - 'BINT' => 'number(20)', - 'UINT' => 'number(8)', - 'UINT:' => 'number(%d)', - 'TINT:' => 'number(%d)', - 'USINT' => 'number(4)', - 'BOOL' => 'number(1)', - 'VCHAR' => 'varchar2(255)', - 'VCHAR:' => 'varchar2(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'varchar2(1000)', - 'STEXT' => 'varchar2(3000)', - 'TEXT' => 'clob', - 'MTEXT' => 'clob', - 'XSTEXT_UNI'=> 'varchar2(300)', - 'STEXT_UNI' => 'varchar2(765)', - 'TEXT_UNI' => 'clob', - 'MTEXT_UNI' => 'clob', - 'TIMESTAMP' => 'number(11)', - 'DECIMAL' => 'number(5, 2)', - 'DECIMAL:' => 'number(%d, 2)', - 'PDECIMAL' => 'number(6, 3)', - 'PDECIMAL:' => 'number(%d, 3)', - 'VCHAR_UNI' => 'varchar2(255)', - 'VCHAR_UNI:'=> array('varchar2(%d)', 'limit' => array('mult', 3, 765, 'clob')), - 'VARBINARY' => 'raw(255)', - ), - - 'sqlite' => array( - 'INT:' => 'int(%d)', - 'BINT' => 'bigint(20)', - 'UINT' => 'INTEGER UNSIGNED', //'mediumint(8) UNSIGNED', - 'UINT:' => 'INTEGER UNSIGNED', // 'int(%d) UNSIGNED', - 'TINT:' => 'tinyint(%d)', - 'USINT' => 'INTEGER UNSIGNED', //'mediumint(4) UNSIGNED', - 'BOOL' => 'INTEGER UNSIGNED', //'tinyint(1) UNSIGNED', - 'VCHAR' => 'varchar(255)', - 'VCHAR:' => 'varchar(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'text(65535)', - 'STEXT' => 'text(65535)', - 'TEXT' => 'text(65535)', - 'MTEXT' => 'mediumtext(16777215)', - 'XSTEXT_UNI'=> 'text(65535)', - 'STEXT_UNI' => 'text(65535)', - 'TEXT_UNI' => 'text(65535)', - 'MTEXT_UNI' => 'mediumtext(16777215)', - 'TIMESTAMP' => 'INTEGER UNSIGNED', //'int(11) UNSIGNED', - 'DECIMAL' => 'decimal(5,2)', - 'DECIMAL:' => 'decimal(%d,2)', - 'PDECIMAL' => 'decimal(6,3)', - 'PDECIMAL:' => 'decimal(%d,3)', - 'VCHAR_UNI' => 'varchar(255)', - 'VCHAR_UNI:'=> 'varchar(%d)', - 'VARBINARY' => 'blob', - ), - - 'db2' => array( - 'INT:' => 'integer', - 'BINT' => 'float', - 'UINT' => 'integer', - 'UINT:' => 'integer', - 'TINT:' => 'smallint', - 'USINT' => 'smallint', - 'BOOL' => 'smallint', - 'VCHAR' => 'varchar(255)', - 'VCHAR:' => 'varchar(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'clob(65K)', - 'STEXT' => 'varchar(3000)', - 'TEXT' => 'clob(65K)', - 'MTEXT' => 'clob(16M)', - 'XSTEXT_UNI'=> 'varchar(100)', - 'STEXT_UNI' => 'varchar(255)', - 'TEXT_UNI' => 'clob(65K)', - 'MTEXT_UNI' => 'clob(16M)', - 'TIMESTAMP' => 'integer', - 'DECIMAL' => 'float', - 'VCHAR_UNI' => 'varchar(255)', - 'VCHAR_UNI:'=> 'varchar(%d)', - 'VARBINARY' => 'varchar(255)', - ), - - 'postgres' => array( - 'INT:' => 'INT4', - 'BINT' => 'INT8', - 'UINT' => 'INT4', // unsigned - 'UINT:' => 'INT4', // unsigned - 'USINT' => 'INT2', // unsigned - 'BOOL' => 'INT2', // unsigned - 'TINT:' => 'INT2', - 'VCHAR' => 'varchar(255)', - 'VCHAR:' => 'varchar(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'varchar(1000)', - 'STEXT' => 'varchar(3000)', - 'TEXT' => 'varchar(8000)', - 'MTEXT' => 'TEXT', - 'XSTEXT_UNI'=> 'varchar(100)', - 'STEXT_UNI' => 'varchar(255)', - 'TEXT_UNI' => 'varchar(4000)', - 'MTEXT_UNI' => 'TEXT', - 'TIMESTAMP' => 'INT4', // unsigned - 'DECIMAL' => 'decimal(5,2)', - 'DECIMAL:' => 'decimal(%d,2)', - 'PDECIMAL' => 'decimal(6,3)', - 'PDECIMAL:' => 'decimal(%d,3)', - 'VCHAR_UNI' => 'varchar(255)', - 'VCHAR_UNI:'=> 'varchar(%d)', - 'VARBINARY' => 'bytea', - ), - ); - - // A list of types being unsigned for better reference in some db's + /** + * A list of types being unsigned for better reference in some db's + * @var array + */ public $unsigned_types = array('UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP'); - public $supported_dbms = array('firebird', 'mssql', 'mysql', 'oracle', 'postgres', 'sqlite', 'db2'); /** - * Set this to true if you only want to return the 'to-be-executed' SQL statement(s) (as an array). + * A list of supported DBMS. We change this class to support more DBMS, the DBMS itself only need to follow some rules. + * @var array + */ + public $supported_dbms = array('mysql', 'mssql', 'sqlite', 'oracle', 'firebird', 'db2', 'postgres'); + + /** + * This is set to true if user only wants to return the 'to-be-executed' SQL statement(s) (as an array). + * This mode has no effect on some methods (inserting of data for example). This is expressed within the methods command. */ public $return_statements = false; - public function __construct($db, $return_statements = false) + /** + * Constructor. Set DB Object and set {@link $return_statements return_statements}. + * + * @param phpbb_dbal $db DBAL object + * @param bool $return_statements True if only statements should be returned and no SQL being executed + */ + public function __construct(phpbb_dbal $db, $return_statements = false) { $this->db = $db; $this->return_statements = $return_statements; - } - /** - * Return/Execute specific SQL commands needed for some databases - */ - public function sql_install_begin() - { - $statements = array(); - - switch ($this->db->dbms_type) + if (!in_array($this->db->dbms_type, $this->supported_dbms)) { - case 'oracle': - /* - CREATE TABLESPACE "PHPBB" - LOGGING - DATAFILE \'E:\ORACLE\ORADATA\LOCAL\PHPBB.ora\' - SIZE 10M - AUTOEXTEND ON NEXT 10M - MAXSIZE 100M; - - CREATE USER "PHPBB" - PROFILE "DEFAULT" - IDENTIFIED BY "phpbb_password" - DEFAULT TABLESPACE "PHPBB" - QUOTA UNLIMITED ON "PHPBB" - ACCOUNT UNLOCK; - - GRANT ANALYZE ANY TO "PHPBB"; - GRANT CREATE SEQUENCE TO "PHPBB"; - GRANT CREATE SESSION TO "PHPBB"; - GRANT CREATE TABLE TO "PHPBB"; - GRANT CREATE TRIGGER TO "PHPBB"; - GRANT CREATE VIEW TO "PHPBB"; - GRANT "CONNECT" TO "PHPBB"; - - COMMIT; - DISCONNECT; - */ - break; - - case 'postgres': - // Create Domain -/* $statements[] = 'CREATE DOMAIN varchar_ci AS varchar(255) NOT NULL DEFAULT \'\'::character varying;'; - - // Operation functions - $statements[] = 'CREATE FUNCTION _varchar_ci_equal(varchar_ci, varchar_ci) RETURNS boolean AS \'SELECT LOWER($1) = LOWER($2)\' LANGUAGE SQL STRICT'; - $statements[] = 'CREATE FUNCTION _varchar_ci_not_equal(varchar_ci, varchar_ci) RETURNS boolean AS \'SELECT LOWER($1) != LOWER($2)\' LANGUAGE SQL STRICT'; - $statements[] = 'CREATE FUNCTION _varchar_ci_less_than(varchar_ci, varchar_ci) RETURNS boolean AS \'SELECT LOWER($1) < LOWER($2)\' LANGUAGE SQL STRICT'; - $statements[] = 'CREATE FUNCTION _varchar_ci_less_equal(varchar_ci, varchar_ci) RETURNS boolean AS \'SELECT LOWER($1) <= LOWER($2)\' LANGUAGE SQL STRICT'; - $statements[] = 'CREATE FUNCTION _varchar_ci_greater_than(varchar_ci, varchar_ci) RETURNS boolean AS \'SELECT LOWER($1) > LOWER($2)\' LANGUAGE SQL STRICT'; - $statements[] = 'CREATE FUNCTION _varchar_ci_greater_equals(varchar_ci, varchar_ci) RETURNS boolean AS \'SELECT LOWER($1) >= LOWER($2)\' LANGUAGE SQL STRICT'; - - // Operators - $statements[] = 'CREATE OPERATOR <( PROCEDURE = _varchar_ci_less_than, LEFTARG = varchar_ci, RIGHTARG = varchar_ci, COMMUTATOR = >, NEGATOR = >=, RESTRICT = scalarltsel, JOIN = scalarltjoinsel)'; - $statements[] = 'CREATE OPERATOR <=( PROCEDURE = _varchar_ci_less_equal, LEFTARG = varchar_ci, RIGHTARG = varchar_ci, COMMUTATOR = >=, NEGATOR = >, RESTRICT = scalarltsel, JOIN = scalarltjoinsel)'; - $statements[] = 'CREATE OPERATOR >( PROCEDURE = _varchar_ci_greater_than, LEFTARG = varchar_ci, RIGHTARG = varchar_ci, COMMUTATOR = <, NEGATOR = <=, RESTRICT = scalargtsel, JOIN = scalargtjoinsel);'; - $statements[] = 'CREATE OPERATOR >=( PROCEDURE = _varchar_ci_greater_equals, LEFTARG = varchar_ci, RIGHTARG = varchar_ci, COMMUTATOR = <=, NEGATOR = <, RESTRICT = scalargtsel, JOIN = scalargtjoinsel)'; - $statements[] = 'CREATE OPERATOR <>( PROCEDURE = _varchar_ci_not_equal, LEFTARG = varchar_ci, RIGHTARG = varchar_ci, COMMUTATOR = <>, NEGATOR = =, RESTRICT = neqsel, JOIN = neqjoinsel)'; - $statements[] = 'CREATE OPERATOR =( PROCEDURE = _varchar_ci_equal, LEFTARG = varchar_ci, RIGHTARG = varchar_ci, COMMUTATOR = =, NEGATOR = <>, RESTRICT = eqsel, JOIN = eqjoinsel, HASHES, MERGES, SORT1= <)'; -*/ - break; + trigger_error('DBMS Type ' . $this->db->dbms_type . ' not supported by DB Tools.', E_USER_ERROR); } - - return $this->_sql_run_sql($statements); - } - - public function sql_install_end() - { - return; } /** - * Create table - * For more information have a look at /install/schemas/schema_data.php + * Create SQL Table + * + * @param string $table_name The table name to create + * @param array $table_data Array containing table data. For a sample layout see {@example } + * @return array Statements if $return_statements is true. */ public function sql_create_table($table_name, $table_data) { // holds the DDL for a column $columns = $statements = array(); + // Begin transaction $statements[] = 'begin'; - $table_sql = 'CREATE TABLE ' . $table_name . ' (' . "\n"; - // Determine if we have created a PRIMARY KEY in the earliest $primary_key_gen = false; @@ -335,6 +87,10 @@ class phpbb_db_tools // Determine if the table requires a sequence $create_sequence = false; + // Begin table sql statement + $table_sql = 'CREATE TABLE ' . $table_name . ' (' . "\n"; + + // Iterate through the columns to create a table foreach ($table_data['COLUMNS'] as $column_name => $column_data) { // here lies an array, filled with information compiled on the column's data @@ -343,8 +99,7 @@ class phpbb_db_tools // here we add the definition of the new column to the list of columns $columns[] = "\t {$column_name} " . $prepared_column['column_type_sql']; - // see if we have found a primary key set due to a column definition, - // if we have found it, we can stop looking + // see if we have found a primary key set due to a column definition if we have found it, we can stop looking if (!$primary_key_gen) { $primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set']; @@ -366,6 +121,7 @@ class phpbb_db_tools // this makes up all the columns in the create table statement $table_sql .= implode(",\n", $columns); + // Close the table for two DBMS and add to the statements switch ($this->db->dbms_type) { case 'firebird': @@ -500,30 +256,29 @@ class phpbb_db_tools } } + // Commit Transaction $statements[] = 'commit'; return $this->_sql_run_sql($statements); } /** - * Handle passed database update array. - * Expected structure... - * Key being one of the following - * change_columns: Column changes (only type, not name) - * add_columns: Add columns to a table - * drop_keys: Dropping keys - * drop_columns: Removing/Dropping columns - * add_primary_keys: adding primary keys - * add_unique_index: adding an unique index - * add_index: adding an index + * Handle passed database update array. Update table schema. * - * The values are in this format: - * {KEY} => array( - * {TABLE NAME} => array( - * {COLUMN NAME} => array({COLUMN TYPE}, {DEFAULT VALUE}, {OPTIONAL VARIABLES}), - * {KEY/INDEX NAME} => array({COLUMN NAMES}), - * ) - * } + * Key being one of the following + *
+	* change_columns - Column changes (only type, not name)
+	* add_columns - Add columns to a table
+	* drop_keys - Dropping keys
+	* drop_columns - Removing/Dropping columns
+	* add_primary_keys - adding primary keys
+	* add_unique_index - adding an unique index
+	* add_index - adding an index
+	* 
+ * + * For a complete definition of the layout please see {@example } + * + * @param array $schema_changes The schema array */ public function sql_schema_changes($schema_changes) { @@ -661,12 +416,11 @@ class phpbb_db_tools } /** - * 'table' => 'phpbb_styles_theme', - * 'columns' => array('theme_name', 'theme_copyright', 'theme_path', 'theme_storedb', 'theme_data'), - * 'data' => array( - * array('prosilver', '© phpBB Group', 'prosilver', 1, ''), - * ), - * 'store_auto_increment' => 'THEME_ID', + * Insert SQL data into tables (INSERT). This function DOES NOT SUPPORT $return_statements. SQL queries are executed as is. + * For a complete definition of the layout see {@example } + * + * @param array $schema_data The schema data array + * @param array &$data A replacement array for replacing template variables within the schema */ public function sql_insert_data($schema_data, &$data) { @@ -693,6 +447,13 @@ class phpbb_db_tools } } + /** + * Update SQL data in tables (UPDATE). This function DOES NOT SUPPORT $return_statements. SQL queries are executed as is. + * For a complete definition of the layout see {@example } + * + * @param array $schema_data The schema data array + * @param array &$data A replacement array for replacing template variables within the schema + */ public function sql_update_data($schema_data, &$data) { // Go through the data array... @@ -739,43 +500,12 @@ class phpbb_db_tools $this->db->sql_query($sql); } - private function _sql_get_special_row($value, &$data) - { - if (is_array($value)) - { - if (isset($value['auto_increment'])) - { - $auto_key = explode(':', $value['auto_increment'], 2); - $value_key = $auto_key[0]; - $auto_key = (int) $auto_key[1]; - - if (isset($this->stored_increments[$value_key][$auto_key])) - { - $value = $this->stored_increments[$value_key][$auto_key]; - } - } - else - { - $value = NULL; - } - } - else if (strpos($value, '{') === 0 && strpos($value, '}') === strlen($value) - 1) - { - if (strpos($value, '{L_') === 0 && isset(phpbb::$user->lang[substr($value, 3, -1)])) - { - $value = phpbb::$user->lang[substr($value, 3, -1)]; - } - else if (isset($data[substr($value, 1, -1)])) - { - $value = $data[substr($value, 1, -1)]; - } - } - - return $value; - } - /** * Check if a specified column exist + * + * @param string $table Table to check the column at + * @param string $column_name The column to check + * * @return bool True if column exists, else false */ public function sql_column_exists($table, $column_name) @@ -1593,6 +1323,41 @@ class phpbb_db_tools return $this->_sql_run_sql($statements); } + private function _sql_get_special_row($value, &$data) + { + if (is_array($value)) + { + if (isset($value['auto_increment'])) + { + $auto_key = explode(':', $value['auto_increment'], 2); + $value_key = $auto_key[0]; + $auto_key = (int) $auto_key[1]; + + if (isset($this->stored_increments[$value_key][$auto_key])) + { + $value = $this->stored_increments[$value_key][$auto_key]; + } + } + else + { + $value = NULL; + } + } + else if (strpos($value, '{') === 0 && strpos($value, '}') === strlen($value) - 1) + { + if (strpos($value, '{L_') === 0 && isset(phpbb::$user->lang[substr($value, 3, -1)])) + { + $value = phpbb::$user->lang[substr($value, 3, -1)]; + } + else if (isset($data[substr($value, 1, -1)])) + { + $value = $data[substr($value, 1, -1)]; + } + } + + return $value; + } + /** * Private method for performing sql statements (either execute them or return them) * @access private @@ -1635,9 +1400,9 @@ class phpbb_db_tools { list($orig_column_type, $column_length) = explode(':', $column_data[0]); - if (!is_array($this->dbms_type_map[$this->db->dbms_type][$orig_column_type . ':'])) + if (!is_array($this->db->dbms_type_map[$orig_column_type . ':'])) { - $column_type = sprintf($this->dbms_type_map[$this->db->dbms_type][$orig_column_type . ':'], $column_length); + $column_type = sprintf($this->db->dbms_type_map[$orig_column_type . ':'], $column_length); } $orig_column_type .= ':'; @@ -1645,7 +1410,7 @@ class phpbb_db_tools else { $orig_column_type = $column_data[0]; - $column_type = $this->dbms_type_map[$this->db->dbms_type][$column_data[0]]; + $column_type = $this->db->dbms_type_map[$column_data[0]]; } // Adjust default value if db-dependant specified @@ -1826,4 +1591,4 @@ class phpbb_db_tools } } -?> +?> \ No newline at end of file diff --git a/phpBB/includes/db/mysql.php b/phpBB/includes/db/mysql.php index ff45a403e9..97a7c2a4ea 100644 --- a/phpBB/includes/db/mysql.php +++ b/phpBB/includes/db/mysql.php @@ -16,8 +16,6 @@ if (!defined('IN_PHPBB')) exit; } -include_once(PHPBB_ROOT_PATH . 'includes/db/dbal.' . PHP_EXT); - /** * MySQL Database Abstraction Layer * Compatible with: @@ -25,78 +23,115 @@ include_once(PHPBB_ROOT_PATH . 'includes/db/dbal.' . PHP_EXT); * MySQL 5.0+ * @package dbal */ -class dbal_mysql extends dbal +class phpbb_dbal_mysql extends phpbb_dbal { - var $multi_insert = true; - - // Supports multiple table deletion - var $multi_table_deletion = true; - - var $dbms_type = 'mysql'; + /** + * @var string Database type. No distinction between versions or used extensions. + */ + public $dbms_type = 'mysql'; /** - * Connect to server - * @access public + * @var array Database type map, column layout information */ - function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) + public $dbms_type_map = array( + 'INT:' => 'int(%d)', + 'BINT' => 'bigint(20)', + 'UINT' => 'mediumint(8) UNSIGNED', + 'UINT:' => 'int(%d) UNSIGNED', + 'TINT:' => 'tinyint(%d)', + 'USINT' => 'smallint(4) UNSIGNED', + 'BOOL' => 'tinyint(1) UNSIGNED', + 'VCHAR' => 'varchar(255)', + 'VCHAR:' => 'varchar(%d)', + 'CHAR:' => 'char(%d)', + 'XSTEXT' => 'text', + 'XSTEXT_UNI'=> 'varchar(100)', + 'STEXT' => 'text', + 'STEXT_UNI' => 'varchar(255)', + 'TEXT' => 'text', + 'TEXT_UNI' => 'text', + 'MTEXT' => 'mediumtext', + 'MTEXT_UNI' => 'mediumtext', + 'TIMESTAMP' => 'int(11) UNSIGNED', + 'DECIMAL' => 'decimal(5,2)', + 'DECIMAL:' => 'decimal(%d,2)', + 'PDECIMAL' => 'decimal(6,3)', + 'PDECIMAL:' => 'decimal(%d,3)', + 'VCHAR_UNI' => 'varchar(255)', + 'VCHAR_UNI:'=> 'varchar(%d)', + 'VARBINARY' => 'varbinary(255)', + ); + + /** + * Connect to server. See {@link phpbb_dbal::sql_connect() sql_connect()} for details. + */ + public function sql_connect($server, $user, $password, $database, $port = false, $persistency = false , $new_link = false) { $this->persistency = $persistency; - $this->user = $sqluser; - $this->server = $sqlserver . (($port) ? ':' . $port : ''); + $this->user = $user; + $this->server = $server . (($port) ? ':' . $port : ''); $this->dbname = $database; - $this->db_connect_id = ($this->persistency) ? @mysql_pconnect($this->server, $this->user, $sqlpassword, $new_link) : @mysql_connect($this->server, $this->user, $sqlpassword, $new_link); + $this->db_connect_id = ($this->persistency) ? @mysql_pconnect($this->server, $this->user, $password, $new_link) : @mysql_connect($this->server, $this->user, $password, $new_link); - if ($this->db_connect_id && $this->dbname != '') + if (!$this->db_connect_id || !$this->dbname) { - if (@mysql_select_db($this->dbname, $this->db_connect_id)) - { - @mysql_query("SET NAMES 'utf8'", $this->db_connect_id); - - // enforce strict mode on databases that support it - if (version_compare($this->sql_server_info(true), '5.0.2', '>=')) - { - if (!in_array('STRICT_ALL_TABLES', $modes)) - { - $modes[] = 'STRICT_ALL_TABLES'; - } - - if (!in_array('STRICT_TRANS_TABLES', $modes)) - { - $modes[] = 'STRICT_TRANS_TABLES'; - } - - $mode = implode(',', $modes); - @mysql_query("SET SESSION sql_mode='{$mode}'", $this->db_connect_id); - } - - return $this->db_connect_id; - } + return $this->sql_error(''); } - return $this->sql_error(''); + if (!@mysql_select_db($this->dbname, $this->db_connect_id)) + { + return $this->sql_error(''); + } + + @mysql_query("SET NAMES 'utf8'", $this->db_connect_id); + + // enforce strict mode on databases that support it + if (version_compare($this->sql_server_info(true), '5.0.2', '>=')) + { + $result = @mysql_query('SELECT @@session.sql_mode AS sql_mode', $this->db_connect_id); + $row = @mysql_fetch_assoc($result); + @mysql_free_result($result); + + $modes = array_map('trim', explode(',', $row['sql_mode'])); + + // TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES + if (!in_array('TRADITIONAL', $modes)) + { + if (!in_array('STRICT_ALL_TABLES', $modes)) + { + $modes[] = 'STRICT_ALL_TABLES'; + } + + if (!in_array('STRICT_TRANS_TABLES', $modes)) + { + $modes[] = 'STRICT_TRANS_TABLES'; + } + } + + $mode = implode(',', $modes); + @mysql_query("SET SESSION sql_mode='{$mode}'", $this->db_connect_id); + } + + return $this->db_connect_id; } /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @return string sql server version + * Version information about used database. See {@link phpbb_dbal::sql_server_info() sql_server_info()} for details. */ - function sql_server_info($raw = false) + public function sql_server_info($raw = false) { - global $cache; - - if (empty($cache) || ($this->sql_server_version = $cache->get('mysql_version')) === false) + if (!phpbb::registered('acm') || ($this->sql_server_version = phpbb::$acm->get('#mysql_version')) === false) { $result = @mysql_query('SELECT VERSION() AS version', $this->db_connect_id); $row = @mysql_fetch_assoc($result); @mysql_free_result($result); - $this->sql_server_version = $row['version']; + $this->sql_server_version = trim($row['version']); - if (!empty($cache)) + if (phpbb::registered('acm')) { - $cache->put('mysql_version', $this->sql_server_version); + phpbb::$acm->put('#mysql_version', $this->sql_server_version); } } @@ -104,10 +139,41 @@ class dbal_mysql extends dbal } /** - * SQL Transaction - * @access private + * DB-specific base query method. See {@link phpbb_dbal::_sql_query() _sql_query()} for details. */ - function _sql_transaction($status = 'begin') + protected function _sql_query($query) + { + return @mysql_query($query, $this->db_connect_id); + } + + /** + * Build LIMIT query and run it. See {@link phpbb_dbal::_sql_query_limit() _sql_query_limit()} for details. + */ + protected function _sql_query_limit($query, $total, $offset, $cache_ttl) + { + // if $total is set to 0 we do not want to limit the number of rows + if ($total == 0) + { + // MySQL 4.1+ no longer supports -1 in limit queries + $total = '18446744073709551615'; + } + + $query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total); + return $this->sql_query($query, $cache_ttl); + } + + /** + * Close sql connection. See {@link phpbb_dbal::_sql_close() _sql_close()} for details. + */ + protected function _sql_close() + { + return @mysql_close($this->db_connect_id); + } + + /** + * SQL Transaction. See {@link phpbb_dbal::_sql_transaction() _sql_transaction()} for details. + */ + protected function _sql_transaction($status) { switch ($status) { @@ -128,149 +194,49 @@ class dbal_mysql extends dbal } /** - * Base query method - * - * @param string $query Contains the SQL query which shall be executed - * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache - * @return mixed When casted to bool the returned value returns true on success and false on failure - * - * @access public + * Return number of affected rows. See {@link phpbb_dbal::sql_affectedrows() sql_affectedrows()} for details. */ - function sql_query($query = '', $cache_ttl = 0) - { - if ($query != '') - { - global $cache; - - // EXPLAIN only in extra debug mode - if (defined('DEBUG_EXTRA')) - { - $this->sql_report('start', $query); - } - - $this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; - $this->sql_add_num_queries($this->query_result); - - if ($this->query_result === false) - { - if (($this->query_result = @mysql_query($query, $this->db_connect_id)) === false) - { - $this->sql_error($query); - } - - if (defined('DEBUG_EXTRA')) - { - $this->sql_report('stop', $query); - } - - if ($cache_ttl && method_exists($cache, 'sql_save')) - { - $this->open_queries[(int) $this->query_result] = $this->query_result; - $cache->sql_save($query, $this->query_result, $cache_ttl); - } - else if (strpos($query, 'SELECT') === 0 && $this->query_result) - { - $this->open_queries[(int) $this->query_result] = $this->query_result; - } - } - else if (defined('DEBUG_EXTRA')) - { - $this->sql_report('fromcache', $query); - } - } - else - { - return false; - } - - return $this->query_result; - } - - /** - * Build LIMIT query - */ - function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) - { - $this->query_result = false; - - // if $total is set to 0 we do not want to limit the number of rows - if ($total == 0) - { - // Having a value of -1 was always a bug - $total = '18446744073709551615'; - } - - $query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total); - - return $this->sql_query($query, $cache_ttl); - } - - /** - * Return number of affected rows - */ - function sql_affectedrows() + public function sql_affectedrows() { return ($this->db_connect_id) ? @mysql_affected_rows($this->db_connect_id) : false; } /** - * Fetch current row + * Get last inserted id after insert statement. See {@link phpbb_dbal::sql_nextid() sql_nextid()} for details. */ - function sql_fetchrow($query_id = false) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if (isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_fetchrow($query_id); - } - - return ($query_id !== false) ? @mysql_fetch_assoc($query_id) : false; - } - - /** - * Get last inserted id after insert statement - */ - function sql_nextid() + public function sql_nextid() { return ($this->db_connect_id) ? @mysql_insert_id($this->db_connect_id) : false; } /** - * Free sql result + * Fetch current row. See {@link phpbb_dbal::_sql_fetchrow() _sql_fetchrow()} for details. */ - function sql_freeresult($query_id = false) + protected function _sql_fetchrow($query_id) { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if (isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_freeresult($query_id); - } - - if (isset($this->open_queries[(int) $query_id])) - { - unset($this->open_queries[(int) $query_id]); - return @mysql_free_result($query_id); - } - - return false; + return @mysql_fetch_assoc($query_id); } /** - * Escape string used in sql query + * Free query result. See {@link phpbb_dbal::_sql_freeresult() _sql_freeresult()} for details. */ - function sql_escape($msg) + protected function _sql_freeresult($query_id) + { + return @mysql_free_result($query_id); + } + + /** + * Correctly adjust LIKE expression for special characters. See {@link phpbb_dbal::_sql_like_expression() _sql_like_expression()} for details. + */ + protected function _sql_like_expression($expression) + { + return $expression; + } + + /** + * Escape string used in sql query. See {@link phpbb_dbal::sql_escape() sql_escape()} for details. + */ + public function sql_escape($msg) { if (!$this->db_connect_id) { @@ -281,9 +247,9 @@ class dbal_mysql extends dbal } /** - * Expose a DBMS specific function + * Expose a DBMS specific function. See {@link phpbb_dbal::sql_function() sql_function()} for details. */ - function sql_function($type, $col) + public function sql_function($type, $col) { switch ($type) { @@ -294,35 +260,27 @@ class dbal_mysql extends dbal } } - function sql_handle_data($type, $table, $data, $where = '') + /** + * Handle data by using prepared statements. See {@link phpbb_dbal::sql_handle_data() sql_handle_data()} for details. + * @todo implement correctly by using types. ;) + */ + public function sql_handle_data($type, $table, $data, $where = '') { if ($type === 'UPDATE') { - $this->sql_query('INSERT INTO ' . $table . ' ' . - $this->sql_build_array('INSERT', $data)); + $where = ($where) ? ' WHERE ' . $where : ''; + $this->sql_query('UPDATE ' . $table . ' SET ' . $db->sql_build_array('UPDATE', $data) . $where); } else { - $this->sql_query('UPDATE ' . $table . ' - SET ' . $db->sql_build_array('UPDATE', $data) . - $where); + $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $data)); } } /** - * Build LIKE expression - * @access private + * Build DB-specific query bits. See {@link phpbb_dbal::_sql_custom_build() _sql_custom_build()} for details. */ - function _sql_like_expression($expression) - { - return $expression; - } - - /** - * Build db-specific query data - * @access private - */ - function _sql_custom_build($stage, $data) + protected function _sql_custom_build($stage, $data) { switch ($stage) { @@ -333,12 +291,11 @@ class dbal_mysql extends dbal return $data; } - + /** - * return sql error array - * @access private + * return sql error array. See {@link phpbb_dbal::_sql_error() _sql_error()} for details. */ - function _sql_error() + protected function _sql_error() { if (!$this->db_connect_id) { @@ -355,19 +312,9 @@ class dbal_mysql extends dbal } /** - * Close sql connection - * @access private + * Run DB-specific code to build SQL Report to explain queries, show statistics and runtime information. See {@link phpbb_dbal::_sql_report() _sql_report()} for details. */ - function _sql_close() - { - return @mysql_close($this->db_connect_id); - } - - /** - * Build db-specific report - * @access private - */ - function _sql_report($mode, $query = '') + protected function _sql_report($mode, $query = '') { static $test_prof; static $test_extend; @@ -381,7 +328,7 @@ class dbal_mysql extends dbal $test_prof = true; } - if (version_compare($ver, '4.1.1', '>=')) + if (version_compare($this->sql_server_info(true), '4.1.1', '>=')) { $test_extend = true; } @@ -445,7 +392,6 @@ class dbal_mysql extends dbal } } - if ($test_prof) { $html_table = false; diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/mysqli.php index fba7b2c22d..783ce43fef 100644 --- a/phpBB/includes/db/mysqli.php +++ b/phpBB/includes/db/mysqli.php @@ -30,6 +30,38 @@ class phpbb_dbal_mysqli extends phpbb_dbal */ public $dbms_type = 'mysql'; + /** + * @var array Database type map, column layout information + */ + public $dbms_type_map = array( + 'INT:' => 'int(%d)', + 'BINT' => 'bigint(20)', + 'UINT' => 'mediumint(8) UNSIGNED', + 'UINT:' => 'int(%d) UNSIGNED', + 'TINT:' => 'tinyint(%d)', + 'USINT' => 'smallint(4) UNSIGNED', + 'BOOL' => 'tinyint(1) UNSIGNED', + 'VCHAR' => 'varchar(255)', + 'VCHAR:' => 'varchar(%d)', + 'CHAR:' => 'char(%d)', + 'XSTEXT' => 'text', + 'XSTEXT_UNI'=> 'varchar(100)', + 'STEXT' => 'text', + 'STEXT_UNI' => 'varchar(255)', + 'TEXT' => 'text', + 'TEXT_UNI' => 'text', + 'MTEXT' => 'mediumtext', + 'MTEXT_UNI' => 'mediumtext', + 'TIMESTAMP' => 'int(11) UNSIGNED', + 'DECIMAL' => 'decimal(5,2)', + 'DECIMAL:' => 'decimal(%d,2)', + 'PDECIMAL' => 'decimal(6,3)', + 'PDECIMAL:' => 'decimal(%d,3)', + 'VCHAR_UNI' => 'varchar(255)', + 'VCHAR_UNI:'=> 'varchar(%d)', + 'VARBINARY' => 'varbinary(255)', + ); + /** * Connect to server. See {@link phpbb_dbal::sql_connect() sql_connect()} for details. */ @@ -44,40 +76,41 @@ class phpbb_dbal_mysqli extends phpbb_dbal // Persistant connections not supported by the mysqli extension? $this->db_connect_id = @mysqli_connect($this->server, $this->user, $password, $this->dbname, $this->port); - if ($this->db_connect_id && $this->dbname != '') + if (!$this->db_connect_id || !$this->dbname) { - @mysqli_query($this->db_connect_id, "SET NAMES 'utf8'"); - - // enforce strict mode on databases that support it - if (version_compare($this->sql_server_info(true), '5.0.2', '>=')) - { - $result = @mysqli_query($this->db_connect_id, 'SELECT @@session.sql_mode AS sql_mode'); - $row = @mysqli_fetch_assoc($result); - @mysqli_free_result($result); - - $modes = array_map('trim', explode(',', $row['sql_mode'])); - - // TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES - if (!in_array('TRADITIONAL', $modes)) - { - if (!in_array('STRICT_ALL_TABLES', $modes)) - { - $modes[] = 'STRICT_ALL_TABLES'; - } - - if (!in_array('STRICT_TRANS_TABLES', $modes)) - { - $modes[] = 'STRICT_TRANS_TABLES'; - } - } - - $mode = implode(',', $modes); - @mysqli_query($this->db_connect_id, "SET SESSION sql_mode='{$mode}'"); - } - return $this->db_connect_id; + return $this->sql_error(''); } - return $this->sql_error(''); + @mysqli_query($this->db_connect_id, "SET NAMES 'utf8'"); + + // enforce strict mode on databases that support it + if (version_compare($this->sql_server_info(true), '5.0.2', '>=')) + { + $result = @mysqli_query($this->db_connect_id, 'SELECT @@session.sql_mode AS sql_mode'); + $row = @mysqli_fetch_assoc($result); + @mysqli_free_result($result); + + $modes = array_map('trim', explode(',', $row['sql_mode'])); + + // TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES + if (!in_array('TRADITIONAL', $modes)) + { + if (!in_array('STRICT_ALL_TABLES', $modes)) + { + $modes[] = 'STRICT_ALL_TABLES'; + } + + if (!in_array('STRICT_TRANS_TABLES', $modes)) + { + $modes[] = 'STRICT_TRANS_TABLES'; + } + } + + $mode = implode(',', $modes); + @mysqli_query($this->db_connect_id, "SET SESSION sql_mode='{$mode}'"); + } + + return $this->db_connect_id; } /** @@ -302,18 +335,20 @@ class phpbb_dbal_mysqli extends phpbb_dbal protected function _sql_report($mode, $query = '') { static $test_prof; + static $test_extend; // current detection method, might just switch to see the existance of INFORMATION_SCHEMA.PROFILING if ($test_prof === null) { - $test_prof = false; - if (strpos(mysqli_get_server_info($this->db_connect_id), 'community') !== false) + $test_prof = $test_extend = false; + if (version_compare($this->sql_server_info(true), '5.0.37', '>=') && version_compare($this->sql_server_info(true), '5.1', '<')) { - $ver = mysqli_get_server_version($this->db_connect_id); - if ($ver >= 50037 && $ver < 50100) - { - $test_prof = true; - } + $test_prof = true; + } + + if (version_compare($this->sql_server_info(true), '4.1.1', '>=')) + { + $test_extend = true; } } @@ -341,7 +376,7 @@ class phpbb_dbal_mysqli extends phpbb_dbal @mysqli_query($this->db_connect_id, 'SET profiling = 1;'); } - if ($result = @mysqli_query($this->db_connect_id, "EXPLAIN $explain_query")) + if ($result = @mysqli_query($this->db_connect_id, 'EXPLAIN ' . (($test_extend) ? 'EXTENDED ' : '') . "$explain_query")) { while ($row = @mysqli_fetch_assoc($result)) { @@ -355,6 +390,26 @@ class phpbb_dbal_mysqli extends phpbb_dbal $this->html_hold .= ''; } + if ($test_extend) + { + $html_table = false; + + if ($result = @mysqli_query($this->db_connect_id, 'SHOW WARNINGS')) + { + $this->html_hold .= '
'; + while ($row = @mysqli_fetch_assoc($result)) + { + $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); + } + } + @mysqli_free_result($result); + + if ($html_table) + { + $this->html_hold .= ''; + } + } + if ($test_prof) { $html_table = false;