mirror of
https://github.com/dg/dibi.git
synced 2025-08-04 21:28:02 +02:00
- REWRITTEN DibiTranslar
- allows modifiers inside SQL -> modifiers become placeholders - new modifier %ex - expand array - new modifiers %or and %and - changed interface IDibiVariable and implementation DibiVariable
This commit is contained in:
@@ -78,7 +78,7 @@ class dibi
|
|||||||
|
|
||||||
// special
|
// special
|
||||||
FIELD_COUNTER = 'C', // counter or autoincrement, is integer
|
FIELD_COUNTER = 'C', // counter or autoincrement, is integer
|
||||||
IDENTIFIER = 'I',
|
IDENTIFIER = 'n',
|
||||||
|
|
||||||
// dibi version
|
// dibi version
|
||||||
VERSION = '0.9 (Revision: $WCREV$, Date: $WCDATE$)';
|
VERSION = '0.9 (Revision: $WCREV$, Date: $WCDATE$)';
|
||||||
@@ -246,8 +246,7 @@ class dibi
|
|||||||
*/
|
*/
|
||||||
public static function query($args)
|
public static function query($args)
|
||||||
{
|
{
|
||||||
if (!is_array($args)) $args = func_get_args();
|
$args = func_get_args();
|
||||||
|
|
||||||
return self::getConnection()->query($args);
|
return self::getConnection()->query($args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,8 +273,7 @@ class dibi
|
|||||||
*/
|
*/
|
||||||
public static function test($args)
|
public static function test($args)
|
||||||
{
|
{
|
||||||
if (!is_array($args)) $args = func_get_args();
|
$args = func_get_args();
|
||||||
|
|
||||||
return self::getConnection()->test($args);
|
return self::getConnection()->test($args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,8 +288,7 @@ class dibi
|
|||||||
*/
|
*/
|
||||||
public static function fetch($args)
|
public static function fetch($args)
|
||||||
{
|
{
|
||||||
if (!is_array($args)) $args = func_get_args();
|
$args = func_get_args();
|
||||||
|
|
||||||
return self::getConnection()->query($args)->fetch();
|
return self::getConnection()->query($args)->fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,8 +303,7 @@ class dibi
|
|||||||
*/
|
*/
|
||||||
public static function fetchAll($args)
|
public static function fetchAll($args)
|
||||||
{
|
{
|
||||||
if (!is_array($args)) $args = func_get_args();
|
$args = func_get_args();
|
||||||
|
|
||||||
return self::getConnection()->query($args)->fetchAll();
|
return self::getConnection()->query($args)->fetchAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,8 +318,7 @@ class dibi
|
|||||||
*/
|
*/
|
||||||
public static function fetchSingle($args)
|
public static function fetchSingle($args)
|
||||||
{
|
{
|
||||||
if (!is_array($args)) $args = func_get_args();
|
$args = func_get_args();
|
||||||
|
|
||||||
return self::getConnection()->query($args)->fetchSingle();
|
return self::getConnection()->query($args)->fetchSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,7 +441,7 @@ class dibi
|
|||||||
public static function date($date = NULL)
|
public static function date($date = NULL)
|
||||||
{
|
{
|
||||||
$var = self::datetime($date);
|
$var = self::datetime($date);
|
||||||
$var->type = dibi::FIELD_DATE;
|
$var->modifier = dibi::FIELD_DATE;
|
||||||
return $var;
|
return $var;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,7 +573,7 @@ class dibi
|
|||||||
$sql = preg_replace("#\n{2,}#", "\n", $sql);
|
$sql = preg_replace("#\n{2,}#", "\n", $sql);
|
||||||
|
|
||||||
// syntax highlight
|
// syntax highlight
|
||||||
$sql = preg_replace_callback("#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(])($keywords2)(?=[\\s,)])#i", array('dibi', 'highlightCallback'), $sql);
|
$sql = preg_replace_callback("#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#i", array('dibi', 'highlightCallback'), $sql);
|
||||||
$sql = trim($sql);
|
$sql = trim($sql);
|
||||||
echo '<pre class="dump">', $sql, "</pre>\n";
|
echo '<pre class="dump">', $sql, "</pre>\n";
|
||||||
}
|
}
|
||||||
|
@@ -206,8 +206,7 @@ class DibiConnection extends NObject
|
|||||||
*/
|
*/
|
||||||
final public function query($args)
|
final public function query($args)
|
||||||
{
|
{
|
||||||
if (!is_array($args)) $args = func_get_args();
|
$args = func_get_args();
|
||||||
|
|
||||||
$this->connect();
|
$this->connect();
|
||||||
$trans = new DibiTranslator($this->driver);
|
$trans = new DibiTranslator($this->driver);
|
||||||
if ($trans->translate($args)) {
|
if ($trans->translate($args)) {
|
||||||
@@ -227,8 +226,7 @@ class DibiConnection extends NObject
|
|||||||
*/
|
*/
|
||||||
final public function test($args)
|
final public function test($args)
|
||||||
{
|
{
|
||||||
if (!is_array($args)) $args = func_get_args();
|
$args = func_get_args();
|
||||||
|
|
||||||
$trans = new DibiTranslator($this->driver);
|
$trans = new DibiTranslator($this->driver);
|
||||||
$ok = $trans->translate($args);
|
$ok = $trans->translate($args);
|
||||||
dibi::dump($trans->sql);
|
dibi::dump($trans->sql);
|
||||||
|
@@ -69,7 +69,7 @@ class DibiDataSource extends NObject implements IDataSource
|
|||||||
{
|
{
|
||||||
return $this->connection->query('
|
return $this->connection->query('
|
||||||
SELECT %n', ($cols === NULL ? '*' : $cols), '
|
SELECT %n', ($cols === NULL ? '*' : $cols), '
|
||||||
FROM %sql', $this->sql, '
|
FROM', $this->sql, '
|
||||||
%ofs %lmt', $offset, $limit
|
%ofs %lmt', $offset, $limit
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -83,8 +83,7 @@ class DibiDataSource extends NObject implements IDataSource
|
|||||||
{
|
{
|
||||||
if ($this->count === NULL) {
|
if ($this->count === NULL) {
|
||||||
$this->count = $this->connection->query('
|
$this->count = $this->connection->query('
|
||||||
SELECT COUNT(*)
|
SELECT COUNT(*) FROM', $this->sql
|
||||||
FROM %sql', $this->sql
|
|
||||||
)->fetchSingle();
|
)->fetchSingle();
|
||||||
}
|
}
|
||||||
return $this->count;
|
return $this->count;
|
||||||
|
@@ -32,14 +32,14 @@ final class DibiTranslator extends NObject
|
|||||||
/** @var string */
|
/** @var string */
|
||||||
public $sql;
|
public $sql;
|
||||||
|
|
||||||
/** @var string NOT USED YET */
|
|
||||||
public $mask;
|
|
||||||
|
|
||||||
/** @var IDibiDriver */
|
/** @var IDibiDriver */
|
||||||
private $driver;
|
private $driver;
|
||||||
|
|
||||||
/** @var string last modifier */
|
/** @var int */
|
||||||
private $modifier;
|
private $cursor;
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
private $args;
|
||||||
|
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
private $hasError;
|
private $hasError;
|
||||||
@@ -54,10 +54,10 @@ final class DibiTranslator extends NObject
|
|||||||
private $ifLevelStart;
|
private $ifLevelStart;
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
public $limit;
|
private $limit;
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
public $offset;
|
private $offset;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -68,6 +68,16 @@ final class DibiTranslator extends NObject
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return IDibiDriver
|
||||||
|
*/
|
||||||
|
public function getDriver()
|
||||||
|
{
|
||||||
|
return $this->driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates SQL
|
* Generates SQL
|
||||||
*
|
*
|
||||||
@@ -81,8 +91,11 @@ final class DibiTranslator extends NObject
|
|||||||
$this->hasError = FALSE;
|
$this->hasError = FALSE;
|
||||||
$commandIns = NULL;
|
$commandIns = NULL;
|
||||||
$lastArr = NULL;
|
$lastArr = NULL;
|
||||||
$mod = & $this->modifier; // shortcut
|
// shortcuts
|
||||||
$mod = FALSE;
|
$cursor = & $this->cursor;
|
||||||
|
$cursor = 0;
|
||||||
|
$this->args = array_values($args);
|
||||||
|
$args = & $this->args;
|
||||||
|
|
||||||
// conditional sql
|
// conditional sql
|
||||||
$this->ifLevel = $this->ifLevelStart = 0;
|
$this->ifLevel = $this->ifLevelStart = 0;
|
||||||
@@ -90,58 +103,73 @@ final class DibiTranslator extends NObject
|
|||||||
$comment = FALSE;
|
$comment = FALSE;
|
||||||
|
|
||||||
// iterate
|
// iterate
|
||||||
$sql = $mask = array();
|
$sql = array();
|
||||||
$i = 0;
|
while ($cursor < count($args))
|
||||||
foreach ($args as $arg)
|
|
||||||
{
|
{
|
||||||
$i++;
|
$arg = $args[$cursor];
|
||||||
|
$cursor++;
|
||||||
// %if was opened
|
|
||||||
if ($mod === 'if') {
|
|
||||||
$mod = FALSE;
|
|
||||||
$this->ifLevel++;
|
|
||||||
if (!$comment && !$arg) {
|
|
||||||
// open comment
|
|
||||||
$sql[] = "\0";
|
|
||||||
$this->ifLevelStart = $this->ifLevel;
|
|
||||||
$comment = TRUE;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// simple string means SQL
|
// simple string means SQL
|
||||||
if (is_string($arg) && (!$mod || $mod === 'sql')) {
|
if (is_string($arg)) {
|
||||||
$mod = FALSE;
|
// speed-up - is regexp required?
|
||||||
// will generate new mod
|
$toSkip = strcspn($arg, '`[\'"%');
|
||||||
/*$mask[] =*/ $sql[] = $this->formatValue($arg, 'sql');
|
|
||||||
|
if (strlen($arg) === $toSkip) { // needn't be translated
|
||||||
|
$sql[] = $arg;
|
||||||
|
} else {
|
||||||
|
$sql[] = substr($arg, 0, $toSkip)
|
||||||
|
/*
|
||||||
|
. preg_replace_callback('/
|
||||||
|
(?=`|\[|\'|"|%) ## speed-up
|
||||||
|
(?:
|
||||||
|
`(.+?)`| ## 1) `identifier`
|
||||||
|
\[(.+?)\]| ## 2) [identifier]
|
||||||
|
(\')((?:\'\'|[^\'])*)\'| ## 3,4) string
|
||||||
|
(")((?:""|[^"])*)"| ## 5,6) "string"
|
||||||
|
(\'|") ## 7) lone-quote
|
||||||
|
%([a-zA-Z]{1,4})(?![a-zA-Z])|## 8) modifier
|
||||||
|
)/xs',
|
||||||
|
*/ // note: this can change $this->args & $this->cursor & ...
|
||||||
|
. preg_replace_callback('/(?=`|\[|\'|"|%)(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|%([a-zA-Z]{1,4})(?![a-zA-Z]))/s',
|
||||||
|
array($this, 'cb'),
|
||||||
|
substr($arg, $toSkip)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// associative array without modifier - autoselect between SET or VALUES & LIST
|
if ($comment) continue;
|
||||||
if (!$mod && is_array($arg) && is_string(key($arg))) {
|
|
||||||
if ($commandIns === NULL) {
|
if (is_array($arg)) {
|
||||||
$commandIns = strtoupper(substr(ltrim($args[0]), 0, 6));
|
if (is_string(key($arg))) {
|
||||||
$commandIns = $commandIns === 'INSERT' || $commandIns === 'REPLAC';
|
// associative array -> autoselect between SET or VALUES & LIST
|
||||||
$mod = $commandIns ? 'v' : 'a';
|
if ($commandIns === NULL) {
|
||||||
} else {
|
$commandIns = strtoupper(substr(ltrim($args[0]), 0, 6));
|
||||||
$mod = $commandIns ? 'l' : 'a';
|
$commandIns = $commandIns === 'INSERT' || $commandIns === 'REPLAC';
|
||||||
if ($lastArr === $i - 1) /*$mask[] =*/ $sql[] = ',';
|
$sql[] = $this->formatValue($arg, $commandIns ? 'v' : 'a');
|
||||||
|
} else {
|
||||||
|
if ($lastArr === $cursor - 1) $sql[] = ',';
|
||||||
|
$sql[] = $this->formatValue($arg, $commandIns ? 'l' : 'a');
|
||||||
|
}
|
||||||
|
$lastArr = $cursor;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} elseif ($cursor === 1) {
|
||||||
|
// implicit array expansion
|
||||||
|
$cursor = 0;
|
||||||
|
array_splice($args, 0, 1, $arg);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
$lastArr = $i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// default processing
|
// default processing
|
||||||
//$mask[] = '?';
|
$sql[] = $this->formatValue($arg, FALSE);
|
||||||
if (!$comment) {
|
} // while
|
||||||
$sql[] = $this->formatValue($arg, $mod);
|
|
||||||
}
|
|
||||||
$mod = FALSE;
|
|
||||||
} // foreach
|
|
||||||
|
|
||||||
if ($comment) $sql[] = "\0";
|
if ($comment) $sql[] = "\0";
|
||||||
|
|
||||||
/*$this->mask = implode(' ', $mask);*/
|
|
||||||
|
|
||||||
$this->sql = implode(' ', $sql);
|
$this->sql = implode(' ', $sql);
|
||||||
|
|
||||||
// remove comments
|
// remove comments
|
||||||
@@ -164,52 +192,53 @@ final class DibiTranslator extends NObject
|
|||||||
* @param string
|
* @param string
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function formatValue($value, $modifier)
|
public function formatValue($value, $modifier)
|
||||||
{
|
{
|
||||||
// array processing (with or without modifier)
|
// array processing (with or without modifier)
|
||||||
if (is_array($value)) {
|
if (is_array($value)) {
|
||||||
|
|
||||||
$vx = $kx = array();
|
$vx = $kx = array();
|
||||||
|
$separator = ', ';
|
||||||
switch ($modifier) {
|
switch ($modifier) {
|
||||||
case 'a': // SET (assoc)
|
case 'and':
|
||||||
|
case 'or':
|
||||||
|
$separator = ' ' . strtoupper($modifier) . ' ';
|
||||||
|
if (!is_string(key($value))) {
|
||||||
|
foreach ($value as $v) {
|
||||||
|
$vx[] = $this->formatValue($v, 'sql');
|
||||||
|
}
|
||||||
|
return implode($separator, $vx);
|
||||||
|
}
|
||||||
|
// break intentionally omitted
|
||||||
|
case 'a': // SET key=val, key=val, ...
|
||||||
foreach ($value as $k => $v) {
|
foreach ($value as $k => $v) {
|
||||||
// split into identifier & modifier
|
$pair = explode('%', $k, 2); // split into identifier & modifier
|
||||||
$pair = explode('%', $k, 2);
|
|
||||||
|
|
||||||
// generate array
|
|
||||||
$vx[] = $this->delimite($pair[0]) . '='
|
$vx[] = $this->delimite($pair[0]) . '='
|
||||||
. $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
. $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
||||||
}
|
}
|
||||||
return implode(', ', $vx);
|
return implode($separator, $vx);
|
||||||
|
|
||||||
|
|
||||||
case 'l': // LIST
|
case 'l': // LIST val, val, ...
|
||||||
$kx = NULL;
|
|
||||||
// break intentionally omitted
|
|
||||||
case 'v': // VALUES
|
|
||||||
foreach ($value as $k => $v) {
|
foreach ($value as $k => $v) {
|
||||||
// split into identifier & modifier
|
$pair = explode('%', $k, 2); // split into identifier & modifier
|
||||||
$pair = explode('%', $k, 2);
|
|
||||||
|
|
||||||
// generate arrays
|
|
||||||
if ($kx !== NULL) {
|
|
||||||
$kx[] = $this->delimite($pair[0]);
|
|
||||||
}
|
|
||||||
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
||||||
}
|
}
|
||||||
|
return '(' . implode(', ', $vx) . ')';
|
||||||
|
|
||||||
if ($kx === NULL) {
|
|
||||||
return '(' . implode(', ', $vx) . ')';
|
case 'v': // (key, key, ...) VALUES (val, val, ...)
|
||||||
} else {
|
foreach ($value as $k => $v) {
|
||||||
return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
|
$pair = explode('%', $k, 2); // split into identifier & modifier
|
||||||
|
$kx[] = $this->delimite($pair[0]);
|
||||||
|
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
|
||||||
}
|
}
|
||||||
|
return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
|
||||||
|
|
||||||
default:
|
default:
|
||||||
foreach ($value as $v) {
|
foreach ($value as $v) {
|
||||||
$vx[] = $this->formatValue($v, $modifier);
|
$vx[] = $this->formatValue($v, $modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
return implode(', ', $vx);
|
return implode(', ', $vx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,7 +251,7 @@ final class DibiTranslator extends NObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($value instanceof IDibiVariable) {
|
if ($value instanceof IDibiVariable) {
|
||||||
return $value->toSql($this->driver, $modifier);
|
return $value->toSql($this, $modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_scalar($value)) { // array is already processed
|
if (!is_scalar($value)) { // array is already processed
|
||||||
@@ -266,59 +295,30 @@ final class DibiTranslator extends NObject
|
|||||||
|
|
||||||
case 'sql':// preserve as SQL
|
case 'sql':// preserve as SQL
|
||||||
$value = (string) $value;
|
$value = (string) $value;
|
||||||
|
|
||||||
// speed-up - is regexp required?
|
// speed-up - is regexp required?
|
||||||
$toSkip = strcspn($value, '`[\'"%');
|
$toSkip = strcspn($value, '`[\'"');
|
||||||
|
|
||||||
if (strlen($value) === $toSkip) { // needn't be translated
|
if (strlen($value) === $toSkip) { // needn't be translated
|
||||||
return $value;
|
return $value;
|
||||||
}
|
} else {
|
||||||
|
return substr($value, 0, $toSkip)
|
||||||
// note: only this can change $this->modifier
|
. preg_replace_callback('/(?=`|\[|\'|")(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"(\'|"))/s',
|
||||||
return substr($value, 0, $toSkip)
|
|
||||||
/*
|
|
||||||
. preg_replace_callback('/
|
|
||||||
(?=`|\[|\'|"|%) ## speed-up
|
|
||||||
(?:
|
|
||||||
`(.+?)`| ## 1) `identifier`
|
|
||||||
\[(.+?)\]| ## 2) [identifier]
|
|
||||||
(\')((?:\'\'|[^\'])*)\'| ## 3,4) string
|
|
||||||
(")((?:""|[^"])*)"| ## 5,6) "string"
|
|
||||||
%(else|end)| ## 7) conditional SQL
|
|
||||||
%([a-zA-Z]{1,3})$| ## 8) right modifier
|
|
||||||
(\'|") ## 9) lone-quote
|
|
||||||
)/xs',
|
|
||||||
*/
|
|
||||||
. preg_replace_callback('/(?=`|\[|\'|"|%)(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|%(else|end)|%([a-zA-Z]{1,3})$|(\'|"))/s',
|
|
||||||
array($this, 'cb'),
|
array($this, 'cb'),
|
||||||
substr($value, $toSkip)
|
substr($value, $toSkip)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
case 'lmt': // apply limit
|
|
||||||
if ($value !== NULL) $this->limit = (int) $value;
|
|
||||||
return '';
|
|
||||||
|
|
||||||
case 'ofs': // apply offset
|
|
||||||
if ($value !== NULL) $this->offset = (int) $value;
|
|
||||||
return '';
|
|
||||||
|
|
||||||
case 'a':
|
case 'a':
|
||||||
case 'v':
|
case 'v':
|
||||||
$this->hasError = TRUE;
|
$this->hasError = TRUE;
|
||||||
return '**Unexpected type ' . gettype($value) . '**';
|
return '**Unexpected type ' . gettype($value) . '**';
|
||||||
|
|
||||||
case 'if':
|
|
||||||
$this->hasError = TRUE;
|
|
||||||
return "**The %$modifier is not allowed here**";
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->hasError = TRUE;
|
$this->hasError = TRUE;
|
||||||
return "**Unknown modifier %$modifier**";
|
return "**Unknown or invalid modifier %$modifier**";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// without modifier procession
|
// without modifier procession
|
||||||
if (is_string($value))
|
if (is_string($value))
|
||||||
return $this->driver->format($value, dibi::FIELD_TEXT);
|
return $this->driver->format($value, dibi::FIELD_TEXT);
|
||||||
@@ -333,7 +333,7 @@ final class DibiTranslator extends NObject
|
|||||||
return 'NULL';
|
return 'NULL';
|
||||||
|
|
||||||
if ($value instanceof IDibiVariable)
|
if ($value instanceof IDibiVariable)
|
||||||
return $value->toSql($this->driver, NULL);
|
return $value->toSql($this, NULL);
|
||||||
|
|
||||||
$this->hasError = TRUE;
|
$this->hasError = TRUE;
|
||||||
return '**Unexpected ' . gettype($value) . '**';
|
return '**Unexpected ' . gettype($value) . '**';
|
||||||
@@ -342,8 +342,7 @@ final class DibiTranslator extends NObject
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PREG callback for @see self::formatValue()
|
* PREG callback from translate() or formatValue()
|
||||||
*
|
|
||||||
* @param array
|
* @param array
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@@ -355,17 +354,40 @@ final class DibiTranslator extends NObject
|
|||||||
// [4] => string
|
// [4] => string
|
||||||
// [5] => "
|
// [5] => "
|
||||||
// [6] => string
|
// [6] => string
|
||||||
// [7] => %else | %end
|
// [7] => lone-quote
|
||||||
// [8] => right modifier
|
// [8] => modifier (when called from self::translate())
|
||||||
// [9] => lone-quote
|
|
||||||
|
|
||||||
if (!empty($matches[7])) { // %end | %else
|
if (!empty($matches[8])) { // modifier
|
||||||
if (!$this->ifLevel) {
|
$mod = $matches[8];
|
||||||
|
$cursor = & $this->cursor;
|
||||||
|
|
||||||
|
if ($cursor >= count($this->args) && $mod !== 'else' && $mod !== 'end') {
|
||||||
$this->hasError = TRUE;
|
$this->hasError = TRUE;
|
||||||
return "**Unexpected condition $matches[7]**";
|
return "**Extra modifier %$mod**";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($matches[7] === 'end') {
|
if ($mod === 'if') {
|
||||||
|
$this->ifLevel++;
|
||||||
|
if (!$this->comment && !$this->args[$cursor]) {
|
||||||
|
// open comment
|
||||||
|
$this->ifLevelStart = $this->ifLevel;
|
||||||
|
$this->comment = TRUE;
|
||||||
|
}
|
||||||
|
$cursor++;
|
||||||
|
return "\0";
|
||||||
|
|
||||||
|
} elseif ($mod === 'else') {
|
||||||
|
if ($this->ifLevelStart === $this->ifLevel) {
|
||||||
|
$this->ifLevelStart = 0;
|
||||||
|
$this->comment = FALSE;
|
||||||
|
return "\0";
|
||||||
|
} elseif (!$this->comment) {
|
||||||
|
$this->ifLevelStart = $this->ifLevel;
|
||||||
|
$this->comment = TRUE;
|
||||||
|
return "\0";
|
||||||
|
}
|
||||||
|
|
||||||
|
} elseif ($mod === 'end') {
|
||||||
$this->ifLevel--;
|
$this->ifLevel--;
|
||||||
if ($this->ifLevelStart === $this->ifLevel + 1) {
|
if ($this->ifLevelStart === $this->ifLevel + 1) {
|
||||||
// close comment
|
// close comment
|
||||||
@@ -374,28 +396,29 @@ final class DibiTranslator extends NObject
|
|||||||
return "\0";
|
return "\0";
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
|
||||||
|
|
||||||
// else
|
} elseif ($mod === 'ex') { // array expansion
|
||||||
if ($this->ifLevelStart === $this->ifLevel) {
|
array_splice($this->args, $cursor, 1, $this->args[$cursor]);
|
||||||
$this->ifLevelStart = 0;
|
return '';
|
||||||
$this->comment = FALSE;
|
|
||||||
return "\0";
|
|
||||||
} elseif (!$this->comment) {
|
|
||||||
$this->ifLevelStart = $this->ifLevel;
|
|
||||||
$this->comment = TRUE;
|
|
||||||
return "\0";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($matches[8])) { // modifier
|
} elseif ($mod === 'lmt') { // apply limit
|
||||||
$this->modifier = $matches[8];
|
if ($this->args[$cursor] !== NULL) $this->limit = (int) $this->args[$cursor];
|
||||||
return '';
|
$cursor++;
|
||||||
|
return '';
|
||||||
|
|
||||||
|
} elseif ($mod === 'ofs') { // apply offset
|
||||||
|
if ($this->args[$cursor] !== NULL) $this->offset = (int) $this->args[$cursor];
|
||||||
|
$cursor++;
|
||||||
|
return '';
|
||||||
|
|
||||||
|
} else { // default processing
|
||||||
|
$cursor++;
|
||||||
|
return $this->formatValue($this->args[$cursor - 1], $mod);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->comment) return '';
|
if ($this->comment) return '';
|
||||||
|
|
||||||
|
|
||||||
if ($matches[1]) // SQL identifiers: `ident`
|
if ($matches[1]) // SQL identifiers: `ident`
|
||||||
return $this->delimite($matches[1]);
|
return $this->delimite($matches[1]);
|
||||||
|
|
||||||
@@ -408,8 +431,7 @@ final class DibiTranslator extends NObject
|
|||||||
if ($matches[5]) // SQL strings: "..."
|
if ($matches[5]) // SQL strings: "..."
|
||||||
return $this->driver->format( str_replace('""', '"', $matches[6]), dibi::FIELD_TEXT);
|
return $this->driver->format( str_replace('""', '"', $matches[6]), dibi::FIELD_TEXT);
|
||||||
|
|
||||||
|
if ($matches[7]) { // string quote
|
||||||
if ($matches[9]) { // string quote
|
|
||||||
$this->hasError = TRUE;
|
$this->hasError = TRUE;
|
||||||
return '**Alone quote**';
|
return '**Alone quote**';
|
||||||
}
|
}
|
||||||
|
@@ -29,20 +29,20 @@ class DibiVariable extends NObject implements IDibiVariable
|
|||||||
public $value;
|
public $value;
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public $type;
|
public $modifier;
|
||||||
|
|
||||||
|
|
||||||
public function __construct($value, $type)
|
public function __construct($value, $modifier)
|
||||||
{
|
{
|
||||||
$this->value = $value;
|
$this->value = $value;
|
||||||
$this->type = $type;
|
$this->modifier = $modifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function toSql(IDibiDriver $driver, $modifier)
|
public function toSql(DibiTranslator $translator, $modifier)
|
||||||
{
|
{
|
||||||
return $driver->format($this->value, $this->type);
|
return $translator->formatValue($this->value, $this->modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -28,11 +28,11 @@ interface IDibiVariable
|
|||||||
/**
|
/**
|
||||||
* Format for SQL
|
* Format for SQL
|
||||||
*
|
*
|
||||||
* @param object destination IDibiDriver
|
* @param object DibiTranslator
|
||||||
* @param string optional modifier
|
* @param string optional modifier
|
||||||
* @return string SQL code
|
* @return string SQL code
|
||||||
*/
|
*/
|
||||||
public function toSql(IDibiDriver $driver, $modifier);
|
public function toSql(DibiTranslator $translator, $modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,34 +0,0 @@
|
|||||||
OK: SELECT * FROM [customers] WHERE [customer_id] = 1;
|
|
||||||
-- rows: 1
|
|
||||||
-- takes: 0.395 ms
|
|
||||||
-- driver: sqlite
|
|
||||||
-- 2007-11-15 01:19:00
|
|
||||||
|
|
||||||
OK: SELECT * FROM [customers] WHERE [customer_id] < 5;
|
|
||||||
-- rows: 4
|
|
||||||
-- takes: 0.437 ms
|
|
||||||
-- driver: sqlite
|
|
||||||
-- 2007-11-15 01:19:00
|
|
||||||
|
|
||||||
ERROR: [1] near "FROM": syntax error
|
|
||||||
-- SQL: SELECT FROM [customers] WHERE [customer_id] < 38
|
|
||||||
-- driver: ;
|
|
||||||
-- 2007-11-15 01:19:00
|
|
||||||
|
|
||||||
OK: SELECT * FROM [customers] WHERE [customer_id] = 1;
|
|
||||||
-- rows: 1
|
|
||||||
-- takes: 0.319 ms
|
|
||||||
-- driver: sqlite
|
|
||||||
-- 2008-01-18 03:57:19
|
|
||||||
|
|
||||||
OK: SELECT * FROM [customers] WHERE [customer_id] < 5;
|
|
||||||
-- rows: 4
|
|
||||||
-- takes: 0.384 ms
|
|
||||||
-- driver: sqlite
|
|
||||||
-- 2008-01-18 03:57:19
|
|
||||||
|
|
||||||
ERROR: [2] sqlite_query(): near "FROM": syntax error
|
|
||||||
-- SQL: SELECT FROM [customers] WHERE [customer_id] < 38
|
|
||||||
-- driver: ;
|
|
||||||
-- 2008-01-18 03:57:19
|
|
||||||
|
|
Reference in New Issue
Block a user