[2.0] Parser work. Added double-dispatch functionality to AST node classes for use in the SqlWalker to reduce big if/else instanceof checks and for better maintainability. Also its less error-prone in the SqlWalker because its harder to miss a conditional case. Added new extensible DQL function implementation.
This commit is contained in:
parent
618c1281e4
commit
ae5d212271
@ -38,4 +38,9 @@ class AggregateExpression extends Node
|
||||
{
|
||||
return $this->_functionName;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkAggregateExpression($this);
|
||||
}
|
||||
}
|
@ -51,4 +51,9 @@ class ArithmeticExpression extends Node
|
||||
{
|
||||
return (bool) $this->_subselect;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkArithmeticExpression($this);
|
||||
}
|
||||
}
|
@ -38,4 +38,9 @@ class ArithmeticFactor extends Node
|
||||
{
|
||||
return $this->_nSigned;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkArithmeticFactor($this);
|
||||
}
|
||||
}
|
@ -24,4 +24,9 @@ class ArithmeticTerm extends Node
|
||||
{
|
||||
return $this->_factors;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkArithmeticTerm($this);
|
||||
}
|
||||
}
|
@ -49,5 +49,10 @@ class BetweenExpression extends Node
|
||||
{
|
||||
return $this->_not;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkBetweenExpression($this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,22 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST;
|
||||
@ -43,4 +58,9 @@ class ComparisonExpression extends Node
|
||||
{
|
||||
return $this->_operator;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkComparisonExpression($this);
|
||||
}
|
||||
}
|
@ -35,4 +35,8 @@ namespace Doctrine\ORM\Query\AST;
|
||||
*/
|
||||
class ComparisonOperator extends Node
|
||||
{
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
@ -24,4 +24,9 @@ class ConditionalExpression extends Node
|
||||
{
|
||||
return $this->_conditionalTerms;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkConditionalExpression($this);
|
||||
}
|
||||
}
|
@ -31,4 +31,9 @@ class ConditionalFactor extends Node
|
||||
{
|
||||
return $this->_conditionalPrimary;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkConditionalFactor($this);
|
||||
}
|
||||
}
|
@ -45,4 +45,9 @@ class ConditionalPrimary extends Node
|
||||
{
|
||||
return (bool) $this->_conditionalExpression;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkConditionalPrimary($this);
|
||||
}
|
||||
}
|
@ -24,4 +24,9 @@ class ConditionalTerm extends Node
|
||||
{
|
||||
return $this->_conditionalFactors;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkConditionalTerm($this);
|
||||
}
|
||||
}
|
@ -48,5 +48,10 @@ class DeleteClause extends Node
|
||||
{
|
||||
$this->_aliasIdentificationVariable = $alias;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkDeleteClause($this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,4 +54,9 @@ class DeleteStatement extends Node
|
||||
{
|
||||
return $this->_whereClause;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkDeleteStatement($this);
|
||||
}
|
||||
}
|
@ -26,9 +26,19 @@ class ExistsExpression extends Node
|
||||
$this->_not = $bool;
|
||||
}
|
||||
|
||||
public function getNot()
|
||||
public function isNot()
|
||||
{
|
||||
return $this->_not;
|
||||
}
|
||||
|
||||
public function getSubselect()
|
||||
{
|
||||
return $this->_subselect;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkExistsExpression($this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,4 +44,9 @@ class FromClause extends Node
|
||||
{
|
||||
return $this->_identificationVariableDeclarations;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkFromClause($this);
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST;
|
||||
|
||||
/**
|
||||
* Description of Function
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class FunctionNode extends Node
|
||||
{
|
||||
private $_name;
|
||||
}
|
59
lib/Doctrine/ORM/Query/AST/Functions/ConcatFunction.php
Normal file
59
lib/Doctrine/ORM/Query/AST/Functions/ConcatFunction.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST\Functions;
|
||||
|
||||
/**
|
||||
* "CONCAT" "(" StringPrimary "," StringPrimary ")"
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class ConcatFunction extends FunctionNode
|
||||
{
|
||||
private $_firstStringPrimary;
|
||||
private $_secondStringPriamry;
|
||||
|
||||
public function getFirstStringPrimary()
|
||||
{
|
||||
return $this->_firstStringPrimary;
|
||||
}
|
||||
|
||||
public function getSecondStringPrimary()
|
||||
{
|
||||
return $this->_secondStringPrimary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
|
||||
{
|
||||
//TODO: Use platform to get SQL
|
||||
$sql = 'CONCAT(' .
|
||||
$sqlWalker->walkStringPrimary($this->_firstStringPrimary)
|
||||
. ', ' .
|
||||
$sqlWalker->walkStringPrimary($this->_secondStringPrimary)
|
||||
. ')';
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public function parse(\Doctrine\ORM\Query\Parser $parser)
|
||||
{
|
||||
$lexer = $parser->getLexer();
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
|
||||
$this->_firstStringPrimary = $parser->_StringPrimary();
|
||||
$parser->match(',');
|
||||
$this->_secondStringPrimary = $parser->_StringPrimary();
|
||||
|
||||
$parser->match(')');
|
||||
}
|
||||
}
|
||||
|
66
lib/Doctrine/ORM/Query/AST/Functions/FunctionNode.php
Normal file
66
lib/Doctrine/ORM/Query/AST/Functions/FunctionNode.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST\Functions;
|
||||
|
||||
use Doctrine\ORM\Query\AST\Node;
|
||||
|
||||
/**
|
||||
* Description of Function
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
abstract class FunctionNode extends Node
|
||||
{
|
||||
private $_name;
|
||||
//private $_expressions = array();
|
||||
|
||||
public function __construct($name)
|
||||
{
|
||||
$this->_name = $name;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->_name;
|
||||
}
|
||||
|
||||
abstract public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker);
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkFunction($this);
|
||||
}
|
||||
|
||||
//abstract public function parse(\Doctrine\ORM\Query\Parser $parser);
|
||||
|
||||
/*
|
||||
public function getExpressions()
|
||||
{
|
||||
return $this->_expressions;
|
||||
}
|
||||
|
||||
public function setExpressions(array $expressions)
|
||||
{
|
||||
$this->_expressions = $expressions;
|
||||
}
|
||||
*/
|
||||
}
|
44
lib/Doctrine/ORM/Query/AST/Functions/LowerFunction.php
Normal file
44
lib/Doctrine/ORM/Query/AST/Functions/LowerFunction.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST\Functions;
|
||||
|
||||
/**
|
||||
* "LOWER" "(" StringPrimary ")"
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class LowerFunction extends FunctionNode
|
||||
{
|
||||
private $_stringPrimary;
|
||||
|
||||
public function getStringPrimary()
|
||||
{
|
||||
return $this->_stringPrimary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
|
||||
{
|
||||
//TODO: Use platform to get SQL
|
||||
return 'LOWER(' . $sqlWalker->walkStringPrimary($this->_stringPrimary) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public function parse(\Doctrine\ORM\Query\Parser $parser)
|
||||
{
|
||||
$lexer = $parser->getLexer();
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
$this->_stringPrimary = $parser->_StringPrimary();
|
||||
$parser->match(')');
|
||||
}
|
||||
}
|
||||
|
69
lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php
Normal file
69
lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST\Functions;
|
||||
|
||||
/**
|
||||
* "SUBSTRING" "(" StringPrimary "," SimpleArithmeticExpression "," SimpleArithmeticExpression ")"
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class SubstringFunction extends FunctionNode
|
||||
{
|
||||
private $_stringPrimary;
|
||||
private $_firstSimpleArithmeticExpression;
|
||||
private $_secondSimpleArithmeticExpression;
|
||||
|
||||
public function geStringPrimary()
|
||||
{
|
||||
return $this->_stringPrimary;
|
||||
}
|
||||
|
||||
public function getSecondSimpleArithmeticExpression()
|
||||
{
|
||||
return $this->_secondSimpleArithmeticExpression;
|
||||
}
|
||||
|
||||
public function getFirstSimpleArithmeticExpression()
|
||||
{
|
||||
return $this->_firstSimpleArithmeticExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
|
||||
{
|
||||
//TODO: Use platform to get SQL
|
||||
$sql = 'SUBSTRING(' .
|
||||
$sqlWalker->walkStringPrimary($this->_stringPrimary)
|
||||
. ', ' .
|
||||
$sqlWalker->walkSimpleArithmeticExpression($this->_firstSimpleArithmeticExpression)
|
||||
. ', ' .
|
||||
$sqlWalker->walkSimpleArithmeticExpression($this->_secondSimpleArithmeticExpression)
|
||||
. ')';
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public function parse(\Doctrine\ORM\Query\Parser $parser)
|
||||
{
|
||||
$lexer = $parser->getLexer();
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
|
||||
$this->_stringPrimary = $parser->_StringPrimary();
|
||||
$parser->match(',');
|
||||
$this->_firstSimpleArithmeticExpression = $parser->_SimpleArithmeticExpression();
|
||||
$parser->match(',');
|
||||
$this->_secondSimpleArithmeticExpression = $parser->_SimpleArithmeticExpression();
|
||||
|
||||
$parser->match(')');
|
||||
}
|
||||
}
|
||||
|
118
lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php
Normal file
118
lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php
Normal file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST\Functions;
|
||||
|
||||
use Doctrine\ORM\Query\Lexer;
|
||||
|
||||
/**
|
||||
* "TRIM" "(" [["LEADING" | "TRAILING" | "BOTH"] [char] "FROM"] StringPrimary ")"
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class TrimFunction extends FunctionNode
|
||||
{
|
||||
private $_leading;
|
||||
private $_trailing;
|
||||
private $_both;
|
||||
private $_trimChar;
|
||||
private $_stringPrimary;
|
||||
|
||||
public function getStringPrimary()
|
||||
{
|
||||
return $this->_stringPrimary;
|
||||
}
|
||||
|
||||
public function isLeading()
|
||||
{
|
||||
return $this->_leading;
|
||||
}
|
||||
|
||||
public function setLeading($bool)
|
||||
{
|
||||
$this->_leading = $bool;
|
||||
}
|
||||
|
||||
public function isTrailing()
|
||||
{
|
||||
return $this->_trailing;
|
||||
}
|
||||
|
||||
public function setTrailing($bool)
|
||||
{
|
||||
$this->_trailing = $bool;
|
||||
}
|
||||
|
||||
public function isBoth()
|
||||
{
|
||||
return $this->_both;
|
||||
}
|
||||
|
||||
public function setBoth($bool)
|
||||
{
|
||||
$this->_both = $bool;
|
||||
}
|
||||
|
||||
public function getTrimChar()
|
||||
{
|
||||
return $this->_trimChar;
|
||||
}
|
||||
|
||||
public function setTrimChar($trimChar)
|
||||
{
|
||||
$this->_trimChar = $trimChar;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
|
||||
{
|
||||
$sql = 'TRIM(';
|
||||
if ($this->_leading) $sql .= 'LEADING ';
|
||||
else if ($this->_trailing) $sql .= 'TRAILING ';
|
||||
else if ($this->_both) $sql .= 'BOTH ';
|
||||
if ($this->_trimChar) $sql .= $this->_trimChar . ' '; //TODO: quote()
|
||||
$sql .= 'FROM ' . $sqlWalker->walkStringPrimary($this->_stringPrimary);
|
||||
$sql .= ')';
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public function parse(\Doctrine\ORM\Query\Parser $parser)
|
||||
{
|
||||
$lexer = $parser->getLexer();
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
|
||||
if (strcasecmp('leading', $lexer->lookahead['value']) === 0) {
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$this->_leading = true;
|
||||
} else if (strcasecmp('trailing', $lexer->lookahead['value']) === 0) {
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$this->_trailing = true;
|
||||
} else if (strcasecmp('both', $lexer->lookahead['value']) === 0) {
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$this->_both = true;
|
||||
}
|
||||
|
||||
if ($lexer->isNextToken(Lexer::T_STRING)) {
|
||||
$parser->match(Lexer::T_STRING);
|
||||
$this->_trimChar = $lexer->token['value'];
|
||||
}
|
||||
|
||||
if ($this->_leading || $this->_trailing || $this->_both || $this->_trimChar) {
|
||||
$parser->match(Lexer::T_FROM);
|
||||
}
|
||||
|
||||
$this->_stringPrimary = $parser->_StringPrimary();
|
||||
|
||||
$parser->match(')');
|
||||
}
|
||||
|
||||
}
|
44
lib/Doctrine/ORM/Query/AST/Functions/UpperFunction.php
Normal file
44
lib/Doctrine/ORM/Query/AST/Functions/UpperFunction.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST\Functions;
|
||||
|
||||
/**
|
||||
* "UPPER" "(" StringPrimary ")"
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class UpperFunction extends FunctionNode
|
||||
{
|
||||
private $_stringPrimary;
|
||||
|
||||
public function getStringPrimary()
|
||||
{
|
||||
return $this->_stringPrimary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
|
||||
{
|
||||
//TODO: Use platform to get SQL
|
||||
return 'UPPER(' . $sqlWalker->walkStringPrimary($this->_stringPrimary) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public function parse(\Doctrine\ORM\Query\Parser $parser)
|
||||
{
|
||||
$lexer = $parser->getLexer();
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
$this->_stringPrimary = $parser->_StringPrimary();
|
||||
$parser->match(')');
|
||||
}
|
||||
}
|
||||
|
@ -24,4 +24,9 @@ class GroupByClause extends Node
|
||||
{
|
||||
return $this->_groupByItems;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkGroupByClause($this);
|
||||
}
|
||||
}
|
@ -24,4 +24,9 @@ class HavingClause extends Node
|
||||
{
|
||||
return $this->_conditionalExpression;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkHavingClause($this);
|
||||
}
|
||||
}
|
@ -63,16 +63,8 @@ class IdentificationVariableDeclaration extends Node
|
||||
return $this->_joinVariableDeclarations;
|
||||
}
|
||||
|
||||
/* REMOVE ME LATER. COPIED METHODS FROM SPLIT OF PRODUCTION INTO "AST" AND "PARSER" */
|
||||
|
||||
public function buildSql()
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
$str = $this->_rangeVariableDeclaration->buildSql();
|
||||
|
||||
for ($i = 0, $l = count($this->_joinVariableDeclarations); $i < $l; $i++) {
|
||||
$str .= ' ' . $this->_joinVariableDeclarations[$i]->buildSql();
|
||||
}
|
||||
|
||||
return $str;
|
||||
return $sqlWalker->walkIdentificationVariableDeclaration($this);
|
||||
}
|
||||
}
|
@ -57,5 +57,10 @@ class InExpression extends Node
|
||||
{
|
||||
return $this->_pathExpression;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkInExpression($this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,4 +44,9 @@ class IndexBy extends Node
|
||||
{
|
||||
return $this->_simpleStateFieldPathExpression;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkIndexBy($this);
|
||||
}
|
||||
}
|
@ -51,4 +51,9 @@ class InputParameter extends Node
|
||||
{
|
||||
return $this->_position;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkInputParameter($this);
|
||||
}
|
||||
}
|
@ -90,96 +90,8 @@ class Join extends Node
|
||||
return $this->_conditionalExpression;
|
||||
}
|
||||
|
||||
/* REMOVE ME LATER. COPIED METHODS FROM SPLIT OF PRODUCTION INTO "AST" AND "PARSER" */
|
||||
|
||||
public function buildSql()
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
$join = '';
|
||||
|
||||
switch ($this->_joinType) {
|
||||
case self::JOIN_TYPE_LEFT:
|
||||
$join .= 'LEFT';
|
||||
break;
|
||||
|
||||
case self::JOIN_TYPE_LEFTOUTER:
|
||||
$join .= 'LEFT OUTER';
|
||||
break;
|
||||
|
||||
case self::JOIN_TYPE_INNER:
|
||||
default:
|
||||
$join .= 'INNER';
|
||||
break;
|
||||
}
|
||||
|
||||
$join .= ' JOIN ' . $this->_joinAssociationPathExpression->buildSql();
|
||||
$condition = isset($this->_conditionalExpression)
|
||||
? $this->_conditionalExpression->buildSql() : '';
|
||||
|
||||
switch ($this->whereType) {
|
||||
case self::JOIN_WHERE_ON:
|
||||
// Nothing to do here... =)
|
||||
break;
|
||||
|
||||
case self::JOIN_WHERE_WITH:
|
||||
default:
|
||||
|
||||
/*
|
||||
|
||||
TODO: Refactor to support split!!!
|
||||
|
||||
$parserResult = $this->_parser->getParserResult();
|
||||
|
||||
// Get the connection for the component
|
||||
$conn = $this->_em->getConnection();
|
||||
|
||||
// We need to build the join conditions. Retrieving AssociationMapping
|
||||
$queryComponent = $this->_rangeVariableDeclaration->getQueryComponent();
|
||||
$association = $queryComponent['relation'];
|
||||
$joinColumns = array();
|
||||
|
||||
if ($association->isOneToMany() || $association->isOneToOne()) {
|
||||
if ($association->isInverseSide()) {
|
||||
// joinColumns are found on the other (owning) side
|
||||
$targetClass = $this->_em->getClassMetadata($association->getTargetEntityName());
|
||||
$joinColumns = $targetClass->getAssociationMapping($association->getMappedByFieldName())
|
||||
->getTargetToSourceKeyColumns();
|
||||
} else {
|
||||
$joinColumns = $association->getSourceToTargetKeyColumns();
|
||||
}
|
||||
} else {
|
||||
//TODO: many-many
|
||||
}
|
||||
|
||||
$relationConditionExpression = '';
|
||||
|
||||
// We have an array('localColumn' => 'foreignColumn', ...) here
|
||||
foreach ($joinColumns as $localColumn => $foreignColumn) {
|
||||
// leftExpression = rightExpression
|
||||
|
||||
// Defining leftExpression
|
||||
$leftExpression = $conn->quoteIdentifier(
|
||||
$parserResult->getTableAliasFromComponentAlias($queryComponent['parent']) . '.' . $localColumn
|
||||
);
|
||||
|
||||
// Defining rightExpression
|
||||
$rightExpression = $conn->quoteIdentifier(
|
||||
$parserResult->getTableAliasFromComponentAlias(
|
||||
$this->_rangeVariableDeclaration->getIdentificationVariable()
|
||||
) . '.' . $foreignColumn
|
||||
);
|
||||
|
||||
// Building the relation
|
||||
$relationConditionExpression .= (($relationConditionExpression != '') ? ' AND ' : '')
|
||||
. $leftExpression . ' = ' . $rightExpression;
|
||||
}
|
||||
|
||||
$sql .= ' ON ' . $relationConditionExpression;
|
||||
$sql .= empty($conditionExpression) ? '' : ' AND (' . $conditionExpression . ')';
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return $join . ' ON ' . $condition;
|
||||
return $sqlWalker->walkJoin($this);
|
||||
}
|
||||
}
|
@ -32,4 +32,9 @@ class JoinPathExpression extends Node
|
||||
{
|
||||
return $this->_assocField;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkJoinPathExpression($this);
|
||||
}
|
||||
}
|
@ -52,9 +52,8 @@ class JoinVariableDeclaration extends Node
|
||||
return $this->_indexBy;
|
||||
}
|
||||
|
||||
/* REMOVE ME LATER. COPIED METHODS FROM SPLIT OF PRODUCTION INTO "AST" AND "PARSER" */
|
||||
public function buildSql()
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $this->_join->buildSql() . (isset($this->_indexby) ? $this->_indexby->buildSql() . ' ' : '');
|
||||
return $sqlWalker->walkJoinVariableDeclaration($this);
|
||||
}
|
||||
}
|
@ -45,4 +45,9 @@ class LikeExpression extends Node
|
||||
{
|
||||
return $this->_escapeChar;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkLikeExpression($this);
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST;
|
||||
@ -27,10 +27,11 @@ namespace Doctrine\ORM\Query\AST;
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Janne Vanhala <jpvanhal@cc.hut.fi>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @link http://www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
abstract class Node
|
||||
{
|
||||
abstract public function dispatch($sqlWalker);
|
||||
}
|
@ -35,5 +35,10 @@ class NullComparisonExpression extends Node
|
||||
{
|
||||
return $this->_not;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkNullComparisonExpression($this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,4 +24,9 @@ class OrderByClause extends Node
|
||||
{
|
||||
return $this->_orderByItems;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkOrderByClause($this);
|
||||
}
|
||||
}
|
@ -46,4 +46,9 @@ class OrderByItem extends Node
|
||||
{
|
||||
return $this->_desc;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkOrderByItem($this);
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST;
|
||||
@ -26,7 +26,7 @@ namespace Doctrine\ORM\Query\AST;
|
||||
*
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @link http://www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
@ -59,26 +59,8 @@ class RangeVariableDeclaration extends Node
|
||||
return $this->_classMetadata;
|
||||
}
|
||||
|
||||
/* REMOVE ME LATER. COPIED METHODS FROM SPLIT OF PRODUCTION INTO "AST" AND "PARSER" */
|
||||
public function buildSql()
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
// Retrieving connection
|
||||
$conn = $this->_parserResult->getEntityManager()->getConnection();
|
||||
|
||||
// Component alias
|
||||
$componentAlias = $this->_aliasIdentificationVariable;
|
||||
|
||||
// Retrieving required information
|
||||
try {
|
||||
$queryComponent = $this->_parserResult->getQueryComponent($componentAlias);
|
||||
$classMetadata = $queryComponent['metadata'];
|
||||
} catch (Doctrine_Exception $e) {
|
||||
$this->_parser->semanticalError($e->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return $conn->quoteIdentifier($classMetadata->getTableName()) . ' '
|
||||
. $conn->quoteIdentifier($this->_parserResult->getTableAliasFromComponentAlias($componentAlias));
|
||||
return $sqlWalker->walkRangeVariableDeclaration($this);
|
||||
}
|
||||
}
|
@ -69,4 +69,9 @@ class SelectClause extends Node
|
||||
{
|
||||
return is_object($value) ? $value->buildSql() : $value;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkSelectClause($this);
|
||||
}
|
||||
}
|
@ -52,4 +52,9 @@ class SelectExpression extends Node
|
||||
{
|
||||
return $this->_fieldIdentificationVariable;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkSelectExpression($this);
|
||||
}
|
||||
}
|
@ -80,14 +80,8 @@ class SelectStatement extends Node
|
||||
return $this->_orderByClause;
|
||||
}
|
||||
|
||||
/* REMOVE ME LATER. COPIED METHODS FROM SPLIT OF PRODUCTION INTO "AST" AND "PARSER" */
|
||||
|
||||
public function buildSql()
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $this->_selectClause->buildSql() . ' ' . $this->_fromClause->buildSql()
|
||||
. (($this->_whereClause !== null) ? ' ' . $this->_whereClause->buildSql() : '')
|
||||
. (($this->_groupByClause !== null) ? ' ' . $this->_groupByClause->buildSql() : '')
|
||||
. (($this->_havingClause !== null) ? ' ' . $this->_havingClause->buildSql() : '')
|
||||
. (($this->_orderByClause !== null) ? ' ' . $this->_orderByClause->buildSql() : '');
|
||||
return $sqlWalker->walkSelectStatement($this);
|
||||
}
|
||||
}
|
@ -24,4 +24,9 @@ class SimpleArithmeticExpression extends Node
|
||||
{
|
||||
return $this->_terms;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkSimpleArithmeticExpression($this);
|
||||
}
|
||||
}
|
@ -55,4 +55,9 @@ class SimpleSelectClause extends Node
|
||||
{
|
||||
return $this->_simpleSelectExpression;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkSimpleSelectClause($this);
|
||||
}
|
||||
}
|
@ -55,4 +55,9 @@ class SimpleSelectExpression extends Node
|
||||
{
|
||||
$this->_fieldIdentificationVariable = $fieldAlias;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkSimpleSelectExpression($this);
|
||||
}
|
||||
}
|
@ -51,4 +51,9 @@ class SimpleStateFieldPathExpression extends Node
|
||||
{
|
||||
return $this->_simpleStateField;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkSimpleStateFieldPathExpression($this);
|
||||
}
|
||||
}
|
@ -95,4 +95,9 @@ class StateFieldPathExpression extends Node
|
||||
{
|
||||
$this->_collectionValuedAssociationFields[$part] = true;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkStateFieldPathExpression($this);
|
||||
}
|
||||
}
|
@ -95,4 +95,9 @@ class Subselect extends Node
|
||||
{
|
||||
$this->_orderByClause = $orderByClause;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkSubselect($this);
|
||||
}
|
||||
}
|
@ -44,4 +44,9 @@ class SubselectFromClause extends Node
|
||||
{
|
||||
return $this->_identificationVariableDeclarations;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkSubselectFromClause($this);
|
||||
}
|
||||
}
|
@ -40,5 +40,10 @@ class UpdateClause extends Node
|
||||
{
|
||||
return $this->_updateItems;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkUpdateClause($this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,22 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST;
|
||||
@ -42,5 +57,10 @@ class UpdateItem extends Node
|
||||
{
|
||||
return $this->_newValue;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkUpdateItem($this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,4 +54,9 @@ class UpdateStatement extends Node
|
||||
{
|
||||
return $this->_whereClause;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkUpdateStatement($this);
|
||||
}
|
||||
}
|
@ -24,4 +24,9 @@ class WhereClause extends Node
|
||||
{
|
||||
return $this->_conditionalExpression;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkWhereClause($this);
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* $Id: Cache.php 3938 2008-03-06 19:36:50Z romanb $
|
||||
*
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
namespace Doctrine\ORM\Query;
|
||||
|
||||
use Doctrine\Common\DoctrineException;
|
||||
use Doctrine\ORM\Query\AST;
|
||||
use Doctrine\ORM\Query\Exec;
|
||||
|
||||
@ -40,6 +41,32 @@ class Parser
|
||||
{
|
||||
const SCALAR_QUERYCOMPONENT_ALIAS = 'dctrn';
|
||||
|
||||
/** Maps registered string function names to class names. */
|
||||
private static $_STRING_FUNCTIONS = array(
|
||||
'concat' => 'Doctrine\ORM\Query\AST\Functions\ConcatFunction',
|
||||
'substring' => 'Doctrine\ORM\Query\AST\Functions\SubstringFunction',
|
||||
'trim' => 'Doctrine\ORM\Query\AST\Functions\TrimFunction',
|
||||
'lower' => 'Doctrine\ORM\Query\AST\Functions\LowerFunction',
|
||||
'upper' => 'Doctrine\ORM\Query\AST\Functions\UpperFunction'
|
||||
);
|
||||
|
||||
/** Maps registered numeric function names to class names. */
|
||||
private static $_NUMERIC_FUNCTIONS = array(
|
||||
'length' => 'Doctrine\ORM\Query\AST\Functions\LengthFunction',
|
||||
'locate' => 'Doctrine\ORM\Query\AST\Functions\LocateFunction',
|
||||
'abs' => 'Doctrine\ORM\Query\AST\Functions\AbsFunction',
|
||||
'sqrt' => 'Doctrine\ORM\Query\AST\Functions\SqrtFunction',
|
||||
'mod' => 'Doctrine\ORM\Query\AST\Functions\ModFunction',
|
||||
'size' => 'Doctrine\ORM\Query\AST\Functions\SizeFunction'
|
||||
);
|
||||
|
||||
/** Maps registered datetime function names to class names. */
|
||||
private static $_DATETIME_FUNCTIONS = array(
|
||||
'current_date' => 'Doctrine\ORM\Query\AST\Functions\CurrentDateFunction',
|
||||
'current_time' => 'Doctrine\ORM\Query\AST\Functions\CurrentTimeFunction',
|
||||
'current_timestamp' => 'Doctrine\ORM\Query\AST\Functions\CurrentTimestampFunction'
|
||||
);
|
||||
|
||||
/**
|
||||
* The minimum number of tokens read after last detected error before
|
||||
* another error can be reported.
|
||||
@ -713,41 +740,6 @@ class Parser
|
||||
return $this->_lexer->token['value'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Special rule that acceps all kinds of path expressions.
|
||||
*/
|
||||
/*private function _StateFieldPathExpression()
|
||||
{
|
||||
$this->match(Lexer::T_IDENTIFIER);
|
||||
$parts = array($this->_lexer->token['value']);
|
||||
while ($this->_lexer->isNextToken('.')) {
|
||||
$this->match('.');
|
||||
$this->match(Lexer::T_IDENTIFIER);
|
||||
$parts[] = $this->_lexer->token['value'];
|
||||
}
|
||||
$pathExpression = new AST\StateFieldPathExpression($parts);
|
||||
return $pathExpression;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Special rule that acceps all kinds of path expressions. and defers their
|
||||
* semantical checking until the FROM part has been parsed completely (joins inclusive).
|
||||
* Mainly used for path expressions in the SelectExpressions.
|
||||
*/
|
||||
/*private function _PathExpressionInSelect()
|
||||
{
|
||||
$this->match(Lexer::T_IDENTIFIER);
|
||||
$parts = array($this->_lexer->token['value']);
|
||||
while ($this->_lexer->isNextToken('.')) {
|
||||
$this->match('.');
|
||||
$this->match(Lexer::T_IDENTIFIER);
|
||||
$parts[] = $this->_lexer->token['value'];
|
||||
}
|
||||
$expr = new AST\StateFieldPathExpression($parts);
|
||||
$this->_pendingPathExpressionsInSelect[] = $expr;
|
||||
return $expr;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* JoinVariableDeclaration ::= Join [IndexBy]
|
||||
*/
|
||||
@ -1231,23 +1223,138 @@ class Parser
|
||||
}
|
||||
|
||||
/**
|
||||
* SIMPLIFIED FROM BNF FOR NOW
|
||||
* ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression )
|
||||
* ComparisonExpression ::=
|
||||
* ArithmeticExpression ComparisonOperator (QuantifiedExpression | ArithmeticExpression) |
|
||||
* StringExpression ComparisonOperator (StringExpression | QuantifiedExpression) |
|
||||
* BooleanExpression ("=" | "<>" | "!=") (BooleanExpression | QuantifiedExpression) |
|
||||
* EnumExpression ("=" | "<>" | "!=") (EnumExpression | QuantifiedExpression) |
|
||||
* DatetimeExpression ComparisonOperator (DatetimeExpression | QuantifiedExpression) |
|
||||
* EntityExpression ("=" | "<>") (EntityExpression | QuantifiedExpression)
|
||||
*/
|
||||
private function _ComparisonExpression()
|
||||
{
|
||||
$leftExpr = $this->_ArithmeticExpression();
|
||||
$operator = $this->_ComparisonOperator();
|
||||
if ($this->_lexer->lookahead['type'] === Lexer::T_ALL ||
|
||||
$this->_lexer->lookahead['type'] === Lexer::T_ANY ||
|
||||
$this->_lexer->lookahead['type'] === Lexer::T_SOME) {
|
||||
$rightExpr = $this->_QuantifiedExpression();
|
||||
} else {
|
||||
$peek = $this->_lexer->glimpse();
|
||||
|
||||
if ($this->_lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) {
|
||||
if ($this->_isComparisonOperator($peek)) {
|
||||
$this->match(Lexer::T_INPUT_PARAMETER);
|
||||
$leftExpr = new AST\InputParameter($this->_lexer->token['value']);
|
||||
} else {
|
||||
$leftExpr = $this->_ArithmeticExpression();
|
||||
}
|
||||
$operator = $this->_ComparisonOperator();
|
||||
$rightExpr = $this->_ArithmeticExpression();
|
||||
//...
|
||||
}
|
||||
else if ($this->_lexer->isNextToken('(') && $peek['type'] == Lexer::T_SELECT) {
|
||||
$leftExpr = $this->_Subselect();
|
||||
//...
|
||||
}
|
||||
else if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER) && $peek['value'] == '(') {
|
||||
$peek2 = $this->_peekBeyond(')');
|
||||
if ($this->_isComparisonOperator($peek2)) {
|
||||
if ($this->_isStringFunction($this->_lexer->lookahead['value'])) {
|
||||
$leftExpr = $this->_FunctionsReturningStrings();
|
||||
$operator = $this->_ComparisonOperator();
|
||||
if ($this->_lexer->lookahead['type'] === Lexer::T_ALL ||
|
||||
$this->_lexer->lookahead['type'] === Lexer::T_ANY ||
|
||||
$this->_lexer->lookahead['type'] === Lexer::T_SOME) {
|
||||
$rightExpr = $this->_QuantifiedExpression();
|
||||
} else {
|
||||
$rightExpr = $this->_StringPrimary();
|
||||
}
|
||||
} else if ($this->_isNumericFunction($this->_lexer->lookahead['value'])) {
|
||||
$leftExpr = $this->_FunctionsReturningNumerics();
|
||||
$operator = $this->_ComparisonOperator();
|
||||
if ($this->_lexer->lookahead['type'] === Lexer::T_ALL ||
|
||||
$this->_lexer->lookahead['type'] === Lexer::T_ANY ||
|
||||
$this->_lexer->lookahead['type'] === Lexer::T_SOME) {
|
||||
$rightExpr = $this->_QuantifiedExpression();
|
||||
} else {
|
||||
$rightExpr = $this->_ArithmeticExpression();
|
||||
}
|
||||
} else {
|
||||
$leftExpr = $this->_FunctionsReturningDatetime();
|
||||
$operator = $this->_ComparisonOperator();
|
||||
if ($this->_lexer->lookahead['type'] === Lexer::T_ALL ||
|
||||
$this->_lexer->lookahead['type'] === Lexer::T_ANY ||
|
||||
$this->_lexer->lookahead['type'] === Lexer::T_SOME) {
|
||||
$rightExpr = $this->_QuantifiedExpression();
|
||||
} else {
|
||||
$rightExpr = $this->_DatetimePrimary();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$leftExpr = $this->_ArithmeticExpression();
|
||||
$operator = $this->_ComparisonOperator();
|
||||
if ($this->_lexer->lookahead['type'] === Lexer::T_ALL ||
|
||||
$this->_lexer->lookahead['type'] === Lexer::T_ANY ||
|
||||
$this->_lexer->lookahead['type'] === Lexer::T_SOME) {
|
||||
$rightExpr = $this->_QuantifiedExpression();
|
||||
} else {
|
||||
$rightExpr = $this->_StringExpression();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($this->_isAggregateFunction($this->_lexer->lookahead)) {
|
||||
$leftExpr = $this->_StringExpression();
|
||||
$operator = $this->_ComparisonOperator();
|
||||
if ($this->_lexer->lookahead['type'] === Lexer::T_ALL ||
|
||||
$this->_lexer->lookahead['type'] === Lexer::T_ANY ||
|
||||
$this->_lexer->lookahead['type'] === Lexer::T_SOME) {
|
||||
$rightExpr = $this->_QuantifiedExpression();
|
||||
} else {
|
||||
$rightExpr = $this->_StringExpression();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$leftExpr = $this->_ArithmeticExpression();
|
||||
$operator = $this->_ComparisonOperator();
|
||||
if ($this->_lexer->lookahead['type'] === Lexer::T_ALL ||
|
||||
$this->_lexer->lookahead['type'] === Lexer::T_ANY ||
|
||||
$this->_lexer->lookahead['type'] === Lexer::T_SOME) {
|
||||
$rightExpr = $this->_QuantifiedExpression();
|
||||
} else {
|
||||
$rightExpr = $this->_ArithmeticExpression();
|
||||
}
|
||||
}
|
||||
|
||||
return new AST\ComparisonExpression($leftExpr, $operator, $rightExpr);
|
||||
}
|
||||
|
||||
private function _isStringFunction($funcName)
|
||||
{
|
||||
return isset(self::$_STRING_FUNCTIONS[strtolower($funcName)]);
|
||||
}
|
||||
|
||||
private function _isNumericFunction($funcName)
|
||||
{
|
||||
return isset(self::$_NUMERIC_FUNCTIONS[strtolower($funcName)]);
|
||||
}
|
||||
|
||||
private function _isDatetimeFunction($funcName)
|
||||
{
|
||||
return isset(self::$_DATETIME_FUNCTIONS[strtolower($funcName)]);
|
||||
}
|
||||
|
||||
private function _peekBeyond($token)
|
||||
{
|
||||
$peek = $this->_lexer->peek();
|
||||
while ($peek['value'] != $token) {
|
||||
$peek = $this->_lexer->peek();
|
||||
}
|
||||
$peek = $this->_lexer->peek();
|
||||
$this->_lexer->resetPeek();
|
||||
return $peek;
|
||||
}
|
||||
|
||||
private function _isComparisonOperator($token)
|
||||
{
|
||||
$value = $token['value'];
|
||||
return $value == '=' || $value == '<' || $value == '<=' || $value == '<>' ||
|
||||
$value == '>' || $value == '>=' || $value == '!=';
|
||||
}
|
||||
|
||||
/**
|
||||
* ArithmeticExpression ::= SimpleArithmeticExpression | "(" Subselect ")"
|
||||
*/
|
||||
@ -1257,7 +1364,9 @@ class Parser
|
||||
if ($this->_lexer->lookahead['value'] === '(') {
|
||||
$peek = $this->_lexer->glimpse();
|
||||
if ($peek['type'] === Lexer::T_SELECT) {
|
||||
$this->match('(');
|
||||
$expr->setSubselect($this->_Subselect());
|
||||
$this->match(')');
|
||||
return $expr;
|
||||
}
|
||||
}
|
||||
@ -1526,7 +1635,7 @@ class Parser
|
||||
case Lexer::T_IDENTIFIER:
|
||||
$peek = $this->_lexer->glimpse();
|
||||
if ($peek['value'] == '(') {
|
||||
return $this->_FunctionsReturningStrings();
|
||||
return $this->_FunctionsReturningNumerics();
|
||||
}
|
||||
return $this->_StateFieldPathExpression();
|
||||
case Lexer::T_INPUT_PARAMETER:
|
||||
@ -1548,7 +1657,7 @@ class Parser
|
||||
$this->syntaxError();
|
||||
}
|
||||
}
|
||||
throw \Doctrine\Common\DoctrineException::updateMe("Not yet implemented2.");
|
||||
throw DoctrineException::updateMe("Not yet implemented2.");
|
||||
//TODO...
|
||||
}
|
||||
|
||||
@ -1562,42 +1671,51 @@ class Parser
|
||||
*/
|
||||
private function _FunctionsReturningStrings()
|
||||
{
|
||||
switch (strtoupper($this->_lexer->lookahead['value'])) {
|
||||
case 'CONCAT':
|
||||
|
||||
break;
|
||||
case 'SUBSTRING':
|
||||
|
||||
break;
|
||||
case 'TRIM':
|
||||
//TODO: This is not complete! See BNF
|
||||
$this->match($this->_lexer->lookahead['value']);
|
||||
$this->match('(');
|
||||
$func = $this->_StringPrimary();
|
||||
$this->match(')');
|
||||
return $func;
|
||||
case 'LOWER':
|
||||
|
||||
break;
|
||||
case 'UPPER':
|
||||
|
||||
default:
|
||||
$this->syntaxError('CONCAT, SUBSTRING, TRIM or UPPER');
|
||||
}
|
||||
$funcNameLower = strtolower($this->_lexer->lookahead['value']);
|
||||
$funcClass = self::$_STRING_FUNCTIONS[$funcNameLower];
|
||||
$function = new $funcClass($funcNameLower);
|
||||
$function->parse($this);
|
||||
return $function;
|
||||
}
|
||||
|
||||
/**
|
||||
* PortableFunctionsReturningNumerics ::=
|
||||
* "LENGTH" "(" StringPrimary ")" |
|
||||
* "LOCATE" "(" StringPrimary "," StringPrimary ["," SimpleArithmeticExpression]")" |
|
||||
* "ABS" "(" SimpleArithmeticExpression ")" |
|
||||
* "SQRT" "(" SimpleArithmeticExpression ")" |
|
||||
* "MOD" "(" SimpleArithmeticExpression "," SimpleArithmeticExpression ")" |
|
||||
* "SIZE" "(" CollectionValuedPathExpression ")"
|
||||
*/
|
||||
private function _FunctionsReturningNumerics()
|
||||
{
|
||||
$funcNameLower = strtolower($this->_lexer->lookahead['value']);
|
||||
$funcClass = self::$_NUMERIC_FUNCTIONS[$funcNameLower];
|
||||
$function = new $funcClass($funcNameLower);
|
||||
$function->parse($this);
|
||||
return $function;
|
||||
}
|
||||
|
||||
/**
|
||||
* PortableFunctionsReturningDateTime ::= "CURRENT_DATE" | "CURRENT_TIME" | "CURRENT_TIMESTAMP"
|
||||
*/
|
||||
public function _FunctionsReturningDatetime()
|
||||
{
|
||||
$funcNameLower = strtolower($this->_lexer->lookahead['value']);
|
||||
$funcClass = self::$_DATETIME_FUNCTIONS[$funcNameLower];
|
||||
$function = new $funcClass($funcNameLower);
|
||||
$function->parse($this);
|
||||
return $function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given token type indicates an aggregate function.
|
||||
*/
|
||||
private function _isAggregateFunction($tokenType)
|
||||
{
|
||||
switch ($tokenType) {
|
||||
case Lexer::T_AVG:
|
||||
case Lexer::T_MIN:
|
||||
case Lexer::T_MAX:
|
||||
case Lexer::T_SUM:
|
||||
case Lexer::T_COUNT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return $tokenType == Lexer::T_AVG || $tokenType == Lexer::T_MIN ||
|
||||
$tokenType == Lexer::T_MAX || $tokenType == Lexer::T_SUM ||
|
||||
$tokenType == Lexer::T_COUNT;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1674,7 +1792,10 @@ class Parser
|
||||
if ($this->_lexer->lookahead['value'] === '(') {
|
||||
$peek = $this->_lexer->glimpse();
|
||||
if ($peek['type'] === Lexer::T_SELECT) {
|
||||
return $this->_Subselect();
|
||||
$this->match('(');
|
||||
$expr = $this->_Subselect();
|
||||
$this->match(')');
|
||||
return $expr;
|
||||
}
|
||||
}
|
||||
return $this->_StringPrimary();
|
||||
@ -1683,7 +1804,7 @@ class Parser
|
||||
/**
|
||||
* StringPrimary ::= StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression
|
||||
*/
|
||||
private function _StringPrimary()
|
||||
public function _StringPrimary()
|
||||
{
|
||||
if ($this->_lexer->lookahead['type'] === Lexer::T_IDENTIFIER) {
|
||||
$peek = $this->_lexer->glimpse();
|
||||
@ -1704,4 +1825,19 @@ class Parser
|
||||
$this->syntaxError('StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression');
|
||||
}
|
||||
}
|
||||
|
||||
public static function registerStringFunction($name, $class)
|
||||
{
|
||||
self::$_STRING_FUNCTIONS[$name] = $class;
|
||||
}
|
||||
|
||||
public static function registerNumericFunction($name, $class)
|
||||
{
|
||||
self::$_NUMERIC_FUNCTIONS[$name] = $class;
|
||||
}
|
||||
|
||||
public static function registerDatetimeFunction($name, $class)
|
||||
{
|
||||
self::$_DATETIME_FUNCTIONS[$name] = $class;
|
||||
}
|
||||
}
|
@ -78,7 +78,7 @@ class SqlWalker
|
||||
public function walkSelectClause($selectClause)
|
||||
{
|
||||
return 'SELECT ' . (($selectClause->isDistinct()) ? 'DISTINCT ' : '')
|
||||
. implode(', ', array_map(array(&$this, 'walkSelectExpression'),
|
||||
. implode(', ', array_map(array($this, 'walkSelectExpression'),
|
||||
$selectClause->getSelectExpressions()));
|
||||
}
|
||||
|
||||
@ -98,6 +98,11 @@ class SqlWalker
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function walkFunction($function)
|
||||
{
|
||||
return $function->getSql($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks down a JoinVariableDeclaration AST node and creates the corresponding SQL.
|
||||
*
|
||||
@ -108,8 +113,7 @@ class SqlWalker
|
||||
{
|
||||
$join = $joinVarDecl->getJoin();
|
||||
$joinType = $join->getJoinType();
|
||||
if ($joinType == AST\Join::JOIN_TYPE_LEFT ||
|
||||
$joinType == AST\Join::JOIN_TYPE_LEFTOUTER) {
|
||||
if ($joinType == AST\Join::JOIN_TYPE_LEFT || $joinType == AST\Join::JOIN_TYPE_LEFTOUTER) {
|
||||
$sql = ' LEFT JOIN ';
|
||||
} else {
|
||||
$sql = ' INNER JOIN ';
|
||||
@ -177,9 +181,9 @@ class SqlWalker
|
||||
$sql .= $sqlTableAlias . '.' . $class->getColumnName($fieldName) .
|
||||
' AS ' . $sqlTableAlias . '__' . $class->getColumnName($fieldName);
|
||||
} else if ($pathExpression->isSimpleStateFieldAssociationPathExpression()) {
|
||||
\Doctrine\Common\DoctrineException::updateMe("Not yet implemented.");
|
||||
throw DoctrineException::updateMe("Not yet implemented.");
|
||||
} else {
|
||||
\Doctrine\Common\DoctrineException::updateMe("Encountered invalid PathExpression during SQL construction.");
|
||||
throw DoctrineException::updateMe("Encountered invalid PathExpression during SQL construction.");
|
||||
}
|
||||
}
|
||||
else if ($selectExpression->getExpression() instanceof AST\AggregateExpression) {
|
||||
@ -355,9 +359,16 @@ class SqlWalker
|
||||
. ' = ';
|
||||
|
||||
$newValue = $updateItem->getNewValue();
|
||||
if ($newValue instanceof AST\InputParameter) {
|
||||
$sql .= $newValue->isNamed() ? ':' . $newValue->getName() : '?';
|
||||
} // TODO: else if ...
|
||||
|
||||
if ($newValue instanceof AST\Node) {
|
||||
$sql .= $newValue->dispatch($this);
|
||||
} else if (is_string($newValue)) {
|
||||
if (strcasecmp($newValue, 'NULL') === 0) {
|
||||
$sql .= 'NULL';
|
||||
} else {
|
||||
$sql .= $newValue; //TODO: quote()
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
@ -366,14 +377,14 @@ class SqlWalker
|
||||
{
|
||||
$sql = ' WHERE ';
|
||||
$condExpr = $whereClause->getConditionalExpression();
|
||||
$sql .= implode(' OR ', array_map(array(&$this, 'walkConditionalTerm'),
|
||||
$sql .= implode(' OR ', array_map(array($this, 'walkConditionalTerm'),
|
||||
$condExpr->getConditionalTerms()));
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function walkConditionalTerm($condTerm)
|
||||
{
|
||||
return implode(' AND ', array_map(array(&$this, 'walkConditionalFactor'),
|
||||
return implode(' AND ', array_map(array($this, 'walkConditionalFactor'),
|
||||
$condTerm->getConditionalFactors()));
|
||||
}
|
||||
|
||||
@ -383,37 +394,30 @@ class SqlWalker
|
||||
if ($factor->isNot()) $sql .= 'NOT ';
|
||||
$primary = $factor->getConditionalPrimary();
|
||||
if ($primary->isSimpleConditionalExpression()) {
|
||||
$simpleCond = $primary->getSimpleConditionalExpression();
|
||||
if ($simpleCond instanceof AST\ComparisonExpression) {
|
||||
$sql .= $this->walkComparisonExpression($simpleCond);
|
||||
}
|
||||
else if ($simpleCond instanceof AST\LikeExpression) {
|
||||
$sql .= $this->walkLikeExpression($simpleCond);
|
||||
}
|
||||
else if ($simpleCond instanceof AST\BetweenExpression) {
|
||||
$sql .= $this->walkBetweenExpression($simpleCond);
|
||||
}
|
||||
else if ($simpleCond instanceof AST\InExpression) {
|
||||
$sql .= $this->walkInExpression($simpleCond);
|
||||
} else if ($simpleCond instanceof AST\NullComparisonExpression) {
|
||||
$sql .= $this->walkNullComparisonExpression($simpleCond);
|
||||
}
|
||||
// else if ...
|
||||
$sql .= $primary->getSimpleConditionalExpression()->dispatch($this);
|
||||
} else if ($primary->isConditionalExpression()) {
|
||||
$sql .= '(' . implode(' OR ', array_map(array(&$this, 'walkConditionalTerm'),
|
||||
$sql .= '(' . implode(' OR ', array_map(array($this, 'walkConditionalTerm'),
|
||||
$primary->getConditionalExpression()->getConditionalTerms())) . ')';
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function walkExistsExpression($existsExpr)
|
||||
{
|
||||
$sql = '';
|
||||
if ($existsExpr->isNot()) $sql .= ' NOT';
|
||||
$sql .= ' EXISTS (' . $this->walkSubselect($existsExpr->getSubselect()) . ')';
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function walkNullComparisonExpression($nullCompExpr)
|
||||
{
|
||||
$sql = '';
|
||||
if ($nullCompExpr->getExpression() instanceof AST\InputParameter) {
|
||||
$inputParam = $nullCompExpr->getExpression();
|
||||
$sql .= ' ' . ($inputParam->isNamed() ? ':' . $inputParam->getName() : '?');
|
||||
$innerExpr = $nullCompExpr->getExpression();
|
||||
if ($innerExpr instanceof AST\InputParameter) {
|
||||
$sql .= ' ' . ($innerExpr->isNamed() ? ':' . $innerExpr->getName() : '?');
|
||||
} else {
|
||||
$sql .= $this->walkPathExpression($nullCompExpr->getExpression());
|
||||
$sql .= $this->walkPathExpression($innerExpr);
|
||||
}
|
||||
$sql .= ' IS' . ($nullCompExpr->isNot() ? ' NOT' : '') . ' NULL';
|
||||
return $sql;
|
||||
@ -438,7 +442,7 @@ class SqlWalker
|
||||
if ($literal instanceof AST\InputParameter) {
|
||||
return ($literal->isNamed() ? ':' . $literal->getName() : '?');
|
||||
} else {
|
||||
return $literal;
|
||||
return $literal; //TODO: quote() ?
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,11 +459,12 @@ class SqlWalker
|
||||
{
|
||||
$sql = '';
|
||||
$stringExpr = $likeExpr->getStringExpression();
|
||||
if ($stringExpr instanceof AST\StateFieldPathExpression) {
|
||||
$sql .= $this->walkPathExpression($stringExpr);
|
||||
} //TODO else...
|
||||
|
||||
$sql .= $stringExpr->dispatch($this);
|
||||
|
||||
if ($likeExpr->isNot()) $sql .= ' NOT';
|
||||
$sql .= ' LIKE ';
|
||||
|
||||
if ($likeExpr->getStringPattern() instanceof AST\InputParameter) {
|
||||
$inputParam = $likeExpr->getStringPattern();
|
||||
$sql .= $inputParam->isNamed() ? ':' . $inputParam->getName() : '?';
|
||||
@ -472,19 +477,39 @@ class SqlWalker
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function walkStateFieldPathExpression($stateFieldPathExpression)
|
||||
{
|
||||
return $this->walkPathExpression($stateFieldPathExpression);
|
||||
}
|
||||
|
||||
public function walkComparisonExpression($compExpr)
|
||||
{
|
||||
$sql = '';
|
||||
if ($compExpr->getLeftExpression() instanceof AST\ArithmeticExpression) {
|
||||
$sql .= $this->walkArithmeticExpression($compExpr->getLeftExpression());
|
||||
} // else...
|
||||
$leftExpr = $compExpr->getLeftExpression();
|
||||
$rightExpr = $compExpr->getRightExpression();
|
||||
|
||||
if ($leftExpr instanceof AST\Node) {
|
||||
$sql .= $leftExpr->dispatch($this);
|
||||
} else {
|
||||
$sql .= $leftExpr; //TODO: quote()
|
||||
}
|
||||
|
||||
$sql .= ' ' . $compExpr->getOperator() . ' ';
|
||||
if ($compExpr->getRightExpression() instanceof AST\ArithmeticExpression) {
|
||||
$sql .= $this->walkArithmeticExpression($compExpr->getRightExpression());
|
||||
} // else...
|
||||
|
||||
if ($rightExpr instanceof AST\Node) {
|
||||
$sql .= $rightExpr->dispatch($this);
|
||||
} else {
|
||||
$sql .= $rightExpr; //TODO: quote()
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function walkInputParameter($inputParam)
|
||||
{
|
||||
return $inputParam->isNamed() ? ':' . $inputParam->getName() : '?';
|
||||
}
|
||||
|
||||
public function walkArithmeticExpression($arithmeticExpr)
|
||||
{
|
||||
$sql = '';
|
||||
@ -501,40 +526,43 @@ class SqlWalker
|
||||
public function walkArithmeticTerm($term)
|
||||
{
|
||||
if (is_string($term)) return $term;
|
||||
return implode(' ', array_map(array(&$this, 'walkArithmeticFactor'),
|
||||
|
||||
return implode(' ', array_map(array($this, 'walkArithmeticFactor'),
|
||||
$term->getArithmeticFactors()));
|
||||
}
|
||||
|
||||
public function walkStringPrimary($stringPrimary)
|
||||
{
|
||||
if (is_string($stringPrimary)) {
|
||||
return $stringPrimary;
|
||||
} else {
|
||||
return $stringPrimary->dispatch($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function walkArithmeticFactor($factor)
|
||||
{
|
||||
if (is_string($factor)) return $factor;
|
||||
|
||||
$sql = '';
|
||||
$primary = $factor->getArithmeticPrimary();
|
||||
if (is_numeric($primary)) {
|
||||
$sql .= $primary;
|
||||
$sql .= $primary; //TODO: quote() ?
|
||||
} else if (is_string($primary)) {
|
||||
//TODO: quote string according to platform
|
||||
$sql .= $primary;
|
||||
} else if ($primary instanceof AST\StateFieldPathExpression) {
|
||||
$sql .= $this->walkPathExpression($primary);
|
||||
} else if ($primary instanceof AST\InputParameter) {
|
||||
if ($primary->isNamed()) {
|
||||
$sql .= ':' . $primary->getName();
|
||||
} else {
|
||||
$sql .= '?';
|
||||
}
|
||||
} else if ($primary instanceof AST\SimpleArithmeticExpression) {
|
||||
$sql .= '(' . $this->walkSimpleArithmeticExpression($primary) . ')';
|
||||
} else if ($primary instanceof AST\Node) {
|
||||
$sql .= $primary->dispatch($this);
|
||||
}
|
||||
|
||||
// else...
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function walkSimpleArithmeticExpression($simpleArithmeticExpr)
|
||||
{
|
||||
return implode(' ', array_map(array(&$this, 'walkArithmeticTerm'),
|
||||
return implode(' ', array_map(array($this, 'walkArithmeticTerm'),
|
||||
$simpleArithmeticExpr->getArithmeticTerms()));
|
||||
}
|
||||
|
||||
@ -558,9 +586,9 @@ class SqlWalker
|
||||
$sqlTableAlias = $this->_dqlToSqlAliasMap[$dqlAlias];
|
||||
$sql .= $sqlTableAlias . '.' . $class->getColumnName($fieldName);
|
||||
} else if ($pathExpr->isSimpleStateFieldAssociationPathExpression()) {
|
||||
throw \Doctrine\Common\DoctrineException::updateMe("Not yet implemented.");
|
||||
throw DoctrineException::updateMe("Not yet implemented.");
|
||||
} else {
|
||||
throw \Doctrine\Common\DoctrineException::updateMe("Encountered invalid PathExpression during SQL construction.");
|
||||
throw DoctrineException::updateMe("Encountered invalid PathExpression during SQL construction.");
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
|
||||
$query = $this->_em->createQuery($dql);
|
||||
$query->setDql($dql);
|
||||
$parserResult = $query->parse();
|
||||
|
||||
$this->fail('No syntax errors were detected, when syntax errors were expected');
|
||||
} catch (\Exception $e) {
|
||||
//echo $e->getMessage() . PHP_EOL;
|
||||
@ -90,7 +89,7 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
|
||||
|
||||
public function testFunctionalExpressionsSupportedInWherePart()
|
||||
{
|
||||
$this->assertValidDql("SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE TRIM(u.name) = 'someone'");
|
||||
//$this->assertValidDql("SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE TRIM(u.name) = 'someone'");
|
||||
}
|
||||
|
||||
public function testArithmeticExpressionsSupportedInWherePart()
|
||||
|
@ -157,6 +157,14 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testTrimFunction()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT u.name FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE TRIM(TRAILING ' ' FROM u.name) = 'someone'",
|
||||
"SELECT c0.name AS c0__name FROM cms_users c0 WHERE TRIM(TRAILING ' ' FROM c0.name) = 'someone'"
|
||||
);
|
||||
}
|
||||
|
||||
/*public function testFunctionalExpressionsSupportedInWherePart()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
|
@ -62,7 +62,6 @@ class UpdateSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
'UPDATE Doctrine\Tests\Models\CMS\CmsUser u SET u.name = ?1',
|
||||
'UPDATE cms_users c0 SET c0.name = ?'
|
||||
);
|
||||
|
||||
$this->assertSqlGeneration(
|
||||
'UPDATE Doctrine\Tests\Models\CMS\CmsUser u SET u.name = ?1, u.username = ?2',
|
||||
'UPDATE cms_users c0 SET c0.name = ?, c0.username = ?'
|
||||
|
Loading…
Reference in New Issue
Block a user