diff options
Diffstat (limited to 'phpBB/phpbb/db/driver/driver.php')
| -rw-r--r-- | phpBB/phpbb/db/driver/driver.php | 162 | 
1 files changed, 153 insertions, 9 deletions
| diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 1b49775b32..5f06cb08fc 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}  	*/ | 
