diff options
Diffstat (limited to 'phpBB/phpbb/db/driver/driver.php')
-rw-r--r-- | phpBB/phpbb/db/driver/driver.php | 164 |
1 files changed, 154 insertions, 10 deletions
diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 01dd66cd6e..214c5590e7 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 */ @@ -271,7 +280,7 @@ abstract class driver implements driver_interface $query_id = $this->query_result; } - if ($query_id !== false) + if ($query_id) { $result = array(); while ($row = $this->sql_fetchrow($query_id)) @@ -302,7 +311,7 @@ abstract class driver implements driver_interface return $cache->sql_rowseek($rownum, $query_id); } - if ($query_id === false) + if (!$query_id) { return false; } @@ -310,7 +319,7 @@ abstract class driver implements driver_interface $this->sql_freeresult($query_id); $query_id = $this->sql_query($this->last_query_text); - if ($query_id === false) + if (!$query_id) { return false; } @@ -339,7 +348,7 @@ abstract class driver implements driver_interface $query_id = $this->query_result; } - if ($query_id !== false) + if ($query_id) { if ($rownum !== false) { @@ -363,8 +372,8 @@ abstract class driver implements driver_interface */ function sql_like_expression($expression) { - $expression = utf8_str_replace(array('_', '%'), array("\_", "\%"), $expression); - $expression = utf8_str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression); + $expression = str_replace(array('_', '%'), array("\_", "\%"), $expression); + $expression = str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression); return $this->_sql_like_expression('LIKE \'' . $this->sql_escape($expression) . '\''); } @@ -374,8 +383,8 @@ abstract class driver implements driver_interface */ function sql_not_like_expression($expression) { - $expression = utf8_str_replace(array('_', '%'), array("\_", "\%"), $expression); - $expression = utf8_str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression); + $expression = str_replace(array('_', '%'), array("\_", "\%"), $expression); + $expression = str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression); return $this->_sql_not_like_expression('NOT LIKE \'' . $this->sql_escape($expression) . '\''); } @@ -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)) |