Fixes in unit tests.
Started refactoring in DQL parser to separate Production into Parser and AST classes. Finished first tests. Currently only 4 are active in IdentifierRecognitionTest, and only 2 are passing.
This commit is contained in:
parent
4b191a3141
commit
ad4db34a87
@ -104,7 +104,7 @@ class Doctrine_ConnectionFactory
|
||||
|
||||
// driver
|
||||
if ( isset($params['driver']) && ! isset($this->_drivers[$params['driver']])) {
|
||||
throw Doctrine_ConnectionFactory_Exception::unknownDriver($driverName);
|
||||
throw Doctrine_ConnectionFactory_Exception::unknownDriver($params['driver']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
49
lib/Doctrine/ConnectionFactory/Exception.php
Normal file
49
lib/Doctrine/ConnectionFactory/Exception.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id: Exception.php 1080 2007-02-10 18:17:08Z romanb $
|
||||
*
|
||||
* 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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Doctrine_ConnectionFactory_Exception
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Hydrate
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.phpdoctrine.org
|
||||
* @since 1.0
|
||||
* @version $Revision: 1080 $
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
*/
|
||||
class Doctrine_ConnectionFactory_Exception extends Doctrine_Exception
|
||||
{
|
||||
public static function invalidPDOInstance()
|
||||
{
|
||||
return new self("Invalid PDO instance provided on connection creation.");
|
||||
}
|
||||
|
||||
public static function driverRequired()
|
||||
{
|
||||
return new self("Please provide a driver or a driverClass to be able to start a Connection.");
|
||||
}
|
||||
|
||||
public static function unknownDriver($driver)
|
||||
{
|
||||
return new self("Unknown Connection driver '$driver'.");
|
||||
}
|
||||
}
|
@ -944,7 +944,7 @@ abstract class Doctrine_DatabasePlatform
|
||||
*
|
||||
* @todo Throw exception by default?
|
||||
*/
|
||||
public function getDropIndexSql($index)
|
||||
public function getDropIndexSql($index, $name)
|
||||
{
|
||||
return 'DROP INDEX ' . $index;
|
||||
}
|
||||
@ -982,7 +982,7 @@ abstract class Doctrine_DatabasePlatform
|
||||
*
|
||||
* @todo Throw exception by default?
|
||||
*/
|
||||
public function getCreateTableSql($table, array $columns, array $options)
|
||||
public function getCreateTableSql($table, array $columns, array $options = array())
|
||||
{
|
||||
if ( ! $table) {
|
||||
throw new Doctrine_Export_Exception('no valid table name specified');
|
||||
|
@ -347,10 +347,10 @@ class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract
|
||||
if ($this->_isIgnoredName($key)) continue;
|
||||
|
||||
// Cache general information like the column name <-> field name mapping
|
||||
$e = explode(Doctrine_Query_Production::SQLALIAS_SEPARATOR, $key);
|
||||
$e = explode(Doctrine_Query_ParserRule::SQLALIAS_SEPARATOR, $key);
|
||||
$columnName = array_pop($e);
|
||||
$cache[$key]['dqlAlias'] = $this->_tableAliases[
|
||||
implode(Doctrine_Query_Production::SQLALIAS_SEPARATOR, $e)
|
||||
implode(Doctrine_Query_ParserRule::SQLALIAS_SEPARATOR, $e)
|
||||
];
|
||||
$classMetadata = $this->_queryComponents[$cache[$key]['dqlAlias']]['metadata'];
|
||||
// check whether it's an aggregate value or a regular field
|
||||
@ -432,10 +432,10 @@ class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract
|
||||
if ($this->_isIgnoredName($key)) continue;
|
||||
|
||||
// cache general information like the column name <-> field name mapping
|
||||
$e = explode(Doctrine_Query_Production::SQLALIAS_SEPARATOR, $key);
|
||||
$e = explode(Doctrine_Query_ParserRule::SQLALIAS_SEPARATOR, $key);
|
||||
$columnName = array_pop($e);
|
||||
$cache[$key]['dqlAlias'] = $this->_tableAliases[
|
||||
implode(Doctrine_Query_Production::SQLALIAS_SEPARATOR, $e)
|
||||
implode(Doctrine_Query_ParserRule::SQLALIAS_SEPARATOR, $e)
|
||||
];
|
||||
$classMetadata = $this->_queryComponents[$cache[$key]['dqlAlias']]['metadata'];
|
||||
// check whether it's an aggregate value or a regular field
|
||||
|
43
lib/Doctrine/Query/AST.php
Normal file
43
lib/Doctrine/Query/AST.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract class of an AST node
|
||||
*
|
||||
* @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$
|
||||
*/
|
||||
abstract class Doctrine_Query_AST
|
||||
{
|
||||
protected $_parserResult = null;
|
||||
|
||||
|
||||
public function __construct(Doctrine_Query_ParserResult $parserResult)
|
||||
{
|
||||
$this->_parserResult = $parserResult;
|
||||
}
|
||||
}
|
50
lib/Doctrine/Query/AST/AbstractSchemaName.php
Normal file
50
lib/Doctrine/Query/AST/AbstractSchemaName.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* AbstractSchemaName ::= identifier
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_AST_AbstractSchemaName extends Doctrine_Query_AST
|
||||
{
|
||||
protected $_componentName;
|
||||
|
||||
|
||||
/* Setters */
|
||||
public function setComponentName($componentName)
|
||||
{
|
||||
$this->_componentName = $componentName;
|
||||
}
|
||||
|
||||
|
||||
/* Getters */
|
||||
public function getComponentName()
|
||||
{
|
||||
return $this->_componentName;
|
||||
}
|
||||
}
|
50
lib/Doctrine/Query/AST/AliasIdentificationVariable.php
Normal file
50
lib/Doctrine/Query/AST/AliasIdentificationVariable.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* AliasIdentificationVariable ::= identifier
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_AST_AliasIdentificationVariable extends Doctrine_Query_AST
|
||||
{
|
||||
protected $_componentAlias;
|
||||
|
||||
|
||||
/* Setters */
|
||||
public function setComponentAlias($componentAlias)
|
||||
{
|
||||
$this->_componentAlias = $componentAlias;
|
||||
}
|
||||
|
||||
|
||||
/* Getters */
|
||||
public function getComponentAlias()
|
||||
{
|
||||
return $this->_componentAlias;
|
||||
}
|
||||
}
|
75
lib/Doctrine/Query/AST/DeleteStatement.php
Normal file
75
lib/Doctrine/Query/AST/DeleteStatement.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DeleteStatement = DeleteClause [WhereClause]
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_AST_DeleteStatement extends Doctrine_Query_AST
|
||||
{
|
||||
protected $_deleteClause;
|
||||
|
||||
protected $_whereClause;
|
||||
|
||||
|
||||
/* Setters */
|
||||
public function setDeleteClause($deleteClause)
|
||||
{
|
||||
$this->_deleteClause = $deleteClause;
|
||||
}
|
||||
|
||||
|
||||
public function setWhereClause($whereClause)
|
||||
{
|
||||
$this->_whereClause = $whereClause;
|
||||
}
|
||||
|
||||
|
||||
/* Getters */
|
||||
public function getDeleteClause()
|
||||
{
|
||||
return $this->_deleteClause;
|
||||
}
|
||||
|
||||
|
||||
public function getWhereClause()
|
||||
{
|
||||
return $this->_whereClause;
|
||||
}
|
||||
|
||||
|
||||
/* REMOVE ME LATER. COPIED METHODS FROM SPLIT OF PRODUCTION INTO "AST" AND "PARSER" */
|
||||
|
||||
public function buildSql()
|
||||
{
|
||||
// The 1=1 is needed to workaround the affected_rows in MySQL.
|
||||
// Simple "DELETE FROM table_name" gives 0 affected rows.
|
||||
return $this->_deleteClause->buildSql() . (($this->_whereClause !== null)
|
||||
? ' ' . $this->_whereClause->buildSql() : ' WHERE 1 = 1');
|
||||
}
|
||||
}
|
50
lib/Doctrine/Query/AST/FieldIdentificationVariable.php
Normal file
50
lib/Doctrine/Query/AST/FieldIdentificationVariable.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* FieldIdentificationVariable ::= identifier
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_AST_FieldIdentificationVariable extends Doctrine_Query_AST
|
||||
{
|
||||
protected $_fieldName;
|
||||
|
||||
|
||||
/* Setters */
|
||||
public function setFieldName($fieldName)
|
||||
{
|
||||
$this->_fieldName = $fieldName;
|
||||
}
|
||||
|
||||
|
||||
/* Getters */
|
||||
public function getFieldName()
|
||||
{
|
||||
return $this->_fieldName;
|
||||
}
|
||||
}
|
87
lib/Doctrine/Query/AST/FromClause.php
Normal file
87
lib/Doctrine/Query/AST/FromClause.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* FromClause ::= "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration}
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_AST_FromClause extends Doctrine_Query_AST
|
||||
{
|
||||
protected $_identificationVariableDeclarations = array();
|
||||
|
||||
|
||||
/* Setters */
|
||||
public function addIdentificationVariableDeclaration($identificationVariableDeclaration)
|
||||
{
|
||||
$this->_identificationVariableDeclarations[] = $identificationVariableDeclaration;
|
||||
}
|
||||
|
||||
|
||||
public function setIdentificationVariableDeclarations($identificationVariableDeclarations, $append = false)
|
||||
{
|
||||
$this->_selectExpressions = ($append === true)
|
||||
? array_merge($this->_identificationVariableDeclarations, $identificationVariableDeclarations)
|
||||
: $identificationVariableDeclarations;
|
||||
}
|
||||
|
||||
|
||||
/* Getters */
|
||||
public function getIdentificationVariableDeclarations()
|
||||
{
|
||||
return $this->_identificationVariableDeclarations;
|
||||
}
|
||||
|
||||
|
||||
/* REMOVE ME LATER. COPIED METHODS FROM SPLIT OF PRODUCTION INTO "AST" AND "PARSER" */
|
||||
|
||||
public function buildSql()
|
||||
{
|
||||
//echo "FromClause:\n";
|
||||
//for ($i = 0; $i < count($this->_identificationVariableDeclaration);$i++) {
|
||||
// echo (($this->_identificationVariableDeclaration[$i] instanceof IdentificationVariableDeclaration)
|
||||
// ? get_class($this->_identificationVariableDeclaration[$i])
|
||||
// : get_class($this->_identificationVariableDeclaration[$i])) . "\n";
|
||||
//}
|
||||
|
||||
return 'FROM ' . implode(', ', $this->_mapIdentificationVariableDeclarations());
|
||||
}
|
||||
|
||||
|
||||
protected function _mapIdentificationVariableDeclarations()
|
||||
{
|
||||
return array_map(
|
||||
array(&$this, '_mapIdentificationVariableDeclaration'), $this->_identificationVariableDeclarations
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
protected function _mapIdentificationVariableDeclaration($value)
|
||||
{
|
||||
return $value->buildSql();
|
||||
}
|
||||
}
|
62
lib/Doctrine/Query/AST/IdentificationVariable.php
Normal file
62
lib/Doctrine/Query/AST/IdentificationVariable.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* IdentificationVariable ::= identifier
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_AST_IdentificationVariable extends Doctrine_Query_AST
|
||||
{
|
||||
protected $_componentAlias;
|
||||
|
||||
|
||||
/* Setters */
|
||||
public function setComponentAlias($componentAlias)
|
||||
{
|
||||
$this->_componentAlias = $componentAlias;
|
||||
}
|
||||
|
||||
|
||||
/* Getters */
|
||||
public function getComponentAlias()
|
||||
{
|
||||
return $this->_componentAlias;
|
||||
}
|
||||
|
||||
|
||||
/* REMOVE ME LATER. COPIED METHODS FROM SPLIT OF PRODUCTION INTO "AST" AND "PARSER" */
|
||||
|
||||
public function buildSql()
|
||||
{
|
||||
$conn = $this->_parserResult->getEntityManager()->getConnection();
|
||||
|
||||
return $conn->quoteIdentifier(
|
||||
$this->_parserResult->getTableAliasFromComponentAlias($this->_componentAlias)
|
||||
);
|
||||
}
|
||||
}
|
100
lib/Doctrine/Query/AST/IdentificationVariableDeclaration.php
Normal file
100
lib/Doctrine/Query/AST/IdentificationVariableDeclaration.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {JoinVariableDeclaration}*
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_AST_IdentificationVariableDeclaration extends Doctrine_Query_AST
|
||||
{
|
||||
protected $_rangeVariableDeclaration = null;
|
||||
|
||||
protected $_indexBy = null;
|
||||
|
||||
protected $_joinVariableDeclarations = array();
|
||||
|
||||
|
||||
/* Setters */
|
||||
public function setRangeVariableDeclaration($rangeVariableDeclaration)
|
||||
{
|
||||
$this->_rangeVariableDeclaration = $rangeVariableDeclaration;
|
||||
}
|
||||
|
||||
|
||||
public function setIndexBy($indexBy)
|
||||
{
|
||||
$this->_indexBy = $indexBy;
|
||||
}
|
||||
|
||||
|
||||
public function addJoinVariableDeclaration($joinVariableDeclaration)
|
||||
{
|
||||
$this->_joinVariableDeclarations[] = $joinVariableDeclaration;
|
||||
}
|
||||
|
||||
|
||||
public function setJoinVariableDeclarations($joinVariableDeclarations, $append = false)
|
||||
{
|
||||
$this->_joinVariableDeclarations = ($append === true)
|
||||
? array_merge($this->_joinVariableDeclarations, $joinVariableDeclarations)
|
||||
: $joinVariableDeclarations;
|
||||
}
|
||||
|
||||
|
||||
/* Getters */
|
||||
public function getRangeVariableDeclaration()
|
||||
{
|
||||
return $this->_rangeVariableDeclaration;
|
||||
}
|
||||
|
||||
|
||||
public function getIndexBy()
|
||||
{
|
||||
return $this->_indexBy;
|
||||
}
|
||||
|
||||
|
||||
public function getJoinVariableDeclarations()
|
||||
{
|
||||
return $this->_joinVariableDeclarations;
|
||||
}
|
||||
|
||||
|
||||
/* REMOVE ME LATER. COPIED METHODS FROM SPLIT OF PRODUCTION INTO "AST" AND "PARSER" */
|
||||
|
||||
public function buildSql()
|
||||
{
|
||||
$str = $this->_rangeVariableDeclaration->buildSql();
|
||||
|
||||
for ($i = 0, $l = count($this->_joinVariableDeclarations); $i < $l; $i++) {
|
||||
$str .= ' ' . $this->_joinVariableDeclarations[$i]->buildSql();
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
}
|
50
lib/Doctrine/Query/AST/IndexBy.php
Normal file
50
lib/Doctrine/Query/AST/IndexBy.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* IndexBy ::= "INDEX" "BY" SimpleStateFieldPathExpression
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_AST_IndexBy extends Doctrine_Query_AST
|
||||
{
|
||||
protected $_simpleStateFieldPathExpression = null;
|
||||
|
||||
|
||||
/* Setters */
|
||||
public function setSimpleStateFieldPathExpression($simpleStateFieldPathExpression)
|
||||
{
|
||||
$this->_simpleStateFieldPathExpression = $simpleStateFieldPathExpression;
|
||||
}
|
||||
|
||||
|
||||
/* Getters */
|
||||
public function getSimpleStateFieldPathExpression()
|
||||
{
|
||||
return $this->_simpleStateFieldPathExpression;
|
||||
}
|
||||
}
|
89
lib/Doctrine/Query/AST/RangeVariableDeclaration.php
Normal file
89
lib/Doctrine/Query/AST/RangeVariableDeclaration.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_AST_RangeVariableDeclaration extends Doctrine_Query_AST
|
||||
{
|
||||
protected $_abstractSchemaName = null;
|
||||
|
||||
protected $_aliasIdentificationVariable = null;
|
||||
|
||||
|
||||
/* Setters */
|
||||
public function setAbstractSchemaName($abstractSchemaName)
|
||||
{
|
||||
$this->_abstractSchemaName = $abstractSchemaName;
|
||||
}
|
||||
|
||||
|
||||
public function setAliasIdentificationVariable($aliasIdentificationVariable)
|
||||
{
|
||||
$this->_aliasIdentificationVariable = $aliasIdentificationVariable;
|
||||
}
|
||||
|
||||
|
||||
/* Getters */
|
||||
public function getAbstractSchemaName()
|
||||
{
|
||||
return $this->_abstractSchemaName;
|
||||
}
|
||||
|
||||
|
||||
public function getAliasIdentificationVariable()
|
||||
{
|
||||
return $this->_aliasIdentificationVariable;
|
||||
}
|
||||
|
||||
|
||||
/* REMOVE ME LATER. COPIED METHODS FROM SPLIT OF PRODUCTION INTO "AST" AND "PARSER" */
|
||||
|
||||
public function buildSql()
|
||||
{
|
||||
// Retrieving connection
|
||||
$conn = $this->_parserResult->getEntityManager()->getConnection();
|
||||
|
||||
// Component alias
|
||||
$componentAlias = $this->_aliasIdentificationVariable->getComponentAlias();
|
||||
|
||||
// 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));
|
||||
}
|
||||
}
|
93
lib/Doctrine/Query/AST/SelectClause.php
Normal file
93
lib/Doctrine/Query/AST/SelectClause.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SelectClause = "SELECT" ["DISTINCT"] SelectExpression {"," SelectExpression}
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_AST_SelectClause extends Doctrine_Query_AST
|
||||
{
|
||||
protected $_isDistinct;
|
||||
|
||||
protected $_selectExpressions = array();
|
||||
|
||||
|
||||
/* Setters */
|
||||
public function setIsDistinct($value)
|
||||
{
|
||||
$this->_isDistinct = $value;
|
||||
}
|
||||
|
||||
|
||||
public function addSelectExpression($expression)
|
||||
{
|
||||
$this->_selectExpressions[] = $expression;
|
||||
}
|
||||
|
||||
|
||||
public function setSelectExpressions($expressions, $append = false)
|
||||
{
|
||||
$this->_selectExpressions = ($append === true)
|
||||
? array_merge($this->_selectExpressions, $expressions)
|
||||
: $expressions;
|
||||
}
|
||||
|
||||
|
||||
/* Getters */
|
||||
public function isDistinct()
|
||||
{
|
||||
return $this->_isDistinct;
|
||||
}
|
||||
|
||||
|
||||
public function getSelectExpressions()
|
||||
{
|
||||
return $this->_selectExpressions;
|
||||
}
|
||||
|
||||
|
||||
/* REMOVE ME LATER. COPIED METHODS FROM SPLIT OF PRODUCTION INTO "AST" AND "PARSER" */
|
||||
|
||||
public function buildSql()
|
||||
{
|
||||
return 'SELECT ' . (($this->_isDistinct) ? 'DISTINCT ' : '')
|
||||
. implode(', ', $this->_mapSelectExpressions());
|
||||
}
|
||||
|
||||
|
||||
protected function _mapSelectExpressions()
|
||||
{
|
||||
return array_map(array(&$this, '_mapSelectExpression'), $this->_selectExpressions);
|
||||
}
|
||||
|
||||
|
||||
protected function _mapSelectExpression($value)
|
||||
{
|
||||
return $value->buildSql();
|
||||
}
|
||||
}
|
132
lib/Doctrine/Query/AST/SelectStatement.php
Normal file
132
lib/Doctrine/Query/AST/SelectStatement.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SelectStatement = SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause]
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_AST_SelectStatement extends Doctrine_Query_AST
|
||||
{
|
||||
protected $_selectClause;
|
||||
|
||||
protected $_fromClause;
|
||||
|
||||
protected $_whereClause;
|
||||
|
||||
protected $_groupByClause;
|
||||
|
||||
protected $_havingClause;
|
||||
|
||||
protected $_orderByClause;
|
||||
|
||||
|
||||
/* Setters */
|
||||
public function setSelectClause($selectClause)
|
||||
{
|
||||
$this->_selectClause = $selectClause;
|
||||
}
|
||||
|
||||
|
||||
public function setFromClause($fromClause)
|
||||
{
|
||||
$this->_fromClause = $fromClause;
|
||||
}
|
||||
|
||||
|
||||
public function setWhereClause($whereClause)
|
||||
{
|
||||
$this->_whereClause = $whereClause;
|
||||
}
|
||||
|
||||
|
||||
public function setGroupByClause($groupByClause)
|
||||
{
|
||||
$this->_groupByClause = $groupByClause;
|
||||
}
|
||||
|
||||
|
||||
public function setHavingClause($havingClause)
|
||||
{
|
||||
$this->_havingClause = $havingClause;
|
||||
}
|
||||
|
||||
|
||||
public function setOrderByClause($orderByClause)
|
||||
{
|
||||
$this->_orderByClause = $orderByClause;
|
||||
}
|
||||
|
||||
|
||||
/* Getters */
|
||||
public function getSelectClause()
|
||||
{
|
||||
return $this->_selectClause;
|
||||
}
|
||||
|
||||
|
||||
public function getFromClause()
|
||||
{
|
||||
return $this->_fromClause;
|
||||
}
|
||||
|
||||
|
||||
public function getWhereClause()
|
||||
{
|
||||
return $this->_whereClause;
|
||||
}
|
||||
|
||||
|
||||
public function getGroupByClause()
|
||||
{
|
||||
return $this->_groupByClause;
|
||||
}
|
||||
|
||||
|
||||
public function getHavingClause()
|
||||
{
|
||||
return $this->_havingClause;
|
||||
}
|
||||
|
||||
|
||||
public function getOrderByClause()
|
||||
{
|
||||
return $this->_orderByClause;
|
||||
}
|
||||
|
||||
|
||||
/* REMOVE ME LATER. COPIED METHODS FROM SPLIT OF PRODUCTION INTO "AST" AND "PARSER" */
|
||||
|
||||
public function buildSql()
|
||||
{
|
||||
return $this->_selectClause->buildSql() . ' ' . $this->_fromClause->buildSql()
|
||||
. (($this->_whereClause !== null) ? ' ' . $this->_whereClause->buildSql() : ' WHERE 1 = 1')
|
||||
. (($this->_groupByClause !== null) ? ' ' . $this->_groupByClause->buildSql() : '')
|
||||
. (($this->_havingClause !== null) ? ' ' . $this->_havingClause->buildSql() : '')
|
||||
. (($this->_orderByClause !== null) ? ' ' . $this->_orderByClause->buildSql() : '');
|
||||
}
|
||||
}
|
64
lib/Doctrine/Query/AST/SimpleStateFieldPathExpression.php
Normal file
64
lib/Doctrine/Query/AST/SimpleStateFieldPathExpression.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SimpleStateFieldPathExpression ::= IdentificationVariable "." SimpleStateField
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_AST_SimpleStateFieldPathExpression extends Doctrine_Query_AST
|
||||
{
|
||||
protected $_identificationVariable = null;
|
||||
|
||||
protected $_simpleStateField = null;
|
||||
|
||||
|
||||
/* Setters */
|
||||
public function setIdentificationVariable($identificationVariable)
|
||||
{
|
||||
$this->_identificationVariable = $identificationVariable;
|
||||
}
|
||||
|
||||
|
||||
public function setSimpleStateField($simpleStateField)
|
||||
{
|
||||
$this->_simpleStateField = $simpleStateField;
|
||||
}
|
||||
|
||||
|
||||
/* Getters */
|
||||
public function getIdentificationVariable()
|
||||
{
|
||||
return $this->_identificationVariable;
|
||||
}
|
||||
|
||||
|
||||
public function getSimpleStateField()
|
||||
{
|
||||
return $this->_simpleStateField;
|
||||
}
|
||||
}
|
75
lib/Doctrine/Query/AST/UpdateStatetement.php
Normal file
75
lib/Doctrine/Query/AST/UpdateStatetement.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* UpdateStatement = UpdateClause [WhereClause]
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.phpdoctrine.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_AST_UpdateStatement extends Doctrine_Query_AST
|
||||
{
|
||||
protected $_updateClause;
|
||||
|
||||
protected $_whereClause;
|
||||
|
||||
|
||||
/* Setters */
|
||||
public function setUpdateClause($updateClause)
|
||||
{
|
||||
$this->_updateClause = $updateClause;
|
||||
}
|
||||
|
||||
|
||||
public function setWhereClause($whereClause)
|
||||
{
|
||||
$this->_whereClause = $whereClause;
|
||||
}
|
||||
|
||||
|
||||
/* Getters */
|
||||
public function getUpdateClause()
|
||||
{
|
||||
return $this->_updateClause;
|
||||
}
|
||||
|
||||
|
||||
public function getWhereClause()
|
||||
{
|
||||
return $this->_whereClause;
|
||||
}
|
||||
|
||||
|
||||
/* REMOVE ME LATER. COPIED METHODS FROM SPLIT OF PRODUCTION INTO "AST" AND "PARSER" */
|
||||
|
||||
public function buildSql()
|
||||
{
|
||||
// The 1=1 is needed to workaround the affected_rows in MySQL.
|
||||
// Simple "UPDATE table_name SET column_name = value" gives 0 affected rows.
|
||||
return $this->_updateClause->buildSql() . (($this->_whereClause !== null)
|
||||
? ' ' . $this->_whereClause->buildSql() : ' WHERE 1 = 1');
|
||||
}
|
||||
}
|
@ -1,355 +1,380 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An LL(k) parser for the context-free grammar of Doctrine Query Language.
|
||||
* Parses a DQL query, reports any errors in it, and generates the corresponding
|
||||
* SQL.
|
||||
*
|
||||
* @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_Query_Parser
|
||||
{
|
||||
/**
|
||||
* The minimum number of tokens read after last detected error before
|
||||
* another error can be reported.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const MIN_ERROR_DISTANCE = 2;
|
||||
|
||||
|
||||
/**
|
||||
* The Sql Builder object.
|
||||
*
|
||||
* @var Doctrine_Query_SqlBuilder
|
||||
*/
|
||||
protected $_sqlbuilder;
|
||||
|
||||
/**
|
||||
* A scanner object.
|
||||
*
|
||||
* @var Doctrine_Query_Scanner
|
||||
*/
|
||||
protected $_scanner;
|
||||
|
||||
/**
|
||||
* The Parser Result object.
|
||||
*
|
||||
* @var Doctrine_Query_ParserResult
|
||||
*/
|
||||
protected $_parserResult;
|
||||
|
||||
/**
|
||||
* Keyword symbol table
|
||||
*
|
||||
* @var Doctrine_Query_Token
|
||||
*/
|
||||
protected $_keywordTable;
|
||||
|
||||
// Scanner Stuff
|
||||
|
||||
/**
|
||||
* @var array The next token in the query string.
|
||||
*/
|
||||
public $lookahead;
|
||||
|
||||
/**
|
||||
* @var array The last matched token.
|
||||
*/
|
||||
public $token;
|
||||
|
||||
// End of Scanner Stuff
|
||||
|
||||
|
||||
// Error management stuff
|
||||
|
||||
/**
|
||||
* Array containing errors detected in the query string during parsing process.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_errors;
|
||||
|
||||
/**
|
||||
* @var int The number of tokens read since last error in the input string.
|
||||
*/
|
||||
protected $_errorDistance;
|
||||
|
||||
/**
|
||||
* The EntityManager.
|
||||
*
|
||||
* @var EnityManager
|
||||
*/
|
||||
protected $_em;
|
||||
|
||||
// End of Error management stuff
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new query parser object.
|
||||
*
|
||||
* @param string $dql DQL to be parsed.
|
||||
* @param Doctrine_Connection $connection The connection to use
|
||||
*/
|
||||
public function __construct(Doctrine_Query $query)
|
||||
{
|
||||
$this->_em = $query->getEntityManager();
|
||||
$this->_scanner = new Doctrine_Query_Scanner($query->getDql());
|
||||
$this->_sqlBuilder = Doctrine_Query_SqlBuilder::fromConnection($this->_em);
|
||||
$this->_keywordTable = new Doctrine_Query_Token();
|
||||
|
||||
$this->_parserResult = new Doctrine_Query_ParserResult(
|
||||
'',
|
||||
array( // queryComponent
|
||||
'dctrn' => array(
|
||||
'metadata' => null,
|
||||
'parent' => null,
|
||||
'relation' => null,
|
||||
'map' => null,
|
||||
'scalar' => null,
|
||||
),
|
||||
),
|
||||
array( // tableAliasMap
|
||||
'dctrn' => 'dctrn',
|
||||
)
|
||||
);
|
||||
|
||||
$this->free(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attempts to match the given token with the current lookahead token.
|
||||
*
|
||||
* If they match, updates the lookahead token; otherwise raises a syntax
|
||||
* error.
|
||||
*
|
||||
* @param int|string token type or value
|
||||
* @return bool True, if tokens match; false otherwise.
|
||||
*/
|
||||
public function match($token)
|
||||
{
|
||||
if (is_string($token)) {
|
||||
$isMatch = ($this->lookahead['value'] === $token);
|
||||
} else {
|
||||
$isMatch = ($this->lookahead['type'] === $token);
|
||||
}
|
||||
|
||||
if ( ! $isMatch) {
|
||||
// No definition for value checking.
|
||||
$this->syntaxError($this->_keywordTable->getLiteral($token));
|
||||
}
|
||||
|
||||
$this->next();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves the parser scanner to next token
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
$this->token = $this->lookahead;
|
||||
$this->lookahead = $this->_scanner->next();
|
||||
$this->_errorDistance++;
|
||||
}
|
||||
|
||||
|
||||
public function isA($value, $token)
|
||||
{
|
||||
return $this->_scanner->isA($value, $token);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free this parser enabling it to be reused
|
||||
*
|
||||
* @param boolean $deep Whether to clean peek and reset errors
|
||||
* @param integer $position Position to reset
|
||||
* @return void
|
||||
*/
|
||||
public function free($deep = false, $position = 0)
|
||||
{
|
||||
// WARNING! Use this method with care. It resets the scanner!
|
||||
$this->_scanner->resetPosition($position);
|
||||
|
||||
// Deep = true cleans peek and also any previously defined errors
|
||||
if ($deep) {
|
||||
$this->_scanner->resetPeek();
|
||||
$this->_errors = array();
|
||||
}
|
||||
|
||||
$this->token = null;
|
||||
$this->lookahead = null;
|
||||
|
||||
$this->_errorDistance = self::MIN_ERROR_DISTANCE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a query string.
|
||||
*/
|
||||
public function parse()
|
||||
{
|
||||
$this->lookahead = $this->_scanner->next();
|
||||
|
||||
// Building the Abstract Syntax Tree
|
||||
// We have to double the call of QueryLanguage to allow it to work correctly... =\
|
||||
$AST = new Doctrine_Query_Production_QueryLanguage($this);
|
||||
$AST = $AST->AST('QueryLanguage', Doctrine_Query_ProductionParamHolder::create());
|
||||
|
||||
// Check for end of string
|
||||
if ($this->lookahead !== null) {
|
||||
$this->syntaxError('end of string');
|
||||
}
|
||||
|
||||
// Check for semantical errors
|
||||
if (count($this->_errors) > 0) {
|
||||
throw new Doctrine_Query_Parser_Exception(implode("\r\n", $this->_errors));
|
||||
}
|
||||
|
||||
// Assign the executor in parser result
|
||||
$this->_parserResult->setSqlExecutor(Doctrine_Query_SqlExecutor_Abstract::create($AST));
|
||||
|
||||
return $this->_parserResult;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the assocated Doctrine_Query_SqlBuilder to this object.
|
||||
*
|
||||
* @return Doctrine_Query_SqlBuilder
|
||||
*/
|
||||
public function getSqlBuilder()
|
||||
{
|
||||
return $this->_sqlBuilder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the scanner object associated with this object.
|
||||
*
|
||||
* @return Doctrine_Query_Scanner
|
||||
*/
|
||||
public function getScanner()
|
||||
{
|
||||
return $this->_scanner;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the parser result associated with this object.
|
||||
*
|
||||
* @return Doctrine_Query_ParserResult
|
||||
*/
|
||||
public function getParserResult()
|
||||
{
|
||||
return $this->_parserResult;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a new syntax error.
|
||||
*
|
||||
* @param string $expected Optional expected string.
|
||||
* @param array $token Optional token.
|
||||
*/
|
||||
public function syntaxError($expected = '', $token = null)
|
||||
{
|
||||
if ($token === null) {
|
||||
$token = $this->lookahead;
|
||||
}
|
||||
|
||||
// Formatting message
|
||||
$message = 'line 0, col ' . (isset($token['position']) ? $token['position'] : '-1') . ': Error: ';
|
||||
|
||||
if ($expected !== '') {
|
||||
$message .= "Expected '$expected', got ";
|
||||
} else {
|
||||
$message .= 'Unexpected ';
|
||||
}
|
||||
|
||||
if ($this->lookahead === null) {
|
||||
$message .= 'end of string.';
|
||||
} else {
|
||||
$message .= "'{$this->lookahead['value']}'";
|
||||
}
|
||||
|
||||
throw new Doctrine_Query_Parser_Exception($message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a new semantical error.
|
||||
*
|
||||
* @param string $message Optional message.
|
||||
* @param array $token Optional token.
|
||||
*/
|
||||
public function semanticalError($message = '', $token = null)
|
||||
{
|
||||
$this->_semanticalErrorCount++;
|
||||
|
||||
if ($token === null) {
|
||||
$token = $this->token;
|
||||
}
|
||||
|
||||
$this->_logError('Warning: ' . $message, $token);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Logs new error entry.
|
||||
*
|
||||
* @param string $message Message to log.
|
||||
* @param array $token Token that it was processing.
|
||||
*/
|
||||
protected function _logError($message = '', $token)
|
||||
{
|
||||
if ($this->_errorDistance >= self::MIN_ERROR_DISTANCE) {
|
||||
$message = 'line 0, col ' . $token['position'] . ': ' . $message;
|
||||
$this->_errors[] = $message;
|
||||
}
|
||||
|
||||
$this->_errorDistance = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EntityManager used by the parser.
|
||||
*
|
||||
* @return EntityManager
|
||||
*/
|
||||
public function getEntityManager()
|
||||
{
|
||||
return $this->_em;
|
||||
}
|
||||
}
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An LL(k) parser for the context-free grammar of Doctrine Query Language.
|
||||
* Parses a DQL query, reports any errors in it, and generates the corresponding
|
||||
* SQL.
|
||||
*
|
||||
* @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_Query_Parser
|
||||
{
|
||||
/**
|
||||
* The minimum number of tokens read after last detected error before
|
||||
* another error can be reported.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const MIN_ERROR_DISTANCE = 2;
|
||||
|
||||
|
||||
/**
|
||||
* The Sql Builder object.
|
||||
*
|
||||
* @var Doctrine_Query_SqlBuilder
|
||||
*/
|
||||
protected $_sqlbuilder;
|
||||
|
||||
/**
|
||||
* DQL string.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_input;
|
||||
|
||||
/**
|
||||
* A scanner object.
|
||||
*
|
||||
* @var Doctrine_Query_Scanner
|
||||
*/
|
||||
protected $_scanner;
|
||||
|
||||
/**
|
||||
* The Parser Result object.
|
||||
*
|
||||
* @var Doctrine_Query_ParserResult
|
||||
*/
|
||||
protected $_parserResult;
|
||||
|
||||
/**
|
||||
* Keyword symbol table
|
||||
*
|
||||
* @var Doctrine_Query_Token
|
||||
*/
|
||||
protected $_keywordTable;
|
||||
|
||||
// Scanner Stuff
|
||||
|
||||
/**
|
||||
* @var array The next token in the query string.
|
||||
*/
|
||||
public $lookahead;
|
||||
|
||||
/**
|
||||
* @var array The last matched token.
|
||||
*/
|
||||
public $token;
|
||||
|
||||
// End of Scanner Stuff
|
||||
|
||||
|
||||
// Error management stuff
|
||||
|
||||
/**
|
||||
* Array containing errors detected in the query string during parsing process.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_errors;
|
||||
|
||||
/**
|
||||
* @var int The number of tokens read since last error in the input string.
|
||||
*/
|
||||
protected $_errorDistance;
|
||||
|
||||
/**
|
||||
* The EntityManager.
|
||||
*
|
||||
* @var EnityManager
|
||||
*/
|
||||
protected $_em;
|
||||
|
||||
// End of Error management stuff
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new query parser object.
|
||||
*
|
||||
* @param string $dql DQL to be parsed.
|
||||
* @param Doctrine_Connection $connection The connection to use
|
||||
*/
|
||||
public function __construct(Doctrine_Query $query)
|
||||
{
|
||||
$this->_em = $query->getEntityManager();
|
||||
$this->_input = $query->getDql();
|
||||
$this->_scanner = new Doctrine_Query_Scanner($this->_input);
|
||||
$this->_sqlBuilder = Doctrine_Query_SqlBuilder::fromConnection($this->_em);
|
||||
$this->_keywordTable = new Doctrine_Query_Token();
|
||||
|
||||
$this->_parserResult = new Doctrine_Query_ParserResult(
|
||||
'',
|
||||
array( // queryComponent
|
||||
'dctrn' => array(
|
||||
'metadata' => null,
|
||||
'parent' => null,
|
||||
'relation' => null,
|
||||
'map' => null,
|
||||
'scalar' => null,
|
||||
),
|
||||
),
|
||||
array( // tableAliasMap
|
||||
'dctrn' => 'dctrn',
|
||||
)
|
||||
);
|
||||
|
||||
$this->_parserResult->setEntityManager($this->_em);
|
||||
|
||||
$this->free(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attempts to match the given token with the current lookahead token.
|
||||
*
|
||||
* If they match, updates the lookahead token; otherwise raises a syntax
|
||||
* error.
|
||||
*
|
||||
* @param int|string token type or value
|
||||
* @return bool True, if tokens match; false otherwise.
|
||||
*/
|
||||
public function match($token)
|
||||
{
|
||||
if (is_string($token)) {
|
||||
$isMatch = ($this->lookahead['value'] === $token);
|
||||
} else {
|
||||
$isMatch = ($this->lookahead['type'] === $token);
|
||||
}
|
||||
|
||||
if ( ! $isMatch) {
|
||||
// No definition for value checking.
|
||||
$this->syntaxError($this->_keywordTable->getLiteral($token));
|
||||
}
|
||||
|
||||
$this->next();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves the parser scanner to next token
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
$this->token = $this->lookahead;
|
||||
$this->lookahead = $this->_scanner->next();
|
||||
$this->_errorDistance++;
|
||||
}
|
||||
|
||||
|
||||
public function isA($value, $token)
|
||||
{
|
||||
return $this->_scanner->isA($value, $token);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free this parser enabling it to be reused
|
||||
*
|
||||
* @param boolean $deep Whether to clean peek and reset errors
|
||||
* @param integer $position Position to reset
|
||||
* @return void
|
||||
*/
|
||||
public function free($deep = false, $position = 0)
|
||||
{
|
||||
// WARNING! Use this method with care. It resets the scanner!
|
||||
$this->_scanner->resetPosition($position);
|
||||
|
||||
// Deep = true cleans peek and also any previously defined errors
|
||||
if ($deep) {
|
||||
$this->_scanner->resetPeek();
|
||||
$this->_errors = array();
|
||||
}
|
||||
|
||||
$this->token = null;
|
||||
$this->lookahead = null;
|
||||
|
||||
$this->_errorDistance = self::MIN_ERROR_DISTANCE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a query string.
|
||||
*/
|
||||
public function parse()
|
||||
{
|
||||
$this->lookahead = $this->_scanner->next();
|
||||
|
||||
// Building the Abstract Syntax Tree
|
||||
// We have to double the call of QueryLanguage to allow it to work correctly... =\
|
||||
$DQL = new Doctrine_Query_Parser_QueryLanguage($this);
|
||||
$AST = $DQL->parse('QueryLanguage', Doctrine_Query_ParserParamHolder::create());
|
||||
|
||||
// Check for end of string
|
||||
if ($this->lookahead !== null) {
|
||||
$this->syntaxError('end of string');
|
||||
}
|
||||
|
||||
// Check for semantical errors
|
||||
if (count($this->_errors) > 0) {
|
||||
throw new Doctrine_Query_Parser_Exception(implode("\r\n", $this->_errors));
|
||||
}
|
||||
|
||||
// Assign the executor in parser result
|
||||
$this->_parserResult->setSqlExecutor(Doctrine_Query_SqlExecutor_Abstract::create($AST));
|
||||
|
||||
return $this->_parserResult;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the assocated Doctrine_Query_SqlBuilder to this object.
|
||||
*
|
||||
* @return Doctrine_Query_SqlBuilder
|
||||
*/
|
||||
public function getSqlBuilder()
|
||||
{
|
||||
return $this->_sqlBuilder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the scanner object associated with this object.
|
||||
*
|
||||
* @return Doctrine_Query_Scanner
|
||||
*/
|
||||
public function getScanner()
|
||||
{
|
||||
return $this->_scanner;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the parser result associated with this object.
|
||||
*
|
||||
* @return Doctrine_Query_ParserResult
|
||||
*/
|
||||
public function getParserResult()
|
||||
{
|
||||
return $this->_parserResult;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a new syntax error.
|
||||
*
|
||||
* @param string $expected Optional expected string.
|
||||
* @param array $token Optional token.
|
||||
*/
|
||||
public function syntaxError($expected = '', $token = null)
|
||||
{
|
||||
if ($token === null) {
|
||||
$token = $this->lookahead;
|
||||
}
|
||||
|
||||
// Formatting message
|
||||
$message = 'line 0, col ' . (isset($token['position']) ? $token['position'] : '-1') . ': Error: ';
|
||||
|
||||
if ($expected !== '') {
|
||||
$message .= "Expected '$expected', got ";
|
||||
} else {
|
||||
$message .= 'Unexpected ';
|
||||
}
|
||||
|
||||
if ($this->lookahead === null) {
|
||||
$message .= 'end of string.';
|
||||
} else {
|
||||
$message .= "'{$this->lookahead['value']}'";
|
||||
}
|
||||
|
||||
throw new Doctrine_Query_Parser_Exception($message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a new semantical error.
|
||||
*
|
||||
* @param string $message Optional message.
|
||||
* @param array $token Optional token.
|
||||
*/
|
||||
public function semanticalError($message = '', $token = null)
|
||||
{
|
||||
$this->_semanticalErrorCount++;
|
||||
|
||||
if ($token === null) {
|
||||
$token = $this->token;
|
||||
}
|
||||
|
||||
$this->_logError('Warning: ' . $message, $token);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Logs new error entry.
|
||||
*
|
||||
* @param string $message Message to log.
|
||||
* @param array $token Token that it was processing.
|
||||
*/
|
||||
protected function _logError($message = '', $token)
|
||||
{
|
||||
if ($this->_errorDistance >= self::MIN_ERROR_DISTANCE) {
|
||||
$message = 'line 0, col ' . $token['position'] . ': ' . $message;
|
||||
$this->_errors[] = $message;
|
||||
}
|
||||
|
||||
$this->_errorDistance = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EntityManager used by the parser.
|
||||
*
|
||||
* @return EntityManager
|
||||
*/
|
||||
public function getEntityManager()
|
||||
{
|
||||
return $this->_em;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the piece of DQL string given the token position
|
||||
*
|
||||
* @param array $token Token that it was processing.
|
||||
* @return string Piece of DQL string.
|
||||
*/
|
||||
public function getQueryPiece($token, $previousChars = 10, $nextChars = 10)
|
||||
{
|
||||
$start = max(0, $token['position'] - $previousChars);
|
||||
$end = max($token['position'] + $nextChars, strlen($this->_input));
|
||||
|
||||
return substr($this->_input, $start, $end);
|
||||
}
|
||||
}
|
||||
|
76
lib/Doctrine/Query/Parser/AbstractSchemaName.php
Normal file
76
lib/Doctrine/Query/Parser/AbstractSchemaName.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* AbstractSchemaName ::= identifier
|
||||
*
|
||||
* @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_Query_Parser_AbstractSchemaName extends Doctrine_Query_ParserRule
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// AbstractSchemaName ::= identifier
|
||||
$this->_AST = $this->AST('AbstractSchemaName');
|
||||
|
||||
$this->_parser->match(Doctrine_Query_Token::T_IDENTIFIER);
|
||||
$this->_AST->setComponentName($this->_parser->token['value']);
|
||||
}
|
||||
|
||||
|
||||
public function semantical($paramHolder)
|
||||
{
|
||||
$componentName = $this->_AST->getComponentName();
|
||||
|
||||
// Check if we are dealing with a real Doctrine_Entity or not
|
||||
if ( ! $this->_isDoctrineEntity($componentName)) {
|
||||
$this->_parser->semanticalError(
|
||||
"Defined entity '" . $companyName . "' is not a valid Doctrine_Entity."
|
||||
);
|
||||
}
|
||||
|
||||
// Return AST node
|
||||
return $this->_AST;
|
||||
}
|
||||
|
||||
|
||||
protected function _isDoctrineEntity($componentName)
|
||||
{
|
||||
if (class_exists($componentName)) {
|
||||
$reflectionClass = new ReflectionClass($componentName);
|
||||
$dctrnEntityReflectionClass = new ReflectionClass('Doctrine_Entity');
|
||||
|
||||
return $reflectionClass->isSubclassOf($dctrnEntityReflectionClass);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
66
lib/Doctrine/Query/Parser/AliasIdentificationVariable.php
Normal file
66
lib/Doctrine/Query/Parser/AliasIdentificationVariable.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.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* AliasIdentificationVariable = identifier
|
||||
*
|
||||
* @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_Query_Parser_AliasIdentificationVariable extends Doctrine_Query_ParserRule
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// AliasIdentificationVariable = identifier
|
||||
$this->_AST = $this->AST('AliasIdentificationVariable');
|
||||
|
||||
$this->_parser->match(Doctrine_Query_Token::T_IDENTIFIER);
|
||||
$this->_AST->setComponentAlias($this->_parser->token['value']);
|
||||
}
|
||||
|
||||
|
||||
public function semantical($paramHolder)
|
||||
{
|
||||
$parserResult = $this->_parser->getParserResult();
|
||||
|
||||
if ($parserResult->hasQueryComponent($this->_AST->getComponentAlias())) {
|
||||
// We should throw semantical error if there's already a component for this alias
|
||||
$queryComponent = $parserResult->getQueryComponent($this->_AST->getComponentAlias());
|
||||
$componentName = $queryComponent['metadata']->getClassName();
|
||||
|
||||
$message = "Cannot re-declare component alias '" . $this->_AST->getComponentAlias() . "'. "
|
||||
. "It was already declared for component '" . $componentName . "'.";
|
||||
|
||||
$this->_parser->semanticalError($message);
|
||||
}
|
||||
|
||||
return $this->_AST;
|
||||
}
|
||||
}
|
53
lib/Doctrine/Query/Parser/DeleteStatement.php
Normal file
53
lib/Doctrine/Query/Parser/DeleteStatement.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DeleteStatement ::= DeleteClause [WhereClause]
|
||||
*
|
||||
* @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_Query_Parser_DeleteStatement extends Doctrine_Query_Parser
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// DeleteStatement ::= DeleteClause [WhereClause]
|
||||
$this->_AST = $this->AST('DeleteStatement');
|
||||
|
||||
$this->_AST->setDeleteClause($this->parse('DeleteClause', $paramHolder));
|
||||
|
||||
if ($this->_isNextToken(Doctrine_Query_Token::T_WHERE)) {
|
||||
$this->_AST->setWhereClause($this->parse('WhereClause', $paramHolder));
|
||||
}
|
||||
|
||||
// Return AST node
|
||||
return $this->_AST;
|
||||
}
|
||||
}
|
61
lib/Doctrine/Query/Parser/FieldIdentificationVariable.php
Normal file
61
lib/Doctrine/Query/Parser/FieldIdentificationVariable.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* FieldIdentificationVariable ::= identifier
|
||||
*
|
||||
* @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_Query_Parser_FieldIdentificationVariable extends Doctrine_Query_ParserRule
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// FieldIdentificationVariable ::= identifier
|
||||
$this->_AST = $this->AST('FieldIdentificationVariable');
|
||||
|
||||
$this->_parser->match(Doctrine_Query_Token::T_IDENTIFIER);
|
||||
$this->_AST->setFieldName($this->_parser->token['value']);
|
||||
|
||||
// Return AST node
|
||||
return $this->_AST;
|
||||
}
|
||||
|
||||
|
||||
public function semantical($paramHolder)
|
||||
{
|
||||
$parserResult = $this->_parser->getParserResult();
|
||||
|
||||
// [TODO] Check for field existance somewhere
|
||||
|
||||
// Return AST node
|
||||
return $this->_AST;
|
||||
}
|
||||
}
|
61
lib/Doctrine/Query/Parser/FromClause.php
Normal file
61
lib/Doctrine/Query/Parser/FromClause.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* FromClause ::= "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration}
|
||||
*
|
||||
* @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 1.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_Parser_FromClause extends Doctrine_Query_ParserRule
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// FromClause ::= "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration}
|
||||
$this->_AST = $this->AST('FromClause');
|
||||
|
||||
$this->_parser->match(Doctrine_Query_Token::T_FROM);
|
||||
|
||||
$this->_AST->addIdentificationVariableDeclaration(
|
||||
$this->parse('IdentificationVariableDeclaration', $paramHolder)
|
||||
);
|
||||
|
||||
while ($this->_isNextToken(',')) {
|
||||
$this->_parser->match(',');
|
||||
|
||||
$this->_AST->addIdentificationVariableDeclaration(
|
||||
$this->parse('IdentificationVariableDeclaration', $paramHolder)
|
||||
);
|
||||
}
|
||||
|
||||
// Return AST node
|
||||
return $this->_AST;
|
||||
}
|
||||
}
|
64
lib/Doctrine/Query/Parser/IdentificationVariable.php
Normal file
64
lib/Doctrine/Query/Parser/IdentificationVariable.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* IdentificationVariable ::= identifier
|
||||
*
|
||||
* @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_Query_Parser_IdentificationVariable extends Doctrine_Query_ParserRule
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// IdentificationVariable ::= identifier
|
||||
$this->_AST = $this->AST('IdentificationVariable');
|
||||
|
||||
$this->_parser->match(Doctrine_Query_Token::T_IDENTIFIER);
|
||||
$this->_AST->setComponentAlias($this->_parser->token['value']);
|
||||
}
|
||||
|
||||
|
||||
public function semantical($paramHolder)
|
||||
{
|
||||
$parserResult = $this->_parser->getParserResult();
|
||||
|
||||
if ( ! $parserResult->hasQueryComponent($this->_AST->getComponentAlias())) {
|
||||
// We should throw semantical error if we cannot find the component alias
|
||||
$message = "No entity related to declared alias '" . $this->_AST->getComponentAlias()
|
||||
. "' near '" . $this->_parser->getQueryPiece($this->_parser->token) . "'.";
|
||||
|
||||
$this->_parser->semanticalError($message);
|
||||
}
|
||||
|
||||
// Return AST node
|
||||
return $this->_AST;
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {JoinVariableDeclaration}*
|
||||
*
|
||||
* @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 1.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_Parser_IdentificationVariableDeclaration extends Doctrine_Query_ParserRule
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {JoinVariableDeclaration}*
|
||||
$this->_AST = $this->AST('IdentificationVariableDeclaration');
|
||||
|
||||
$this->_AST->setRangeVariableDeclaration($this->parse('RangeVariableDeclaration', $paramHolder));
|
||||
|
||||
if ($this->_isNextToken(Doctrine_Query_Token::T_INDEX)) {
|
||||
$paramHolder->set(
|
||||
'componentAlias',
|
||||
$this->_AST->getRangeVariableDeclaration()->getAliasIdentificationVariable()->getComponentAlias()
|
||||
);
|
||||
|
||||
$this->_AST->setIndexBy($this->parse('IndexBy', $paramHolder));
|
||||
|
||||
$paramHolder->remove('componentAlias');
|
||||
}
|
||||
|
||||
while (
|
||||
$this->_isNextToken(Doctrine_Query_Token::T_LEFT) ||
|
||||
$this->_isNextToken(Doctrine_Query_Token::T_INNER) ||
|
||||
$this->_isNextToken(Doctrine_Query_Token::T_JOIN)
|
||||
) {
|
||||
$this->_AST->addJoinVariableDeclaration($this->parse('JoinVariableDeclaration', $paramHolder));
|
||||
}
|
||||
|
||||
// Return AST node
|
||||
return $this->_AST;
|
||||
}
|
||||
}
|
106
lib/Doctrine/Query/Parser/IndexBy.php
Normal file
106
lib/Doctrine/Query/Parser/IndexBy.php
Normal file
@ -0,0 +1,106 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* IndexBy ::= "INDEX" "BY" SimpleStateFieldPathExpression
|
||||
*
|
||||
* @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_Query_Parser_IndexBy extends Doctrine_Query_ParserRule
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// IndexBy ::= "INDEX" "BY" SimpleStateFieldPathExpression
|
||||
$this->_AST = $this->AST('IndexBy');
|
||||
|
||||
$this->_parser->match(Doctrine_Query_Token::T_INDEX);
|
||||
$this->_parser->match(Doctrine_Query_Token::T_BY);
|
||||
|
||||
$this->_AST->setSimpleStateFieldPathExpression($this->parse('SimpleStateFieldPathExpression', $paramHolder));
|
||||
}
|
||||
|
||||
|
||||
public function semantical($paramHolder)
|
||||
{
|
||||
$parserResult = $this->_parser->getParserResult();
|
||||
$componentAlias = $this->_AST->getSimpleStateFieldPathExpression()
|
||||
->getIdentificationVariable()->getComponentAlias();
|
||||
$componentFieldName = $this->_AST->getSimpleStateFieldPathExpression()
|
||||
->getSimpleStateField()->getFieldName();
|
||||
|
||||
// Check if we have same component being used in index
|
||||
if ($componentAlias !== $paramHolder->get('componentAlias')) {
|
||||
$message = "Invalid alising. Cannot index by '" . $paramHolder->get('componentAlias')
|
||||
. "' inside '" . $componentAlias . "' scope.";
|
||||
|
||||
$this->_parser->semanticalError($message);
|
||||
}
|
||||
|
||||
// Retrieving required information
|
||||
try {
|
||||
$queryComponent = $parserResult->getQueryComponent($componentAlias);
|
||||
$classMetadata = $queryComponent['metadata'];
|
||||
} catch (Doctrine_Exception $e) {
|
||||
$this->_parser->semanticalError($e->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// The INDEXBY field must be either the (primary && not part of composite pk) || (unique && notnull)
|
||||
$columnMapping = $classMetadata->getFieldMapping($componentFieldName);
|
||||
|
||||
if (
|
||||
! $classMetadata->isIdentifier($componentFieldName) &&
|
||||
! $classMetadata->isUniqueField($componentFieldName) &&
|
||||
! $classMetadata->isNotNull($componentFieldName)
|
||||
) {
|
||||
$this->_parser->semanticalError(
|
||||
"Field '" . $componentFieldName . "' of component '" . $classMetadata->getClassName() .
|
||||
"' must be unique and notnull to be used as index.",
|
||||
$this->_parser->token
|
||||
);
|
||||
}
|
||||
|
||||
if ($classMetadata->isIdentifier($componentFieldName) && $classMetadata->isIdentifierComposite()) {
|
||||
$this->_parser->semanticalError(
|
||||
"Field '" . $componentFieldName . "' of component '" . $classMetadata->getClassName() .
|
||||
"' must be primary and not part of a composite primary key to be used as index.",
|
||||
$this->_parser->token
|
||||
);
|
||||
}
|
||||
|
||||
$queryComponent['map'] = $componentFieldName;
|
||||
$parserResult->setQueryComponent($componentAlias, $queryComponent);
|
||||
|
||||
// Return AST node
|
||||
return $this->_AST;
|
||||
}
|
||||
}
|
57
lib/Doctrine/Query/Parser/QueryLanguage.php
Normal file
57
lib/Doctrine/Query/Parser/QueryLanguage.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* QueryLanguage ::= SelectStatement | UpdateStatement | DeleteStatement
|
||||
*
|
||||
* @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_Query_Parser_QueryLanguage extends Doctrine_Query_ParserRule
|
||||
{
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// QueryLanguage ::= SelectStatement | UpdateStatement | DeleteStatement
|
||||
switch ($this->_parser->lookahead['type']) {
|
||||
case Doctrine_Query_Token::T_SELECT:
|
||||
return $this->parse('SelectStatement', $paramHolder);
|
||||
break;
|
||||
|
||||
case Doctrine_Query_Token::T_UPDATE:
|
||||
return $this->parse('UpdateStatement', $paramHolder);
|
||||
break;
|
||||
|
||||
case Doctrine_Query_Token::T_DELETE:
|
||||
return $this->parse('DeleteStatement', $paramHolder);
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->_parser->syntaxError('SELECT, UPDATE or DELETE');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
98
lib/Doctrine/Query/Parser/RangeVariableDeclaration.php
Normal file
98
lib/Doctrine/Query/Parser/RangeVariableDeclaration.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable
|
||||
*
|
||||
* @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 1.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_Parser_RangeVariableDeclaration extends Doctrine_Query_ParserRule
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable
|
||||
$this->_AST = $this->AST('RangeVariableDeclaration');
|
||||
|
||||
$this->_AST->setAbstractSchemaName($this->parse('AbstractSchemaName', $paramHolder));
|
||||
|
||||
if ($this->_isNextToken(Doctrine_Query_Token::T_AS)) {
|
||||
$this->_parser->match(Doctrine_Query_Token::T_AS);
|
||||
}
|
||||
|
||||
if ($this->_isNextToken(Doctrine_Query_Token::T_IDENTIFIER)) {
|
||||
$this->_AST->setAliasIdentificationVariable($this->parse('AliasIdentificationVariable', $paramHolder));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function semantical($paramHolder)
|
||||
{
|
||||
$parserResult = $this->_parser->getParserResult();
|
||||
$componentName = $this->_AST->getAbstractSchemaName()->getComponentName();
|
||||
$componentAlias = $this->_AST->getAliasIdentificationVariable()->getComponentAlias();
|
||||
|
||||
// Check if we already have a component defined without an alias
|
||||
if ($componentAlias === null && $parserResult->hasQueryComponent($componentName)) {
|
||||
$this->_parser->semanticalError(
|
||||
"Cannot re-declare component '{$componentName}'. Please assign an alias to it."
|
||||
);
|
||||
// Define new queryComponent since it does not exist yet
|
||||
} else {
|
||||
// Retrieving ClassMetadata and Mapper
|
||||
try {
|
||||
$classMetadata = $this->_em->getClassMetadata($componentName);
|
||||
|
||||
// Building queryComponent
|
||||
$queryComponent = array(
|
||||
'metadata' => $classMetadata,
|
||||
'parent' => null,
|
||||
'relation' => null,
|
||||
'map' => null,
|
||||
'scalar' => null,
|
||||
);
|
||||
} catch (Doctrine_Exception $e) {
|
||||
$this->_parser->semanticalError($e->getMessage());
|
||||
}
|
||||
|
||||
// Inspect for possible non-aliasing
|
||||
if ($componentAlias === null) {
|
||||
$componentAlias = $componentName;
|
||||
}
|
||||
|
||||
$tableAlias = $parserResult->generateTableAlias($classMetadata->getClassName());
|
||||
$parserResult->setQueryComponent($componentAlias, $queryComponent);
|
||||
$parserResult->setTableAlias($tableAlias, $componentAlias);
|
||||
}
|
||||
|
||||
// Return AST node
|
||||
return $this->_AST;
|
||||
}
|
||||
}
|
76
lib/Doctrine/Query/Parser/SelectClause.php
Normal file
76
lib/Doctrine/Query/Parser/SelectClause.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SelectClause ::= "SELECT" ["DISTINCT"] SelectExpression {"," SelectExpression}
|
||||
*
|
||||
* @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_Query_Parser_SelectClause extends Doctrine_Query_ParserRule
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
protected $_selectExpressions = array();
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// SelectClause ::= "SELECT" ["DISTINCT"] SelectExpression {"," SelectExpression}
|
||||
$this->_AST = $this->AST('SelectClause');
|
||||
|
||||
$this->_parser->match(Doctrine_Query_Token::T_SELECT);
|
||||
|
||||
// Inspecting if we are in a DISTINCT query
|
||||
if ($this->_isNextToken(Doctrine_Query_Token::T_DISTINCT)) {
|
||||
$this->_parser->match(Doctrine_Query_Token::T_DISTINCT);
|
||||
|
||||
$this->_AST->setIsDistinct(true);
|
||||
}
|
||||
|
||||
// Process SelectExpressions (1..N)
|
||||
$this->_selectExpressions[] = $this->parse('SelectExpression', $paramHolder);
|
||||
|
||||
while ($this->_isNextToken(',')) {
|
||||
$this->_parser->match(',');
|
||||
|
||||
$this->_selectExpressions[] = $this->parse('SelectExpression', $paramHolder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function semantical($paramHolder)
|
||||
{
|
||||
// We need to validate each SelectExpression
|
||||
for ($i = 0, $l = count($this->_selectExpressions); $i < $l; $i++) {
|
||||
$this->_AST->addSelectExpression($this->_selectExpressions[$i]->semantical($paramHolder));
|
||||
}
|
||||
|
||||
// Return AST node
|
||||
return $this->_AST;
|
||||
}
|
||||
}
|
82
lib/Doctrine/Query/Parser/SelectExpression.php
Normal file
82
lib/Doctrine/Query/Parser/SelectExpression.php
Normal file
@ -0,0 +1,82 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SelectExpression ::= IdentificationVariable ["." "*"] |
|
||||
* (StateFieldPathExpression | AggregateExpression | "(" Subselect ")" )
|
||||
* [["AS"] FieldIdentificationVariable]
|
||||
*
|
||||
* @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 1.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_Parser_SelectExpression extends Doctrine_Query_ParserRule
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// SelectExpression ::= IdentificationVariable ["." "*"] |
|
||||
// (StateFieldPathExpression | AggregateExpression | "(" Subselect ")" )
|
||||
// [["AS"] FieldIdentificationVariable]
|
||||
|
||||
// First we recognize for an IdentificationVariable (Component alias)
|
||||
if ($this->_isIdentificationVariable()) {
|
||||
$identificationVariable = $this->parse('IdentificationVariable', $paramHolder);
|
||||
|
||||
// Inspecting if we are in a ["." "*"]
|
||||
if ($this->_isNextToken('.')) {
|
||||
$this->_parser->match('.');
|
||||
$this->_parser->match('*');
|
||||
}
|
||||
|
||||
return $identificationVariable;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function _isIdentificationVariable()
|
||||
{
|
||||
// Retrying to recoginize this grammar: IdentificationVariable ["." "*"]
|
||||
$token = $this->_parser->lookahead;
|
||||
$this->_parser->getScanner()->resetPeek();
|
||||
|
||||
// We have an identifier here
|
||||
if ($token['type'] === Doctrine_Query_Token::T_IDENTIFIER) {
|
||||
$token = $this->_parser->getScanner()->peek();
|
||||
|
||||
// If we have a dot ".", then next char must be the "*"
|
||||
if ($token['value'] === '.') {
|
||||
$token = $this->_parser->getScanner()->peek();
|
||||
|
||||
return $token['value'] === '*';
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
83
lib/Doctrine/Query/Parser/SelectStatement.php
Normal file
83
lib/Doctrine/Query/Parser/SelectStatement.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SelectStatement ::= SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause]
|
||||
*
|
||||
* @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_Query_Parser_SelectStatement extends Doctrine_Query_ParserRule
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
protected $_selectClause = null;
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// SelectStatement ::= SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause]
|
||||
$this->_AST = $this->AST('SelectStatement');
|
||||
|
||||
// Disable the semantical check for SelectClause now. This is needed
|
||||
// since we dont know the query components yet (will be known only
|
||||
// when the FROM and WHERE clause are processed).
|
||||
$paramHolder->set('semanticalCheck', false);
|
||||
$this->_selectClause = $this->parse('SelectClause', $paramHolder);
|
||||
$paramHolder->remove('semanticalCheck');
|
||||
|
||||
$this->_AST->setFromClause($this->parse('FromClause', $paramHolder));
|
||||
|
||||
if ($this->_isNextToken(Doctrine_Query_Token::T_WHERE)) {
|
||||
$this->_AST->setWhereClause($this->parse('WhereClause', $paramHolder));
|
||||
}
|
||||
|
||||
if ($this->_isNextToken(Doctrine_Query_Token::T_GROUP)) {
|
||||
$this->_AST->setGroupByClause($this->parse('GroupByClause', $paramHolder));
|
||||
}
|
||||
|
||||
if ($this->_isNextToken(Doctrine_Query_Token::T_HAVING)) {
|
||||
$this->_AST->setHavingClause($this->parse('HavingClause', $paramHolder));
|
||||
}
|
||||
|
||||
if ($this->_isNextToken(Doctrine_Query_Token::T_ORDER)) {
|
||||
$this->_AST->setOrderByClause($this->parse('OrderByClause', $paramHolder));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function semantical($paramHolder)
|
||||
{
|
||||
// We need to invoke the semantical check of SelectClause here, since
|
||||
// it was not yet checked.
|
||||
// The semantical checks will be forwarded to all SelectClause dependant grammar rules
|
||||
$this->_AST->setSelectClause($this->_selectClause->semantical($paramHolder));
|
||||
|
||||
// Return AST node
|
||||
return $this->_AST;
|
||||
}
|
||||
}
|
44
lib/Doctrine/Query/Parser/SimpleStateField.php
Normal file
44
lib/Doctrine/Query/Parser/SimpleStateField.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SimpleStateField ::= FieldIdentificationVariable
|
||||
*
|
||||
* @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_Query_Parser_SimpleStateField extends Doctrine_Query_ParserRule
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// SimpleStateField ::= FieldIdentificationVariable
|
||||
return $this->parse('FieldIdentificationVariable', $paramHolder);
|
||||
}
|
||||
}
|
79
lib/Doctrine/Query/Parser/SimpleStateFieldPathExpression.php
Normal file
79
lib/Doctrine/Query/Parser/SimpleStateFieldPathExpression.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SimpleStateFieldPathExpression ::= IdentificationVariable "." SimpleStateField
|
||||
*
|
||||
* @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_Query_Parser_SimpleStateFieldPathExpression extends Doctrine_Query_ParserRule
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// SimpleStateFieldPathExpression ::= IdentificationVariable "." SimpleStateField
|
||||
$this->_AST = $this->AST('SimpleStateFieldPathExpression');
|
||||
|
||||
$this->_AST->setIdentificationVariable($this->parse('IdentificationVariable', $paramHolder));
|
||||
|
||||
$this->_parser->match('.');
|
||||
|
||||
$this->_AST->setSimpleStateField($this->parse('SimpleStateField', $paramHolder));
|
||||
}
|
||||
|
||||
|
||||
public function semantical($paramHolder)
|
||||
{
|
||||
$parserResult = $this->_parser->getParserResult();
|
||||
$componentAlias = $this->_AST->getIdentificationVariable()->getComponentAlias();
|
||||
$componentFieldName = $this->_AST->getSimpleStateField()->getFieldName();
|
||||
|
||||
// We need to make sure field exists
|
||||
try {
|
||||
$queryComponent = $parserResult->getQueryComponent($componentAlias);
|
||||
$classMetadata = $queryComponent['metadata'];
|
||||
} catch (Doctrine_Exception $e) {
|
||||
$this->_parser->semanticalError($e->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($classMetadata instanceof Doctrine_ClassMetadata && ! $classMetadata->hasField($componentFieldName)) {
|
||||
$this->_parser->semanticalError(
|
||||
"Cannot use key mapping. Field '" . $componentFieldName . "' " .
|
||||
"does not exist in component '" . $classMetadata->getClassName() . "'.",
|
||||
$this->_parser->token
|
||||
);
|
||||
}
|
||||
|
||||
// Return AST node
|
||||
return $this->_AST;
|
||||
}
|
||||
}
|
53
lib/Doctrine/Query/Parser/UpdateStatement.php
Normal file
53
lib/Doctrine/Query/Parser/UpdateStatement.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* UpdateStatement ::= UpdateClause [WhereClause]
|
||||
*
|
||||
* @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_Query_Parser_UpdateStatement extends Doctrine_Query_Parser
|
||||
{
|
||||
protected $_AST = null;
|
||||
|
||||
|
||||
public function syntax($paramHolder)
|
||||
{
|
||||
// UpdateStatement ::= UpdateClause [WhereClause]
|
||||
$this->_AST = $this->AST('UpdateStatement');
|
||||
|
||||
$this->_AST->setUpdateClause($this->parse('UpdateClause', $paramHolder));
|
||||
|
||||
if ($this->_isNextToken(Doctrine_Query_Token::T_WHERE)) {
|
||||
$this->_AST->setWhereClause($this->parse('WhereClause', $paramHolder));
|
||||
}
|
||||
|
||||
// Return AST node
|
||||
return $this->_AST;
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class Doctrine_Query_ProductionParamHolder
|
||||
class Doctrine_Query_ParserParamHolder
|
||||
{
|
||||
protected static $_instance;
|
||||
|
@ -33,6 +33,13 @@
|
||||
*/
|
||||
class Doctrine_Query_ParserResult extends Doctrine_Query_AbstractResult
|
||||
{
|
||||
/**
|
||||
* The EntityManager.
|
||||
*
|
||||
* @var Doctrine_EntityManager
|
||||
*/
|
||||
protected $_em;
|
||||
|
||||
/**
|
||||
* A simple array keys representing table aliases and values table alias
|
||||
* seeds. The seeds are used for generating short table aliases.
|
||||
@ -47,6 +54,28 @@ class Doctrine_Query_ParserResult extends Doctrine_Query_AbstractResult
|
||||
* @var array $_queryFields
|
||||
*/
|
||||
protected $_queryFields = array();
|
||||
|
||||
|
||||
/**
|
||||
* Sets the Entity Manager.
|
||||
*
|
||||
* @param Doctrine_EntityManager $em The Entity Manager.
|
||||
*/
|
||||
public function setEntityManager($em)
|
||||
{
|
||||
$this->_em = $em;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the Entity Manager.
|
||||
*
|
||||
* @return Doctrine_EntityManager
|
||||
*/
|
||||
public function getEntityManager()
|
||||
{
|
||||
return $this->_em;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,7 @@
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
abstract class Doctrine_Query_Production
|
||||
abstract class Doctrine_Query_ParserRule
|
||||
{
|
||||
/**
|
||||
* @nodoc
|
||||
@ -97,27 +97,27 @@ abstract class Doctrine_Query_Production
|
||||
|
||||
|
||||
/**
|
||||
* Executes the production AST using the specified parameters.
|
||||
* Executes the grammar rule using the specified parameters.
|
||||
*
|
||||
* @param string $AstName Production AST name
|
||||
* @param string $RuleName BNF Grammar Rule name
|
||||
* @param array $paramHolder Production parameter holder
|
||||
* @return Doctrine_Query_Production
|
||||
* @return Doctrine_Query_ParserRule
|
||||
*/
|
||||
public function AST($AstName, $paramHolder)
|
||||
public function parse($RuleName, $paramHolder)
|
||||
{
|
||||
$AST = $this->_getProduction($AstName);
|
||||
$BNFGrammarRule = $this->_getGrammarRule($RuleName);
|
||||
|
||||
//echo "Processing class: " . get_class($AST) . "...\n";
|
||||
//echo "Processing class: " . get_class($BNFGrammarRule) . "...\n";
|
||||
//echo "Params: " . var_export($paramHolder, true) . "\n";
|
||||
|
||||
// Syntax check
|
||||
if ( ! $paramHolder->has('syntaxCheck') || $paramHolder->get('syntaxCheck') === true) {
|
||||
//echo "Processing syntax checks of " . $AstName . "...\n";
|
||||
//echo "Processing syntax checks of " . $RuleName . "...\n";
|
||||
|
||||
$return = $AST->syntax($paramHolder);
|
||||
$return = $BNFGrammarRule->syntax($paramHolder);
|
||||
|
||||
if ($return !== null) {
|
||||
//echo "Returning AST class: " . (is_object($return) ? get_class($return) : $return) . "...\n";
|
||||
//echo "Returning Gramma Rule class: " . (is_object($return) ? get_class($return) : $return) . "...\n";
|
||||
|
||||
return $return;
|
||||
}
|
||||
@ -125,87 +125,64 @@ abstract class Doctrine_Query_Production
|
||||
|
||||
// Semantical check
|
||||
if ( ! $paramHolder->has('semanticalCheck') || $paramHolder->get('semanticalCheck') === true) {
|
||||
//echo "Processing semantical checks of " . $AstName . "...\n";
|
||||
//echo "Processing semantical checks of " . $RuleName . "...\n";
|
||||
|
||||
$return = $AST->semantical($paramHolder);
|
||||
$return = $BNFGrammarRule->semantical($paramHolder);
|
||||
|
||||
if ($return !== null) {
|
||||
//echo "Returning AST class: " . (is_object($return) ? get_class($return) : $return) . "...\n";
|
||||
//echo "Returning Gramma Rule class: " . (is_object($return) ? get_class($return) : $return) . "...\n";
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
||||
//echo "Returning AST class: " . get_class($AST) . "...\n";
|
||||
|
||||
return $AST;
|
||||
return $BNFGrammarRule;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a production object with the given name.
|
||||
* Returns a grammar rule object with the given name.
|
||||
*
|
||||
* @param string $name production name
|
||||
* @return Doctrine_Query_Production
|
||||
* @param string $name grammar rule name
|
||||
* @return Doctrine_Query_ParserRule
|
||||
*/
|
||||
protected function _getProduction($name)
|
||||
protected function _getGrammarRule($name)
|
||||
{
|
||||
$class = 'Doctrine_Query_Production_' . $name;
|
||||
$class = 'Doctrine_Query_Parser_' . $name;
|
||||
|
||||
//echo $class . "\r\n";
|
||||
|
||||
if ( ! class_exists($class)) {
|
||||
throw new Doctrine_Query_Parser_Exception(
|
||||
"Unknown Grammar Rule '$name'. Could not find related compiler class."
|
||||
);
|
||||
}
|
||||
|
||||
return new $class($this->_parser);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes this production using the specified parameters.
|
||||
* Creates an AST node with the given name.
|
||||
*
|
||||
* @param array $paramHolder Production parameter holder
|
||||
* @return Doctrine_Query_Production
|
||||
* @param string $AstName AST node name
|
||||
* @return Doctrine_Query_AST
|
||||
*/
|
||||
public function execute($paramHolder)
|
||||
public function AST($AstName)
|
||||
{
|
||||
//echo "Processing class: " . get_class($this) . " params: \n" . var_export($paramHolder, true) . "\n";
|
||||
$class = 'Doctrine_Query_AST_' . $AstName;
|
||||
|
||||
// Syntax check
|
||||
if ( ! $paramHolder->has('syntaxCheck') || $paramHolder->get('syntaxCheck') === true) {
|
||||
//echo "Processing syntax checks of " . get_class($this) . "...\n";
|
||||
//echo $class . "\r\n";
|
||||
|
||||
$return = $this->syntax($paramHolder);
|
||||
|
||||
if ($return !== null) {
|
||||
return $return;
|
||||
}
|
||||
if ( ! class_exists($class)) {
|
||||
throw new Doctrine_Query_Parser_Exception(
|
||||
"Unknown AST node '" . $AstName . "'. Could not find related compiler class."
|
||||
);
|
||||
}
|
||||
|
||||
// Semantical check
|
||||
if ( ! $paramHolder->has('semanticalCheck') || $paramHolder->get('semanticalCheck') === true) {
|
||||
//echo "Processing semantical checks of " . get_class($this) . "...\n";
|
||||
|
||||
$return = $this->semantical($paramHolder);
|
||||
|
||||
if ($return !== null) {
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
||||
// Return AST instance
|
||||
return $this;
|
||||
return new $class($this->_parser->getParserResult());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes this sql builder using the specified parameters.
|
||||
*
|
||||
* @return string Sql piece
|
||||
*/
|
||||
/*public function buildSql()
|
||||
{
|
||||
$className = get_class($this);
|
||||
$methodName = substr($className, strrpos($className, '_'));
|
||||
|
||||
$this->_sqlBuilder->$methodName($this);
|
||||
}*/
|
||||
|
||||
|
||||
/**
|
||||
* @nodoc
|
||||
*/
|
@ -70,7 +70,6 @@ class Doctrine_Query_Production_UpdateStatement extends Doctrine_Query_Productio
|
||||
}
|
||||
|
||||
/* Getters */
|
||||
|
||||
public function getUpdateClause()
|
||||
{
|
||||
return $this->_updateClause;
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
@ -35,7 +35,7 @@ abstract class Doctrine_Query_SqlExecutor_Abstract implements Serializable
|
||||
|
||||
protected $_sqlStatements;
|
||||
|
||||
public function __construct(Doctrine_Query_Production $AST)
|
||||
public function __construct(Doctrine_Query_AST $AST)
|
||||
{
|
||||
// [TODO] Remove me later!
|
||||
//$this->AST = $AST;
|
||||
@ -66,10 +66,10 @@ abstract class Doctrine_Query_SqlExecutor_Abstract implements Serializable
|
||||
* @param Doctrine_Query_Production $AST The root node of the AST.
|
||||
* @return Doctrine_Query_SqlExecutor_Abstract The executor that is suitable for the given AST.
|
||||
*/
|
||||
public static function create(Doctrine_Query_Production $AST)
|
||||
public static function create(Doctrine_Query_AST $AST)
|
||||
{
|
||||
$isDeleteStatement = $AST instanceof Doctrine_Query_Production_DeleteStatement;
|
||||
$isUpdateStatement = $AST instanceof Doctrine_Query_Production_UpdateStatement;
|
||||
$isDeleteStatement = $AST instanceof Doctrine_Query_AST_DeleteStatement;
|
||||
$isUpdateStatement = $AST instanceof Doctrine_Query_AST_UpdateStatement;
|
||||
|
||||
if ($isUpdateStatement || $isDeleteStatement) {
|
||||
// TODO: Inspect the $AST and create the proper executor like so (pseudo-code):
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
@ -39,7 +39,7 @@ class Doctrine_Query_SqlExecutor_MultiTableDelete extends Doctrine_Query_SqlExec
|
||||
*
|
||||
* @param Doctrine_Query_Production $AST
|
||||
*/
|
||||
public function __construct(Doctrine_Query_Production $AST)
|
||||
public function __construct(Doctrine_Query_AST $AST)
|
||||
{
|
||||
// TODO: Inspect the AST, create the necessary SQL queries and store them
|
||||
// in $this->_sqlStatements
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
@ -34,7 +34,7 @@
|
||||
*/
|
||||
class Doctrine_Query_SqlExecutor_MultiTableUpdate extends Doctrine_Query_SqlExecutor_Abstract
|
||||
{
|
||||
public function __construct(Doctrine_Query_Production $AST)
|
||||
public function __construct(Doctrine_Query_AST $AST)
|
||||
{
|
||||
// TODO: Inspect the AST, create the necessary SQL queries and store them
|
||||
// in $this->_sqlStatements
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
class Doctrine_Query_SqlExecutor_SingleSelect extends Doctrine_Query_SqlExecutor_Abstract
|
||||
{
|
||||
public function __construct(Doctrine_Query_Production $AST)
|
||||
public function __construct(Doctrine_Query_AST $AST)
|
||||
{
|
||||
parent::__construct($AST);
|
||||
$this->_sqlStatements = $AST->buildSql();
|
||||
|
@ -32,7 +32,7 @@
|
||||
*/
|
||||
class Doctrine_Query_SqlExecutor_SingleTableDeleteUpdate extends Doctrine_Query_SqlExecutor_Abstract
|
||||
{
|
||||
public function __construct(Doctrine_Query_Production $AST)
|
||||
public function __construct(Doctrine_Query_AST $AST)
|
||||
{
|
||||
parent::__construct($AST);
|
||||
$this->_sqlStatements = $AST->buildSql();
|
||||
|
@ -1,151 +1,153 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Container for token type constants of Doctrine Query Language.
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @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$
|
||||
*/
|
||||
final class Doctrine_Query_Token
|
||||
{
|
||||
const T_NONE = 1;
|
||||
const T_IDENTIFIER = 2;
|
||||
const T_INTEGER = 3;
|
||||
const T_STRING = 4;
|
||||
const T_INPUT_PARAMETER = 5;
|
||||
const T_FLOAT = 6;
|
||||
|
||||
const T_ALL = 101;
|
||||
const T_AND = 102;
|
||||
const T_ANY = 103;
|
||||
const T_AS = 104;
|
||||
const T_ASC = 105;
|
||||
const T_AVG = 106;
|
||||
const T_BETWEEN = 107;
|
||||
const T_BY = 108;
|
||||
const T_COUNT = 109;
|
||||
const T_DELETE = 110;
|
||||
const T_DESC = 111;
|
||||
const T_DISTINCT = 112;
|
||||
const T_ESCAPE = 113;
|
||||
const T_EXISTS = 114;
|
||||
const T_FROM = 115;
|
||||
const T_GROUP = 116;
|
||||
const T_HAVING = 117;
|
||||
const T_IN = 118;
|
||||
const T_INDEX = 119;
|
||||
const T_INNER = 120;
|
||||
const T_IS = 121;
|
||||
const T_JOIN = 122;
|
||||
const T_LEFT = 123;
|
||||
const T_LIKE = 124;
|
||||
const T_LIMIT = 125;
|
||||
const T_MAX = 126;
|
||||
const T_MIN = 127;
|
||||
const T_MOD = 128;
|
||||
const T_NOT = 129;
|
||||
const T_NULL = 130;
|
||||
const T_OFFSET = 131;
|
||||
const T_ON = 132;
|
||||
const T_OR = 133;
|
||||
const T_ORDER = 134;
|
||||
const T_SELECT = 135;
|
||||
const T_SET = 136;
|
||||
const T_SIZE = 137;
|
||||
const T_SOME = 138;
|
||||
const T_SUM = 139;
|
||||
const T_UPDATE = 140;
|
||||
const T_WHERE = 141;
|
||||
const T_WITH = 142;
|
||||
|
||||
const T_TRUE = 143;
|
||||
const T_FALSE = 144;
|
||||
|
||||
|
||||
protected $_keywordsTable = array();
|
||||
|
||||
|
||||
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_COUNT, "COUNT");
|
||||
$this->addKeyword(self::T_DELETE, "DELETE");
|
||||
$this->addKeyword(self::T_DESC, "DESC");
|
||||
$this->addKeyword(self::T_DISTINCT, "DISTINCT");
|
||||
$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_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");
|
||||
}
|
||||
|
||||
|
||||
protected function addKeyword($token, $value)
|
||||
{
|
||||
$this->_keywordsTable[$token] = $value;
|
||||
}
|
||||
|
||||
|
||||
public function getLiteral($token)
|
||||
{
|
||||
return isset($this->_keywordsTable[$token]) ? $this->_keywordsTable[$token] : '';
|
||||
}
|
||||
}
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Container for token type constants of Doctrine Query Language.
|
||||
*
|
||||
* @package Doctrine
|
||||
* @subpackage Query
|
||||
* @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$
|
||||
*/
|
||||
final class Doctrine_Query_Token
|
||||
{
|
||||
const T_NONE = 1;
|
||||
const T_IDENTIFIER = 2;
|
||||
const T_INTEGER = 3;
|
||||
const T_STRING = 4;
|
||||
const T_INPUT_PARAMETER = 5;
|
||||
const T_FLOAT = 6;
|
||||
|
||||
const T_ALL = 101;
|
||||
const T_AND = 102;
|
||||
const T_ANY = 103;
|
||||
const T_AS = 104;
|
||||
const T_ASC = 105;
|
||||
const T_AVG = 106;
|
||||
const T_BETWEEN = 107;
|
||||
const T_BY = 108;
|
||||
const T_COUNT = 109;
|
||||
const T_DELETE = 110;
|
||||
const T_DESC = 111;
|
||||
const T_DISTINCT = 112;
|
||||
const T_ESCAPE = 113;
|
||||
const T_EXISTS = 114;
|
||||
const T_FROM = 115;
|
||||
const T_GROUP = 116;
|
||||
const T_HAVING = 117;
|
||||
const T_IN = 118;
|
||||
const T_INDEX = 119;
|
||||
const T_INNER = 120;
|
||||
const T_IS = 121;
|
||||
const T_JOIN = 122;
|
||||
const T_LEFT = 123;
|
||||
const T_LIKE = 124;
|
||||
const T_LIMIT = 125;
|
||||
const T_MAX = 126;
|
||||
const T_MIN = 127;
|
||||
const T_MOD = 128;
|
||||
const T_NOT = 129;
|
||||
const T_NULL = 130;
|
||||
const T_OFFSET = 131;
|
||||
const T_ON = 132;
|
||||
const T_OR = 133;
|
||||
const T_ORDER = 134;
|
||||
const T_SELECT = 135;
|
||||
const T_SET = 136;
|
||||
const T_SIZE = 137;
|
||||
const T_SOME = 138;
|
||||
const T_SUM = 139;
|
||||
const T_UPDATE = 140;
|
||||
const T_WHERE = 141;
|
||||
const T_WITH = 142;
|
||||
|
||||
const T_TRUE = 143;
|
||||
const T_FALSE = 144;
|
||||
|
||||
|
||||
protected $_keywordsTable = array();
|
||||
|
||||
|
||||
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_COUNT, "COUNT");
|
||||
$this->addKeyword(self::T_DELETE, "DELETE");
|
||||
$this->addKeyword(self::T_DESC, "DESC");
|
||||
$this->addKeyword(self::T_DISTINCT, "DISTINCT");
|
||||
$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_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");
|
||||
}
|
||||
|
||||
|
||||
protected function addKeyword($token, $value)
|
||||
{
|
||||
$this->_keywordsTable[$token] = $value;
|
||||
}
|
||||
|
||||
|
||||
public function getLiteral($token)
|
||||
{
|
||||
return isset($this->_keywordsTable[$token])
|
||||
? $this->_keywordsTable[$token]
|
||||
: (is_string($token) ? $token : '');
|
||||
}
|
||||
}
|
||||
|
@ -1,250 +1,257 @@
|
||||
/* Context-free grammar for Doctrine Query Language
|
||||
*
|
||||
* Document syntax:
|
||||
* - non-terminals begin with an upper case character
|
||||
* - terminals begin with a lower case character
|
||||
* - parentheses (...) are used for grouping
|
||||
* - square brackets [...] are used for defining an optional part, eg. zero or
|
||||
* one time
|
||||
* - curly brackets {...} are used for repetion, eg. zero or more times
|
||||
* - double quotation marks "..." define a terminal string
|
||||
* - a vertical bar | represents an alternative
|
||||
*
|
||||
* At a first glance we'll support SQL-99 based queries
|
||||
* Initially Select and Sub-select DQL will not support LIMIT and OFFSET (due to limit-subquery algorithm)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* TERMINALS
|
||||
*
|
||||
* identifier (name, email, ...)
|
||||
* string ('foo', 'bar''s house', '%ninja%', ...)
|
||||
* char ('/', '\\', ' ', ...)
|
||||
* integer (-1, 0, 1, 34, ...)
|
||||
* float (-0.23, 0.007, 1.245342E+8, ...)
|
||||
* boolean (false, true)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* QUERY LANGUAGE (START)
|
||||
*/
|
||||
QueryLanguage ::= SelectStatement | UpdateStatement | DeleteStatement
|
||||
|
||||
|
||||
/*
|
||||
* STATEMENTS
|
||||
*/
|
||||
SelectStatement ::= SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause]
|
||||
UpdateStatement ::= UpdateClause [WhereClause]
|
||||
DeleteStatement ::= DeleteClause [WhereClause]
|
||||
|
||||
|
||||
/*
|
||||
* IDENTIFIERS
|
||||
*/
|
||||
IdentificationVariable ::= identifier
|
||||
|
||||
/* identifier that must be a class name */
|
||||
AbstractSchemaName ::= identifier
|
||||
|
||||
/* identifier that must be a field */
|
||||
FieldIdentificationVariable ::= identifier
|
||||
|
||||
/* identifier that must be a collection-valued association field (to-many) */
|
||||
CollectionValuedAssociationField ::= FieldIdentificationVariable
|
||||
|
||||
/* identifier that must be a single-valued association field (to-one) */
|
||||
SingleValuedAssociationField ::= FieldIdentificationVariable
|
||||
|
||||
/* identifier that must be an embedded class state field (for the future) */
|
||||
EmbeddedClassStateField ::= FieldIdentificationVariable
|
||||
|
||||
/* identifier that must be a simple state field (name, email, ...) */
|
||||
SimpleStateField ::= FieldIdentificationVariable
|
||||
|
||||
|
||||
/*
|
||||
* PATH EXPRESSIONS
|
||||
*/
|
||||
JoinAssociationPathExpression ::= JoinCollectionValuedPathExpression | JoinSingleValuedAssociationPathExpression
|
||||
JoinCollectionValuedPathExpression ::= IdentificationVariable "." CollectionValuedAssociationField
|
||||
JoinSingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField
|
||||
AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression
|
||||
SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression
|
||||
StateFieldPathExpression ::= {IdentificationVariable | SingleValuedAssociationPathExpression} "." StateField
|
||||
SingleValuedAssociationPathExpression ::= IdentificationVariable "." {SingleValuedAssociationField "."}* SingleValuedAssociationField
|
||||
CollectionValuedPathExpression ::= IdentificationVariable "." {SingleValuedAssociationField "."}* CollectionValuedAssociationField
|
||||
StateField ::= {EmbeddedClassStateField "."}* SimpleStateField
|
||||
|
||||
|
||||
/*
|
||||
* CLAUSES
|
||||
*/
|
||||
SelectClause ::= "SELECT" ["ALL" | "DISTINCT"] SelectExpression {"," SelectExpression}*
|
||||
SimpleSelectClause ::= "SELECT" ["ALL" | "DISTINCT"] SimpleSelectExpression
|
||||
DeleteClause ::= "DELETE" ["FROM"] AbstractSchemaName [["AS"] IdentificationVariable]
|
||||
WhereClause ::= "WHERE" ConditionalExpression
|
||||
FromClause ::= "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration}*
|
||||
SubselectFromClause ::= "FROM" SubselectIdentificationVariableDeclaration {"," SubselectIdentificationVariableDeclaration}*
|
||||
HavingClause ::= "HAVING" ConditionalExpression
|
||||
GroupByClause ::= "GROUP" "BY" GroupByItem {"," GroupByItem}*
|
||||
OrderByClause ::= "ORDER" "BY" OrderByItem {"," OrderByItem}*
|
||||
LimitClause ::= "LIMIT" integer
|
||||
OffsetClause ::= "OFFSET" integer
|
||||
UpdateClause ::= "UPDATE" AbstractSchemaName [["AS"] IdentificationVariable] "SET" UpdateItem {"," UpdateItem}*
|
||||
Subselect ::= SimpleSelectClause SubselectFromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause]
|
||||
|
||||
|
||||
/*
|
||||
* ITEMS
|
||||
*/
|
||||
OrderByItem ::= StateFieldPathExpression ["ASC" | "DESC"]
|
||||
GroupByItem ::= SingleValuedPathExpression
|
||||
UpdateItem ::= [IdentificationVariable"."]{StateField | SingleValuedAssociationField} "=" NewValue
|
||||
NewValue ::= SimpleArithmeticExpression | StringPrimary | DatetimePrimary | BooleanPrimary |
|
||||
EnumPrimary | SimpleEntityExpression | "NULL"
|
||||
|
||||
|
||||
/*
|
||||
* FROM/JOIN/INDEX BY
|
||||
*/
|
||||
IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {JoinVariableDeclaration}*
|
||||
SubselectIdentificationVariableDeclaration ::= IdentificationVariableDeclaration | AssociationPathExpression
|
||||
["AS"] IdentificationVariable
|
||||
JoinVariableDeclaration ::= Join [IndexBy]
|
||||
RangeVariableDeclaration ::= AbstractSchemaName ["AS"] IdentificationVariable
|
||||
Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" JoinAssociationPathExpression
|
||||
["AS"] IdentificationVariable [("ON" | "WITH") ConditionalExpression]
|
||||
IndexBy ::= "INDEX" "BY" StateFieldPathExpression
|
||||
|
||||
|
||||
/*
|
||||
* SELECT EXPRESSION
|
||||
*/
|
||||
SelectExpression ::= IdentificationVariable ["." "*"] |
|
||||
(StateFieldPathExpression | AggregateExpression |
|
||||
"(" Subselect ")" ) [["AS"] FieldIdentificationVariable]
|
||||
SimpleSelectExpression ::= SingleValuedPathExpression | IdentificationVariable | AggregateExpression
|
||||
|
||||
|
||||
/*
|
||||
* CONDITIONAL EXPRESSIONS
|
||||
*/
|
||||
ConditionalExpression ::= ConditionalTerm | ConditionalExpression "OR" ConditionalTerm
|
||||
ConditionalTerm ::= ConditionalFactor | ConditionalTerm "AND" ConditionalFactor
|
||||
ConditionalFactor ::= ["NOT"] ConditionalPrimary
|
||||
ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")"
|
||||
SimpleConditionalExpression ::= ComparisonExpression | BetweenExpression | LikeExpression |
|
||||
InExpression | NullComparisonExpression | ExistsExpression |
|
||||
EmptyCollectionComparisonExpression | CollectionMemberExpression
|
||||
/* EmptyCollectionComparisonExpression and CollectionMemberExpression are for the future */
|
||||
|
||||
|
||||
/*
|
||||
* COLLECTION EXPRESSIONS (FOR THE FUTURE)
|
||||
*/
|
||||
EmptyCollectionComparisonExpression ::= CollectionValuedPathExpression "IS" ["NOT"] "EMPTY"
|
||||
CollectionMemberExpression ::= EntityExpression ["NOT"] "MEMBER" ["OF"] CollectionValuedPathExpression
|
||||
|
||||
|
||||
/*
|
||||
* LITERAL VALUES
|
||||
*/
|
||||
Literal ::= string | char | integer | float | boolean | InputParameter
|
||||
|
||||
|
||||
/*
|
||||
* INPUT PARAMETER
|
||||
*/
|
||||
InputParameter ::= PositionalParameter | NamedParameter
|
||||
PositionalParameter ::= "?" integer
|
||||
NamedParameter ::= ":" string
|
||||
|
||||
|
||||
/*
|
||||
* ARITHMETIC EXPRESSIONS
|
||||
*/
|
||||
ArithmeticExpression ::= SimpleArithmeticExpression | "(" Subselect ")"
|
||||
SimpleArithmeticExpression ::= ArithmeticTerm | SimpleArithmeticExpression ("+"|"-") ArithmeticTerm
|
||||
ArithmeticTerm ::= ArithmeticFactor | ArithmeticTerm ("*" |"/") ArithmeticFactor
|
||||
ArithmeticFactor ::= [("+" | "-")] ArithmeticPrimary
|
||||
ArithmeticPrimary ::= StateFieldPathExpression | Literal | "(" SimpleArithmeticExpression ")" | Function | AggregateExpression
|
||||
|
||||
|
||||
/*
|
||||
* STRING/BOOLEAN/DATE/ENTITY/ENUM EXPRESSIONS
|
||||
*/
|
||||
StringExpression ::= StringPrimary | "(" Subselect ")"
|
||||
StringPrimary ::= StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression
|
||||
BooleanExpression ::= BooleanPrimary | "(" Subselect ")"
|
||||
BooleanPrimary ::= StateFieldPathExpression | boolean | InputParameter
|
||||
EnumExpression ::= EnumPrimary | "(" Subselect ")"
|
||||
EnumPrimary ::= StateFieldPathExpression | string | InputParameter
|
||||
EntityExpression ::= SingleValuedAssociationPathExpression | SimpleEntityExpression
|
||||
SimpleEntityExpression ::= IdentificationVariable | InputParameter
|
||||
DatetimeExpression ::= DatetimePrimary | "(" Subselect ")"
|
||||
DatetimePrimary ::= StateFieldPathExpression | InputParameter | FunctionsReturningDatetime | AggregateExpression
|
||||
|
||||
|
||||
/*
|
||||
* AGGREGATE EXPRESSION
|
||||
*/
|
||||
AggregateExpression ::= ("AVG" | "MAX" | "MIN" | "SUM") "(" ["DISTINCT"] StateFieldPathExpression ")" |
|
||||
"COUNT" "(" ["DISTINCT"] (IdentificationVariable | SingleValuedAssociationPathExpression | StateFieldPathExpression) ")"
|
||||
|
||||
|
||||
/*
|
||||
* QUANTIFIED/BETWEEN/COMPARISON/LIKE/NULL/EXISTS EXPRESSIONS
|
||||
*/
|
||||
QuantifiedExpression ::= ("ALL" | "ANY" | "SOME") "(" Subselect ")"
|
||||
BetweenExpression ::= ArithmeticExpression ["NOT"] "BETWEEN" ArithmeticExpression "AND" ArithmeticExpression
|
||||
ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression ) |
|
||||
StringExpression ComparisonOperator (StringExpression | QuantifiedExpression) |
|
||||
BooleanExpression ("=" | "<>") (BooleanExpression | QuantifiedExpression) |
|
||||
EnumExpression ("=" | "<>") (EnumExpression | QuantifiedExpression) |
|
||||
DatetimeExpression ComparisonOperator (DatetimeExpression | QuantifiedExpression) |
|
||||
EntityExpression ("=" | "<>") (EntityExpression | QuantifiedExpression)
|
||||
InExpression ::= StateFieldPathExpression ["NOT"] "IN" "(" (Literal {"," Literal}* | Subselect) ")"
|
||||
LikeExpression ::= ["NOT"] "LIKE" string ["ESCAPE" char]
|
||||
NullComparisonExpression ::= (SingleValuedPathExpression | InputParameter) "IS" ["NOT"] "NULL"
|
||||
ExistsExpression ::= ["NOT"] "EXISTS" "(" Subselect ")"
|
||||
ComparisonOperator ::= "=" | "<" | "<=" | "<>" | ">" | ">=" | "!="
|
||||
|
||||
|
||||
/*
|
||||
* FUNCTIONS
|
||||
*/
|
||||
FunctionsReturningStrings ::= PortableFunctionsReturningStrings | OtherFunctionsReturningStrings
|
||||
FunctionsReturningNumerics ::= PortableFunctionsReturningNumerics | OtherFunctionsReturningNumerics
|
||||
FunctionsReturningDateTime ::= PortableFunctionsReturningDateTime | OtherFunctionsReturningDateTime
|
||||
|
||||
|
||||
/*
|
||||
* OTHER FUNCTIONS: List of all allowed (but not portable) functions here.
|
||||
*/
|
||||
OtherFunctionsReturningStrings ::= ...
|
||||
OtherFunctionsReturningNumerics ::= ...
|
||||
OtherFunctionsReturningDateTime ::= ...
|
||||
|
||||
|
||||
/*
|
||||
* PORTABLE FUNCTIONS: List all portable functions here
|
||||
* @TODO add all supported portable functions here
|
||||
*/
|
||||
PortableFunctionsReturningNumerics ::=
|
||||
"LENGTH" "(" StringPrimary ")" |
|
||||
"LOCATE" "(" StringPrimary "," StringPrimary ["," SimpleArithmeticExpression]")" |
|
||||
"ABS" "(" SimpleArithmeticExpression ")" | "SQRT" "(" SimpleArithmeticExpression ")" |
|
||||
"MOD" "(" SimpleArithmeticExpression "," SimpleArithmeticExpression ")" |
|
||||
"SIZE" "(" CollectionValuedPathExpression ")"
|
||||
|
||||
PortableFunctionsReturningDateTime ::= "CURRENT_DATE" | "CURRENT_TIME" | "CURRENT_TIMESTAMP"
|
||||
|
||||
PortableFunctionsReturningStrings ::=
|
||||
"CONCAT" "(" StringPrimary "," StringPrimary ")" |
|
||||
"SUBSTRING" "(" StringPrimary "," SimpleArithmeticExpression "," SimpleArithmeticExpression ")" |
|
||||
"TRIM" "(" [["LEADING" | "TRAILING" | "BOTH"] [char] "FROM"] StringPrimary ")" |
|
||||
"LOWER" "(" StringPrimary ")" |
|
||||
/* Context-free grammar for Doctrine Query Language
|
||||
*
|
||||
* Document syntax:
|
||||
* - non-terminals begin with an upper case character
|
||||
* - terminals begin with a lower case character
|
||||
* - parentheses (...) are used for grouping
|
||||
* - square brackets [...] are used for defining an optional part, eg. zero or
|
||||
* one time
|
||||
* - curly brackets {...} are used for repetion, eg. zero or more times
|
||||
* - double quotation marks "..." define a terminal string
|
||||
* - a vertical bar | represents an alternative
|
||||
*
|
||||
* At a first glance we'll support SQL-99 based queries
|
||||
* Initially Select and Sub-select DQL will not support LIMIT and OFFSET (due to limit-subquery algorithm)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* TERMINALS
|
||||
*
|
||||
* identifier (name, email, ...)
|
||||
* string ('foo', 'bar''s house', '%ninja%', ...)
|
||||
* char ('/', '\\', ' ', ...)
|
||||
* integer (-1, 0, 1, 34, ...)
|
||||
* float (-0.23, 0.007, 1.245342E+8, ...)
|
||||
* boolean (false, true)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* QUERY LANGUAGE (START)
|
||||
*/
|
||||
QueryLanguage ::= SelectStatement | UpdateStatement | DeleteStatement
|
||||
|
||||
|
||||
/*
|
||||
* STATEMENTS
|
||||
*/
|
||||
SelectStatement ::= SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause]
|
||||
UpdateStatement ::= UpdateClause [WhereClause]
|
||||
DeleteStatement ::= DeleteClause [WhereClause]
|
||||
|
||||
|
||||
/*
|
||||
* IDENTIFIERS
|
||||
*/
|
||||
|
||||
/* Alias Identification usage */
|
||||
IdentificationVariable ::= identifier
|
||||
|
||||
/* Alias Identification declaration */
|
||||
AliasIdentificationVariable :: = identifier
|
||||
|
||||
/* identifier that must be a class name */
|
||||
AbstractSchemaName ::= identifier
|
||||
|
||||
/* identifier that must be a field */
|
||||
FieldIdentificationVariable ::= identifier
|
||||
|
||||
/* identifier that must be a collection-valued association field (to-many) */
|
||||
CollectionValuedAssociationField ::= FieldIdentificationVariable
|
||||
|
||||
/* identifier that must be a single-valued association field (to-one) */
|
||||
SingleValuedAssociationField ::= FieldIdentificationVariable
|
||||
|
||||
/* identifier that must be an embedded class state field (for the future) */
|
||||
EmbeddedClassStateField ::= FieldIdentificationVariable
|
||||
|
||||
/* identifier that must be a simple state field (name, email, ...) */
|
||||
SimpleStateField ::= FieldIdentificationVariable
|
||||
|
||||
|
||||
/*
|
||||
* PATH EXPRESSIONS
|
||||
*/
|
||||
JoinAssociationPathExpression ::= JoinCollectionValuedPathExpression | JoinSingleValuedAssociationPathExpression
|
||||
JoinCollectionValuedPathExpression ::= IdentificationVariable "." CollectionValuedAssociationField
|
||||
JoinSingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField
|
||||
AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression
|
||||
SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression
|
||||
StateFieldPathExpression ::= SimpleStateFieldPathExpression | SimpleStateFieldAssociationPathExpression
|
||||
SingleValuedAssociationPathExpression ::= IdentificationVariable "." {SingleValuedAssociationField "."}* SingleValuedAssociationField
|
||||
CollectionValuedPathExpression ::= IdentificationVariable "." {SingleValuedAssociationField "."}* CollectionValuedAssociationField
|
||||
StateField ::= {EmbeddedClassStateField "."}* SimpleStateField
|
||||
SimpleStateFieldPathExpression ::= IdentificationVariable "." SimpleStateField
|
||||
SimpleStateFieldAssociationPathExpression ::= SingleValuedAssociationPathExpression "." StateField
|
||||
|
||||
|
||||
/*
|
||||
* CLAUSES
|
||||
*/
|
||||
SelectClause ::= "SELECT" ["ALL" | "DISTINCT"] SelectExpression {"," SelectExpression}*
|
||||
SimpleSelectClause ::= "SELECT" ["ALL" | "DISTINCT"] SimpleSelectExpression
|
||||
DeleteClause ::= "DELETE" ["FROM"] AbstractSchemaName [["AS"] AliasIdentificationVariable]
|
||||
WhereClause ::= "WHERE" ConditionalExpression
|
||||
FromClause ::= "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration}*
|
||||
SubselectFromClause ::= "FROM" SubselectIdentificationVariableDeclaration {"," SubselectIdentificationVariableDeclaration}*
|
||||
HavingClause ::= "HAVING" ConditionalExpression
|
||||
GroupByClause ::= "GROUP" "BY" GroupByItem {"," GroupByItem}*
|
||||
OrderByClause ::= "ORDER" "BY" OrderByItem {"," OrderByItem}*
|
||||
LimitClause ::= "LIMIT" integer
|
||||
OffsetClause ::= "OFFSET" integer
|
||||
UpdateClause ::= "UPDATE" AbstractSchemaName [["AS"] AliasIdentificationVariable] "SET" UpdateItem {"," UpdateItem}*
|
||||
Subselect ::= SimpleSelectClause SubselectFromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause]
|
||||
|
||||
|
||||
/*
|
||||
* ITEMS
|
||||
*/
|
||||
OrderByItem ::= StateFieldPathExpression ["ASC" | "DESC"]
|
||||
GroupByItem ::= SingleValuedPathExpression
|
||||
UpdateItem ::= [IdentificationVariable"."]{StateField | SingleValuedAssociationField} "=" NewValue
|
||||
NewValue ::= SimpleArithmeticExpression | StringPrimary | DatetimePrimary | BooleanPrimary |
|
||||
EnumPrimary | SimpleEntityExpression | "NULL"
|
||||
|
||||
|
||||
/*
|
||||
* FROM/JOIN/INDEX BY
|
||||
*/
|
||||
IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {JoinVariableDeclaration}*
|
||||
SubselectIdentificationVariableDeclaration ::= IdentificationVariableDeclaration | AssociationPathExpression
|
||||
["AS"] AliasIdentificationVariable
|
||||
JoinVariableDeclaration ::= Join [IndexBy]
|
||||
RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable
|
||||
Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" JoinAssociationPathExpression
|
||||
["AS"] AliasIdentificationVariable [("ON" | "WITH") ConditionalExpression]
|
||||
IndexBy ::= "INDEX" "BY" SimpleStateFieldPathExpression
|
||||
|
||||
|
||||
/*
|
||||
* SELECT EXPRESSION
|
||||
*/
|
||||
SelectExpression ::= IdentificationVariable ["." "*"] |
|
||||
(StateFieldPathExpression | AggregateExpression |
|
||||
"(" Subselect ")" ) [["AS"] FieldIdentificationVariable]
|
||||
SimpleSelectExpression ::= SingleValuedPathExpression | IdentificationVariable | AggregateExpression
|
||||
|
||||
|
||||
/*
|
||||
* CONDITIONAL EXPRESSIONS
|
||||
*/
|
||||
ConditionalExpression ::= ConditionalTerm | ConditionalExpression "OR" ConditionalTerm
|
||||
ConditionalTerm ::= ConditionalFactor | ConditionalTerm "AND" ConditionalFactor
|
||||
ConditionalFactor ::= ["NOT"] ConditionalPrimary
|
||||
ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")"
|
||||
SimpleConditionalExpression ::= ComparisonExpression | BetweenExpression | LikeExpression |
|
||||
InExpression | NullComparisonExpression | ExistsExpression |
|
||||
EmptyCollectionComparisonExpression | CollectionMemberExpression
|
||||
/* EmptyCollectionComparisonExpression and CollectionMemberExpression are for the future */
|
||||
|
||||
|
||||
/*
|
||||
* COLLECTION EXPRESSIONS (FOR THE FUTURE)
|
||||
*/
|
||||
EmptyCollectionComparisonExpression ::= CollectionValuedPathExpression "IS" ["NOT"] "EMPTY"
|
||||
CollectionMemberExpression ::= EntityExpression ["NOT"] "MEMBER" ["OF"] CollectionValuedPathExpression
|
||||
|
||||
|
||||
/*
|
||||
* LITERAL VALUES
|
||||
*/
|
||||
Literal ::= string | char | integer | float | boolean | InputParameter
|
||||
|
||||
|
||||
/*
|
||||
* INPUT PARAMETER
|
||||
*/
|
||||
InputParameter ::= PositionalParameter | NamedParameter
|
||||
PositionalParameter ::= "?" integer
|
||||
NamedParameter ::= ":" string
|
||||
|
||||
|
||||
/*
|
||||
* ARITHMETIC EXPRESSIONS
|
||||
*/
|
||||
ArithmeticExpression ::= SimpleArithmeticExpression | "(" Subselect ")"
|
||||
SimpleArithmeticExpression ::= ArithmeticTerm | SimpleArithmeticExpression ("+"|"-") ArithmeticTerm
|
||||
ArithmeticTerm ::= ArithmeticFactor | ArithmeticTerm ("*" |"/") ArithmeticFactor
|
||||
ArithmeticFactor ::= [("+" | "-")] ArithmeticPrimary
|
||||
ArithmeticPrimary ::= StateFieldPathExpression | Literal | "(" SimpleArithmeticExpression ")" | Function | AggregateExpression
|
||||
|
||||
|
||||
/*
|
||||
* STRING/BOOLEAN/DATE/ENTITY/ENUM EXPRESSIONS
|
||||
*/
|
||||
StringExpression ::= StringPrimary | "(" Subselect ")"
|
||||
StringPrimary ::= StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression
|
||||
BooleanExpression ::= BooleanPrimary | "(" Subselect ")"
|
||||
BooleanPrimary ::= StateFieldPathExpression | boolean | InputParameter
|
||||
EnumExpression ::= EnumPrimary | "(" Subselect ")"
|
||||
EnumPrimary ::= StateFieldPathExpression | string | InputParameter
|
||||
EntityExpression ::= SingleValuedAssociationPathExpression | SimpleEntityExpression
|
||||
SimpleEntityExpression ::= IdentificationVariable | InputParameter
|
||||
DatetimeExpression ::= DatetimePrimary | "(" Subselect ")"
|
||||
DatetimePrimary ::= StateFieldPathExpression | InputParameter | FunctionsReturningDatetime | AggregateExpression
|
||||
|
||||
|
||||
/*
|
||||
* AGGREGATE EXPRESSION
|
||||
*/
|
||||
AggregateExpression ::= ("AVG" | "MAX" | "MIN" | "SUM") "(" ["DISTINCT"] StateFieldPathExpression ")" |
|
||||
"COUNT" "(" ["DISTINCT"] (IdentificationVariable | SingleValuedAssociationPathExpression | StateFieldPathExpression) ")"
|
||||
|
||||
|
||||
/*
|
||||
* QUANTIFIED/BETWEEN/COMPARISON/LIKE/NULL/EXISTS EXPRESSIONS
|
||||
*/
|
||||
QuantifiedExpression ::= ("ALL" | "ANY" | "SOME") "(" Subselect ")"
|
||||
BetweenExpression ::= ArithmeticExpression ["NOT"] "BETWEEN" ArithmeticExpression "AND" ArithmeticExpression
|
||||
ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression ) |
|
||||
StringExpression ComparisonOperator (StringExpression | QuantifiedExpression) |
|
||||
BooleanExpression ("=" | "<>" | "!=") (BooleanExpression | QuantifiedExpression) |
|
||||
EnumExpression ("=" | "<>" | "!=") (EnumExpression | QuantifiedExpression) |
|
||||
DatetimeExpression ComparisonOperator (DatetimeExpression | QuantifiedExpression) |
|
||||
EntityExpression ("=" | "<>") (EntityExpression | QuantifiedExpression)
|
||||
InExpression ::= StateFieldPathExpression ["NOT"] "IN" "(" (Literal {"," Literal}* | Subselect) ")"
|
||||
LikeExpression ::= ["NOT"] "LIKE" string ["ESCAPE" char]
|
||||
NullComparisonExpression ::= (SingleValuedPathExpression | InputParameter) "IS" ["NOT"] "NULL"
|
||||
ExistsExpression ::= ["NOT"] "EXISTS" "(" Subselect ")"
|
||||
ComparisonOperator ::= "=" | "<" | "<=" | "<>" | ">" | ">=" | "!="
|
||||
|
||||
|
||||
/*
|
||||
* FUNCTIONS
|
||||
*/
|
||||
FunctionsReturningStrings ::= PortableFunctionsReturningStrings | OtherFunctionsReturningStrings
|
||||
FunctionsReturningNumerics ::= PortableFunctionsReturningNumerics | OtherFunctionsReturningNumerics
|
||||
FunctionsReturningDateTime ::= PortableFunctionsReturningDateTime | OtherFunctionsReturningDateTime
|
||||
|
||||
|
||||
/*
|
||||
* OTHER FUNCTIONS: List of all allowed (but not portable) functions here.
|
||||
*/
|
||||
OtherFunctionsReturningStrings ::= ...
|
||||
OtherFunctionsReturningNumerics ::= ...
|
||||
OtherFunctionsReturningDateTime ::= ...
|
||||
|
||||
|
||||
/*
|
||||
* PORTABLE FUNCTIONS: List all portable functions here
|
||||
* @TODO add all supported portable functions here
|
||||
*/
|
||||
PortableFunctionsReturningNumerics ::=
|
||||
"LENGTH" "(" StringPrimary ")" |
|
||||
"LOCATE" "(" StringPrimary "," StringPrimary ["," SimpleArithmeticExpression]")" |
|
||||
"ABS" "(" SimpleArithmeticExpression ")" | "SQRT" "(" SimpleArithmeticExpression ")" |
|
||||
"MOD" "(" SimpleArithmeticExpression "," SimpleArithmeticExpression ")" |
|
||||
"SIZE" "(" CollectionValuedPathExpression ")"
|
||||
|
||||
PortableFunctionsReturningDateTime ::= "CURRENT_DATE" | "CURRENT_TIME" | "CURRENT_TIMESTAMP"
|
||||
|
||||
PortableFunctionsReturningStrings ::=
|
||||
"CONCAT" "(" StringPrimary "," StringPrimary ")" |
|
||||
"SUBSTRING" "(" StringPrimary "," SimpleArithmeticExpression "," SimpleArithmeticExpression ")" |
|
||||
"TRIM" "(" [["LEADING" | "TRAILING" | "BOTH"] [char] "FROM"] StringPrimary ")" |
|
||||
"LOWER" "(" StringPrimary ")" |
|
||||
"UPPER" "(" StringPrimary ")"
|
@ -25,12 +25,12 @@ class Orm_Query_AllTests
|
||||
$suite = new Doctrine_TestSuite('Doctrine Orm Query');
|
||||
|
||||
$suite->addTestSuite('Orm_Query_IdentifierRecognitionTest');
|
||||
$suite->addTestSuite('Orm_Query_LanguageRecognitionTest');
|
||||
/*$suite->addTestSuite('Orm_Query_LanguageRecognitionTest');
|
||||
$suite->addTestSuite('Orm_Query_ScannerTest');
|
||||
$suite->addTestSuite('Orm_Query_DqlGenerationTest');
|
||||
$suite->addTestSuite('Orm_Query_DeleteSqlGenerationTest');
|
||||
$suite->addTestSuite('Orm_Query_UpdateSqlGenerationTest');
|
||||
$suite->addTestSuite('Orm_Query_SelectSqlGenerationTest');
|
||||
$suite->addTestSuite('Orm_Query_SelectSqlGenerationTest');*/
|
||||
|
||||
return $suite;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ class Orm_Query_IdentifierRecognitionTest extends Doctrine_OrmTestCase
|
||||
public function testSingleAliasDeclarationWithIndexByIsSupported()
|
||||
{
|
||||
$entityManager = $this->_em;
|
||||
$query = $entityManager->createQuery('SELECT u.* FROM CmsUser u INDEX BY id');
|
||||
$query = $entityManager->createQuery('SELECT u.* FROM CmsUser u INDEX BY u.id');
|
||||
$parserResult = $query->parse();
|
||||
|
||||
$decl = $parserResult->getQueryComponent('u');
|
||||
|
@ -1,6 +1,11 @@
|
||||
<?php
|
||||
require_once 'PHPUnit/Framework.php';
|
||||
require_once 'PHPUnit/TextUI/TestRunner.php';
|
||||
|
||||
require_once '../lib/Doctrine.php';
|
||||
spl_autoload_register(array('Doctrine', 'autoload'));
|
||||
|
||||
// Some of these classes depends on Doctrine_* classes
|
||||
require_once 'Doctrine_TestCase.php';
|
||||
require_once 'Doctrine_TestUtil.php';
|
||||
require_once 'Doctrine_DbalTestCase.php';
|
||||
@ -11,9 +16,6 @@ require_once 'Doctrine_OrmTestSuite.php';
|
||||
require_once 'Doctrine_OrmFunctionalTestSuite.php';
|
||||
require_once 'Doctrine_DbalTestSuite.php';
|
||||
|
||||
require_once '../lib/Doctrine.php';
|
||||
spl_autoload_register(array('Doctrine', 'autoload'));
|
||||
|
||||
$modelDir = dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'models';
|
||||
Doctrine_Manager::getInstance()->setAttribute(Doctrine::ATTR_MODEL_LOADING, Doctrine::MODEL_LOADING_CONSERVATIVE);
|
||||
Doctrine::loadModels($modelDir);
|
||||
|
@ -1,4 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once 'lib/mocks/Doctrine_ConnectionMock.php';
|
||||
|
||||
/**
|
||||
* Base testcase class for all orm testcases.
|
||||
*
|
||||
@ -15,7 +18,7 @@ class Doctrine_OrmTestCase extends Doctrine_TestCase
|
||||
$config = new Doctrine_Configuration();
|
||||
$eventManager = new Doctrine_EventManager();
|
||||
$connectionOptions = array(
|
||||
'driver' => 'Doctrine_ConnectionMock',
|
||||
'driverClass' => 'Doctrine_ConnectionMock',
|
||||
'user' => 'john',
|
||||
'password' => 'wayne'
|
||||
);
|
||||
|
@ -8,7 +8,7 @@ class Doctrine_EntityPersisterMock extends Doctrine_EntityPersister_Standard
|
||||
|
||||
private $_identityColumnValueCounter = 0;
|
||||
|
||||
public function insert($entity)
|
||||
public function insert(Doctrine_Entity $entity)
|
||||
{
|
||||
if ($entity->getClass()->isIdGeneratorIdentity()) {
|
||||
$entity->_assignIdentifier($this->_identityColumnValueCounter++);
|
||||
@ -18,12 +18,12 @@ class Doctrine_EntityPersisterMock extends Doctrine_EntityPersister_Standard
|
||||
$this->_inserts[] = $entity;
|
||||
}
|
||||
|
||||
public function update($entity)
|
||||
public function update(Doctrine_Entity $entity)
|
||||
{
|
||||
$this->_updates[] = $entity;
|
||||
}
|
||||
|
||||
public function delete($entity)
|
||||
public function delete(Doctrine_Entity $entity)
|
||||
{
|
||||
$this->_deletes[] = $entity;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user