Commit 618c1281 authored by romanb's avatar romanb

[2.0] Parser work.

parent 98076e0b
......@@ -194,10 +194,10 @@ abstract class AbstractHydrator
if ($this->_isIgnoredName($key)) continue;
// Cache general information like the column name <-> field name mapping
$e = explode(\Doctrine\ORM\Query\ParserRule::SQLALIAS_SEPARATOR, $key);
$e = explode(\Doctrine\ORM\Query\SqlWalker::SQLALIAS_SEPARATOR, $key);
$columnName = array_pop($e);
$cache[$key]['dqlAlias'] = $this->_tableAliases[
implode(\Doctrine\ORM\Query\ParserRule::SQLALIAS_SEPARATOR, $e)
implode(\Doctrine\ORM\Query\SqlWalker::SQLALIAS_SEPARATOR, $e)
];
$classMetadata = $this->_queryComponents[$cache[$key]['dqlAlias']]['metadata'];
// check whether it's an aggregate value or a regular field
......@@ -264,10 +264,10 @@ abstract class AbstractHydrator
if ($this->_isIgnoredName($key)) continue;
// cache general information like the column name <-> field name mapping
$e = explode(\Doctrine\ORM\Query\ParserRule::SQLALIAS_SEPARATOR, $key);
$e = explode(\Doctrine\ORM\Query\SqlWalker::SQLALIAS_SEPARATOR, $key);
$columnName = array_pop($e);
$cache[$key]['dqlAlias'] = $this->_tableAliases[
implode(\Doctrine\ORM\Query\ParserRule::SQLALIAS_SEPARATOR, $e)
implode(\Doctrine\ORM\Query\SqlWalker::SQLALIAS_SEPARATOR, $e)
];
$classMetadata = $this->_queryComponents[$cache[$key]['dqlAlias']]['metadata'];
// check whether it's an aggregate value or a regular field
......
......@@ -19,6 +19,10 @@ class InputParameter extends Node
public function __construct($value)
{
if (strlen($value) == 1) {
throw new \InvalidArgumentException("Invalid parameter format.");
}
$param = substr($value, 1);
$this->_isNamed = ! is_numeric($param);
if ($this->_isNamed) {
......
......@@ -62,6 +62,8 @@ abstract class AbstractResult
*/
protected $_enumParams;
protected $_defaultQueryComponentAlias;
/**
* Cannot be called directly, factory methods handle this job.
*
......@@ -110,6 +112,24 @@ abstract class AbstractResult
return $this->_queryComponents;
}
/**
*
*/
public function getDefaultQueryComponentAlias()
{
return $this->_defaultQueryComponentAlias;
}
/**
*
*
* @param <type> $alias
*/
public function setDefaultQueryComponentAlias($alias)
{
$this->_defaultQueryComponentAlias = $alias;
}
/**
* Get the declaration for given component alias.
*
......
......@@ -222,7 +222,7 @@ class Lexer
'[a-z_][a-z0-9_\\\]*',
'(?:[0-9]+(?:[,\.][0-9]+)*)(?:e[+-]?[0-9]+)?',
"'(?:[^']|'')*'",
'\?[0-9]+|:[a-z][a-z0-9_]+'
'\?[1-9]+|:[a-z][a-z0-9_]+'
);
$regex = '/(' . implode(')|(', $patterns) . ')|\s+|(.)/i';
}
......
......@@ -38,6 +38,8 @@ use Doctrine\ORM\Query\Exec;
*/
class Parser
{
const SCALAR_QUERYCOMPONENT_ALIAS = 'dctrn';
/**
* The minimum number of tokens read after last detected error before
* another error can be reported.
......@@ -85,13 +87,11 @@ class Parser
{
$this->_em = $query->getEntityManager();
$this->_lexer = new Lexer($query->getDql());
$defaultQueryComponent = ParserRule::DEFAULT_QUERYCOMPONENT;
$this->_parserResult = new ParserResult(
'',
array( // queryComponent
$defaultQueryComponent => array(
self::SCALAR_QUERYCOMPONENT_ALIAS => array(
'metadata' => null,
'parent' => null,
'relation' => null,
......@@ -100,7 +100,7 @@ class Parser
),
),
array( // tableAliasMap
$defaultQueryComponent => $defaultQueryComponent,
self::SCALAR_QUERYCOMPONENT_ALIAS => self::SCALAR_QUERYCOMPONENT_ALIAS,
)
);
......@@ -215,7 +215,6 @@ class Parser
$token = $this->_lexer->lookahead;
}
// Formatting message
$message = 'line 0, col ' . (isset($token['position']) ? $token['position'] : '-1') . ': Error: ';
if ($expected !== '') {
......@@ -272,21 +271,7 @@ class Parser
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);
}*/
}
/**
* Checks if the next-next (after lookahead) token start a function.
......@@ -296,7 +281,7 @@ class Parser
private function _isFunction()
{
$next = $this->_lexer->glimpse();
return ($next['value'] === '(');
return $next['value'] === '(';
}
/**
......@@ -360,7 +345,7 @@ class Parser
}
/**
*
* Begins a new stack of deferred path expressions.
*/
private function _beginDeferredPathExpressionStack()
{
......@@ -368,8 +353,8 @@ class Parser
}
/**
* Processes pending path expressions that were encountered while parsing
* select expressions. These will be validated to make sure they are indeed
* Processes the topmost stack of deferred path expressions.
* These will be validated to make sure they are indeed
* valid <tt>StateFieldPathExpression</tt>s and additional information
* is attached to their AST nodes.
*/
......@@ -451,6 +436,8 @@ class Parser
if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
$this->match(Lexer::T_IDENTIFIER);
$aliasIdentificationVariable = $this->_lexer->token['value'];
} else {
$aliasIdentificationVariable = $abstractSchemaName;
}
$this->match(Lexer::T_SET);
$updateItems = array();
......@@ -460,18 +447,17 @@ class Parser
$updateItems[] = $this->_UpdateItem();
}
if ($aliasIdentificationVariable) {
$classMetadata = $this->_em->getClassMetadata($abstractSchemaName);
// Building queryComponent
$queryComponent = array(
'metadata' => $classMetadata,
'parent' => null,
'relation' => null,
'map' => null,
'scalar' => null,
);
$this->_parserResult->setQueryComponent($aliasIdentificationVariable, $queryComponent);
}
$classMetadata = $this->_em->getClassMetadata($abstractSchemaName);
// Building queryComponent
$queryComponent = array(
'metadata' => $classMetadata,
'parent' => null,
'relation' => null,
'map' => null,
'scalar' => null,
);
$this->_parserResult->setQueryComponent($aliasIdentificationVariable, $queryComponent);
$this->_parserResult->setDefaultQueryComponentAlias($aliasIdentificationVariable);
$updateClause = new AST\UpdateClause($abstractSchemaName, $updateItems);
$updateClause->setAliasIdentificationVariable($aliasIdentificationVariable);
......@@ -490,6 +476,8 @@ class Parser
$this->match(Lexer::T_IDENTIFIER);
$identVariable = $this->_lexer->token['value'];
$this->match('.');
} else {
$identVariable = $this->_parserResult->getDefaultQueryComponentAlias();
}
$this->match(Lexer::T_IDENTIFIER);
$field = $this->_lexer->token['value'];
......@@ -551,18 +539,22 @@ class Parser
if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
$this->match(Lexer::T_IDENTIFIER);
$deleteClause->setAliasIdentificationVariable($this->_lexer->token['value']);
$classMetadata = $this->_em->getClassMetadata($deleteClause->getAbstractSchemaName());
// Building queryComponent
$queryComponent = array(
'metadata' => $classMetadata,
'parent' => null,
'relation' => null,
'map' => null,
'scalar' => null,
);
$this->_parserResult->setQueryComponent($this->_lexer->token['value'], $queryComponent);
} else {
$deleteClause->setAliasIdentificationVariable($deleteClause->getAbstractSchemaName());
}
$classMetadata = $this->_em->getClassMetadata($deleteClause->getAbstractSchemaName());
$queryComponent = array(
'metadata' => $classMetadata,
'parent' => null,
'relation' => null,
'map' => null,
'scalar' => null,
);
$this->_parserResult->setQueryComponent($deleteClause->getAliasIdentificationVariable(),
$queryComponent);
$this->_parserResult->setDefaultQueryComponentAlias($deleteClause->getAliasIdentificationVariable());
return $deleteClause;
}
......@@ -599,6 +591,9 @@ class Parser
$this->match(Lexer::T_FROM);
$identificationVariableDeclarations = array();
$identificationVariableDeclarations[] = $this->_IdentificationVariableDeclaration();
$this->_parserResult->setDefaultQueryComponentAlias(
$identificationVariableDeclarations[0]->getRangeVariableDeclaration()->getAbstractSchemaName()
);
while ($this->_lexer->isNextToken(',')) {
$this->match(',');
$identificationVariableDeclarations[] = $this->_IdentificationVariableDeclaration();
......@@ -1345,6 +1340,7 @@ class Parser
$this->match(',');
$literals[] = $this->_Literal();
}
$inExpression->setLiterals($literals);
}
$this->match(')');
......
<?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>.
*/
/**
* Production variables holder
*
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Janne Vanhala <jpvanhal@cc.hut.fi>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link http://www.phpdoctrine.org
* @since 2.0
* @version $Revision$
*/
class Doctrine_ORM_Query_ParserDataHolder
{
protected static $_instance;
protected $_data;
protected function __construct()
{
$this->free();
}
public static function create()
{
if ( ! isset(self::$_instance)) {
self::$_instance = new self;
}
return self::$_instance;
}
public function free()
{
$this->_data = array();
}
public function set($offset, $value)
{
$this->_data[$offset] = $value;
}
public function get($offset)
{
return isset($this->_data[$offset]) ? $this->_data[$offset] : null;
}
public function has($offset)
{
return isset($this->_data[$offset]);
}
public function remove($offset)
{
if ($this->has($offset)) {
$this->_data[$offset] = null;
unset($this->_data[$offset]);
}
}
}
\ No newline at end of file
......@@ -16,7 +16,7 @@
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Query;
......@@ -27,7 +27,7 @@ namespace Doctrine\ORM\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
* @link http://www.doctrine-project.org
* @since 2.0
* @version $Revision$
*/
......
<?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>.
*/
namespace Doctrine\ORM\Query;
/**
* An abstract base class for the productions of the Doctrine Query Language
* context-free grammar.
*
* @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 ParserRule
{
/**
* @nodoc
*/
const SQLALIAS_SEPARATOR = '__';
/**
* @nodoc
*/
const DEFAULT_QUERYCOMPONENT = 'dctrn';
/**
* Parser object
*
* @var Doctrine_ORM_Query_Parser
*/
protected $_parser;
/**
* The EntityManager.
*
* @var EntityManager
*/
protected $_em;
/**
* The Parser Data Holder.
*
* @var ParserDataHolder
*/
protected $_dataHolder;
/**
* Creates a new production object.
*
* @param Doctrine_ORM_Query_Parser $parser a parser object
*/
public function __construct(Doctrine_ORM_Query_Parser $parser)
{
$this->_parser = $parser;
$this->_em = $this->_parser->getEntityManager();
$this->_dataHolder = Doctrine_ORM_Query_ParserDataHolder::create();
}
protected function _isNextToken($token)
{
$la = $this->_parser->lookahead;
return ($la['type'] === $token || $la['value'] === $token);
}
protected function _isFunction()
{
$la = $this->_parser->lookahead;
$next = $this->_parser->getScanner()->peek();
return ($la['type'] === Doctrine_ORM_Query_Token::T_IDENTIFIER && $next['value'] === '(');
}
protected function _isSubselect()
{
$la = $this->_parser->lookahead;
$next = $this->_parser->getScanner()->peek();
return ($la['value'] === '(' && $next['type'] === Doctrine_ORM_Query_Token::T_SELECT);
}
/**
* Executes the grammar rule using the specified parameters.
*
* @param string $RuleName BNF Grammar Rule name
* @param array $paramHolder Production parameter holder
* @return Doctrine_ORM_Query_AST The constructed subtree during parsing.
*/
public function parse($ruleName)
{
echo $ruleName . PHP_EOL;
return $this->_getGrammarRule($ruleName)->syntax();
// Syntax check
/*if ( ! $this->_dataHolder->has('syntaxCheck') || $this->_dataHolder->get('syntaxCheck') === true) {
//echo "Processing syntax checks of " . $RuleName . "...\n";
$ASTNode = $BNFGrammarRule->syntax();
if ($ASTNode !== null) {
//echo "Returning Grammar Rule class: " . (is_object($ASTNode) ? get_class($ASTNode) : $ASTNode) . "...\n";
return $ASTNode;
}
}*/
// Semantical check
/*if ( ! $this->_dataHolder->has('semanticalCheck') || $this->_dataHolder->get('semanticalCheck') === true) {
echo "Processing semantical checks of " . $RuleName . "...\n";
$return = $BNFGrammarRule->semantical();
if ($return !== null) {
echo "Returning Grammar Rule class: " . (is_object($return) ? get_class($return) : $return) . "...\n";
return $return;
}
}*/
return $BNFGrammarRule;
}
/**
* Returns a grammar rule object with the given name.
*
* @param string $name grammar rule name
* @return Doctrine_ORM_Query_ParserRule
*/
protected function _getGrammarRule($name)
{
$class = 'Doctrine_ORM_Query_Parser_' . $name;
//echo $class . "\r\n";
//TODO: This expensive check is not necessary. Should be removed at the end.
// "new $class" will throw an error anyway if the class is not found.
if ( ! class_exists($class)) {
throw \Doctrine\Common\DoctrineException::updateMe(
"Unknown Grammar Rule '$name'. Could not find related compiler class."
);
}
return new $class($this->_parser);
}
/**
* Creates an AST node with the given name.
*
* @param string $AstName AST node name
* @return Doctrine_ORM_Query_AST
*/
public function AST($AstName)
{
$class = 'Doctrine_ORM_Query_AST_' . $AstName;
return new $class($this->_parser->getParserResult());
}
/**
* @nodoc
*/
abstract public function syntax();
/**
* @nodoc
*/
public function semantical()
{
}
public function getParser()
{
return $this->_parser;
}
public function getDataHolder()
{
return $this->_dataHolder;
}
}
\ No newline at end of file
......@@ -16,7 +16,7 @@
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Query;
......@@ -27,7 +27,7 @@ namespace Doctrine\ORM\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
* @link http://www.doctrine-project.org
* @since 2.0
* @version $Revision$
*/
......
......@@ -21,6 +21,7 @@
namespace Doctrine\ORM\Query;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\AST;
use Doctrine\Common\DoctrineException;
......@@ -35,6 +36,8 @@ use Doctrine\Common\DoctrineException;
*/
class SqlWalker
{
const SQLALIAS_SEPARATOR = '__';
private $_tableAliasCounter = 0;
private $_parserResult;
private $_em;
......@@ -50,7 +53,7 @@ class SqlWalker
$this->_parserResult = $parserResult;
$sqlToDqlAliasMap = array();
foreach ($parserResult->getQueryComponents() as $dqlAlias => $qComp) {
if ($dqlAlias != 'dctrn') {
if ($dqlAlias != Parser::SCALAR_QUERYCOMPONENT_ALIAS) {
$sqlAlias = $this->generateSqlTableAlias($qComp['metadata']->getTableName());
$sqlToDqlAliasMap[$sqlAlias] = $dqlAlias;
}
......@@ -302,7 +305,9 @@ class SqlWalker
public function walkUpdateStatement(AST\UpdateStatement $AST)
{
$sql = $this->walkUpdateClause($AST->getUpdateClause());
$sql .= $AST->getWhereClause() ? $this->walkWhereClause($AST->getWhereClause()) : '';
return $sql;
}
public function walkDeleteStatement(AST\DeleteStatement $AST)
......@@ -323,6 +328,40 @@ class SqlWalker
return $sql;
}
public function walkUpdateClause($updateClause)
{
$sql = 'UPDATE ';
$class = $this->_em->getClassMetadata($updateClause->getAbstractSchemaName());
$sql .= $class->getTableName();
if ($updateClause->getAliasIdentificationVariable()) {
$sql .= ' ' . $this->_dqlToSqlAliasMap[$updateClause->getAliasIdentificationVariable()];
}
$sql .= ' SET ' . implode(', ', array_map(array($this, 'walkUpdateItem'),
$updateClause->getUpdateItems()));
return $sql;
}
public function walkUpdateItem($updateItem)
{
$sql = '';
$dqlAlias = $updateItem->getIdentificationVariable() ?
$updateItem->getIdentificationVariable() :
$this->_parserResult->getDefaultQueryComponentAlias();
$qComp = $this->_parserResult->getQueryComponent($dqlAlias);
$sql .= $this->_dqlToSqlAliasMap[$dqlAlias] . '.'
. $qComp['metadata']->getColumnName($updateItem->getField())
. ' = ';
$newValue = $updateItem->getNewValue();
if ($newValue instanceof AST\InputParameter) {
$sql .= $newValue->isNamed() ? ':' . $newValue->getName() : '?';
} // TODO: else if ...
return $sql;
}
public function walkWhereClause($whereClause)
{
$sql = ' WHERE ';
......@@ -388,12 +427,21 @@ class SqlWalker
if ($inExpr->getSubselect()) {
$sql .= $this->walkSubselect($inExpr->getSubselect());
} else {
//$sql .= implode(', ', array_map(array($this, 'walkLiteral'), $inExpr->getLiterals()));
$sql .= implode(', ', array_map(array($this, 'walkLiteral'), $inExpr->getLiterals()));
}
$sql .= ')';
return $sql;
}
public function walkLiteral($literal)
{
if ($literal instanceof AST\InputParameter) {
return ($literal->isNamed() ? ':' . $literal->getName() : '?');
} else {
return $literal;
}
}
public function walkBetweenExpression($betweenExpr)
{
$sql = $this->walkArithmeticExpression($betweenExpr->getBaseExpression());
......@@ -433,7 +481,7 @@ class SqlWalker
$sql .= ' ' . $compExpr->getOperator() . ' ';
if ($compExpr->getRightExpression() instanceof AST\ArithmeticExpression) {
$sql .= $this->walkArithmeticExpression($compExpr->getRightExpression());
}
} // else...
return $sql;
}
......
......@@ -24,9 +24,7 @@ class AllTests
$suite->addTestSuite('Doctrine\Tests\ORM\Query\LanguageRecognitionTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Query\LexerTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Query\DeleteSqlGenerationTest');
/*
$suite->addTestSuite('Orm_Query_UpdateSqlGenerationTest');*/
$suite->addTestSuite('Doctrine\Tests\ORM\Query\UpdateSqlGenerationTest');
return $suite;
}
......
......@@ -218,19 +218,17 @@ class DeleteSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
);
}
/*
public function testWithExprAndIn()
{
// "WHERE" Expression InExpression
$this->assertSqlGeneration(
'DELETE Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id IN ( ?, ?, ?, ? )',
'DELETE Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id IN ( ?1, ?2, ?3, ?4 )',
'DELETE FROM cms_users c0 WHERE c0.id IN (?, ?, ?, ?)'
);
$this->assertSqlGeneration(
'DELETE Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id NOT IN ( ?, ? )',
'DELETE Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id NOT IN ( ?1, ?2 )',
'DELETE FROM cms_users c0 WHERE c0.id NOT IN (?, ?)'
);
}
*/
}
......@@ -181,13 +181,12 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
public function testSubselectInSelectPart()
{
// Semantical error: Unknown query component u (probably in subselect)
$this->assertValidDql("SELECT u.name, (SELECT COUNT(p.phonenumber) FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE p.phonenumber = 1234) pcount FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = 'jon'");
}
public function testPositionalInputParameter()
{
$this->assertValidDql('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?');
$this->assertValidDql('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1');
}
public function testNamedInputParameter()
......
......@@ -16,14 +16,16 @@
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Tests\ORM\Query;
require_once __DIR__ . '/../../TestInit.php';
/**
* Test case for testing the saving and referencing of query identifiers.
*
* @package Doctrine
* @subpackage Query
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Janne Vanhala <jpvanhal@cc.hut.fi>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
......@@ -35,34 +37,36 @@
* testcases later since we'll have a lot of them and we might want to have special SQL
* generation tests for some dbms specific SQL syntaxes.
*/
class Orm_Query_UpdateSqlGenerationTest extends Doctrine_OrmTestCase
class UpdateSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{
private $_em;
protected function setUp() {
$this->_em = $this->_getTestEntityManager();
}
public function assertSqlGeneration($dqlToBeTested, $sqlToBeConfirmed)
{
try {
$entityManager = $this->_em;
$query = $entityManager->createQuery($dqlToBeTested);
$query = $this->_em->createQuery($dqlToBeTested);
parent::assertEquals($sqlToBeConfirmed, $query->getSql());
$query->free();
} catch (Doctrine_Exception $e) {
} catch (\Exception $e) {
$this->fail($e->getMessage());
}
}
public function testWithoutWhere()
{
// NO WhereClause
$this->assertSqlGeneration(
'UPDATE CmsUser u SET name = ?',
'UPDATE cms_user cu SET cu.name = ? WHERE 1 = 1'
'UPDATE Doctrine\Tests\Models\CMS\CmsUser u SET u.name = ?1',
'UPDATE cms_users c0 SET c0.name = ?'
);
$this->assertSqlGeneration(
'UPDATE CmsUser u SET name = ?, username = ?',
'UPDATE cms_user cu SET cu.name = ?, cu.username = ? WHERE 1 = 1'
'UPDATE Doctrine\Tests\Models\CMS\CmsUser u SET u.name = ?1, u.username = ?2',
'UPDATE cms_users c0 SET c0.name = ?, c0.username = ?'
);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment