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
|
* @author robo
|
||||||
*/
|
*/
|
||||||
class Doctrine_ORM_Query_AST_ComparisonExpression extends Doctrine_ORM_Query_AST
|
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()
|
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;
|
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 $_isSimpleStateFieldAssociationPathExpression = false;
|
||||||
private $_embeddedClassFields = array();
|
private $_embeddedClassFields = array();
|
||||||
private $_singleValuedAssociationFields = array();
|
private $_singleValuedAssociationFields = array();
|
||||||
|
private $_collectionValuedAssociationFields = array();
|
||||||
|
|
||||||
public function __construct(array $parts)
|
public function __construct(array $parts)
|
||||||
{
|
{
|
||||||
@ -61,6 +62,11 @@ class Doctrine_ORM_Query_AST_PathExpression
|
|||||||
return isset($this->_singleValuedAssociationFields[$part]);
|
return isset($this->_singleValuedAssociationFields[$part]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isPartCollectionValuedAssociationField($part)
|
||||||
|
{
|
||||||
|
return isset($this->_collectionValuedAssociationFields[$part]);
|
||||||
|
}
|
||||||
|
|
||||||
/* Setters to attach semantical information during semantical analysis. */
|
/* Setters to attach semantical information during semantical analysis. */
|
||||||
|
|
||||||
public function setIsSimpleStateFieldPathExpression($bool)
|
public function setIsSimpleStateFieldPathExpression($bool)
|
||||||
@ -82,5 +88,10 @@ class Doctrine_ORM_Query_AST_PathExpression
|
|||||||
{
|
{
|
||||||
$this->_singleValuedAssociationFields[$part] = true;
|
$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);
|
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 ::=
|
* AggregateExpression ::=
|
||||||
* ("AVG" | "MAX" | "MIN" | "SUM") "(" ["DISTINCT"] StateFieldPathExpression ")" |
|
* ("AVG" | "MAX" | "MIN" | "SUM") "(" ["DISTINCT"] StateFieldPathExpression ")" |
|
||||||
@ -963,52 +1012,6 @@ class Doctrine_ORM_Query_Parser
|
|||||||
* EmptyCollectionComparisonExpression | CollectionMemberExpression
|
* EmptyCollectionComparisonExpression | CollectionMemberExpression
|
||||||
*/
|
*/
|
||||||
private function _SimpleConditionalExpression()
|
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)) {
|
if ($this->_isNextToken(Doctrine_ORM_Query_Token::T_NOT)) {
|
||||||
$token = $this->_scanner->peek();
|
$token = $this->_scanner->peek();
|
||||||
@ -1016,11 +1019,183 @@ class Doctrine_ORM_Query_Parser
|
|||||||
} else {
|
} else {
|
||||||
$token = $this->lookahead;
|
$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()
|
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_]*',
|
'[a-z_][a-z0-9_]*',
|
||||||
'(?:[0-9]+(?:[,\.][0-9]+)*)(?:e[+-]?[0-9]+)?',
|
'(?:[0-9]+(?:[,\.][0-9]+)*)(?:e[+-]?[0-9]+)?',
|
||||||
"'(?:[^']|'')*'",
|
"'(?:[^']|'')*'",
|
||||||
'\?|:[a-z]+'
|
'\?[0-9]+|:[a-z]+'
|
||||||
);
|
);
|
||||||
$regex = '/(' . implode(')|(', $patterns) . ')|\s+|(.)/i';
|
$regex = '/(' . implode(')|(', $patterns) . ')|\s+|(.)/i';
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,9 @@ class Doctrine_ORM_Query_SqlWalker
|
|||||||
{
|
{
|
||||||
$sql = $this->walkSelectClause($AST->getSelectClause());
|
$sql = $this->walkSelectClause($AST->getSelectClause());
|
||||||
$sql .= $this->walkFromClause($AST->getFromClause());
|
$sql .= $this->walkFromClause($AST->getFromClause());
|
||||||
|
$sql .= $AST->getWhereClause() ? $this->walkWhereClause($AST->getWhereClause()) : '';
|
||||||
$sql .= $AST->getGroupByClause() ? $this->walkGroupByClause($AST->getGroupByClause()) : '';
|
$sql .= $AST->getGroupByClause() ? $this->walkGroupByClause($AST->getGroupByClause()) : '';
|
||||||
|
|
||||||
//... more clauses
|
//... more clauses
|
||||||
return $sql;
|
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
|
* Generates an SQL table alias from given table name and associates
|
||||||
* it with given component alias
|
* it with given component alias
|
||||||
|
@ -88,11 +88,23 @@ final class Doctrine_ORM_Query_Token
|
|||||||
const T_FALSE = 147;
|
const T_FALSE = 147;
|
||||||
|
|
||||||
|
|
||||||
protected $_keywordsTable = array();
|
protected $_keywordsTable;
|
||||||
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected function addKeyword($token, $value)
|
||||||
|
{
|
||||||
|
$this->_keywordsTable[$token] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getLiteral($token)
|
||||||
|
{
|
||||||
|
if ( ! $this->_keywordsTable) {
|
||||||
$this->addKeyword(self::T_ALL, "ALL");
|
$this->addKeyword(self::T_ALL, "ALL");
|
||||||
$this->addKeyword(self::T_AND, "AND");
|
$this->addKeyword(self::T_AND, "AND");
|
||||||
$this->addKeyword(self::T_ANY, "ANY");
|
$this->addKeyword(self::T_ANY, "ANY");
|
||||||
@ -141,16 +153,6 @@ final class Doctrine_ORM_Query_Token
|
|||||||
$this->addKeyword(self::T_WHERE, "WHERE");
|
$this->addKeyword(self::T_WHERE, "WHERE");
|
||||||
$this->addKeyword(self::T_WITH, "WITH");
|
$this->addKeyword(self::T_WITH, "WITH");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function addKeyword($token, $value)
|
|
||||||
{
|
|
||||||
$this->_keywordsTable[$token] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function getLiteral($token)
|
|
||||||
{
|
|
||||||
return isset($this->_keywordsTable[$token])
|
return isset($this->_keywordsTable[$token])
|
||||||
? $this->_keywordsTable[$token]
|
? $this->_keywordsTable[$token]
|
||||||
: (is_string($token) ? $token : '');
|
: (is_string($token) ? $token : '');
|
||||||
|
@ -50,6 +50,7 @@ class Orm_Query_SelectSqlGenerationTest extends Doctrine_OrmTestCase
|
|||||||
parent::assertEquals($sqlToBeConfirmed, $query->getSql());
|
parent::assertEquals($sqlToBeConfirmed, $query->getSql());
|
||||||
$query->free();
|
$query->free();
|
||||||
} catch (Doctrine_Exception $e) {
|
} catch (Doctrine_Exception $e) {
|
||||||
|
echo $e->getMessage();
|
||||||
echo $e->getTraceAsString(); die();
|
echo $e->getTraceAsString(); die();
|
||||||
$this->fail($e->getMessage());
|
$this->fail($e->getMessage());
|
||||||
}
|
}
|
||||||
@ -112,7 +113,7 @@ class Orm_Query_SelectSqlGenerationTest extends Doctrine_OrmTestCase
|
|||||||
public function testWhereClauseInSelect()
|
public function testWhereClauseInSelect()
|
||||||
{
|
{
|
||||||
$this->assertSqlGeneration(
|
$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 = ?'
|
'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