diff options
Diffstat (limited to 'phpBB/phpbb/db/driver')
-rw-r--r-- | phpBB/phpbb/db/driver/driver.php | 150 | ||||
-rw-r--r-- | phpBB/phpbb/db/driver/oracle.php | 2 | ||||
-rw-r--r-- | phpBB/phpbb/db/driver/sqlite3.php | 25 |
3 files changed, 169 insertions, 8 deletions
diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 8d360fc3e2..30cb667344 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -66,6 +66,15 @@ abstract class driver implements driver_interface */ var $sql_server_version = false; + const LOGICAL_OP = 0; + const STATEMENTS = 1; + const LEFT_STMT = 0; + const COMPARE_OP = 1; + const RIGHT_STMT = 2; + const SUBQUERY_OP = 3; + const SUBQUERY_SELECT_TYPE = 4; + const SUBQUERY_BUILD = 5; + /** * Constructor */ @@ -774,7 +783,18 @@ abstract class driver implements driver_interface if (!empty($array['WHERE'])) { - $sql .= ' WHERE ' . $this->_sql_custom_build('WHERE', $array['WHERE']); + $sql .= ' WHERE '; + + if (is_array($array['WHERE'])) + { + $sql_where = $this->_process_boolean_tree_first($array['WHERE']); + } + else + { + $sql_where = $array['WHERE']; + } + + $sql .= $this->_sql_custom_build('WHERE', $sql_where); } if (!empty($array['GROUP_BY'])) @@ -793,6 +813,130 @@ abstract class driver implements driver_interface return $sql; } + + protected function _process_boolean_tree_first($operations_ary) + { + // In cases where an array exists but there is no head condition, + // it should be because there's only 1 WHERE clause. This seems the best way to deal with it. + if ($operations_ary[self::LOGICAL_OP] !== 'AND' && + $operations_ary[self::LOGICAL_OP] !== 'OR') + { + $operations_ary = array('AND', array($operations_ary)); + } + return $this->_process_boolean_tree($operations_ary) . "\n"; + } + + protected function _process_boolean_tree($operations_ary) + { + $operation = $operations_ary[self::LOGICAL_OP]; + + foreach ($operations_ary[self::STATEMENTS] as &$condition) + { + switch ($condition[self::LOGICAL_OP]) + { + case 'AND': + case 'OR': + + $condition = ' ( ' . $this->_process_boolean_tree($condition) . ') '; + + break; + case 'NOT': + + $condition = ' NOT (' . $this->_process_boolean_tree($condition) . ') '; + + break; + + default: + + switch (sizeof($condition)) + { + case 3: + + // Typical 3 element clause with {left hand} {operator} {right hand} + switch ($condition[self::COMPARE_OP]) + { + case 'IN': + case 'NOT_IN': + + // As this is used with an IN, assume it is a set of elements for sql_in_set() + $condition = $this->sql_in_set($condition[self::LEFT_STMT], $condition[self::RIGHT_STMT], $condition[self::COMPARE_OP] === 'NOT_IN', true); + + break; + + case 'LIKE': + + $condition = $condition[self::LEFT_STMT] . ' ' . $this->sql_like_expression($condition[self::RIGHT_STMT]) . ' '; + + break; + + case 'NOT_LIKE': + + $condition = $condition[self::LEFT_STMT] . ' ' . $this->sql_not_like_expression($condition[self::RIGHT_STMT]) . ' '; + + break; + + case 'IS_NOT': + + $condition[self::COMPARE_OP] = 'IS NOT'; + + // no break + case 'IS': + + // If the value is NULL, the string of it is the empty string ('') which is not the intended result. + // this should solve that + if ($condition[self::RIGHT_STMT] === null) + { + $condition[self::RIGHT_STMT] = 'NULL'; + } + + $condition = implode(' ', $condition); + + break; + + default: + + $condition = implode(' ', $condition); + + break; + } + + break; + + case 5: + + // Subquery with {left hand} {operator} {compare kind} {SELECT Kind } {Sub Query} + + $condition = $condition[self::LEFT_STMT] . ' ' . $condition[self::COMPARE_OP] . ' ' . $condition[self::SUBQUERY_OP] . ' ( '; + $condition .= $this->sql_build_query($condition[self::SUBQUERY_SELECT_TYPE], $condition[self::SUBQUERY_BUILD]); + $condition .= ' )'; + + break; + + default: + // This is an unpredicted clause setup. Just join all elements. + $condition = implode(' ', $condition); + + break; + } + + break; + } + + } + + if ($operation === 'NOT') + { + $operations_ary = implode("", $operations_ary[self::STATEMENTS]); + } + else + { + $operations_ary = implode(" \n $operation ", $operations_ary[self::STATEMENTS]); + } + + return $operations_ary; + } + + /** * {@inheritDoc} */ @@ -868,7 +1012,7 @@ abstract class driver implements driver_interface */ function sql_report($mode, $query = '') { - global $cache, $starttime, $phpbb_root_path, $phpbb_path_helper, $user; + global $cache, $starttime, $phpbb_root_path, $phpbb_path_helper; global $request; if (is_object($request) && !$request->variable('explain', false)) @@ -962,7 +1106,7 @@ abstract class driver implements driver_interface { if (preg_match('/^(UPDATE|DELETE|REPLACE)/', $query)) { - $this->sql_report .= 'Affected rows: <b>' . $this->sql_affectedrows($this->query_result) . '</b> | '; + $this->sql_report .= 'Affected rows: <b>' . $this->sql_affectedrows() . '</b> | '; } $this->sql_report .= 'Before: ' . sprintf('%.5f', $this->curtime - $starttime) . 's | After: ' . sprintf('%.5f', $endtime - $starttime) . 's | Elapsed: <b>' . sprintf('%.5f', $endtime - $this->curtime) . 's</b>'; } diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index 89e1b68aac..54238a15ef 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -84,8 +84,6 @@ class oracle extends \phpbb\db\driver\driver * but I assume its because the Oracle extension provides a direct method to access it * without a query. */ - - $use_cache = false; /* global $cache; diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php index f5c2dd225b..0508500c52 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) @@ -101,7 +102,7 @@ class sqlite3 extends \phpbb\db\driver\driver break; case 'rollback': - return $this->dbo->exec('ROLLBACK'); + return @$this->dbo->exec('ROLLBACK'); break; } @@ -133,9 +134,26 @@ class sqlite3 extends \phpbb\db\driver\driver if ($this->query_result === false) { + if ($this->transaction === true && strpos($query, 'INSERT') === 0) + { + $query = preg_replace('/^INSERT INTO/', 'INSERT OR ROLLBACK INTO', $query); + } + if (($this->query_result = @$this->dbo->query($query)) === false) { - $this->sql_error($query); + // Try to recover a lost database connection + if ($this->dbo && !@$this->dbo->lastErrorMsg()) + { + if ($this->sql_connect($this->server, $this->user, '', $this->dbname)) + { + $this->query_result = @$this->dbo->query($query); + } + } + + if ($this->query_result === false) + { + $this->sql_error($query); + } } if (defined('DEBUG')) @@ -212,6 +230,7 @@ class sqlite3 extends \phpbb\db\driver\driver if ($query_id === false) { + /** @var \SQLite3Result $query_id */ $query_id = $this->query_result; } @@ -220,7 +239,7 @@ class sqlite3 extends \phpbb\db\driver\driver return $cache->sql_fetchrow($query_id); } - return is_object($query_id) ? $query_id->fetchArray(SQLITE3_ASSOC) : false; + return is_object($query_id) ? @$query_id->fetchArray(SQLITE3_ASSOC) : false; } /** |