More DQL parser work. First basic WHERE conditions. Changed scanner according to new positional parameter syntax (?<number>)
This commit is contained in:
parent
663a7415f8
commit
3f60b8b5b5
49
lib/Doctrine/ORM/Query/AST/ArithmeticExpression.php
Normal file
49
lib/Doctrine/ORM/Query/AST/ArithmeticExpression.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ArithmeticExpression ::= SimpleArithmeticExpression | "(" Subselect ")"
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class Doctrine_ORM_Query_AST_ArithmeticExpression extends Doctrine_ORM_Query_AST
|
||||
{
|
||||
private $_simpleArithmeticExpression;
|
||||
private $_subselect;
|
||||
|
||||
public function setSimpleArithmeticExpression($simpleArithmeticExpr)
|
||||
{
|
||||
if ($this->_subselect) throw new Doctrine_Exception;
|
||||
$this->_simpleArithmeticExpression = $simpleArithmeticExpr;
|
||||
}
|
||||
|
||||
public function setSubselect($subselect)
|
||||
{
|
||||
if ($this->_simpleArithmeticExpression) throw new Doctrine_Exception;
|
||||
$this->_subselect = $subselect;
|
||||
}
|
||||
|
||||
public function getSimpleArithmeticExpression()
|
||||
{
|
||||
return $this->_simpleArithmeticExpression;
|
||||
}
|
||||
|
||||
public function getSubselect()
|
||||
{
|
||||
return $this->_subselect;
|
||||
}
|
||||
|
||||
public function isSimpleArithmeticExpression()
|
||||
{
|
||||
return (bool)$this->_simpleArithmeticExpression;
|
||||
}
|
||||
|
||||
public function isSubselect()
|
||||
{
|
||||
return (bool)$this->_subselect;
|
||||
}
|
||||
}
|
||||
|
40
lib/Doctrine/ORM/Query/AST/ArithmeticFactor.php
Normal file
40
lib/Doctrine/ORM/Query/AST/ArithmeticFactor.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ArithmeticFactor ::= [("+" | "-")] ArithmeticPrimary
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class Doctrine_ORM_Query_AST_ArithmeticFactor extends Doctrine_ORM_Query_AST
|
||||
{
|
||||
private $_arithmeticPrimary;
|
||||
private $_pSigned;
|
||||
private $_nSigned;
|
||||
|
||||
public function __construct($arithmeticPrimary, $pSigned = false, $nSigned = false)
|
||||
{
|
||||
$this->_arithmeticPrimary = $arithmeticPrimary;
|
||||
$this->_pSigned = $pSigned;
|
||||
$this->_nSigned = $nSigned;
|
||||
}
|
||||
|
||||
public function getArithmeticPrimary()
|
||||
{
|
||||
return $this->_arithmeticPrimary;
|
||||
}
|
||||
|
||||
public function isPositiveSigned()
|
||||
{
|
||||
return $this->_pSigned;
|
||||
}
|
||||
|
||||
public function isNegativeSigned()
|
||||
{
|
||||
return $this->_nSigned;
|
||||
}
|
||||
}
|
||||
|
26
lib/Doctrine/ORM/Query/AST/ArithmeticTerm.php
Normal file
26
lib/Doctrine/ORM/Query/AST/ArithmeticTerm.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ArithmeticTerm ::= ArithmeticFactor {("*" | "/") ArithmeticFactor}*
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class Doctrine_ORM_Query_AST_ArithmeticTerm extends Doctrine_ORM_Query_AST
|
||||
{
|
||||
private $_factors;
|
||||
|
||||
public function __construct(array $arithmeticFactors)
|
||||
{
|
||||
$this->_factors = $arithmeticFactors;
|
||||
}
|
||||
|
||||
public function getArithmeticFactors()
|
||||
{
|
||||
return $this->_factors;
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,41 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Description of ComparisonExpression
|
||||
* ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression ) |
|
||||
* StringExpression ComparisonOperator (StringExpression | QuantifiedExpression) |
|
||||
* BooleanExpression ("=" | "<>" | "!=") (BooleanExpression | QuantifiedExpression) |
|
||||
* EnumExpression ("=" | "<>" | "!=") (EnumExpression | QuantifiedExpression) |
|
||||
* DatetimeExpression ComparisonOperator (DatetimeExpression | QuantifiedExpression) |
|
||||
* EntityExpression ("=" | "<>") (EntityExpression | QuantifiedExpression)
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class Doctrine_ORM_Query_AST_ComparisonExpression extends Doctrine_ORM_Query_AST
|
||||
{
|
||||
|
||||
private $_leftExpr;
|
||||
private $_rightExpr;
|
||||
private $_operator;
|
||||
|
||||
public function __construct($leftExpr, $operator, $rightExpr)
|
||||
{
|
||||
$this->_leftExpr = $leftExpr;
|
||||
$this->_rightExpr = $rightExpr;
|
||||
$this->_operator = $operator;
|
||||
}
|
||||
|
||||
public function getLeftExpression()
|
||||
{
|
||||
return $this->_leftExpr;
|
||||
}
|
||||
|
||||
public function getRightExpression()
|
||||
{
|
||||
return $this->_rightExpr;
|
||||
}
|
||||
|
||||
public function getOperator()
|
||||
{
|
||||
return $this->_operator;
|
||||
}
|
||||
}
|
||||
|
||||
|
37
lib/Doctrine/ORM/Query/AST/ComparisonOperator.php
Normal file
37
lib/Doctrine/ORM/Query/AST/ComparisonOperator.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?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.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ComparisonOperator = "=" | "<" | "<=" | "<>" | ">" | ">=" | "!="
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @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
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_ORM_Query_AST_ComparisonOperator extends Doctrine_ORM_Query_AST
|
||||
{
|
||||
|
||||
}
|
@ -20,7 +20,7 @@ class Doctrine_ORM_Query_AST_ConditionalExpression extends Doctrine_ORM_Query_AS
|
||||
|
||||
public function getConditionalTerms()
|
||||
{
|
||||
return $this->_conditionalTerm;
|
||||
return $this->_conditionalTerms;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,5 +33,15 @@ class Doctrine_ORM_Query_AST_ConditionalPrimary extends Doctrine_ORM_Query_AST
|
||||
{
|
||||
return $this->_conditionalExpression;
|
||||
}
|
||||
|
||||
public function isSimpleConditionalExpression()
|
||||
{
|
||||
return (bool)$this->_simpleConditionalExpression;
|
||||
}
|
||||
|
||||
public function isConditionalExpression()
|
||||
{
|
||||
return (bool)$this->_conditionalExpression;
|
||||
}
|
||||
}
|
||||
|
||||
|
49
lib/Doctrine/ORM/Query/AST/InputParameter.php
Normal file
49
lib/Doctrine/ORM/Query/AST/InputParameter.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Description of InputParameter
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class Doctrine_ORM_Query_AST_InputParameter extends Doctrine_ORM_Query_AST
|
||||
{
|
||||
private $_isNamed;
|
||||
private $_position;
|
||||
private $_name;
|
||||
|
||||
public function __construct($value)
|
||||
{
|
||||
$param = substr($value, 1);
|
||||
$this->_isNamed = ! is_numeric($param);
|
||||
if ($this->_isNamed) {
|
||||
$this->_name = $param;
|
||||
} else {
|
||||
$this->_position = $param;
|
||||
}
|
||||
}
|
||||
|
||||
public function isNamed()
|
||||
{
|
||||
return $this->_isNamed;
|
||||
}
|
||||
|
||||
public function isPositional()
|
||||
{
|
||||
return ! $this->_isNamed;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->_name;
|
||||
}
|
||||
|
||||
public function getPosition()
|
||||
{
|
||||
return $this->_position;
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ class Doctrine_ORM_Query_AST_PathExpression
|
||||
private $_isSimpleStateFieldAssociationPathExpression = false;
|
||||
private $_embeddedClassFields = array();
|
||||
private $_singleValuedAssociationFields = array();
|
||||
private $_collectionValuedAssociationFields = array();
|
||||
|
||||
public function __construct(array $parts)
|
||||
{
|
||||
@ -61,6 +62,11 @@ class Doctrine_ORM_Query_AST_PathExpression
|
||||
return isset($this->_singleValuedAssociationFields[$part]);
|
||||
}
|
||||
|
||||
public function isPartCollectionValuedAssociationField($part)
|
||||
{
|
||||
return isset($this->_collectionValuedAssociationFields[$part]);
|
||||
}
|
||||
|
||||
/* Setters to attach semantical information during semantical analysis. */
|
||||
|
||||
public function setIsSimpleStateFieldPathExpression($bool)
|
||||
@ -82,5 +88,10 @@ class Doctrine_ORM_Query_AST_PathExpression
|
||||
{
|
||||
$this->_singleValuedAssociationFields[$part] = true;
|
||||
}
|
||||
|
||||
public function setIsCollectionValuedAssociationPart($part)
|
||||
{
|
||||
$this->_collectionValuedAssociationFields[$part] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
26
lib/Doctrine/ORM/Query/AST/SimpleArithmeticExpression.php
Normal file
26
lib/Doctrine/ORM/Query/AST/SimpleArithmeticExpression.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SimpleArithmeticExpression ::= ArithmeticTerm {("+" | "-") ArithmeticTerm}*
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class Doctrine_ORM_Query_AST_SimpleArithmeticExpression extends Doctrine_ORM_Query_AST
|
||||
{
|
||||
private $_terms;
|
||||
|
||||
public function __construct(array $arithmeticTerms)
|
||||
{
|
||||
$this->_terms = $arithmeticTerms;
|
||||
}
|
||||
|
||||
public function getArithmeticTerms()
|
||||
{
|
||||
return $this->_terms;
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SimpleConditionalExpression ::= ExistsExpression |
|
||||
* (SimpleStateFieldPathExpression (ComparisonExpression | BetweenExpression | LikeExpression |
|
||||
* InExpression | NullComparisonExpression)) |
|
||||
* (CollectionValuedPathExpression EmptyCollectionComparisonExpression) |
|
||||
* (EntityExpression CollectionMemberExpression)
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class Doctrine_ORM_Query_AST_SimpleConditionalExpression extends Doctrine_ORM_Query_AST
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -841,6 +841,55 @@ class Doctrine_ORM_Query_Parser
|
||||
return new Doctrine_ORM_Query_AST_SimpleStateFieldPathExpression($identificationVariable, $simpleStateField);
|
||||
}
|
||||
|
||||
/**
|
||||
* StateFieldPathExpression ::= SimpleStateFieldPathExpression | SimpleStateFieldAssociationPathExpression
|
||||
*/
|
||||
private function _StateFieldPathExpression()
|
||||
{
|
||||
$parts = array();
|
||||
$stateFieldSeen = false;
|
||||
$assocSeen = false;
|
||||
|
||||
$identificationVariable = $this->_IdentificationVariable();
|
||||
if ( ! $this->_parserResult->hasQueryComponent($identificationVariable)) {
|
||||
$this->syntaxError("Identification variable.");
|
||||
}
|
||||
$qComp = $this->_parserResult->getQueryComponent($identificationVariable);
|
||||
$parts[] = $identificationVariable;
|
||||
|
||||
$class = $qComp['metadata'];
|
||||
|
||||
if ( ! $this->_isNextToken('.')) {
|
||||
$this->syntaxError();
|
||||
}
|
||||
|
||||
while ($this->_isNextToken('.')) {
|
||||
if ($stateFieldSeen) $this->syntaxError();
|
||||
$this->match('.');
|
||||
$part = $this->_IdentificationVariable();
|
||||
if ($class->hasField($part)) {
|
||||
$stateFieldSeen = true;
|
||||
} else if ($class->hasAssociation($part)) {
|
||||
$assoc = $class->getAssociationMapping($part);
|
||||
$class = $this->_em->getClassMetadata($assoc->getTargetEntityName());
|
||||
$assocSeen = true;
|
||||
} else {
|
||||
$this->syntaxError();
|
||||
}
|
||||
$parts[] = $part;
|
||||
}
|
||||
|
||||
$pathExpr = new Doctrine_ORM_Query_AST_PathExpression($parts);
|
||||
|
||||
if ($assocSeen) {
|
||||
$pathExpr->setIsSimpleStateFieldAssociationPathExpression(true);
|
||||
} else {
|
||||
$pathExpr->setIsSimpleStateFieldPathExpression(true);
|
||||
}
|
||||
|
||||
return $pathExpr;
|
||||
}
|
||||
|
||||
/**
|
||||
* AggregateExpression ::=
|
||||
* ("AVG" | "MAX" | "MIN" | "SUM") "(" ["DISTINCT"] StateFieldPathExpression ")" |
|
||||
@ -963,52 +1012,6 @@ class Doctrine_ORM_Query_Parser
|
||||
* EmptyCollectionComparisonExpression | CollectionMemberExpression
|
||||
*/
|
||||
private function _SimpleConditionalExpression()
|
||||
{
|
||||
if ($this->_getExpressionType() === Doctrine_ORM_Query_Token::T_EXISTS) {
|
||||
return $this->_ExistsExpression();
|
||||
}
|
||||
|
||||
// For now... just SimpleStateFieldPathExpression
|
||||
$leftExpression = $this->_SimpleStateFieldPathExpression();
|
||||
|
||||
switch ($this->_getExpressionType()) {
|
||||
case Doctrine_ORM_Query_Token::T_NONE:
|
||||
// [TODO] Check out ticket #935 to understand what will be done with enumParams
|
||||
$rightExpression = $this->_ComparisonExpression();
|
||||
break;
|
||||
case Doctrine_ORM_Query_Token::T_BETWEEN:
|
||||
$rightExpression = $this->_BetweenExpression();
|
||||
break;
|
||||
|
||||
case Doctrine_ORM_Query_Token::T_LIKE:
|
||||
$rightExpression = $this->_LikeExpression();
|
||||
break;
|
||||
|
||||
case Doctrine_ORM_Query_Token::T_IN:
|
||||
$rightExpression = $this->_InExpression();
|
||||
break;
|
||||
|
||||
case Doctrine_ORM_Query_Token::T_IS:
|
||||
$rightExpression = $this->_NullComparisonExpression();
|
||||
break;
|
||||
|
||||
case Doctrine_ORM_Query_Token::T_ALL:
|
||||
case Doctrine_ORM_Query_Token::T_ANY:
|
||||
case Doctrine_ORM_Query_Token::T_SOME:
|
||||
$rightExpression = $this->_QuantifiedExpression();
|
||||
break;
|
||||
|
||||
default:
|
||||
$message = "BETWEEN, LIKE, IN, IS, quantified (ALL, ANY or SOME) "
|
||||
. "or comparison (=, <, <=, <>, >, >=, !=)";
|
||||
$this->syntaxError($message);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private function _getExpressionType()
|
||||
{
|
||||
if ($this->_isNextToken(Doctrine_ORM_Query_Token::T_NOT)) {
|
||||
$token = $this->_scanner->peek();
|
||||
@ -1016,11 +1019,183 @@ class Doctrine_ORM_Query_Parser
|
||||
} else {
|
||||
$token = $this->lookahead;
|
||||
}
|
||||
return $token['type'];
|
||||
if ($token['type'] === Doctrine_ORM_Query_Token::T_EXISTS) {
|
||||
return $this->_ExistsExpression();
|
||||
}
|
||||
|
||||
$stateFieldPathExpr = false;
|
||||
if ($token['type'] === Doctrine_ORM_Query_Token::T_IDENTIFIER) {
|
||||
// Peek beyond the PathExpression
|
||||
$stateFieldPathExpr = true;
|
||||
$peek = $this->_scanner->peek();
|
||||
while ($peek['value'] === '.') {
|
||||
$this->_scanner->peek();
|
||||
$peek = $this->_scanner->peek();
|
||||
}
|
||||
$this->_scanner->resetPeek();
|
||||
$token = $peek;
|
||||
}
|
||||
|
||||
if ($stateFieldPathExpr) {
|
||||
switch ($token['type']) {
|
||||
case Doctrine_ORM_Query_Token::T_BETWEEN:
|
||||
return $this->_BetweenExpression();
|
||||
case Doctrine_ORM_Query_Token::T_LIKE:
|
||||
return $this->_LikeExpression();
|
||||
case Doctrine_ORM_Query_Token::T_IN:
|
||||
return $this->_InExpression();
|
||||
case Doctrine_ORM_Query_Token::T_IS:
|
||||
return $this->_NullComparisonExpression();
|
||||
case Doctrine_ORM_Query_Token::T_NONE:
|
||||
return $this->_ComparisonExpression();
|
||||
default:
|
||||
$this->syntaxError();
|
||||
}
|
||||
} else {
|
||||
switch ($token['type']) {
|
||||
case Doctrine_ORM_Query_Token::T_INTEGER:
|
||||
// IF it turns out its a ComparisonExpression, then it MUST be ArithmeticExpression
|
||||
break;
|
||||
case Doctrine_ORM_Query_Token::T_STRING:
|
||||
// IF it turns out its a ComparisonExpression, then it MUST be StringExpression
|
||||
break;
|
||||
default:
|
||||
$this->syntaxError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SIMPLIFIED FROM BNF FOR NOW
|
||||
* ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression )
|
||||
*/
|
||||
private function _ComparisonExpression()
|
||||
{
|
||||
var_dump($this->lookahead);
|
||||
$leftExpr = $this->_ArithmeticExpression();
|
||||
$operator = $this->_ComparisonOperator();
|
||||
if ($this->lookahead['type'] === Doctrine_ORM_Query_Token::T_ALL ||
|
||||
$this->lookahead['type'] === Doctrine_ORM_Query_Token::T_ANY ||
|
||||
$this->lookahead['type'] === Doctrine_ORM_Query_Token::T_SOME) {
|
||||
$rightExpr = $this->_QuantifiedExpression();
|
||||
} else {
|
||||
$rightExpr = $this->_ArithmeticExpression();
|
||||
}
|
||||
return new Doctrine_ORM_Query_AST_ComparisonExpression($leftExpr, $operator, $rightExpr);
|
||||
}
|
||||
|
||||
/**
|
||||
* ArithmeticExpression ::= SimpleArithmeticExpression | "(" Subselect ")"
|
||||
*/
|
||||
private function _ArithmeticExpression()
|
||||
{
|
||||
$expr = new Doctrine_ORM_Query_AST_ArithmeticExpression;
|
||||
if ($this->lookahead['value'] === '(') {
|
||||
$peek = $this->_scanner->peek();
|
||||
$this->_scanner->resetPeek();
|
||||
if ($peek['type'] === Doctrine_ORM_Query_Token::T_SELECT) {
|
||||
$expr->setSubselect($this->_Subselect());
|
||||
return $expr;
|
||||
}
|
||||
}
|
||||
$expr->setSimpleArithmeticExpression($this->_SimpleArithmeticExpression());
|
||||
return $expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* SimpleArithmeticExpression ::= ArithmeticTerm {("+" | "-") ArithmeticTerm}*
|
||||
*/
|
||||
private function _SimpleArithmeticExpression()
|
||||
{
|
||||
$terms = array();
|
||||
$terms[] = $this->_ArithmeticTerm();
|
||||
while ($this->lookahead['value'] == '+' || $this->lookahead['value'] == '-') {
|
||||
$terms[] = $this->_ArithmeticTerm();
|
||||
}
|
||||
return new Doctrine_ORM_Query_AST_SimpleArithmeticExpression($terms);
|
||||
}
|
||||
|
||||
/**
|
||||
* ArithmeticTerm ::= ArithmeticFactor {("*" | "/") ArithmeticFactor}*
|
||||
*/
|
||||
private function _ArithmeticTerm()
|
||||
{
|
||||
$factors = array();
|
||||
$factors[] = $this->_ArithmeticFactor();
|
||||
while ($this->lookahead['value'] == '*' || $this->lookahead['value'] == '/') {
|
||||
$factors[] = $this->_ArithmeticFactor();
|
||||
}
|
||||
return new Doctrine_ORM_Query_AST_ArithmeticTerm($factors);
|
||||
}
|
||||
|
||||
/**
|
||||
* ArithmeticFactor ::= [("+" | "-")] ArithmeticPrimary
|
||||
*/
|
||||
private function _ArithmeticFactor()
|
||||
{
|
||||
$pSign = $nSign = false;
|
||||
if ($this->lookahead['value'] == '+') {
|
||||
$this->match('+');
|
||||
$pSign = true;
|
||||
} else if ($this->lookahead['value'] == '-') {
|
||||
$this->match('-');
|
||||
$nSign = true;
|
||||
}
|
||||
return new Doctrine_ORM_Query_AST_ArithmeticFactor($this->_ArithmeticPrimary(), $pSign, $nSign);
|
||||
}
|
||||
|
||||
/**
|
||||
* ArithmeticPrimary ::= StateFieldPathExpression | Literal | "(" SimpleArithmeticExpression ")" | Function | AggregateExpression
|
||||
*/
|
||||
private function _ArithmeticPrimary()
|
||||
{
|
||||
if ($this->lookahead['type'] === Doctrine_ORM_Query_Token::T_IDENTIFIER) {
|
||||
return $this->_StateFieldPathExpression();
|
||||
}
|
||||
if ($this->lookahead['value'] === '(') {
|
||||
return $this->_SimpleArithmeticExpression();
|
||||
}
|
||||
if ($this->lookahead['type'] === Doctrine_ORM_Query_Token::T_INPUT_PARAMETER) {
|
||||
$this->match($this->lookahead['value']);
|
||||
return new Doctrine_ORM_Query_AST_InputParameter($this->token['value']);
|
||||
}
|
||||
//TODO...
|
||||
}
|
||||
|
||||
/**
|
||||
* ComparisonOperator ::= "=" | "<" | "<=" | "<>" | ">" | ">=" | "!="
|
||||
*/
|
||||
private function _ComparisonOperator()
|
||||
{
|
||||
switch ($this->lookahead['value']) {
|
||||
case '=':
|
||||
$this->match('=');
|
||||
return '=';
|
||||
case '<':
|
||||
$this->match('<');
|
||||
$operator = '<';
|
||||
if ($this->_isNextToken('=')) {
|
||||
$this->match('=');
|
||||
$operator .= '=';
|
||||
} else if ($this->_isNextToken('>')) {
|
||||
$this->match('>');
|
||||
$operator .= '>';
|
||||
}
|
||||
return $operator;
|
||||
case '>':
|
||||
$this->match('>');
|
||||
$operator = '>';
|
||||
if ($this->_isNextToken('=')) {
|
||||
$this->match('=');
|
||||
$operator .= '=';
|
||||
}
|
||||
return $operator;
|
||||
case '!':
|
||||
$this->match('!');
|
||||
$this->match('=');
|
||||
return '<>';
|
||||
default:
|
||||
$this->_parser->syntaxError('=, <, <=, <>, >, >=, !=');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ class Doctrine_ORM_Query_Scanner
|
||||
'[a-z_][a-z0-9_]*',
|
||||
'(?:[0-9]+(?:[,\.][0-9]+)*)(?:e[+-]?[0-9]+)?',
|
||||
"'(?:[^']|'')*'",
|
||||
'\?|:[a-z]+'
|
||||
'\?[0-9]+|:[a-z]+'
|
||||
);
|
||||
$regex = '/(' . implode(')|(', $patterns) . ')|\s+|(.)/i';
|
||||
}
|
||||
|
@ -44,7 +44,9 @@ class Doctrine_ORM_Query_SqlWalker
|
||||
{
|
||||
$sql = $this->walkSelectClause($AST->getSelectClause());
|
||||
$sql .= $this->walkFromClause($AST->getFromClause());
|
||||
$sql .= $AST->getWhereClause() ? $this->walkWhereClause($AST->getWhereClause()) : '';
|
||||
$sql .= $AST->getGroupByClause() ? $this->walkGroupByClause($AST->getGroupByClause()) : '';
|
||||
|
||||
//... more clauses
|
||||
return $sql;
|
||||
}
|
||||
@ -223,6 +225,122 @@ class Doctrine_ORM_Query_SqlWalker
|
||||
|
||||
}
|
||||
|
||||
public function walkWhereClause($whereClause)
|
||||
{
|
||||
$sql = ' WHERE ';
|
||||
$condExpr = $whereClause->getConditionalExpression();
|
||||
foreach ($condExpr->getConditionalTerms() as $term) {
|
||||
$sql .= $this->walkConditionalTerm($term);
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function walkConditionalTerm($condTerm)
|
||||
{
|
||||
$sql = '';
|
||||
foreach ($condTerm->getConditionalFactors() as $factor) {
|
||||
$sql .= $this->walkConditionalFactor($factor);
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function walkConditionalFactor($factor)
|
||||
{
|
||||
$sql = '';
|
||||
if ($factor->isNot()) $sql .= ' NOT ';
|
||||
$primary = $factor->getConditionalPrimary();
|
||||
if ($primary->isSimpleConditionalExpression()) {
|
||||
$simpleCond = $primary->getSimpleConditionalExpression();
|
||||
if ($simpleCond instanceof Doctrine_ORM_Query_AST_ComparisonExpression) {
|
||||
$sql .= $this->walkComparisonExpression($simpleCond);
|
||||
}
|
||||
// else if ...
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function walkComparisonExpression($compExpr)
|
||||
{
|
||||
$sql = '';
|
||||
if ($compExpr->getLeftExpression() instanceof Doctrine_ORM_Query_AST_ArithmeticExpression) {
|
||||
$sql .= $this->walkArithmeticExpression($compExpr->getLeftExpression());
|
||||
} // else...
|
||||
$sql .= ' ' . $compExpr->getOperator() . ' ';
|
||||
if ($compExpr->getRightExpression() instanceof Doctrine_ORM_Query_AST_ArithmeticExpression) {
|
||||
$sql .= $this->walkArithmeticExpression($compExpr->getRightExpression());
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function walkArithmeticExpression($arithmeticExpr)
|
||||
{
|
||||
$sql = '';
|
||||
if ($arithmeticExpr->isSimpleArithmeticExpression()) {
|
||||
foreach ($arithmeticExpr->getSimpleArithmeticExpression()->getArithmeticTerms() as $term) {
|
||||
$sql .= $this->walkArithmeticTerm($term);
|
||||
}
|
||||
} else {
|
||||
$sql .= $this->walkSubselect($arithmeticExpr->getSubselect());
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function walkArithmeticTerm($term)
|
||||
{
|
||||
$sql = '';
|
||||
foreach ($term->getArithmeticFactors() as $factor) {
|
||||
$sql .= $this->walkArithmeticFactor($factor);
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function walkArithmeticFactor($factor)
|
||||
{
|
||||
$sql = '';
|
||||
$primary = $factor->getArithmeticPrimary();
|
||||
if ($primary instanceof Doctrine_ORM_Query_AST_PathExpression) {
|
||||
$sql .= $this->walkPathExpression($primary);
|
||||
} else if ($primary instanceof Doctrine_ORM_Query_AST_InputParameter) {
|
||||
if ($primary->isNamed()) {
|
||||
$sql .= ':' . $primary->getName();
|
||||
} else {
|
||||
$sql .= '?';
|
||||
}
|
||||
}
|
||||
|
||||
// else...
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function walkPathExpression($pathExpr)
|
||||
{
|
||||
$sql = '';
|
||||
if ($pathExpr->isSimpleStateFieldPathExpression()) {
|
||||
$parts = $pathExpr->getParts();
|
||||
$numParts = count($parts);
|
||||
$dqlAlias = $parts[0];
|
||||
$fieldName = $parts[$numParts-1];
|
||||
$qComp = $this->_parserResult->getQueryComponent($dqlAlias);
|
||||
$class = $qComp['metadata'];
|
||||
|
||||
if ($numParts > 2) {
|
||||
for ($i = 1; $i < $numParts-1; ++$i) {
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
||||
$sqlTableAlias = $this->_dqlToSqlAliasMap[$dqlAlias];
|
||||
$sql .= $sqlTableAlias . '.' . $class->getColumnName($fieldName);
|
||||
} else if ($pathExpr->isSimpleStateFieldAssociationPathExpression()) {
|
||||
throw new Doctrine_Exception("Not yet implemented.");
|
||||
} else {
|
||||
throw new Doctrine_ORM_Query_Exception("Encountered invalid PathExpression during SQL construction.");
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an SQL table alias from given table name and associates
|
||||
* it with given component alias
|
||||
|
@ -88,58 +88,11 @@ final class Doctrine_ORM_Query_Token
|
||||
const T_FALSE = 147;
|
||||
|
||||
|
||||
protected $_keywordsTable = array();
|
||||
protected $_keywordsTable;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->addKeyword(self::T_ALL, "ALL");
|
||||
$this->addKeyword(self::T_AND, "AND");
|
||||
$this->addKeyword(self::T_ANY, "ANY");
|
||||
$this->addKeyword(self::T_AS, "AS");
|
||||
$this->addKeyword(self::T_ASC, "ASC");
|
||||
$this->addKeyword(self::T_AVG, "AVG");
|
||||
$this->addKeyword(self::T_BETWEEN, "BETWEEN");
|
||||
$this->addKeyword(self::T_BY, "BY");
|
||||
$this->addKeyword(self::T_COMMA, ",");
|
||||
$this->addKeyword(self::T_COUNT, "COUNT");
|
||||
$this->addKeyword(self::T_DELETE, "DELETE");
|
||||
$this->addKeyword(self::T_DESC, "DESC");
|
||||
$this->addKeyword(self::T_DISTINCT, "DISTINCT");
|
||||
$this->addKeyword(self::T_DOT, ".");
|
||||
$this->addKeyword(self::T_ESCAPE, "ESPACE");
|
||||
$this->addKeyword(self::T_EXISTS, "EXISTS");
|
||||
$this->addKeyword(self::T_FALSE, "FALSE");
|
||||
$this->addKeyword(self::T_FROM, "FROM");
|
||||
$this->addKeyword(self::T_GROUP, "GROUP");
|
||||
$this->addKeyword(self::T_HAVING, "HAVING");
|
||||
$this->addKeyword(self::T_IN, "IN");
|
||||
$this->addKeyword(self::T_INDEX, "INDEX");
|
||||
$this->addKeyword(self::T_INNER, "INNER");
|
||||
$this->addKeyword(self::T_IS, "IS");
|
||||
$this->addKeyword(self::T_JOIN, "JOIN");
|
||||
$this->addKeyword(self::T_LEFT, "LEFT");
|
||||
$this->addKeyword(self::T_LIKE, "LIKE");
|
||||
$this->addKeyword(self::T_LIMIT, "LIMIT");
|
||||
$this->addKeyword(self::T_MAX, "MAX");
|
||||
$this->addKeyword(self::T_MIN, "MIN");
|
||||
$this->addKeyword(self::T_MOD, "MOD");
|
||||
$this->addKeyword(self::T_NOT, "NOT");
|
||||
$this->addKeyword(self::T_NULL, "NULL");
|
||||
$this->addKeyword(self::T_OFFSET, "OFFSET");
|
||||
$this->addKeyword(self::T_ON, "ON");
|
||||
$this->addKeyword(self::T_OR, "OR");
|
||||
$this->addKeyword(self::T_ORDER, "ORDER");
|
||||
$this->addKeyword(self::T_OUTER, "OUTER");
|
||||
$this->addKeyword(self::T_SELECT, "SELECT");
|
||||
$this->addKeyword(self::T_SET, "SET");
|
||||
$this->addKeyword(self::T_SIZE, "SIZE");
|
||||
$this->addKeyword(self::T_SOME, "SOME");
|
||||
$this->addKeyword(self::T_SUM, "SUM");
|
||||
$this->addKeyword(self::T_TRUE, "TRUE");
|
||||
$this->addKeyword(self::T_UPDATE, "UPDATE");
|
||||
$this->addKeyword(self::T_WHERE, "WHERE");
|
||||
$this->addKeyword(self::T_WITH, "WITH");
|
||||
}
|
||||
|
||||
|
||||
@ -151,6 +104,55 @@ final class Doctrine_ORM_Query_Token
|
||||
|
||||
public function getLiteral($token)
|
||||
{
|
||||
if ( ! $this->_keywordsTable) {
|
||||
$this->addKeyword(self::T_ALL, "ALL");
|
||||
$this->addKeyword(self::T_AND, "AND");
|
||||
$this->addKeyword(self::T_ANY, "ANY");
|
||||
$this->addKeyword(self::T_AS, "AS");
|
||||
$this->addKeyword(self::T_ASC, "ASC");
|
||||
$this->addKeyword(self::T_AVG, "AVG");
|
||||
$this->addKeyword(self::T_BETWEEN, "BETWEEN");
|
||||
$this->addKeyword(self::T_BY, "BY");
|
||||
$this->addKeyword(self::T_COMMA, ",");
|
||||
$this->addKeyword(self::T_COUNT, "COUNT");
|
||||
$this->addKeyword(self::T_DELETE, "DELETE");
|
||||
$this->addKeyword(self::T_DESC, "DESC");
|
||||
$this->addKeyword(self::T_DISTINCT, "DISTINCT");
|
||||
$this->addKeyword(self::T_DOT, ".");
|
||||
$this->addKeyword(self::T_ESCAPE, "ESPACE");
|
||||
$this->addKeyword(self::T_EXISTS, "EXISTS");
|
||||
$this->addKeyword(self::T_FALSE, "FALSE");
|
||||
$this->addKeyword(self::T_FROM, "FROM");
|
||||
$this->addKeyword(self::T_GROUP, "GROUP");
|
||||
$this->addKeyword(self::T_HAVING, "HAVING");
|
||||
$this->addKeyword(self::T_IN, "IN");
|
||||
$this->addKeyword(self::T_INDEX, "INDEX");
|
||||
$this->addKeyword(self::T_INNER, "INNER");
|
||||
$this->addKeyword(self::T_IS, "IS");
|
||||
$this->addKeyword(self::T_JOIN, "JOIN");
|
||||
$this->addKeyword(self::T_LEFT, "LEFT");
|
||||
$this->addKeyword(self::T_LIKE, "LIKE");
|
||||
$this->addKeyword(self::T_LIMIT, "LIMIT");
|
||||
$this->addKeyword(self::T_MAX, "MAX");
|
||||
$this->addKeyword(self::T_MIN, "MIN");
|
||||
$this->addKeyword(self::T_MOD, "MOD");
|
||||
$this->addKeyword(self::T_NOT, "NOT");
|
||||
$this->addKeyword(self::T_NULL, "NULL");
|
||||
$this->addKeyword(self::T_OFFSET, "OFFSET");
|
||||
$this->addKeyword(self::T_ON, "ON");
|
||||
$this->addKeyword(self::T_OR, "OR");
|
||||
$this->addKeyword(self::T_ORDER, "ORDER");
|
||||
$this->addKeyword(self::T_OUTER, "OUTER");
|
||||
$this->addKeyword(self::T_SELECT, "SELECT");
|
||||
$this->addKeyword(self::T_SET, "SET");
|
||||
$this->addKeyword(self::T_SIZE, "SIZE");
|
||||
$this->addKeyword(self::T_SOME, "SOME");
|
||||
$this->addKeyword(self::T_SUM, "SUM");
|
||||
$this->addKeyword(self::T_TRUE, "TRUE");
|
||||
$this->addKeyword(self::T_UPDATE, "UPDATE");
|
||||
$this->addKeyword(self::T_WHERE, "WHERE");
|
||||
$this->addKeyword(self::T_WITH, "WITH");
|
||||
}
|
||||
return isset($this->_keywordsTable[$token])
|
||||
? $this->_keywordsTable[$token]
|
||||
: (is_string($token) ? $token : '');
|
||||
|
@ -50,6 +50,7 @@ class Orm_Query_SelectSqlGenerationTest extends Doctrine_OrmTestCase
|
||||
parent::assertEquals($sqlToBeConfirmed, $query->getSql());
|
||||
$query->free();
|
||||
} catch (Doctrine_Exception $e) {
|
||||
echo $e->getMessage();
|
||||
echo $e->getTraceAsString(); die();
|
||||
$this->fail($e->getMessage());
|
||||
}
|
||||
@ -112,7 +113,7 @@ class Orm_Query_SelectSqlGenerationTest extends Doctrine_OrmTestCase
|
||||
public function testWhereClauseInSelect()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'select u from ForumUser u where u.id = ?',
|
||||
'select u from ForumUser u where u.id = ?1',
|
||||
'SELECT fu.id AS fu__id, fu.username AS fu__username FROM ForumUser fu WHERE fu.id = ?'
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user