mirror of
https://github.com/dg/dibi.git
synced 2025-08-15 10:34:06 +02:00
updated conditional SQL
This commit is contained in:
@@ -347,6 +347,22 @@ class dibi
|
||||
|
||||
|
||||
|
||||
static private function dumpHighlight($matches)
|
||||
{
|
||||
if (!empty($matches[1])) // comment
|
||||
return '<em style="color:gray">'.$matches[1].'</em>';
|
||||
|
||||
if (!empty($matches[2])) // error
|
||||
return '<strong style="color:red">'.$matches[2].'</strong>';
|
||||
|
||||
if (!empty($matches[3])) // most important keywords
|
||||
return '<strong style="color:blue">'.$matches[3].'</strong>';
|
||||
|
||||
if (!empty($matches[4])) // other keywords
|
||||
return '<strong style="color:green">'.$matches[4].'</strong>';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints out a syntax highlighted version of the SQL command
|
||||
*
|
||||
@@ -354,12 +370,11 @@ class dibi
|
||||
* @return void
|
||||
*/
|
||||
static public function dump($sql) {
|
||||
static $highlight = array ('ALL', 'DISTINCT', 'AS', 'ON', 'INTO', 'AND', 'OR', 'AS', );
|
||||
static $newline = array ('SELECT', 'UPDATE', 'INSERT', 'DELETE', 'FROM', 'WHERE', 'HAVING', 'GROUP BY', 'ORDER BY', 'LIMIT', 'SET', 'VALUES', 'LEFT JOIN', 'INNER JOIN',);
|
||||
static $keywords2 = 'ALL|DISTINCT|AS|ON|INTO|AND|OR|AS';
|
||||
static $keywords1 = 'SELECT|UPDATE|INSERT|DELETE|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN';
|
||||
|
||||
// insert new lines
|
||||
foreach ($newline as $word)
|
||||
$sql = preg_replace('#\b'.$word.'\b#', "\n\$0", $sql);
|
||||
$sql = preg_replace("#\\b(?:$keywords1)\\b#", "\n\$0", $sql);
|
||||
|
||||
$sql = trim($sql);
|
||||
// reduce spaces
|
||||
@@ -369,13 +384,8 @@ class dibi
|
||||
$sql = htmlSpecialChars($sql);
|
||||
$sql = strtr($sql, array("\n" => '<br />'));
|
||||
|
||||
foreach ($newline as $word)
|
||||
$sql = preg_replace('#\b'.$word.'\b#', '<strong style="color:blue">$0</strong>', $sql);
|
||||
|
||||
foreach ($highlight as $word)
|
||||
$sql = preg_replace('#\b'.$word.'\b#', '<strong style="color:green">$0</strong>', $sql);
|
||||
|
||||
$sql = preg_replace('#\*\*.+?\*\*#', '<strong style="color:red">$0</strong>', $sql);
|
||||
// syntax highlight
|
||||
$sql = preg_replace_callback("#(/\*.+?\*/)|(\*\*.+?\*\*)|\\b($keywords1)\\b|\\b($keywords2)\\b#", array('dibi', 'dumpHighlight'), $sql);
|
||||
|
||||
echo '<pre class="dibi">', $sql, '</pre>';
|
||||
}
|
||||
|
@@ -30,7 +30,9 @@ class DibiParser
|
||||
private
|
||||
$modifier,
|
||||
$hasError,
|
||||
$driver;
|
||||
$driver,
|
||||
$ifLevel,
|
||||
$ifLevelStart;
|
||||
|
||||
|
||||
/**
|
||||
@@ -42,15 +44,15 @@ class DibiParser
|
||||
public function parse($driver, $args)
|
||||
{
|
||||
$this->driver = $driver;
|
||||
$mod = & $this->modifier; // shortcut
|
||||
$mod = false;
|
||||
$this->hasError = false;
|
||||
$this->hasError = FALSE;
|
||||
$command = null;
|
||||
$mod = & $this->modifier; // shortcut
|
||||
$mod = FALSE;
|
||||
|
||||
// conditional sql
|
||||
static $condKeys = array('if'=>1, 'else'=>1, 'end'=>1);
|
||||
$cond = true;
|
||||
$conds = array();
|
||||
$this->ifLevel = $this->ifLevelStart = 0;
|
||||
$comment = & $this->comment;
|
||||
$comment = FALSE;
|
||||
|
||||
// iterate
|
||||
$sql = array();
|
||||
@@ -65,8 +67,10 @@ class DibiParser
|
||||
// speed-up - is regexp required?
|
||||
$toSkip = strcspn($arg, '`[\'"%');
|
||||
|
||||
if ($toSkip != strlen($arg)) // need be translated?
|
||||
$arg = substr($arg, 0, $toSkip)
|
||||
if ($toSkip == strlen($arg)) { // need be translated?
|
||||
$sql[] = $arg;
|
||||
} else {
|
||||
$sql[] = substr($arg, 0, $toSkip)
|
||||
. preg_replace_callback('/
|
||||
(?=`|\[|\'|"|%) ## speed-up
|
||||
(?:
|
||||
@@ -74,50 +78,29 @@ class DibiParser
|
||||
\[(.+?)\]| ## 2) [identifier]
|
||||
(\')((?:\'\'|[^\'])*)\'| ## 3,4) string
|
||||
(")((?:""|[^"])*)"| ## 5,6) "string"
|
||||
%([a-zA-Z]{1,4})$| ## 7) right modifier
|
||||
(\'|") ## 8) lone-quote
|
||||
%([a-zA-Z]{1,2})$| ## 7) right modifier
|
||||
%(else|end)| ## 8) conditional SQL
|
||||
(\'|") ## 9) lone-quote
|
||||
)/xs',
|
||||
array($this, 'callback'),
|
||||
substr($arg, $toSkip)
|
||||
);
|
||||
|
||||
// add to SQL
|
||||
if ($cond) $sql[] = $arg;
|
||||
|
||||
// conditional sequence
|
||||
if (isset($condKeys[$mod])) {
|
||||
switch ($mod) {
|
||||
case 'if':
|
||||
$conds[] = $cond;
|
||||
$cond = (bool) $args[++$i];
|
||||
break;
|
||||
|
||||
case 'else':
|
||||
if ($conds) {
|
||||
$cond = !$cond;
|
||||
break;
|
||||
}
|
||||
// no break!
|
||||
|
||||
case 'end':
|
||||
if ($conds) {
|
||||
$cond = array_pop($conds);
|
||||
break;
|
||||
}
|
||||
|
||||
$this->hasError = true;
|
||||
$sql[] = "**Unexpected condition $mod**";
|
||||
} // switch
|
||||
|
||||
$mod = false;
|
||||
} // if cond comments
|
||||
|
||||
if ($mod == 'if') {
|
||||
$mod = FALSE;
|
||||
$this->ifLevel++;
|
||||
if (!$args[++$i] && !$comment) {
|
||||
// open comment
|
||||
$sql[] = '/*';
|
||||
$this->ifLevelStart = $this->ifLevel;
|
||||
$comment = TRUE;
|
||||
}
|
||||
}
|
||||
} // if
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// conditional sql (!!! or not?)
|
||||
if (!$cond) continue;
|
||||
|
||||
|
||||
|
||||
// array processing without modifier - autoselect between SET or VALUES
|
||||
if (is_array($arg) && !$mod && is_string(key($arg))) {
|
||||
@@ -128,10 +111,14 @@ class DibiParser
|
||||
}
|
||||
|
||||
// default processing
|
||||
$sql[] = $this->formatValue($arg, $mod);
|
||||
$mod = false;
|
||||
$sql[] = $comment
|
||||
? '...'
|
||||
: $this->formatValue($arg, $mod);
|
||||
$mod = FALSE;
|
||||
} // for
|
||||
|
||||
if ($comment) $sql[] = '*/';
|
||||
|
||||
$sql = implode(' ', $sql);
|
||||
|
||||
if ($this->hasError)
|
||||
@@ -184,7 +171,7 @@ class DibiParser
|
||||
return $value->toSql($this->driver, $modifier);
|
||||
|
||||
if (!is_scalar($value) && !is_null($value)) { // array is already processed
|
||||
$this->hasError = true;
|
||||
$this->hasError = TRUE;
|
||||
return '**Unexpected '.gettype($value).'**';
|
||||
}
|
||||
|
||||
@@ -208,7 +195,7 @@ class DibiParser
|
||||
case 'p': // preserve as SQL
|
||||
return (string) $value;
|
||||
default:
|
||||
$this->hasError = true;
|
||||
$this->hasError = TRUE;
|
||||
return "**Unknown modifier %$modifier**";
|
||||
}
|
||||
}
|
||||
@@ -231,7 +218,7 @@ class DibiParser
|
||||
if ($value instanceof IDibiVariable)
|
||||
return $value->toSql($this->driver);
|
||||
|
||||
$this->hasError = true;
|
||||
$this->hasError = TRUE;
|
||||
return '**Unexpected '.gettype($value).'**';
|
||||
}
|
||||
|
||||
@@ -253,7 +240,8 @@ class DibiParser
|
||||
// [5] => "
|
||||
// [6] => string
|
||||
// [7] => right modifier
|
||||
// [8] => lone-quote
|
||||
// [8] => %else | %end
|
||||
// [9] => lone-quote
|
||||
|
||||
if ($matches[1]) // SQL identifiers: `ident`
|
||||
return $this->driver->quoteName($matches[1]);
|
||||
@@ -262,19 +250,53 @@ class DibiParser
|
||||
return $this->driver->quoteName($matches[2]);
|
||||
|
||||
if ($matches[3]) // SQL strings: '....'
|
||||
return $this->driver->escape( strtr($matches[4], array("''" => "'")), true);
|
||||
return $this->comment
|
||||
? '...'
|
||||
: $this->driver->escape( strtr($matches[4], array("''" => "'")), TRUE);
|
||||
|
||||
if ($matches[5]) // SQL strings: "..."
|
||||
return $this->driver->escape( strtr($matches[6], array('""' => '"')), true);
|
||||
return $this->comment
|
||||
? '...'
|
||||
: $this->driver->escape( strtr($matches[6], array('""' => '"')), TRUE);
|
||||
|
||||
if ($matches[7]) { // modifier
|
||||
$this->modifier = $matches[7];
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($matches[8]) { // string quote
|
||||
if ($matches[8]) { // %end | %else
|
||||
if (!$this->ifLevel) {
|
||||
$this->hasError = TRUE;
|
||||
return "**Unexpected condition $mod**";
|
||||
}
|
||||
|
||||
if ($matches[8] == 'end') {
|
||||
$this->ifLevel--;
|
||||
if ($this->ifLevelStart == $this->ifLevel + 1) {
|
||||
// close comment
|
||||
$this->ifLevelStart = 0;
|
||||
$this->comment = FALSE;
|
||||
return '*/';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
// else
|
||||
if ($this->ifLevelStart == $this->ifLevel) {
|
||||
$this->ifLevelStart = 0;
|
||||
$this->comment = FALSE;
|
||||
return '*/';
|
||||
} elseif (!$this->comment) {
|
||||
$this->ifLevelStart = $this->ifLevel;
|
||||
$this->comment = TRUE;
|
||||
return '/*';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($matches[9]) { // string quote
|
||||
$this->hasError = TRUE;
|
||||
return '**Alone quote**';
|
||||
$this->hasError = true;
|
||||
}
|
||||
|
||||
die('this should be never executed');
|
||||
|
Reference in New Issue
Block a user