diff options
Diffstat (limited to 'phpBB/includes/db')
-rw-r--r-- | phpBB/includes/db/db_tools.php | 69 | ||||
-rw-r--r-- | phpBB/includes/db/firebird.php | 11 | ||||
-rw-r--r-- | phpBB/includes/db/mssql.php | 7 | ||||
-rw-r--r-- | phpBB/includes/db/mssql_odbc.php | 7 | ||||
-rw-r--r-- | phpBB/includes/db/mssqlnative.php | 641 | ||||
-rw-r--r-- | phpBB/includes/db/mysql.php | 7 | ||||
-rw-r--r-- | phpBB/includes/db/mysqli.php | 8 | ||||
-rw-r--r-- | phpBB/includes/db/oracle.php | 15 | ||||
-rw-r--r-- | phpBB/includes/db/postgres.php | 21 | ||||
-rw-r--r-- | phpBB/includes/db/sqlite.php | 11 |
10 files changed, 771 insertions, 26 deletions
diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index 7123c83e51..f4b181c6ad 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -160,6 +160,36 @@ class phpbb_db_tools '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)', @@ -261,7 +291,7 @@ class phpbb_db_tools * 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', 'mysql_40', 'mysql_41', 'oracle', 'postgres', 'sqlite'); + 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). @@ -307,6 +337,10 @@ class phpbb_db_tools $this->sql_layer = 'mssql'; break; + case 'mssqlnative': + $this->sql_layer = 'mssqlnative'; + break; + default: $this->sql_layer = $this->db->sql_layer; break; @@ -368,6 +402,7 @@ class phpbb_db_tools switch ($this->sql_layer) { case 'mssql': + case 'mssqlnative': $table_sql = 'CREATE TABLE [' . $table_name . '] (' . "\n"; break; @@ -386,6 +421,7 @@ class phpbb_db_tools switch ($this->sql_layer) { case 'mssql': + case 'mssqlnative': $columns[] = "\t [{$column_name}] " . $prepared_column['column_type_sql_default']; break; @@ -425,6 +461,7 @@ class phpbb_db_tools break; case 'mssql': + case 'mssqlnative': $table_sql .= "\n) ON [PRIMARY]" . (($create_textimage) ? ' TEXTIMAGE_ON [PRIMARY]' : ''); $statements[] = $table_sql; break; @@ -453,6 +490,7 @@ class phpbb_db_tools case 'firebird': case 'mssql': + case 'mssqlnative': // We need the data here $old_return_statements = $this->return_statements; $this->return_statements = true; @@ -573,7 +611,7 @@ class phpbb_db_tools * drop_columns: Removing/Dropping columns * add_primary_keys: adding primary keys * add_unique_index: adding an unique index - * add_index: adding an 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( @@ -970,6 +1008,7 @@ class phpbb_db_tools // 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 @@ -1187,6 +1226,7 @@ class phpbb_db_tools break; case 'mssql': + case 'mssqlnative': $sql .= " {$column_type} "; $sql_default = " {$column_type} "; @@ -1335,6 +1375,7 @@ class phpbb_db_tools break; case 'mssql': + case 'mssqlnative': $statements[] = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql_default']; break; @@ -1455,6 +1496,7 @@ class phpbb_db_tools break; case 'mssql': + case 'mssqlnative': $statements[] = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']'; break; @@ -1549,6 +1591,7 @@ class phpbb_db_tools switch ($this->sql_layer) { case 'mssql': + case 'mssqlnative': $statements[] = 'DROP INDEX ' . $table_name . '.' . $index_name; break; @@ -1652,6 +1695,7 @@ class phpbb_db_tools 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) . ']'; @@ -1745,6 +1789,7 @@ class phpbb_db_tools break; case 'mssql': + case 'mssqlnative': $statements[] = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]'; break; } @@ -1759,6 +1804,12 @@ class phpbb_db_tools { $statements = array(); + // remove index length unless MySQL4 + if ('mysql_40' != $this->sql_layer) + { + $column = preg_replace('#:.*$#', '', $column); + } + switch ($this->sql_layer) { case 'firebird': @@ -1769,11 +1820,22 @@ class phpbb_db_tools 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[] = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; break; case 'mssql': + case 'mssqlnative': $statements[] = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]'; break; } @@ -1791,7 +1853,7 @@ class phpbb_db_tools { $index_array = array(); - if ($this->sql_layer == 'mssql') + if ($this->sql_layer == 'mssql' || $this->sql_layer == 'mssqlnative') { $sql = "EXEC sp_statistics '$table_name'"; $result = $this->db->sql_query($sql); @@ -1900,6 +1962,7 @@ class phpbb_db_tools break; case 'mssql': + case 'mssqlnative': $statements[] = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql']; if (!empty($column_data['default'])) diff --git a/phpBB/includes/db/firebird.php b/phpBB/includes/db/firebird.php index e554b0f2fb..6f60dd5dad 100644 --- a/phpBB/includes/db/firebird.php +++ b/phpBB/includes/db/firebird.php @@ -63,10 +63,19 @@ class dbal_firebird extends dbal /** * 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) + 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); diff --git a/phpBB/includes/db/mssql.php b/phpBB/includes/db/mssql.php index 7134574691..6899a73902 100644 --- a/phpBB/includes/db/mssql.php +++ b/phpBB/includes/db/mssql.php @@ -65,13 +65,14 @@ class dbal_mssql extends dbal /** * 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) + function sql_server_info($raw = false, $use_cache = true) { global $cache; - if (empty($cache) || ($this->sql_server_version = $cache->get('mssql_version')) === false) + 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); @@ -84,7 +85,7 @@ class dbal_mssql extends dbal $this->sql_server_version = ($row) ? trim(implode(' ', $row)) : 0; - if (!empty($cache)) + if (!empty($cache) && $use_cache) { $cache->put('mssql_version', $this->sql_server_version); } diff --git a/phpBB/includes/db/mssql_odbc.php b/phpBB/includes/db/mssql_odbc.php index 14c4831010..75a080b1b7 100644 --- a/phpBB/includes/db/mssql_odbc.php +++ b/phpBB/includes/db/mssql_odbc.php @@ -76,13 +76,14 @@ class dbal_mssql_odbc extends dbal /** * 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) + function sql_server_info($raw = false, $use_cache = true) { global $cache; - if (empty($cache) || ($this->sql_server_version = $cache->get('mssqlodbc_version')) === false) + 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')"); @@ -95,7 +96,7 @@ class dbal_mssql_odbc extends dbal $this->sql_server_version = ($row) ? trim(implode(' ', $row)) : 0; - if (!empty($cache)) + if (!empty($cache) && $use_cache) { $cache->put('mssqlodbc_version', $this->sql_server_version); } diff --git a/phpBB/includes/db/mssqlnative.php b/phpBB/includes/db/mssqlnative.php new file mode 100644 index 0000000000..7ed4146f27 --- /dev/null +++ b/phpBB/includes/db/mssqlnative.php @@ -0,0 +1,641 @@ +<?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 = count($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(); + + /** + * 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')) + { + trigger_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\n', E_USER_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 + error_reporting(E_ALL); + $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'; + } + + /** + * 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 ($this->db_connect_id) ? @sqlsrv_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 = @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 $row; + } + + /** + * Seek to given row number + * rownum is zero-based + */ + function sql_rowseek($rownum, &$query_id) + { + global $cache; + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($rownum, $query_id); + } + + $seek = new result_mssqlnative($query_id); + $row = $seek->seek($rownum); + return ($row = $seek->fetch()) ? $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); + } + + /** + * Build LIKE expression + * @access private + */ + function _sql_like_expression($expression) + { + return $expression . " ESCAPE '\\'"; + } + + /** + * return sql error array + * @access private + */ + function _sql_error() + { + $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(); + } + + return array( + 'message' => $error, + 'code' => $code, + ); + } + + /** + * 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 index 0487dfa6d2..1e24c79577 100644 --- a/phpBB/includes/db/mysql.php +++ b/phpBB/includes/db/mysql.php @@ -96,13 +96,14 @@ class dbal_mysql extends dbal /** * 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) + function sql_server_info($raw = false, $use_cache = true) { global $cache; - if (empty($cache) || ($this->sql_server_version = $cache->get('mysql_version')) === false) + 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); @@ -110,7 +111,7 @@ class dbal_mysql extends dbal $this->sql_server_version = $row['version']; - if (!empty($cache)) + if (!empty($cache) && $use_cache) { $cache->put('mysql_version', $this->sql_server_version); } diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/mysqli.php index f0e58fd148..862d62f4ba 100644 --- a/phpBB/includes/db/mysqli.php +++ b/phpBB/includes/db/mysqli.php @@ -80,14 +80,14 @@ class dbal_mysqli extends dbal /** * 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) + function sql_server_info($raw = false, $use_cache = true) { global $cache; - if (empty($cache) || ($this->sql_server_version = $cache->get('mysqli_version')) === false) + 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); @@ -95,7 +95,7 @@ class dbal_mysqli extends dbal $this->sql_server_version = $row['version']; - if (!empty($cache)) + if (!empty($cache) && $use_cache) { $cache->put('mysqli_version', $this->sql_server_version); } diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/oracle.php index 55b3599800..c8a9a5f604 100644 --- a/phpBB/includes/db/oracle.php +++ b/phpBB/includes/db/oracle.php @@ -56,10 +56,18 @@ class dbal_oracle extends dbal /** * 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) + 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; @@ -261,6 +269,10 @@ class dbal_oracle extends dbal { $cols = explode(', ', $regs[2]); +/* 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. + preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER); if (sizeof($cols) !== sizeof($vals)) @@ -310,6 +322,7 @@ class dbal_oracle extends dbal $vals = array(0 => $vals); } +*/ $inserts = $vals[0]; unset($vals); diff --git a/phpBB/includes/db/postgres.php b/phpBB/includes/db/postgres.php index d117e8c948..4360c790a1 100644 --- a/phpBB/includes/db/postgres.php +++ b/phpBB/includes/db/postgres.php @@ -46,7 +46,10 @@ class dbal_postgres extends dbal if ($sqlserver) { - if (strpos($sqlserver, ':') !== false) + // $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); } @@ -76,7 +79,14 @@ class dbal_postgres extends dbal $this->persistency = $persistency; - $this->db_connect_id = ($this->persistency) ? @pg_pconnect($connect_string, $new_link) : @pg_connect($connect_string, $new_link); + if ($this->persistency) + { + $this->db_connect_id = (!$new_link) ? @pg_pconnect($connect_string) : @pg_pconnect($connect_string, PGSQL_CONNECT_FORCE_NEW); + } + else + { + $this->db_connect_id = (!$new_link) ? @pg_connect($connect_string) : @pg_connect($connect_string, PGSQL_CONNECT_FORCE_NEW); + } if ($this->db_connect_id) { @@ -98,13 +108,14 @@ class dbal_postgres extends dbal /** * 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) + function sql_server_info($raw = false, $use_cache = true) { global $cache; - if (empty($cache) || ($this->sql_server_version = $cache->get('pgsql_version')) === false) + 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); @@ -112,7 +123,7 @@ class dbal_postgres extends dbal $this->sql_server_version = (!empty($row['version'])) ? trim(substr($row['version'], 10)) : 0; - if (!empty($cache)) + if (!empty($cache) && $use_cache) { $cache->put('pgsql_version', $this->sql_server_version); } diff --git a/phpBB/includes/db/sqlite.php b/phpBB/includes/db/sqlite.php index 288f6e0992..8de72fd394 100644 --- a/phpBB/includes/db/sqlite.php +++ b/phpBB/includes/db/sqlite.php @@ -50,19 +50,24 @@ class dbal_sqlite extends dbal /** * 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) + function sql_server_info($raw = false, $use_cache = true) { global $cache; - if (empty($cache) || ($this->sql_server_version = $cache->get('sqlite_version')) === false) + 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; - $cache->put('sqlite_version', $this->sql_server_version); + + if (!empty($cache) && $use_cache) + { + $cache->put('sqlite_version', $this->sql_server_version); + } } return ($raw) ? $this->sql_server_version : 'SQLite ' . $this->sql_server_version; |