1
0
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:
David Grudl
2006-06-07 21:33:46 +00:00
parent a3a17f1c55
commit 0e7f85c73a
5 changed files with 120 additions and 93 deletions

View File

@@ -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>';
}

View File

@@ -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');