diff options
Diffstat (limited to 'phpBB/includes/db')
-rw-r--r-- | phpBB/includes/db/db_tools.php | 2477 | ||||
-rw-r--r-- | phpBB/includes/db/dbal.php | 1000 | ||||
-rw-r--r-- | phpBB/includes/db/firebird.php | 526 | ||||
-rw-r--r-- | phpBB/includes/db/mssql.php | 476 | ||||
-rw-r--r-- | phpBB/includes/db/mssql_odbc.php | 422 | ||||
-rw-r--r-- | phpBB/includes/db/mssqlnative.php | 652 | ||||
-rw-r--r-- | phpBB/includes/db/mysql.php | 591 | ||||
-rw-r--r-- | phpBB/includes/db/mysqli.php | 581 | ||||
-rw-r--r-- | phpBB/includes/db/oracle.php | 808 | ||||
-rw-r--r-- | phpBB/includes/db/postgres.php | 485 | ||||
-rw-r--r-- | phpBB/includes/db/schema_data.php | 1219 | ||||
-rw-r--r-- | phpBB/includes/db/sqlite.php | 370 |
12 files changed, 1219 insertions, 8388 deletions
diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php deleted file mode 100644 index f63ff18cbe..0000000000 --- a/phpBB/includes/db/db_tools.php +++ /dev/null @@ -1,2477 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2007 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* 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 -{ - /** - * Current sql layer - */ - var $sql_layer = ''; - - /** - * @var object DB object - */ - var $db = NULL; - - /** - * The Column types for every database we support - * @var array - */ - var $dbms_type_map = array( - 'mysql_41' => 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)', - 'VCHAR_CI' => 'varchar(255)', - 'VARBINARY' => 'varbinary(255)', - ), - - 'mysql_40' => 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' => 'varbinary(255)', - 'VCHAR:' => 'varbinary(%d)', - 'CHAR:' => 'binary(%d)', - 'XSTEXT' => 'blob', - 'XSTEXT_UNI'=> 'blob', - 'STEXT' => 'blob', - 'STEXT_UNI' => 'blob', - 'TEXT' => 'blob', - 'TEXT_UNI' => 'blob', - 'MTEXT' => 'mediumblob', - 'MTEXT_UNI' => 'mediumblob', - 'TIMESTAMP' => 'int(11) UNSIGNED', - 'DECIMAL' => 'decimal(5,2)', - 'DECIMAL:' => 'decimal(%d,2)', - 'PDECIMAL' => 'decimal(6,3)', - 'PDECIMAL:' => 'decimal(%d,3)', - 'VCHAR_UNI' => 'blob', - 'VCHAR_UNI:'=> array('varbinary(%d)', 'limit' => array('mult', 3, 255, 'blob')), - 'VCHAR_CI' => 'blob', - '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', - 'VCHAR_CI' => 'VARCHAR(255) 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)', - 'VCHAR_CI' => '[varchar] (255)', - 'VARBINARY' => '[varchar] (255)', - ), - - 'mssqlnative' => 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)', - 'VCHAR_CI' => '[varchar] (255)', - '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(765)', - 'VCHAR_UNI:'=> array('varchar2(%d)', 'limit' => array('mult', 3, 765, 'clob')), - 'VCHAR_CI' => 'varchar2(255)', - '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)', - 'VCHAR_CI' => 'varchar(255)', - 'VARBINARY' => 'blob', - ), - - '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)', - 'VCHAR_CI' => 'varchar_ci', - 'VARBINARY' => 'bytea', - ), - ); - - /** - * A list of types being unsigned for better reference in some db's - * @var array - */ - var $unsigned_types = array('UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP'); - - /** - * A list of supported DBMS. We change this class to support more DBMS, the DBMS itself only need to follow some rules. - * @var array - */ - var $supported_dbms = array('firebird', 'mssql', 'mssqlnative', 'mysql_40', 'mysql_41', 'oracle', 'postgres', 'sqlite'); - - /** - * 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. - */ - var $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 - */ - function phpbb_db_tools(&$db, $return_statements = false) - { - $this->db = $db; - $this->return_statements = $return_statements; - - // Determine mapping database type - switch ($this->db->sql_layer) - { - case 'mysql': - $this->sql_layer = 'mysql_40'; - break; - - case 'mysql4': - if (version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) - { - $this->sql_layer = 'mysql_41'; - } - else - { - $this->sql_layer = 'mysql_40'; - } - break; - - case 'mysqli': - $this->sql_layer = 'mysql_41'; - break; - - case 'mssql': - case 'mssql_odbc': - $this->sql_layer = 'mssql'; - break; - - case 'mssqlnative': - $this->sql_layer = 'mssqlnative'; - break; - - default: - $this->sql_layer = $this->db->sql_layer; - break; - } - } - - /** - * Gets a list of tables in the database. - * - * @return array Array of table names (all lower case) - */ - function sql_list_tables() - { - switch ($this->db->sql_layer) - { - case 'mysql': - case 'mysql4': - case 'mysqli': - $sql = 'SHOW TABLES'; - break; - - case 'sqlite': - $sql = 'SELECT name - FROM sqlite_master - WHERE type = "table"'; - break; - - case 'mssql': - case 'mssql_odbc': - case 'mssqlnative': - $sql = "SELECT name - FROM sysobjects - WHERE type='U'"; - break; - - case 'postgres': - $sql = 'SELECT relname - FROM pg_stat_user_tables'; - break; - - case 'firebird': - $sql = 'SELECT rdb$relation_name - FROM rdb$relations - WHERE rdb$view_source is null - AND rdb$system_flag = 0'; - break; - - case 'oracle': - $sql = 'SELECT table_name - FROM USER_TABLES'; - break; - } - - $result = $this->db->sql_query($sql); - - $tables = array(); - while ($row = $this->db->sql_fetchrow($result)) - { - $name = current($row); - $tables[$name] = $name; - } - $this->db->sql_freeresult($result); - - return $tables; - } - - /** - * Check if table exists - * - * - * @param string $table_name The table name to check for - * @return bool true if table exists, else false - */ - function sql_table_exists($table_name) - { - $this->db->sql_return_on_error(true); - $result = $this->db->sql_query_limit('SELECT * FROM ' . $table_name, 1); - $this->db->sql_return_on_error(false); - - if ($result) - { - $this->db->sql_freeresult($result); - return true; - } - - return false; - } - - /** - * Create SQL Table - * - * @param string $table_name The table name to create - * @param array $table_data Array containing table data. - * @return array Statements if $return_statements is true. - */ - function sql_create_table($table_name, $table_data) - { - // holds the DDL for a column - $columns = $statements = array(); - - if ($this->sql_table_exists($table_name)) - { - return $this->_sql_run_sql($statements); - } - - // Begin transaction - $statements[] = 'begin'; - - // Determine if we have created a PRIMARY KEY in the earliest - $primary_key_gen = false; - - // Determine if the table must be created with TEXTIMAGE - $create_textimage = false; - - // Determine if the table requires a sequence - $create_sequence = false; - - // Begin table sql statement - switch ($this->sql_layer) - { - case 'mssql': - case 'mssqlnative': - $table_sql = 'CREATE TABLE [' . $table_name . '] (' . "\n"; - break; - - default: - $table_sql = 'CREATE TABLE ' . $table_name . ' (' . "\n"; - break; - } - - // 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 - $prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data); - - if (isset($prepared_column['auto_increment']) && strlen($column_name) > 26) // "${column_name}_gen" - { - trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR); - } - - // here we add the definition of the new column to the list of columns - switch ($this->sql_layer) - { - case 'mssql': - case 'mssqlnative': - $columns[] = "\t [{$column_name}] " . $prepared_column['column_type_sql_default']; - break; - - default: - $columns[] = "\t {$column_name} " . $prepared_column['column_type_sql']; - break; - } - - // 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']; - } - - // create textimage DDL based off of the existance of certain column types - if (!$create_textimage) - { - $create_textimage = isset($prepared_column['textimage']) && $prepared_column['textimage']; - } - - // create sequence DDL based off of the existance of auto incrementing columns - if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment']) - { - $create_sequence = $column_name; - } - } - - // 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->sql_layer) - { - case 'firebird': - $table_sql .= "\n);"; - $statements[] = $table_sql; - break; - - case 'mssql': - case 'mssqlnative': - $table_sql .= "\n) ON [PRIMARY]" . (($create_textimage) ? ' TEXTIMAGE_ON [PRIMARY]' : ''); - $statements[] = $table_sql; - break; - } - - // we have yet to create a primary key for this table, - // this means that we can add the one we really wanted instead - if (!$primary_key_gen) - { - // Write primary key - if (isset($table_data['PRIMARY_KEY'])) - { - if (!is_array($table_data['PRIMARY_KEY'])) - { - $table_data['PRIMARY_KEY'] = array($table_data['PRIMARY_KEY']); - } - - switch ($this->sql_layer) - { - case 'mysql_40': - case 'mysql_41': - case 'postgres': - case 'sqlite': - $table_sql .= ",\n\t PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')'; - break; - - case 'firebird': - case 'mssql': - case 'mssqlnative': - // We need the data here - $old_return_statements = $this->return_statements; - $this->return_statements = true; - - $primary_key_stmts = $this->sql_create_primary_key($table_name, $table_data['PRIMARY_KEY']); - foreach ($primary_key_stmts as $pk_stmt) - { - $statements[] = $pk_stmt; - } - - $this->return_statements = $old_return_statements; - break; - - case 'oracle': - $table_sql .= ",\n\t CONSTRAINT pk_{$table_name} PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')'; - break; - } - } - } - - // close the table - switch ($this->sql_layer) - { - case 'mysql_41': - // make sure the table is in UTF-8 mode - $table_sql .= "\n) CHARACTER SET `utf8` COLLATE `utf8_bin`;"; - $statements[] = $table_sql; - break; - - case 'mysql_40': - case 'sqlite': - $table_sql .= "\n);"; - $statements[] = $table_sql; - break; - - case 'postgres': - // do we need to add a sequence for auto incrementing columns? - if ($create_sequence) - { - $statements[] = "CREATE SEQUENCE {$table_name}_seq;"; - } - - $table_sql .= "\n);"; - $statements[] = $table_sql; - break; - - case 'oracle': - $table_sql .= "\n)"; - $statements[] = $table_sql; - - // do we need to add a sequence and a tigger for auto incrementing columns? - if ($create_sequence) - { - // create the actual sequence - $statements[] = "CREATE SEQUENCE {$table_name}_seq"; - - // the trigger is the mechanism by which we increment the counter - $trigger = "CREATE OR REPLACE TRIGGER t_{$table_name}\n"; - $trigger .= "BEFORE INSERT ON {$table_name}\n"; - $trigger .= "FOR EACH ROW WHEN (\n"; - $trigger .= "\tnew.{$create_sequence} IS NULL OR new.{$create_sequence} = 0\n"; - $trigger .= ")\n"; - $trigger .= "BEGIN\n"; - $trigger .= "\tSELECT {$table_name}_seq.nextval\n"; - $trigger .= "\tINTO :new.{$create_sequence}\n"; - $trigger .= "\tFROM dual;\n"; - $trigger .= "END;"; - - $statements[] = $trigger; - } - break; - - case 'firebird': - if ($create_sequence) - { - $statements[] = "CREATE GENERATOR {$table_name}_gen;"; - $statements[] = "SET GENERATOR {$table_name}_gen TO 0;"; - - $trigger = "CREATE TRIGGER t_$table_name FOR $table_name\n"; - $trigger .= "BEFORE INSERT\nAS\nBEGIN\n"; - $trigger .= "\tNEW.{$create_sequence} = GEN_ID({$table_name}_gen, 1);\nEND;"; - $statements[] = $trigger; - } - break; - } - - // Write Keys - if (isset($table_data['KEYS'])) - { - foreach ($table_data['KEYS'] as $key_name => $key_data) - { - if (!is_array($key_data[1])) - { - $key_data[1] = array($key_data[1]); - } - - $old_return_statements = $this->return_statements; - $this->return_statements = true; - - $key_stmts = ($key_data[0] == 'UNIQUE') ? $this->sql_create_unique_index($table_name, $key_name, $key_data[1]) : $this->sql_create_index($table_name, $key_name, $key_data[1]); - - foreach ($key_stmts as $key_stmt) - { - $statements[] = $key_stmt; - } - - $this->return_statements = $old_return_statements; - } - } - - // 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 (can be column:index_size if you need to provide size) - * - * The values are in this format: - * {TABLE NAME} => array( - * {COLUMN NAME} => array({COLUMN TYPE}, {DEFAULT VALUE}, {OPTIONAL VARIABLES}), - * {KEY/INDEX NAME} => array({COLUMN NAMES}), - * ) - * - * For more information have a look at /develop/create_schema_files.php (only available through SVN) - */ - function perform_schema_changes($schema_changes) - { - if (empty($schema_changes)) - { - return; - } - - $statements = array(); - $sqlite = false; - - // For SQLite we need to perform the schema changes in a much more different way - if ($this->db->sql_layer == 'sqlite' && $this->return_statements) - { - $sqlite_data = array(); - $sqlite = true; - } - - // Drop tables? - if (!empty($schema_changes['drop_tables'])) - { - foreach ($schema_changes['drop_tables'] as $table) - { - // only drop table if it exists - if ($this->sql_table_exists($table)) - { - $result = $this->sql_table_drop($table); - if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - } - - // Add tables? - if (!empty($schema_changes['add_tables'])) - { - foreach ($schema_changes['add_tables'] as $table => $table_data) - { - $result = $this->sql_create_table($table, $table_data); - if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - - // Change columns? - if (!empty($schema_changes['change_columns'])) - { - foreach ($schema_changes['change_columns'] as $table => $columns) - { - foreach ($columns as $column_name => $column_data) - { - // If the column exists we change it, else we add it ;) - if ($column_exists = $this->sql_column_exists($table, $column_name)) - { - $result = $this->sql_column_change($table, $column_name, $column_data, true); - } - else - { - $result = $this->sql_column_add($table, $column_name, $column_data, true); - } - - if ($sqlite) - { - if ($column_exists) - { - $sqlite_data[$table]['change_columns'][] = $result; - } - else - { - $sqlite_data[$table]['add_columns'][] = $result; - } - } - else if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - } - - // Add columns? - if (!empty($schema_changes['add_columns'])) - { - foreach ($schema_changes['add_columns'] as $table => $columns) - { - foreach ($columns as $column_name => $column_data) - { - // Only add the column if it does not exist yet - if ($column_exists = $this->sql_column_exists($table, $column_name)) - { - continue; - // This is commented out here because it can take tremendous time on updates -// $result = $this->sql_column_change($table, $column_name, $column_data, true); - } - else - { - $result = $this->sql_column_add($table, $column_name, $column_data, true); - } - - if ($sqlite) - { - if ($column_exists) - { - continue; -// $sqlite_data[$table]['change_columns'][] = $result; - } - else - { - $sqlite_data[$table]['add_columns'][] = $result; - } - } - else if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - } - - // Remove keys? - if (!empty($schema_changes['drop_keys'])) - { - foreach ($schema_changes['drop_keys'] as $table => $indexes) - { - foreach ($indexes as $index_name) - { - if (!$this->sql_index_exists($table, $index_name)) - { - continue; - } - - $result = $this->sql_index_drop($table, $index_name); - - if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - } - - // Drop columns? - if (!empty($schema_changes['drop_columns'])) - { - foreach ($schema_changes['drop_columns'] as $table => $columns) - { - foreach ($columns as $column) - { - // Only remove the column if it exists... - if ($this->sql_column_exists($table, $column)) - { - $result = $this->sql_column_remove($table, $column, true); - - if ($sqlite) - { - $sqlite_data[$table]['drop_columns'][] = $result; - } - else if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - } - } - - // Add primary keys? - if (!empty($schema_changes['add_primary_keys'])) - { - foreach ($schema_changes['add_primary_keys'] as $table => $columns) - { - $result = $this->sql_create_primary_key($table, $columns, true); - - if ($sqlite) - { - $sqlite_data[$table]['primary_key'] = $result; - } - else if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - - // Add unqiue indexes? - if (!empty($schema_changes['add_unique_index'])) - { - foreach ($schema_changes['add_unique_index'] as $table => $index_array) - { - foreach ($index_array as $index_name => $column) - { - if ($this->sql_unique_index_exists($table, $index_name)) - { - continue; - } - - $result = $this->sql_create_unique_index($table, $index_name, $column); - - if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - } - - // Add indexes? - if (!empty($schema_changes['add_index'])) - { - foreach ($schema_changes['add_index'] as $table => $index_array) - { - foreach ($index_array as $index_name => $column) - { - if ($this->sql_index_exists($table, $index_name)) - { - continue; - } - - $result = $this->sql_create_index($table, $index_name, $column); - - if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - } - - if ($sqlite) - { - foreach ($sqlite_data as $table_name => $sql_schema_changes) - { - // Create temporary table with original data - $statements[] = 'begin'; - - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '{$table_name}' - ORDER BY type DESC, name;"; - $result = $this->db->sql_query($sql); - - if (!$result) - { - continue; - } - - $row = $this->db->sql_fetchrow($result); - $this->db->sql_freeresult($result); - - // Create a backup table and populate it, destroy the existing one - $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']); - $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name; - $statements[] = 'DROP TABLE ' . $table_name; - - // Get the columns... - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $plain_table_cols = trim($matches[1]); - $new_table_cols = preg_split('/,(?![\s\w]+\))/m', $plain_table_cols); - $column_list = array(); - - foreach ($new_table_cols as $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if ($entities[0] == 'PRIMARY') - { - continue; - } - $column_list[] = $entities[0]; - } - - // note down the primary key notation because sqlite only supports adding it to the end for the new table - $primary_key = false; - $_new_cols = array(); - - foreach ($new_table_cols as $key => $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if ($entities[0] == 'PRIMARY') - { - $primary_key = $declaration; - continue; - } - $_new_cols[] = $declaration; - } - - $new_table_cols = $_new_cols; - - // First of all... change columns - if (!empty($sql_schema_changes['change_columns'])) - { - foreach ($sql_schema_changes['change_columns'] as $column_sql) - { - foreach ($new_table_cols as $key => $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if (strpos($column_sql, $entities[0] . ' ') === 0) - { - $new_table_cols[$key] = $column_sql; - } - } - } - } - - if (!empty($sql_schema_changes['add_columns'])) - { - foreach ($sql_schema_changes['add_columns'] as $column_sql) - { - $new_table_cols[] = $column_sql; - } - } - - // Now drop them... - if (!empty($sql_schema_changes['drop_columns'])) - { - foreach ($sql_schema_changes['drop_columns'] as $column_name) - { - // Remove from column list... - $new_column_list = array(); - foreach ($column_list as $key => $value) - { - if ($value === $column_name) - { - continue; - } - - $new_column_list[] = $value; - } - - $column_list = $new_column_list; - - // Remove from table... - $_new_cols = array(); - foreach ($new_table_cols as $key => $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if (strpos($column_name . ' ', $entities[0] . ' ') === 0) - { - continue; - } - $_new_cols[] = $declaration; - } - $new_table_cols = $_new_cols; - } - } - - // Primary key... - if (!empty($sql_schema_changes['primary_key'])) - { - $new_table_cols[] = 'PRIMARY KEY (' . implode(', ', $sql_schema_changes['primary_key']) . ')'; - } - // Add a new one or the old primary key - else if ($primary_key !== false) - { - $new_table_cols[] = $primary_key; - } - - $columns = implode(',', $column_list); - - // create a new table and fill it up. destroy the temp one - $statements[] = 'CREATE TABLE ' . $table_name . ' (' . implode(',', $new_table_cols) . ');'; - $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'; - $statements[] = 'DROP TABLE ' . $table_name . '_temp'; - - $statements[] = 'commit'; - } - } - - if ($this->return_statements) - { - return $statements; - } - } - - /** - * Gets a list of columns of a table. - * - * @param string $table Table name - * - * @return array Array of column names (all lower case) - */ - function sql_list_columns($table) - { - $columns = array(); - - switch ($this->sql_layer) - { - case 'mysql_40': - case 'mysql_41': - $sql = "SHOW COLUMNS FROM $table"; - break; - - // PostgreSQL has a way of doing this in a much simpler way but would - // not allow us to support all versions of PostgreSQL - case 'postgres': - $sql = "SELECT a.attname - FROM pg_class c, pg_attribute a - WHERE c.relname = '{$table}' - AND a.attnum > 0 - AND a.attrelid = c.oid"; - break; - - // same deal with PostgreSQL, we must perform more complex operations than - // we technically could - case 'mssql': - case 'mssqlnative': - $sql = "SELECT c.name - FROM syscolumns c - LEFT JOIN sysobjects o ON c.id = o.id - WHERE o.name = '{$table}'"; - break; - - case 'oracle': - $sql = "SELECT column_name - FROM user_tab_columns - WHERE LOWER(table_name) = '" . strtolower($table) . "'"; - break; - - case 'firebird': - $sql = "SELECT RDB\$FIELD_NAME as FNAME - FROM RDB\$RELATION_FIELDS - WHERE RDB\$RELATION_NAME = '" . strtoupper($table) . "'"; - break; - - case 'sqlite': - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '{$table}'"; - - $result = $this->db->sql_query($sql); - - if (!$result) - { - return false; - } - - $row = $this->db->sql_fetchrow($result); - $this->db->sql_freeresult($result); - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $cols = trim($matches[1]); - $col_array = preg_split('/,(?![\s\w]+\))/m', $cols); - - foreach ($col_array as $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if ($entities[0] == 'PRIMARY') - { - continue; - } - - $column = strtolower($entities[0]); - $columns[$column] = $column; - } - - return $columns; - break; - } - - $result = $this->db->sql_query($sql); - - while ($row = $this->db->sql_fetchrow($result)) - { - $column = strtolower(current($row)); - $columns[$column] = $column; - } - $this->db->sql_freeresult($result); - - return $columns; - } - - /** - * Check whether a specified column exist in a table - * - * @param string $table Table to check - * @param string $column_name Column to check - * - * @return bool True if column exists, false otherwise - */ - function sql_column_exists($table, $column_name) - { - $columns = $this->sql_list_columns($table); - - return isset($columns[$column_name]); - } - - /** - * Check if a specified index exists in table. Does not return PRIMARY KEY and UNIQUE indexes. - * - * @param string $table_name Table to check the index at - * @param string $index_name The index name to check - * - * @return bool True if index exists, else false - */ - function sql_index_exists($table_name, $index_name) - { - if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative') - { - $sql = "EXEC sp_statistics '$table_name'"; - $result = $this->db->sql_query($sql); - - while ($row = $this->db->sql_fetchrow($result)) - { - if ($row['TYPE'] == 3) - { - if (strtolower($row['INDEX_NAME']) == strtolower($index_name)) - { - $this->db->sql_freeresult($result); - return true; - } - } - } - $this->db->sql_freeresult($result); - - return false; - } - - switch ($this->sql_layer) - { - case 'firebird': - $sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name - FROM RDB\$INDICES - WHERE RDB\$RELATION_NAME = '" . strtoupper($table_name) . "' - AND RDB\$UNIQUE_FLAG IS NULL - AND RDB\$FOREIGN_KEY IS NULL"; - $col = 'index_name'; - break; - - case 'postgres': - $sql = "SELECT ic.relname as index_name - FROM pg_class bc, pg_class ic, pg_index i - WHERE (bc.oid = i.indrelid) - AND (ic.oid = i.indexrelid) - AND (bc.relname = '" . $table_name . "') - AND (i.indisunique != 't') - AND (i.indisprimary != 't')"; - $col = 'index_name'; - break; - - case 'mysql_40': - case 'mysql_41': - $sql = 'SHOW KEYS - FROM ' . $table_name; - $col = 'Key_name'; - break; - - case 'oracle': - $sql = "SELECT index_name - FROM user_indexes - WHERE table_name = '" . strtoupper($table_name) . "' - AND generated = 'N' - AND uniqueness = 'NONUNIQUE'"; - $col = 'index_name'; - break; - - case 'sqlite': - $sql = "PRAGMA index_list('" . $table_name . "');"; - $col = 'name'; - break; - } - - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && !$row['Non_unique']) - { - continue; - } - - // These DBMS prefix index name with the table name - switch ($this->sql_layer) - { - case 'firebird': - case 'oracle': - case 'postgres': - case 'sqlite': - $row[$col] = substr($row[$col], strlen($table_name) + 1); - break; - } - - if (strtolower($row[$col]) == strtolower($index_name)) - { - $this->db->sql_freeresult($result); - return true; - } - } - $this->db->sql_freeresult($result); - - return false; - } - - /** - * Check if a specified index exists in table. Does not return PRIMARY KEY and UNIQUE indexes. - * - * @param string $table_name Table to check the index at - * @param string $index_name The index name to check - * - * @return bool True if index exists, else false - */ - function sql_unique_index_exists($table_name, $index_name) - { - if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative') - { - $sql = "EXEC sp_statistics '$table_name'"; - $result = $this->db->sql_query($sql); - - while ($row = $this->db->sql_fetchrow($result)) - { - // Usually NON_UNIQUE is the column we want to check, but we allow for both - if ($row['TYPE'] == 3) - { - if (strtolower($row['INDEX_NAME']) == strtolower($index_name)) - { - $this->db->sql_freeresult($result); - return true; - } - } - } - $this->db->sql_freeresult($result); - return false; - } - - switch ($this->sql_layer) - { - case 'firebird': - $sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name - FROM RDB\$INDICES - WHERE RDB\$RELATION_NAME = '" . strtoupper($table_name) . "' - AND RDB\$UNIQUE_FLAG IS NOT NULL - AND RDB\$FOREIGN_KEY IS NULL"; - $col = 'index_name'; - break; - - case 'postgres': - $sql = "SELECT ic.relname as index_name, i.indisunique - FROM pg_class bc, pg_class ic, pg_index i - WHERE (bc.oid = i.indrelid) - AND (ic.oid = i.indexrelid) - AND (bc.relname = '" . $table_name . "') - AND (i.indisprimary != 't')"; - $col = 'index_name'; - break; - - case 'mysql_40': - case 'mysql_41': - $sql = 'SHOW KEYS - FROM ' . $table_name; - $col = 'Key_name'; - break; - - case 'oracle': - $sql = "SELECT index_name, table_owner - FROM user_indexes - WHERE table_name = '" . strtoupper($table_name) . "' - AND generated = 'N' - AND uniqueness = 'UNIQUE'"; - $col = 'index_name'; - break; - - case 'sqlite': - $sql = "PRAGMA index_list('" . $table_name . "');"; - $col = 'name'; - break; - } - - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && ($row['Non_unique'] || $row[$col] == 'PRIMARY')) - { - continue; - } - - if ($this->sql_layer == 'sqlite' && !$row['unique']) - { - continue; - } - - if ($this->sql_layer == 'postgres' && $row['indisunique'] != 't') - { - continue; - } - - // These DBMS prefix index name with the table name - switch ($this->sql_layer) - { - case 'oracle': - // Two cases here... prefixed with U_[table_owner] and not prefixed with table_name - if (strpos($row[$col], 'U_') === 0) - { - $row[$col] = substr($row[$col], strlen('U_' . $row['table_owner']) + 1); - } - else if (strpos($row[$col], strtoupper($table_name)) === 0) - { - $row[$col] = substr($row[$col], strlen($table_name) + 1); - } - break; - - case 'firebird': - case 'postgres': - case 'sqlite': - $row[$col] = substr($row[$col], strlen($table_name) + 1); - break; - } - - if (strtolower($row[$col]) == strtolower($index_name)) - { - $this->db->sql_freeresult($result); - return true; - } - } - $this->db->sql_freeresult($result); - - return false; - } - - /** - * Private method for performing sql statements (either execute them or return them) - * @access private - */ - function _sql_run_sql($statements) - { - if ($this->return_statements) - { - return $statements; - } - - // We could add error handling here... - foreach ($statements as $sql) - { - if ($sql === 'begin') - { - $this->db->sql_transaction('begin'); - } - else if ($sql === 'commit') - { - $this->db->sql_transaction('commit'); - } - else - { - $this->db->sql_query($sql); - } - } - - return true; - } - - /** - * Function to prepare some column information for better usage - * @access private - */ - function sql_prepare_column_data($table_name, $column_name, $column_data) - { - if (strlen($column_name) > 30) - { - trigger_error("Column name '$column_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR); - } - - // Get type - if (strpos($column_data[0], ':') !== false) - { - list($orig_column_type, $column_length) = explode(':', $column_data[0]); - if (!is_array($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'])) - { - $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'], $column_length); - } - else - { - if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'])) - { - switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][0]) - { - case 'div': - $column_length /= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][1]; - $column_length = ceil($column_length); - $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length); - break; - } - } - - if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'])) - { - switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][0]) - { - case 'mult': - $column_length *= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][1]; - if ($column_length > $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][2]) - { - $column_type = $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][3]; - } - else - { - $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length); - } - break; - } - } - } - $orig_column_type .= ':'; - } - else - { - $orig_column_type = $column_data[0]; - $column_type = $this->dbms_type_map[$this->sql_layer][$column_data[0]]; - } - - // Adjust default value if db-dependant specified - if (is_array($column_data[1])) - { - $column_data[1] = (isset($column_data[1][$this->sql_layer])) ? $column_data[1][$this->sql_layer] : $column_data[1]['default']; - } - - $sql = ''; - - $return_array = array(); - - switch ($this->sql_layer) - { - case 'firebird': - $sql .= " {$column_type} "; - $return_array['column_type_sql_type'] = " {$column_type} "; - - if (!is_null($column_data[1])) - { - $sql .= 'DEFAULT ' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' '; - $return_array['column_type_sql_default'] = ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' '; - } - - $sql .= 'NOT NULL'; - - // This is a UNICODE column and thus should be given it's fair share - if (preg_match('/^X?STEXT_UNI|VCHAR_(CI|UNI:?)/', $column_data[0])) - { - $sql .= ' COLLATE UNICODE'; - } - - $return_array['auto_increment'] = false; - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') - { - $return_array['auto_increment'] = true; - } - - break; - - case 'mssql': - case 'mssqlnative': - $sql .= " {$column_type} "; - $sql_default = " {$column_type} "; - - // For adding columns we need the default definition - if (!is_null($column_data[1])) - { - // For hexadecimal values do not use single quotes - if (strpos($column_data[1], '0x') === 0) - { - $return_array['default'] = 'DEFAULT (' . $column_data[1] . ') '; - $sql_default .= $return_array['default']; - } - else - { - $return_array['default'] = 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') '; - $sql_default .= $return_array['default']; - } - } - - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') - { -// $sql .= 'IDENTITY (1, 1) '; - $sql_default .= 'IDENTITY (1, 1) '; - } - - $return_array['textimage'] = $column_type === '[text]'; - - $sql .= 'NOT NULL'; - $sql_default .= 'NOT NULL'; - - $return_array['column_type_sql_default'] = $sql_default; - - break; - - case 'mysql_40': - case 'mysql_41': - $sql .= " {$column_type} "; - - // For hexadecimal values do not use single quotes - if (!is_null($column_data[1]) && substr($column_type, -4) !== 'text' && substr($column_type, -4) !== 'blob') - { - $sql .= (strpos($column_data[1], '0x') === 0) ? "DEFAULT {$column_data[1]} " : "DEFAULT '{$column_data[1]}' "; - } - $sql .= 'NOT NULL'; - - if (isset($column_data[2])) - { - if ($column_data[2] == 'auto_increment') - { - $sql .= ' auto_increment'; - } - else if ($this->sql_layer === 'mysql_41' && $column_data[2] == 'true_sort') - { - $sql .= ' COLLATE utf8_unicode_ci'; - } - } - - break; - - case 'oracle': - $sql .= " {$column_type} "; - $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}' " : ''; - - // In Oracle empty strings ('') are treated as NULL. - // Therefore in oracle we allow NULL's for all DEFAULT '' entries - // Oracle does not like setting NOT NULL on a column that is already NOT NULL (this happens only on number fields) - if (!preg_match('/number/i', $column_type)) - { - $sql .= ($column_data[1] === '') ? '' : 'NOT NULL'; - } - - $return_array['auto_increment'] = false; - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') - { - $return_array['auto_increment'] = true; - } - - break; - - case 'postgres': - $return_array['column_type'] = $column_type; - - $sql .= " {$column_type} "; - - $return_array['auto_increment'] = false; - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') - { - $default_val = "nextval('{$table_name}_seq')"; - $return_array['auto_increment'] = true; - } - else if (!is_null($column_data[1])) - { - $default_val = "'" . $column_data[1] . "'"; - $return_array['null'] = 'NOT NULL'; - $sql .= 'NOT NULL '; - } - - $return_array['default'] = $default_val; - - $sql .= "DEFAULT {$default_val}"; - - // Unsigned? Then add a CHECK contraint - if (in_array($orig_column_type, $this->unsigned_types)) - { - $return_array['constraint'] = "CHECK ({$column_name} >= 0)"; - $sql .= " CHECK ({$column_name} >= 0)"; - } - - break; - - case 'sqlite': - $return_array['primary_key_set'] = false; - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') - { - $sql .= ' INTEGER PRIMARY KEY'; - $return_array['primary_key_set'] = true; - } - else - { - $sql .= ' ' . $column_type; - } - - $sql .= ' NOT NULL '; - $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}'" : ''; - - break; - } - - $return_array['column_type_sql'] = $sql; - - return $return_array; - } - - /** - * Add new column - */ - function sql_column_add($table_name, $column_name, $column_data, $inline = false) - { - $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data); - $statements = array(); - - switch ($this->sql_layer) - { - case 'firebird': - // Does not support AFTER statement, only POSITION (and there you need the column position) - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD "' . strtoupper($column_name) . '" ' . $column_data['column_type_sql']; - break; - - case 'mssql': - case 'mssqlnative': - // Does not support AFTER, only through temporary table - $statements[] = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql_default']; - break; - - case 'mysql_40': - case 'mysql_41': - $after = (!empty($column_data['after'])) ? ' AFTER ' . $column_data['after'] : ''; - $statements[] = 'ALTER TABLE `' . $table_name . '` ADD COLUMN `' . $column_name . '` ' . $column_data['column_type_sql'] . $after; - break; - - case 'oracle': - // Does not support AFTER, only through temporary table - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql']; - break; - - case 'postgres': - // Does not support AFTER, only through temporary table - if (version_compare($this->db->sql_server_info(true), '8.0', '>=')) - { - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql']; - } - else - { - // old versions cannot add columns with default and null information - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type'] . ' ' . $column_data['constraint']; - - if (isset($column_data['null'])) - { - if ($column_data['null'] == 'NOT NULL') - { - $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET NOT NULL'; - } - } - - if (isset($column_data['default'])) - { - $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default']; - } - } - - break; - - case 'sqlite': - - if ($inline && $this->return_statements) - { - return $column_name . ' ' . $column_data['column_type_sql']; - } - - if (version_compare(sqlite_libversion(), '3.0') == -1) - { - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '{$table_name}' - ORDER BY type DESC, name;"; - $result = $this->db->sql_query($sql); - - if (!$result) - { - break; - } - - $row = $this->db->sql_fetchrow($result); - $this->db->sql_freeresult($result); - - $statements[] = 'begin'; - - // Create a backup table and populate it, destroy the existing one - $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']); - $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name; - $statements[] = 'DROP TABLE ' . $table_name; - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $new_table_cols = trim($matches[1]); - $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols); - $column_list = array(); - - foreach ($old_table_cols as $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if ($entities[0] == 'PRIMARY') - { - continue; - } - $column_list[] = $entities[0]; - } - - $columns = implode(',', $column_list); - - $new_table_cols = $column_name . ' ' . $column_data['column_type_sql'] . ',' . $new_table_cols; - - // create a new table and fill it up. destroy the temp one - $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');'; - $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'; - $statements[] = 'DROP TABLE ' . $table_name . '_temp'; - - $statements[] = 'commit'; - } - else - { - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' [' . $column_data['column_type_sql'] . ']'; - } - break; - } - - return $this->_sql_run_sql($statements); - } - - /** - * Drop column - */ - function sql_column_remove($table_name, $column_name, $inline = false) - { - $statements = array(); - - switch ($this->sql_layer) - { - case 'firebird': - $statements[] = 'ALTER TABLE ' . $table_name . ' DROP "' . strtoupper($column_name) . '"'; - break; - - case 'mssql': - case 'mssqlnative': - // remove default cosntraints first - // http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx - $statements[] = "DECLARE @drop_default_name VARCHAR(100), @cmd VARCHAR(1000) - SET @drop_default_name = - (SELECT so.name FROM sysobjects so - JOIN sysconstraints sc ON so.id = sc.constid - WHERE object_name(so.parent_obj) = '{$table_name}' - AND so.xtype = 'D' - AND sc.colid = (SELECT colid FROM syscolumns - WHERE id = object_id('{$table_name}') - AND name = '{$column_name}')) - IF @drop_default_name <> '' - BEGIN - SET @cmd = 'ALTER TABLE [{$table_name}] DROP CONSTRAINT [' + @drop_default_name + ']' - EXEC(@cmd) - END"; - $statements[] = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']'; - break; - - case 'mysql_40': - case 'mysql_41': - $statements[] = 'ALTER TABLE `' . $table_name . '` DROP COLUMN `' . $column_name . '`'; - break; - - case 'oracle': - $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name; - break; - - case 'postgres': - $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"'; - break; - - case 'sqlite': - - if ($inline && $this->return_statements) - { - return $column_name; - } - - if (version_compare(sqlite_libversion(), '3.0') == -1) - { - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '{$table_name}' - ORDER BY type DESC, name;"; - $result = $this->db->sql_query($sql); - - if (!$result) - { - break; - } - - $row = $this->db->sql_fetchrow($result); - $this->db->sql_freeresult($result); - - $statements[] = 'begin'; - - // Create a backup table and populate it, destroy the existing one - $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']); - $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name; - $statements[] = 'DROP TABLE ' . $table_name; - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $new_table_cols = trim($matches[1]); - $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols); - $column_list = array(); - - foreach ($old_table_cols as $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if ($entities[0] == 'PRIMARY' || $entities[0] === $column_name) - { - continue; - } - $column_list[] = $entities[0]; - } - - $columns = implode(',', $column_list); - - $new_table_cols = preg_replace('/' . $column_name . '[^,]+(?:,|$)/m', '', $new_table_cols); - - // create a new table and fill it up. destroy the temp one - $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');'; - $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'; - $statements[] = 'DROP TABLE ' . $table_name . '_temp'; - - $statements[] = 'commit'; - } - else - { - $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name; - } - break; - } - - return $this->_sql_run_sql($statements); - } - - /** - * Drop Index - */ - function sql_index_drop($table_name, $index_name) - { - $statements = array(); - - switch ($this->sql_layer) - { - case 'mssql': - case 'mssqlnative': - $statements[] = 'DROP INDEX ' . $table_name . '.' . $index_name; - break; - - case 'mysql_40': - case 'mysql_41': - $statements[] = 'DROP INDEX ' . $index_name . ' ON ' . $table_name; - break; - - case 'firebird': - case 'oracle': - case 'postgres': - case 'sqlite': - $statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name; - break; - } - - return $this->_sql_run_sql($statements); - } - - /** - * Drop Table - */ - function sql_table_drop($table_name) - { - $statements = array(); - - if (!$this->sql_table_exists($table_name)) - { - return $this->_sql_run_sql($statements); - } - - // the most basic operation, get rid of the table - $statements[] = 'DROP TABLE ' . $table_name; - - switch ($this->sql_layer) - { - case 'firebird': - $sql = 'SELECT RDB$GENERATOR_NAME as gen - FROM RDB$GENERATORS - WHERE RDB$SYSTEM_FLAG = 0 - AND RDB$GENERATOR_NAME = \'' . strtoupper($table_name) . "_GEN'"; - $result = $this->db->sql_query($sql); - - // does a generator exist? - if ($row = $this->db->sql_fetchrow($result)) - { - $statements[] = "DROP GENERATOR {$row['gen']};"; - } - $this->db->sql_freeresult($result); - break; - - case 'oracle': - $sql = 'SELECT A.REFERENCED_NAME - FROM USER_DEPENDENCIES A, USER_TRIGGERS B - WHERE A.REFERENCED_TYPE = \'SEQUENCE\' - AND A.NAME = B.TRIGGER_NAME - AND B.TABLE_NAME = \'' . strtoupper($table_name) . "'"; - $result = $this->db->sql_query($sql); - - // any sequences ref'd to this table's triggers? - while ($row = $this->db->sql_fetchrow($result)) - { - $statements[] = "DROP SEQUENCE {$row['referenced_name']}"; - } - $this->db->sql_freeresult($result); - break; - - case 'postgres': - // PGSQL does not "tightly" bind sequences and tables, we must guess... - $sql = "SELECT relname - FROM pg_class - WHERE relkind = 'S' - AND relname = '{$table_name}_seq'"; - $result = $this->db->sql_query($sql); - - // We don't even care about storing the results. We already know the answer if we get rows back. - if ($this->db->sql_fetchrow($result)) - { - $statements[] = "DROP SEQUENCE {$table_name}_seq;\n"; - } - $this->db->sql_freeresult($result); - break; - } - - return $this->_sql_run_sql($statements); - } - - /** - * Add primary key - */ - function sql_create_primary_key($table_name, $column, $inline = false) - { - $statements = array(); - - switch ($this->sql_layer) - { - case 'firebird': - case 'postgres': - case 'mysql_40': - case 'mysql_41': - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')'; - break; - - case 'mssql': - case 'mssqlnative': - $sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD "; - $sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED ("; - $sql .= '[' . implode("],\n\t\t[", $column) . ']'; - $sql .= ') ON [PRIMARY]'; - - $statements[] = $sql; - break; - - case 'oracle': - $statements[] = 'ALTER TABLE ' . $table_name . 'add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')'; - break; - - case 'sqlite': - - if ($inline && $this->return_statements) - { - return $column; - } - - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '{$table_name}' - ORDER BY type DESC, name;"; - $result = $this->db->sql_query($sql); - - if (!$result) - { - break; - } - - $row = $this->db->sql_fetchrow($result); - $this->db->sql_freeresult($result); - - $statements[] = 'begin'; - - // Create a backup table and populate it, destroy the existing one - $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']); - $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name; - $statements[] = 'DROP TABLE ' . $table_name; - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $new_table_cols = trim($matches[1]); - $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols); - $column_list = array(); - - foreach ($old_table_cols as $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if ($entities[0] == 'PRIMARY') - { - continue; - } - $column_list[] = $entities[0]; - } - - $columns = implode(',', $column_list); - - // create a new table and fill it up. destroy the temp one - $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ', PRIMARY KEY (' . implode(', ', $column) . '));'; - $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'; - $statements[] = 'DROP TABLE ' . $table_name . '_temp'; - - $statements[] = 'commit'; - break; - } - - return $this->_sql_run_sql($statements); - } - - /** - * Add unique index - */ - function sql_create_unique_index($table_name, $index_name, $column) - { - $statements = array(); - - $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config) - if (strlen($table_name . $index_name) - strlen($table_prefix) > 24) - { - $max_length = strlen($table_prefix) + 24; - trigger_error("Index name '{$table_name}_$index_name' on table '$table_name' is too long. The maximum is $max_length characters.", E_USER_ERROR); - } - - switch ($this->sql_layer) - { - case 'firebird': - case 'postgres': - case 'oracle': - case 'sqlite': - $statements[] = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; - break; - - case 'mysql_40': - case 'mysql_41': - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD UNIQUE INDEX ' . $index_name . '(' . implode(', ', $column) . ')'; - break; - - case 'mssql': - case 'mssqlnative': - $statements[] = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]'; - break; - } - - return $this->_sql_run_sql($statements); - } - - /** - * Add index - */ - function sql_create_index($table_name, $index_name, $column) - { - $statements = array(); - - $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config) - if (strlen($table_name . $index_name) - strlen($table_prefix) > 24) - { - $max_length = strlen($table_prefix) + 24; - trigger_error("Index name '{$table_name}_$index_name' on table '$table_name' is too long. The maximum is $max_length characters.", E_USER_ERROR); - } - - // remove index length unless MySQL4 - if ('mysql_40' != $this->sql_layer) - { - $column = preg_replace('#:.*$#', '', $column); - } - - switch ($this->sql_layer) - { - case 'firebird': - case 'postgres': - case 'oracle': - case 'sqlite': - $statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; - break; - - case 'mysql_40': - // add index size to definition as required by MySQL4 - foreach ($column as $i => $col) - { - if (false !== strpos($col, ':')) - { - list($col, $index_size) = explode(':', $col); - $column[$i] = "$col($index_size)"; - } - } - // no break - case 'mysql_41': - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD INDEX ' . $index_name . '(' . implode(', ', $column) . ')'; - break; - - case 'mssql': - case 'mssqlnative': - $statements[] = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]'; - break; - } - - return $this->_sql_run_sql($statements); - } - - /** - * List all of the indices that belong to a table, - * does not count: - * * UNIQUE indices - * * PRIMARY keys - */ - function sql_list_index($table_name) - { - $index_array = array(); - - if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative') - { - $sql = "EXEC sp_statistics '$table_name'"; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - if ($row['TYPE'] == 3) - { - $index_array[] = $row['INDEX_NAME']; - } - } - $this->db->sql_freeresult($result); - } - else - { - switch ($this->sql_layer) - { - case 'firebird': - $sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name - FROM RDB\$INDICES - WHERE RDB\$RELATION_NAME = '" . strtoupper($table_name) . "' - AND RDB\$UNIQUE_FLAG IS NULL - AND RDB\$FOREIGN_KEY IS NULL"; - $col = 'index_name'; - break; - - case 'postgres': - $sql = "SELECT ic.relname as index_name - FROM pg_class bc, pg_class ic, pg_index i - WHERE (bc.oid = i.indrelid) - AND (ic.oid = i.indexrelid) - AND (bc.relname = '" . $table_name . "') - AND (i.indisunique != 't') - AND (i.indisprimary != 't')"; - $col = 'index_name'; - break; - - case 'mysql_40': - case 'mysql_41': - $sql = 'SHOW KEYS - FROM ' . $table_name; - $col = 'Key_name'; - break; - - case 'oracle': - $sql = "SELECT index_name - FROM user_indexes - WHERE table_name = '" . strtoupper($table_name) . "' - AND generated = 'N' - AND uniqueness = 'NONUNIQUE'"; - $col = 'index_name'; - break; - - case 'sqlite': - $sql = "PRAGMA index_info('" . $table_name . "');"; - $col = 'name'; - break; - } - - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && !$row['Non_unique']) - { - continue; - } - - switch ($this->sql_layer) - { - case 'firebird': - case 'oracle': - case 'postgres': - case 'sqlite': - $row[$col] = substr($row[$col], strlen($table_name) + 1); - break; - } - - $index_array[] = $row[$col]; - } - $this->db->sql_freeresult($result); - } - - return array_map('strtolower', $index_array); - } - - /** - * Change column type (not name!) - */ - function sql_column_change($table_name, $column_name, $column_data, $inline = false) - { - $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data); - $statements = array(); - - switch ($this->sql_layer) - { - case 'firebird': - // Change type... - if (!empty($column_data['column_type_sql_default'])) - { - $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql_type']; - $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" SET DEFAULT ' . ' ' . $column_data['column_type_sql_default']; - } - else - { - // TODO: try to change pkey without removing trigger, generator or constraints. ATM this query may fail. - $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql_type']; - } - break; - - case 'mssql': - case 'mssqlnative': - $statements[] = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql']; - - if (!empty($column_data['default'])) - { - // Using TRANSACT-SQL for this statement because we do not want to have colliding data if statements are executed at a later stage - $statements[] = "DECLARE @drop_default_name VARCHAR(100), @cmd VARCHAR(1000) - SET @drop_default_name = - (SELECT so.name FROM sysobjects so - JOIN sysconstraints sc ON so.id = sc.constid - WHERE object_name(so.parent_obj) = '{$table_name}' - AND so.xtype = 'D' - AND sc.colid = (SELECT colid FROM syscolumns - WHERE id = object_id('{$table_name}') - AND name = '{$column_name}')) - IF @drop_default_name <> '' - BEGIN - SET @cmd = 'ALTER TABLE [{$table_name}] DROP CONSTRAINT [' + @drop_default_name + ']' - EXEC(@cmd) - END - SET @cmd = 'ALTER TABLE [{$table_name}] ADD CONSTRAINT [DF_{$table_name}_{$column_name}_1] {$column_data['default']} FOR [{$column_name}]' - EXEC(@cmd)"; - } - break; - - case 'mysql_40': - case 'mysql_41': - $statements[] = 'ALTER TABLE `' . $table_name . '` CHANGE `' . $column_name . '` `' . $column_name . '` ' . $column_data['column_type_sql']; - break; - - case 'oracle': - $statements[] = 'ALTER TABLE ' . $table_name . ' MODIFY ' . $column_name . ' ' . $column_data['column_type_sql']; - break; - - case 'postgres': - $sql = 'ALTER TABLE ' . $table_name . ' '; - - $sql_array = array(); - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' TYPE ' . $column_data['column_type']; - - if (isset($column_data['null'])) - { - if ($column_data['null'] == 'NOT NULL') - { - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET NOT NULL'; - } - else if ($column_data['null'] == 'NULL') - { - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' DROP NOT NULL'; - } - } - - if (isset($column_data['default'])) - { - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default']; - } - - // we don't want to double up on constraints if we change different number data types - if (isset($column_data['constraint'])) - { - $constraint_sql = "SELECT consrc as constraint_data - FROM pg_constraint, pg_class bc - WHERE conrelid = bc.oid - AND bc.relname = '{$table_name}' - AND NOT EXISTS ( - SELECT * - FROM pg_constraint as c, pg_inherits as i - WHERE i.inhrelid = pg_constraint.conrelid - AND c.conname = pg_constraint.conname - AND c.consrc = pg_constraint.consrc - AND c.conrelid = i.inhparent - )"; - - $constraint_exists = false; - - $result = $this->db->sql_query($constraint_sql); - while ($row = $this->db->sql_fetchrow($result)) - { - if (trim($row['constraint_data']) == trim($column_data['constraint'])) - { - $constraint_exists = true; - break; - } - } - $this->db->sql_freeresult($result); - - if (!$constraint_exists) - { - $sql_array[] = 'ADD ' . $column_data['constraint']; - } - } - - $sql .= implode(', ', $sql_array); - - $statements[] = $sql; - break; - - case 'sqlite': - - if ($inline && $this->return_statements) - { - return $column_name . ' ' . $column_data['column_type_sql']; - } - - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '{$table_name}' - ORDER BY type DESC, name;"; - $result = $this->db->sql_query($sql); - - if (!$result) - { - break; - } - - $row = $this->db->sql_fetchrow($result); - $this->db->sql_freeresult($result); - - $statements[] = 'begin'; - - // Create a temp table and populate it, destroy the existing one - $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']); - $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name; - $statements[] = 'DROP TABLE ' . $table_name; - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $new_table_cols = trim($matches[1]); - $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols); - $column_list = array(); - - foreach ($old_table_cols as $key => $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - $column_list[] = $entities[0]; - if ($entities[0] == $column_name) - { - $old_table_cols[$key] = $column_name . ' ' . $column_data['column_type_sql']; - } - } - - $columns = implode(',', $column_list); - - // create a new table and fill it up. destroy the temp one - $statements[] = 'CREATE TABLE ' . $table_name . ' (' . implode(',', $old_table_cols) . ');'; - $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'; - $statements[] = 'DROP TABLE ' . $table_name . '_temp'; - - $statements[] = 'commit'; - - break; - } - - return $this->_sql_run_sql($statements); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php deleted file mode 100644 index 30d2870938..0000000000 --- a/phpBB/includes/db/dbal.php +++ /dev/null @@ -1,1000 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Database Abstraction Layer -* @package dbal -*/ -class dbal -{ - var $db_connect_id; - var $query_result; - var $return_on_error = false; - var $transaction = false; - var $sql_time = 0; - var $num_queries = array(); - var $open_queries = array(); - - var $curtime = 0; - var $query_hold = ''; - var $html_hold = ''; - var $sql_report = ''; - - var $persistency = false; - var $user = ''; - var $server = ''; - var $dbname = ''; - - // Set to true if error triggered - var $sql_error_triggered = false; - - // Holding the last sql query on sql error - var $sql_error_sql = ''; - // Holding the error information - only populated if sql_error_triggered is set - var $sql_error_returned = array(); - - // Holding transaction count - var $transactions = 0; - - // Supports multi inserts? - var $multi_insert = false; - - /** - * Current sql layer - */ - var $sql_layer = ''; - - /** - * Wildcards for matching any (%) or exactly one (_) character within LIKE expressions - */ - var $any_char; - var $one_char; - - /** - * Exact version of the DBAL, directly queried - */ - var $sql_server_version = false; - - /** - * Constructor - */ - function dbal() - { - $this->num_queries = array( - 'cached' => 0, - 'normal' => 0, - 'total' => 0, - ); - - // Fill default sql layer based on the class being called. - // This can be changed by the specified layer itself later if needed. - $this->sql_layer = substr(get_class($this), 5); - - // Do not change this please! This variable is used to easy the use of it - and is hardcoded. - $this->any_char = chr(0) . '%'; - $this->one_char = chr(0) . '_'; - } - - /** - * return on error or display error message - */ - function sql_return_on_error($fail = false) - { - $this->sql_error_triggered = false; - $this->sql_error_sql = ''; - - $this->return_on_error = $fail; - } - - /** - * Return number of sql queries and cached sql queries used - */ - function sql_num_queries($cached = false) - { - return ($cached) ? $this->num_queries['cached'] : $this->num_queries['normal']; - } - - /** - * Add to query count - */ - function sql_add_num_queries($cached = false) - { - $this->num_queries['cached'] += ($cached !== false) ? 1 : 0; - $this->num_queries['normal'] += ($cached !== false) ? 0 : 1; - $this->num_queries['total'] += 1; - } - - /** - * DBAL garbage collection, close sql connection - */ - function sql_close() - { - if (!$this->db_connect_id) - { - return false; - } - - if ($this->transaction) - { - do - { - $this->sql_transaction('commit'); - } - while ($this->transaction); - } - - foreach ($this->open_queries as $query_id) - { - $this->sql_freeresult($query_id); - } - - // Connection closed correctly. Set db_connect_id to false to prevent errors - if ($result = $this->_sql_close()) - { - $this->db_connect_id = false; - } - - return $result; - } - - /** - * Build LIMIT query - * Doing some validation here. - */ - function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) - { - if (empty($query)) - { - return false; - } - - // Never use a negative total or offset - $total = ($total < 0) ? 0 : $total; - $offset = ($offset < 0) ? 0 : $offset; - - return $this->_sql_query_limit($query, $total, $offset, $cache_ttl); - } - - /** - * Fetch all rows - */ - function sql_fetchrowset($query_id = false) - { - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if ($query_id !== false) - { - $result = array(); - while ($row = $this->sql_fetchrow($query_id)) - { - $result[] = $row; - } - - return $result; - } - - return false; - } - - /** - * Seek to given row number - * rownum is zero-based - */ - function sql_rowseek($rownum, &$query_id) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if (isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_rowseek($rownum, $query_id); - } - - if ($query_id === false) - { - return false; - } - - $this->sql_freeresult($query_id); - $query_id = $this->sql_query($this->last_query_text); - - if ($query_id === false) - { - return false; - } - - // We do not fetch the row for rownum == 0 because then the next resultset would be the second row - for ($i = 0; $i < $rownum; $i++) - { - if (!$this->sql_fetchrow($query_id)) - { - return false; - } - } - - return true; - } - - /** - * Fetch field - * if rownum is false, the current row is used, else it is pointing to the row (zero-based) - */ - function sql_fetchfield($field, $rownum = false, $query_id = false) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if ($query_id !== false) - { - if ($rownum !== false) - { - $this->sql_rowseek($rownum, $query_id); - } - - if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_fetchfield($query_id, $field); - } - - $row = $this->sql_fetchrow($query_id); - return (isset($row[$field])) ? $row[$field] : false; - } - - return false; - } - - /** - * Correctly adjust LIKE expression for special characters - * Some DBMS are handling them in a different way - * - * @param string $expression The expression to use. Every wildcard is escaped, except $this->any_char and $this->one_char - * @return string LIKE expression including the keyword! - */ - function sql_like_expression($expression) - { - $expression = utf8_str_replace(array('_', '%'), array("\_", "\%"), $expression); - $expression = utf8_str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression); - - return $this->_sql_like_expression('LIKE \'' . $this->sql_escape($expression) . '\''); - } - - /** - * Returns whether results of a query need to be buffered to run a transaction while iterating over them. - * - * @return bool Whether buffering is required. - */ - function sql_buffer_nested_transactions() - { - return false; - } - - /** - * SQL Transaction - * @access private - */ - function sql_transaction($status = 'begin') - { - switch ($status) - { - case 'begin': - // If we are within a transaction we will not open another one, but enclose the current one to not loose data (prevening auto commit) - if ($this->transaction) - { - $this->transactions++; - return true; - } - - $result = $this->_sql_transaction('begin'); - - if (!$result) - { - $this->sql_error(); - } - - $this->transaction = true; - break; - - case 'commit': - // If there was a previously opened transaction we do not commit yet... but count back the number of inner transactions - if ($this->transaction && $this->transactions) - { - $this->transactions--; - return true; - } - - // Check if there is a transaction (no transaction can happen if there was an error, with a combined rollback and error returning enabled) - // This implies we have transaction always set for autocommit db's - if (!$this->transaction) - { - return false; - } - - $result = $this->_sql_transaction('commit'); - - if (!$result) - { - $this->sql_error(); - } - - $this->transaction = false; - $this->transactions = 0; - break; - - case 'rollback': - $result = $this->_sql_transaction('rollback'); - $this->transaction = false; - $this->transactions = 0; - break; - - default: - $result = $this->_sql_transaction($status); - break; - } - - return $result; - } - - /** - * Build sql statement from array for insert/update/select statements - * - * Idea for this from Ikonboard - * Possible query values: INSERT, INSERT_SELECT, UPDATE, SELECT - * - */ - function sql_build_array($query, $assoc_ary = false) - { - if (!is_array($assoc_ary)) - { - return false; - } - - $fields = $values = array(); - - if ($query == 'INSERT' || $query == 'INSERT_SELECT') - { - foreach ($assoc_ary as $key => $var) - { - $fields[] = $key; - - if (is_array($var) && is_string($var[0])) - { - // This is used for INSERT_SELECT(s) - $values[] = $var[0]; - } - else - { - $values[] = $this->_sql_validate_value($var); - } - } - - $query = ($query == 'INSERT') ? ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')' : ' (' . implode(', ', $fields) . ') SELECT ' . implode(', ', $values) . ' '; - } - else if ($query == 'MULTI_INSERT') - { - trigger_error('The MULTI_INSERT query value is no longer supported. Please use sql_multi_insert() instead.', E_USER_ERROR); - } - else if ($query == 'UPDATE' || $query == 'SELECT') - { - $values = array(); - foreach ($assoc_ary as $key => $var) - { - $values[] = "$key = " . $this->_sql_validate_value($var); - } - $query = implode(($query == 'UPDATE') ? ', ' : ' AND ', $values); - } - - return $query; - } - - /** - * Build IN or NOT IN sql comparison string, uses <> or = on single element - * arrays to improve comparison speed - * - * @access public - * @param string $field name of the sql column that shall be compared - * @param array $array array of values that are allowed (IN) or not allowed (NOT IN) - * @param bool $negate true for NOT IN (), false for IN () (default) - * @param bool $allow_empty_set If true, allow $array to be empty, this function will return 1=1 or 1=0 then. Default to false. - */ - function sql_in_set($field, $array, $negate = false, $allow_empty_set = false) - { - if (!sizeof($array)) - { - if (!$allow_empty_set) - { - // Print the backtrace to help identifying the location of the problematic code - $this->sql_error('No values specified for SQL IN comparison'); - } - else - { - // NOT IN () actually means everything so use a tautology - if ($negate) - { - return '1=1'; - } - // IN () actually means nothing so use a contradiction - else - { - return '1=0'; - } - } - } - - if (!is_array($array)) - { - $array = array($array); - } - - if (sizeof($array) == 1) - { - @reset($array); - $var = current($array); - - return $field . ($negate ? ' <> ' : ' = ') . $this->_sql_validate_value($var); - } - else - { - return $field . ($negate ? ' NOT IN ' : ' IN ') . '(' . implode(', ', array_map(array($this, '_sql_validate_value'), $array)) . ')'; - } - } - - /** - * Run binary AND operator on DB column. - * Results in sql statement: "{$column_name} & (1 << {$bit}) {$compare}" - * - * @param string $column_name The column name to use - * @param int $bit The value to use for the AND operator, will be converted to (1 << $bit). Is used by options, using the number schema... 0, 1, 2...29 - * @param string $compare Any custom SQL code after the check (for example "= 0") - */ - function sql_bit_and($column_name, $bit, $compare = '') - { - if (method_exists($this, '_sql_bit_and')) - { - return $this->_sql_bit_and($column_name, $bit, $compare); - } - - return $column_name . ' & ' . (1 << $bit) . (($compare) ? ' ' . $compare : ''); - } - - /** - * Run binary OR operator on DB column. - * Results in sql statement: "{$column_name} | (1 << {$bit}) {$compare}" - * - * @param string $column_name The column name to use - * @param int $bit The value to use for the OR operator, will be converted to (1 << $bit). Is used by options, using the number schema... 0, 1, 2...29 - * @param string $compare Any custom SQL code after the check (for example "= 0") - */ - function sql_bit_or($column_name, $bit, $compare = '') - { - if (method_exists($this, '_sql_bit_or')) - { - return $this->_sql_bit_or($column_name, $bit, $compare); - } - - return $column_name . ' | ' . (1 << $bit) . (($compare) ? ' ' . $compare : ''); - } - - /** - * Run LOWER() on DB column of type text (i.e. neither varchar nor char). - * - * @param string $column_name The column name to use - * - * @return string A SQL statement like "LOWER($column_name)" - */ - function sql_lower_text($column_name) - { - return "LOWER($column_name)"; - } - - /** - * Run more than one insert statement. - * - * @param string $table table name to run the statements on - * @param array &$sql_ary multi-dimensional array holding the statement data. - * - * @return bool false if no statements were executed. - * @access public - */ - function sql_multi_insert($table, &$sql_ary) - { - if (!sizeof($sql_ary)) - { - return false; - } - - if ($this->multi_insert) - { - $ary = array(); - foreach ($sql_ary as $id => $_sql_ary) - { - // If by accident the sql array is only one-dimensional we build a normal insert statement - if (!is_array($_sql_ary)) - { - return $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $sql_ary)); - } - - $values = array(); - foreach ($_sql_ary as $key => $var) - { - $values[] = $this->_sql_validate_value($var); - } - $ary[] = '(' . implode(', ', $values) . ')'; - } - - return $this->sql_query('INSERT INTO ' . $table . ' ' . ' (' . implode(', ', array_keys($sql_ary[0])) . ') VALUES ' . implode(', ', $ary)); - } - else - { - foreach ($sql_ary as $ary) - { - if (!is_array($ary)) - { - return false; - } - - $result = $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $ary)); - - if (!$result) - { - return false; - } - } - } - - return true; - } - - /** - * Function for validating values - * @access private - */ - function _sql_validate_value($var) - { - if (is_null($var)) - { - return 'NULL'; - } - else if (is_string($var)) - { - return "'" . $this->sql_escape($var) . "'"; - } - else - { - return (is_bool($var)) ? intval($var) : $var; - } - } - - /** - * Build sql statement from array for select and select distinct statements - * - * Possible query values: SELECT, SELECT_DISTINCT - */ - function sql_build_query($query, $array) - { - $sql = ''; - switch ($query) - { - case 'SELECT': - case 'SELECT_DISTINCT'; - - $sql = str_replace('_', ' ', $query) . ' ' . $array['SELECT'] . ' FROM '; - - // Build table array. We also build an alias array for later checks. - $table_array = $aliases = array(); - $used_multi_alias = false; - - foreach ($array['FROM'] as $table_name => $alias) - { - if (is_array($alias)) - { - $used_multi_alias = true; - - foreach ($alias as $multi_alias) - { - $table_array[] = $table_name . ' ' . $multi_alias; - $aliases[] = $multi_alias; - } - } - else - { - $table_array[] = $table_name . ' ' . $alias; - $aliases[] = $alias; - } - } - - // We run the following code to determine if we need to re-order the table array. ;) - // The reason for this is that for multi-aliased tables (two equal tables) in the FROM statement the last table need to match the first comparison. - // DBMS who rely on this: Oracle, PostgreSQL and MSSQL. For all other DBMS it makes absolutely no difference in which order the table is. - if (!empty($array['LEFT_JOIN']) && sizeof($array['FROM']) > 1 && $used_multi_alias !== false) - { - // Take first LEFT JOIN - $join = current($array['LEFT_JOIN']); - - // Determine the table used there (even if there are more than one used, we only want to have one - preg_match('/(' . implode('|', $aliases) . ')\.[^\s]+/U', str_replace(array('(', ')', 'AND', 'OR', ' '), '', $join['ON']), $matches); - - // If there is a first join match, we need to make sure the table order is correct - if (!empty($matches[1])) - { - $first_join_match = trim($matches[1]); - $table_array = $last = array(); - - foreach ($array['FROM'] as $table_name => $alias) - { - if (is_array($alias)) - { - foreach ($alias as $multi_alias) - { - ($multi_alias === $first_join_match) ? $last[] = $table_name . ' ' . $multi_alias : $table_array[] = $table_name . ' ' . $multi_alias; - } - } - else - { - ($alias === $first_join_match) ? $last[] = $table_name . ' ' . $alias : $table_array[] = $table_name . ' ' . $alias; - } - } - - $table_array = array_merge($table_array, $last); - } - } - - $sql .= $this->_sql_custom_build('FROM', implode(' CROSS JOIN ', $table_array)); - - if (!empty($array['LEFT_JOIN'])) - { - foreach ($array['LEFT_JOIN'] as $join) - { - $sql .= ' LEFT JOIN ' . key($join['FROM']) . ' ' . current($join['FROM']) . ' ON (' . $join['ON'] . ')'; - } - } - - if (!empty($array['WHERE'])) - { - $sql .= ' WHERE ' . $this->_sql_custom_build('WHERE', $array['WHERE']); - } - - if (!empty($array['GROUP_BY'])) - { - $sql .= ' GROUP BY ' . $array['GROUP_BY']; - } - - if (!empty($array['ORDER_BY'])) - { - $sql .= ' ORDER BY ' . $array['ORDER_BY']; - } - - break; - } - - return $sql; - } - - /** - * display sql error page - */ - function sql_error($sql = '') - { - global $auth, $user, $config; - - // Set var to retrieve errored status - $this->sql_error_triggered = true; - $this->sql_error_sql = $sql; - - $this->sql_error_returned = $this->_sql_error(); - - if (!$this->return_on_error) - { - $message = 'SQL ERROR [ ' . $this->sql_layer . ' ]<br /><br />' . $this->sql_error_returned['message'] . ' [' . $this->sql_error_returned['code'] . ']'; - - // Show complete SQL error and path to administrators only - // Additionally show complete error on installation or if extended debug mode is enabled - // The DEBUG_EXTRA constant is for development only! - if ((isset($auth) && $auth->acl_get('a_')) || defined('IN_INSTALL') || defined('DEBUG_EXTRA')) - { - $message .= ($sql) ? '<br /><br />SQL<br /><br />' . htmlspecialchars($sql) : ''; - } - else - { - // If error occurs in initiating the session we need to use a pre-defined language string - // This could happen if the connection could not be established for example (then we are not able to grab the default language) - if (!isset($user->lang['SQL_ERROR_OCCURRED'])) - { - $message .= '<br /><br />An sql error occurred while fetching this page. Please contact an administrator if this problem persists.'; - } - else - { - if (!empty($config['board_contact'])) - { - $message .= '<br /><br />' . sprintf($user->lang['SQL_ERROR_OCCURRED'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'); - } - else - { - $message .= '<br /><br />' . sprintf($user->lang['SQL_ERROR_OCCURRED'], '', ''); - } - } - } - - if ($this->transaction) - { - $this->sql_transaction('rollback'); - } - - if (strlen($message) > 1024) - { - // We need to define $msg_long_text here to circumvent text stripping. - global $msg_long_text; - $msg_long_text = $message; - - trigger_error(false, E_USER_ERROR); - } - - trigger_error($message, E_USER_ERROR); - } - - if ($this->transaction) - { - $this->sql_transaction('rollback'); - } - - return $this->sql_error_returned; - } - - /** - * Explain queries - */ - function sql_report($mode, $query = '') - { - global $cache, $starttime, $phpbb_root_path, $user; - - if (empty($_REQUEST['explain'])) - { - return false; - } - - if (!$query && $this->query_hold != '') - { - $query = $this->query_hold; - } - - switch ($mode) - { - case 'display': - if (!empty($cache)) - { - $cache->unload(); - } - $this->sql_close(); - - $mtime = explode(' ', microtime()); - $totaltime = $mtime[0] + $mtime[1] - $starttime; - - echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - <html xmlns="http://www.w3.org/1999/xhtml" dir="ltr"> - <head> - <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> - <meta http-equiv="Content-Style-Type" content="text/css" /> - <meta http-equiv="imagetoolbar" content="no" /> - <title>SQL Report</title> - <link href="' . $phpbb_root_path . 'adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" /> - </head> - <body id="errorpage"> - <div id="wrap"> - <div id="page-header"> - <a href="' . build_url('explain') . '">Return to previous page</a> - </div> - <div id="page-body"> - <div id="acp"> - <div class="panel"> - <span class="corners-top"><span></span></span> - <div id="content"> - <h1>SQL Report</h1> - <br /> - <p><b>Page generated in ' . round($totaltime, 4) . " seconds with {$this->num_queries['normal']} queries" . (($this->num_queries['cached']) ? " + {$this->num_queries['cached']} " . (($this->num_queries['cached'] == 1) ? 'query' : 'queries') . ' returning data from cache' : '') . '</b></p> - - <p>Time spent on ' . $this->sql_layer . ' queries: <b>' . round($this->sql_time, 5) . 's</b> | Time spent on PHP: <b>' . round($totaltime - $this->sql_time, 5) . 's</b></p> - - <br /><br /> - ' . $this->sql_report . ' - </div> - <span class="corners-bottom"><span></span></span> - </div> - </div> - </div> - <div id="page-footer"> - Powered by <a href="https://www.phpbb.com/">phpBB</a>® Forum Software © phpBB Group - </div> - </div> - </body> - </html>'; - - exit_handler(); - - break; - - case 'stop': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $this->sql_report .= ' - - <table cellspacing="1"> - <thead> - <tr> - <th>Query #' . $this->num_queries['total'] . '</th> - </tr> - </thead> - <tbody> - <tr> - <td class="row3"><textarea style="font-family:\'Courier New\',monospace;width:99%" rows="5" cols="10">' . preg_replace('/\t(AND|OR)(\W)/', "\$1\$2", htmlspecialchars(preg_replace('/[\s]*[\n\r\t]+[\n\r\s\t]*/', "\n", $query))) . '</textarea></td> - </tr> - </tbody> - </table> - - ' . $this->html_hold . ' - - <p style="text-align: center;"> - '; - - if ($this->query_result) - { - if (preg_match('/^(UPDATE|DELETE|REPLACE)/', $query)) - { - $this->sql_report .= 'Affected rows: <b>' . $this->sql_affectedrows($this->query_result) . '</b> | '; - } - $this->sql_report .= 'Before: ' . sprintf('%.5f', $this->curtime - $starttime) . 's | After: ' . sprintf('%.5f', $endtime - $starttime) . 's | Elapsed: <b>' . sprintf('%.5f', $endtime - $this->curtime) . 's</b>'; - } - else - { - $error = $this->sql_error(); - $this->sql_report .= '<b style="color: red">FAILED</b> - ' . $this->sql_layer . ' Error ' . $error['code'] . ': ' . htmlspecialchars($error['message']); - } - - $this->sql_report .= '</p><br /><br />'; - - $this->sql_time += $endtime - $this->curtime; - break; - - case 'start': - $this->query_hold = $query; - $this->html_hold = ''; - - $this->_sql_report($mode, $query); - - $this->curtime = explode(' ', microtime()); - $this->curtime = $this->curtime[0] + $this->curtime[1]; - - break; - - case 'add_select_row': - - $html_table = func_get_arg(2); - $row = func_get_arg(3); - - if (!$html_table && sizeof($row)) - { - $html_table = true; - $this->html_hold .= '<table cellspacing="1"><tr>'; - - foreach (array_keys($row) as $val) - { - $this->html_hold .= '<th>' . (($val) ? ucwords(str_replace('_', ' ', $val)) : ' ') . '</th>'; - } - $this->html_hold .= '</tr>'; - } - $this->html_hold .= '<tr>'; - - $class = 'row1'; - foreach (array_values($row) as $val) - { - $class = ($class == 'row1') ? 'row2' : 'row1'; - $this->html_hold .= '<td class="' . $class . '">' . (($val) ? $val : ' ') . '</td>'; - } - $this->html_hold .= '</tr>'; - - return $html_table; - - break; - - case 'fromcache': - - $this->_sql_report($mode, $query); - - break; - - case 'record_fromcache': - - $endtime = func_get_arg(2); - $splittime = func_get_arg(3); - - $time_cache = $endtime - $this->curtime; - $time_db = $splittime - $endtime; - $color = ($time_db > $time_cache) ? 'green' : 'red'; - - $this->sql_report .= '<table cellspacing="1"><thead><tr><th>Query results obtained from the cache</th></tr></thead><tbody><tr>'; - $this->sql_report .= '<td class="row3"><textarea style="font-family:\'Courier New\',monospace;width:99%" rows="5" cols="10">' . preg_replace('/\t(AND|OR)(\W)/', "\$1\$2", htmlspecialchars(preg_replace('/[\s]*[\n\r\t]+[\n\r\s\t]*/', "\n", $query))) . '</textarea></td></tr></tbody></table>'; - $this->sql_report .= '<p style="text-align: center;">'; - $this->sql_report .= 'Before: ' . sprintf('%.5f', $this->curtime - $starttime) . 's | After: ' . sprintf('%.5f', $endtime - $starttime) . 's | Elapsed [cache]: <b style="color: ' . $color . '">' . sprintf('%.5f', ($time_cache)) . 's</b> | Elapsed [db]: <b>' . sprintf('%.5f', $time_db) . 's</b></p><br /><br />'; - - // Pad the start time to not interfere with page timing - $starttime += $time_db; - - break; - - default: - - $this->_sql_report($mode, $query); - - break; - } - - return true; - } - - /** - * Gets the estimated number of rows in a specified table. - * - * @param string $table_name Table name - * - * @return string Number of rows in $table_name. - * Prefixed with ~ if estimated (otherwise exact). - * - * @access public - */ - function get_estimated_row_count($table_name) - { - return $this->get_row_count($table_name); - } - - /** - * Gets the exact number of rows in a specified table. - * - * @param string $table_name Table name - * - * @return string Exact number of rows in $table_name. - * - * @access public - */ - function get_row_count($table_name) - { - $sql = 'SELECT COUNT(*) AS rows_total - FROM ' . $this->sql_escape($table_name); - $result = $this->sql_query($sql); - $rows_total = $this->sql_fetchfield('rows_total'); - $this->sql_freeresult($result); - - return $rows_total; - } -} - -/** -* This variable holds the class name to use later -*/ -$sql_db = (!empty($dbms)) ? 'dbal_' . basename($dbms) : 'dbal'; - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/firebird.php b/phpBB/includes/db/firebird.php deleted file mode 100644 index 7072c58ac0..0000000000 --- a/phpBB/includes/db/firebird.php +++ /dev/null @@ -1,526 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - -/** -* Firebird/Interbase Database Abstraction Layer -* Minimum Requirement is Firebird 2.1 -* @package dbal -*/ -class dbal_firebird extends dbal -{ - var $last_query_text = ''; - var $service_handle = false; - var $affected_rows = 0; - var $connect_error = ''; - - /** - * Connect to server - */ - function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) - { - $this->persistency = $persistency; - $this->user = $sqluser; - $this->server = $sqlserver . (($port) ? ':' . $port : ''); - $this->dbname = str_replace('\\', '/', $database); - - // There are three possibilities to connect to an interbase db - if (!$this->server) - { - $use_database = $this->dbname; - } - else if (strpos($this->server, '//') === 0) - { - $use_database = $this->server . $this->dbname; - } - else - { - $use_database = $this->server . ':' . $this->dbname; - } - - if ($this->persistency) - { - if (!function_exists('ibase_pconnect')) - { - $this->connect_error = 'ibase_pconnect function does not exist, is interbase extension installed?'; - return $this->sql_error(''); - } - $this->db_connect_id = @ibase_pconnect($use_database, $this->user, $sqlpassword, false, false, 3); - } - else - { - if (!function_exists('ibase_connect')) - { - $this->connect_error = 'ibase_connect function does not exist, is interbase extension installed?'; - return $this->sql_error(''); - } - $this->db_connect_id = @ibase_connect($use_database, $this->user, $sqlpassword, false, false, 3); - } - - // Do not call ibase_service_attach if connection failed, - // otherwise error message from ibase_(p)connect call will be clobbered. - if ($this->db_connect_id && function_exists('ibase_service_attach') && $this->server) - { - $this->service_handle = @ibase_service_attach($this->server, $this->user, $sqlpassword); - } - else - { - $this->service_handle = false; - } - - return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); - } - - /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache forced to false for Interbase - * @return string sql server version - */ - function sql_server_info($raw = false, $use_cache = true) - { - /** - * force $use_cache false. I didn't research why the caching code there is no caching code - * but I assume its because the IB extension provides a direct method to access it - * without a query. - */ - - $use_cache = false; - - if ($this->service_handle !== false && function_exists('ibase_server_info')) - { - return @ibase_server_info($this->service_handle, IBASE_SVC_SERVER_VERSION); - } - - return ($raw) ? '2.1' : 'Firebird/Interbase'; - } - - /** - * SQL Transaction - * @access private - */ - function _sql_transaction($status = 'begin') - { - switch ($status) - { - case 'begin': - return true; - break; - - case 'commit': - return @ibase_commit(); - break; - - case 'rollback': - return @ibase_rollback(); - break; - } - - return true; - } - - /** - * 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 - */ - 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->last_query_text = $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) - { - $array = array(); - // We overcome Firebird's 32767 char limit by binding vars - if (strlen($query) > 32767) - { - if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/s', $query, $regs)) - { - if (strlen($regs[3]) > 32767) - { - preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER); - - $inserts = $vals[0]; - unset($vals); - - foreach ($inserts as $key => $value) - { - if (!empty($value) && $value[0] === "'" && strlen($value) > 32769) // check to see if this thing is greater than the max + 'x2 - { - $inserts[$key] = '?'; - $array[] = str_replace("''", "'", substr($value, 1, -1)); - } - } - - $query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')'; - } - } - else if (preg_match('/^(UPDATE ([\\w_]++)\\s+SET )([\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|\\d+)(?:,\\s*[\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+)\\s+(WHERE.*)$/s', $query, $data)) - { - if (strlen($data[3]) > 32767) - { - $update = $data[1]; - $where = $data[4]; - preg_match_all('/(\\w++)\\s*=\\s*(\'(?:[^\']++|\'\')*+\'|[\d-.]++)/', $data[3], $temp, PREG_SET_ORDER); - unset($data); - - $cols = array(); - foreach ($temp as $value) - { - if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 32769) // check to see if this thing is greater than the max + 'x2 - { - $array[] = str_replace("''", "'", substr($value[2], 1, -1)); - $cols[] = $value[1] . '=?'; - } - else - { - $cols[] = $value[1] . '=' . $value[2]; - } - } - - $query = $update . implode(', ', $cols) . ' ' . $where; - unset($cols); - } - } - } - - if (!function_exists('ibase_affected_rows') && (preg_match('/^UPDATE ([\w_]++)\s+SET [\w_]++\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+)(?:,\s*[\w_]++\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+\s+(WHERE.*)?$/s', $query, $regs) || preg_match('/^DELETE FROM ([\w_]++)\s*(WHERE\s*.*)?$/s', $query, $regs))) - { - $affected_sql = 'SELECT COUNT(*) as num_rows_affected FROM ' . $regs[1]; - if (!empty($regs[2])) - { - $affected_sql .= ' ' . $regs[2]; - } - - if (!($temp_q_id = @ibase_query($this->db_connect_id, $affected_sql))) - { - return false; - } - - $temp_result = @ibase_fetch_assoc($temp_q_id); - @ibase_free_result($temp_q_id); - - $this->affected_rows = ($temp_result) ? $temp_result['NUM_ROWS_AFFECTED'] : false; - } - - if (sizeof($array)) - { - $p_query = @ibase_prepare($this->db_connect_id, $query); - array_unshift($array, $p_query); - $this->query_result = call_user_func_array('ibase_execute', $array); - unset($array); - - if ($this->query_result === false) - { - $this->sql_error($query); - } - } - else if (($this->query_result = @ibase_query($this->db_connect_id, $query)) === false) - { - $this->sql_error($query); - } - - if (defined('DEBUG_EXTRA')) - { - $this->sql_report('stop', $query); - } - - if (!$this->transaction) - { - if (function_exists('ibase_commit_ret')) - { - @ibase_commit_ret(); - } - else - { - // way cooler than ibase_commit_ret :D - @ibase_query('COMMIT RETAIN;'); - } - } - - 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; - - $query = 'SELECT FIRST ' . $total . ((!empty($offset)) ? ' SKIP ' . $offset : '') . substr($query, 6); - - return $this->sql_query($query, $cache_ttl); - } - - /** - * Return number of affected rows - */ - function sql_affectedrows() - { - // PHP 5+ function - if (function_exists('ibase_affected_rows')) - { - return ($this->db_connect_id) ? @ibase_affected_rows($this->db_connect_id) : false; - } - else - { - return $this->affected_rows; - } - } - - /** - * Fetch current row - */ - 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); - } - - if ($query_id === false) - { - return false; - } - - $row = array(); - $cur_row = @ibase_fetch_object($query_id, IBASE_TEXT); - - if (!$cur_row) - { - return false; - } - - foreach (get_object_vars($cur_row) as $key => $value) - { - $row[strtolower($key)] = (is_string($value)) ? trim(str_replace(array("\\0", "\\n"), array("\0", "\n"), $value)) : $value; - } - - return (sizeof($row)) ? $row : false; - } - - /** - * Get last inserted id after insert statement - */ - function sql_nextid() - { - $query_id = $this->query_result; - - if ($query_id !== false && $this->last_query_text != '') - { - if ($this->query_result && preg_match('#^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)#i', $this->last_query_text, $tablename)) - { - $sql = 'SELECT GEN_ID(' . $tablename[1] . '_gen, 0) AS new_id FROM RDB$DATABASE'; - - if (!($temp_q_id = @ibase_query($this->db_connect_id, $sql))) - { - return false; - } - - $temp_result = @ibase_fetch_assoc($temp_q_id); - @ibase_free_result($temp_q_id); - - return ($temp_result) ? $temp_result['NEW_ID'] : false; - } - } - - return false; - } - - /** - * Free sql result - */ - function sql_freeresult($query_id = false) - { - 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 @ibase_free_result($query_id); - } - - return false; - } - - /** - * Escape string used in sql query - */ - function sql_escape($msg) - { - return str_replace(array("'", "\0"), array("''", ''), $msg); - } - - /** - * Build LIKE expression - * @access private - */ - function _sql_like_expression($expression) - { - return $expression . " ESCAPE '\\'"; - } - - /** - * Build db-specific query data - * @access private - */ - function _sql_custom_build($stage, $data) - { - return $data; - } - - function _sql_bit_and($column_name, $bit, $compare = '') - { - return 'BIN_AND(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : ''); - } - - function _sql_bit_or($column_name, $bit, $compare = '') - { - return 'BIN_OR(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : ''); - } - - /** - * return sql error array - * @access private - */ - function _sql_error() - { - // Need special handling here because ibase_errmsg returns - // connection errors, however if the interbase extension - // is not installed then ibase_errmsg does not exist and - // we cannot call it. - if (function_exists('ibase_errmsg')) - { - $msg = @ibase_errmsg(); - if (!$msg) - { - $msg = $this->connect_error; - } - } - else - { - $msg = $this->connect_error; - } - return array( - 'message' => $msg, - 'code' => (@function_exists('ibase_errcode') ? @ibase_errcode() : '') - ); - } - - /** - * Close sql connection - * @access private - */ - function _sql_close() - { - if ($this->service_handle !== false) - { - @ibase_service_detach($this->service_handle); - } - - return @ibase_close($this->db_connect_id); - } - - /** - * Build db-specific report - * @access private - */ - function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @ibase_query($this->db_connect_id, $query); - while ($void = @ibase_fetch_object($result, IBASE_TEXT)) - { - // Take the time spent on parsing rows into account - } - @ibase_free_result($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/mssql.php b/phpBB/includes/db/mssql.php deleted file mode 100644 index 2dd95c2508..0000000000 --- a/phpBB/includes/db/mssql.php +++ /dev/null @@ -1,476 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - -/** -* MSSQL Database Abstraction Layer -* Minimum Requirement is MSSQL 2000+ -* @package dbal -*/ -class dbal_mssql extends dbal -{ - var $connect_error = ''; - - /** - * Connect to server - */ - function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) - { - if (!function_exists('mssql_connect')) - { - $this->connect_error = 'mssql_connect function does not exist, is mssql extension installed?'; - return $this->sql_error(''); - } - - $this->persistency = $persistency; - $this->user = $sqluser; - $this->dbname = $database; - - $port_delimiter = (defined('PHP_OS') && substr(PHP_OS, 0, 3) === 'WIN') ? ',' : ':'; - $this->server = $sqlserver . (($port) ? $port_delimiter . $port : ''); - - @ini_set('mssql.charset', 'UTF-8'); - @ini_set('mssql.textlimit', 2147483647); - @ini_set('mssql.textsize', 2147483647); - - if (version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.1', '>='))) - { - $this->db_connect_id = ($this->persistency) ? @mssql_pconnect($this->server, $this->user, $sqlpassword, $new_link) : @mssql_connect($this->server, $this->user, $sqlpassword, $new_link); - } - else - { - $this->db_connect_id = ($this->persistency) ? @mssql_pconnect($this->server, $this->user, $sqlpassword) : @mssql_connect($this->server, $this->user, $sqlpassword); - } - - if ($this->db_connect_id && $this->dbname != '') - { - if (!@mssql_select_db($this->dbname, $this->db_connect_id)) - { - @mssql_close($this->db_connect_id); - return false; - } - } - - return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); - } - - /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache If true, it is safe to retrieve the value from the cache - * @return string sql server version - */ - function sql_server_info($raw = false, $use_cache = true) - { - global $cache; - - if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mssql_version')) === false) - { - $result_id = @mssql_query("SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY('productlevel'), SERVERPROPERTY('edition')", $this->db_connect_id); - - $row = false; - if ($result_id) - { - $row = @mssql_fetch_assoc($result_id); - @mssql_free_result($result_id); - } - - $this->sql_server_version = ($row) ? trim(implode(' ', $row)) : 0; - - if (!empty($cache) && $use_cache) - { - $cache->put('mssql_version', $this->sql_server_version); - } - } - - if ($raw) - { - return $this->sql_server_version; - } - - return ($this->sql_server_version) ? 'MSSQL<br />' . $this->sql_server_version : 'MSSQL'; - } - - /** - * SQL Transaction - * @access private - */ - function _sql_transaction($status = 'begin') - { - switch ($status) - { - case 'begin': - return @mssql_query('BEGIN TRANSACTION', $this->db_connect_id); - break; - - case 'commit': - return @mssql_query('COMMIT TRANSACTION', $this->db_connect_id); - break; - - case 'rollback': - return @mssql_query('ROLLBACK TRANSACTION', $this->db_connect_id); - break; - } - - return true; - } - - /** - * 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 - */ - 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 = @mssql_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; - - // Since TOP is only returning a set number of rows we won't need it if total is set to 0 (return all rows) - if ($total) - { - // We need to grab the total number of rows + the offset number of rows to get the correct result - if (strpos($query, 'SELECT DISTINCT') === 0) - { - $query = 'SELECT DISTINCT TOP ' . ($total + $offset) . ' ' . substr($query, 15); - } - else - { - $query = 'SELECT TOP ' . ($total + $offset) . ' ' . substr($query, 6); - } - } - - $result = $this->sql_query($query, $cache_ttl); - - // Seek by $offset rows - if ($offset) - { - $this->sql_rowseek($offset, $result); - } - - return $result; - } - - /** - * Return number of affected rows - */ - function sql_affectedrows() - { - return ($this->db_connect_id) ? @mssql_rows_affected($this->db_connect_id) : false; - } - - /** - * Fetch current row - */ - 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); - } - - if ($query_id === false) - { - return false; - } - - $row = @mssql_fetch_assoc($query_id); - - // I hope i am able to remove this later... hopefully only a PHP or MSSQL bug - if ($row) - { - foreach ($row as $key => $value) - { - $row[$key] = ($value === ' ' || $value === NULL) ? '' : $value; - } - } - - return $row; - } - - /** - * Seek to given row number - * rownum is zero-based - */ - function sql_rowseek($rownum, &$query_id) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if (isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_rowseek($rownum, $query_id); - } - - return ($query_id !== false) ? @mssql_data_seek($query_id, $rownum) : false; - } - - /** - * Get last inserted id after insert statement - */ - function sql_nextid() - { - $result_id = @mssql_query('SELECT SCOPE_IDENTITY()', $this->db_connect_id); - if ($result_id) - { - if ($row = @mssql_fetch_assoc($result_id)) - { - @mssql_free_result($result_id); - return $row['computed']; - } - @mssql_free_result($result_id); - } - - return false; - } - - /** - * Free sql result - */ - function sql_freeresult($query_id = false) - { - 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[$query_id])) - { - unset($this->open_queries[$query_id]); - return @mssql_free_result($query_id); - } - - return false; - } - - /** - * Escape string used in sql query - */ - function sql_escape($msg) - { - return str_replace(array("'", "\0"), array("''", ''), $msg); - } - - /** - * {@inheritDoc} - */ - function sql_lower_text($column_name) - { - return "LOWER(SUBSTRING($column_name, 1, DATALENGTH($column_name)))"; - } - - /** - * Build LIKE expression - * @access private - */ - function _sql_like_expression($expression) - { - return $expression . " ESCAPE '\\'"; - } - - /** - * return sql error array - * @access private - */ - function _sql_error() - { - if (function_exists('mssql_get_last_message')) - { - $error = array( - 'message' => @mssql_get_last_message(), - 'code' => '', - ); - - // Get error code number - $result_id = @mssql_query('SELECT @@ERROR as code', $this->db_connect_id); - if ($result_id) - { - $row = @mssql_fetch_assoc($result_id); - $error['code'] = $row['code']; - @mssql_free_result($result_id); - } - - // Get full error message if possible - $sql = 'SELECT CAST(description as varchar(255)) as message - FROM master.dbo.sysmessages - WHERE error = ' . $error['code']; - $result_id = @mssql_query($sql); - - if ($result_id) - { - $row = @mssql_fetch_assoc($result_id); - if (!empty($row['message'])) - { - $error['message'] .= '<br />' . $row['message']; - } - @mssql_free_result($result_id); - } - } - else - { - $error = array( - 'message' => $this->connect_error, - 'code' => '', - ); - } - - return $error; - } - - /** - * Build db-specific query data - * @access private - */ - function _sql_custom_build($stage, $data) - { - return $data; - } - - /** - * Close sql connection - * @access private - */ - function _sql_close() - { - return @mssql_close($this->db_connect_id); - } - - /** - * Build db-specific report - * @access private - */ - function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - $html_table = false; - @mssql_query('SET SHOWPLAN_TEXT ON;', $this->db_connect_id); - if ($result = @mssql_query($query, $this->db_connect_id)) - { - @mssql_next_result($result); - while ($row = @mssql_fetch_row($result)) - { - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - } - @mssql_query('SET SHOWPLAN_TEXT OFF;', $this->db_connect_id); - @mssql_free_result($result); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @mssql_query($query, $this->db_connect_id); - while ($void = @mssql_fetch_assoc($result)) - { - // Take the time spent on parsing rows into account - } - @mssql_free_result($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/mssql_odbc.php b/phpBB/includes/db/mssql_odbc.php deleted file mode 100644 index 04501cce8b..0000000000 --- a/phpBB/includes/db/mssql_odbc.php +++ /dev/null @@ -1,422 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - -/** -* Unified ODBC functions -* Unified ODBC functions support any database having ODBC driver, for example Adabas D, IBM DB2, iODBC, Solid, Sybase SQL Anywhere... -* Here we only support MSSQL Server 2000+ because of the provided schema -* -* @note number of bytes returned for returning data depends on odbc.defaultlrl php.ini setting. -* If it is limited to 4K for example only 4K of data is returned max, resulting in incomplete theme data for example. -* @note odbc.defaultbinmode may affect UTF8 characters -* -* @package dbal -*/ -class dbal_mssql_odbc extends dbal -{ - var $last_query_text = ''; - var $connect_error = ''; - - /** - * Connect to server - */ - function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) - { - $this->persistency = $persistency; - $this->user = $sqluser; - $this->dbname = $database; - - $port_delimiter = (defined('PHP_OS') && substr(PHP_OS, 0, 3) === 'WIN') ? ',' : ':'; - $this->server = $sqlserver . (($port) ? $port_delimiter . $port : ''); - - $max_size = @ini_get('odbc.defaultlrl'); - if (!empty($max_size)) - { - $unit = strtolower(substr($max_size, -1, 1)); - $max_size = (int) $max_size; - - if ($unit == 'k') - { - $max_size = floor($max_size / 1024); - } - else if ($unit == 'g') - { - $max_size *= 1024; - } - else if (is_numeric($unit)) - { - $max_size = floor((int) ($max_size . $unit) / 1048576); - } - $max_size = max(8, $max_size) . 'M'; - - @ini_set('odbc.defaultlrl', $max_size); - } - - if ($this->persistency) - { - if (!function_exists('odbc_pconnect')) - { - $this->connect_error = 'odbc_pconnect function does not exist, is odbc extension installed?'; - return $this->sql_error(''); - } - $this->db_connect_id = @odbc_pconnect($this->server, $this->user, $sqlpassword); - } - else - { - if (!function_exists('odbc_connect')) - { - $this->connect_error = 'odbc_connect function does not exist, is odbc extension installed?'; - return $this->sql_error(''); - } - $this->db_connect_id = @odbc_connect($this->server, $this->user, $sqlpassword); - } - - return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); - } - - /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache If true, it is safe to retrieve the value from the cache - * @return string sql server version - */ - function sql_server_info($raw = false, $use_cache = true) - { - global $cache; - - if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mssqlodbc_version')) === false) - { - $result_id = @odbc_exec($this->db_connect_id, "SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY('productlevel'), SERVERPROPERTY('edition')"); - - $row = false; - if ($result_id) - { - $row = @odbc_fetch_array($result_id); - @odbc_free_result($result_id); - } - - $this->sql_server_version = ($row) ? trim(implode(' ', $row)) : 0; - - if (!empty($cache) && $use_cache) - { - $cache->put('mssqlodbc_version', $this->sql_server_version); - } - } - - if ($raw) - { - return $this->sql_server_version; - } - - return ($this->sql_server_version) ? 'MSSQL (ODBC)<br />' . $this->sql_server_version : 'MSSQL (ODBC)'; - } - - /** - * SQL Transaction - * @access private - */ - function _sql_transaction($status = 'begin') - { - switch ($status) - { - case 'begin': - return @odbc_exec($this->db_connect_id, 'BEGIN TRANSACTION'); - break; - - case 'commit': - return @odbc_exec($this->db_connect_id, 'COMMIT TRANSACTION'); - break; - - case 'rollback': - return @odbc_exec($this->db_connect_id, 'ROLLBACK TRANSACTION'); - break; - } - - return true; - } - - /** - * 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 - */ - 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->last_query_text = $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 = @odbc_exec($this->db_connect_id, $query)) === 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; - - // Since TOP is only returning a set number of rows we won't need it if total is set to 0 (return all rows) - if ($total) - { - // We need to grab the total number of rows + the offset number of rows to get the correct result - if (strpos($query, 'SELECT DISTINCT') === 0) - { - $query = 'SELECT DISTINCT TOP ' . ($total + $offset) . ' ' . substr($query, 15); - } - else - { - $query = 'SELECT TOP ' . ($total + $offset) . ' ' . substr($query, 6); - } - } - - $result = $this->sql_query($query, $cache_ttl); - - // Seek by $offset rows - if ($offset) - { - $this->sql_rowseek($offset, $result); - } - - return $result; - } - - /** - * Return number of affected rows - */ - function sql_affectedrows() - { - return ($this->db_connect_id) ? @odbc_num_rows($this->query_result) : false; - } - - /** - * Fetch current row - * @note number of bytes returned depends on odbc.defaultlrl php.ini setting. If it is limited to 4K for example only 4K of data is returned max. - */ - function sql_fetchrow($query_id = false, $debug = 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) ? @odbc_fetch_array($query_id) : false; - } - - /** - * Get last inserted id after insert statement - */ - function sql_nextid() - { - $result_id = @odbc_exec($this->db_connect_id, 'SELECT @@IDENTITY'); - - if ($result_id) - { - if (@odbc_fetch_array($result_id)) - { - $id = @odbc_result($result_id, 1); - @odbc_free_result($result_id); - return $id; - } - @odbc_free_result($result_id); - } - - return false; - } - - /** - * Free sql result - */ - function sql_freeresult($query_id = false) - { - 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 @odbc_free_result($query_id); - } - - return false; - } - - /** - * Escape string used in sql query - */ - function sql_escape($msg) - { - return str_replace(array("'", "\0"), array("''", ''), $msg); - } - - /** - * {@inheritDoc} - */ - function sql_lower_text($column_name) - { - return "LOWER(SUBSTRING($column_name, 1, DATALENGTH($column_name)))"; - } - - /** - * Build LIKE expression - * @access private - */ - function _sql_like_expression($expression) - { - return $expression . " ESCAPE '\\'"; - } - - /** - * Build db-specific query data - * @access private - */ - function _sql_custom_build($stage, $data) - { - return $data; - } - - /** - * return sql error array - * @access private - */ - function _sql_error() - { - if (function_exists('odbc_errormsg')) - { - $error = array( - 'message' => @odbc_errormsg(), - 'code' => @odbc_error(), - ); - } - else - { - $error = array( - 'message' => $this->connect_error, - 'code' => '', - ); - } - - return $error; - } - - /** - * Close sql connection - * @access private - */ - function _sql_close() - { - return @odbc_close($this->db_connect_id); - } - - /** - * Build db-specific report - * @access private - */ - function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @odbc_exec($this->db_connect_id, $query); - while ($void = @odbc_fetch_array($result)) - { - // Take the time spent on parsing rows into account - } - @odbc_free_result($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/mssqlnative.php b/phpBB/includes/db/mssqlnative.php deleted file mode 100644 index b91372ac61..0000000000 --- a/phpBB/includes/db/mssqlnative.php +++ /dev/null @@ -1,652 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2010 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -* This is the MS SQL Server Native database abstraction layer. -* PHP mssql native driver required. -* @author Chris Pucci -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - -/** - * Prior to version 1.1 the SQL Server Native PHP driver didn't support sqlsrv_num_rows, or cursor based seeking so we recall all rows into an array - * and maintain our own cursor index into that array. - */ -class result_mssqlnative -{ - public function result_mssqlnative($queryresult = false) - { - $this->m_cursor = 0; - $this->m_rows = array(); - $this->m_num_fields = sqlsrv_num_fields($queryresult); - $this->m_field_meta = sqlsrv_field_metadata($queryresult); - - while ($row = sqlsrv_fetch_array($queryresult, SQLSRV_FETCH_ASSOC)) - { - if ($row !== null) - { - foreach($row as $k => $v) - { - if (is_object($v) && method_exists($v, 'format')) - { - $row[$k] = $v->format("Y-m-d\TH:i:s\Z"); - } - } - $this->m_rows[] = $row;//read results into memory, cursors are not supported - } - } - - $this->m_row_count = sizeof($this->m_rows); - } - - private function array_to_obj($array, &$obj) - { - foreach ($array as $key => $value) - { - if (is_array($value)) - { - $obj->$key = new stdClass(); - array_to_obj($value, $obj->$key); - } - else - { - $obj->$key = $value; - } - } - return $obj; - } - - public function fetch($mode = SQLSRV_FETCH_BOTH, $object_class = 'stdClass') - { - if ($this->m_cursor >= $this->m_row_count || $this->m_row_count == 0) - { - return false; - } - - $ret = false; - $arr_num = array(); - - if ($mode == SQLSRV_FETCH_NUMERIC || $mode == SQLSRV_FETCH_BOTH) - { - foreach($this->m_rows[$this->m_cursor] as $key => $value) - { - $arr_num[] = $value; - } - } - - switch ($mode) - { - case SQLSRV_FETCH_ASSOC: - $ret = $this->m_rows[$this->m_cursor]; - break; - case SQLSRV_FETCH_NUMERIC: - $ret = $arr_num; - break; - case 'OBJECT': - $ret = $this->array_to_obj($this->m_rows[$this->m_cursor], $o = new $object_class); - break; - case SQLSRV_FETCH_BOTH: - default: - $ret = $this->m_rows[$this->m_cursor] + $arr_num; - break; - } - $this->m_cursor++; - return $ret; - } - - public function get($pos, $fld) - { - return $this->m_rows[$pos][$fld]; - } - - public function num_rows() - { - return $this->m_row_count; - } - - public function seek($iRow) - { - $this->m_cursor = min($iRow, $this->m_row_count); - } - - public function num_fields() - { - return $this->m_num_fields; - } - - public function field_name($nr) - { - $arr_keys = array_keys($this->m_rows[0]); - return $arr_keys[$nr]; - } - - public function field_type($nr) - { - $i = 0; - $int_type = -1; - $str_type = ''; - - foreach ($this->m_field_meta as $meta) - { - if ($nr == $i) - { - $int_type = $meta['Type']; - break; - } - $i++; - } - - //http://msdn.microsoft.com/en-us/library/cc296183.aspx contains type table - switch ($int_type) - { - case SQLSRV_SQLTYPE_BIGINT: $str_type = 'bigint'; break; - case SQLSRV_SQLTYPE_BINARY: $str_type = 'binary'; break; - case SQLSRV_SQLTYPE_BIT: $str_type = 'bit'; break; - case SQLSRV_SQLTYPE_CHAR: $str_type = 'char'; break; - case SQLSRV_SQLTYPE_DATETIME: $str_type = 'datetime'; break; - case SQLSRV_SQLTYPE_DECIMAL/*($precision, $scale)*/: $str_type = 'decimal'; break; - case SQLSRV_SQLTYPE_FLOAT: $str_type = 'float'; break; - case SQLSRV_SQLTYPE_IMAGE: $str_type = 'image'; break; - case SQLSRV_SQLTYPE_INT: $str_type = 'int'; break; - case SQLSRV_SQLTYPE_MONEY: $str_type = 'money'; break; - case SQLSRV_SQLTYPE_NCHAR/*($charCount)*/: $str_type = 'nchar'; break; - case SQLSRV_SQLTYPE_NUMERIC/*($precision, $scale)*/: $str_type = 'numeric'; break; - case SQLSRV_SQLTYPE_NVARCHAR/*($charCount)*/: $str_type = 'nvarchar'; break; - case SQLSRV_SQLTYPE_NTEXT: $str_type = 'ntext'; break; - case SQLSRV_SQLTYPE_REAL: $str_type = 'real'; break; - case SQLSRV_SQLTYPE_SMALLDATETIME: $str_type = 'smalldatetime'; break; - case SQLSRV_SQLTYPE_SMALLINT: $str_type = 'smallint'; break; - case SQLSRV_SQLTYPE_SMALLMONEY: $str_type = 'smallmoney'; break; - case SQLSRV_SQLTYPE_TEXT: $str_type = 'text'; break; - case SQLSRV_SQLTYPE_TIMESTAMP: $str_type = 'timestamp'; break; - case SQLSRV_SQLTYPE_TINYINT: $str_type = 'tinyint'; break; - case SQLSRV_SQLTYPE_UNIQUEIDENTIFIER: $str_type = 'uniqueidentifier'; break; - case SQLSRV_SQLTYPE_UDT: $str_type = 'UDT'; break; - case SQLSRV_SQLTYPE_VARBINARY/*($byteCount)*/: $str_type = 'varbinary'; break; - case SQLSRV_SQLTYPE_VARCHAR/*($charCount)*/: $str_type = 'varchar'; break; - case SQLSRV_SQLTYPE_XML: $str_type = 'xml'; break; - default: $str_type = $int_type; - } - return $str_type; - } - - public function free() - { - unset($this->m_rows); - return; - } -} - -/** -* @package dbal -*/ -class dbal_mssqlnative extends dbal -{ - var $m_insert_id = NULL; - var $last_query_text = ''; - var $query_options = array(); - var $connect_error = ''; - - /** - * Connect to server - */ - function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) - { - // Test for driver support, to avoid suppressed fatal error - if (!function_exists('sqlsrv_connect')) - { - $this->connect_error = 'Native MS SQL Server driver for PHP is missing or needs to be updated. Version 1.1 or later is required to install phpBB3. You can download the driver from: http://www.microsoft.com/sqlserver/2005/en/us/PHP-Driver.aspx'; - return $this->sql_error(''); - } - - //set up connection variables - $this->persistency = $persistency; - $this->user = $sqluser; - $this->dbname = $database; - $port_delimiter = (defined('PHP_OS') && substr(PHP_OS, 0, 3) === 'WIN') ? ',' : ':'; - $this->server = $sqlserver . (($port) ? $port_delimiter . $port : ''); - - //connect to database - $this->db_connect_id = sqlsrv_connect($this->server, array( - 'Database' => $this->dbname, - 'UID' => $this->user, - 'PWD' => $sqlpassword - )); - - return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); - } - - /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache If true, it is safe to retrieve the value from the cache - * @return string sql server version - */ - function sql_server_info($raw = false, $use_cache = true) - { - global $cache; - - if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mssql_version')) === false) - { - $arr_server_info = sqlsrv_server_info($this->db_connect_id); - $this->sql_server_version = $arr_server_info['SQLServerVersion']; - - if (!empty($cache) && $use_cache) - { - $cache->put('mssql_version', $this->sql_server_version); - } - } - - if ($raw) - { - return $this->sql_server_version; - } - - return ($this->sql_server_version) ? 'MSSQL<br />' . $this->sql_server_version : 'MSSQL'; - } - - /** - * {@inheritDoc} - */ - function sql_buffer_nested_transactions() - { - return true; - } - - /** - * SQL Transaction - * @access private - */ - function _sql_transaction($status = 'begin') - { - switch ($status) - { - case 'begin': - return sqlsrv_begin_transaction($this->db_connect_id); - break; - - case 'commit': - return sqlsrv_commit($this->db_connect_id); - break; - - case 'rollback': - return sqlsrv_rollback($this->db_connect_id); - break; - } - return true; - } - - /** - * 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 - */ - 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->last_query_text = $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 = @sqlsrv_query($this->db_connect_id, $query, array(), $this->query_options)) === false) - { - $this->sql_error($query); - } - // reset options for next query - $this->query_options = array(); - - 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; - - // total == 0 means all results - not zero results - if ($offset == 0 && $total !== 0) - { - if (strpos($query, "SELECT") === false) - { - $query = "TOP {$total} " . $query; - } - else - { - $query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP '.$total, $query); - } - } - else if ($offset > 0) - { - $query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP(10000000) ', $query); - $query = 'SELECT * - FROM (SELECT sub2.*, ROW_NUMBER() OVER(ORDER BY sub2.line2) AS line3 - FROM (SELECT 1 AS line2, sub1.* FROM (' . $query . ') AS sub1) as sub2) AS sub3'; - - if ($total > 0) - { - $query .= ' WHERE line3 BETWEEN ' . ($offset+1) . ' AND ' . ($offset + $total); - } - else - { - $query .= ' WHERE line3 > ' . $offset; - } - } - - $result = $this->sql_query($query, $cache_ttl); - - return $result; - } - - /** - * Return number of affected rows - */ - function sql_affectedrows() - { - return (!empty($this->query_result)) ? @sqlsrv_rows_affected($this->query_result) : false; - } - - /** - * Fetch current row - */ - 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); - } - - if ($query_id === false) - { - return false; - } - - $row = @sqlsrv_fetch_array($query_id, SQLSRV_FETCH_ASSOC); - - if ($row) - { - foreach ($row as $key => $value) - { - $row[$key] = ($value === ' ' || $value === NULL) ? '' : $value; - } - - // remove helper values from LIMIT queries - if (isset($row['line2'])) - { - unset($row['line2'], $row['line3']); - } - } - return (sizeof($row)) ? $row : false; - } - - /** - * Get last inserted id after insert statement - */ - function sql_nextid() - { - $result_id = @sqlsrv_query($this->db_connect_id, 'SELECT @@IDENTITY'); - - if ($result_id !== false) - { - $row = @sqlsrv_fetch_array($result_id); - $id = $row[0]; - @sqlsrv_free_stmt($result_id); - return $id; - } - else - { - return false; - } - } - - /** - * Free sql result - */ - function sql_freeresult($query_id = false) - { - 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[$query_id])) - { - unset($this->open_queries[$query_id]); - return @sqlsrv_free_stmt($query_id); - } - return false; - } - - /** - * Escape string used in sql query - */ - function sql_escape($msg) - { - return str_replace(array("'", "\0"), array("''", ''), $msg); - } - - /** - * {@inheritDoc} - */ - function sql_lower_text($column_name) - { - return "LOWER(SUBSTRING($column_name, 1, DATALENGTH($column_name)))"; - } - - /** - * Build LIKE expression - * @access private - */ - function _sql_like_expression($expression) - { - return $expression . " ESCAPE '\\'"; - } - - /** - * return sql error array - * @access private - */ - function _sql_error() - { - if (function_exists('sqlsrv_errors')) - { - $errors = @sqlsrv_errors(SQLSRV_ERR_ERRORS); - $error_message = ''; - $code = 0; - - if ($errors != null) - { - foreach ($errors as $error) - { - $error_message .= "SQLSTATE: " . $error[ 'SQLSTATE'] . "\n"; - $error_message .= "code: " . $error[ 'code'] . "\n"; - $code = $error['code']; - $error_message .= "message: " . $error[ 'message'] . "\n"; - } - $this->last_error_result = $error_message; - $error = $this->last_error_result; - } - else - { - $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array(); - } - - $error = array( - 'message' => $error, - 'code' => $code, - ); - } - else - { - $error = array( - 'message' => $this->connect_error, - 'code' => '', - ); - } - - return $error; - } - - /** - * Build db-specific query data - * @access private - */ - function _sql_custom_build($stage, $data) - { - return $data; - } - - /** - * Close sql connection - * @access private - */ - function _sql_close() - { - return @sqlsrv_close($this->db_connect_id); - } - - /** - * Build db-specific report - * @access private - */ - function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - $html_table = false; - @sqlsrv_query($this->db_connect_id, 'SET SHOWPLAN_TEXT ON;'); - if ($result = @sqlsrv_query($this->db_connect_id, $query)) - { - @sqlsrv_next_result($result); - while ($row = @sqlsrv_fetch_array($result)) - { - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - } - @sqlsrv_query($this->db_connect_id, 'SET SHOWPLAN_TEXT OFF;'); - @sqlsrv_free_stmt($result); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @sqlsrv_query($this->db_connect_id, $query); - while ($void = @sqlsrv_fetch_array($result)) - { - // Take the time spent on parsing rows into account - } - @sqlsrv_free_stmt($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } - - /** - * Utility method used to retrieve number of rows - * Emulates mysql_num_rows - * Used in acp_database.php -> write_data_mssqlnative() - * Requires a static or keyset cursor to be definde via - * mssqlnative_set_query_options() - */ - function mssqlnative_num_rows($res) - { - if ($res !== false) - { - return sqlsrv_num_rows($res); - } - else - { - return false; - } - } - - /** - * Allows setting mssqlnative specific query options passed to sqlsrv_query as 4th parameter. - */ - function mssqlnative_set_query_options($options) - { - $this->query_options = $options; - } -} - -?> diff --git a/phpBB/includes/db/mysql.php b/phpBB/includes/db/mysql.php deleted file mode 100644 index 252cb20bd4..0000000000 --- a/phpBB/includes/db/mysql.php +++ /dev/null @@ -1,591 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - -/** -* MySQL4 Database Abstraction Layer -* Compatible with: -* MySQL 3.23+ -* MySQL 4.0+ -* MySQL 4.1+ -* MySQL 5.0+ -* @package dbal -*/ -class dbal_mysql extends dbal -{ - var $multi_insert = true; - var $connect_error = ''; - - /** - * Connect to server - * @access public - */ - function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) - { - $this->persistency = $persistency; - $this->user = $sqluser; - $this->server = $sqlserver . (($port) ? ':' . $port : ''); - $this->dbname = $database; - - $this->sql_layer = 'mysql4'; - - if ($this->persistency) - { - if (!function_exists('mysql_pconnect')) - { - $this->connect_error = 'mysql_pconnect function does not exist, is mysql extension installed?'; - return $this->sql_error(''); - } - $this->db_connect_id = @mysql_pconnect($this->server, $this->user, $sqlpassword); - } - else - { - if (!function_exists('mysql_connect')) - { - $this->connect_error = 'mysql_connect function does not exist, is mysql extension installed?'; - return $this->sql_error(''); - } - $this->db_connect_id = @mysql_connect($this->server, $this->user, $sqlpassword, $new_link); - } - - if ($this->db_connect_id && $this->dbname != '') - { - if (@mysql_select_db($this->dbname, $this->db_connect_id)) - { - // Determine what version we are using and if it natively supports UNICODE - if (version_compare($this->sql_server_info(true), '4.1.0', '>=')) - { - @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); - } - } - else if (version_compare($this->sql_server_info(true), '4.0.0', '<')) - { - $this->sql_layer = 'mysql'; - } - - return $this->db_connect_id; - } - } - - return $this->sql_error(''); - } - - /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache If true, it is safe to retrieve the value from the cache - * @return string sql server version - */ - function sql_server_info($raw = false, $use_cache = true) - { - global $cache; - - if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->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']; - - if (!empty($cache) && $use_cache) - { - $cache->put('mysql_version', $this->sql_server_version); - } - } - - return ($raw) ? $this->sql_server_version : 'MySQL ' . $this->sql_server_version; - } - - /** - * SQL Transaction - * @access private - */ - function _sql_transaction($status = 'begin') - { - switch ($status) - { - case 'begin': - return @mysql_query('BEGIN', $this->db_connect_id); - break; - - case 'commit': - return @mysql_query('COMMIT', $this->db_connect_id); - break; - - case 'rollback': - return @mysql_query('ROLLBACK', $this->db_connect_id); - break; - } - - return true; - } - - /** - * 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 - */ - 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() - { - return ($this->db_connect_id) ? @mysql_affected_rows($this->db_connect_id) : false; - } - - /** - * Fetch current row - */ - 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; - } - - /** - * Seek to given row number - * rownum is zero-based - */ - function sql_rowseek($rownum, &$query_id) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if (isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_rowseek($rownum, $query_id); - } - - return ($query_id !== false) ? @mysql_data_seek($query_id, $rownum) : false; - } - - /** - * Get last inserted id after insert statement - */ - function sql_nextid() - { - return ($this->db_connect_id) ? @mysql_insert_id($this->db_connect_id) : false; - } - - /** - * Free sql result - */ - function sql_freeresult($query_id = false) - { - 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; - } - - /** - * Escape string used in sql query - */ - function sql_escape($msg) - { - if (!$this->db_connect_id) - { - return @mysql_real_escape_string($msg); - } - - return @mysql_real_escape_string($msg, $this->db_connect_id); - } - - /** - * Gets the estimated number of rows in a specified table. - * - * @param string $table_name Table name - * - * @return string Number of rows in $table_name. - * Prefixed with ~ if estimated (otherwise exact). - * - * @access public - */ - function get_estimated_row_count($table_name) - { - $table_status = $this->get_table_status($table_name); - - if (isset($table_status['Engine'])) - { - if ($table_status['Engine'] === 'MyISAM') - { - return $table_status['Rows']; - } - else if ($table_status['Engine'] === 'InnoDB' && $table_status['Rows'] > 100000) - { - return '~' . $table_status['Rows']; - } - } - - return parent::get_row_count($table_name); - } - - /** - * Gets the exact number of rows in a specified table. - * - * @param string $table_name Table name - * - * @return string Exact number of rows in $table_name. - * - * @access public - */ - function get_row_count($table_name) - { - $table_status = $this->get_table_status($table_name); - - if (isset($table_status['Engine']) && $table_status['Engine'] === 'MyISAM') - { - return $table_status['Rows']; - } - - return parent::get_row_count($table_name); - } - - /** - * Gets some information about the specified table. - * - * @param string $table_name Table name - * - * @return array - * - * @access protected - */ - function get_table_status($table_name) - { - $sql = "SHOW TABLE STATUS - LIKE '" . $this->sql_escape($table_name) . "'"; - $result = $this->sql_query($sql); - $table_status = $this->sql_fetchrow($result); - $this->sql_freeresult($result); - - return $table_status; - } - - /** - * Build LIKE expression - * @access private - */ - function _sql_like_expression($expression) - { - return $expression; - } - - /** - * Build db-specific query data - * @access private - */ - function _sql_custom_build($stage, $data) - { - switch ($stage) - { - case 'FROM': - $data = '(' . $data . ')'; - break; - } - - return $data; - } - - /** - * return sql error array - * @access private - */ - function _sql_error() - { - if ($this->db_connect_id) - { - $error = array( - 'message' => @mysql_error($this->db_connect_id), - 'code' => @mysql_errno($this->db_connect_id), - ); - } - else if (function_exists('mysql_error')) - { - $error = array( - 'message' => @mysql_error(), - 'code' => @mysql_errno(), - ); - } - else - { - $error = array( - 'message' => $this->connect_error, - 'code' => '', - ); - } - - return $error; - } - - /** - * Close sql connection - * @access private - */ - function _sql_close() - { - return @mysql_close($this->db_connect_id); - } - - /** - * Build db-specific report - * @access private - */ - function _sql_report($mode, $query = '') - { - static $test_prof; - - // current detection method, might just switch to see the existance of INFORMATION_SCHEMA.PROFILING - if ($test_prof === null) - { - $test_prof = false; - if (version_compare($this->sql_server_info(true), '5.0.37', '>=') && version_compare($this->sql_server_info(true), '5.1', '<')) - { - $test_prof = true; - } - } - - switch ($mode) - { - case 'start': - - $explain_query = $query; - if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m)) - { - $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2]; - } - else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m)) - { - $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2]; - } - - if (preg_match('/^SELECT/', $explain_query)) - { - $html_table = false; - - // begin profiling - if ($test_prof) - { - @mysql_query('SET profiling = 1;', $this->db_connect_id); - } - - if ($result = @mysql_query("EXPLAIN $explain_query", $this->db_connect_id)) - { - while ($row = @mysql_fetch_assoc($result)) - { - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - } - @mysql_free_result($result); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - - if ($test_prof) - { - $html_table = false; - - // get the last profile - if ($result = @mysql_query('SHOW PROFILE ALL;', $this->db_connect_id)) - { - $this->html_hold .= '<br />'; - while ($row = @mysql_fetch_assoc($result)) - { - // make <unknown> HTML safe - if (!empty($row['Source_function'])) - { - $row['Source_function'] = str_replace(array('<', '>'), array('<', '>'), $row['Source_function']); - } - - // remove unsupported features - foreach ($row as $key => $val) - { - if ($val === null) - { - unset($row[$key]); - } - } - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - } - @mysql_free_result($result); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - - @mysql_query('SET profiling = 0;', $this->db_connect_id); - } - } - - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @mysql_query($query, $this->db_connect_id); - while ($void = @mysql_fetch_assoc($result)) - { - // Take the time spent on parsing rows into account - } - @mysql_free_result($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/mysqli.php deleted file mode 100644 index 69f1d26a40..0000000000 --- a/phpBB/includes/db/mysqli.php +++ /dev/null @@ -1,581 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - -/** -* MySQLi Database Abstraction Layer -* mysqli-extension has to be compiled with: -* MySQL 4.1+ or MySQL 5.0+ -* @package dbal -*/ -class dbal_mysqli extends dbal -{ - var $multi_insert = true; - var $connect_error = ''; - - /** - * Connect to server - */ - function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false , $new_link = false) - { - if (!function_exists('mysqli_connect')) - { - $this->connect_error = 'mysqli_connect function does not exist, is mysqli extension installed?'; - return $this->sql_error(''); - } - - // Mysqli extension supports persistent connection since PHP 5.3.0 - $this->persistency = (version_compare(PHP_VERSION, '5.3.0', '>=')) ? $persistency : false; - $this->user = $sqluser; - - // If persistent connection, set dbhost to localhost when empty and prepend it with 'p:' prefix - $this->server = ($this->persistency) ? 'p:' . (($sqlserver) ? $sqlserver : 'localhost') : $sqlserver; - - $this->dbname = $database; - $port = (!$port) ? NULL : $port; - - // If port is set and it is not numeric, most likely mysqli socket is set. - // Try to map it to the $socket parameter. - $socket = NULL; - if ($port) - { - if (is_numeric($port)) - { - $port = (int) $port; - } - else - { - $socket = $port; - $port = NULL; - } - } - - $this->db_connect_id = @mysqli_connect($this->server, $this->user, $sqlpassword, $this->dbname, $port, $socket); - - 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(''); - } - - /** - * Version information about used database - * @param bool $use_cache If true, it is safe to retrieve the value from the cache - * @return string sql server version - */ - function sql_server_info($raw = false, $use_cache = true) - { - global $cache; - - if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mysqli_version')) === false) - { - $result = @mysqli_query($this->db_connect_id, 'SELECT VERSION() AS version'); - $row = @mysqli_fetch_assoc($result); - @mysqli_free_result($result); - - $this->sql_server_version = $row['version']; - - if (!empty($cache) && $use_cache) - { - $cache->put('mysqli_version', $this->sql_server_version); - } - } - - return ($raw) ? $this->sql_server_version : 'MySQL(i) ' . $this->sql_server_version; - } - - /** - * SQL Transaction - * @access private - */ - function _sql_transaction($status = 'begin') - { - switch ($status) - { - case 'begin': - return @mysqli_autocommit($this->db_connect_id, false); - break; - - case 'commit': - $result = @mysqli_commit($this->db_connect_id); - @mysqli_autocommit($this->db_connect_id, true); - return $result; - break; - - case 'rollback': - $result = @mysqli_rollback($this->db_connect_id); - @mysqli_autocommit($this->db_connect_id, true); - return $result; - break; - } - - return true; - } - - /** - * 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 - */ - 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 = @mysqli_query($this->db_connect_id, $query)) === false) - { - $this->sql_error($query); - } - - if (defined('DEBUG_EXTRA')) - { - $this->sql_report('stop', $query); - } - - if ($cache_ttl && method_exists($cache, 'sql_save')) - { - $cache->sql_save($query, $this->query_result, $cache_ttl); - } - } - 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) - { - // 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); - } - - /** - * Return number of affected rows - */ - function sql_affectedrows() - { - return ($this->db_connect_id) ? @mysqli_affected_rows($this->db_connect_id) : false; - } - - /** - * Fetch current row - */ - function sql_fetchrow($query_id = false) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_fetchrow($query_id); - } - - if ($query_id !== false) - { - $result = @mysqli_fetch_assoc($query_id); - return $result !== null ? $result : false; - } - - return false; - } - - /** - * Seek to given row number - * rownum is zero-based - */ - function sql_rowseek($rownum, &$query_id) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_rowseek($rownum, $query_id); - } - - return ($query_id !== false) ? @mysqli_data_seek($query_id, $rownum) : false; - } - - /** - * Get last inserted id after insert statement - */ - function sql_nextid() - { - return ($this->db_connect_id) ? @mysqli_insert_id($this->db_connect_id) : false; - } - - /** - * Free sql result - */ - function sql_freeresult($query_id = false) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_freeresult($query_id); - } - - return @mysqli_free_result($query_id); - } - - /** - * Escape string used in sql query - */ - function sql_escape($msg) - { - return @mysqli_real_escape_string($this->db_connect_id, $msg); - } - - /** - * Gets the estimated number of rows in a specified table. - * - * @param string $table_name Table name - * - * @return string Number of rows in $table_name. - * Prefixed with ~ if estimated (otherwise exact). - * - * @access public - */ - function get_estimated_row_count($table_name) - { - $table_status = $this->get_table_status($table_name); - - if (isset($table_status['Engine'])) - { - if ($table_status['Engine'] === 'MyISAM') - { - return $table_status['Rows']; - } - else if ($table_status['Engine'] === 'InnoDB' && $table_status['Rows'] > 100000) - { - return '~' . $table_status['Rows']; - } - } - - return parent::get_row_count($table_name); - } - - /** - * Gets the exact number of rows in a specified table. - * - * @param string $table_name Table name - * - * @return string Exact number of rows in $table_name. - * - * @access public - */ - function get_row_count($table_name) - { - $table_status = $this->get_table_status($table_name); - - if (isset($table_status['Engine']) && $table_status['Engine'] === 'MyISAM') - { - return $table_status['Rows']; - } - - return parent::get_row_count($table_name); - } - - /** - * Gets some information about the specified table. - * - * @param string $table_name Table name - * - * @return array - * - * @access protected - */ - function get_table_status($table_name) - { - $sql = "SHOW TABLE STATUS - LIKE '" . $this->sql_escape($table_name) . "'"; - $result = $this->sql_query($sql); - $table_status = $this->sql_fetchrow($result); - $this->sql_freeresult($result); - - return $table_status; - } - - /** - * Build LIKE expression - * @access private - */ - function _sql_like_expression($expression) - { - return $expression; - } - - /** - * Build db-specific query data - * @access private - */ - function _sql_custom_build($stage, $data) - { - switch ($stage) - { - case 'FROM': - $data = '(' . $data . ')'; - break; - } - - return $data; - } - - /** - * return sql error array - * @access private - */ - function _sql_error() - { - if ($this->db_connect_id) - { - $error = array( - 'message' => @mysqli_error($this->db_connect_id), - 'code' => @mysqli_errno($this->db_connect_id) - ); - } - else if (function_exists('mysqli_connect_error')) - { - $error = array( - 'message' => @mysqli_connect_error(), - 'code' => @mysqli_connect_errno(), - ); - } - else - { - $error = array( - 'message' => $this->connect_error, - 'code' => '', - ); - } - - return $error; - } - - /** - * Close sql connection - * @access private - */ - function _sql_close() - { - return @mysqli_close($this->db_connect_id); - } - - /** - * Build db-specific report - * @access private - */ - function _sql_report($mode, $query = '') - { - static $test_prof; - - // 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) - { - $ver = mysqli_get_server_version($this->db_connect_id); - if ($ver >= 50037 && $ver < 50100) - { - $test_prof = true; - } - } - } - - switch ($mode) - { - case 'start': - - $explain_query = $query; - if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m)) - { - $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2]; - } - else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m)) - { - $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2]; - } - - if (preg_match('/^SELECT/', $explain_query)) - { - $html_table = false; - - // begin profiling - if ($test_prof) - { - @mysqli_query($this->db_connect_id, 'SET profiling = 1;'); - } - - if ($result = @mysqli_query($this->db_connect_id, "EXPLAIN $explain_query")) - { - 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 .= '</table>'; - } - - if ($test_prof) - { - $html_table = false; - - // get the last profile - if ($result = @mysqli_query($this->db_connect_id, 'SHOW PROFILE ALL;')) - { - $this->html_hold .= '<br />'; - while ($row = @mysqli_fetch_assoc($result)) - { - // make <unknown> HTML safe - if (!empty($row['Source_function'])) - { - $row['Source_function'] = str_replace(array('<', '>'), array('<', '>'), $row['Source_function']); - } - - // remove unsupported features - foreach ($row as $key => $val) - { - if ($val === null) - { - unset($row[$key]); - } - } - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - } - @mysqli_free_result($result); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - - @mysqli_query($this->db_connect_id, 'SET profiling = 0;'); - } - } - - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @mysqli_query($this->db_connect_id, $query); - while ($void = @mysqli_fetch_assoc($result)) - { - // Take the time spent on parsing rows into account - } - @mysqli_free_result($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/oracle.php deleted file mode 100644 index 4a7a4ecc8c..0000000000 --- a/phpBB/includes/db/oracle.php +++ /dev/null @@ -1,808 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - -/** -* Oracle Database Abstraction Layer -* @package dbal -*/ -class dbal_oracle extends dbal -{ - var $last_query_text = ''; - var $connect_error = ''; - - /** - * Connect to server - */ - function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) - { - $this->persistency = $persistency; - $this->user = $sqluser; - $this->server = $sqlserver . (($port) ? ':' . $port : ''); - $this->dbname = $database; - - $connect = $database; - - // support for "easy connect naming" - if ($sqlserver !== '' && $sqlserver !== '/') - { - if (substr($sqlserver, -1, 1) == '/') - { - $sqlserver == substr($sqlserver, 0, -1); - } - $connect = $sqlserver . (($port) ? ':' . $port : '') . '/' . $database; - } - - if ($new_link) - { - if (!function_exists('ocinlogon')) - { - $this->connect_error = 'ocinlogon function does not exist, is oci extension installed?'; - return $this->sql_error(''); - } - $this->db_connect_id = @ocinlogon($this->user, $sqlpassword, $connect, 'UTF8'); - } - else if ($this->persistency) - { - if (!function_exists('ociplogon')) - { - $this->connect_error = 'ociplogon function does not exist, is oci extension installed?'; - return $this->sql_error(''); - } - $this->db_connect_id = @ociplogon($this->user, $sqlpassword, $connect, 'UTF8'); - } - else - { - if (!function_exists('ocilogon')) - { - $this->connect_error = 'ocilogon function does not exist, is oci extension installed?'; - return $this->sql_error(''); - } - $this->db_connect_id = @ocilogon($this->user, $sqlpassword, $connect, 'UTF8'); - } - - return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); - } - - /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache forced to false for Oracle - * @return string sql server version - */ - function sql_server_info($raw = false, $use_cache = true) - { - /** - * force $use_cache false. I didn't research why the caching code below is commented out - * but I assume its because the Oracle extension provides a direct method to access it - * without a query. - */ - - $use_cache = false; -/* - global $cache; - - if (empty($cache) || ($this->sql_server_version = $cache->get('oracle_version')) === false) - { - $result = @ociparse($this->db_connect_id, 'SELECT * FROM v$version WHERE banner LIKE \'Oracle%\''); - @ociexecute($result, OCI_DEFAULT); - @ocicommit($this->db_connect_id); - - $row = array(); - @ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS); - @ocifreestatement($result); - $this->sql_server_version = trim($row['BANNER']); - - $cache->put('oracle_version', $this->sql_server_version); - } -*/ - $this->sql_server_version = @ociserverversion($this->db_connect_id); - - return $this->sql_server_version; - } - - /** - * SQL Transaction - * @access private - */ - function _sql_transaction($status = 'begin') - { - switch ($status) - { - case 'begin': - return true; - break; - - case 'commit': - return @ocicommit($this->db_connect_id); - break; - - case 'rollback': - return @ocirollback($this->db_connect_id); - break; - } - - return true; - } - - /** - * Oracle specific code to handle the fact that it does not compare columns properly - * @access private - */ - function _rewrite_col_compare($args) - { - if (sizeof($args) == 4) - { - if ($args[2] == '=') - { - return '(' . $args[0] . ' OR (' . $args[1] . ' is NULL AND ' . $args[3] . ' is NULL))'; - } - else if ($args[2] == '<>') - { - // really just a fancy way of saying foo <> bar or (foo is NULL XOR bar is NULL) but SQL has no XOR :P - return '(' . $args[0] . ' OR ((' . $args[1] . ' is NULL AND ' . $args[3] . ' is NOT NULL) OR (' . $args[1] . ' is NOT NULL AND ' . $args[3] . ' is NULL)))'; - } - } - else - { - return $this->_rewrite_where($args[0]); - } - } - - /** - * Oracle specific code to handle it's lack of sanity - * @access private - */ - function _rewrite_where($where_clause) - { - preg_match_all('/\s*(AND|OR)?\s*([\w_.()]++)\s*(?:(=|<[=>]?|>=?|LIKE)\s*((?>\'(?>[^\']++|\'\')*+\'|[\d-.()]+))|((NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]+,? ?)*+\)))/', $where_clause, $result, PREG_SET_ORDER); - $out = ''; - foreach ($result as $val) - { - if (!isset($val[5])) - { - if ($val[4] !== "''") - { - $out .= $val[0]; - } - else - { - $out .= ' ' . $val[1] . ' ' . $val[2]; - if ($val[3] == '=') - { - $out .= ' is NULL'; - } - else if ($val[3] == '<>') - { - $out .= ' is NOT NULL'; - } - } - } - else - { - $in_clause = array(); - $sub_exp = substr($val[5], strpos($val[5], '(') + 1, -1); - $extra = false; - preg_match_all('/\'(?>[^\']++|\'\')*+\'|[\d-.]++/', $sub_exp, $sub_vals, PREG_PATTERN_ORDER); - $i = 0; - foreach ($sub_vals[0] as $sub_val) - { - // two things: - // 1) This determines if an empty string was in the IN clausing, making us turn it into a NULL comparison - // 2) This fixes the 1000 list limit that Oracle has (ORA-01795) - if ($sub_val !== "''") - { - $in_clause[(int) $i++/1000][] = $sub_val; - } - else - { - $extra = true; - } - } - if (!$extra && $i < 1000) - { - $out .= $val[0]; - } - else - { - $out .= ' ' . $val[1] . '('; - $in_array = array(); - - // constuct each IN() clause - foreach ($in_clause as $in_values) - { - $in_array[] = $val[2] . ' ' . (isset($val[6]) ? $val[6] : '') . 'IN(' . implode(', ', $in_values) . ')'; - } - - // Join the IN() clauses against a few ORs (IN is just a nicer OR anyway) - $out .= implode(' OR ', $in_array); - - // handle the empty string case - if ($extra) - { - $out .= ' OR ' . $val[2] . ' is ' . (isset($val[6]) ? $val[6] : '') . 'NULL'; - } - $out .= ')'; - - unset($in_array, $in_clause); - } - } - } - - return $out; - } - - /** - * 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 - */ - 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->last_query_text = $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) - { - $in_transaction = false; - if (!$this->transaction) - { - $this->sql_transaction('begin'); - } - else - { - $in_transaction = true; - } - - $array = array(); - - // We overcome Oracle's 4000 char limit by binding vars - if (strlen($query) > 4000) - { - if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/sU', $query, $regs)) - { - if (strlen($regs[3]) > 4000) - { - $cols = explode(', ', $regs[2]); - - preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER); - -/* The code inside this comment block breaks clob handling, but does allow the - database restore script to work. If you want to allow no posts longer than 4KB - and/or need the db restore script, uncomment this. - - - if (sizeof($cols) !== sizeof($vals)) - { - // Try to replace some common data we know is from our restore script or from other sources - $regs[3] = str_replace("'||chr(47)||'", '/', $regs[3]); - $_vals = explode(', ', $regs[3]); - - $vals = array(); - $is_in_val = false; - $i = 0; - $string = ''; - - foreach ($_vals as $value) - { - if (strpos($value, "'") === false && !$is_in_val) - { - $vals[$i++] = $value; - continue; - } - - if (substr($value, -1) === "'") - { - $vals[$i] = $string . (($is_in_val) ? ', ' : '') . $value; - $string = ''; - $is_in_val = false; - - if ($vals[$i][0] !== "'") - { - $vals[$i] = "''" . $vals[$i]; - } - $i++; - continue; - } - else - { - $string .= (($is_in_val) ? ', ' : '') . $value; - $is_in_val = true; - } - } - - if ($string) - { - // New value if cols != value - $vals[(sizeof($cols) !== sizeof($vals)) ? $i : $i - 1] .= $string; - } - - $vals = array(0 => $vals); - } -*/ - - $inserts = $vals[0]; - unset($vals); - - foreach ($inserts as $key => $value) - { - if (!empty($value) && $value[0] === "'" && strlen($value) > 4002) // check to see if this thing is greater than the max + 'x2 - { - $inserts[$key] = ':' . strtoupper($cols[$key]); - $array[$inserts[$key]] = str_replace("''", "'", substr($value, 1, -1)); - } - } - - $query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')'; - } - } - else if (preg_match_all('/^(UPDATE [\\w_]++\\s+SET )([\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+)(?:,\\s*[\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+)\\s+(WHERE.*)$/s', $query, $data, PREG_SET_ORDER)) - { - if (strlen($data[0][2]) > 4000) - { - $update = $data[0][1]; - $where = $data[0][3]; - preg_match_all('/([\\w_]++)\\s*=\\s*(\'(?:[^\']++|\'\')*+\'|[\d-.]++)/', $data[0][2], $temp, PREG_SET_ORDER); - unset($data); - - $cols = array(); - foreach ($temp as $value) - { - if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 4002) // check to see if this thing is greater than the max + 'x2 - { - $cols[] = $value[1] . '=:' . strtoupper($value[1]); - $array[$value[1]] = str_replace("''", "'", substr($value[2], 1, -1)); - } - else - { - $cols[] = $value[1] . '=' . $value[2]; - } - } - - $query = $update . implode(', ', $cols) . ' ' . $where; - unset($cols); - } - } - } - - switch (substr($query, 0, 6)) - { - case 'DELETE': - if (preg_match('/^(DELETE FROM [\w_]++ WHERE)((?:\s*(?:AND|OR)?\s*[\w_]+\s*(?:(?:=|<>)\s*(?>\'(?>[^\']++|\'\')*+\'|[\d-.]+)|(?:NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]+,? ?)*+\)))*+)$/', $query, $regs)) - { - $query = $regs[1] . $this->_rewrite_where($regs[2]); - unset($regs); - } - break; - - case 'UPDATE': - if (preg_match('/^(UPDATE [\\w_]++\\s+SET [\\w_]+\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]++|:\w++)(?:, [\\w_]+\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]++|:\w++))*+\\s+WHERE)(.*)$/s', $query, $regs)) - { - $query = $regs[1] . $this->_rewrite_where($regs[2]); - unset($regs); - } - break; - - case 'SELECT': - $query = preg_replace_callback('/([\w_.]++)\s*(?:(=|<>)\s*(?>\'(?>[^\']++|\'\')*+\'|[\d-.]++|([\w_.]++))|(?:NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]++,? ?)*+\))/', array($this, '_rewrite_col_compare'), $query); - break; - } - - $this->query_result = @ociparse($this->db_connect_id, $query); - - foreach ($array as $key => $value) - { - @ocibindbyname($this->query_result, $key, $array[$key], -1); - } - - $success = @ociexecute($this->query_result, OCI_DEFAULT); - - if (!$success) - { - $this->sql_error($query); - $this->query_result = false; - } - else - { - if (!$in_transaction) - { - $this->sql_transaction('commit'); - } - } - - 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; - - $query = 'SELECT * FROM (SELECT /*+ FIRST_ROWS */ rownum AS xrownum, a.* FROM (' . $query . ') a WHERE rownum <= ' . ($offset + $total) . ') WHERE xrownum >= ' . $offset; - - return $this->sql_query($query, $cache_ttl); - } - - /** - * Return number of affected rows - */ - function sql_affectedrows() - { - return ($this->query_result) ? @ocirowcount($this->query_result) : false; - } - - /** - * Fetch current row - */ - 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); - } - - if ($query_id !== false) - { - $row = array(); - $result = @ocifetchinto($query_id, $row, OCI_ASSOC + OCI_RETURN_NULLS); - - if (!$result || !$row) - { - return false; - } - - $result_row = array(); - foreach ($row as $key => $value) - { - // Oracle treats empty strings as null - if (is_null($value)) - { - $value = ''; - } - - // OCI->CLOB? - if (is_object($value)) - { - $value = $value->load(); - } - - $result_row[strtolower($key)] = $value; - } - - return $result_row; - } - - return false; - } - - /** - * Seek to given row number - * rownum is zero-based - */ - function sql_rowseek($rownum, &$query_id) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if (isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_rowseek($rownum, $query_id); - } - - if ($query_id === false) - { - return false; - } - - // Reset internal pointer - @ociexecute($query_id, OCI_DEFAULT); - - // We do not fetch the row for rownum == 0 because then the next resultset would be the second row - for ($i = 0; $i < $rownum; $i++) - { - if (!$this->sql_fetchrow($query_id)) - { - return false; - } - } - - return true; - } - - /** - * Get last inserted id after insert statement - */ - function sql_nextid() - { - $query_id = $this->query_result; - - if ($query_id !== false && $this->last_query_text != '') - { - if (preg_match('#^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)#is', $this->last_query_text, $tablename)) - { - $query = 'SELECT ' . $tablename[1] . '_seq.currval FROM DUAL'; - $stmt = @ociparse($this->db_connect_id, $query); - @ociexecute($stmt, OCI_DEFAULT); - - $temp_result = @ocifetchinto($stmt, $temp_array, OCI_ASSOC + OCI_RETURN_NULLS); - @ocifreestatement($stmt); - - if ($temp_result) - { - return $temp_array['CURRVAL']; - } - else - { - return false; - } - } - } - - return false; - } - - /** - * Free sql result - */ - function sql_freeresult($query_id = false) - { - 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 @ocifreestatement($query_id); - } - - return false; - } - - /** - * Escape string used in sql query - */ - function sql_escape($msg) - { - return str_replace(array("'", "\0"), array("''", ''), $msg); - } - - /** - * Build LIKE expression - * @access private - */ - function _sql_like_expression($expression) - { - return $expression . " ESCAPE '\\'"; - } - - function _sql_custom_build($stage, $data) - { - return $data; - } - - function _sql_bit_and($column_name, $bit, $compare = '') - { - return 'BITAND(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : ''); - } - - function _sql_bit_or($column_name, $bit, $compare = '') - { - return 'BITOR(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : ''); - } - - /** - * return sql error array - * @access private - */ - function _sql_error() - { - if (function_exists('ocierror')) - { - $error = @ocierror(); - $error = (!$error) ? @ocierror($this->query_result) : $error; - $error = (!$error) ? @ocierror($this->db_connect_id) : $error; - - if ($error) - { - $this->last_error_result = $error; - } - else - { - $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array(); - } - } - else - { - $error = array( - 'message' => $this->connect_error, - 'code' => '', - ); - } - - return $error; - } - - /** - * Close sql connection - * @access private - */ - function _sql_close() - { - return @ocilogoff($this->db_connect_id); - } - - /** - * Build db-specific report - * @access private - */ - function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - - $html_table = false; - - // Grab a plan table, any will do - $sql = "SELECT table_name - FROM USER_TABLES - WHERE table_name LIKE '%PLAN_TABLE%'"; - $stmt = ociparse($this->db_connect_id, $sql); - ociexecute($stmt); - $result = array(); - - if (ocifetchinto($stmt, $result, OCI_ASSOC + OCI_RETURN_NULLS)) - { - $table = $result['TABLE_NAME']; - - // This is the statement_id that will allow us to track the plan - $statement_id = substr(md5($query), 0, 30); - - // Remove any stale plans - $stmt2 = ociparse($this->db_connect_id, "DELETE FROM $table WHERE statement_id='$statement_id'"); - ociexecute($stmt2); - ocifreestatement($stmt2); - - // Explain the plan - $sql = "EXPLAIN PLAN - SET STATEMENT_ID = '$statement_id' - FOR $query"; - $stmt2 = ociparse($this->db_connect_id, $sql); - ociexecute($stmt2); - ocifreestatement($stmt2); - - // Get the data from the plan - $sql = "SELECT operation, options, object_name, object_type, cardinality, cost - FROM plan_table - START WITH id = 0 AND statement_id = '$statement_id' - CONNECT BY PRIOR id = parent_id - AND statement_id = '$statement_id'"; - $stmt2 = ociparse($this->db_connect_id, $sql); - ociexecute($stmt2); - - $row = array(); - while (ocifetchinto($stmt2, $row, OCI_ASSOC + OCI_RETURN_NULLS)) - { - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - - ocifreestatement($stmt2); - - // Remove the plan we just made, we delete them on request anyway - $stmt2 = ociparse($this->db_connect_id, "DELETE FROM $table WHERE statement_id='$statement_id'"); - ociexecute($stmt2); - ocifreestatement($stmt2); - } - - ocifreestatement($stmt); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @ociparse($this->db_connect_id, $query); - $success = @ociexecute($result, OCI_DEFAULT); - $row = array(); - - while (@ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS)) - { - // Take the time spent on parsing rows into account - } - @ocifreestatement($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/postgres.php b/phpBB/includes/db/postgres.php deleted file mode 100644 index bb116e0763..0000000000 --- a/phpBB/includes/db/postgres.php +++ /dev/null @@ -1,485 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - -if (!class_exists('phpbb_error_collector')) -{ - include($phpbb_root_path . 'includes/error_collector.' . $phpEx); -} - -/** -* PostgreSQL Database Abstraction Layer -* Minimum Requirement is Version 7.3+ -* @package dbal -*/ -class dbal_postgres extends dbal -{ - var $last_query_text = ''; - var $connect_error = ''; - - /** - * Connect to server - */ - function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) - { - $connect_string = ''; - - if ($sqluser) - { - $connect_string .= "user=$sqluser "; - } - - if ($sqlpassword) - { - $connect_string .= "password=$sqlpassword "; - } - - if ($sqlserver) - { - // $sqlserver can carry a port separated by : for compatibility reasons - // If $sqlserver has more than one : it's probably an IPv6 address. - // In this case we only allow passing a port via the $port variable. - if (substr_count($sqlserver, ':') === 1) - { - list($sqlserver, $port) = explode(':', $sqlserver); - } - - if ($sqlserver !== 'localhost') - { - $connect_string .= "host=$sqlserver "; - } - - if ($port) - { - $connect_string .= "port=$port "; - } - } - - $schema = ''; - - if ($database) - { - $this->dbname = $database; - if (strpos($database, '.') !== false) - { - list($database, $schema) = explode('.', $database); - } - $connect_string .= "dbname=$database"; - } - - $this->persistency = $persistency; - - if ($this->persistency) - { - if (!function_exists('pg_pconnect')) - { - $this->connect_error = 'pg_pconnect function does not exist, is pgsql extension installed?'; - return $this->sql_error(''); - } - $collector = new phpbb_error_collector; - $collector->install(); - $this->db_connect_id = (!$new_link) ? @pg_pconnect($connect_string) : @pg_pconnect($connect_string, PGSQL_CONNECT_FORCE_NEW); - } - else - { - if (!function_exists('pg_connect')) - { - $this->connect_error = 'pg_connect function does not exist, is pgsql extension installed?'; - return $this->sql_error(''); - } - $collector = new phpbb_error_collector; - $collector->install(); - $this->db_connect_id = (!$new_link) ? @pg_connect($connect_string) : @pg_connect($connect_string, PGSQL_CONNECT_FORCE_NEW); - } - - $collector->uninstall(); - - if ($this->db_connect_id) - { - if (version_compare($this->sql_server_info(true), '8.2', '>=')) - { - $this->multi_insert = true; - } - - if ($schema !== '') - { - @pg_query($this->db_connect_id, 'SET search_path TO ' . $schema); - } - return $this->db_connect_id; - } - - $this->connect_error = $collector->format_errors(); - return $this->sql_error(''); - } - - /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache If true, it is safe to retrieve the value from the cache - * @return string sql server version - */ - function sql_server_info($raw = false, $use_cache = true) - { - global $cache; - - if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('pgsql_version')) === false) - { - $query_id = @pg_query($this->db_connect_id, 'SELECT VERSION() AS version'); - $row = @pg_fetch_assoc($query_id, null); - @pg_free_result($query_id); - - $this->sql_server_version = (!empty($row['version'])) ? trim(substr($row['version'], 10)) : 0; - - if (!empty($cache) && $use_cache) - { - $cache->put('pgsql_version', $this->sql_server_version); - } - } - - return ($raw) ? $this->sql_server_version : 'PostgreSQL ' . $this->sql_server_version; - } - - /** - * SQL Transaction - * @access private - */ - function _sql_transaction($status = 'begin') - { - switch ($status) - { - case 'begin': - return @pg_query($this->db_connect_id, 'BEGIN'); - break; - - case 'commit': - return @pg_query($this->db_connect_id, 'COMMIT'); - break; - - case 'rollback': - return @pg_query($this->db_connect_id, 'ROLLBACK'); - break; - } - - return true; - } - - /** - * 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 - */ - 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->last_query_text = $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 = @pg_query($this->db_connect_id, $query)) === 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 db-specific query data - * @access private - */ - function _sql_custom_build($stage, $data) - { - return $data; - } - - /** - * 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) - { - $total = 'ALL'; - } - - $query .= "\n LIMIT $total OFFSET $offset"; - - return $this->sql_query($query, $cache_ttl); - } - - /** - * Return number of affected rows - */ - function sql_affectedrows() - { - return ($this->query_result) ? @pg_affected_rows($this->query_result) : false; - } - - /** - * Fetch current row - */ - 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) ? @pg_fetch_assoc($query_id, null) : false; - } - - /** - * Seek to given row number - * rownum is zero-based - */ - function sql_rowseek($rownum, &$query_id) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if (isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_rowseek($rownum, $query_id); - } - - return ($query_id !== false) ? @pg_result_seek($query_id, $rownum) : false; - } - - /** - * Get last inserted id after insert statement - */ - function sql_nextid() - { - $query_id = $this->query_result; - - if ($query_id !== false && $this->last_query_text != '') - { - if (preg_match("/^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)/is", $this->last_query_text, $tablename)) - { - $query = "SELECT currval('" . $tablename[1] . "_seq') AS last_value"; - $temp_q_id = @pg_query($this->db_connect_id, $query); - - if (!$temp_q_id) - { - return false; - } - - $temp_result = @pg_fetch_assoc($temp_q_id, NULL); - @pg_free_result($query_id); - - return ($temp_result) ? $temp_result['last_value'] : false; - } - } - - return false; - } - - /** - * Free sql result - */ - function sql_freeresult($query_id = false) - { - 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 @pg_free_result($query_id); - } - - return false; - } - - /** - * Escape string used in sql query - * Note: Do not use for bytea values if we may use them at a later stage - */ - function sql_escape($msg) - { - return @pg_escape_string($msg); - } - - /** - * Build LIKE expression - * @access private - */ - function _sql_like_expression($expression) - { - return $expression; - } - - /** - * return sql error array - * @access private - */ - function _sql_error() - { - // pg_last_error only works when there is an established connection. - // Connection errors have to be tracked by us manually. - if ($this->db_connect_id) - { - $message = @pg_last_error($this->db_connect_id); - } - else - { - $message = $this->connect_error; - } - - return array( - 'message' => $message, - 'code' => '' - ); - } - - /** - * Close sql connection - * @access private - */ - function _sql_close() - { - return @pg_close($this->db_connect_id); - } - - /** - * Build db-specific report - * @access private - */ - function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - - $explain_query = $query; - if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m)) - { - $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2]; - } - else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m)) - { - $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2]; - } - - if (preg_match('/^SELECT/', $explain_query)) - { - $html_table = false; - - if ($result = @pg_query($this->db_connect_id, "EXPLAIN $explain_query")) - { - while ($row = @pg_fetch_assoc($result, NULL)) - { - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - } - @pg_free_result($result); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - } - - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @pg_query($this->db_connect_id, $query); - while ($void = @pg_fetch_assoc($result, NULL)) - { - // Take the time spent on parsing rows into account - } - @pg_free_result($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/schema_data.php b/phpBB/includes/db/schema_data.php new file mode 100644 index 0000000000..69d39e0f8c --- /dev/null +++ b/phpBB/includes/db/schema_data.php @@ -0,0 +1,1219 @@ +<?php +/** +* +* @package dbal +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +$schema_data = array(); + +/** +* Define the basic structure +* The format: +* array('{TABLE_NAME}' => {TABLE_DATA}) +* {TABLE_DATA}: +* COLUMNS = array({column_name} = array({column_type}, {default}, {auto_increment})) +* PRIMARY_KEY = {column_name(s)} +* KEYS = array({key_name} = array({key_type}, {column_name(s)})), +* +* Column Types: +* INT:x => SIGNED int(x) +* BINT => BIGINT +* UINT => mediumint(8) UNSIGNED +* UINT:x => int(x) UNSIGNED +* TINT:x => tinyint(x) +* USINT => smallint(4) UNSIGNED (for _order columns) +* BOOL => tinyint(1) UNSIGNED +* VCHAR => varchar(255) +* CHAR:x => char(x) +* XSTEXT_UNI => text for storing 100 characters (topic_title for example) +* STEXT_UNI => text for storing 255 characters (normal input field with a max of 255 single-byte chars) - same as VCHAR_UNI +* TEXT_UNI => text for storing 3000 characters (short text, descriptions, comments, etc.) +* MTEXT_UNI => mediumtext (post text, large text) +* VCHAR:x => varchar(x) +* TIMESTAMP => int(11) UNSIGNED +* DECIMAL => decimal number (5,2) +* DECIMAL: => decimal number (x,2) +* PDECIMAL => precision decimal number (6,3) +* PDECIMAL: => precision decimal number (x,3) +* VCHAR_UNI => varchar(255) BINARY +* VCHAR_CI => varchar_ci for postgresql, others VCHAR +*/ +$schema_data['phpbb_attachments'] = array( + 'COLUMNS' => array( + 'attach_id' => array('UINT', NULL, 'auto_increment'), + 'post_msg_id' => array('UINT', 0), + 'topic_id' => array('UINT', 0), + 'in_message' => array('BOOL', 0), + 'poster_id' => array('UINT', 0), + 'is_orphan' => array('BOOL', 1), + 'physical_filename' => array('VCHAR', ''), + 'real_filename' => array('VCHAR', ''), + 'download_count' => array('UINT', 0), + 'attach_comment' => array('TEXT_UNI', ''), + 'extension' => array('VCHAR:100', ''), + 'mimetype' => array('VCHAR:100', ''), + 'filesize' => array('UINT:20', 0), + 'filetime' => array('TIMESTAMP', 0), + 'thumbnail' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'attach_id', + 'KEYS' => array( + 'filetime' => array('INDEX', 'filetime'), + 'post_msg_id' => array('INDEX', 'post_msg_id'), + 'topic_id' => array('INDEX', 'topic_id'), + 'poster_id' => array('INDEX', 'poster_id'), + 'is_orphan' => array('INDEX', 'is_orphan'), + ), +); + +$schema_data['phpbb_acl_groups'] = array( + 'COLUMNS' => array( + 'group_id' => array('UINT', 0), + 'forum_id' => array('UINT', 0), + 'auth_option_id' => array('UINT', 0), + 'auth_role_id' => array('UINT', 0), + 'auth_setting' => array('TINT:2', 0), + ), + 'KEYS' => array( + 'group_id' => array('INDEX', 'group_id'), + 'auth_opt_id' => array('INDEX', 'auth_option_id'), + 'auth_role_id' => array('INDEX', 'auth_role_id'), + ), +); + +$schema_data['phpbb_acl_options'] = array( + 'COLUMNS' => array( + 'auth_option_id' => array('UINT', NULL, 'auto_increment'), + 'auth_option' => array('VCHAR:50', ''), + 'is_global' => array('BOOL', 0), + 'is_local' => array('BOOL', 0), + 'founder_only' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'auth_option_id', + 'KEYS' => array( + 'auth_option' => array('UNIQUE', 'auth_option'), + ), +); + +$schema_data['phpbb_acl_roles'] = array( + 'COLUMNS' => array( + 'role_id' => array('UINT', NULL, 'auto_increment'), + 'role_name' => array('VCHAR_UNI', ''), + 'role_description' => array('TEXT_UNI', ''), + 'role_type' => array('VCHAR:10', ''), + 'role_order' => array('USINT', 0), + ), + 'PRIMARY_KEY' => 'role_id', + 'KEYS' => array( + 'role_type' => array('INDEX', 'role_type'), + 'role_order' => array('INDEX', 'role_order'), + ), +); + +$schema_data['phpbb_acl_roles_data'] = array( + 'COLUMNS' => array( + 'role_id' => array('UINT', 0), + 'auth_option_id' => array('UINT', 0), + 'auth_setting' => array('TINT:2', 0), + ), + 'PRIMARY_KEY' => array('role_id', 'auth_option_id'), + 'KEYS' => array( + 'ath_op_id' => array('INDEX', 'auth_option_id'), + ), +); + +$schema_data['phpbb_acl_users'] = array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), + 'forum_id' => array('UINT', 0), + 'auth_option_id' => array('UINT', 0), + 'auth_role_id' => array('UINT', 0), + 'auth_setting' => array('TINT:2', 0), + ), + 'KEYS' => array( + 'user_id' => array('INDEX', 'user_id'), + 'auth_option_id' => array('INDEX', 'auth_option_id'), + 'auth_role_id' => array('INDEX', 'auth_role_id'), + ), +); + +$schema_data['phpbb_banlist'] = array( + 'COLUMNS' => array( + 'ban_id' => array('UINT', NULL, 'auto_increment'), + 'ban_userid' => array('UINT', 0), + 'ban_ip' => array('VCHAR:40', ''), + 'ban_email' => array('VCHAR_UNI:100', ''), + 'ban_start' => array('TIMESTAMP', 0), + 'ban_end' => array('TIMESTAMP', 0), + 'ban_exclude' => array('BOOL', 0), + 'ban_reason' => array('VCHAR_UNI', ''), + 'ban_give_reason' => array('VCHAR_UNI', ''), + ), + 'PRIMARY_KEY' => 'ban_id', + 'KEYS' => array( + 'ban_end' => array('INDEX', 'ban_end'), + 'ban_user' => array('INDEX', array('ban_userid', 'ban_exclude')), + 'ban_email' => array('INDEX', array('ban_email', 'ban_exclude')), + 'ban_ip' => array('INDEX', array('ban_ip', 'ban_exclude')), + ), +); + +$schema_data['phpbb_bbcodes'] = array( + 'COLUMNS' => array( + 'bbcode_id' => array('USINT', 0), + 'bbcode_tag' => array('VCHAR:16', ''), + 'bbcode_helpline' => array('VCHAR_UNI', ''), + 'display_on_posting' => array('BOOL', 0), + 'bbcode_match' => array('TEXT_UNI', ''), + 'bbcode_tpl' => array('MTEXT_UNI', ''), + 'first_pass_match' => array('MTEXT_UNI', ''), + 'first_pass_replace' => array('MTEXT_UNI', ''), + 'second_pass_match' => array('MTEXT_UNI', ''), + 'second_pass_replace' => array('MTEXT_UNI', ''), + ), + 'PRIMARY_KEY' => 'bbcode_id', + 'KEYS' => array( + 'display_on_post' => array('INDEX', 'display_on_posting'), + ), +); + +$schema_data['phpbb_bookmarks'] = array( + 'COLUMNS' => array( + 'topic_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + ), + 'PRIMARY_KEY' => array('topic_id', 'user_id'), +); + +$schema_data['phpbb_bots'] = array( + 'COLUMNS' => array( + 'bot_id' => array('UINT', NULL, 'auto_increment'), + 'bot_active' => array('BOOL', 1), + 'bot_name' => array('STEXT_UNI', ''), + 'user_id' => array('UINT', 0), + 'bot_agent' => array('VCHAR', ''), + 'bot_ip' => array('VCHAR', ''), + ), + 'PRIMARY_KEY' => 'bot_id', + 'KEYS' => array( + 'bot_active' => array('INDEX', 'bot_active'), + ), +); + +$schema_data['phpbb_config'] = array( + 'COLUMNS' => array( + 'config_name' => array('VCHAR', ''), + 'config_value' => array('VCHAR_UNI', ''), + 'is_dynamic' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'config_name', + 'KEYS' => array( + 'is_dynamic' => array('INDEX', 'is_dynamic'), + ), +); + +$schema_data['phpbb_config_text'] = array( + 'COLUMNS' => array( + 'config_name' => array('VCHAR', ''), + 'config_value' => array('MTEXT', ''), + ), + 'PRIMARY_KEY' => 'config_name', +); + +$schema_data['phpbb_confirm'] = array( + 'COLUMNS' => array( + 'confirm_id' => array('CHAR:32', ''), + 'session_id' => array('CHAR:32', ''), + 'confirm_type' => array('TINT:3', 0), + 'code' => array('VCHAR:8', ''), + 'seed' => array('UINT:10', 0), + 'attempts' => array('UINT', 0), + ), + 'PRIMARY_KEY' => array('session_id', 'confirm_id'), + 'KEYS' => array( + 'confirm_type' => array('INDEX', 'confirm_type'), + ), +); + +$schema_data['phpbb_disallow'] = array( + 'COLUMNS' => array( + 'disallow_id' => array('UINT', NULL, 'auto_increment'), + 'disallow_username' => array('VCHAR_UNI:255', ''), + ), + 'PRIMARY_KEY' => 'disallow_id', +); + +$schema_data['phpbb_drafts'] = array( + 'COLUMNS' => array( + 'draft_id' => array('UINT', NULL, 'auto_increment'), + 'user_id' => array('UINT', 0), + 'topic_id' => array('UINT', 0), + 'forum_id' => array('UINT', 0), + 'save_time' => array('TIMESTAMP', 0), + 'draft_subject' => array('STEXT_UNI', ''), + 'draft_message' => array('MTEXT_UNI', ''), + ), + 'PRIMARY_KEY' => 'draft_id', + 'KEYS' => array( + 'save_time' => array('INDEX', 'save_time'), + ), +); + +$schema_data['phpbb_ext'] = array( + 'COLUMNS' => array( + 'ext_name' => array('VCHAR', ''), + 'ext_active' => array('BOOL', 0), + 'ext_state' => array('TEXT', ''), + ), + 'KEYS' => array( + 'ext_name' => array('UNIQUE', 'ext_name'), + ), +); + +$schema_data['phpbb_extensions'] = array( + 'COLUMNS' => array( + 'extension_id' => array('UINT', NULL, 'auto_increment'), + 'group_id' => array('UINT', 0), + 'extension' => array('VCHAR:100', ''), + ), + 'PRIMARY_KEY' => 'extension_id', +); + +$schema_data['phpbb_extension_groups'] = array( + 'COLUMNS' => array( + 'group_id' => array('UINT', NULL, 'auto_increment'), + 'group_name' => array('VCHAR_UNI', ''), + 'cat_id' => array('TINT:2', 0), + 'allow_group' => array('BOOL', 0), + 'download_mode' => array('BOOL', 1), + 'upload_icon' => array('VCHAR', ''), + 'max_filesize' => array('UINT:20', 0), + 'allowed_forums' => array('TEXT', ''), + 'allow_in_pm' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'group_id', +); + +$schema_data['phpbb_forums'] = array( + 'COLUMNS' => array( + 'forum_id' => array('UINT', NULL, 'auto_increment'), + 'parent_id' => array('UINT', 0), + 'left_id' => array('UINT', 0), + 'right_id' => array('UINT', 0), + 'forum_parents' => array('MTEXT', ''), + 'forum_name' => array('STEXT_UNI', ''), + 'forum_desc' => array('TEXT_UNI', ''), + 'forum_desc_bitfield' => array('VCHAR:255', ''), + 'forum_desc_options' => array('UINT:11', 7), + 'forum_desc_uid' => array('VCHAR:8', ''), + 'forum_link' => array('VCHAR_UNI', ''), + 'forum_password' => array('VCHAR_UNI:40', ''), + 'forum_style' => array('UINT', 0), + 'forum_image' => array('VCHAR', ''), + 'forum_rules' => array('TEXT_UNI', ''), + 'forum_rules_link' => array('VCHAR_UNI', ''), + 'forum_rules_bitfield' => array('VCHAR:255', ''), + 'forum_rules_options' => array('UINT:11', 7), + 'forum_rules_uid' => array('VCHAR:8', ''), + 'forum_topics_per_page' => array('TINT:4', 0), + 'forum_type' => array('TINT:4', 0), + 'forum_status' => array('TINT:4', 0), + 'forum_posts_approved' => array('UINT', 0), + 'forum_posts_unapproved' => array('UINT', 0), + 'forum_posts_softdeleted' => array('UINT', 0), + 'forum_topics_approved' => array('UINT', 0), + 'forum_topics_unapproved' => array('UINT', 0), + 'forum_topics_softdeleted' => array('UINT', 0), + 'forum_last_post_id' => array('UINT', 0), + 'forum_last_poster_id' => array('UINT', 0), + 'forum_last_post_subject' => array('STEXT_UNI', ''), + 'forum_last_post_time' => array('TIMESTAMP', 0), + 'forum_last_poster_name'=> array('VCHAR_UNI', ''), + 'forum_last_poster_colour'=> array('VCHAR:6', ''), + 'forum_flags' => array('TINT:4', 32), + 'forum_options' => array('UINT:20', 0), + 'display_subforum_list' => array('BOOL', 1), + 'display_on_index' => array('BOOL', 1), + 'enable_indexing' => array('BOOL', 1), + 'enable_icons' => array('BOOL', 1), + 'enable_prune' => array('BOOL', 0), + 'prune_next' => array('TIMESTAMP', 0), + 'prune_days' => array('UINT', 0), + 'prune_viewed' => array('UINT', 0), + 'prune_freq' => array('UINT', 0), + ), + 'PRIMARY_KEY' => 'forum_id', + 'KEYS' => array( + 'left_right_id' => array('INDEX', array('left_id', 'right_id')), + 'forum_lastpost_id' => array('INDEX', 'forum_last_post_id'), + ), +); + +$schema_data['phpbb_forums_access'] = array( + 'COLUMNS' => array( + 'forum_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'session_id' => array('CHAR:32', ''), + ), + 'PRIMARY_KEY' => array('forum_id', 'user_id', 'session_id'), +); + +$schema_data['phpbb_forums_track'] = array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), + 'forum_id' => array('UINT', 0), + 'mark_time' => array('TIMESTAMP', 0), + ), + 'PRIMARY_KEY' => array('user_id', 'forum_id'), +); + +$schema_data['phpbb_forums_watch'] = array( + 'COLUMNS' => array( + 'forum_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'notify_status' => array('BOOL', 0), + ), + 'KEYS' => array( + 'forum_id' => array('INDEX', 'forum_id'), + 'user_id' => array('INDEX', 'user_id'), + 'notify_stat' => array('INDEX', 'notify_status'), + ), +); + +$schema_data['phpbb_groups'] = array( + 'COLUMNS' => array( + 'group_id' => array('UINT', NULL, 'auto_increment'), + 'group_type' => array('TINT:4', 1), + 'group_founder_manage' => array('BOOL', 0), + 'group_skip_auth' => array('BOOL', 0), + 'group_name' => array('VCHAR_CI', ''), + 'group_desc' => array('TEXT_UNI', ''), + 'group_desc_bitfield' => array('VCHAR:255', ''), + 'group_desc_options' => array('UINT:11', 7), + 'group_desc_uid' => array('VCHAR:8', ''), + 'group_display' => array('BOOL', 0), + 'group_avatar' => array('VCHAR', ''), + 'group_avatar_type' => array('VCHAR:255', ''), + 'group_avatar_width' => array('USINT', 0), + 'group_avatar_height' => array('USINT', 0), + 'group_rank' => array('UINT', 0), + 'group_colour' => array('VCHAR:6', ''), + 'group_sig_chars' => array('UINT', 0), + 'group_receive_pm' => array('BOOL', 0), + 'group_message_limit' => array('UINT', 0), + 'group_max_recipients' => array('UINT', 0), + 'group_legend' => array('UINT', 0), + ), + 'PRIMARY_KEY' => 'group_id', + 'KEYS' => array( + 'group_legend_name' => array('INDEX', array('group_legend', 'group_name')), + ), +); + +$schema_data['phpbb_icons'] = array( + 'COLUMNS' => array( + 'icons_id' => array('UINT', NULL, 'auto_increment'), + 'icons_url' => array('VCHAR', ''), + 'icons_width' => array('TINT:4', 0), + 'icons_height' => array('TINT:4', 0), + 'icons_order' => array('UINT', 0), + 'display_on_posting' => array('BOOL', 1), + ), + 'PRIMARY_KEY' => 'icons_id', + 'KEYS' => array( + 'display_on_posting' => array('INDEX', 'display_on_posting'), + ), +); + +$schema_data['phpbb_lang'] = array( + 'COLUMNS' => array( + 'lang_id' => array('TINT:4', NULL, 'auto_increment'), + 'lang_iso' => array('VCHAR:30', ''), + 'lang_dir' => array('VCHAR:30', ''), + 'lang_english_name' => array('VCHAR_UNI:100', ''), + 'lang_local_name' => array('VCHAR_UNI:255', ''), + 'lang_author' => array('VCHAR_UNI:255', ''), + ), + 'PRIMARY_KEY' => 'lang_id', + 'KEYS' => array( + 'lang_iso' => array('INDEX', 'lang_iso'), + ), +); + +$schema_data['phpbb_log'] = array( + 'COLUMNS' => array( + 'log_id' => array('UINT', NULL, 'auto_increment'), + 'log_type' => array('TINT:4', 0), + 'user_id' => array('UINT', 0), + 'forum_id' => array('UINT', 0), + 'topic_id' => array('UINT', 0), + 'reportee_id' => array('UINT', 0), + 'log_ip' => array('VCHAR:40', ''), + 'log_time' => array('TIMESTAMP', 0), + 'log_operation' => array('TEXT_UNI', ''), + 'log_data' => array('MTEXT_UNI', ''), + ), + 'PRIMARY_KEY' => 'log_id', + 'KEYS' => array( + 'log_type' => array('INDEX', 'log_type'), + 'log_time' => array('INDEX', 'log_time'), + 'forum_id' => array('INDEX', 'forum_id'), + 'topic_id' => array('INDEX', 'topic_id'), + 'reportee_id' => array('INDEX', 'reportee_id'), + 'user_id' => array('INDEX', 'user_id'), + ), +); + +$schema_data['phpbb_login_attempts'] = array( + 'COLUMNS' => array( + 'attempt_ip' => array('VCHAR:40', ''), + 'attempt_browser' => array('VCHAR:150', ''), + 'attempt_forwarded_for' => array('VCHAR:255', ''), + 'attempt_time' => array('TIMESTAMP', 0), + 'user_id' => array('UINT', 0), + 'username' => array('VCHAR_UNI:255', 0), + 'username_clean' => array('VCHAR_CI', 0), + ), + 'KEYS' => array( + 'att_ip' => array('INDEX', array('attempt_ip', 'attempt_time')), + 'att_for' => array('INDEX', array('attempt_forwarded_for', 'attempt_time')), + 'att_time' => array('INDEX', array('attempt_time')), + 'user_id' => array('INDEX', 'user_id'), + ), +); + +$schema_data['phpbb_moderator_cache'] = array( + 'COLUMNS' => array( + 'forum_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'username' => array('VCHAR_UNI:255', ''), + 'group_id' => array('UINT', 0), + 'group_name' => array('VCHAR_UNI', ''), + 'display_on_index' => array('BOOL', 1), + ), + 'KEYS' => array( + 'disp_idx' => array('INDEX', 'display_on_index'), + 'forum_id' => array('INDEX', 'forum_id'), + ), +); + +$schema_data['phpbb_migrations'] = array( + 'COLUMNS' => array( + 'migration_name' => array('VCHAR', ''), + 'migration_depends_on' => array('TEXT', ''), + 'migration_schema_done' => array('BOOL', 0), + 'migration_data_done' => array('BOOL', 0), + 'migration_data_state' => array('TEXT', ''), + 'migration_start_time' => array('TIMESTAMP', 0), + 'migration_end_time' => array('TIMESTAMP', 0), + ), + 'PRIMARY_KEY' => 'migration_name', +); + +$schema_data['phpbb_modules'] = array( + 'COLUMNS' => array( + 'module_id' => array('UINT', NULL, 'auto_increment'), + 'module_enabled' => array('BOOL', 1), + 'module_display' => array('BOOL', 1), + 'module_basename' => array('VCHAR', ''), + 'module_class' => array('VCHAR:10', ''), + 'parent_id' => array('UINT', 0), + 'left_id' => array('UINT', 0), + 'right_id' => array('UINT', 0), + 'module_langname' => array('VCHAR', ''), + 'module_mode' => array('VCHAR', ''), + 'module_auth' => array('VCHAR', ''), + ), + 'PRIMARY_KEY' => 'module_id', + 'KEYS' => array( + 'left_right_id' => array('INDEX', array('left_id', 'right_id')), + 'module_enabled' => array('INDEX', 'module_enabled'), + 'class_left_id' => array('INDEX', array('module_class', 'left_id')), + ), +); + +$schema_data['phpbb_notification_types'] = array( + 'COLUMNS' => array( + 'notification_type_id' => array('USINT', NULL, 'auto_increment'), + 'notification_type_name' => array('VCHAR:255', ''), + 'notification_type_enabled' => array('BOOL', 1), + ), + 'PRIMARY_KEY' => array('notification_type_id'), + 'KEYS' => array( + 'type' => array('UNIQUE', array('notification_type_name')), + ), +); + +$schema_data['phpbb_notifications'] = array( + 'COLUMNS' => array( + 'notification_id' => array('UINT:10', NULL, 'auto_increment'), + 'notification_type_id' => array('USINT', 0), + 'item_id' => array('UINT', 0), + 'item_parent_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'notification_read' => array('BOOL', 0), + 'notification_time' => array('TIMESTAMP', 1), + 'notification_data' => array('TEXT_UNI', ''), + ), + 'PRIMARY_KEY' => 'notification_id', + 'KEYS' => array( + 'item_ident' => array('INDEX', array('notification_type_id', 'item_id')), + 'user' => array('INDEX', array('user_id', 'notification_read')), + ), +); + +$schema_data['phpbb_oauth_accounts'] = array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), + 'provider' => array('VCHAR', ''), + 'oauth_provider_id' => array('TEXT_UNI', ''), + ), + 'PRIMARY_KEY' => array( + 'user_id', + 'provider', + ), +); + +$schema_data['phpbb_oauth_tokens'] = array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), // phpbb_users.user_id + 'session_id' => array('CHAR:32', ''), // phpbb_sessions.session_id used only when user_id not set + 'provider' => array('VCHAR', ''), // Name of the OAuth provider + 'oauth_token' => array('MTEXT', ''), // Serialized token + ), + 'KEYS' => array( + 'user_id' => array('INDEX', 'user_id'), + 'provider' => array('INDEX', 'provider'), + ), +); + +$schema_data['phpbb_poll_options'] = array( + 'COLUMNS' => array( + 'poll_option_id' => array('TINT:4', 0), + 'topic_id' => array('UINT', 0), + 'poll_option_text' => array('TEXT_UNI', ''), + 'poll_option_total' => array('UINT', 0), + ), + 'KEYS' => array( + 'poll_opt_id' => array('INDEX', 'poll_option_id'), + 'topic_id' => array('INDEX', 'topic_id'), + ), +); + +$schema_data['phpbb_poll_votes'] = array( + 'COLUMNS' => array( + 'topic_id' => array('UINT', 0), + 'poll_option_id' => array('TINT:4', 0), + 'vote_user_id' => array('UINT', 0), + 'vote_user_ip' => array('VCHAR:40', ''), + ), + 'KEYS' => array( + 'topic_id' => array('INDEX', 'topic_id'), + 'vote_user_id' => array('INDEX', 'vote_user_id'), + 'vote_user_ip' => array('INDEX', 'vote_user_ip'), + ), +); + +$schema_data['phpbb_posts'] = array( + 'COLUMNS' => array( + 'post_id' => array('UINT', NULL, 'auto_increment'), + 'topic_id' => array('UINT', 0), + 'forum_id' => array('UINT', 0), + 'poster_id' => array('UINT', 0), + 'icon_id' => array('UINT', 0), + 'poster_ip' => array('VCHAR:40', ''), + 'post_time' => array('TIMESTAMP', 0), + 'post_visibility' => array('TINT:3', 0), + 'post_reported' => array('BOOL', 0), + 'enable_bbcode' => array('BOOL', 1), + 'enable_smilies' => array('BOOL', 1), + 'enable_magic_url' => array('BOOL', 1), + 'enable_sig' => array('BOOL', 1), + 'post_username' => array('VCHAR_UNI:255', ''), + 'post_subject' => array('STEXT_UNI', '', 'true_sort'), + 'post_text' => array('MTEXT_UNI', ''), + 'post_checksum' => array('VCHAR:32', ''), + 'post_attachment' => array('BOOL', 0), + 'bbcode_bitfield' => array('VCHAR:255', ''), + 'bbcode_uid' => array('VCHAR:8', ''), + 'post_postcount' => array('BOOL', 1), + 'post_edit_time' => array('TIMESTAMP', 0), + 'post_edit_reason' => array('STEXT_UNI', ''), + 'post_edit_user' => array('UINT', 0), + 'post_edit_count' => array('USINT', 0), + 'post_edit_locked' => array('BOOL', 0), + 'post_delete_time' => array('TIMESTAMP', 0), + 'post_delete_reason' => array('STEXT_UNI', ''), + 'post_delete_user' => array('UINT', 0), + ), + 'PRIMARY_KEY' => 'post_id', + 'KEYS' => array( + 'forum_id' => array('INDEX', 'forum_id'), + 'topic_id' => array('INDEX', 'topic_id'), + 'poster_ip' => array('INDEX', 'poster_ip'), + 'poster_id' => array('INDEX', 'poster_id'), + 'post_visibility' => array('INDEX', 'post_visibility'), + 'post_username' => array('INDEX', 'post_username'), + 'tid_post_time' => array('INDEX', array('topic_id', 'post_time')), + ), +); + +$schema_data['phpbb_privmsgs'] = array( + 'COLUMNS' => array( + 'msg_id' => array('UINT', NULL, 'auto_increment'), + 'root_level' => array('UINT', 0), + 'author_id' => array('UINT', 0), + 'icon_id' => array('UINT', 0), + 'author_ip' => array('VCHAR:40', ''), + 'message_time' => array('TIMESTAMP', 0), + 'enable_bbcode' => array('BOOL', 1), + 'enable_smilies' => array('BOOL', 1), + 'enable_magic_url' => array('BOOL', 1), + 'enable_sig' => array('BOOL', 1), + 'message_subject' => array('STEXT_UNI', ''), + 'message_text' => array('MTEXT_UNI', ''), + 'message_edit_reason' => array('STEXT_UNI', ''), + 'message_edit_user' => array('UINT', 0), + 'message_attachment' => array('BOOL', 0), + 'bbcode_bitfield' => array('VCHAR:255', ''), + 'bbcode_uid' => array('VCHAR:8', ''), + 'message_edit_time' => array('TIMESTAMP', 0), + 'message_edit_count' => array('USINT', 0), + 'to_address' => array('TEXT_UNI', ''), + 'bcc_address' => array('TEXT_UNI', ''), + 'message_reported' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'msg_id', + 'KEYS' => array( + 'author_ip' => array('INDEX', 'author_ip'), + 'message_time' => array('INDEX', 'message_time'), + 'author_id' => array('INDEX', 'author_id'), + 'root_level' => array('INDEX', 'root_level'), + ), +); + +$schema_data['phpbb_privmsgs_folder'] = array( + 'COLUMNS' => array( + 'folder_id' => array('UINT', NULL, 'auto_increment'), + 'user_id' => array('UINT', 0), + 'folder_name' => array('VCHAR_UNI', ''), + 'pm_count' => array('UINT', 0), + ), + 'PRIMARY_KEY' => 'folder_id', + 'KEYS' => array( + 'user_id' => array('INDEX', 'user_id'), + ), +); + +$schema_data['phpbb_privmsgs_rules'] = array( + 'COLUMNS' => array( + 'rule_id' => array('UINT', NULL, 'auto_increment'), + 'user_id' => array('UINT', 0), + 'rule_check' => array('UINT', 0), + 'rule_connection' => array('UINT', 0), + 'rule_string' => array('VCHAR_UNI', ''), + 'rule_user_id' => array('UINT', 0), + 'rule_group_id' => array('UINT', 0), + 'rule_action' => array('UINT', 0), + 'rule_folder_id' => array('INT:11', 0), + ), + 'PRIMARY_KEY' => 'rule_id', + 'KEYS' => array( + 'user_id' => array('INDEX', 'user_id'), + ), +); + +$schema_data['phpbb_privmsgs_to'] = array( + 'COLUMNS' => array( + 'msg_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'author_id' => array('UINT', 0), + 'pm_deleted' => array('BOOL', 0), + 'pm_new' => array('BOOL', 1), + 'pm_unread' => array('BOOL', 1), + 'pm_replied' => array('BOOL', 0), + 'pm_marked' => array('BOOL', 0), + 'pm_forwarded' => array('BOOL', 0), + 'folder_id' => array('INT:11', 0), + ), + 'KEYS' => array( + 'msg_id' => array('INDEX', 'msg_id'), + 'author_id' => array('INDEX', 'author_id'), + 'usr_flder_id' => array('INDEX', array('user_id', 'folder_id')), + ), +); + +$schema_data['phpbb_profile_fields'] = array( + 'COLUMNS' => array( + 'field_id' => array('UINT', NULL, 'auto_increment'), + 'field_name' => array('VCHAR_UNI', ''), + 'field_type' => array('TINT:4', 0), + 'field_ident' => array('VCHAR:20', ''), + 'field_length' => array('VCHAR:20', ''), + 'field_minlen' => array('VCHAR', ''), + 'field_maxlen' => array('VCHAR', ''), + 'field_novalue' => array('VCHAR_UNI', ''), + 'field_default_value' => array('VCHAR_UNI', ''), + 'field_validation' => array('VCHAR_UNI:20', ''), + 'field_required' => array('BOOL', 0), + 'field_show_novalue' => array('BOOL', 0), + 'field_show_on_reg' => array('BOOL', 0), + 'field_show_on_pm' => array('BOOL', 0), + 'field_show_on_vt' => array('BOOL', 0), + 'field_show_profile' => array('BOOL', 0), + 'field_hide' => array('BOOL', 0), + 'field_no_view' => array('BOOL', 0), + 'field_active' => array('BOOL', 0), + 'field_order' => array('UINT', 0), + ), + 'PRIMARY_KEY' => 'field_id', + 'KEYS' => array( + 'fld_type' => array('INDEX', 'field_type'), + 'fld_ordr' => array('INDEX', 'field_order'), + ), +); + +$schema_data['phpbb_profile_fields_data'] = array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), + ), + 'PRIMARY_KEY' => 'user_id', +); + +$schema_data['phpbb_profile_fields_lang'] = array( + 'COLUMNS' => array( + 'field_id' => array('UINT', 0), + 'lang_id' => array('UINT', 0), + 'option_id' => array('UINT', 0), + 'field_type' => array('TINT:4', 0), + 'lang_value' => array('VCHAR_UNI', ''), + ), + 'PRIMARY_KEY' => array('field_id', 'lang_id', 'option_id'), +); + +$schema_data['phpbb_profile_lang'] = array( + 'COLUMNS' => array( + 'field_id' => array('UINT', 0), + 'lang_id' => array('UINT', 0), + 'lang_name' => array('VCHAR_UNI', ''), + 'lang_explain' => array('TEXT_UNI', ''), + 'lang_default_value' => array('VCHAR_UNI', ''), + ), + 'PRIMARY_KEY' => array('field_id', 'lang_id'), +); + +$schema_data['phpbb_ranks'] = array( + 'COLUMNS' => array( + 'rank_id' => array('UINT', NULL, 'auto_increment'), + 'rank_title' => array('VCHAR_UNI', ''), + 'rank_min' => array('UINT', 0), + 'rank_special' => array('BOOL', 0), + 'rank_image' => array('VCHAR', ''), + ), + 'PRIMARY_KEY' => 'rank_id', +); + +$schema_data['phpbb_reports'] = array( + 'COLUMNS' => array( + 'report_id' => array('UINT', NULL, 'auto_increment'), + 'reason_id' => array('USINT', 0), + 'post_id' => array('UINT', 0), + 'pm_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'user_notify' => array('BOOL', 0), + 'report_closed' => array('BOOL', 0), + 'report_time' => array('TIMESTAMP', 0), + 'report_text' => array('MTEXT_UNI', ''), + 'reported_post_text' => array('MTEXT_UNI', ''), + 'reported_post_uid' => array('VCHAR:8', ''), + 'reported_post_bitfield' => array('VCHAR:255', ''), + 'reported_post_enable_magic_url' => array('BOOL', 1), + 'reported_post_enable_smilies' => array('BOOL', 1), + 'reported_post_enable_bbcode' => array('BOOL', 1) + ), + 'PRIMARY_KEY' => 'report_id', + 'KEYS' => array( + 'post_id' => array('INDEX', 'post_id'), + 'pm_id' => array('INDEX', 'pm_id'), + ), +); + +$schema_data['phpbb_reports_reasons'] = array( + 'COLUMNS' => array( + 'reason_id' => array('USINT', NULL, 'auto_increment'), + 'reason_title' => array('VCHAR_UNI', ''), + 'reason_description' => array('MTEXT_UNI', ''), + 'reason_order' => array('USINT', 0), + ), + 'PRIMARY_KEY' => 'reason_id', +); + +$schema_data['phpbb_search_results'] = array( + 'COLUMNS' => array( + 'search_key' => array('VCHAR:32', ''), + 'search_time' => array('TIMESTAMP', 0), + 'search_keywords' => array('MTEXT_UNI', ''), + 'search_authors' => array('MTEXT', ''), + ), + 'PRIMARY_KEY' => 'search_key', +); + +$schema_data['phpbb_search_wordlist'] = array( + 'COLUMNS' => array( + 'word_id' => array('UINT', NULL, 'auto_increment'), + 'word_text' => array('VCHAR_UNI', ''), + 'word_common' => array('BOOL', 0), + 'word_count' => array('UINT', 0), + ), + 'PRIMARY_KEY' => 'word_id', + 'KEYS' => array( + 'wrd_txt' => array('UNIQUE', 'word_text'), + 'wrd_cnt' => array('INDEX', 'word_count'), + ), +); + +$schema_data['phpbb_search_wordmatch'] = array( + 'COLUMNS' => array( + 'post_id' => array('UINT', 0), + 'word_id' => array('UINT', 0), + 'title_match' => array('BOOL', 0), + ), + 'KEYS' => array( + 'unq_mtch' => array('UNIQUE', array('word_id', 'post_id', 'title_match')), + 'word_id' => array('INDEX', 'word_id'), + 'post_id' => array('INDEX', 'post_id'), + ), +); + +$schema_data['phpbb_sessions'] = array( + 'COLUMNS' => array( + 'session_id' => array('CHAR:32', ''), + 'session_user_id' => array('UINT', 0), + 'session_forum_id' => array('UINT', 0), + 'session_last_visit' => array('TIMESTAMP', 0), + 'session_start' => array('TIMESTAMP', 0), + 'session_time' => array('TIMESTAMP', 0), + 'session_ip' => array('VCHAR:40', ''), + 'session_browser' => array('VCHAR:150', ''), + 'session_forwarded_for' => array('VCHAR:255', ''), + 'session_page' => array('VCHAR_UNI', ''), + 'session_viewonline' => array('BOOL', 1), + 'session_autologin' => array('BOOL', 0), + 'session_admin' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'session_id', + 'KEYS' => array( + 'session_time' => array('INDEX', 'session_time'), + 'session_user_id' => array('INDEX', 'session_user_id'), + 'session_fid' => array('INDEX', 'session_forum_id'), + ), +); + +$schema_data['phpbb_sessions_keys'] = array( + 'COLUMNS' => array( + 'key_id' => array('CHAR:32', ''), + 'user_id' => array('UINT', 0), + 'last_ip' => array('VCHAR:40', ''), + 'last_login' => array('TIMESTAMP', 0), + ), + 'PRIMARY_KEY' => array('key_id', 'user_id'), + 'KEYS' => array( + 'last_login' => array('INDEX', 'last_login'), + ), +); + +$schema_data['phpbb_sitelist'] = array( + 'COLUMNS' => array( + 'site_id' => array('UINT', NULL, 'auto_increment'), + 'site_ip' => array('VCHAR:40', ''), + 'site_hostname' => array('VCHAR', ''), + 'ip_exclude' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => 'site_id', +); + +$schema_data['phpbb_smilies'] = array( + 'COLUMNS' => array( + 'smiley_id' => array('UINT', NULL, 'auto_increment'), + // We may want to set 'code' to VCHAR:50 or check if unicode support is possible... at the moment only ASCII characters are allowed. + 'code' => array('VCHAR_UNI:50', ''), + 'emotion' => array('VCHAR_UNI:50', ''), + 'smiley_url' => array('VCHAR:50', ''), + 'smiley_width' => array('USINT', 0), + 'smiley_height' => array('USINT', 0), + 'smiley_order' => array('UINT', 0), + 'display_on_posting'=> array('BOOL', 1), + ), + 'PRIMARY_KEY' => 'smiley_id', + 'KEYS' => array( + 'display_on_post' => array('INDEX', 'display_on_posting'), + ), +); + +$schema_data['phpbb_styles'] = array( + 'COLUMNS' => array( + 'style_id' => array('UINT', NULL, 'auto_increment'), + 'style_name' => array('VCHAR_UNI:255', ''), + 'style_copyright' => array('VCHAR_UNI', ''), + 'style_active' => array('BOOL', 1), + 'style_path' => array('VCHAR:100', ''), + 'bbcode_bitfield' => array('VCHAR:255', 'kNg='), + 'style_parent_id' => array('UINT:4', 0), + 'style_parent_tree' => array('TEXT', ''), + ), + 'PRIMARY_KEY' => 'style_id', + 'KEYS' => array( + 'style_name' => array('UNIQUE', 'style_name'), + ), +); + +$schema_data['phpbb_teampage'] = array( + 'COLUMNS' => array( + 'teampage_id' => array('UINT', NULL, 'auto_increment'), + 'group_id' => array('UINT', 0), + 'teampage_name' => array('VCHAR_UNI:255', ''), + 'teampage_position' => array('UINT', 0), + 'teampage_parent' => array('UINT', 0), + ), + 'PRIMARY_KEY' => 'teampage_id', +); + +$schema_data['phpbb_topics'] = array( + 'COLUMNS' => array( + 'topic_id' => array('UINT', NULL, 'auto_increment'), + 'forum_id' => array('UINT', 0), + 'icon_id' => array('UINT', 0), + 'topic_attachment' => array('BOOL', 0), + 'topic_visibility' => array('TINT:3', 0), + 'topic_reported' => array('BOOL', 0), + 'topic_title' => array('STEXT_UNI', '', 'true_sort'), + 'topic_poster' => array('UINT', 0), + 'topic_time' => array('TIMESTAMP', 0), + 'topic_time_limit' => array('TIMESTAMP', 0), + 'topic_views' => array('UINT', 0), + 'topic_posts_approved' => array('UINT', 0), + 'topic_posts_unapproved' => array('UINT', 0), + 'topic_posts_softdeleted' => array('UINT', 0), + 'topic_status' => array('TINT:3', 0), + 'topic_type' => array('TINT:3', 0), + 'topic_first_post_id' => array('UINT', 0), + 'topic_first_poster_name' => array('VCHAR_UNI', ''), + 'topic_first_poster_colour' => array('VCHAR:6', ''), + 'topic_last_post_id' => array('UINT', 0), + 'topic_last_poster_id' => array('UINT', 0), + 'topic_last_poster_name' => array('VCHAR_UNI', ''), + 'topic_last_poster_colour' => array('VCHAR:6', ''), + 'topic_last_post_subject' => array('STEXT_UNI', ''), + 'topic_last_post_time' => array('TIMESTAMP', 0), + 'topic_last_view_time' => array('TIMESTAMP', 0), + 'topic_moved_id' => array('UINT', 0), + 'topic_bumped' => array('BOOL', 0), + 'topic_bumper' => array('UINT', 0), + 'poll_title' => array('STEXT_UNI', ''), + 'poll_start' => array('TIMESTAMP', 0), + 'poll_length' => array('TIMESTAMP', 0), + 'poll_max_options' => array('TINT:4', 1), + 'poll_last_vote' => array('TIMESTAMP', 0), + 'poll_vote_change' => array('BOOL', 0), + 'topic_delete_time' => array('TIMESTAMP', 0), + 'topic_delete_reason' => array('STEXT_UNI', ''), + 'topic_delete_user' => array('UINT', 0), + ), + 'PRIMARY_KEY' => 'topic_id', + 'KEYS' => array( + 'forum_id' => array('INDEX', 'forum_id'), + 'forum_id_type' => array('INDEX', array('forum_id', 'topic_type')), + 'last_post_time' => array('INDEX', 'topic_last_post_time'), + 'topic_visibility' => array('INDEX', 'topic_visibility'), + 'forum_appr_last' => array('INDEX', array('forum_id', 'topic_visibility', 'topic_last_post_id')), + 'fid_time_moved' => array('INDEX', array('forum_id', 'topic_last_post_time', 'topic_moved_id')), + ), +); + +$schema_data['phpbb_topics_track'] = array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), + 'topic_id' => array('UINT', 0), + 'forum_id' => array('UINT', 0), + 'mark_time' => array('TIMESTAMP', 0), + ), + 'PRIMARY_KEY' => array('user_id', 'topic_id'), + 'KEYS' => array( + 'topic_id' => array('INDEX', 'topic_id'), + 'forum_id' => array('INDEX', 'forum_id'), + ), +); + +$schema_data['phpbb_topics_posted'] = array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), + 'topic_id' => array('UINT', 0), + 'topic_posted' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => array('user_id', 'topic_id'), +); + +$schema_data['phpbb_topics_watch'] = array( + 'COLUMNS' => array( + 'topic_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'notify_status' => array('BOOL', 0), + ), + 'KEYS' => array( + 'topic_id' => array('INDEX', 'topic_id'), + 'user_id' => array('INDEX', 'user_id'), + 'notify_stat' => array('INDEX', 'notify_status'), + ), +); + +$schema_data['phpbb_user_notifications'] = array( + 'COLUMNS' => array( + 'item_type' => array('VCHAR:255', ''), + 'item_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'method' => array('VCHAR:255', ''), + 'notify' => array('BOOL', 1), + ), +); + +$schema_data['phpbb_user_group'] = array( + 'COLUMNS' => array( + 'group_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'group_leader' => array('BOOL', 0), + 'user_pending' => array('BOOL', 1), + ), + 'KEYS' => array( + 'group_id' => array('INDEX', 'group_id'), + 'user_id' => array('INDEX', 'user_id'), + 'group_leader' => array('INDEX', 'group_leader'), + ), +); + +$schema_data['phpbb_users'] = array( + 'COLUMNS' => array( + 'user_id' => array('UINT', NULL, 'auto_increment'), + 'user_type' => array('TINT:2', 0), + 'group_id' => array('UINT', 3), + 'user_permissions' => array('MTEXT', ''), + 'user_perm_from' => array('UINT', 0), + 'user_ip' => array('VCHAR:40', ''), + 'user_regdate' => array('TIMESTAMP', 0), + 'username' => array('VCHAR_CI', ''), + 'username_clean' => array('VCHAR_CI', ''), + 'user_password' => array('VCHAR_UNI:40', ''), + 'user_passchg' => array('TIMESTAMP', 0), + 'user_pass_convert' => array('BOOL', 0), + 'user_email' => array('VCHAR_UNI:100', ''), + 'user_email_hash' => array('BINT', 0), + 'user_birthday' => array('VCHAR:10', ''), + 'user_lastvisit' => array('TIMESTAMP', 0), + 'user_lastmark' => array('TIMESTAMP', 0), + 'user_lastpost_time' => array('TIMESTAMP', 0), + 'user_lastpage' => array('VCHAR_UNI:200', ''), + 'user_last_confirm_key' => array('VCHAR:10', ''), + 'user_last_search' => array('TIMESTAMP', 0), + 'user_warnings' => array('TINT:4', 0), + 'user_last_warning' => array('TIMESTAMP', 0), + 'user_login_attempts' => array('TINT:4', 0), + 'user_inactive_reason' => array('TINT:2', 0), + 'user_inactive_time' => array('TIMESTAMP', 0), + 'user_posts' => array('UINT', 0), + 'user_lang' => array('VCHAR:30', ''), + 'user_timezone' => array('VCHAR:100', 'UTC'), + 'user_dateformat' => array('VCHAR_UNI:30', 'd M Y H:i'), + 'user_style' => array('UINT', 0), + 'user_rank' => array('UINT', 0), + 'user_colour' => array('VCHAR:6', ''), + 'user_new_privmsg' => array('INT:4', 0), + 'user_unread_privmsg' => array('INT:4', 0), + 'user_last_privmsg' => array('TIMESTAMP', 0), + 'user_message_rules' => array('BOOL', 0), + 'user_full_folder' => array('INT:11', -3), + 'user_emailtime' => array('TIMESTAMP', 0), + 'user_topic_show_days' => array('USINT', 0), + 'user_topic_sortby_type' => array('VCHAR:1', 't'), + 'user_topic_sortby_dir' => array('VCHAR:1', 'd'), + 'user_post_show_days' => array('USINT', 0), + 'user_post_sortby_type' => array('VCHAR:1', 't'), + 'user_post_sortby_dir' => array('VCHAR:1', 'a'), + 'user_notify' => array('BOOL', 0), + 'user_notify_pm' => array('BOOL', 1), + 'user_notify_type' => array('TINT:4', 0), + 'user_allow_pm' => array('BOOL', 1), + 'user_allow_viewonline' => array('BOOL', 1), + 'user_allow_viewemail' => array('BOOL', 1), + 'user_allow_massemail' => array('BOOL', 1), + 'user_options' => array('UINT:11', 230271), + 'user_avatar' => array('VCHAR', ''), + 'user_avatar_type' => array('VCHAR:255', ''), + 'user_avatar_width' => array('USINT', 0), + 'user_avatar_height' => array('USINT', 0), + 'user_sig' => array('MTEXT_UNI', ''), + 'user_sig_bbcode_uid' => array('VCHAR:8', ''), + 'user_sig_bbcode_bitfield' => array('VCHAR:255', ''), + 'user_from' => array('VCHAR_UNI:100', ''), + 'user_icq' => array('VCHAR:15', ''), + 'user_aim' => array('VCHAR_UNI', ''), + 'user_yim' => array('VCHAR_UNI', ''), + 'user_msnm' => array('VCHAR_UNI', ''), + 'user_jabber' => array('VCHAR_UNI', ''), + 'user_website' => array('VCHAR_UNI:200', ''), + 'user_occ' => array('TEXT_UNI', ''), + 'user_interests' => array('TEXT_UNI', ''), + 'user_actkey' => array('VCHAR:32', ''), + 'user_newpasswd' => array('VCHAR_UNI:40', ''), + 'user_form_salt' => array('VCHAR_UNI:32', ''), + 'user_new' => array('BOOL', 1), + 'user_reminded' => array('TINT:4', 0), + 'user_reminded_time' => array('TIMESTAMP', 0), + ), + 'PRIMARY_KEY' => 'user_id', + 'KEYS' => array( + 'user_birthday' => array('INDEX', 'user_birthday'), + 'user_email_hash' => array('INDEX', 'user_email_hash'), + 'user_type' => array('INDEX', 'user_type'), + 'username_clean' => array('UNIQUE', 'username_clean'), + ), +); + +$schema_data['phpbb_warnings'] = array( + 'COLUMNS' => array( + 'warning_id' => array('UINT', NULL, 'auto_increment'), + 'user_id' => array('UINT', 0), + 'post_id' => array('UINT', 0), + 'log_id' => array('UINT', 0), + 'warning_time' => array('TIMESTAMP', 0), + ), + 'PRIMARY_KEY' => 'warning_id', +); + +$schema_data['phpbb_words'] = array( + 'COLUMNS' => array( + 'word_id' => array('UINT', NULL, 'auto_increment'), + 'word' => array('VCHAR_UNI', ''), + 'replacement' => array('VCHAR_UNI', ''), + ), + 'PRIMARY_KEY' => 'word_id', +); + +$schema_data['phpbb_zebra'] = array( + 'COLUMNS' => array( + 'user_id' => array('UINT', 0), + 'zebra_id' => array('UINT', 0), + 'friend' => array('BOOL', 0), + 'foe' => array('BOOL', 0), + ), + 'PRIMARY_KEY' => array('user_id', 'zebra_id'), +); diff --git a/phpBB/includes/db/sqlite.php b/phpBB/includes/db/sqlite.php deleted file mode 100644 index 557b057cce..0000000000 --- a/phpBB/includes/db/sqlite.php +++ /dev/null @@ -1,370 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - -/** -* Sqlite Database Abstraction Layer -* Minimum Requirement: 2.8.2+ -* @package dbal -*/ -class dbal_sqlite extends dbal -{ - var $connect_error = ''; - - /** - * Connect to server - */ - function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) - { - $this->persistency = $persistency; - $this->user = $sqluser; - $this->server = $sqlserver . (($port) ? ':' . $port : ''); - $this->dbname = $database; - - $error = ''; - if ($this->persistency) - { - if (!function_exists('sqlite_popen')) - { - $this->connect_error = 'sqlite_popen function does not exist, is sqlite extension installed?'; - return $this->sql_error(''); - } - $this->db_connect_id = @sqlite_popen($this->server, 0666, $error); - } - else - { - if (!function_exists('sqlite_open')) - { - $this->connect_error = 'sqlite_open function does not exist, is sqlite extension installed?'; - return $this->sql_error(''); - } - $this->db_connect_id = @sqlite_open($this->server, 0666, $error); - } - - if ($this->db_connect_id) - { - @sqlite_query('PRAGMA short_column_names = 1', $this->db_connect_id); -// @sqlite_query('PRAGMA encoding = "UTF-8"', $this->db_connect_id); - } - - return ($this->db_connect_id) ? true : array('message' => $error); - } - - /** - * Version information about used database - * @param bool $raw if true, only return the fetched sql_server_version - * @param bool $use_cache if true, it is safe to retrieve the stored value from the cache - * @return string sql server version - */ - function sql_server_info($raw = false, $use_cache = true) - { - global $cache; - - if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('sqlite_version')) === false) - { - $result = @sqlite_query('SELECT sqlite_version() AS version', $this->db_connect_id); - $row = @sqlite_fetch_array($result, SQLITE_ASSOC); - - $this->sql_server_version = (!empty($row['version'])) ? $row['version'] : 0; - - if (!empty($cache) && $use_cache) - { - $cache->put('sqlite_version', $this->sql_server_version); - } - } - - return ($raw) ? $this->sql_server_version : 'SQLite ' . $this->sql_server_version; - } - - /** - * SQL Transaction - * @access private - */ - function _sql_transaction($status = 'begin') - { - switch ($status) - { - case 'begin': - return @sqlite_query('BEGIN', $this->db_connect_id); - break; - - case 'commit': - return @sqlite_query('COMMIT', $this->db_connect_id); - break; - - case 'rollback': - return @sqlite_query('ROLLBACK', $this->db_connect_id); - break; - } - - return true; - } - - /** - * 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 - */ - 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 = @sqlite_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) - { - $total = -1; - } - - $query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total); - - return $this->sql_query($query, $cache_ttl); - } - - /** - * Return number of affected rows - */ - function sql_affectedrows() - { - return ($this->db_connect_id) ? @sqlite_changes($this->db_connect_id) : false; - } - - /** - * Fetch current row - */ - 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) ? @sqlite_fetch_array($query_id, SQLITE_ASSOC) : false; - } - - /** - * Seek to given row number - * rownum is zero-based - */ - function sql_rowseek($rownum, &$query_id) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if (isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_rowseek($rownum, $query_id); - } - - return ($query_id !== false) ? @sqlite_seek($query_id, $rownum) : false; - } - - /** - * Get last inserted id after insert statement - */ - function sql_nextid() - { - return ($this->db_connect_id) ? @sqlite_last_insert_rowid($this->db_connect_id) : false; - } - - /** - * Free sql result - */ - function sql_freeresult($query_id = false) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if (isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_freeresult($query_id); - } - - return true; - } - - /** - * Escape string used in sql query - */ - function sql_escape($msg) - { - return @sqlite_escape_string($msg); - } - - /** - * Correctly adjust LIKE expression for special characters - * For SQLite an underscore is a not-known character... this may change with SQLite3 - */ - function sql_like_expression($expression) - { - // Unlike LIKE, GLOB is case sensitive (unfortunatly). SQLite users need to live with it! - // We only catch * and ? here, not the character map possible on file globbing. - $expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression); - - $expression = str_replace(array('?', '*'), array("\?", "\*"), $expression); - $expression = str_replace(array(chr(0) . "\?", chr(0) . "\*"), array('?', '*'), $expression); - - return 'GLOB \'' . $this->sql_escape($expression) . '\''; - } - - /** - * return sql error array - * @access private - */ - function _sql_error() - { - if (function_exists('sqlite_error_string')) - { - $error = array( - 'message' => @sqlite_error_string(@sqlite_last_error($this->db_connect_id)), - 'code' => @sqlite_last_error($this->db_connect_id), - ); - } - else - { - $error = array( - 'message' => $this->connect_error, - 'code' => '', - ); - } - - return $error; - } - - /** - * Build db-specific query data - * @access private - */ - function _sql_custom_build($stage, $data) - { - return $data; - } - - /** - * Close sql connection - * @access private - */ - function _sql_close() - { - return @sqlite_close($this->db_connect_id); - } - - /** - * Build db-specific report - * @access private - */ - function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @sqlite_query($query, $this->db_connect_id); - while ($void = @sqlite_fetch_array($result, SQLITE_ASSOC)) - { - // Take the time spent on parsing rows into account - } - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file |