|
|
@@ -3,25 +3,19 @@
|
|
|
class SqlQueryWhereBuilder {
|
|
|
|
|
|
private $_log = array();
|
|
|
+ private $_usedFields = array();
|
|
|
+ private $_raw = "";
|
|
|
|
|
|
public function __construct() {
|
|
|
}
|
|
|
|
|
|
public function openBlock($blockType) {
|
|
|
- if ('and' == $blockType) {
|
|
|
- } else if ('or' == $blockType) {
|
|
|
- } else {
|
|
|
- throw new Exception("unsupported block type");
|
|
|
- }
|
|
|
+ if (!$this->isAllowedBlockType($blockType)) throw new Exception("unsupported block type");
|
|
|
$this->_log[] = "open_block_{$blockType}";
|
|
|
}
|
|
|
|
|
|
public function closeBlock($blockType) {
|
|
|
- if ('and' == $blockType) {
|
|
|
- } else if ('or' == $blockType) {
|
|
|
- } else {
|
|
|
- throw new Exception("unsupported block type");
|
|
|
- }
|
|
|
+ if (!$this->isAllowedBlockType($blockType)) throw new Exception("unsupported block type");
|
|
|
$this->_log[] = "close_block_{$blockType}";
|
|
|
}
|
|
|
|
|
|
@@ -35,62 +29,52 @@ class SqlQueryWhereBuilder {
|
|
|
}
|
|
|
|
|
|
public function getQueryWhere($tablePrefix = '') {
|
|
|
- $sqlWhere = "";
|
|
|
+ $sqlWhereRaw = $this->parseQueryWhere();
|
|
|
+ $sqlTablePrefix = ($tablePrefix)? "`{$tablePrefix}`." : '';
|
|
|
+ return str_replace('{tablePrefix}', $sqlTablePrefix, $sqlWhereRaw);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function parseQueryWhere() {
|
|
|
+ $this->_raw = "";
|
|
|
+ $this->_usedFields = array();
|
|
|
+
|
|
|
$sqlBlocksStack = array();
|
|
|
$sqlValuesStack = array();
|
|
|
- $sqlTablePrefix = ($tablePrefix)? "`{$tablePrefix}`." : '';
|
|
|
$arr = array(); array_push($sqlValuesStack, $arr);// empty array to start
|
|
|
foreach ($this->_log as $log) {
|
|
|
switch ($log) {
|
|
|
- case 'open_block_and': {
|
|
|
- array_push($sqlBlocksStack, 'and');
|
|
|
- $arr = array(); array_push($sqlValuesStack, $arr);
|
|
|
- }
|
|
|
- break;
|
|
|
- case 'close_block_and': {
|
|
|
- if (empty($sqlBlocksStack)) throw new Exception("parse sql query failed - blocks stack is empty");
|
|
|
- $blockType = array_pop($sqlBlocksStack);
|
|
|
- if ('and' != $blockType) throw new Exception("parse sql query failed - expected stop 'and', given '{$blockType}'");
|
|
|
-
|
|
|
- // parse to string and add to parent value stack
|
|
|
- $stackValue = array_pop($sqlValuesStack);
|
|
|
- if (!is_array($stackValue)) throw new Exception("parse sql query failed - stack value is not array");
|
|
|
- if (empty($stackValue)) throw new Exception("parse sql query failed - stack value is empty");
|
|
|
- $sqlFromStack = " ( " . implode(" and ", $stackValue) . " ) ";
|
|
|
- $parentStackValue = array_pop($sqlValuesStack);
|
|
|
- if (!is_array($parentStackValue)) throw new Exception("parse sql query failed - parent stack value is not array");
|
|
|
- array_push($parentStackValue, $sqlFromStack);
|
|
|
- array_push($sqlValuesStack, $parentStackValue);
|
|
|
- }
|
|
|
- break;
|
|
|
+ case 'open_block_and':
|
|
|
case 'open_block_or': {
|
|
|
- array_push($sqlBlocksStack, 'or');
|
|
|
+ $blockType = substr($log, 11);
|
|
|
+ array_push($sqlBlocksStack, $blockType);
|
|
|
$arr = array(); array_push($sqlValuesStack, $arr);
|
|
|
//echo "L.".__LINE__.":sqlBlocksStack:" . json_encode($sqlBlocksStack) . "\n";
|
|
|
//echo "L.".__LINE__.":sqlValuesStack:" . json_encode($sqlValuesStack) . "\n\n";
|
|
|
}
|
|
|
break;
|
|
|
+ case 'close_block_and':
|
|
|
case 'close_block_or': {
|
|
|
+ $blockType = substr($log, 12);
|
|
|
if (empty($sqlBlocksStack)) throw new Exception("parse sql query failed - blocks stack is empty");
|
|
|
- $blockType = array_pop($sqlBlocksStack);
|
|
|
- if ('or' != $blockType) throw new Exception("parse sql query failed - expected stop 'or', given '{$blockType}'");
|
|
|
+ $stackBlockType = array_pop($sqlBlocksStack);
|
|
|
+ if ($blockType != $stackBlockType) throw new Exception("parse sql query failed - expected stop '{$blockType}', given '{$stackBlockType}'");
|
|
|
|
|
|
// parse to string and add to parent value stack
|
|
|
$stackValue = array_pop($sqlValuesStack);
|
|
|
if (!is_array($stackValue)) throw new Exception("parse sql query failed - stack value is not array");
|
|
|
if (empty($stackValue)) throw new Exception("parse sql query failed - stack value is empty");
|
|
|
- $sqlFromStack = " ( " . implode(" or ", $stackValue) . " ) ";
|
|
|
+ $sqlFromStack = " ( " . implode(" {$blockType} ", $stackValue) . " ) ";
|
|
|
$parentStackValue = array_pop($sqlValuesStack);
|
|
|
if (!is_array($parentStackValue)) throw new Exception("parse sql query failed - parent stack value is not array");
|
|
|
array_push($parentStackValue, $sqlFromStack);
|
|
|
array_push($sqlValuesStack, $parentStackValue);
|
|
|
-//echo "L.".__LINE__.":sqlBlocksStack:" . json_encode($sqlBlocksStack) . "\n";
|
|
|
-//echo "L.".__LINE__.":sqlValuesStack:" . json_encode($sqlValuesStack) . "\n\n";
|
|
|
}
|
|
|
break;
|
|
|
default: {
|
|
|
if (is_array($log) && 4 == count($log) && 'comparisonFieldToValue' == $log[0]) {
|
|
|
- $sqlFromStack = "{$sqlTablePrefix}`{$log[1]}` {$log[2]} '{$log[3]}'";
|
|
|
+ $sqlFieldName = $log[1];
|
|
|
+ $this->_usedFields[$sqlFieldName] = true;
|
|
|
+ $sqlFromStack = "{tablePrefix}`{$sqlFieldName}` {$log[2]} '{$log[3]}'";
|
|
|
$stackValue = array_pop($sqlValuesStack);
|
|
|
if (!is_array($stackValue)) throw new Exception("parse sql query failed - stack value is not array");
|
|
|
array_push($stackValue, $sqlFromStack);
|
|
|
@@ -108,8 +92,21 @@ class SqlQueryWhereBuilder {
|
|
|
//echo "L.".__LINE__.":sqlValuesStack:" . json_encode($sqlValuesStack) . "\n--------\n";
|
|
|
if (!empty($sqlBlocksStack)) throw new Exception("parse sql query failed - blocks stack is not empty");
|
|
|
if (1 !== count($sqlValuesStack)) throw new Exception("parse sql query failed - values stack is empty");
|
|
|
- $sqlWhere = implode("\n", $sqlValuesStack[0]);
|
|
|
- return $sqlWhere;
|
|
|
+ $this->_raw = implode("\n", $sqlValuesStack[0]);
|
|
|
+ return $this->_raw;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function getUsedFields() {
|
|
|
+ return array_keys($this->_usedFields);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function isAllowedBlockType($blockType) {
|
|
|
+ if ('and' == $blockType || 'or' == $blockType) {
|
|
|
+ return true;
|
|
|
+ } else if ('not' == $blockType) {
|
|
|
+ return false;// TODO: allow not operator: expect only one children, if more -> use only last
|
|
|
+ }
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
}
|