From 7030578bbe9e11c18b5becaf8b06e670e3c2e3cd Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sun, 14 Jul 2013 01:32:34 -0400 Subject: [ticket/11698] Moving all autoloadable files to phpbb/ PHPBB3-11698 --- phpBB/phpbb/db/driver/driver.php | 1044 +++++++++++++++++++++++++++++++++ phpBB/phpbb/db/driver/firebird.php | 538 +++++++++++++++++ phpBB/phpbb/db/driver/mssql.php | 472 +++++++++++++++ phpBB/phpbb/db/driver/mssql_base.php | 65 ++ phpBB/phpbb/db/driver/mssql_odbc.php | 383 ++++++++++++ phpBB/phpbb/db/driver/mssqlnative.php | 613 +++++++++++++++++++ phpBB/phpbb/db/driver/mysql.php | 472 +++++++++++++++ phpBB/phpbb/db/driver/mysql_base.php | 145 +++++ phpBB/phpbb/db/driver/mysqli.php | 463 +++++++++++++++ phpBB/phpbb/db/driver/oracle.php | 803 +++++++++++++++++++++++++ phpBB/phpbb/db/driver/postgres.php | 491 ++++++++++++++++ phpBB/phpbb/db/driver/sqlite.php | 365 ++++++++++++ 12 files changed, 5854 insertions(+) create mode 100644 phpBB/phpbb/db/driver/driver.php create mode 100644 phpBB/phpbb/db/driver/firebird.php create mode 100644 phpBB/phpbb/db/driver/mssql.php create mode 100644 phpBB/phpbb/db/driver/mssql_base.php create mode 100644 phpBB/phpbb/db/driver/mssql_odbc.php create mode 100644 phpBB/phpbb/db/driver/mssqlnative.php create mode 100644 phpBB/phpbb/db/driver/mysql.php create mode 100644 phpBB/phpbb/db/driver/mysql_base.php create mode 100644 phpBB/phpbb/db/driver/mysqli.php create mode 100644 phpBB/phpbb/db/driver/oracle.php create mode 100644 phpBB/phpbb/db/driver/postgres.php create mode 100644 phpBB/phpbb/db/driver/sqlite.php (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php new file mode 100644 index 0000000000..08c966c07a --- /dev/null +++ b/phpBB/phpbb/db/driver/driver.php @@ -0,0 +1,1044 @@ +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), strlen('phpbb_db_driver_')); + + // 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 ($cache && $cache->sql_exists($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 ($cache && !is_object($query_id) && $cache->sql_exists($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) . '\''); + } + + /** + * Build a case expression + * + * Note: The two statements action_true and action_false must have the same data type (int, vchar, ...) in the database! + * + * @param string $condition The condition which must be true, to use action_true rather then action_else + * @param string $action_true SQL expression that is used, if the condition is true + * @param string $action_else SQL expression that is used, if the condition is false, optional + * @return string CASE expression including the condition and statements + */ + public function sql_case($condition, $action_true, $action_false = false) + { + $sql_case = 'CASE WHEN ' . $condition; + $sql_case .= ' THEN ' . $action_true; + $sql_case .= ($action_false !== false) ? ' ELSE ' . $action_false : ''; + $sql_case .= ' END'; + return $sql_case; + } + + /** + * Build a concatenated expression + * + * @param string $expr1 Base SQL expression where we append the second one + * @param string $expr2 SQL expression that is appended to the first expression + * @return string Concatenated string + */ + public function sql_concatenate($expr1, $expr2) + { + return $expr1 . ' || ' . $expr2; + } + + /** + * 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 : ''); + } + + /** + * Returns SQL string to cast a string expression to an int. + * + * @param string $expression An expression evaluating to string + * @return string Expression returning an int + */ + function cast_expr_to_bigint($expression) + { + return $expression; + } + + /** + * Returns SQL string to cast an integer expression to a string. + * + * @param string $expression An expression evaluating to int + * @return string Expression returning a string + */ + function cast_expr_to_string($expression) + { + return $expression; + } + + /** + * 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 . ' ]

' . $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 constant is for development only! + if ((isset($auth) && $auth->acl_get('a_')) || defined('IN_INSTALL') || defined('DEBUG')) + { + $message .= ($sql) ? '

SQL

' . 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 .= '

An sql error occurred while fetching this page. Please contact an administrator if this problem persists.'; + } + else + { + if (!empty($config['board_contact'])) + { + $message .= '

' . sprintf($user->lang['SQL_ERROR_OCCURRED'], '', ''); + } + else + { + $message .= '

' . 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, $phpbb_admin_path, $user; + global $request; + + if (is_object($request) && !$request->variable('explain', false)) + { + 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 ' + + + + SQL Report + + + +
+ +
+
+
+ +
+

SQL Report

+
+

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' : '') . '

+ +

Time spent on ' . $this->sql_layer . ' queries: ' . round($this->sql_time, 5) . 's | Time spent on PHP: ' . round($totaltime - $this->sql_time, 5) . 's

+ +

+ ' . $this->sql_report . ' +
+ +
+
+
+ +
+ + '; + + exit_handler(); + + break; + + case 'stop': + $endtime = explode(' ', microtime()); + $endtime = $endtime[0] + $endtime[1]; + + $this->sql_report .= ' + + + + + + + + + + + + +
Query #' . $this->num_queries['total'] . '
+ + ' . $this->html_hold . ' + +

+ '; + + if ($this->query_result) + { + if (preg_match('/^(UPDATE|DELETE|REPLACE)/', $query)) + { + $this->sql_report .= 'Affected rows: ' . $this->sql_affectedrows($this->query_result) . ' | '; + } + $this->sql_report .= 'Before: ' . sprintf('%.5f', $this->curtime - $starttime) . 's | After: ' . sprintf('%.5f', $endtime - $starttime) . 's | Elapsed: ' . sprintf('%.5f', $endtime - $this->curtime) . 's'; + } + else + { + $error = $this->sql_error(); + $this->sql_report .= 'FAILED - ' . $this->sql_layer . ' Error ' . $error['code'] . ': ' . htmlspecialchars($error['message']); + } + + $this->sql_report .= '



'; + + $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 .= ''; + + foreach (array_keys($row) as $val) + { + $this->html_hold .= ''; + } + $this->html_hold .= ''; + } + $this->html_hold .= ''; + + $class = 'row1'; + foreach (array_values($row) as $val) + { + $class = ($class == 'row1') ? 'row2' : 'row1'; + $this->html_hold .= ''; + } + $this->html_hold .= ''; + + 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 .= '
' . (($val) ? ucwords(str_replace('_', ' ', $val)) : ' ') . '
' . (($val) ? $val : ' ') . '
'; + $this->sql_report .= '
Query results obtained from the cache
'; + $this->sql_report .= '

'; + $this->sql_report .= 'Before: ' . sprintf('%.5f', $this->curtime - $starttime) . 's | After: ' . sprintf('%.5f', $endtime - $starttime) . 's | Elapsed [cache]: ' . sprintf('%.5f', ($time_cache)) . 's | Elapsed [db]: ' . sprintf('%.5f', $time_db) . 's



'; + + // 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; + } +} diff --git a/phpBB/phpbb/db/driver/firebird.php b/phpBB/phpbb/db/driver/firebird.php new file mode 100644 index 0000000000..787c28b812 --- /dev/null +++ b/phpBB/phpbb/db/driver/firebird.php @@ -0,0 +1,538 @@ +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')) + { + $this->sql_report('start', $query); + } + + $this->last_query_text = $query; + $this->query_result = ($cache && $cache_ttl) ? $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')) + { + $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 && $cache_ttl) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $this->query_result = $cache->sql_save($this, $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')) + { + $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 ($cache && $cache->sql_exists($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 ($cache && $cache->sql_exists($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 : ''); + } + + /** + * @inheritdoc + */ + function cast_expr_to_bigint($expression) + { + // Precision must be from 1 to 18 + return 'CAST(' . $expression . ' as DECIMAL(18, 0))'; + } + + /** + * @inheritdoc + */ + function cast_expr_to_string($expression) + { + return 'CAST(' . $expression . ' as VARCHAR(255))'; + } + + /** + * 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; + } + } +} diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php new file mode 100644 index 0000000000..89c2c2351b --- /dev/null +++ b/phpBB/phpbb/db/driver/mssql.php @@ -0,0 +1,472 @@ +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); + + $this->db_connect_id = ($this->persistency) ? @mssql_pconnect($this->server, $this->user, $sqlpassword, $new_link) : @mssql_connect($this->server, $this->user, $sqlpassword, $new_link); + + 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
' . $this->sql_server_version : 'MSSQL'; + } + + /** + * {@inheritDoc} + */ + public function sql_concatenate($expr1, $expr2) + { + return $expr1 . ' + ' . $expr2; + } + + /** + * 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')) + { + $this->sql_report('start', $query); + } + + $this->query_result = ($cache && $cache_ttl) ? $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')) + { + $this->sql_report('stop', $query); + } + + if ($cache && $cache_ttl) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $this->query_result = $cache->sql_save($this, $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')) + { + $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 ($cache && $cache->sql_exists($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 ($cache && $cache->sql_exists($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 ($cache && $cache->sql_exists($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'] .= '
' . $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 .= ''; + } + 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; + } + } +} diff --git a/phpBB/phpbb/db/driver/mssql_base.php b/phpBB/phpbb/db/driver/mssql_base.php new file mode 100644 index 0000000000..56c111c871 --- /dev/null +++ b/phpBB/phpbb/db/driver/mssql_base.php @@ -0,0 +1,65 @@ +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)
' . $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')) + { + $this->sql_report('start', $query); + } + + $this->last_query_text = $query; + $this->query_result = ($cache && $cache_ttl) ? $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')) + { + $this->sql_report('stop', $query); + } + + if ($cache && $cache_ttl) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $this->query_result = $cache->sql_save($this, $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')) + { + $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) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if ($cache && $cache->sql_exists($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 ($cache && $cache->sql_exists($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; + } + + /** + * 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; + } + } +} diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php new file mode 100644 index 0000000000..28fc88298a --- /dev/null +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -0,0 +1,613 @@ +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 phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base +{ + 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
' . $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')) + { + $this->sql_report('start', $query); + } + + $this->last_query_text = $query; + $this->query_result = ($cache && $cache_ttl) ? $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')) + { + $this->sql_report('stop', $query); + } + + if ($cache && $cache_ttl) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $this->query_result = $cache->sql_save($this, $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')) + { + $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->query_result) : false; + } + + /** + * Fetch current row + */ + function sql_fetchrow($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if ($cache && $cache->sql_exists($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 ($cache->sql_exists($query_id)) + { + return $cache->sql_freeresult($query_id); + } + + if (isset($this->open_queries[(int) $query_id])) + { + unset($this->open_queries[(int) $query_id]); + return @sqlsrv_free_stmt($query_id); + } + return false; + } + + /** + * 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; + } + + /** + * 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 .= ''; + } + 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/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php new file mode 100644 index 0000000000..f3744ac09d --- /dev/null +++ b/phpBB/phpbb/db/driver/mysql.php @@ -0,0 +1,472 @@ +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')) + { + $this->sql_report('start', $query); + } + + $this->query_result = ($cache && $cache_ttl) ? $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')) + { + $this->sql_report('stop', $query); + } + + if ($cache && $cache_ttl) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $this->query_result = $cache->sql_save($this, $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')) + { + $this->sql_report('fromcache', $query); + } + } + else + { + return false; + } + + return $this->query_result; + } + + /** + * 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 ($cache && $cache->sql_exists($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 ($cache && $cache->sql_exists($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 ($cache && $cache->sql_exists($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); + } + + /** + * 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 .= ''; + } + + if ($test_prof) + { + $html_table = false; + + // get the last profile + if ($result = @mysql_query('SHOW PROFILE ALL;', $this->db_connect_id)) + { + $this->html_hold .= '
'; + while ($row = @mysql_fetch_assoc($result)) + { + // make 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 .= ''; + } + + @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; + } + } +} diff --git a/phpBB/phpbb/db/driver/mysql_base.php b/phpBB/phpbb/db/driver/mysql_base.php new file mode 100644 index 0000000000..ba44ea61aa --- /dev/null +++ b/phpBB/phpbb/db/driver/mysql_base.php @@ -0,0 +1,145 @@ +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); + } + + /** + * 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; + } +} diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php new file mode 100644 index 0000000000..0f7a73ee6e --- /dev/null +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -0,0 +1,463 @@ +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 $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('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')) + { + $this->sql_report('start', $query); + } + + $this->query_result = ($cache && $cache_ttl) ? $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')) + { + $this->sql_report('stop', $query); + } + + if ($cache && $cache_ttl) + { + $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); + } + } + else if (defined('DEBUG')) + { + $this->sql_report('fromcache', $query); + } + } + else + { + return false; + } + + return $this->query_result; + } + + /** + * 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 ($cache && !is_object($query_id) && $cache->sql_exists($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 ($cache && !is_object($query_id) && $cache->sql_exists($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 ($cache && !is_object($query_id) && $cache->sql_exists($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); + } + + /** + * 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 .= ''; + } + + if ($test_prof) + { + $html_table = false; + + // get the last profile + if ($result = @mysqli_query($this->db_connect_id, 'SHOW PROFILE ALL;')) + { + $this->html_hold .= '
'; + while ($row = @mysqli_fetch_assoc($result)) + { + // make 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 .= ''; + } + + @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; + } + } +} diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php new file mode 100644 index 0000000000..e21e07055d --- /dev/null +++ b/phpBB/phpbb/db/driver/oracle.php @@ -0,0 +1,803 @@ +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')) + { + $this->sql_report('start', $query); + } + + $this->last_query_text = $query; + $this->query_result = ($cache && $cache_ttl) ? $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')) + { + $this->sql_report('stop', $query); + } + + if ($cache && $cache_ttl) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $this->query_result = $cache->sql_save($this, $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')) + { + $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 ($cache && $cache->sql_exists($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 ($cache && $cache->sql_exists($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 ($cache && $cache->sql_exists($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 .= ''; + } + + 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; + } + } +} diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php new file mode 100644 index 0000000000..14854d179d --- /dev/null +++ b/phpBB/phpbb/db/driver/postgres.php @@ -0,0 +1,491 @@ +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')) + { + $this->sql_report('start', $query); + } + + $this->last_query_text = $query; + $this->query_result = ($cache && $cache_ttl) ? $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')) + { + $this->sql_report('stop', $query); + } + + if ($cache && $cache_ttl) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $this->query_result = $cache->sql_save($this, $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')) + { + $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 ($cache && $cache->sql_exists($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 ($cache && $cache->sql_exists($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 ($cache && $cache->sql_exists($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; + } + + /** + * @inheritdoc + */ + function cast_expr_to_bigint($expression) + { + return 'CAST(' . $expression . ' as DECIMAL(255, 0))'; + } + + /** + * @inheritdoc + */ + function cast_expr_to_string($expression) + { + return 'CAST(' . $expression . ' as VARCHAR(255))'; + } + + /** + * 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 .= ''; + } + } + + 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; + } + } +} diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php new file mode 100644 index 0000000000..7188f0daa2 --- /dev/null +++ b/phpBB/phpbb/db/driver/sqlite.php @@ -0,0 +1,365 @@ +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')) + { + $this->sql_report('start', $query); + } + + $this->query_result = ($cache && $cache_ttl) ? $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')) + { + $this->sql_report('stop', $query); + } + + if ($cache && $cache_ttl) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $this->query_result = $cache->sql_save($this, $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')) + { + $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 ($cache && $cache->sql_exists($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 ($cache && $cache->sql_exists($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 ($cache && $cache->sql_exists($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; + } + } +} -- cgit v1.2.1 From b95fdacdd378877d277e261465da73deb06e50da Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Tue, 10 Sep 2013 14:01:09 +0200 Subject: [ticket/11700] Move all recent code to namespaces PHPBB3-11700 --- phpBB/phpbb/db/driver/driver.php | 8 +++++--- phpBB/phpbb/db/driver/firebird.php | 4 +++- phpBB/phpbb/db/driver/mssql.php | 4 +++- phpBB/phpbb/db/driver/mssql_base.php | 4 +++- phpBB/phpbb/db/driver/mssql_odbc.php | 4 +++- phpBB/phpbb/db/driver/mssqlnative.php | 6 ++++-- phpBB/phpbb/db/driver/mysql.php | 4 +++- phpBB/phpbb/db/driver/mysql_base.php | 4 +++- phpBB/phpbb/db/driver/mysqli.php | 4 +++- phpBB/phpbb/db/driver/oracle.php | 4 +++- phpBB/phpbb/db/driver/postgres.php | 8 +++++--- phpBB/phpbb/db/driver/sqlite.php | 4 +++- 12 files changed, 41 insertions(+), 17 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 08c966c07a..a266b2aa48 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\db\driver; + /** * @ignore */ @@ -19,7 +21,7 @@ if (!defined('IN_PHPBB')) * Database Abstraction Layer * @package dbal */ -class phpbb_db_driver +class driver { var $db_connect_id; var $query_result; @@ -272,7 +274,7 @@ class phpbb_db_driver * 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 + * @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) @@ -450,7 +452,7 @@ class phpbb_db_driver * @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. + * @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) { diff --git a/phpBB/phpbb/db/driver/firebird.php b/phpBB/phpbb/db/driver/firebird.php index 787c28b812..2df5eaf369 100644 --- a/phpBB/phpbb/db/driver/firebird.php +++ b/phpBB/phpbb/db/driver/firebird.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\db\driver; + /** * @ignore */ @@ -20,7 +22,7 @@ if (!defined('IN_PHPBB')) * Minimum Requirement is Firebird 2.1 * @package dbal */ -class phpbb_db_driver_firebird extends phpbb_db_driver +class firebird extends \phpbb\db\driver\driver { var $last_query_text = ''; var $service_handle = false; diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php index 89c2c2351b..4d2cd287da 100644 --- a/phpBB/phpbb/db/driver/mssql.php +++ b/phpBB/phpbb/db/driver/mssql.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\db\driver; + /** * @ignore */ @@ -20,7 +22,7 @@ if (!defined('IN_PHPBB')) * Minimum Requirement is MSSQL 2000+ * @package dbal */ -class phpbb_db_driver_mssql extends phpbb_db_driver +class mssql extends \phpbb\db\driver\driver { var $connect_error = ''; diff --git a/phpBB/phpbb/db/driver/mssql_base.php b/phpBB/phpbb/db/driver/mssql_base.php index 56c111c871..57c4e0f1fd 100644 --- a/phpBB/phpbb/db/driver/mssql_base.php +++ b/phpBB/phpbb/db/driver/mssql_base.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\db\driver; + /** * @ignore */ @@ -19,7 +21,7 @@ if (!defined('IN_PHPBB')) * MSSQL Database Base Abstraction Layer * @package dbal */ -abstract class phpbb_db_driver_mssql_base extends phpbb_db_driver +abstract class mssql_base extends \phpbb\db\driver\driver { /** * {@inheritDoc} diff --git a/phpBB/phpbb/db/driver/mssql_odbc.php b/phpBB/phpbb/db/driver/mssql_odbc.php index a1d1a5d5dd..9db34a69fb 100644 --- a/phpBB/phpbb/db/driver/mssql_odbc.php +++ b/phpBB/phpbb/db/driver/mssql_odbc.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\db\driver; + /** * @ignore */ @@ -26,7 +28,7 @@ if (!defined('IN_PHPBB')) * * @package dbal */ -class phpbb_db_driver_mssql_odbc extends phpbb_db_driver_mssql_base +class mssql_odbc extends \phpbb\db\driver\mssql_base { var $last_query_text = ''; var $connect_error = ''; diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index 28fc88298a..e6002fe1a3 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -11,6 +11,8 @@ * */ +namespace phpbb\db\driver; + /** * @ignore */ @@ -56,7 +58,7 @@ class result_mssqlnative { if (is_array($value)) { - $obj->$key = new stdClass(); + $obj->$key = new \stdClass(); array_to_obj($value, $obj->$key); } else @@ -191,7 +193,7 @@ class result_mssqlnative /** * @package dbal */ -class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base +class mssqlnative extends \phpbb\db\driver\mssql_base { var $m_insert_id = NULL; var $last_query_text = ''; diff --git a/phpBB/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php index f3744ac09d..c76126763d 100644 --- a/phpBB/phpbb/db/driver/mysql.php +++ b/phpBB/phpbb/db/driver/mysql.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\db\driver; + /** * @ignore */ @@ -24,7 +26,7 @@ if (!defined('IN_PHPBB')) * MySQL 5.0+ * @package dbal */ -class phpbb_db_driver_mysql extends phpbb_db_driver_mysql_base +class mysql extends \phpbb\db\driver\mysql_base { var $multi_insert = true; var $connect_error = ''; diff --git a/phpBB/phpbb/db/driver/mysql_base.php b/phpBB/phpbb/db/driver/mysql_base.php index ba44ea61aa..8f2f66674b 100644 --- a/phpBB/phpbb/db/driver/mysql_base.php +++ b/phpBB/phpbb/db/driver/mysql_base.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\db\driver; + /** * @ignore */ @@ -19,7 +21,7 @@ if (!defined('IN_PHPBB')) * Abstract MySQL Database Base Abstraction Layer * @package dbal */ -abstract class phpbb_db_driver_mysql_base extends phpbb_db_driver +abstract class mysql_base extends \phpbb\db\driver\driver { /** * {@inheritDoc} diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index 0f7a73ee6e..4d0e43b464 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\db\driver; + /** * @ignore */ @@ -21,7 +23,7 @@ if (!defined('IN_PHPBB')) * MySQL 4.1+ or MySQL 5.0+ * @package dbal */ -class phpbb_db_driver_mysqli extends phpbb_db_driver_mysql_base +class mysqli extends \phpbb\db\driver\mysql_base { var $multi_insert = true; var $connect_error = ''; diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index e21e07055d..5dfab21455 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\db\driver; + /** * @ignore */ @@ -19,7 +21,7 @@ if (!defined('IN_PHPBB')) * Oracle Database Abstraction Layer * @package dbal */ -class phpbb_db_driver_oracle extends phpbb_db_driver +class oracle extends \phpbb\db\driver\driver { var $last_query_text = ''; var $connect_error = ''; diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index 14854d179d..7a98b90c73 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\db\driver; + /** * @ignore */ @@ -20,7 +22,7 @@ if (!defined('IN_PHPBB')) * Minimum Requirement is Version 7.3+ * @package dbal */ -class phpbb_db_driver_postgres extends phpbb_db_driver +class postgres extends \phpbb\db\driver\driver { var $last_query_text = ''; var $connect_error = ''; @@ -84,7 +86,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver $this->connect_error = 'pg_pconnect function does not exist, is pgsql extension installed?'; return $this->sql_error(''); } - $collector = new phpbb_error_collector; + $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); } @@ -95,7 +97,7 @@ class phpbb_db_driver_postgres extends phpbb_db_driver $this->connect_error = 'pg_connect function does not exist, is pgsql extension installed?'; return $this->sql_error(''); } - $collector = new phpbb_error_collector; + $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); } diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php index 7188f0daa2..a548fd2618 100644 --- a/phpBB/phpbb/db/driver/sqlite.php +++ b/phpBB/phpbb/db/driver/sqlite.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\db\driver; + /** * @ignore */ @@ -20,7 +22,7 @@ if (!defined('IN_PHPBB')) * Minimum Requirement: 2.8.2+ * @package dbal */ -class phpbb_db_driver_sqlite extends phpbb_db_driver +class sqlite extends \phpbb\db\driver\driver { var $connect_error = ''; -- cgit v1.2.1 From d626ebaf1e3d993ba3474c8dd403b18d5faf8863 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Mon, 16 Sep 2013 04:45:58 +0200 Subject: [ticket/11700] Fix a few more comments PHPBB3-11700 --- phpBB/phpbb/db/driver/driver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index a266b2aa48..cd960bc65a 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -274,7 +274,7 @@ class driver * 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 + * @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) @@ -452,7 +452,7 @@ class driver * @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. + * @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) { -- cgit v1.2.1 From 03639c081cfe92dea223b6c2125e94319ae001ce Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 26 Sep 2013 00:42:04 +0200 Subject: [ticket/11866] Update some occurances of phpbb_db_ to new Namespace PHPBB3-11866 --- phpBB/phpbb/db/driver/driver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index cd960bc65a..53d39e9127 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -84,7 +84,7 @@ class driver // 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), strlen('phpbb_db_driver_')); + $this->sql_layer = substr(get_class($this), strlen('phpbb\db\driver\\')); // Do not change this please! This variable is used to easy the use of it - and is hardcoded. $this->any_char = chr(0) . '%'; -- cgit v1.2.1 From 76ddf1ca4143f38f3bf8fc6aabdb3fa302d6ed40 Mon Sep 17 00:00:00 2001 From: Patrick Webster Date: Mon, 14 Oct 2013 16:37:23 -0500 Subject: [ticket/11918] Make sql_freeresult() consistent across all DB drivers PHPBB3-11918 --- phpBB/phpbb/db/driver/firebird.php | 2 +- phpBB/phpbb/db/driver/mssql.php | 6 +++--- phpBB/phpbb/db/driver/mssql_odbc.php | 2 +- phpBB/phpbb/db/driver/mssqlnative.php | 3 ++- phpBB/phpbb/db/driver/mysql.php | 2 +- phpBB/phpbb/db/driver/oracle.php | 2 +- phpBB/phpbb/db/driver/postgres.php | 2 +- phpBB/phpbb/db/driver/sqlite.php | 2 +- 8 files changed, 11 insertions(+), 10 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/firebird.php b/phpBB/phpbb/db/driver/firebird.php index 2df5eaf369..aef75eab15 100644 --- a/phpBB/phpbb/db/driver/firebird.php +++ b/phpBB/phpbb/db/driver/firebird.php @@ -398,7 +398,7 @@ class firebird extends \phpbb\db\driver\driver $query_id = $this->query_result; } - if ($cache && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php index 4d2cd287da..50096deded 100644 --- a/phpBB/phpbb/db/driver/mssql.php +++ b/phpBB/phpbb/db/driver/mssql.php @@ -318,14 +318,14 @@ class mssql extends \phpbb\db\driver\driver $query_id = $this->query_result; } - if ($cache && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } - if (isset($this->open_queries[$query_id])) + if (isset($this->open_queries[(int) $query_id])) { - unset($this->open_queries[$query_id]); + unset($this->open_queries[(int) $query_id]); return @mssql_free_result($query_id); } diff --git a/phpBB/phpbb/db/driver/mssql_odbc.php b/phpBB/phpbb/db/driver/mssql_odbc.php index 9db34a69fb..b9881035c0 100644 --- a/phpBB/phpbb/db/driver/mssql_odbc.php +++ b/phpBB/phpbb/db/driver/mssql_odbc.php @@ -305,7 +305,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base $query_id = $this->query_result; } - if ($cache && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index e6002fe1a3..aade311bcb 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -471,7 +471,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } @@ -481,6 +481,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base unset($this->open_queries[(int) $query_id]); return @sqlsrv_free_stmt($query_id); } + return false; } diff --git a/phpBB/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php index c76126763d..d215453ccb 100644 --- a/phpBB/phpbb/db/driver/mysql.php +++ b/phpBB/phpbb/db/driver/mysql.php @@ -289,7 +289,7 @@ class mysql extends \phpbb\db\driver\mysql_base $query_id = $this->query_result; } - if ($cache && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index 5dfab21455..4fba654d1e 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -621,7 +621,7 @@ class oracle extends \phpbb\db\driver\driver $query_id = $this->query_result; } - if ($cache && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index 7a98b90c73..9cbb1ecb07 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -350,7 +350,7 @@ class postgres extends \phpbb\db\driver\driver $query_id = $this->query_result; } - if ($cache && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php index a548fd2618..55a33284f2 100644 --- a/phpBB/phpbb/db/driver/sqlite.php +++ b/phpBB/phpbb/db/driver/sqlite.php @@ -261,7 +261,7 @@ class sqlite extends \phpbb\db\driver\driver $query_id = $this->query_result; } - if ($cache && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } -- cgit v1.2.1 From 7f58a4572eaca75aecff2da889e67ea151616011 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 28 Oct 2013 22:27:25 +0100 Subject: [ticket/11981] Fix code sniffer complaints PHPBB3-11981 --- phpBB/phpbb/db/driver/mssql.php | 2 +- phpBB/phpbb/db/driver/mssqlnative.php | 4 ++-- phpBB/phpbb/db/driver/mysqli.php | 6 +++--- phpBB/phpbb/db/driver/postgres.php | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php index 50096deded..e1b41461e2 100644 --- a/phpBB/phpbb/db/driver/mssql.php +++ b/phpBB/phpbb/db/driver/mssql.php @@ -259,7 +259,7 @@ class mssql extends \phpbb\db\driver\driver { foreach ($row as $key => $value) { - $row[$key] = ($value === ' ' || $value === NULL) ? '' : $value; + $row[$key] = ($value === ' ' || $value === null) ? '' : $value; } } diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index aade311bcb..2eb625fb11 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -195,7 +195,7 @@ class result_mssqlnative */ class mssqlnative extends \phpbb\db\driver\mssql_base { - var $m_insert_id = NULL; + var $m_insert_id = null; var $last_query_text = ''; var $query_options = array(); var $connect_error = ''; @@ -427,7 +427,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base { foreach ($row as $key => $value) { - $row[$key] = ($value === ' ' || $value === NULL) ? '' : $value; + $row[$key] = ($value === ' ' || $value === null) ? '' : $value; } // remove helper values from LIMIT queries diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index 4d0e43b464..6144dba0c4 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -47,11 +47,11 @@ class mysqli extends \phpbb\db\driver\mysql_base $this->server = ($this->persistency) ? 'p:' . (($sqlserver) ? $sqlserver : 'localhost') : $sqlserver; $this->dbname = $database; - $port = (!$port) ? NULL : $port; + $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; + $socket = null; if ($port) { if (is_numeric($port)) @@ -61,7 +61,7 @@ class mysqli extends \phpbb\db\driver\mysql_base else { $socket = $port; - $port = NULL; + $port = null; } } diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index 9cbb1ecb07..5cd6578d87 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -328,7 +328,7 @@ class postgres extends \phpbb\db\driver\driver return false; } - $temp_result = @pg_fetch_assoc($temp_q_id, NULL); + $temp_result = @pg_fetch_assoc($temp_q_id, null); @pg_free_result($query_id); return ($temp_result) ? $temp_result['last_value'] : false; @@ -456,7 +456,7 @@ class postgres extends \phpbb\db\driver\driver if ($result = @pg_query($this->db_connect_id, "EXPLAIN $explain_query")) { - while ($row = @pg_fetch_assoc($result, NULL)) + while ($row = @pg_fetch_assoc($result, null)) { $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); } @@ -476,7 +476,7 @@ class postgres extends \phpbb\db\driver\driver $endtime = $endtime[0] + $endtime[1]; $result = @pg_query($this->db_connect_id, $query); - while ($void = @pg_fetch_assoc($result, NULL)) + while ($void = @pg_fetch_assoc($result, null)) { // Take the time spent on parsing rows into account } -- cgit v1.2.1 From 02e9f6e2840d7227f158b4baf96fd9c0f6207531 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Tue, 29 Oct 2013 21:31:07 +0100 Subject: [task/code-sniffer] Fix argument list spacing. PHPBB3-11980 --- phpBB/phpbb/db/driver/mysqli.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index 6144dba0c4..aeb66c00cd 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -31,7 +31,7 @@ class mysqli extends \phpbb\db\driver\mysql_base /** * Connect to server */ - function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false , $new_link = false) + function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { if (!function_exists('mysqli_connect')) { -- cgit v1.2.1 From 7aa8f6461f1e85cf91931f56b95384e54fec07c2 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Wed, 30 Oct 2013 13:05:28 +0100 Subject: [task/code-sniffer] Remove the IN_PHPBB check side-effect from class files. PHPBB3-11980 --- phpBB/phpbb/db/driver/driver.php | 8 -------- phpBB/phpbb/db/driver/firebird.php | 8 -------- phpBB/phpbb/db/driver/mssql.php | 8 -------- phpBB/phpbb/db/driver/mssql_base.php | 8 -------- phpBB/phpbb/db/driver/mssql_odbc.php | 8 -------- phpBB/phpbb/db/driver/mssqlnative.php | 8 -------- phpBB/phpbb/db/driver/mysql.php | 8 -------- phpBB/phpbb/db/driver/mysql_base.php | 8 -------- phpBB/phpbb/db/driver/mysqli.php | 8 -------- phpBB/phpbb/db/driver/oracle.php | 8 -------- phpBB/phpbb/db/driver/postgres.php | 8 -------- phpBB/phpbb/db/driver/sqlite.php | 8 -------- 12 files changed, 96 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 53d39e9127..58d0b61519 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -9,14 +9,6 @@ namespace phpbb\db\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * Database Abstraction Layer * @package dbal diff --git a/phpBB/phpbb/db/driver/firebird.php b/phpBB/phpbb/db/driver/firebird.php index aef75eab15..ed56a5d154 100644 --- a/phpBB/phpbb/db/driver/firebird.php +++ b/phpBB/phpbb/db/driver/firebird.php @@ -9,14 +9,6 @@ namespace phpbb\db\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * Firebird/Interbase Database Abstraction Layer * Minimum Requirement is Firebird 2.1 diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php index e1b41461e2..6ebc891673 100644 --- a/phpBB/phpbb/db/driver/mssql.php +++ b/phpBB/phpbb/db/driver/mssql.php @@ -9,14 +9,6 @@ namespace phpbb\db\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * MSSQL Database Abstraction Layer * Minimum Requirement is MSSQL 2000+ diff --git a/phpBB/phpbb/db/driver/mssql_base.php b/phpBB/phpbb/db/driver/mssql_base.php index 57c4e0f1fd..113f1c6902 100644 --- a/phpBB/phpbb/db/driver/mssql_base.php +++ b/phpBB/phpbb/db/driver/mssql_base.php @@ -9,14 +9,6 @@ namespace phpbb\db\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * MSSQL Database Base Abstraction Layer * @package dbal diff --git a/phpBB/phpbb/db/driver/mssql_odbc.php b/phpBB/phpbb/db/driver/mssql_odbc.php index b9881035c0..f8c70f1cd7 100644 --- a/phpBB/phpbb/db/driver/mssql_odbc.php +++ b/phpBB/phpbb/db/driver/mssql_odbc.php @@ -9,14 +9,6 @@ namespace phpbb\db\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * Unified ODBC functions * Unified ODBC functions support any database having ODBC driver, for example Adabas D, IBM DB2, iODBC, Solid, Sybase SQL Anywhere... diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index 2eb625fb11..76cbd59d93 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -13,14 +13,6 @@ namespace phpbb\db\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * 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. diff --git a/phpBB/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php index d215453ccb..e311f0dd74 100644 --- a/phpBB/phpbb/db/driver/mysql.php +++ b/phpBB/phpbb/db/driver/mysql.php @@ -9,14 +9,6 @@ namespace phpbb\db\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * MySQL4 Database Abstraction Layer * Compatible with: diff --git a/phpBB/phpbb/db/driver/mysql_base.php b/phpBB/phpbb/db/driver/mysql_base.php index 8f2f66674b..87b6d153a9 100644 --- a/phpBB/phpbb/db/driver/mysql_base.php +++ b/phpBB/phpbb/db/driver/mysql_base.php @@ -9,14 +9,6 @@ namespace phpbb\db\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * Abstract MySQL Database Base Abstraction Layer * @package dbal diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index aeb66c00cd..adc8f96302 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -9,14 +9,6 @@ namespace phpbb\db\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * MySQLi Database Abstraction Layer * mysqli-extension has to be compiled with: diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index 4fba654d1e..36ed43d4a7 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -9,14 +9,6 @@ namespace phpbb\db\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * Oracle Database Abstraction Layer * @package dbal diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index 5cd6578d87..5dbd1ca74f 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -9,14 +9,6 @@ namespace phpbb\db\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * PostgreSQL Database Abstraction Layer * Minimum Requirement is Version 7.3+ diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php index 55a33284f2..59ec895c0f 100644 --- a/phpBB/phpbb/db/driver/sqlite.php +++ b/phpBB/phpbb/db/driver/sqlite.php @@ -9,14 +9,6 @@ namespace phpbb\db\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * Sqlite Database Abstraction Layer * Minimum Requirement: 2.8.2+ -- cgit v1.2.1 From ae7ef3e09dd284b8876ad74de16321c373d251af Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Thu, 31 Oct 2013 00:48:03 +0100 Subject: [task/code-sniffer] Remove class result_mssqlnative. PHPBB3-11980 --- phpBB/phpbb/db/driver/mssqlnative.php | 169 ---------------------------------- 1 file changed, 169 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index 76cbd59d93..125db9c8d4 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -13,175 +13,6 @@ namespace phpbb\db\driver; -/** - * 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 */ -- cgit v1.2.1 From 23e2f920f5ed52cf9b354f61fcff548a03335ecc Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 14 Nov 2013 15:55:04 +0100 Subject: [ticket/12018] Use path_helper for admin style CSS in sql report The path to the admin style CSS is currently created with $phpbb_admin_path. We should however use the path_helper to correctly link to this file in order to have a correct link on pages like extensions PHPBB3-12018 --- phpBB/phpbb/db/driver/driver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 58d0b61519..d721ed2eb7 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -816,7 +816,7 @@ class driver */ function sql_report($mode, $query = '') { - global $cache, $starttime, $phpbb_root_path, $phpbb_admin_path, $user; + global $cache, $starttime, $phpbb_root_path, $phpbb_path_helper, $user; global $request; if (is_object($request) && !$request->variable('explain', false)) @@ -846,7 +846,7 @@ class driver SQL Report - +
-- cgit v1.2.1 From a88366f4b6807c27de9bf8029ca2e37c45bc9978 Mon Sep 17 00:00:00 2001 From: Oliver Schramm Date: Sun, 2 Mar 2014 20:51:00 +0100 Subject: [ticket/11693] Change sql_build_array to support DELETE PHPBB3-11693 --- phpBB/phpbb/db/driver/driver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index d721ed2eb7..b61800006f 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -388,7 +388,7 @@ class driver * Build sql statement from array for insert/update/select statements * * Idea for this from Ikonboard - * Possible query values: INSERT, INSERT_SELECT, UPDATE, SELECT + * Possible query values: INSERT, INSERT_SELECT, UPDATE, SELECT, DELETE * */ function sql_build_array($query, $assoc_ary = false) @@ -423,7 +423,7 @@ class driver { 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') + else if ($query == 'UPDATE' || $query == 'SELECT' || $query == 'DELETE') { $values = array(); foreach ($assoc_ary as $key => $var) -- cgit v1.2.1 From 7b131119e6d44e8b884c592f0bf2a90cc3372980 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 17 Mar 2014 13:03:45 +0100 Subject: [ticket/12282] Add Interface for DBAL drivers PHPBB3-12282 --- phpBB/phpbb/db/driver/driver.php | 4 +- phpBB/phpbb/db/driver/driver_interface.php | 355 +++++++++++++++++++++++++++++ 2 files changed, 357 insertions(+), 2 deletions(-) create mode 100644 phpBB/phpbb/db/driver/driver_interface.php (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index b61800006f..9e6e005467 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -13,7 +13,7 @@ namespace phpbb\db\driver; * Database Abstraction Layer * @package dbal */ -class driver +abstract class driver implements driver_interface { var $db_connect_id; var $query_result; @@ -327,7 +327,7 @@ class driver 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 we are within a transaction we will not open another one, but enclose the current one to not loose data (preventing auto commit) if ($this->transaction) { $this->transactions++; diff --git a/phpBB/phpbb/db/driver/driver_interface.php b/phpBB/phpbb/db/driver/driver_interface.php new file mode 100644 index 0000000000..56794b038a --- /dev/null +++ b/phpBB/phpbb/db/driver/driver_interface.php @@ -0,0 +1,355 @@ +return_on_error + * is set, null otherwise + */ + public function sql_error($sql = ''); + + /** + * Returns whether results of a query need to be buffered to run a + * transaction while iterating over them. + * + * @return bool Whether buffering is required. + */ + public function sql_buffer_nested_transactions(); + + /** + * Run binary OR operator on DB column. + * + * @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 (e.g. "= 0") + * @return string A SQL statement like "$column | (1 << $bit) {$compare}" + */ + public function sql_bit_or($column_name, $bit, $compare = ''); + + /** + * Version information about used database + * + * @param bool $raw Only return the fetched sql_server_version + * @param bool $use_cache Is it safe to retrieve the value from the cache + * @return string sql server version + */ + public function sql_server_info($raw = false, $use_cache = true); + + /** + * Return on error or display error message + * + * @param bool $fail Should we return on errors, or stop + * @return null + */ + public function sql_return_on_error($fail = false); + + /** + * Build sql statement from an array + * + * @param string $query Should be on of the following strings: + * INSERT, INSERT_SELECT, UPDATE, SELECT, DELETE + * @param array $assoc_ary Array with "column => value" pairs + * @return string A SQL statement like "c1 = 'a' AND c2 = 'b'" + */ + public function sql_build_array($query, $assoc_ary = array()); + + /** + * Fetch all rows + * + * @param mixed $query_id Already executed query to get the rows from, + * if false, the last query will be used. + * @return mixed Nested array if the query had rows, false otherwise + */ + public function sql_fetchrowset($query_id = false); + + /** + * SQL Transaction + * + * @param string $status Should be one of the following strings: + * begin, commit, rollback + * @return mixed Buffered, seekable result handle, false on error + */ + public function sql_transaction($status = 'begin'); + + /** + * Build a concatenated expression + * + * @param string $expr1 Base SQL expression where we append the second one + * @param string $expr2 SQL expression that is appended to the first expression + * @return string Concatenated string + */ + public function sql_concatenate($expr1, $expr2); + + /** + * Build a case expression + * + * Note: The two statements action_true and action_false must have the same + * data type (int, vchar, ...) in the database! + * + * @param string $condition The condition which must be true, + * to use action_true rather then action_else + * @param string $action_true SQL expression that is used, if the condition is true + * @param mixed $action_false SQL expression that is used, if the condition is false + * @return string CASE expression including the condition and statements + */ + public function sql_case($condition, $action_true, $action_false = false); + + /** + * Build sql statement from array for select and select distinct statements + * + * Possible query values: SELECT, SELECT_DISTINCT + * + * @param string $query Should be one of: SELECT, SELECT_DISTINCT + * @param array $array Array with the query data: + * SELECT A comma imploded list of columns to select + * FROM Array with "table => alias" pairs, + * (alias can also be an array) + * Optional: LEFT_JOIN Array of join entries: + * FROM Table that should be joined + * ON Condition for the join + * Optional: WHERE Where SQL statement + * Optional: GROUP_BY Group by SQL statement + * Optional: ORDER_BY Order by SQL statement + * @return string A SQL statement ready for execution + */ + public function sql_build_query($query, $array); + + /** + * Fetch field + * if rownum is false, the current row is used, else it is pointing to the row (zero-based) + * + * @param string $field Name of the column + * @param mixed $rownum Row number, if false the current row will be used + * and the row curser will point to the next row + * Note: $rownum is 0 based + * @param mixed $query_id Already executed query to get the rows from, + * if false, the last query will be used. + * @return mixed String value of the field in the selected row, + * false, if the row does not exist + */ + public function sql_fetchfield($field, $rownum = false, $query_id = false); + + /** + * Fetch current row + * + * @param mixed $query_id Already executed query to get the rows from, + * if false, the last query will be used. + * @return mixed Array with the current row, + * false, if the row does not exist + */ + public function sql_fetchrow($query_id = false); + + /** + * Returns SQL string to cast a string expression to an int. + * + * @param string $expression An expression evaluating to string + * @return string Expression returning an int + */ + public function cast_expr_to_bigint($expression); + + /** + * Get last inserted id after insert statement + * + * @return string Autoincrement value of the last inserted row + */ + public function sql_nextid(); + + /** + * Add to query count + * + * @param bool $cached Is this query cached? + * @return null + */ + public function sql_add_num_queries($cached = false); + + /** + * Build LIMIT query + * + * @param string $query The SQL query to execute + * @param int $total The number of rows to select + * @param int $offset + * @param int $cache_ttl Either 0 to avoid caching or + * the time in seconds which the result shall be kept in cache + * @return mixed Buffered, seekable result handle, false on error + */ + public function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0); + + /** + * Base query method + * + * @param string $query The SQL query to execute + * @param int $cache_ttl Either 0 to avoid caching or + * the time in seconds which the result shall be kept in cache + * @return mixed Buffered, seekable result handle, false on error + */ + public function sql_query($query = '', $cache_ttl = 0); + + /** + * Returns SQL string to cast an integer expression to a string. + * + * @param string $expression An expression evaluating to int + * @return string Expression returning a string + */ + public function cast_expr_to_string($expression); + + /** + * Connect to server + * + * @param string $sqlserver Address of the database server + * @param string $sqluser User name of the SQL user + * @param string $sqlpassword Password of the SQL user + * @param string $database Name of the database + * @param mixed $port Port of the database server + * @param bool $persistency + * @param bool $new_link Should a new connection be established + * @return mixed Connection ID on success, string error message otherwise + */ + public function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false); + + /** + * 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") + * @return string A SQL statement like: "{$column} & (1 << {$bit}) {$compare}" + */ + public function sql_bit_and($column_name, $bit, $compare = ''); + + /** + * Free sql result + * + * @param mixed $query_id Already executed query result, + * if false, the last query will be used. + * @return null + */ + public function sql_freeresult($query_id = false); + + /** + * Return number of sql queries and cached sql queries used + * + * @param bool $cached Should we return the number of cached or normal queries? + * @return int Number of queries that have been executed + */ + public function sql_num_queries($cached = false); + + /** + * 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. + */ + public function sql_multi_insert($table, $sql_ary); + + /** + * Return number of affected rows + * + * @return mixed Number of the affected rows by the last query + * false if no query has been run before + */ + public function sql_affectedrows(); + + /** + * DBAL garbage collection, close SQL connection + * + * @return mixed False if no connection was opened before, + * Server response otherwise + */ + public function sql_close(); + + /** + * Seek to given row number + * + * @param mixed $rownum Row number the curser should point to + * Note: $rownum is 0 based + * @param mixed $query_id ID of the query to set the row cursor on + * if false, the last query will be used. + * $query_id will then be set correctly + * @return bool False if something went wrong + */ + public function sql_rowseek($rownum, &$query_id); + + /** + * Escape string used in sql query + * + * @param string $msg String to be escaped + * @return string Escaped version of $msg + */ + public function sql_escape($msg); + + /** + * 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 A SQL statement like: "LIKE 'bertie_%'" + */ + public function sql_like_expression($expression); + + /** + * Explain queries + * + * @param string $mode Available modes: display, start, stop, + * add_select_row, fromcache, record_fromcache + * @param string $query The Query that should be explained + * @return mixed Either a full HTML page, boolean or null + */ + public function sql_report($mode, $query = ''); + + /** + * Build IN or NOT IN sql comparison string, uses <> or = on single element + * arrays to improve comparison speed + * + * @param string $field Name of the sql column that shall be compared + * @param array $array Array of values that are (not) allowed + * @param bool $negate true for NOT IN (), false for IN () + * @param bool $allow_empty_set If true, allow $array to be empty, + * this function will return 1=1 or 1=0 then. + * @return string A SQL statement like: "IN (1, 2, 3, 4)" or "= 1" + */ + public function sql_in_set($field, $array, $negate = false, $allow_empty_set = false); +} \ No newline at end of file -- cgit v1.2.1 From 1f28451d587aa3566cdb6f7848439d2d5efdf820 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 17 Mar 2014 13:18:05 +0100 Subject: [ticket/12282] Use {@inheritDoc} for inherited methods PHPBB3-12282 --- phpBB/phpbb/db/driver/driver.php | 131 ++++++++-------------------------- phpBB/phpbb/db/driver/firebird.php | 29 +++----- phpBB/phpbb/db/driver/mssql.php | 28 +++----- phpBB/phpbb/db/driver/mssql_base.php | 2 +- phpBB/phpbb/db/driver/mssql_odbc.php | 24 ++----- phpBB/phpbb/db/driver/mssqlnative.php | 23 ++---- phpBB/phpbb/db/driver/mysql.php | 29 +++----- phpBB/phpbb/db/driver/mysql_base.php | 17 +---- phpBB/phpbb/db/driver/mysqli.php | 28 +++----- phpBB/phpbb/db/driver/oracle.php | 28 +++----- phpBB/phpbb/db/driver/postgres.php | 33 +++------ phpBB/phpbb/db/driver/sqlite.php | 31 +++----- 12 files changed, 115 insertions(+), 288 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 9e6e005467..85d160c80e 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -84,7 +84,7 @@ abstract class driver implements driver_interface } /** - * return on error or display error message + * {@inheritDoc} */ function sql_return_on_error($fail = false) { @@ -95,7 +95,7 @@ abstract class driver implements driver_interface } /** - * Return number of sql queries and cached sql queries used + * {@inheritDoc} */ function sql_num_queries($cached = false) { @@ -103,7 +103,7 @@ abstract class driver implements driver_interface } /** - * Add to query count + * {@inheritDoc} */ function sql_add_num_queries($cached = false) { @@ -113,7 +113,7 @@ abstract class driver implements driver_interface } /** - * DBAL garbage collection, close sql connection + * {@inheritDoc} */ function sql_close() { @@ -146,8 +146,7 @@ abstract class driver implements driver_interface } /** - * Build LIMIT query - * Doing some validation here. + * {@inheritDoc} */ function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) { @@ -164,7 +163,7 @@ abstract class driver implements driver_interface } /** - * Fetch all rows + * {@inheritDoc} */ function sql_fetchrowset($query_id = false) { @@ -188,8 +187,7 @@ abstract class driver implements driver_interface } /** - * Seek to given row number - * rownum is zero-based + * {@inheritDoc} */ function sql_rowseek($rownum, &$query_id) { @@ -231,8 +229,7 @@ abstract class driver implements driver_interface } /** - * Fetch field - * if rownum is false, the current row is used, else it is pointing to the row (zero-based) + * {@inheritDoc} */ function sql_fetchfield($field, $rownum = false, $query_id = false) { @@ -263,11 +260,7 @@ abstract class driver implements driver_interface } /** - * 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! + * {@inheritDoc} */ function sql_like_expression($expression) { @@ -278,14 +271,7 @@ abstract class driver implements driver_interface } /** - * Build a case expression - * - * Note: The two statements action_true and action_false must have the same data type (int, vchar, ...) in the database! - * - * @param string $condition The condition which must be true, to use action_true rather then action_else - * @param string $action_true SQL expression that is used, if the condition is true - * @param string $action_else SQL expression that is used, if the condition is false, optional - * @return string CASE expression including the condition and statements + * {@inheritDoc} */ public function sql_case($condition, $action_true, $action_false = false) { @@ -297,11 +283,7 @@ abstract class driver implements driver_interface } /** - * Build a concatenated expression - * - * @param string $expr1 Base SQL expression where we append the second one - * @param string $expr2 SQL expression that is appended to the first expression - * @return string Concatenated string + * {@inheritDoc} */ public function sql_concatenate($expr1, $expr2) { @@ -309,9 +291,7 @@ abstract class driver implements driver_interface } /** - * Returns whether results of a query need to be buffered to run a transaction while iterating over them. - * - * @return bool Whether buffering is required. + * {@inheritDoc} */ function sql_buffer_nested_transactions() { @@ -319,8 +299,7 @@ abstract class driver implements driver_interface } /** - * SQL Transaction - * @access private + * {@inheritDoc} */ function sql_transaction($status = 'begin') { @@ -345,14 +324,16 @@ abstract class driver implements driver_interface break; case 'commit': - // If there was a previously opened transaction we do not commit yet... but count back the number of inner transactions + // 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) + // 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) { @@ -385,11 +366,7 @@ abstract class driver implements driver_interface } /** - * Build sql statement from array for insert/update/select statements - * - * Idea for this from Ikonboard - * Possible query values: INSERT, INSERT_SELECT, UPDATE, SELECT, DELETE - * + * {@inheritDoc} */ function sql_build_array($query, $assoc_ary = false) { @@ -437,14 +414,7 @@ abstract class driver implements driver_interface } /** - * 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. + * {@inheritDoc} */ function sql_in_set($field, $array, $negate = false, $allow_empty_set = false) { @@ -489,12 +459,7 @@ abstract class driver implements driver_interface } /** - * 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") + * {@inheritDoc} */ function sql_bit_and($column_name, $bit, $compare = '') { @@ -507,12 +472,7 @@ abstract class driver implements driver_interface } /** - * 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") + * {@inheritDoc} */ function sql_bit_or($column_name, $bit, $compare = '') { @@ -525,10 +485,7 @@ abstract class driver implements driver_interface } /** - * Returns SQL string to cast a string expression to an int. - * - * @param string $expression An expression evaluating to string - * @return string Expression returning an int + * {@inheritDoc} */ function cast_expr_to_bigint($expression) { @@ -536,10 +493,7 @@ abstract class driver implements driver_interface } /** - * Returns SQL string to cast an integer expression to a string. - * - * @param string $expression An expression evaluating to int - * @return string Expression returning a string + * {@inheritDoc} */ function cast_expr_to_string($expression) { @@ -547,11 +501,7 @@ abstract class driver implements driver_interface } /** - * 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)" + * {@inheritDoc} */ function sql_lower_text($column_name) { @@ -559,13 +509,7 @@ abstract class driver implements driver_interface } /** - * 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 + * {@inheritDoc} */ function sql_multi_insert($table, $sql_ary) { @@ -637,9 +581,7 @@ abstract class driver implements driver_interface } /** - * Build sql statement from array for select and select distinct statements - * - * Possible query values: SELECT, SELECT_DISTINCT + * {@inheritDoc} */ function sql_build_query($query, $array) { @@ -742,7 +684,7 @@ abstract class driver implements driver_interface } /** - * display sql error page + * {@inheritDoc} */ function sql_error($sql = '') { @@ -812,7 +754,7 @@ abstract class driver implements driver_interface } /** - * Explain queries + * {@inheritDoc} */ function sql_report($mode, $query = '') { @@ -1002,14 +944,7 @@ abstract class driver implements driver_interface } /** - * 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 + * {@inheritDoc} */ function get_estimated_row_count($table_name) { @@ -1017,13 +952,7 @@ abstract class driver implements driver_interface } /** - * 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 + * {@inheritDoc} */ function get_row_count($table_name) { diff --git a/phpBB/phpbb/db/driver/firebird.php b/phpBB/phpbb/db/driver/firebird.php index ed56a5d154..a4967c7ffe 100644 --- a/phpBB/phpbb/db/driver/firebird.php +++ b/phpBB/phpbb/db/driver/firebird.php @@ -22,7 +22,7 @@ class firebird extends \phpbb\db\driver\driver var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -79,10 +79,7 @@ class firebird extends \phpbb\db\driver\driver } /** - * 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 + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -127,13 +124,7 @@ class firebird extends \phpbb\db\driver\driver } /** - * 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 + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -297,7 +288,7 @@ class firebird extends \phpbb\db\driver\driver } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -313,7 +304,7 @@ class firebird extends \phpbb\db\driver\driver } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -351,7 +342,7 @@ class firebird extends \phpbb\db\driver\driver } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -379,7 +370,7 @@ class firebird extends \phpbb\db\driver\driver } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -405,7 +396,7 @@ class firebird extends \phpbb\db\driver\driver } /** - * Escape string used in sql query + * {@inheritDoc} */ function sql_escape($msg) { @@ -441,7 +432,7 @@ class firebird extends \phpbb\db\driver\driver } /** - * @inheritdoc + * {@inheritDoc} */ function cast_expr_to_bigint($expression) { @@ -450,7 +441,7 @@ class firebird extends \phpbb\db\driver\driver } /** - * @inheritdoc + * {@inheritDoc} */ function cast_expr_to_string($expression) { diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php index 6ebc891673..588cd7a7e8 100644 --- a/phpBB/phpbb/db/driver/mssql.php +++ b/phpBB/phpbb/db/driver/mssql.php @@ -19,7 +19,7 @@ class mssql extends \phpbb\db\driver\driver var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -55,10 +55,7 @@ class mssql extends \phpbb\db\driver\driver } /** - * 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 + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -124,13 +121,7 @@ class mssql extends \phpbb\db\driver\driver } /** - * 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 + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -215,7 +206,7 @@ class mssql extends \phpbb\db\driver\driver } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -223,7 +214,7 @@ class mssql extends \phpbb\db\driver\driver } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -259,8 +250,7 @@ class mssql extends \phpbb\db\driver\driver } /** - * Seek to given row number - * rownum is zero-based + * {@inheritDoc} */ function sql_rowseek($rownum, &$query_id) { @@ -280,7 +270,7 @@ class mssql extends \phpbb\db\driver\driver } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -299,7 +289,7 @@ class mssql extends \phpbb\db\driver\driver } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -325,7 +315,7 @@ class mssql extends \phpbb\db\driver\driver } /** - * Escape string used in sql query + * {@inheritDoc} */ function sql_escape($msg) { diff --git a/phpBB/phpbb/db/driver/mssql_base.php b/phpBB/phpbb/db/driver/mssql_base.php index 113f1c6902..1e3fb8235a 100644 --- a/phpBB/phpbb/db/driver/mssql_base.php +++ b/phpBB/phpbb/db/driver/mssql_base.php @@ -24,7 +24,7 @@ abstract class mssql_base extends \phpbb\db\driver\driver } /** - * Escape string used in sql query + * {@inheritDoc} */ function sql_escape($msg) { diff --git a/phpBB/phpbb/db/driver/mssql_odbc.php b/phpBB/phpbb/db/driver/mssql_odbc.php index f8c70f1cd7..34b913dc8a 100644 --- a/phpBB/phpbb/db/driver/mssql_odbc.php +++ b/phpBB/phpbb/db/driver/mssql_odbc.php @@ -26,7 +26,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -83,10 +83,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base } /** - * 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 + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -144,13 +141,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base } /** - * 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 + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -236,7 +227,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -244,8 +235,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base } /** - * 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. + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -265,7 +255,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -286,7 +276,7 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index 125db9c8d4..b449de2ae4 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -24,7 +24,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -53,10 +53,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base } /** - * 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 + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -113,13 +110,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base } /** - * 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 + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -215,7 +206,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -223,7 +214,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -263,7 +254,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -283,7 +274,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { diff --git a/phpBB/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php index e311f0dd74..1a4fd364df 100644 --- a/phpBB/phpbb/db/driver/mysql.php +++ b/phpBB/phpbb/db/driver/mysql.php @@ -24,8 +24,7 @@ class mysql extends \phpbb\db\driver\mysql_base var $connect_error = ''; /** - * Connect to server - * @access public + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -103,10 +102,7 @@ class mysql extends \phpbb\db\driver\mysql_base } /** - * 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 + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -154,13 +150,7 @@ class mysql extends \phpbb\db\driver\mysql_base } /** - * 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 + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -213,7 +203,7 @@ class mysql extends \phpbb\db\driver\mysql_base } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -221,7 +211,7 @@ class mysql extends \phpbb\db\driver\mysql_base } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -241,8 +231,7 @@ class mysql extends \phpbb\db\driver\mysql_base } /** - * Seek to given row number - * rownum is zero-based + * {@inheritDoc} */ function sql_rowseek($rownum, &$query_id) { @@ -262,7 +251,7 @@ class mysql extends \phpbb\db\driver\mysql_base } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -270,7 +259,7 @@ class mysql extends \phpbb\db\driver\mysql_base } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -296,7 +285,7 @@ class mysql extends \phpbb\db\driver\mysql_base } /** - * Escape string used in sql query + * {@inheritDoc} */ function sql_escape($msg) { diff --git a/phpBB/phpbb/db/driver/mysql_base.php b/phpBB/phpbb/db/driver/mysql_base.php index 87b6d153a9..d0f6a9e8fa 100644 --- a/phpBB/phpbb/db/driver/mysql_base.php +++ b/phpBB/phpbb/db/driver/mysql_base.php @@ -43,14 +43,7 @@ abstract class mysql_base extends \phpbb\db\driver\driver } /** - * 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 + * {@inheritDoc} */ function get_estimated_row_count($table_name) { @@ -72,13 +65,7 @@ abstract class mysql_base extends \phpbb\db\driver\driver } /** - * 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 + * {@inheritDoc} */ function get_row_count($table_name) { diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index adc8f96302..6814599b24 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -21,7 +21,7 @@ class mysqli extends \phpbb\db\driver\mysql_base var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -96,10 +96,7 @@ class mysqli extends \phpbb\db\driver\mysql_base } /** - * 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 + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -151,13 +148,7 @@ class mysqli extends \phpbb\db\driver\mysql_base } /** - * 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 + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -205,7 +196,7 @@ class mysqli extends \phpbb\db\driver\mysql_base } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -213,7 +204,7 @@ class mysqli extends \phpbb\db\driver\mysql_base } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -239,8 +230,7 @@ class mysqli extends \phpbb\db\driver\mysql_base } /** - * Seek to given row number - * rownum is zero-based + * {@inheritDoc} */ function sql_rowseek($rownum, &$query_id) { @@ -260,7 +250,7 @@ class mysqli extends \phpbb\db\driver\mysql_base } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -268,7 +258,7 @@ class mysqli extends \phpbb\db\driver\mysql_base } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -288,7 +278,7 @@ class mysqli extends \phpbb\db\driver\mysql_base } /** - * Escape string used in sql query + * {@inheritDoc} */ function sql_escape($msg) { diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index 36ed43d4a7..8a304b5042 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -19,7 +19,7 @@ class oracle extends \phpbb\db\driver\driver var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -72,10 +72,7 @@ class oracle extends \phpbb\db\driver\driver } /** - * 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 + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -240,13 +237,7 @@ class oracle extends \phpbb\db\driver\driver } /** - * 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 + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -473,7 +464,7 @@ class oracle extends \phpbb\db\driver\driver } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -481,7 +472,7 @@ class oracle extends \phpbb\db\driver\driver } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -532,8 +523,7 @@ class oracle extends \phpbb\db\driver\driver } /** - * Seek to given row number - * rownum is zero-based + * {@inheritDoc} */ function sql_rowseek($rownum, &$query_id) { @@ -570,7 +560,7 @@ class oracle extends \phpbb\db\driver\driver } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -602,7 +592,7 @@ class oracle extends \phpbb\db\driver\driver } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -628,7 +618,7 @@ class oracle extends \phpbb\db\driver\driver } /** - * Escape string used in sql query + * {@inheritDoc} */ function sql_escape($msg) { diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index 5dbd1ca74f..9e091f0a5d 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -20,7 +20,7 @@ class postgres extends \phpbb\db\driver\driver var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -115,10 +115,7 @@ class postgres extends \phpbb\db\driver\driver } /** - * 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 + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -166,13 +163,7 @@ class postgres extends \phpbb\db\driver\driver } /** - * 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 + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -253,7 +244,7 @@ class postgres extends \phpbb\db\driver\driver } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -261,7 +252,7 @@ class postgres extends \phpbb\db\driver\driver } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -281,8 +272,7 @@ class postgres extends \phpbb\db\driver\driver } /** - * Seek to given row number - * rownum is zero-based + * {@inheritDoc} */ function sql_rowseek($rownum, &$query_id) { @@ -302,7 +292,7 @@ class postgres extends \phpbb\db\driver\driver } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -331,7 +321,7 @@ class postgres extends \phpbb\db\driver\driver } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -357,8 +347,7 @@ class postgres extends \phpbb\db\driver\driver } /** - * Escape string used in sql query - * Note: Do not use for bytea values if we may use them at a later stage + * {@inheritDoc} */ function sql_escape($msg) { @@ -375,7 +364,7 @@ class postgres extends \phpbb\db\driver\driver } /** - * @inheritdoc + * {@inheritDoc} */ function cast_expr_to_bigint($expression) { @@ -383,7 +372,7 @@ class postgres extends \phpbb\db\driver\driver } /** - * @inheritdoc + * {@inheritDoc} */ function cast_expr_to_string($expression) { diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php index 59ec895c0f..86a585f4eb 100644 --- a/phpBB/phpbb/db/driver/sqlite.php +++ b/phpBB/phpbb/db/driver/sqlite.php @@ -19,7 +19,7 @@ class sqlite extends \phpbb\db\driver\driver var $connect_error = ''; /** - * Connect to server + * {@inheritDoc} */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { @@ -58,10 +58,7 @@ class sqlite extends \phpbb\db\driver\driver } /** - * 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 + * {@inheritDoc} */ function sql_server_info($raw = false, $use_cache = true) { @@ -108,13 +105,7 @@ class sqlite extends \phpbb\db\driver\driver } /** - * 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 + * {@inheritDoc} */ function sql_query($query = '', $cache_ttl = 0) { @@ -185,7 +176,7 @@ class sqlite extends \phpbb\db\driver\driver } /** - * Return number of affected rows + * {@inheritDoc} */ function sql_affectedrows() { @@ -193,7 +184,7 @@ class sqlite extends \phpbb\db\driver\driver } /** - * Fetch current row + * {@inheritDoc} */ function sql_fetchrow($query_id = false) { @@ -213,8 +204,7 @@ class sqlite extends \phpbb\db\driver\driver } /** - * Seek to given row number - * rownum is zero-based + * {@inheritDoc} */ function sql_rowseek($rownum, &$query_id) { @@ -234,7 +224,7 @@ class sqlite extends \phpbb\db\driver\driver } /** - * Get last inserted id after insert statement + * {@inheritDoc} */ function sql_nextid() { @@ -242,7 +232,7 @@ class sqlite extends \phpbb\db\driver\driver } /** - * Free sql result + * {@inheritDoc} */ function sql_freeresult($query_id = false) { @@ -262,7 +252,7 @@ class sqlite extends \phpbb\db\driver\driver } /** - * Escape string used in sql query + * {@inheritDoc} */ function sql_escape($msg) { @@ -270,7 +260,8 @@ class sqlite extends \phpbb\db\driver\driver } /** - * Correctly adjust LIKE expression for special characters + * {@inheritDoc} + * * For SQLite an underscore is a not-known character... this may change with SQLite3 */ function sql_like_expression($expression) -- cgit v1.2.1 From 94a033160303de579bff69aa0fb1cb93a3f890d7 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 17 Mar 2014 13:49:56 +0100 Subject: [ticket/12282] Add new line at EOF of the interface PHPBB3-12282 --- phpBB/phpbb/db/driver/driver_interface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver_interface.php b/phpBB/phpbb/db/driver/driver_interface.php index 56794b038a..a9051616c9 100644 --- a/phpBB/phpbb/db/driver/driver_interface.php +++ b/phpBB/phpbb/db/driver/driver_interface.php @@ -352,4 +352,4 @@ interface driver_interface * @return string A SQL statement like: "IN (1, 2, 3, 4)" or "= 1" */ public function sql_in_set($field, $array, $negate = false, $allow_empty_set = false); -} \ No newline at end of file +} -- cgit v1.2.1 From b39b0369aa0ac6853bde0504259166f570beb983 Mon Sep 17 00:00:00 2001 From: Patrick Webster Date: Sun, 3 Nov 2013 21:58:05 -0600 Subject: [feature/sqlite3] Add support for SQLite 3 Minimum version requirement is 3.6.15 as that's what ships with PHP 5.3.0 when support for SQLite 3 was added. PHPBB3-9728 --- phpBB/phpbb/db/driver/sqlite3.php | 350 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 phpBB/phpbb/db/driver/sqlite3.php (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php new file mode 100644 index 0000000000..fcb21b39c9 --- /dev/null +++ b/phpBB/phpbb/db/driver/sqlite3.php @@ -0,0 +1,350 @@ +persistency = false; + $this->user = $sqluser; + $this->server = $sqlserver . (($port) ? ':' . $port : ''); + $this->dbname = $database; + + if (!class_exists('SQLite3', false)) + { + $this->connect_error = 'SQLite3 not found, is the extension installed?'; + return $this->sql_error(''); + } + + try + { + $this->dbo = new \SQLite3($this->server, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE); + $this->db_connect_id = true; + } + catch (Exception $e) + { + return array('message' => $e->getMessage()); + } + + return true; + } + + /** + * {@inheritDoc} + */ + 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) + { + $version = \SQLite3::version(); + + $this->sql_server_version = $version['versionString']; + + 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 $this->dbo->exec('BEGIN IMMEDIATE'); + break; + + case 'commit': + return $this->dbo->exec('COMMIT'); + break; + + case 'rollback': + return $this->dbo->exec('ROLLBACK'); + break; + } + + return true; + } + + /** + * {@inheritDoc} + */ + function sql_query($query = '', $cache_ttl = 0) + { + if ($query != '') + { + global $cache; + + // EXPLAIN only in extra debug mode + if (defined('DEBUG')) + { + $this->sql_report('start', $query); + } + + $this->last_query_text = $query; + $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; + $this->sql_add_num_queries($this->query_result); + + if ($this->query_result === false) + { + if (($this->query_result = @$this->dbo->query($query)) === false) + { + $this->sql_error($query); + } + + if (defined('DEBUG')) + { + $this->sql_report('stop', $query); + } + + if ($cache && $cache_ttl) + { + $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); + } + } + else if (defined('DEBUG')) + { + $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); + } + + /** + * {@inheritDoc} + */ + function sql_affectedrows() + { + return ($this->db_connect_id) ? $this->dbo->changes() : false; + } + + /** + * {@inheritDoc} + */ + function sql_fetchrow($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) + { + return $cache->sql_fetchrow($query_id); + } + + return is_object($query_id) ? $query_id->fetchArray(SQLITE3_ASSOC) : false; + } + + /** + * {@inheritDoc} + */ + function sql_nextid() + { + return ($this->db_connect_id) ? $this->dbo->lastInsertRowID() : false; + } + + /** + * {@inheritDoc} + */ + function sql_freeresult($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) + { + return $cache->sql_freeresult($query_id); + } + + if ($query_id) + { + return @$query_id->finalize(); + } + } + + /** + * {@inheritDoc} + */ + function sql_escape($msg) + { + return \SQLite3::escapeString($msg); + } + + /** + * {@inheritDoc} + * + * For SQLite an underscore is a not-known character... + */ + 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 (class_exists('SQLite3', false)) + { + $error = array( + 'message' => $this->dbo->lastErrorMsg(), + 'code' => $this->dbo->lastErrorCode(), + ); + } + 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 $this->dbo->close(); + } + + /** + * 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 = $this->dbo->query("EXPLAIN QUERY PLAN $explain_query")) + { + while ($row = $result->fetchArray(SQLITE3_ASSOC)) + { + $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); + } + } + + if ($html_table) + { + $this->html_hold .= ''; + } + } + + break; + + case 'fromcache': + $endtime = explode(' ', microtime()); + $endtime = $endtime[0] + $endtime[1]; + + $result = $this->dbo->query($query); + while ($void = $result->fetchArray(SQLITE3_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; + } + } +} -- cgit v1.2.1 From 8c2b80e3d25c716ae9c81fe833cc4bb62eb03279 Mon Sep 17 00:00:00 2001 From: Patrick Webster Date: Fri, 25 Apr 2014 18:24:39 -0500 Subject: [feature/sqlite3] Update docblocks and function visibility Added missing docblock annotations and added visibility identifiers. PHPBB3-9728 --- phpBB/phpbb/db/driver/sqlite3.php | 71 ++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 23 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php index fcb21b39c9..971b3e55d3 100644 --- a/phpBB/phpbb/db/driver/sqlite3.php +++ b/phpBB/phpbb/db/driver/sqlite3.php @@ -16,15 +16,20 @@ namespace phpbb\db\driver; */ class sqlite3 extends \phpbb\db\driver\driver { - var $connect_error = ''; + /** + * @var string Stores errors during connection setup in case the driver is not available + */ + protected $connect_error = ''; - /** @var \SQLite3 */ - var $dbo = null; + /** + * @var \SQLite3 The SQLite3 database object to operate against + */ + protected $dbo = null; /** * {@inheritDoc} */ - function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) + public function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { $this->persistency = false; $this->user = $sqluser; @@ -53,7 +58,7 @@ class sqlite3 extends \phpbb\db\driver\driver /** * {@inheritDoc} */ - function sql_server_info($raw = false, $use_cache = true) + public function sql_server_info($raw = false, $use_cache = true) { global $cache; @@ -74,9 +79,12 @@ class sqlite3 extends \phpbb\db\driver\driver /** * SQL Transaction - * @access private + * + * @param string $status Should be one of the following strings: + * begin, commit, rollback + * @return bool Success/failure of the transaction query */ - function _sql_transaction($status = 'begin') + protected function _sql_transaction($status = 'begin') { switch ($status) { @@ -99,7 +107,7 @@ class sqlite3 extends \phpbb\db\driver\driver /** * {@inheritDoc} */ - function sql_query($query = '', $cache_ttl = 0) + public function sql_query($query = '', $cache_ttl = 0) { if ($query != '') { @@ -147,8 +155,15 @@ class sqlite3 extends \phpbb\db\driver\driver /** * Build LIMIT query + * + * @param string $query The SQL query to execute + * @param int $total The number of rows to select + * @param int $offset + * @param int $cache_ttl Either 0 to avoid caching or + * the time in seconds which the result shall be kept in cache + * @return mixed Buffered, seekable result handle, false on error */ - function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) + protected function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) { $this->query_result = false; @@ -166,7 +181,7 @@ class sqlite3 extends \phpbb\db\driver\driver /** * {@inheritDoc} */ - function sql_affectedrows() + public function sql_affectedrows() { return ($this->db_connect_id) ? $this->dbo->changes() : false; } @@ -174,7 +189,7 @@ class sqlite3 extends \phpbb\db\driver\driver /** * {@inheritDoc} */ - function sql_fetchrow($query_id = false) + public function sql_fetchrow($query_id = false) { global $cache; @@ -194,7 +209,7 @@ class sqlite3 extends \phpbb\db\driver\driver /** * {@inheritDoc} */ - function sql_nextid() + public function sql_nextid() { return ($this->db_connect_id) ? $this->dbo->lastInsertRowID() : false; } @@ -202,7 +217,7 @@ class sqlite3 extends \phpbb\db\driver\driver /** * {@inheritDoc} */ - function sql_freeresult($query_id = false) + public function sql_freeresult($query_id = false) { global $cache; @@ -225,7 +240,7 @@ class sqlite3 extends \phpbb\db\driver\driver /** * {@inheritDoc} */ - function sql_escape($msg) + public function sql_escape($msg) { return \SQLite3::escapeString($msg); } @@ -235,7 +250,7 @@ class sqlite3 extends \phpbb\db\driver\driver * * For SQLite an underscore is a not-known character... */ - function sql_like_expression($expression) + public 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. @@ -249,9 +264,10 @@ class sqlite3 extends \phpbb\db\driver\driver /** * return sql error array - * @access private + * + * @return array */ - function _sql_error() + protected function _sql_error() { if (class_exists('SQLite3', false)) { @@ -273,27 +289,36 @@ class sqlite3 extends \phpbb\db\driver\driver /** * Build db-specific query data - * @access private + * + * @param string $stage Available stages: FROM, WHERE + * @param mixed $data A string containing the CROSS JOIN query or an array of WHERE clauses + * + * @return string The db-specific query fragment */ - function _sql_custom_build($stage, $data) + protected function _sql_custom_build($stage, $data) { return $data; } /** * Close sql connection - * @access private + * + * @return bool False if failure */ - function _sql_close() + protected function _sql_close() { return $this->dbo->close(); } /** * Build db-specific report - * @access private + * + * @param string $mode Available modes: display, start, stop, + * add_select_row, fromcache, record_fromcache + * @param string $query The Query that should be explained + * @return mixed Either a full HTML page, boolean or null */ - function _sql_report($mode, $query = '') + protected function _sql_report($mode, $query = '') { switch ($mode) { -- cgit v1.2.1 From b92eac71e49f184d1fe451a8b1b1d396768c6fb7 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 23 May 2014 16:12:22 +0200 Subject: [ticket/12570] Fix MySQLi affectedrows by specifying MYSQLI_CLIENT_FOUND_ROWS PHPBB3-12570 --- phpBB/phpbb/db/driver/mysqli.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index 6814599b24..a0df7599f8 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -57,7 +57,8 @@ class mysqli extends \phpbb\db\driver\mysql_base } } - $this->db_connect_id = @mysqli_connect($this->server, $this->user, $sqlpassword, $this->dbname, $port, $socket); + $this->db_connect_id = @mysqli_init(); + $this->db_connect_id->real_connect($this->server, $this->user, $sqlpassword, $this->dbname, $port, $socket, MYSQLI_CLIENT_FOUND_ROWS); if ($this->db_connect_id && $this->dbname != '') { -- cgit v1.2.1 From d87dba3b0527ab1590be143c13c0c0d1010e3410 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 23 May 2014 16:13:19 +0200 Subject: [ticket/12570] Fix MySQL affectedrows We always want the number of matched rows instead of changed rows, when running an update. So when mysql_info() returns the number of matched rows we return that one instead of mysql_affected_rows() PHPBB3-12570 --- phpBB/phpbb/db/driver/mysql.php | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php index 1a4fd364df..de4d2de9c6 100644 --- a/phpBB/phpbb/db/driver/mysql.php +++ b/phpBB/phpbb/db/driver/mysql.php @@ -207,7 +207,26 @@ class mysql extends \phpbb\db\driver\mysql_base */ function sql_affectedrows() { - return ($this->db_connect_id) ? @mysql_affected_rows($this->db_connect_id) : false; + if ($this->db_connect_id) + { + // We always want the number of matched rows + // instead of changed rows, when running an update. + // So when mysql_info() returns the number of matched rows + // we return that one instead of mysql_affected_rows() + $mysql_info = @mysql_info($this->db_connect_id); + if ($mysql_info !== false) + { + $match = array(); + preg_match('#^Rows matched: (\d)+ Changed: (\d)+ Warnings: (\d)+$#', $mysql_info, $match); + if (isset($match[1])) + { + return $match[1]; + } + } + + return @mysql_affected_rows($this->db_connect_id); + } + return false; } /** -- cgit v1.2.1 From fcdf1101cba7999081f12bca2f5f96ef7769539c Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 24 May 2014 13:06:25 +0200 Subject: [ticket/12570] Keep MySQLi procedural PHPBB3-12570 --- phpBB/phpbb/db/driver/mysqli.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index a0df7599f8..39df175860 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -57,8 +57,8 @@ class mysqli extends \phpbb\db\driver\mysql_base } } - $this->db_connect_id = @mysqli_init(); - $this->db_connect_id->real_connect($this->server, $this->user, $sqlpassword, $this->dbname, $port, $socket, MYSQLI_CLIENT_FOUND_ROWS); + $this->db_connect_id = mysqli_init(); + @mysqli_real_connect($this->db_connect_id, $this->server, $this->user, $sqlpassword, $this->dbname, $port, $socket, MYSQLI_CLIENT_FOUND_ROWS); if ($this->db_connect_id && $this->dbname != '') { -- cgit v1.2.1 From a759704b39fc1c1353f865a633759b1369589b67 Mon Sep 17 00:00:00 2001 From: Yuriy Rusko Date: Tue, 27 May 2014 20:18:06 +0200 Subject: [ticket/12594] Remove @package tags and update file headers PHPBB3-12594 --- phpBB/phpbb/db/driver/driver.php | 11 +++++++---- phpBB/phpbb/db/driver/driver_interface.php | 10 +++++++--- phpBB/phpbb/db/driver/firebird.php | 11 +++++++---- phpBB/phpbb/db/driver/mssql.php | 11 +++++++---- phpBB/phpbb/db/driver/mssql_base.php | 11 +++++++---- phpBB/phpbb/db/driver/mssql_odbc.php | 12 +++++++----- phpBB/phpbb/db/driver/mssqlnative.php | 16 ++++++++++------ phpBB/phpbb/db/driver/mysql.php | 11 +++++++---- phpBB/phpbb/db/driver/mysql_base.php | 11 +++++++---- phpBB/phpbb/db/driver/mysqli.php | 11 +++++++---- phpBB/phpbb/db/driver/oracle.php | 11 +++++++---- phpBB/phpbb/db/driver/postgres.php | 11 +++++++---- phpBB/phpbb/db/driver/sqlite.php | 11 +++++++---- phpBB/phpbb/db/driver/sqlite3.php | 11 +++++++---- 14 files changed, 101 insertions(+), 58 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 85d160c80e..8a8a7f8777 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ @@ -11,7 +15,6 @@ namespace phpbb\db\driver; /** * Database Abstraction Layer -* @package dbal */ abstract class driver implements driver_interface { diff --git a/phpBB/phpbb/db/driver/driver_interface.php b/phpBB/phpbb/db/driver/driver_interface.php index a9051616c9..7f7d341e2d 100644 --- a/phpBB/phpbb/db/driver/driver_interface.php +++ b/phpBB/phpbb/db/driver/driver_interface.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ diff --git a/phpBB/phpbb/db/driver/firebird.php b/phpBB/phpbb/db/driver/firebird.php index a4967c7ffe..c7b185a577 100644 --- a/phpBB/phpbb/db/driver/firebird.php +++ b/phpBB/phpbb/db/driver/firebird.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ @@ -12,7 +16,6 @@ namespace phpbb\db\driver; /** * Firebird/Interbase Database Abstraction Layer * Minimum Requirement is Firebird 2.1 -* @package dbal */ class firebird extends \phpbb\db\driver\driver { diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php index 588cd7a7e8..2e56638617 100644 --- a/phpBB/phpbb/db/driver/mssql.php +++ b/phpBB/phpbb/db/driver/mssql.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ @@ -12,7 +16,6 @@ namespace phpbb\db\driver; /** * MSSQL Database Abstraction Layer * Minimum Requirement is MSSQL 2000+ -* @package dbal */ class mssql extends \phpbb\db\driver\driver { diff --git a/phpBB/phpbb/db/driver/mssql_base.php b/phpBB/phpbb/db/driver/mssql_base.php index 1e3fb8235a..e7101903b8 100644 --- a/phpBB/phpbb/db/driver/mssql_base.php +++ b/phpBB/phpbb/db/driver/mssql_base.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ @@ -11,7 +15,6 @@ namespace phpbb\db\driver; /** * MSSQL Database Base Abstraction Layer -* @package dbal */ abstract class mssql_base extends \phpbb\db\driver\driver { diff --git a/phpBB/phpbb/db/driver/mssql_odbc.php b/phpBB/phpbb/db/driver/mssql_odbc.php index 34b913dc8a..de90d878e7 100644 --- a/phpBB/phpbb/db/driver/mssql_odbc.php +++ b/phpBB/phpbb/db/driver/mssql_odbc.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ @@ -17,8 +21,6 @@ namespace phpbb\db\driver; * @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 mssql_odbc extends \phpbb\db\driver\mssql_base { diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index b449de2ae4..9639bfa988 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -1,10 +1,17 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** * This is the MS SQL Server Native database abstraction layer. * PHP mssql native driver required. * @author Chris Pucci @@ -13,9 +20,6 @@ namespace phpbb\db\driver; -/** -* @package dbal -*/ class mssqlnative extends \phpbb\db\driver\mssql_base { var $m_insert_id = null; diff --git a/phpBB/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php index 1a4fd364df..9b6d9962c9 100644 --- a/phpBB/phpbb/db/driver/mysql.php +++ b/phpBB/phpbb/db/driver/mysql.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ @@ -16,7 +20,6 @@ namespace phpbb\db\driver; * MySQL 4.0+ * MySQL 4.1+ * MySQL 5.0+ -* @package dbal */ class mysql extends \phpbb\db\driver\mysql_base { diff --git a/phpBB/phpbb/db/driver/mysql_base.php b/phpBB/phpbb/db/driver/mysql_base.php index d0f6a9e8fa..e7c9b63f20 100644 --- a/phpBB/phpbb/db/driver/mysql_base.php +++ b/phpBB/phpbb/db/driver/mysql_base.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ @@ -11,7 +15,6 @@ namespace phpbb\db\driver; /** * Abstract MySQL Database Base Abstraction Layer -* @package dbal */ abstract class mysql_base extends \phpbb\db\driver\driver { diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index 6814599b24..da6dcbc776 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ @@ -13,7 +17,6 @@ namespace phpbb\db\driver; * MySQLi Database Abstraction Layer * mysqli-extension has to be compiled with: * MySQL 4.1+ or MySQL 5.0+ -* @package dbal */ class mysqli extends \phpbb\db\driver\mysql_base { diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index 8a304b5042..bfc5373e35 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ @@ -11,7 +15,6 @@ namespace phpbb\db\driver; /** * Oracle Database Abstraction Layer -* @package dbal */ class oracle extends \phpbb\db\driver\driver { diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index 9e091f0a5d..a4aa9497ed 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ @@ -12,7 +16,6 @@ namespace phpbb\db\driver; /** * PostgreSQL Database Abstraction Layer * Minimum Requirement is Version 7.3+ -* @package dbal */ class postgres extends \phpbb\db\driver\driver { diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php index 86a585f4eb..f4c5e240fc 100644 --- a/phpBB/phpbb/db/driver/sqlite.php +++ b/phpBB/phpbb/db/driver/sqlite.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ @@ -12,7 +16,6 @@ namespace phpbb\db\driver; /** * Sqlite Database Abstraction Layer * Minimum Requirement: 2.8.2+ -* @package dbal */ class sqlite extends \phpbb\db\driver\driver { diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php index 971b3e55d3..2c6bf99497 100644 --- a/phpBB/phpbb/db/driver/sqlite3.php +++ b/phpBB/phpbb/db/driver/sqlite3.php @@ -1,9 +1,13 @@ +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. * */ @@ -12,7 +16,6 @@ namespace phpbb\db\driver; /** * SQLite3 Database Abstraction Layer * Minimum Requirement: 3.6.15+ -* @package dbal */ class sqlite3 extends \phpbb\db\driver\driver { -- cgit v1.2.1 From 27f787e5e4e118b77a3e16879d6c684bdaafc303 Mon Sep 17 00:00:00 2001 From: Yuriy Rusko Date: Tue, 27 May 2014 21:25:33 +0200 Subject: [ticket/12594] Update footer credit lines PHPBB3-12594 --- phpBB/phpbb/db/driver/driver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 8a8a7f8777..3d4aa95606 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -817,7 +817,7 @@ abstract class driver implements driver_interface
-- cgit v1.2.1 From 34a4ba36cd554ebd3cab1bdbb422d97a9429bd72 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sun, 15 Jun 2014 20:52:51 +0200 Subject: [ticket/12721] Add Squiz.Arrays.ArrayBracketSpacing in the legacy ruleset PHPBB3-12721 --- phpBB/phpbb/db/driver/mssqlnative.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index 9639bfa988..a7f93c8feb 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -319,10 +319,10 @@ class mssqlnative extends \phpbb\db\driver\mssql_base { foreach ($errors as $error) { - $error_message .= "SQLSTATE: " . $error[ 'SQLSTATE'] . "\n"; - $error_message .= "code: " . $error[ 'code'] . "\n"; + $error_message .= "SQLSTATE: " . $error['SQLSTATE'] . "\n"; + $error_message .= "code: " . $error['code'] . "\n"; $code = $error['code']; - $error_message .= "message: " . $error[ 'message'] . "\n"; + $error_message .= "message: " . $error['message'] . "\n"; } $this->last_error_result = $error_message; $error = $this->last_error_result; -- cgit v1.2.1 From 04164affe672be6feea676fd05cf9761bf2e477a Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 20 Jun 2014 12:35:42 +0200 Subject: [ticket/12747] Drop support for Firebird PHPBB3-12747 --- phpBB/phpbb/db/driver/firebird.php | 526 ------------------------------------- 1 file changed, 526 deletions(-) delete mode 100644 phpBB/phpbb/db/driver/firebird.php (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/firebird.php b/phpBB/phpbb/db/driver/firebird.php deleted file mode 100644 index c7b185a577..0000000000 --- a/phpBB/phpbb/db/driver/firebird.php +++ /dev/null @@ -1,526 +0,0 @@ - -* @license GNU General Public License, version 2 (GPL-2.0) -* -* For full copyright and license information, please see -* the docs/CREDITS.txt file. -* -*/ - -namespace phpbb\db\driver; - -/** -* Firebird/Interbase Database Abstraction Layer -* Minimum Requirement is Firebird 2.1 -*/ -class firebird extends \phpbb\db\driver\driver -{ - var $last_query_text = ''; - var $service_handle = false; - var $affected_rows = 0; - var $connect_error = ''; - - /** - * {@inheritDoc} - */ - 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(''); - } - - /** - * {@inheritDoc} - */ - 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; - } - - /** - * {@inheritDoc} - */ - function sql_query($query = '', $cache_ttl = 0) - { - if ($query != '') - { - global $cache; - - // EXPLAIN only in extra debug mode - if (defined('DEBUG')) - { - $this->sql_report('start', $query); - } - - $this->last_query_text = $query; - $this->query_result = ($cache && $cache_ttl) ? $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')) - { - $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 && $cache_ttl) - { - $this->open_queries[(int) $this->query_result] = $this->query_result; - $this->query_result = $cache->sql_save($this, $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')) - { - $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); - } - - /** - * {@inheritDoc} - */ - 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; - } - } - - /** - * {@inheritDoc} - */ - function sql_fetchrow($query_id = false) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if ($cache && $cache->sql_exists($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; - } - - /** - * {@inheritDoc} - */ - 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; - } - - /** - * {@inheritDoc} - */ - function sql_freeresult($query_id = false) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if ($cache && !is_object($query_id) && $cache->sql_exists($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; - } - - /** - * {@inheritDoc} - */ - 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 : ''); - } - - /** - * {@inheritDoc} - */ - function cast_expr_to_bigint($expression) - { - // Precision must be from 1 to 18 - return 'CAST(' . $expression . ' as DECIMAL(18, 0))'; - } - - /** - * {@inheritDoc} - */ - function cast_expr_to_string($expression) - { - return 'CAST(' . $expression . ' as VARCHAR(255))'; - } - - /** - * 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; - } - } -} -- cgit v1.2.1 From f850d5fa90584bb73ef1a77fd21f825e1d0794ed Mon Sep 17 00:00:00 2001 From: rxu Date: Sat, 14 Jun 2014 20:53:34 +0800 Subject: [ticket/12704] Improve the load time information in the footer when enabled PR #2570 has added new constant to display load time information without debug mode is being on (https://tracker.phpbb.com/browse/PHPBB3-12687). This patch expands the total load time info with SQL/PHP load times, while hiding the additional info with element. PHPBB3-12704 --- phpBB/phpbb/db/driver/firebird.php | 8 ++++++++ phpBB/phpbb/db/driver/mssql.php | 8 ++++++++ phpBB/phpbb/db/driver/mssql_odbc.php | 8 ++++++++ phpBB/phpbb/db/driver/mssqlnative.php | 8 ++++++++ phpBB/phpbb/db/driver/mysql.php | 8 ++++++++ phpBB/phpbb/db/driver/mysqli.php | 8 ++++++++ phpBB/phpbb/db/driver/oracle.php | 8 ++++++++ phpBB/phpbb/db/driver/postgres.php | 8 ++++++++ phpBB/phpbb/db/driver/sqlite.php | 8 ++++++++ phpBB/phpbb/db/driver/sqlite3.php | 8 ++++++++ 10 files changed, 80 insertions(+) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/firebird.php b/phpBB/phpbb/db/driver/firebird.php index c7b185a577..67d7f12b66 100644 --- a/phpBB/phpbb/db/driver/firebird.php +++ b/phpBB/phpbb/db/driver/firebird.php @@ -140,6 +140,10 @@ class firebird extends \phpbb\db\driver\driver { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->last_query_text = $query; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; @@ -241,6 +245,10 @@ class firebird extends \phpbb\db\driver\driver { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if (!$this->transaction) { diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php index 2e56638617..268463a151 100644 --- a/phpBB/phpbb/db/driver/mssql.php +++ b/phpBB/phpbb/db/driver/mssql.php @@ -137,6 +137,10 @@ class mssql extends \phpbb\db\driver\driver { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); @@ -152,6 +156,10 @@ class mssql extends \phpbb\db\driver\driver { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if ($cache && $cache_ttl) { diff --git a/phpBB/phpbb/db/driver/mssql_odbc.php b/phpBB/phpbb/db/driver/mssql_odbc.php index de90d878e7..8e5d4c7a4c 100644 --- a/phpBB/phpbb/db/driver/mssql_odbc.php +++ b/phpBB/phpbb/db/driver/mssql_odbc.php @@ -156,6 +156,10 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->last_query_text = $query; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; @@ -172,6 +176,10 @@ class mssql_odbc extends \phpbb\db\driver\mssql_base { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if ($cache && $cache_ttl) { diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index 9639bfa988..dbeef7e0d7 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -127,6 +127,10 @@ class mssqlnative extends \phpbb\db\driver\mssql_base { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->last_query_text = $query; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; @@ -145,6 +149,10 @@ class mssqlnative extends \phpbb\db\driver\mssql_base { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if ($cache && $cache_ttl) { diff --git a/phpBB/phpbb/db/driver/mysql.php b/phpBB/phpbb/db/driver/mysql.php index 569bd4f10a..e93c7239e8 100644 --- a/phpBB/phpbb/db/driver/mysql.php +++ b/phpBB/phpbb/db/driver/mysql.php @@ -166,6 +166,10 @@ class mysql extends \phpbb\db\driver\mysql_base { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); @@ -181,6 +185,10 @@ class mysql extends \phpbb\db\driver\mysql_base { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if ($cache && $cache_ttl) { diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index 58361ff0f8..ad4cdaef5c 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -165,6 +165,10 @@ class mysqli extends \phpbb\db\driver\mysql_base { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); @@ -180,6 +184,10 @@ class mysqli extends \phpbb\db\driver\mysql_base { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if ($cache && $cache_ttl) { diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index bfc5373e35..d1a186f1ba 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -253,6 +253,10 @@ class oracle extends \phpbb\db\driver\driver { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->last_query_text = $query; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; @@ -430,6 +434,10 @@ class oracle extends \phpbb\db\driver\driver { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if ($cache && $cache_ttl) { diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index a4aa9497ed..a67cd9f7c2 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -179,6 +179,10 @@ class postgres extends \phpbb\db\driver\driver { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->last_query_text = $query; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; @@ -195,6 +199,10 @@ class postgres extends \phpbb\db\driver\driver { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if ($cache && $cache_ttl) { diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php index f4c5e240fc..2112e5ba2f 100644 --- a/phpBB/phpbb/db/driver/sqlite.php +++ b/phpBB/phpbb/db/driver/sqlite.php @@ -121,6 +121,10 @@ class sqlite extends \phpbb\db\driver\driver { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); @@ -136,6 +140,10 @@ class sqlite extends \phpbb\db\driver\driver { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if ($cache && $cache_ttl) { diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php index 2c6bf99497..6511c755a0 100644 --- a/phpBB/phpbb/db/driver/sqlite3.php +++ b/phpBB/phpbb/db/driver/sqlite3.php @@ -121,6 +121,10 @@ class sqlite3 extends \phpbb\db\driver\driver { $this->sql_report('start', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->curtime = microtime(true); + } $this->last_query_text = $query; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; @@ -137,6 +141,10 @@ class sqlite3 extends \phpbb\db\driver\driver { $this->sql_report('stop', $query); } + else if (defined('PHPBB_DISPLAY_LOAD_TIME')) + { + $this->sql_time += microtime(true) - $this->curtime; + } if ($cache && $cache_ttl) { -- cgit v1.2.1 From 89a7a551902e66a057f5d8a069c37307b91efc16 Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Sat, 21 Jun 2014 11:52:32 +0200 Subject: [ticket/12756] Fix mysqli_fetch_assoc on hhvm PHPBB3-12756 --- phpBB/phpbb/db/driver/mysqli.php | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index 58361ff0f8..520bb65b67 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -71,10 +71,17 @@ class mysqli extends \phpbb\db\driver\mysql_base 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); + if ($result !== null) + { + $row = @mysqli_fetch_assoc($result); - $modes = array_map('trim', explode(',', $row['sql_mode'])); + $modes = array_map('trim', explode(',', $row['sql_mode'])); + } + else + { + $modes = array(); + } + @mysqli_free_result($result); // TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES if (!in_array('TRADITIONAL', $modes)) @@ -109,15 +116,18 @@ class mysqli extends \phpbb\db\driver\mysql_base 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); + if ($result !== null) + { + $row = @mysqli_fetch_assoc($result); - $this->sql_server_version = $row['version']; + $this->sql_server_version = $row['version']; - if (!empty($cache) && $use_cache) - { - $cache->put('mysqli_version', $this->sql_server_version); + if (!empty($cache) && $use_cache) + { + $cache->put('mysqli_version', $this->sql_server_version); + } } + @mysqli_free_result($result); } return ($raw) ? $this->sql_server_version : 'MySQL(i) ' . $this->sql_server_version; @@ -224,7 +234,7 @@ class mysqli extends \phpbb\db\driver\mysql_base return $cache->sql_fetchrow($query_id); } - if ($query_id !== false) + if ($query_id !== false && $query_id !== null) { $result = @mysqli_fetch_assoc($query_id); return $result !== null ? $result : false; @@ -434,9 +444,12 @@ class mysqli extends \phpbb\db\driver\mysql_base $endtime = $endtime[0] + $endtime[1]; $result = @mysqli_query($this->db_connect_id, $query); - while ($void = @mysqli_fetch_assoc($result)) + if ($result !== null) { - // Take the time spent on parsing rows into account + while ($void = @mysqli_fetch_assoc($result)) + { + // Take the time spent on parsing rows into account + } } @mysqli_free_result($result); -- cgit v1.2.1 From 40a65abc3ae312876842cc3e19220e74fa002667 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 26 Jun 2014 14:25:40 +0200 Subject: [ticket/12764] Properly handle errors upon connecting to MySQLi database As the db_connect_id gets set up by mysql_init(), the db_connect_id will be an object with empty settings instead of just empty. Even if mysql_real_connect() encounters an error upon connecting, the db_connect_id is still set. This will result in trying to just access the database which obviously does nothing. By setting db_connect_id to an empty string, the script will not try to query th database and properly handle any errors that occur upon connecting. PHPBB3-12764 --- phpBB/phpbb/db/driver/mysqli.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index 8fc306b2cc..2ed08211ad 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -61,7 +61,11 @@ class mysqli extends \phpbb\db\driver\mysql_base } $this->db_connect_id = mysqli_init(); - @mysqli_real_connect($this->db_connect_id, $this->server, $this->user, $sqlpassword, $this->dbname, $port, $socket, MYSQLI_CLIENT_FOUND_ROWS); + + if (!@mysqli_real_connect($this->db_connect_id, $this->server, $this->user, $sqlpassword, $this->dbname, $port, $socket, MYSQLI_CLIENT_FOUND_ROWS)) + { + $this->db_connect_id = ''; + } if ($this->db_connect_id && $this->dbname != '') { -- cgit v1.2.1 From ff6e026a403a622bd1aa498bff396a737735faed Mon Sep 17 00:00:00 2001 From: Tristan Darricau Date: Thu, 26 Jun 2014 17:17:35 +0200 Subject: [ticket/12446] Unnecessary db connect inphpbb_bootstrap_enabled_exts PHPBB3-12446 --- phpBB/phpbb/db/driver/driver.php | 96 +++++++ phpBB/phpbb/db/driver/driver_interface.php | 84 ++++++ phpBB/phpbb/db/driver/factory.php | 435 +++++++++++++++++++++++++++++ 3 files changed, 615 insertions(+) create mode 100644 phpBB/phpbb/db/driver/factory.php (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 3d4aa95606..3e9110d8bc 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -86,6 +86,102 @@ abstract class driver implements driver_interface $this->one_char = chr(0) . '_'; } + /** + * {@inheritdoc} + */ + public function get_sql_layer() + { + return $this->sql_layer; + } + + /** + * {@inheritdoc} + */ + public function get_db_name() + { + return $this->dbname; + } + + /** + * {@inheritdoc} + */ + public function get_any_char() + { + return $this->any_char; + } + + /** + * {@inheritdoc} + */ + public function get_one_char() + { + return $this->one_char; + } + + /** + * {@inheritdoc} + */ + public function get_db_connect_id() + { + return $this->db_connect_id; + } + + /** + * {@inheritdoc} + */ + public function get_sql_error_triggered() + { + return $this->sql_error_triggered; + } + + /** + * {@inheritdoc} + */ + public function get_sql_error_sql() + { + return $this->sql_error_sql; + } + + /** + * {@inheritdoc} + */ + public function get_transaction() + { + return $this->transaction; + } + + /** + * {@inheritdoc} + */ + public function get_sql_time() + { + return $this->sql_time; + } + + /** + * {@inheritdoc} + */ + public function get_sql_error_returned() + { + return $this->sql_error_returned; + } + + /** + * {@inheritdoc} + */ + public function get_multi_insert() + { + return $this->multi_insert; + } + + /** + * {@inheritdoc} + */ + public function set_multi_insert($multi_insert) + { + $this->multi_insert = $multi_insert; + } + /** * {@inheritDoc} */ diff --git a/phpBB/phpbb/db/driver/driver_interface.php b/phpBB/phpbb/db/driver/driver_interface.php index 7f7d341e2d..6722d059a5 100644 --- a/phpBB/phpbb/db/driver/driver_interface.php +++ b/phpBB/phpbb/db/driver/driver_interface.php @@ -15,6 +15,90 @@ namespace phpbb\db\driver; interface driver_interface { + /** + * Gets the name of the sql layer. + * + * @return string + */ + public function get_sql_layer(); + + /** + * Gets the name of the database. + * + * @return string + */ + public function get_db_name(); + + /** + * Wildcards for matching any (%) character within LIKE expressions + * + * @return string + */ + public function get_any_char(); + + /** + * Wildcards for matching exactly one (_) character within LIKE expressions + * + * @return string + */ + public function get_one_char(); + + /** + * Gets the time spent into the queries + * + * @return int + */ + public function get_sql_time(); + + /** + * Gets the connect ID. + * + * @return mixed + */ + public function get_db_connect_id(); + + /** + * Indicates if an error was triggered. + * + * @return bool + */ + public function get_sql_error_triggered(); + + /** + * Gets the last faulty query + * + * @return string + */ + public function get_sql_error_sql(); + + /** + * Indicates if we are in a transaction. + * + * @return bool + */ + public function get_transaction(); + + /** + * Gets the returned error. + * + * @return array + */ + public function get_sql_error_returned(); + + /** + * Indicates if multiple insertion can be used + * + * @return bool + */ + public function get_multi_insert(); + + /** + * Set if multiple insertion can be used + * + * @param bool $multi_insert + */ + public function set_multi_insert($multi_insert); + /** * Gets the exact number of rows in a specified table. * diff --git a/phpBB/phpbb/db/driver/factory.php b/phpBB/phpbb/db/driver/factory.php new file mode 100644 index 0000000000..f0fa18051b --- /dev/null +++ b/phpBB/phpbb/db/driver/factory.php @@ -0,0 +1,435 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\driver; + +use \Symfony\Component\DependencyInjection\ContainerInterface; + +/** +* Database Abstraction Layer +*/ +class factory implements driver_interface +{ + /** + * @var driver_interface + */ + protected $driver = null; + + /** + * @var ContainerInterface + */ + protected $container; + + /** + * Constructor. + * + * @param ContainerInterface $container A ContainerInterface instance + */ + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * Return the current driver (and retrieved it from the container if necessary) + * + * @return driver_interface + */ + protected function get_driver() + { + if ($this->driver === null) + { + $this->driver = $this->container->get('dbal.conn.driver'); + } + + return $this->driver; + } + + /** + * Set the current driver + * + * @param driver_interface $driver + */ + public function set_driver(driver_interface $driver) + { + $this->driver = $driver; + } + + /** + * {@inheritdoc} + */ + public function get_sql_layer() + { + return $this->get_driver()->get_sql_layer(); + } + + /** + * {@inheritdoc} + */ + public function get_db_name() + { + return $this->get_driver()->get_db_name(); + } + + /** + * {@inheritdoc} + */ + public function get_any_char() + { + return $this->get_driver()->get_any_char(); + } + + /** + * {@inheritdoc} + */ + public function get_one_char() + { + return $this->get_driver()->get_one_char(); + } + + /** + * {@inheritdoc} + */ + public function get_db_connect_id() + { + return $this->get_driver()->get_db_connect_id(); + } + + /** + * {@inheritdoc} + */ + public function get_sql_error_triggered() + { + return $this->get_driver()->get_sql_error_triggered(); + } + + /** + * {@inheritdoc} + */ + public function get_sql_error_sql() + { + return $this->get_driver()->get_sql_error_sql(); + } + + /** + * {@inheritdoc} + */ + public function get_transaction() + { + return $this->get_driver()->get_transaction(); + } + + /** + * {@inheritdoc} + */ + public function get_sql_time() + { + return $this->get_driver()->get_sql_time(); + } + + /** + * {@inheritdoc} + */ + public function get_sql_error_returned() + { + return $this->get_driver()->get_sql_error_returned(); + } + + /** + * {@inheritdoc} + */ + public function get_multi_insert() + { + return $this->get_driver()->get_multi_insert(); + } + + /** + * {@inheritdoc} + */ + public function set_multi_insert($multi_insert) + { + $this->get_driver()->set_multi_insert($multi_insert); + } + + /** + * {@inheritdoc} + */ + public function get_row_count($table_name) + { + return $this->get_driver()->get_row_count($table_name); + } + + /** + * {@inheritdoc} + */ + public function get_estimated_row_count($table_name) + { + return $this->get_driver()->get_estimated_row_count($table_name); + } + + /** + * {@inheritdoc} + */ + public function sql_lower_text($column_name) + { + return $this->get_driver()->sql_lower_text($column_name); + } + + /** + * {@inheritdoc} + */ + public function sql_error($sql = '') + { + return $this->get_driver()->sql_error($sql); + } + + /** + * {@inheritdoc} + */ + public function sql_buffer_nested_transactions() + { + return $this->get_driver()->sql_buffer_nested_transactions(); + } + + /** + * {@inheritdoc} + */ + public function sql_bit_or($column_name, $bit, $compare = '') + { + return $this->get_driver()->sql_bit_or($column_name, $bit, $compare); + } + + /** + * {@inheritdoc} + */ + public function sql_server_info($raw = false, $use_cache = true) + { + return $this->get_driver()->sql_server_info($raw, $use_cache); + } + + /** + * {@inheritdoc} + */ + public function sql_return_on_error($fail = false) + { + return $this->get_driver()->sql_return_on_error($fail); + } + + /** + * {@inheritdoc} + */ + public function sql_build_array($query, $assoc_ary = array()) + { + return $this->get_driver()->sql_build_array($query, $assoc_ary); + } + + /** + * {@inheritdoc} + */ + public function sql_fetchrowset($query_id = false) + { + return $this->get_driver()->sql_fetchrowset($query_id); + } + + /** + * {@inheritdoc} + */ + public function sql_transaction($status = 'begin') + { + return $this->get_driver()->sql_transaction($status); + } + + /** + * {@inheritdoc} + */ + public function sql_concatenate($expr1, $expr2) + { + return $this->get_driver()->sql_concatenate($expr1, $expr2); + } + + /** + * {@inheritdoc} + */ + public function sql_case($condition, $action_true, $action_false = false) + { + return $this->get_driver()->sql_case($condition, $action_true, $action_false); + } + + /** + * {@inheritdoc} + */ + public function sql_build_query($query, $array) + { + return $this->get_driver()->sql_build_query($query, $array); + } + + /** + * {@inheritdoc} + */ + public function sql_fetchfield($field, $rownum = false, $query_id = false) + { + return $this->get_driver()->sql_fetchfield($field, $rownum, $query_id); + } + + /** + * {@inheritdoc} + */ + public function sql_fetchrow($query_id = false) + { + return $this->get_driver()->sql_fetchrow($query_id); + } + + /** + * {@inheritdoc} + */ + public function cast_expr_to_bigint($expression) + { + return $this->get_driver()->cast_expr_to_bigint($expression); + } + + /** + * {@inheritdoc} + */ + public function sql_nextid() + { + return $this->get_driver()->sql_nextid(); + } + + /** + * {@inheritdoc} + */ + public function sql_add_num_queries($cached = false) + { + return $this->get_driver()->sql_add_num_queries($cached); + } + + /** + * {@inheritdoc} + */ + public function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) + { + return $this->get_driver()->sql_query_limit($query, $total, $offset, $cache_ttl); + } + + /** + * {@inheritdoc} + */ + public function sql_query($query = '', $cache_ttl = 0) + { + return $this->get_driver()->sql_query($query, $cache_ttl); + } + + /** + * {@inheritdoc} + */ + public function cast_expr_to_string($expression) + { + return $this->get_driver()->cast_expr_to_string($expression); + } + + /** + * {@inheritdoc} + */ + public function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) + { + throw new \Exception('Disabled method.'); + } + + /** + * {@inheritdoc} + */ + public function sql_bit_and($column_name, $bit, $compare = '') + { + return $this->get_driver()->sql_bit_and($column_name, $bit, $compare); + } + + /** + * {@inheritdoc} + */ + public function sql_freeresult($query_id = false) + { + return $this->get_driver()->sql_freeresult($query_id); + } + + /** + * {@inheritdoc} + */ + public function sql_num_queries($cached = false) + { + return $this->get_driver()->sql_num_queries($cached); + } + + /** + * {@inheritdoc} + */ + public function sql_multi_insert($table, $sql_ary) + { + return $this->get_driver()->sql_multi_insert($table, $sql_ary); + } + + /** + * {@inheritdoc} + */ + public function sql_affectedrows() + { + return $this->get_driver()->sql_affectedrows(); + } + + /** + * {@inheritdoc} + */ + public function sql_close() + { + return $this->get_driver()->sql_close(); + } + + /** + * {@inheritdoc} + */ + public function sql_rowseek($rownum, &$query_id) + { + return $this->get_driver()->sql_rowseek($rownum, $query_id); + } + + /** + * {@inheritdoc} + */ + public function sql_escape($msg) + { + return $this->get_driver()->sql_escape($msg); + } + + /** + * {@inheritdoc} + */ + public function sql_like_expression($expression) + { + return $this->get_driver()->sql_like_expression($expression); + } + + /** + * {@inheritdoc} + */ + public function sql_report($mode, $query = '') + { + return $this->get_driver()->sql_report($mode, $query); + } + + /** + * {@inheritdoc} + */ + public function sql_in_set($field, $array, $negate = false, $allow_empty_set = false) + { + return $this->get_driver()->sql_in_set($field, $array, $negate, $allow_empty_set); + } +} -- cgit v1.2.1 From 3ca708edadce1c82903559f384fd15638d0ab2de Mon Sep 17 00:00:00 2001 From: Patrick Webster Date: Thu, 3 Jul 2014 13:05:54 -0500 Subject: [ticket/12802] Properly handle connection failures in SQLite3 PHPBB3-12802 --- phpBB/phpbb/db/driver/sqlite3.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php index 2c6bf99497..36d8a83f4b 100644 --- a/phpBB/phpbb/db/driver/sqlite3.php +++ b/phpBB/phpbb/db/driver/sqlite3.php @@ -50,9 +50,10 @@ class sqlite3 extends \phpbb\db\driver\driver $this->dbo = new \SQLite3($this->server, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE); $this->db_connect_id = true; } - catch (Exception $e) + catch (\Exception $e) { - return array('message' => $e->getMessage()); + $this->connect_error = $e->getMessage(); + return array('message' => $this->connect_error); } return true; @@ -272,7 +273,7 @@ class sqlite3 extends \phpbb\db\driver\driver */ protected function _sql_error() { - if (class_exists('SQLite3', false)) + if (class_exists('SQLite3', false) && isset($this->dbo)) { $error = array( 'message' => $this->dbo->lastErrorMsg(), -- cgit v1.2.1 From b08497f66c6008dc9bf178e7479435a860f12f9f Mon Sep 17 00:00:00 2001 From: n-aleha Date: Mon, 7 Jul 2014 23:10:18 +0300 Subject: [ticket/12829] Remove check for pgsql 8.3/8.2 Remove check for pgsql 8.3/8.2 and set multi_insert to true. PHPBB3-12829 --- phpBB/phpbb/db/driver/postgres.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index a67cd9f7c2..83e9fa51f6 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -15,10 +15,11 @@ namespace phpbb\db\driver; /** * PostgreSQL Database Abstraction Layer -* Minimum Requirement is Version 7.3+ +* Minimum Requirement is Version 8.3+ */ class postgres extends \phpbb\db\driver\driver { + var $multi_insert = true; var $last_query_text = ''; var $connect_error = ''; @@ -101,11 +102,6 @@ class postgres extends \phpbb\db\driver\driver 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); -- cgit v1.2.1 From 6b60153ab4ac036bcd4eaaa90806d9898fc1e9a2 Mon Sep 17 00:00:00 2001 From: Geolim4 Date: Fri, 8 Aug 2014 15:06:12 +0200 Subject: [ticket/12671] Possibility to use NOT LIKE expression PHPBB3-12671 --- phpBB/phpbb/db/driver/driver.php | 11 +++++++++++ phpBB/phpbb/db/driver/driver_interface.php | 10 ++++++++++ phpBB/phpbb/db/driver/factory.php | 8 ++++++++ phpBB/phpbb/db/driver/mssql.php | 9 +++++++++ phpBB/phpbb/db/driver/mssql_base.php | 9 +++++++++ phpBB/phpbb/db/driver/mysql_base.php | 9 +++++++++ phpBB/phpbb/db/driver/oracle.php | 9 +++++++++ phpBB/phpbb/db/driver/postgres.php | 9 +++++++++ phpBB/phpbb/db/driver/sqlite.php | 17 +++++++++++++++++ 9 files changed, 91 insertions(+) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 3e9110d8bc..ed650bd6a9 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -369,6 +369,17 @@ abstract class driver implements driver_interface return $this->_sql_like_expression('LIKE \'' . $this->sql_escape($expression) . '\''); } + /** + * {@inheritDoc} + */ + function sql_not_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('NOT LIKE \'' . $this->sql_escape($expression) . '\''); + } + /** * {@inheritDoc} */ diff --git a/phpBB/phpbb/db/driver/driver_interface.php b/phpBB/phpbb/db/driver/driver_interface.php index 6722d059a5..8b487c5d42 100644 --- a/phpBB/phpbb/db/driver/driver_interface.php +++ b/phpBB/phpbb/db/driver/driver_interface.php @@ -418,6 +418,16 @@ interface driver_interface */ public function sql_like_expression($expression); + /** + * Correctly adjust NOT 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 A SQL statement like: "NOT LIKE 'bertie_%'" + */ + public function sql_not_like_expression($expression); + /** * Explain queries * diff --git a/phpBB/phpbb/db/driver/factory.php b/phpBB/phpbb/db/driver/factory.php index f0fa18051b..fb3a826254 100644 --- a/phpBB/phpbb/db/driver/factory.php +++ b/phpBB/phpbb/db/driver/factory.php @@ -417,6 +417,14 @@ class factory implements driver_interface return $this->get_driver()->sql_like_expression($expression); } + /** + * {@inheritdoc} + */ + public function sql_not_like_expression($expression) + { + return $this->get_driver()->sql_not_like_expression($expression); + } + /** * {@inheritdoc} */ diff --git a/phpBB/phpbb/db/driver/mssql.php b/phpBB/phpbb/db/driver/mssql.php index 268463a151..f9ea884ce2 100644 --- a/phpBB/phpbb/db/driver/mssql.php +++ b/phpBB/phpbb/db/driver/mssql.php @@ -350,6 +350,15 @@ class mssql extends \phpbb\db\driver\driver return $expression . " ESCAPE '\\'"; } + /** + * Build NOT LIKE expression + * @access private + */ + function _sql_not_like_expression($expression) + { + return $expression . " ESCAPE '\\'"; + } + /** * return sql error array * @access private diff --git a/phpBB/phpbb/db/driver/mssql_base.php b/phpBB/phpbb/db/driver/mssql_base.php index e7101903b8..514df9eaca 100644 --- a/phpBB/phpbb/db/driver/mssql_base.php +++ b/phpBB/phpbb/db/driver/mssql_base.php @@ -51,6 +51,15 @@ abstract class mssql_base extends \phpbb\db\driver\driver return $expression . " ESCAPE '\\'"; } + /** + * Build NOT LIKE expression + * @access private + */ + function _sql_not_like_expression($expression) + { + return $expression . " ESCAPE '\\'"; + } + /** * Build db-specific query data * @access private diff --git a/phpBB/phpbb/db/driver/mysql_base.php b/phpBB/phpbb/db/driver/mysql_base.php index e7c9b63f20..5e0b359134 100644 --- a/phpBB/phpbb/db/driver/mysql_base.php +++ b/phpBB/phpbb/db/driver/mysql_base.php @@ -111,6 +111,15 @@ abstract class mysql_base extends \phpbb\db\driver\driver return $expression; } + /** + * Build NOT LIKE expression + * @access private + */ + function _sql_not_like_expression($expression) + { + return $expression; + } + /** * Build db-specific query data * @access private diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index d1a186f1ba..6dcab5dd7d 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -645,6 +645,15 @@ class oracle extends \phpbb\db\driver\driver return $expression . " ESCAPE '\\'"; } + /** + * Build NOT LIKE expression + * @access private + */ + function _sql_not_like_expression($expression) + { + return $expression . " ESCAPE '\\'"; + } + function _sql_custom_build($stage, $data) { return $data; diff --git a/phpBB/phpbb/db/driver/postgres.php b/phpBB/phpbb/db/driver/postgres.php index 83e9fa51f6..a3b9aa4c6b 100644 --- a/phpBB/phpbb/db/driver/postgres.php +++ b/phpBB/phpbb/db/driver/postgres.php @@ -370,6 +370,15 @@ class postgres extends \phpbb\db\driver\driver return $expression; } + /** + * Build NOT LIKE expression + * @access private + */ + function _sql_not_like_expression($expression) + { + return $expression; + } + /** * {@inheritDoc} */ diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php index 2112e5ba2f..841662c1ed 100644 --- a/phpBB/phpbb/db/driver/sqlite.php +++ b/phpBB/phpbb/db/driver/sqlite.php @@ -287,6 +287,23 @@ class sqlite extends \phpbb\db\driver\driver return 'GLOB \'' . $this->sql_escape($expression) . '\''; } + /** + * {@inheritDoc} + * + * For SQLite an underscore is a not-known character... this may change with SQLite3 + */ + function sql_not_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 -- cgit v1.2.1 From 01943adbf72e137b9dfbda3ac85120c21a30fab8 Mon Sep 17 00:00:00 2001 From: Geolim4 Date: Fri, 8 Aug 2014 18:32:17 +0200 Subject: [ticket/12671] Possibility to use NOT LIKE expression PHPBB3-12671 --- phpBB/phpbb/db/driver/driver.php | 2 +- phpBB/phpbb/db/driver/sqlite3.php | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index ed650bd6a9..9fc04d47a1 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -377,7 +377,7 @@ abstract class driver implements driver_interface $expression = utf8_str_replace(array('_', '%'), array("\_", "\%"), $expression); $expression = utf8_str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression); - return $this->_sql_like_expression('NOT LIKE \'' . $this->sql_escape($expression) . '\''); + return $this->_sql_not_like_expression('NOT LIKE \'' . $this->sql_escape($expression) . '\''); } /** diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php index 0922229e0a..f79245afb1 100644 --- a/phpBB/phpbb/db/driver/sqlite3.php +++ b/phpBB/phpbb/db/driver/sqlite3.php @@ -274,6 +274,23 @@ class sqlite3 extends \phpbb\db\driver\driver return 'GLOB \'' . $this->sql_escape($expression) . '\''; } + /** + * {@inheritDoc} + * + * For SQLite an underscore is a not-known character... + */ + public function sql_not_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 * -- cgit v1.2.1 From 635cde218c786f76397c3354e59f96a8a151c132 Mon Sep 17 00:00:00 2001 From: Geolim4 Date: Sat, 9 Aug 2014 15:04:39 +0200 Subject: [ticket/12671] Possibility to use NOT LIKE expression PHPBB3-12671 --- phpBB/phpbb/db/driver/sqlite.php | 4 ++-- phpBB/phpbb/db/driver/sqlite3.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php index 841662c1ed..68372200b6 100644 --- a/phpBB/phpbb/db/driver/sqlite.php +++ b/phpBB/phpbb/db/driver/sqlite.php @@ -294,14 +294,14 @@ class sqlite extends \phpbb\db\driver\driver */ function sql_not_like_expression($expression) { - // Unlike LIKE, GLOB is case sensitive (unfortunatly). SQLite users need to live with it! + // Unlike NOT LIKE, NOT 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 'NOT GLOB \'' . $this->sql_escape($expression) . '\''; } /** diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php index f79245afb1..2bf4ed51aa 100644 --- a/phpBB/phpbb/db/driver/sqlite3.php +++ b/phpBB/phpbb/db/driver/sqlite3.php @@ -281,14 +281,14 @@ class sqlite3 extends \phpbb\db\driver\driver */ public function sql_not_like_expression($expression) { - // Unlike LIKE, GLOB is case sensitive (unfortunatly). SQLite users need to live with it! + // Unlike NOT LIKE,NOT 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 'NOT GLOB \'' . $this->sql_escape($expression) . '\''; } /** -- cgit v1.2.1 From db0815f680d4ed9da845facb6e8e3975ac14621e Mon Sep 17 00:00:00 2001 From: Geolim4 Date: Sat, 9 Aug 2014 19:11:21 +0200 Subject: [ticket/12671] Possibility to use NOT LIKE expression PHPBB3-12671 --- phpBB/phpbb/db/driver/sqlite.php | 6 +++--- phpBB/phpbb/db/driver/sqlite3.php | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/sqlite.php b/phpBB/phpbb/db/driver/sqlite.php index 68372200b6..d5da0e2438 100644 --- a/phpBB/phpbb/db/driver/sqlite.php +++ b/phpBB/phpbb/db/driver/sqlite.php @@ -277,7 +277,7 @@ class sqlite extends \phpbb\db\driver\driver */ function sql_like_expression($expression) { - // Unlike LIKE, GLOB is case sensitive (unfortunatly). SQLite users need to live with it! + // Unlike LIKE, GLOB is unfortunately case sensitive. // 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); @@ -290,11 +290,11 @@ class sqlite extends \phpbb\db\driver\driver /** * {@inheritDoc} * - * For SQLite an underscore is a not-known character... this may change with SQLite3 + * For SQLite an underscore is a not-known character... */ function sql_not_like_expression($expression) { - // Unlike NOT LIKE, NOT GLOB is case sensitive (unfortunatly). SQLite users need to live with it! + // Unlike NOT LIKE, NOT GLOB is unfortunately case sensitive. // 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); diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php index 2bf4ed51aa..4e3e0d3329 100644 --- a/phpBB/phpbb/db/driver/sqlite3.php +++ b/phpBB/phpbb/db/driver/sqlite3.php @@ -260,11 +260,11 @@ class sqlite3 extends \phpbb\db\driver\driver /** * {@inheritDoc} * - * For SQLite an underscore is a not-known character... + * For SQLite an underscore is an unknown character. */ public function sql_like_expression($expression) { - // Unlike LIKE, GLOB is case sensitive (unfortunatly). SQLite users need to live with it! + // Unlike LIKE, GLOB is unfortunately case sensitive. // 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); @@ -277,11 +277,11 @@ class sqlite3 extends \phpbb\db\driver\driver /** * {@inheritDoc} * - * For SQLite an underscore is a not-known character... + * For SQLite an underscore is an unknown character. */ public function sql_not_like_expression($expression) { - // Unlike NOT LIKE,NOT GLOB is case sensitive (unfortunatly). SQLite users need to live with it! + // Unlike NOT LIKE, NOT GLOB is unfortunately case sensitive // 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); -- cgit v1.2.1 From f23d2ec42fea8f22366e4ecd644fabcf4a36c5b0 Mon Sep 17 00:00:00 2001 From: Jakub Senko Date: Mon, 16 Feb 2015 20:25:11 +0100 Subject: [ticket/13570] Remove unnecessary ternary condition from mysqli driver PHPBB3-13570 --- phpBB/phpbb/db/driver/mysqli.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/mysqli.php b/phpBB/phpbb/db/driver/mysqli.php index 2ed08211ad..c0ddfbf76c 100644 --- a/phpBB/phpbb/db/driver/mysqli.php +++ b/phpBB/phpbb/db/driver/mysqli.php @@ -34,8 +34,7 @@ class mysqli extends \phpbb\db\driver\mysql_base 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->persistency = $persistency; $this->user = $sqluser; // If persistent connection, set dbhost to localhost when empty and prepend it with 'p:' prefix -- cgit v1.2.1 From 50a7167c9a76404a1e3cfb207b303920ce2b3827 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Wed, 19 Aug 2015 16:12:01 -0700 Subject: [ticket/14116] sql_affectedrows method has no arguments PHPBB3-14116 --- phpBB/phpbb/db/driver/driver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 9fc04d47a1..1b49775b32 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -962,7 +962,7 @@ abstract class driver implements driver_interface { if (preg_match('/^(UPDATE|DELETE|REPLACE)/', $query)) { - $this->sql_report .= 'Affected rows: ' . $this->sql_affectedrows($this->query_result) . ' | '; + $this->sql_report .= 'Affected rows: ' . $this->sql_affectedrows() . ' | '; } $this->sql_report .= 'Before: ' . sprintf('%.5f', $this->curtime - $starttime) . 's | After: ' . sprintf('%.5f', $endtime - $starttime) . 's | Elapsed: ' . sprintf('%.5f', $endtime - $this->curtime) . 's'; } -- cgit v1.2.1 From ea594d00f750843997fcbbd829a64c8cc983fca2 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 7 Sep 2015 12:23:49 +0200 Subject: [ticket/13423] Set busyTimeout on connect to prevent db locking PHPBB3-13423 --- phpBB/phpbb/db/driver/sqlite3.php | 1 + 1 file changed, 1 insertion(+) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php index 4e3e0d3329..cc3352af34 100644 --- a/phpBB/phpbb/db/driver/sqlite3.php +++ b/phpBB/phpbb/db/driver/sqlite3.php @@ -48,6 +48,7 @@ class sqlite3 extends \phpbb\db\driver\driver try { $this->dbo = new \SQLite3($this->server, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE); + $this->dbo->busyTimeout(60000); $this->db_connect_id = true; } catch (\Exception $e) -- cgit v1.2.1 From 244d171cb035f0229ad2a06d01062ca809a72025 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 24 Mar 2016 16:07:07 +0100 Subject: [ticket/14136] Add back X-UA-Compatible meta tag This was previously removed without needing to. Adding it back to force users to not emulate the page for previous versions of IE. The imagetoolbar http-equiv tag was not restored as IE does not contain that anymore since IE7. Also, the chome=1 has been removed from the X-UA-Compatible content as ChromeFrame does not receive any further updates since 2014 and is potentially broken. PHPBB3-14136 --- phpBB/phpbb/db/driver/driver.php | 1 + 1 file changed, 1 insertion(+) (limited to 'phpBB/phpbb/db/driver') diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 1b49775b32..01dd66cd6e 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -897,6 +897,7 @@ abstract class driver implements driver_interface + SQL Report -- cgit v1.2.1