[2.0] Parser work.
This commit is contained in:
parent
84c62d8aec
commit
104398003c
@ -33,7 +33,6 @@ use \ArrayIterator;
|
||||
*
|
||||
* @author Roman S. Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
* @todo Consider extending ArrayObject
|
||||
*/
|
||||
class Collection implements Countable, IteratorAggregate, ArrayAccess
|
||||
{
|
||||
@ -310,6 +309,7 @@ class Collection implements Countable, IteratorAggregate, ArrayAccess
|
||||
|
||||
/**
|
||||
* Checks whether the collection is empty.
|
||||
*
|
||||
* Note: This is preferrable over count() == 0.
|
||||
*
|
||||
* @return boolean TRUE if the collection is empty, FALSE otherwise.
|
||||
|
@ -603,14 +603,14 @@ class Connection
|
||||
}
|
||||
|
||||
if ( ! empty($params)) {
|
||||
$stmt = $this->prepare($query);
|
||||
$stmt = $this->_conn->prepare($query);
|
||||
$stmt->execute($params);
|
||||
return $stmt;
|
||||
} else {
|
||||
$stmt = $this->_conn->query($query);
|
||||
$this->_queryCount++;
|
||||
return $stmt;
|
||||
}
|
||||
$this->_queryCount++;
|
||||
|
||||
return $stmt;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -630,14 +630,15 @@ class Connection
|
||||
}
|
||||
|
||||
if ( ! empty($params)) {
|
||||
$stmt = $this->prepare($query);
|
||||
$stmt = $this->_conn->prepare($query);
|
||||
$stmt->execute($params);
|
||||
return $stmt->rowCount();
|
||||
$result = $stmt->rowCount();
|
||||
} else {
|
||||
$count = $this->_conn->exec($query);
|
||||
$this->_queryCount++;
|
||||
return $count;
|
||||
$result = $this->_conn->exec($query);
|
||||
}
|
||||
$this->_queryCount++;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -769,23 +770,6 @@ class Connection
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quotes pattern (% and _) characters in a string)
|
||||
*
|
||||
* EXPERIMENTAL
|
||||
*
|
||||
* WARNING: this function is experimental and may change signature at
|
||||
* any time until labelled as non-experimental
|
||||
*
|
||||
* @param string the input string to quote
|
||||
*
|
||||
* @return string quoted string
|
||||
*/
|
||||
protected function _escapePattern($text)
|
||||
{
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the wrapped driver connection.
|
||||
*
|
||||
|
@ -1219,11 +1219,9 @@ abstract class AbstractPlatform
|
||||
$item[$k] = (int) $value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (is_bool($item)) {
|
||||
} else if (is_bool($item)) {
|
||||
$item = (int) $item;
|
||||
}
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ class BooleanType extends Type
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
public function convertToDatabaseValue($value, Doctrine_DatabasePlatform $platform)
|
||||
public function convertToDatabaseValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
|
||||
{
|
||||
return $platform->convertBooleans($value);
|
||||
}
|
||||
@ -24,7 +24,7 @@ class BooleanType extends Type
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
public function convertToObjectValue($value)
|
||||
public function convertToPHPValue($value)
|
||||
{
|
||||
return (bool) $value;
|
||||
}
|
||||
|
@ -178,19 +178,23 @@ abstract class AbstractQuery
|
||||
*
|
||||
* @return array Defined parameters
|
||||
*/
|
||||
public function getParams($params = array())
|
||||
public function getParameters($params = array())
|
||||
{
|
||||
if ($params) {
|
||||
return array_merge($this->_params, $params);
|
||||
}
|
||||
return $this->_params;
|
||||
}
|
||||
|
||||
/**
|
||||
* setParams
|
||||
* Gets a query parameter.
|
||||
*
|
||||
* @param array $params
|
||||
* @param mixed $key The key (index or name) of the bound parameter.
|
||||
* @return mixed The value of the bound parameter.
|
||||
*/
|
||||
public function setParams(array $params = array())
|
||||
public function getParameter($key)
|
||||
{
|
||||
$this->_params = $params;
|
||||
return isset($this->_params[$key]) ? $this->_params[$key] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -470,7 +474,7 @@ abstract class AbstractQuery
|
||||
$this->_hydrationMode = $hydrationMode;
|
||||
}
|
||||
|
||||
$params = $this->getParams($params);
|
||||
$params = $this->getParameters($params);
|
||||
|
||||
// Check result cache
|
||||
if ($cacheDriver = $this->getResultCacheDriver()) {
|
||||
@ -503,12 +507,15 @@ abstract class AbstractQuery
|
||||
}
|
||||
|
||||
/**
|
||||
* @nodoc
|
||||
* Prepares the given parameters for execution in an SQL statement.
|
||||
*
|
||||
* Note to inheritors: This method must return a numerically, continously indexed array,
|
||||
* starting with index 0 where the values (the parameter values) are in the order
|
||||
* in which the parameters appear in the SQL query.
|
||||
*
|
||||
* @return array The SQL parameter array.
|
||||
*/
|
||||
protected function _prepareParams(array $params)
|
||||
{
|
||||
return $this->_em->getConnection()->getDatabasePlatform()->convertBooleans($params);
|
||||
}
|
||||
abstract protected function _prepareParams(array $params);
|
||||
|
||||
/**
|
||||
* Executes the query and returns a reference to the resulting Statement object.
|
||||
|
@ -71,6 +71,7 @@ class DynamicProxyGenerator
|
||||
require $fileName;
|
||||
}
|
||||
$proxyClassName = '\\' . self::$_ns . $proxyClassName;
|
||||
|
||||
return new $proxyClassName($this->_em, $class, $identifier);
|
||||
}
|
||||
|
||||
@ -89,6 +90,7 @@ class DynamicProxyGenerator
|
||||
require $fileName;
|
||||
}
|
||||
$proxyClassName = '\\' . self::$_ns . $proxyClassName;
|
||||
|
||||
return new $proxyClassName($this->_em, $assoc, $owner);
|
||||
}
|
||||
|
||||
|
@ -859,6 +859,9 @@ final class ClassMetadata
|
||||
/**
|
||||
* Extracts the identifier values of an entity of this class.
|
||||
*
|
||||
* For composite identifiers, the identifier values are returned as an array
|
||||
* with the same order as the field order in {@link identifier}.
|
||||
*
|
||||
* @param object $entity
|
||||
* @return mixed
|
||||
*/
|
||||
|
@ -63,6 +63,9 @@ class ManyToManyMapping extends AssociationMapping
|
||||
*/
|
||||
public $joinTableColumns = array();
|
||||
|
||||
/** FUTURE: The key column mapping, if any. The key column holds the keys of the Collection. */
|
||||
//public $keyColumn;
|
||||
|
||||
/**
|
||||
* Initializes a new ManyToManyMapping.
|
||||
*
|
||||
|
@ -42,24 +42,10 @@ namespace Doctrine\ORM\Mapping;
|
||||
*/
|
||||
class OneToManyMapping extends AssociationMapping
|
||||
{
|
||||
/** The target foreign key columns that reference the sourceKeyColumns. */
|
||||
/* NOTE: Currently not used because uni-directional one-many not supported atm. */
|
||||
//protected $_targetForeignKeyColumns;
|
||||
|
||||
/** The (typically primary) source key columns that are referenced by the targetForeignKeyColumns. */
|
||||
/* NOTE: Currently not used because uni-directional one-many not supported atm. */
|
||||
//protected $_sourceKeyColumns;
|
||||
|
||||
/** This maps the target foreign key columns to the corresponding (primary) source key columns. */
|
||||
/* NOTE: Currently not used because uni-directional one-many not supported atm. */
|
||||
//protected $_targetForeignKeysToSourceKeys;
|
||||
|
||||
/** This maps the (primary) source key columns to the corresponding target foreign key columns. */
|
||||
/* NOTE: Currently not used because uni-directional one-many not supported atm. */
|
||||
//protected $_sourceKeysToTargetForeignKeys;
|
||||
|
||||
/** Whether to delete orphaned elements (removed from the collection) */
|
||||
public $deleteOrphans = false;
|
||||
/** FUTURE: The key column mapping, if any. The key column holds the keys of the Collection. */
|
||||
//public $keyColumn;
|
||||
|
||||
/**
|
||||
* Initializes a new OneToManyMapping.
|
||||
|
@ -74,4 +74,21 @@ final class NativeQuery extends AbstractQuery
|
||||
{
|
||||
return $this->_em->getConnection()->execute($this->_sql, $this->_prepareParams($params));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
protected function _prepareParams(array $params)
|
||||
{
|
||||
$sqlParams = array();
|
||||
|
||||
foreach ($params as $key => $value) {
|
||||
$sqlParams[$key] = $value;
|
||||
}
|
||||
ksort($sqlParams);
|
||||
|
||||
return array_values($sqlParams);
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ use Doctrine\ORM\Mapping\AssociationMapping;
|
||||
|
||||
/**
|
||||
* A PersistentCollection represents a collection of elements that have persistent state.
|
||||
*
|
||||
* Collections of entities represent only the associations (links) to those entities.
|
||||
* That means, if the collection is part of a many-many mapping and you remove
|
||||
* entities from the collection, only the links in the relation table are removed (on flush).
|
||||
|
@ -65,6 +65,16 @@ final class Query extends AbstractQuery
|
||||
*/
|
||||
private $_parserResult;
|
||||
|
||||
/**
|
||||
* @var integer The first result to return (the "offset").
|
||||
*/
|
||||
private $_firstResult = null;
|
||||
|
||||
/**
|
||||
* @var integer The maximum number of results to return (the "limit").
|
||||
*/
|
||||
private $_maxResults = null;
|
||||
|
||||
/**
|
||||
* @var CacheDriver The cache driver used for caching queries.
|
||||
*/
|
||||
@ -100,7 +110,7 @@ final class Query extends AbstractQuery
|
||||
*/
|
||||
public function getSql()
|
||||
{
|
||||
return $this->parse()->getSqlExecutor()->getSqlStatements();
|
||||
return $this->_parse()->getSqlExecutor()->getSqlStatements();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,7 +120,7 @@ final class Query extends AbstractQuery
|
||||
*
|
||||
* @return Doctrine\ORM\Query\ParserResult
|
||||
*/
|
||||
public function parse()
|
||||
private function _parse()
|
||||
{
|
||||
if ($this->_state === self::STATE_DIRTY) {
|
||||
$parser = new Parser($this);
|
||||
@ -121,15 +131,15 @@ final class Query extends AbstractQuery
|
||||
}
|
||||
|
||||
/**
|
||||
* _execute
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param array $params
|
||||
* @return PDOStatement The executed PDOStatement.
|
||||
* @return Statement The resulting Statement.
|
||||
* @override
|
||||
*/
|
||||
protected function _doExecute(array $params)
|
||||
{
|
||||
// If there is a CacheDriver associated to cache queries...
|
||||
// Check query cache
|
||||
if ($queryCache = $this->getQueryCacheDriver()) {
|
||||
// Calculate hash for dql query.
|
||||
$hash = md5($this->getDql() . 'DOCTRINE_QUERY_CACHE_SALT');
|
||||
@ -137,7 +147,7 @@ final class Query extends AbstractQuery
|
||||
|
||||
if ($cached === false) {
|
||||
// Cache miss.
|
||||
$executor = $this->parse()->getSqlExecutor();
|
||||
$executor = $this->_parse()->getSqlExecutor();
|
||||
$queryCache->save($hash, serialize($this->_parserResult), null);
|
||||
} else {
|
||||
// Cache hit.
|
||||
@ -145,20 +155,49 @@ final class Query extends AbstractQuery
|
||||
$executor = $this->_parserResult->getSqlExecutor();
|
||||
}
|
||||
} else {
|
||||
$executor = $this->parse()->getSqlExecutor();
|
||||
$executor = $this->_parse()->getSqlExecutor();
|
||||
}
|
||||
|
||||
// Converting parameters
|
||||
$params = $this->_prepareParams($params);
|
||||
|
||||
if ( ! $this->_resultSetMapping) {
|
||||
$this->_resultSetMapping = $this->_parserResult->getResultSetMapping();
|
||||
}
|
||||
|
||||
// Executing the query and returning statement
|
||||
return $executor->execute($this->_em->getConnection(), $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
protected function _prepareParams(array $params)
|
||||
{
|
||||
$sqlParams = array();
|
||||
|
||||
$paramMappings = $this->_parserResult->getParameterMappings();
|
||||
foreach ($params as $key => $value) {
|
||||
if (is_object($value)) {
|
||||
$values = $this->_em->getClassMetadata(get_class($value))->getIdentifierValues($value);
|
||||
$sqlPositions = $paramMappings[$key];
|
||||
$sqlParams = array_merge($sqlParams, array_combine((array)$sqlPositions, (array)$values));
|
||||
} else if (is_bool($value)) {
|
||||
$boolValue = $this->_em->getConnection()->getDatabasePlatform()->convertBooleans($value);
|
||||
foreach ($paramMappings[$key] as $position) {
|
||||
$sqlParams[$position] = $boolValue;
|
||||
}
|
||||
} else {
|
||||
foreach ($paramMappings[$key] as $position) {
|
||||
$sqlParams[$position] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
ksort($sqlParams);
|
||||
|
||||
return array_values($sqlParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a cache driver to be used for caching queries.
|
||||
*
|
||||
@ -294,4 +333,50 @@ final class Query extends AbstractQuery
|
||||
{
|
||||
return stripos($this->getDql(), $dql) === false ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the position of the first result to retrieve (the "offset").
|
||||
*
|
||||
* @param integer $firstResult The first result to return.
|
||||
* @return Query This query object.
|
||||
*/
|
||||
public function setFirstResult($firstResult)
|
||||
{
|
||||
$this->_firstResult = $firstResult;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the position of the first result the query object was set to retrieve (the "offset").
|
||||
* Returns NULL if {@link setFirstResult} was not applied to this query.
|
||||
*
|
||||
* @return integer The position of the first result.
|
||||
*/
|
||||
public function getFirstResult()
|
||||
{
|
||||
return $this->_firstResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum number of results to retrieve (the "limit").
|
||||
*
|
||||
* @param integer $maxResults
|
||||
* @return Query This query object.
|
||||
*/
|
||||
public function setMaxResults($maxResults)
|
||||
{
|
||||
$this->_maxResults = $maxResults;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum number of results the query object was set to retrieve (the "limit").
|
||||
* Returns NULL if {@link setMaxResults} was not applied to this query.
|
||||
*
|
||||
* @return integer Maximum number of results.
|
||||
*/
|
||||
public function getMaxResults()
|
||||
{
|
||||
return $this->_maxResults;
|
||||
}
|
||||
}
|
28
lib/Doctrine/ORM/Query/AST/CollectionMemberExpression.php
Normal file
28
lib/Doctrine/ORM/Query/AST/CollectionMemberExpression.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\ORM\Query\AST;
|
||||
|
||||
/**
|
||||
* CollectionMemberExpression ::= EntityExpression ["NOT"] "MEMBER" ["OF"] CollectionValuedPathExpression
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class CollectionMemberExpression extends Node
|
||||
{
|
||||
public $entityExpression;
|
||||
public $collectionValuedPathExpression;
|
||||
public $isNot;
|
||||
|
||||
public function __construct($entityExpr, $collValuedPathExpr, $isNot)
|
||||
{
|
||||
$this->entityExpression = $entityExpr;
|
||||
$this->collectionValuedPathExpression = $collValuedPathExpr;
|
||||
$this->isNot = $isNot;
|
||||
}
|
||||
|
||||
public function dispatch($walker)
|
||||
{
|
||||
return $walker->walkCollectionMemberExpression($this);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ namespace Doctrine\ORM\Query\AST\Functions;
|
||||
/**
|
||||
* "ABS" "(" SimpleArithmeticExpression ")"
|
||||
*
|
||||
* @author robo
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class AbsFunction extends FunctionNode
|
||||
{
|
||||
@ -37,7 +37,7 @@ class AbsFunction extends FunctionNode
|
||||
$lexer = $parser->getLexer();
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
$this->_simpleArithmeticExpression = $parser->_SimpleArithmeticExpression();
|
||||
$this->_simpleArithmeticExpression = $parser->SimpleArithmeticExpression();
|
||||
$parser->match(')');
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ namespace Doctrine\ORM\Query\AST\Functions;
|
||||
/**
|
||||
* "CONCAT" "(" StringPrimary "," StringPrimary ")"
|
||||
*
|
||||
* @author robo
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class ConcatFunction extends FunctionNode
|
||||
{
|
||||
@ -36,13 +36,6 @@ class ConcatFunction extends FunctionNode
|
||||
$sqlWalker->walkStringPrimary($this->_firstStringPrimary),
|
||||
$sqlWalker->walkStringPrimary($this->_secondStringPrimary)
|
||||
);
|
||||
/*
|
||||
$sql = 'CONCAT(' .
|
||||
$sqlWalker->walkStringPrimary($this->_firstStringPrimary)
|
||||
. ', ' .
|
||||
$sqlWalker->walkStringPrimary($this->_secondStringPrimary)
|
||||
. ')';
|
||||
return $sql;*/
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,9 +47,9 @@ class ConcatFunction extends FunctionNode
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
|
||||
$this->_firstStringPrimary = $parser->_StringPrimary();
|
||||
$this->_firstStringPrimary = $parser->StringPrimary();
|
||||
$parser->match(',');
|
||||
$this->_secondStringPrimary = $parser->_StringPrimary();
|
||||
$this->_secondStringPrimary = $parser->StringPrimary();
|
||||
|
||||
$parser->match(')');
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ use Doctrine\ORM\Query\AST\Node;
|
||||
abstract class FunctionNode extends Node
|
||||
{
|
||||
private $_name;
|
||||
//private $_expressions = array();
|
||||
|
||||
public function __construct($name)
|
||||
{
|
||||
|
@ -9,7 +9,7 @@ namespace Doctrine\ORM\Query\AST\Functions;
|
||||
/**
|
||||
* "LENGTH" "(" StringPrimary ")"
|
||||
*
|
||||
* @author robo
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class LengthFunction extends FunctionNode
|
||||
{
|
||||
@ -37,7 +37,7 @@ class LengthFunction extends FunctionNode
|
||||
$lexer = $parser->getLexer();
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
$this->_stringPrimary = $parser->_StringPrimary();
|
||||
$this->_stringPrimary = $parser->StringPrimary();
|
||||
$parser->match(')');
|
||||
}
|
||||
}
|
||||
|
@ -57,12 +57,12 @@ class LocateFunction extends FunctionNode
|
||||
$lexer = $parser->getLexer();
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
$this->_firstStringPrimary = $parser->_StringPrimary();
|
||||
$this->_firstStringPrimary = $parser->StringPrimary();
|
||||
$parser->match(',');
|
||||
$this->_secondStringPrimary = $parser->_StringPrimary();
|
||||
$this->_secondStringPrimary = $parser->StringPrimary();
|
||||
if ($lexer->isNextToken(',')) {
|
||||
$parser->match(',');
|
||||
$this->_simpleArithmeticExpression = $parser->_SimpleArithmeticExpression();
|
||||
$this->_simpleArithmeticExpression = $parser->SimpleArithmeticExpression();
|
||||
}
|
||||
$parser->match(')');
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class LowerFunction extends FunctionNode
|
||||
$lexer = $parser->getLexer();
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
$this->_stringPrimary = $parser->_StringPrimary();
|
||||
$this->_stringPrimary = $parser->StringPrimary();
|
||||
$parser->match(')');
|
||||
}
|
||||
}
|
||||
|
@ -47,9 +47,9 @@ class ModFunction extends FunctionNode
|
||||
$lexer = $parser->getLexer();
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
$this->_firstSimpleArithmeticExpression = $parser->_SimpleArithmeticExpression();
|
||||
$this->_firstSimpleArithmeticExpression = $parser->SimpleArithmeticExpression();
|
||||
$parser->match(',');
|
||||
$this->_secondSimpleArithmeticExpression = $parser->_SimpleArithmeticExpression();
|
||||
$this->_secondSimpleArithmeticExpression = $parser->SimpleArithmeticExpression();
|
||||
$parser->match(')');
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class SizeFunction extends FunctionNode
|
||||
$lexer = $parser->getLexer();
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
$this->_collectionPathExpression = $parser->_CollectionValuedPathExpression();
|
||||
$this->_collectionPathExpression = $parser->CollectionValuedPathExpression();
|
||||
$parser->match(')');
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ namespace Doctrine\ORM\Query\AST\Functions;
|
||||
/**
|
||||
* "SQRT" "(" SimpleArithmeticExpression ")"
|
||||
*
|
||||
* @author robo
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class SqrtFunction extends FunctionNode
|
||||
{
|
||||
@ -37,7 +37,7 @@ class SqrtFunction extends FunctionNode
|
||||
$lexer = $parser->getLexer();
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
$this->_simpleArithmeticExpression = $parser->_SimpleArithmeticExpression();
|
||||
$this->_simpleArithmeticExpression = $parser->SimpleArithmeticExpression();
|
||||
$parser->match(')');
|
||||
}
|
||||
}
|
||||
|
@ -57,11 +57,11 @@ class SubstringFunction extends FunctionNode
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
|
||||
$this->_stringPrimary = $parser->_StringPrimary();
|
||||
$this->_stringPrimary = $parser->StringPrimary();
|
||||
$parser->match(',');
|
||||
$this->_firstSimpleArithmeticExpression = $parser->_SimpleArithmeticExpression();
|
||||
$this->_firstSimpleArithmeticExpression = $parser->SimpleArithmeticExpression();
|
||||
$parser->match(',');
|
||||
$this->_secondSimpleArithmeticExpression = $parser->_SimpleArithmeticExpression();
|
||||
$this->_secondSimpleArithmeticExpression = $parser->SimpleArithmeticExpression();
|
||||
|
||||
$parser->match(')');
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ class TrimFunction extends FunctionNode
|
||||
if ($this->_leading) $sql .= 'LEADING ';
|
||||
else if ($this->_trailing) $sql .= 'TRAILING ';
|
||||
else if ($this->_both) $sql .= 'BOTH ';
|
||||
if ($this->_trimChar) $sql .= $this->_trimChar . ' '; //TODO: quote()
|
||||
if ($this->_trimChar) $sql .= $sqlWalker->getConnection()->quote($this->_trimChar) . ' ';
|
||||
$sql .= 'FROM ' . $sqlWalker->walkStringPrimary($this->_stringPrimary);
|
||||
$sql .= ')';
|
||||
return $sql;
|
||||
@ -110,7 +110,7 @@ class TrimFunction extends FunctionNode
|
||||
$parser->match(Lexer::T_FROM);
|
||||
}
|
||||
|
||||
$this->_stringPrimary = $parser->_StringPrimary();
|
||||
$this->_stringPrimary = $parser->StringPrimary();
|
||||
|
||||
$parser->match(')');
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class UpperFunction extends FunctionNode
|
||||
$lexer = $parser->getLexer();
|
||||
$parser->match($lexer->lookahead['value']);
|
||||
$parser->match('(');
|
||||
$this->_stringPrimary = $parser->_StringPrimary();
|
||||
$this->_stringPrimary = $parser->StringPrimary();
|
||||
$parser->match(')');
|
||||
}
|
||||
}
|
||||
|
72
lib/Doctrine/ORM/Query/AST/PathExpression.php
Normal file
72
lib/Doctrine/ORM/Query/AST/PathExpression.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\ORM\Query\AST;
|
||||
|
||||
/**
|
||||
* AST node for the following path expressions:
|
||||
*
|
||||
* AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression
|
||||
*
|
||||
* SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression
|
||||
*
|
||||
* StateFieldPathExpression ::= SimpleStateFieldPathExpression | SimpleStateFieldAssociationPathExpression
|
||||
*
|
||||
* SingleValuedAssociationPathExpression ::= IdentificationVariable "." {SingleValuedAssociationField "."}* SingleValuedAssociationField
|
||||
*
|
||||
* CollectionValuedPathExpression ::= IdentificationVariable "." {SingleValuedAssociationField "."}* CollectionValuedAssociationField
|
||||
*
|
||||
* StateField ::= {EmbeddedClassStateField "."}* SimpleStateField
|
||||
*
|
||||
* SimpleStateFieldPathExpression ::= IdentificationVariable "." StateField
|
||||
*
|
||||
* SimpleStateFieldAssociationPathExpression ::= SingleValuedAssociationPathExpression "." StateField
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
*/
|
||||
class PathExpression extends Node
|
||||
{
|
||||
const TYPE_COLLECTION_VALUED_ASSOCIATION = 1;
|
||||
const TYPE_SINGLE_VALUED_ASSOCIATION = 2;
|
||||
const TYPE_STATE_FIELD = 4;
|
||||
|
||||
private $_type;
|
||||
private $_identificationVariable;
|
||||
private $_parts;
|
||||
|
||||
public function __construct($type, $identificationVariable, array $parts)
|
||||
{
|
||||
$this->_type = $type;
|
||||
$this->_identificationVariable = $identificationVariable;
|
||||
$this->_parts = $parts;
|
||||
}
|
||||
|
||||
public function getIdentificationVariable()
|
||||
{
|
||||
return $this->_identificationVariable;
|
||||
}
|
||||
|
||||
public function getParts()
|
||||
{
|
||||
return $this->_parts;
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return $this->_type;
|
||||
}
|
||||
|
||||
public function dispatch($walker)
|
||||
{
|
||||
switch ($this->_type) {
|
||||
case self::TYPE_STATE_FIELD:
|
||||
return $walker->walkStateFieldPathExpression($this);
|
||||
case self::TYPE_SINGLE_VALUED_ASSOCIATION:
|
||||
return $walker->walkSingleValuedAssociationPathExpression($this);
|
||||
case self::TYPE_COLLECTION_VALUED_ASSOCIATION:
|
||||
return $walker->walkCollectionValuedAssociationPathExpression($this);
|
||||
default:
|
||||
throw new \Exception("Unexhaustive match.");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST;
|
||||
|
||||
/**
|
||||
* SimpleStateFieldPathExpression ::= IdentificationVariable "." SimpleStateField
|
||||
*
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link http://www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
*/
|
||||
class SimpleStateFieldPathExpression extends Node
|
||||
{
|
||||
private $_identificationVariable = null;
|
||||
private $_simpleStateField = null;
|
||||
|
||||
public function __construct($identificationVariable, $simpleStateField)
|
||||
{
|
||||
$this->_identificationVariable = $identificationVariable;
|
||||
$this->_simpleStateField = $simpleStateField;
|
||||
}
|
||||
|
||||
/* Getters */
|
||||
public function getIdentificationVariable()
|
||||
{
|
||||
return $this->_identificationVariable;
|
||||
}
|
||||
|
||||
public function getSimpleStateField()
|
||||
{
|
||||
return $this->_simpleStateField;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkSimpleStateFieldPathExpression($this);
|
||||
}
|
||||
}
|
@ -1,124 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Query\AST;
|
||||
|
||||
/**
|
||||
* StateFieldPathExpression ::= SimpleStateFieldPathExpression | SimpleStateFieldAssociationPathExpression
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class StateFieldPathExpression extends Node
|
||||
{
|
||||
//const TYPE_COLLECTION_VALUED_ASSOCIATION = 1;
|
||||
//const TYPE_SINGLE_VALUED_ASSOCIATION = 2;
|
||||
//const TYPE_STATE_FIELD = 3;
|
||||
//private $_type;
|
||||
|
||||
|
||||
private $_parts;
|
||||
// Information that is attached during semantical analysis.
|
||||
private $_isSimpleStateFieldPathExpression = false;
|
||||
private $_isSimpleStateFieldAssociationPathExpression = false;
|
||||
private $_embeddedClassFields = array();
|
||||
private $_singleValuedAssociationFields = array();
|
||||
private $_collectionValuedAssociationFields = array();
|
||||
|
||||
public function __construct(array $parts)
|
||||
{
|
||||
$this->_parts = $parts;
|
||||
}
|
||||
|
||||
public function getParts() {
|
||||
return $this->_parts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the path expression represents a state field that is reached
|
||||
* either directly (u.name) or by navigating over optionally many embedded class instances
|
||||
* (u.address.zip).
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isSimpleStateFieldPathExpression()
|
||||
{
|
||||
return $this->_isSimpleStateFieldPathExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the path expression represents a state field that is reached
|
||||
* by navigating over at least one single-valued association and optionally
|
||||
* many embedded class instances. (u.Group.address.zip, u.Group.address, ...)
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isSimpleStateFieldAssociationPathExpression()
|
||||
{
|
||||
return $this->_isSimpleStateFieldAssociationPathExpression;
|
||||
}
|
||||
|
||||
public function isPartEmbeddedClassField($part)
|
||||
{
|
||||
return isset($this->_embeddedClassFields[$part]);
|
||||
}
|
||||
|
||||
public function isPartSingleValuedAssociationField($part)
|
||||
{
|
||||
return isset($this->_singleValuedAssociationFields[$part]);
|
||||
}
|
||||
|
||||
public function isPartCollectionValuedAssociationField($part)
|
||||
{
|
||||
return isset($this->_collectionValuedAssociationFields[$part]);
|
||||
}
|
||||
|
||||
/* Setters to attach semantical information during semantical analysis. */
|
||||
|
||||
public function setIsSimpleStateFieldPathExpression($bool)
|
||||
{
|
||||
$this->_isSimpleStateFieldPathExpression = $bool;
|
||||
}
|
||||
|
||||
public function setIsSimpleStateFieldAssociationPathExpression($bool)
|
||||
{
|
||||
$this->_isSimpleStateFieldAssociationPathExpression = $bool;
|
||||
}
|
||||
|
||||
public function setIsEmbeddedClassPart($part)
|
||||
{
|
||||
$this->_embeddedClassFields[$part] = true;
|
||||
}
|
||||
|
||||
public function setIsSingleValuedAssociationPart($part)
|
||||
{
|
||||
$this->_singleValuedAssociationFields[$part] = true;
|
||||
}
|
||||
|
||||
public function setIsCollectionValuedAssociationPart($part)
|
||||
{
|
||||
$this->_collectionValuedAssociationFields[$part] = true;
|
||||
}
|
||||
|
||||
public function dispatch($sqlWalker)
|
||||
{
|
||||
return $sqlWalker->walkStateFieldPathExpression($this);
|
||||
}
|
||||
}
|
@ -88,6 +88,8 @@ class Lexer
|
||||
const T_WITH = 145;
|
||||
const T_TRUE = 146;
|
||||
const T_FALSE = 147;
|
||||
const T_MEMBER = 148;
|
||||
const T_OF = 149;
|
||||
|
||||
private $_keywordsTable;
|
||||
|
||||
@ -131,8 +133,8 @@ class Lexer
|
||||
/**
|
||||
* Checks whether a given token matches the current lookahead.
|
||||
*
|
||||
* @param <type> $token
|
||||
* @return <type>
|
||||
* @param integer|string $token
|
||||
* @return boolean
|
||||
*/
|
||||
public function isNextToken($token)
|
||||
{
|
||||
@ -170,7 +172,7 @@ class Lexer
|
||||
* @param string $identifier identifier name
|
||||
* @return int token type
|
||||
*/
|
||||
public function _checkLiteral($identifier)
|
||||
private function _checkLiteral($identifier)
|
||||
{
|
||||
$name = 'Doctrine\ORM\Query\Lexer::T_' . strtoupper($identifier);
|
||||
|
||||
@ -237,6 +239,7 @@ class Lexer
|
||||
}
|
||||
if ($value[0] === "'" && $value[strlen($value) - 1] === "'") {
|
||||
$type = self::T_STRING;
|
||||
$value = str_replace("''", "'", substr($value, 1, strlen($value) - 2));
|
||||
} else if (ctype_alpha($value[0]) || $value[0] === '_') {
|
||||
$type = $this->_checkLiteral($value);
|
||||
} else if ($value[0] === '?' || $value[0] === ':') {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -35,8 +35,12 @@ namespace Doctrine\ORM\Query;
|
||||
*/
|
||||
class ParserResult
|
||||
{
|
||||
/** The SQL executor used for executing the SQL. */
|
||||
private $_sqlExecutor;
|
||||
/** The ResultSetMapping that describes how to map the SQL result set. */
|
||||
private $_resultSetMapping;
|
||||
/** The mappings of DQL parameter names/positions to SQL parameter positions. */
|
||||
private $_parameterMappings;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the <tt>ParserResult</tt> class.
|
||||
@ -87,4 +91,37 @@ class ParserResult
|
||||
{
|
||||
return $this->_sqlExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a DQL to SQL parameter mapping. One DQL parameter name/position can map to
|
||||
* several SQL parameter positions.
|
||||
*
|
||||
* @param string|integer $dqlPosition
|
||||
* @param integer $sqlPosition
|
||||
*/
|
||||
public function addParameterMapping($dqlPosition, $sqlPosition)
|
||||
{
|
||||
$this->_parameterMappings[$dqlPosition][] = $sqlPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all DQL to SQL parameter mappings.
|
||||
*
|
||||
* @return array The parameter mappings.
|
||||
*/
|
||||
public function getParameterMappings()
|
||||
{
|
||||
return $this->_parameterMappings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SQL parameter positions for a DQL parameter name/position.
|
||||
*
|
||||
* @param string|integer $dqlPosition The name or position of the DQL parameter.
|
||||
* @return array The positions of the corresponding SQL parameters.
|
||||
*/
|
||||
public function getSqlParameterPositions($dqlPosition)
|
||||
{
|
||||
return $this->_parameterMappings[$dqlPosition];
|
||||
}
|
||||
}
|
@ -26,23 +26,31 @@ use Doctrine\ORM\Query\AST;
|
||||
use Doctrine\Common\DoctrineException;
|
||||
|
||||
/**
|
||||
* The SqlWalker walks over an AST that represents a DQL query and constructs
|
||||
* the corresponding SQL. The walking can start at any node, not only at some root
|
||||
* node. Therefore it is possible to only generate SQL parts by simply walking over
|
||||
* certain subtrees of the AST.
|
||||
* The SqlWalker is a TreeWalker that walks over a DQL AST and constructs
|
||||
* the corresponding SQL.
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
* @todo Code review for identifier quoting.
|
||||
*/
|
||||
class SqlWalker
|
||||
class SqlWalker implements TreeWalker
|
||||
{
|
||||
private $_resultSetMapping;
|
||||
/** The ResultSetMapping. */
|
||||
private $_rsm;
|
||||
/** Counter for generating unique column aliases. */
|
||||
private $_aliasCounter = 0;
|
||||
/** Counter for generating unique table aliases. */
|
||||
private $_tableAliasCounter = 0;
|
||||
private $_scalarResultCounter = 0;
|
||||
/** Counter for SQL parameter positions. */
|
||||
private $_sqlParamIndex = 1;
|
||||
/** The ParserResult. */
|
||||
private $_parserResult;
|
||||
/** The EntityManager. */
|
||||
private $_em;
|
||||
/** The Connection of the EntityManager. */
|
||||
private $_conn;
|
||||
/** The parsed Query instance. */
|
||||
private $_query;
|
||||
private $_dqlToSqlAliasMap = array();
|
||||
/** Map of all components/classes that appear in the DQL query. */
|
||||
@ -54,7 +62,10 @@ class SqlWalker
|
||||
* TODO: May need to be turned into a stack for usage in subqueries
|
||||
*/
|
||||
private $_currentRootAlias;
|
||||
/** Flag that indicates whether to generate SQL table aliases in the SQL. */
|
||||
/**
|
||||
* Flag that indicates whether to generate SQL table aliases in the SQL.
|
||||
* These should only be generated for SELECT queries.
|
||||
*/
|
||||
private $_useSqlTableAliases = true;
|
||||
|
||||
/**
|
||||
@ -65,7 +76,7 @@ class SqlWalker
|
||||
*/
|
||||
public function __construct($query, $parserResult, array $queryComponents)
|
||||
{
|
||||
$this->_resultSetMapping = $parserResult->getResultSetMapping();
|
||||
$this->_rsm = $parserResult->getResultSetMapping();
|
||||
$this->_query = $query;
|
||||
$this->_em = $query->getEntityManager();
|
||||
$this->_conn = $this->_em->getConnection();
|
||||
@ -116,9 +127,9 @@ class SqlWalker
|
||||
|
||||
foreach ($this->_selectedClasses as $dqlAlias => $class) {
|
||||
if ($this->_queryComponents[$dqlAlias]['relation'] === null) {
|
||||
$this->_resultSetMapping->addEntityResult($class->name, $dqlAlias);
|
||||
$this->_rsm->addEntityResult($class->name, $dqlAlias);
|
||||
} else {
|
||||
$this->_resultSetMapping->addJoinedEntityResult(
|
||||
$this->_rsm->addJoinedEntityResult(
|
||||
$class->name, $dqlAlias,
|
||||
$this->_queryComponents[$dqlAlias]['parent'],
|
||||
$this->_queryComponents[$dqlAlias]['relation']
|
||||
@ -132,7 +143,7 @@ class SqlWalker
|
||||
$discrColumn = $rootClass->discriminatorColumn;
|
||||
$columnAlias = $this->getSqlColumnAlias($discrColumn['name']);
|
||||
$sql .= ", $tblAlias." . $discrColumn['name'] . ' AS ' . $columnAlias;
|
||||
$this->_resultSetMapping->setDiscriminatorColumn($dqlAlias, $columnAlias);
|
||||
$this->_rsm->setDiscriminatorColumn($dqlAlias, $columnAlias);
|
||||
}
|
||||
//}
|
||||
}
|
||||
@ -204,9 +215,10 @@ class SqlWalker
|
||||
//TODO: support general SingleValuedPathExpression, not just state field
|
||||
$pathExpr = $orderByItem->getStateFieldPathExpression();
|
||||
$parts = $pathExpr->getParts();
|
||||
$qComp = $this->_queryComponents[$parts[0]];
|
||||
$columnName = $qComp['metadata']->getColumnName($parts[1]);
|
||||
$sql = $this->getSqlTableAlias($qComp['metadata']->getTableName() . $parts[0]) . '.' . $columnName;
|
||||
$dqlAlias = $pathExpr->getIdentificationVariable();
|
||||
$qComp = $this->_queryComponents[$dqlAlias];
|
||||
$columnName = $qComp['metadata']->getColumnName($parts[0]);
|
||||
$sql = $this->getSqlTableAlias($qComp['metadata']->getTableName() . $dqlAlias) . '.' . $columnName;
|
||||
$sql .= $orderByItem->isAsc() ? ' ASC' : ' DESC';
|
||||
return $sql;
|
||||
}
|
||||
@ -219,7 +231,6 @@ class SqlWalker
|
||||
*/
|
||||
public function walkHavingClause($havingClause)
|
||||
{
|
||||
// HavingClause ::= "HAVING" ConditionalExpression
|
||||
return ' HAVING ' . implode(' OR ', array_map(array($this, 'walkConditionalTerm'),
|
||||
$havingClause->getConditionalExpression()->getConditionalTerms()));
|
||||
}
|
||||
@ -228,7 +239,7 @@ class SqlWalker
|
||||
* Walks down a JoinVariableDeclaration AST node and creates the corresponding SQL.
|
||||
*
|
||||
* @param JoinVariableDeclaration $joinVarDecl
|
||||
* @return string
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkJoinVariableDeclaration($joinVarDecl)
|
||||
{
|
||||
@ -333,11 +344,11 @@ class SqlWalker
|
||||
{
|
||||
$sql = '';
|
||||
$expr = $selectExpression->getExpression();
|
||||
if ($expr instanceof AST\StateFieldPathExpression) {
|
||||
if ($expr->isSimpleStateFieldPathExpression()) {
|
||||
if ($expr instanceof AST\PathExpression) {
|
||||
if ($expr->getType() == AST\PathExpression::TYPE_STATE_FIELD) {
|
||||
$parts = $expr->getParts();
|
||||
$numParts = count($parts);
|
||||
$dqlAlias = $parts[0];
|
||||
$dqlAlias = $expr->getIdentificationVariable();
|
||||
$fieldName = $parts[$numParts-1];
|
||||
$qComp = $this->_queryComponents[$dqlAlias];
|
||||
$class = $qComp['metadata'];
|
||||
@ -346,21 +357,13 @@ class SqlWalker
|
||||
$this->_selectedClasses[$dqlAlias] = $class;
|
||||
}
|
||||
|
||||
if ($numParts > 2) {
|
||||
for ($i = 1; $i < $numParts-1; ++$i) {
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
||||
$sqlTableAlias = $this->getSqlTableAlias($class->getTableName() . $dqlAlias);
|
||||
$columnName = $class->getColumnName($fieldName);
|
||||
$columnAlias = $this->getSqlColumnAlias($columnName);
|
||||
$sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias;
|
||||
|
||||
$this->_resultSetMapping->addFieldResult($dqlAlias, $columnAlias, $fieldName);
|
||||
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName);
|
||||
|
||||
} else if ($expr->isSimpleStateFieldAssociationPathExpression()) {
|
||||
throw DoctrineException::updateMe("Not yet implemented.");
|
||||
} else {
|
||||
throw DoctrineException::updateMe("Encountered invalid PathExpression during SQL construction.");
|
||||
}
|
||||
@ -372,7 +375,7 @@ class SqlWalker
|
||||
}
|
||||
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||
$sql .= $this->walkAggregateExpression($expr) . ' AS ' . $columnAlias;
|
||||
$this->_resultSetMapping->addScalarResult($columnAlias, $resultAlias);
|
||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||
} else if ($expr instanceof AST\Subselect) {
|
||||
$sql .= $this->walkSubselect($expr);
|
||||
} else if ($expr instanceof AST\Functions\FunctionNode) {
|
||||
@ -383,7 +386,7 @@ class SqlWalker
|
||||
}
|
||||
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||
$sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias;
|
||||
$this->_resultSetMapping->addScalarResult($columnAlias, $resultAlias);
|
||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||
} else {
|
||||
// IdentificationVariable
|
||||
|
||||
@ -408,7 +411,7 @@ class SqlWalker
|
||||
$sqlTableAlias = $this->getSqlTableAlias($tableName . $dqlAlias);
|
||||
$columnAlias = $this->getSqlColumnAlias($mapping['columnName']);
|
||||
$sql .= $sqlTableAlias . '.' . $this->_conn->quoteIdentifier($mapping['columnName']) . ' AS ' . $columnAlias;
|
||||
$this->_resultSetMapping->addFieldResult($dqlAlias, $columnAlias, $fieldName);
|
||||
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName);
|
||||
}
|
||||
|
||||
// Add any additional fields of subclasses (not inherited fields)
|
||||
@ -422,7 +425,7 @@ class SqlWalker
|
||||
$sqlTableAlias = $this->getSqlTableAlias($subClass->primaryTable['name'] . $dqlAlias);
|
||||
$columnAlias = $this->getSqlColumnAlias($mapping['columnName']);
|
||||
$sql .= $sqlTableAlias . '.' . $this->_conn->quoteIdentifier($mapping['columnName']) . ' AS ' . $columnAlias;
|
||||
$this->_resultSetMapping->addFieldResult($dqlAlias, $columnAlias, $fieldName);
|
||||
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -438,7 +441,7 @@ class SqlWalker
|
||||
if ($beginning) $beginning = false; else $sql .= ', ';
|
||||
$columnAlias = $this->getSqlColumnAlias($mapping['columnName']);
|
||||
$sql .= $sqlTableAlias . '.' . $this->_conn->quoteIdentifier($mapping['columnName']) . ' AS ' . $columnAlias;
|
||||
$this->_resultSetMapping->addFieldResult($dqlAlias, $columnAlias, $fieldName);
|
||||
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -530,7 +533,7 @@ class SqlWalker
|
||||
{
|
||||
$sql = '';
|
||||
$expr = $simpleSelectExpression->getExpression();
|
||||
if ($expr instanceof AST\StateFieldPathExpression) {
|
||||
if ($expr instanceof AST\PathExpression) {
|
||||
$sql .= ' ' . $this->walkPathExpression($expr);
|
||||
//...
|
||||
} else if ($expr instanceof AST\AggregateExpression) {
|
||||
@ -561,8 +564,8 @@ class SqlWalker
|
||||
{
|
||||
$sql = '';
|
||||
$parts = $aggExpression->getPathExpression()->getParts();
|
||||
$dqlAlias = $parts[0];
|
||||
$fieldName = $parts[1];
|
||||
$dqlAlias = $aggExpression->getPathExpression()->getIdentificationVariable();
|
||||
$fieldName = $parts[0];
|
||||
|
||||
$qComp = $this->_queryComponents[$dqlAlias];
|
||||
$columnName = $qComp['metadata']->getColumnName($fieldName);
|
||||
@ -593,13 +596,14 @@ class SqlWalker
|
||||
* @param GroupByItem
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkGroupByItem($pathExpr)
|
||||
public function walkGroupByItem(AST\PathExpression $pathExpr)
|
||||
{
|
||||
//TODO: support general SingleValuedPathExpression, not just state field
|
||||
$parts = $pathExpr->getParts();
|
||||
$qComp = $this->_queryComponents[$parts[0]];
|
||||
$columnName = $qComp['metadata']->getColumnName($parts[1]);
|
||||
return $this->getSqlTableAlias($qComp['metadata']->getTableName() . $parts[0]) . '.' . $columnName;
|
||||
$dqlAlias = $pathExpr->getIdentificationVariable();
|
||||
$qComp = $this->_queryComponents[$dqlAlias];
|
||||
$columnName = $qComp['metadata']->getColumnName($parts[0]);
|
||||
return $this->getSqlTableAlias($qComp['metadata']->getTableName() . $dqlAlias) . '.' . $columnName;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -704,7 +708,7 @@ class SqlWalker
|
||||
if (strcasecmp($newValue, 'NULL') === 0) {
|
||||
$sql .= 'NULL';
|
||||
} else {
|
||||
$sql .= $newValue; //TODO: quote()
|
||||
$sql .= $this->_conn->quote($newValue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -756,8 +760,6 @@ class SqlWalker
|
||||
$sql .= $this->getSqlTableAlias($class->getTableName() . $dqlAlias) . '.';
|
||||
}
|
||||
$sql .= $discrColumn['name'] . ' IN (' . implode(', ', $values) . ')';
|
||||
} else if ($class->isInheritanceTypeJoined()) {
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
return $sql;
|
||||
@ -809,6 +811,97 @@ class SqlWalker
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks down a CollectionMemberExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param CollectionMemberExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkCollectionMemberExpression($collMemberExpr)
|
||||
{
|
||||
$sql = $collMemberExpr->isNot ? 'NOT ' : '';
|
||||
$sql .= 'EXISTS (SELECT 1 FROM ';
|
||||
$entityExpr = $collMemberExpr->entityExpression;
|
||||
$collPathExpr = $collMemberExpr->collectionValuedPathExpression;
|
||||
$parts = $collPathExpr->getParts();
|
||||
$dqlAlias = $collPathExpr->getIdentificationVariable();
|
||||
|
||||
$class = $this->_queryComponents[$dqlAlias]['metadata'];
|
||||
|
||||
if ($entityExpr instanceof AST\InputParameter) {
|
||||
$dqlParamKey = $entityExpr->isNamed() ? $entityExpr->getName() : $entityExpr->getPosition();
|
||||
$entity = $this->_query->getParameter($dqlParamKey);
|
||||
|
||||
} else {
|
||||
throw DoctrineException::notImplemented();
|
||||
}
|
||||
|
||||
$assoc = $class->associationMappings[$parts[0]];
|
||||
if ($assoc->isOneToMany()) {
|
||||
$targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
|
||||
$targetTableAlias = $this->getSqlTableAlias($targetClass->primaryTable['name']);
|
||||
$sourceTableAlias = $this->getSqlTableAlias($class->primaryTable['name'] . $dqlAlias);
|
||||
|
||||
$sql .= $this->_conn->quoteIdentifier($targetClass->primaryTable['name'])
|
||||
. ' ' . $targetTableAlias . ' WHERE ';
|
||||
|
||||
$owningAssoc = $targetClass->associationMappings[$assoc->mappedByFieldName];
|
||||
|
||||
$first = true;
|
||||
foreach ($owningAssoc->targetToSourceKeyColumns as $targetColumn => $sourceColumn) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$sql .= $sourceTableAlias . '.' . $targetColumn . ' = ' . $targetTableAlias . '.' . $sourceColumn;
|
||||
}
|
||||
|
||||
$sql .= ' AND ';
|
||||
$first = true;
|
||||
foreach ($targetClass->identifier as $idField) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
|
||||
$sql .= $targetTableAlias . '.' . $targetClass->columnNames[$idField] . ' = ?';
|
||||
}
|
||||
} else { // many-to-many
|
||||
$targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
|
||||
$sourceTableAlias = $this->getSqlTableAlias($class->primaryTable['name'] . $dqlAlias);
|
||||
$joinTable = $assoc->isOwningSide ? $assoc->joinTable : $targetClass->associationMappings[$assoc->mappedByFieldName]->joinTable;
|
||||
$joinTableAlias = $this->getSqlTableAlias($joinTable['name']);
|
||||
$targetTableAlias = $this->getSqlTableAlias($targetClass->primaryTable['name']);
|
||||
|
||||
// join to target table
|
||||
$sql .= $this->_conn->quoteIdentifier($joinTable['name'])
|
||||
. ' ' . $joinTableAlias . ' INNER JOIN '
|
||||
. $this->_conn->quoteIdentifier($targetClass->primaryTable['name'])
|
||||
. ' ' . $targetTableAlias . ' ON ';
|
||||
|
||||
// join conditions
|
||||
$joinColumns = $assoc->isOwningSide ? $joinTable['joinColumns'] : $joinTable['inverseJoinColumns'];
|
||||
$first = true;
|
||||
foreach ($joinColumns as $joinColumn) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$sql .= $joinTableAlias . '.' . $joinColumn['name'] . ' = ' . $sourceTableAlias . '.' . $joinColumn['referencedColumnName'];
|
||||
}
|
||||
|
||||
$sql .= ' WHERE ';
|
||||
|
||||
$joinColumns = $assoc->isOwningSide ? $joinTable['inverseJoinColumns'] : $joinTable['joinColumns'];
|
||||
$first = true;
|
||||
foreach ($joinColumns as $joinColumn) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$sql .= $joinTableAlias . '.' . $joinColumn['name'] . ' = ' . $targetTableAlias . '.' . $joinColumn['referencedColumnName'];
|
||||
}
|
||||
|
||||
$sql .= ' AND ';
|
||||
$first = true;
|
||||
foreach ($targetClass->identifier as $idField) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
|
||||
$sql .= $targetTableAlias . '.' . $targetClass->columnNames[$idField] . ' = ?';
|
||||
}
|
||||
}
|
||||
|
||||
return $sql . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks down a NullComparisonExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
@ -820,7 +913,9 @@ class SqlWalker
|
||||
$sql = '';
|
||||
$innerExpr = $nullCompExpr->getExpression();
|
||||
if ($innerExpr instanceof AST\InputParameter) {
|
||||
$sql .= ' ' . ($innerExpr->isNamed() ? ':' . $innerExpr->getName() : '?');
|
||||
$dqlParamKey = $innerExpr->isNamed() ? $innerExpr->getName() : $innerExpr->getPosition();
|
||||
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
|
||||
$sql .= ' ?';// . ($innerExpr->isNamed() ? ':' . $innerExpr->getName() : '?');
|
||||
} else {
|
||||
$sql .= $this->walkPathExpression($innerExpr);
|
||||
}
|
||||
@ -857,7 +952,10 @@ class SqlWalker
|
||||
public function walkLiteral($literal)
|
||||
{
|
||||
if ($literal instanceof AST\InputParameter) {
|
||||
return ($literal->isNamed() ? ':' . $literal->getName() : '?');
|
||||
$dqlParamKey = $literal->isNamed() ? $literal->getName() : $literal->getPosition();
|
||||
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
|
||||
//return ($literal->isNamed() ? ':' . $literal->getName() : '?');
|
||||
return '?';
|
||||
} else {
|
||||
return $literal; //TODO: quote() ?
|
||||
}
|
||||
@ -896,12 +994,15 @@ class SqlWalker
|
||||
|
||||
if ($likeExpr->getStringPattern() instanceof AST\InputParameter) {
|
||||
$inputParam = $likeExpr->getStringPattern();
|
||||
$sql .= $inputParam->isNamed() ? ':' . $inputParam->getName() : '?';
|
||||
$dqlParamKey = $inputParam->isNamed() ? $inputParam->getName() : $inputParam->getPosition();
|
||||
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
|
||||
//$sql .= $inputParam->isNamed() ? ':' . $inputParam->getName() : '?';
|
||||
$sql .= '?';
|
||||
} else {
|
||||
$sql .= $likeExpr->getStringPattern();
|
||||
$sql .= $this->_conn->quote($likeExpr->getStringPattern());
|
||||
}
|
||||
if ($likeExpr->getEscapeChar()) {
|
||||
$sql .= ' ESCAPE ' . $likeExpr->getEscapeChar();
|
||||
$sql .= ' ESCAPE ' . $this->_conn->quote($likeExpr->getEscapeChar());
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
@ -954,7 +1055,9 @@ class SqlWalker
|
||||
*/
|
||||
public function walkInputParameter($inputParam)
|
||||
{
|
||||
return $inputParam->isNamed() ? ':' . $inputParam->getName() : '?';
|
||||
$dqlParamKey = $inputParam->isNamed() ? $inputParam->getName() : $inputParam->getPosition();
|
||||
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
|
||||
return '?';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -999,7 +1102,7 @@ class SqlWalker
|
||||
public function walkStringPrimary($stringPrimary)
|
||||
{
|
||||
if (is_string($stringPrimary)) {
|
||||
return $stringPrimary;
|
||||
return $this->_conn->quote($stringPrimary);
|
||||
} else {
|
||||
return $stringPrimary->dispatch($this);
|
||||
}
|
||||
@ -1021,7 +1124,7 @@ class SqlWalker
|
||||
$sql .= $primary; //TODO: quote() ?
|
||||
} else if (is_string($primary)) {
|
||||
//TODO: quote string according to platform
|
||||
$sql .= $primary;
|
||||
$sql .= $this->_conn->quote($primary);
|
||||
} else if ($primary instanceof AST\SimpleArithmeticExpression) {
|
||||
$sql .= '(' . $this->walkSimpleArithmeticExpression($primary) . ')';
|
||||
} else if ($primary instanceof AST\Node) {
|
||||
@ -1052,10 +1155,10 @@ class SqlWalker
|
||||
public function walkPathExpression($pathExpr)
|
||||
{
|
||||
$sql = '';
|
||||
if ($pathExpr->isSimpleStateFieldPathExpression()) {
|
||||
if ($pathExpr->getType() == AST\PathExpression::TYPE_STATE_FIELD) {
|
||||
$parts = $pathExpr->getParts();
|
||||
$numParts = count($parts);
|
||||
$dqlAlias = $parts[0];
|
||||
$dqlAlias = $pathExpr->getIdentificationVariable();
|
||||
$fieldName = $parts[$numParts-1];
|
||||
$qComp = $this->_queryComponents[$dqlAlias];
|
||||
$class = $qComp['metadata'];
|
||||
|
336
lib/Doctrine/ORM/Query/TreeWalker.php
Normal file
336
lib/Doctrine/ORM/Query/TreeWalker.php
Normal file
@ -0,0 +1,336 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\ORM\Query;
|
||||
|
||||
/**
|
||||
* Interface for walkers of DQL ASTs (abstract syntax trees).
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
*/
|
||||
interface TreeWalker
|
||||
{
|
||||
/**
|
||||
* Walks down a SelectStatement AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkSelectStatement(AST\SelectStatement $AST);
|
||||
|
||||
/**
|
||||
* Walks down a SelectClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkSelectClause($selectClause);
|
||||
|
||||
/**
|
||||
* Walks down a FromClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkFromClause($fromClause);
|
||||
|
||||
/**
|
||||
* Walks down a FunctionNode AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkFunction($function);
|
||||
|
||||
/**
|
||||
* Walks down an OrderByClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param OrderByClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkOrderByClause($orderByClause);
|
||||
|
||||
/**
|
||||
* Walks down an OrderByItem AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param OrderByItem
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkOrderByItem($orderByItem);
|
||||
|
||||
/**
|
||||
* Walks down a HavingClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param HavingClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkHavingClause($havingClause);
|
||||
|
||||
/**
|
||||
* Walks down a JoinVariableDeclaration AST node and creates the corresponding SQL.
|
||||
*
|
||||
* @param JoinVariableDeclaration $joinVarDecl
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkJoinVariableDeclaration($joinVarDecl);
|
||||
|
||||
/**
|
||||
* Walks down a SelectExpression AST node and generates the corresponding SQL.
|
||||
*
|
||||
* @param SelectExpression $selectExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkSelectExpression($selectExpression);
|
||||
|
||||
/**
|
||||
* Walks down a QuantifiedExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param QuantifiedExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkQuantifiedExpression($qExpr);
|
||||
|
||||
/**
|
||||
* Walks down a Subselect AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param Subselect
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkSubselect($subselect);
|
||||
|
||||
/**
|
||||
* Walks down a SubselectFromClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param SubselectFromClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkSubselectFromClause($subselectFromClause);
|
||||
|
||||
/**
|
||||
* Walks down a SimpleSelectClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param SimpleSelectClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkSimpleSelectClause($simpleSelectClause);
|
||||
|
||||
/**
|
||||
* Walks down a SimpleSelectExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param SimpleSelectExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkSimpleSelectExpression($simpleSelectExpression);
|
||||
|
||||
/**
|
||||
* Walks down an AggregateExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param AggregateExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkAggregateExpression($aggExpression);
|
||||
|
||||
/**
|
||||
* Walks down a GroupByClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param GroupByClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkGroupByClause($groupByClause);
|
||||
|
||||
/**
|
||||
* Walks down a GroupByItem AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param GroupByItem
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkGroupByItem(AST\PathExpression $pathExpr);
|
||||
|
||||
/**
|
||||
* Walks down an UpdateStatement AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param UpdateStatement
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkUpdateStatement(AST\UpdateStatement $AST);
|
||||
|
||||
/**
|
||||
* Walks down a DeleteStatement AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param DeleteStatement
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkDeleteStatement(AST\DeleteStatement $AST);
|
||||
|
||||
/**
|
||||
* Walks down a DeleteClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param DeleteClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkDeleteClause(AST\DeleteClause $deleteClause);
|
||||
|
||||
/**
|
||||
* Walks down an UpdateClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param UpdateClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkUpdateClause($updateClause);
|
||||
|
||||
/**
|
||||
* Walks down an UpdateItem AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param UpdateItem
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkUpdateItem($updateItem);
|
||||
|
||||
/**
|
||||
* Walks down a WhereClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param WhereClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkWhereClause($whereClause);
|
||||
|
||||
/**
|
||||
* Walks down a ConditionalTerm AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param ConditionalTerm
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkConditionalTerm($condTerm);
|
||||
|
||||
/**
|
||||
* Walks down a ConditionalFactor AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param ConditionalFactor
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkConditionalFactor($factor);
|
||||
|
||||
/**
|
||||
* Walks down an ExistsExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param ExistsExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkExistsExpression($existsExpr);
|
||||
|
||||
/**
|
||||
* Walks down a CollectionMemberExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param CollectionMemberExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkCollectionMemberExpression($collMemberExpr);
|
||||
|
||||
/**
|
||||
* Walks down a NullComparisonExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param NullComparisonExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkNullComparisonExpression($nullCompExpr);
|
||||
|
||||
/**
|
||||
* Walks down an InExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param InExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkInExpression($inExpr);
|
||||
|
||||
/**
|
||||
* Walks down a literal that represents an AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param mixed
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkLiteral($literal);
|
||||
|
||||
/**
|
||||
* Walks down a BetweenExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param BetweenExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkBetweenExpression($betweenExpr);
|
||||
|
||||
/**
|
||||
* Walks down a LikeExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param LikeExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkLikeExpression($likeExpr);
|
||||
|
||||
/**
|
||||
* Walks down a StateFieldPathExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param StateFieldPathExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkStateFieldPathExpression($stateFieldPathExpression);
|
||||
|
||||
/**
|
||||
* Walks down a ComparisonExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param ComparisonExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkComparisonExpression($compExpr);
|
||||
|
||||
/**
|
||||
* Walks down an InputParameter AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param InputParameter
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkInputParameter($inputParam);
|
||||
|
||||
/**
|
||||
* Walks down an ArithmeticExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param ArithmeticExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkArithmeticExpression($arithmeticExpr);
|
||||
|
||||
/**
|
||||
* Walks down an ArithmeticTerm AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param mixed
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkArithmeticTerm($term);
|
||||
|
||||
/**
|
||||
* Walks down a StringPrimary that represents an AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param mixed
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkStringPrimary($stringPrimary);
|
||||
|
||||
/**
|
||||
* Walks down an ArithmeticFactor that represents an AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param mixed
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkArithmeticFactor($factor);
|
||||
|
||||
/**
|
||||
* Walks down an SimpleArithmeticExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param SimpleArithmeticExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkSimpleArithmeticExpression($simpleArithmeticExpr);
|
||||
|
||||
/**
|
||||
* Walks down an PathExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param mixed
|
||||
* @return string The SQL.
|
||||
*/
|
||||
function walkPathExpression($pathExpr);
|
||||
}
|
337
lib/Doctrine/ORM/Query/TreeWalkerAdapter.php
Normal file
337
lib/Doctrine/ORM/Query/TreeWalkerAdapter.php
Normal file
@ -0,0 +1,337 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\ORM\Query;
|
||||
|
||||
/**
|
||||
* An adapter implementation of the TreeWalker interface. The methods in this class
|
||||
* are empty. This class exists as convenience for creating tree walkers.
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
*/
|
||||
abstract class TreeWalkerAdapter implements TreeWalker
|
||||
{
|
||||
/**
|
||||
* Walks down a SelectStatement AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkSelectStatement(AST\SelectStatement $AST) {}
|
||||
|
||||
/**
|
||||
* Walks down a SelectClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkSelectClause($selectClause) {}
|
||||
|
||||
/**
|
||||
* Walks down a FromClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkFromClause($fromClause) {}
|
||||
|
||||
/**
|
||||
* Walks down a FunctionNode AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkFunction($function) {}
|
||||
|
||||
/**
|
||||
* Walks down an OrderByClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param OrderByClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkOrderByClause($orderByClause) {}
|
||||
|
||||
/**
|
||||
* Walks down an OrderByItem AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param OrderByItem
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkOrderByItem($orderByItem) {}
|
||||
|
||||
/**
|
||||
* Walks down a HavingClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param HavingClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkHavingClause($havingClause) {}
|
||||
|
||||
/**
|
||||
* Walks down a JoinVariableDeclaration AST node and creates the corresponding SQL.
|
||||
*
|
||||
* @param JoinVariableDeclaration $joinVarDecl
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkJoinVariableDeclaration($joinVarDecl) {}
|
||||
|
||||
/**
|
||||
* Walks down a SelectExpression AST node and generates the corresponding SQL.
|
||||
*
|
||||
* @param SelectExpression $selectExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkSelectExpression($selectExpression) {}
|
||||
|
||||
/**
|
||||
* Walks down a QuantifiedExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param QuantifiedExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkQuantifiedExpression($qExpr) {}
|
||||
|
||||
/**
|
||||
* Walks down a Subselect AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param Subselect
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkSubselect($subselect) {}
|
||||
|
||||
/**
|
||||
* Walks down a SubselectFromClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param SubselectFromClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkSubselectFromClause($subselectFromClause) {}
|
||||
|
||||
/**
|
||||
* Walks down a SimpleSelectClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param SimpleSelectClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkSimpleSelectClause($simpleSelectClause) {}
|
||||
|
||||
/**
|
||||
* Walks down a SimpleSelectExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param SimpleSelectExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkSimpleSelectExpression($simpleSelectExpression) {}
|
||||
|
||||
/**
|
||||
* Walks down an AggregateExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param AggregateExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkAggregateExpression($aggExpression) {}
|
||||
|
||||
/**
|
||||
* Walks down a GroupByClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param GroupByClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkGroupByClause($groupByClause) {}
|
||||
|
||||
/**
|
||||
* Walks down a GroupByItem AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param GroupByItem
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkGroupByItem(AST\PathExpression $pathExpr) {}
|
||||
|
||||
/**
|
||||
* Walks down an UpdateStatement AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param UpdateStatement
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkUpdateStatement(AST\UpdateStatement $AST) {}
|
||||
|
||||
/**
|
||||
* Walks down a DeleteStatement AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param DeleteStatement
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkDeleteStatement(AST\DeleteStatement $AST) {}
|
||||
|
||||
/**
|
||||
* Walks down a DeleteClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param DeleteClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkDeleteClause(AST\DeleteClause $deleteClause) {}
|
||||
|
||||
/**
|
||||
* Walks down an UpdateClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param UpdateClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkUpdateClause($updateClause) {}
|
||||
|
||||
/**
|
||||
* Walks down an UpdateItem AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param UpdateItem
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkUpdateItem($updateItem) {}
|
||||
|
||||
/**
|
||||
* Walks down a WhereClause AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param WhereClause
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkWhereClause($whereClause) {}
|
||||
|
||||
/**
|
||||
* Walks down a ConditionalTerm AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param ConditionalTerm
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkConditionalTerm($condTerm) {}
|
||||
|
||||
/**
|
||||
* Walks down a ConditionalFactor AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param ConditionalFactor
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkConditionalFactor($factor) {}
|
||||
|
||||
/**
|
||||
* Walks down an ExistsExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param ExistsExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkExistsExpression($existsExpr) {}
|
||||
|
||||
/**
|
||||
* Walks down a CollectionMemberExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param CollectionMemberExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkCollectionMemberExpression($collMemberExpr) {}
|
||||
|
||||
/**
|
||||
* Walks down a NullComparisonExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param NullComparisonExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkNullComparisonExpression($nullCompExpr) {}
|
||||
|
||||
/**
|
||||
* Walks down an InExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param InExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkInExpression($inExpr) {}
|
||||
|
||||
/**
|
||||
* Walks down a literal that represents an AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param mixed
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkLiteral($literal) {}
|
||||
|
||||
/**
|
||||
* Walks down a BetweenExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param BetweenExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkBetweenExpression($betweenExpr) {}
|
||||
|
||||
/**
|
||||
* Walks down a LikeExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param LikeExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkLikeExpression($likeExpr) {}
|
||||
|
||||
/**
|
||||
* Walks down a StateFieldPathExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param StateFieldPathExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkStateFieldPathExpression($stateFieldPathExpression) {}
|
||||
|
||||
/**
|
||||
* Walks down a ComparisonExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param ComparisonExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkComparisonExpression($compExpr) {}
|
||||
|
||||
/**
|
||||
* Walks down an InputParameter AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param InputParameter
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkInputParameter($inputParam) {}
|
||||
|
||||
/**
|
||||
* Walks down an ArithmeticExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param ArithmeticExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkArithmeticExpression($arithmeticExpr) {}
|
||||
|
||||
/**
|
||||
* Walks down an ArithmeticTerm AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param mixed
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkArithmeticTerm($term) {}
|
||||
|
||||
/**
|
||||
* Walks down a StringPrimary that represents an AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param mixed
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkStringPrimary($stringPrimary) {}
|
||||
|
||||
/**
|
||||
* Walks down an ArithmeticFactor that represents an AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param mixed
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkArithmeticFactor($factor) {}
|
||||
|
||||
/**
|
||||
* Walks down an SimpleArithmeticExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param SimpleArithmeticExpression
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkSimpleArithmeticExpression($simpleArithmeticExpr) {}
|
||||
|
||||
/**
|
||||
* Walks down an PathExpression AST node, thereby generating the appropriate SQL.
|
||||
*
|
||||
* @param mixed
|
||||
* @return string The SQL.
|
||||
*/
|
||||
public function walkPathExpression($pathExpr) {}
|
||||
}
|
@ -224,6 +224,7 @@ class SchemaTool
|
||||
if (isset($class->inheritedAssociationFields[$fieldName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$foreignClass = $this->_em->getClassMetadata($mapping->targetEntityName);
|
||||
if ($mapping->isOneToOne() && $mapping->isOwningSide) {
|
||||
$constraint = array();
|
||||
|
@ -403,9 +403,11 @@ class UnitOfWork implements PropertyChangedListener
|
||||
&& $actualData[$name] !== null
|
||||
&& ! ($actualData[$name] instanceof PersistentCollection)
|
||||
) {
|
||||
//TODO: If $actualData[$name] is Collection then unwrap the array
|
||||
// If $actualData[$name] is Collection then unwrap the array
|
||||
if ($actualData[$name] instanceof Collection) {
|
||||
$actualData[$name] = $actualData[$name]->unwrap();
|
||||
}
|
||||
$assoc = $class->associationMappings[$name];
|
||||
//echo PHP_EOL . "INJECTING PCOLL into $name" . PHP_EOL;
|
||||
// Inject PersistentCollection
|
||||
$coll = new PersistentCollection($this->_em, $this->_em->getClassMetadata($assoc->targetEntityName),
|
||||
$actualData[$name] ? $actualData[$name] : array());
|
||||
|
@ -19,9 +19,9 @@ class CollectionTest extends \Doctrine\Tests\DoctrineTestCase
|
||||
{
|
||||
$this->_coll->add("one");
|
||||
$this->_coll->add("two");
|
||||
$exists = $this->_coll->exists(function($key, $element) { return $element == "one"; });
|
||||
$exists = $this->_coll->exists(function($k, $e) { return $e == "one"; });
|
||||
$this->assertTrue($exists);
|
||||
$exists = $this->_coll->exists(function($key, $element) { return $element == "other"; });
|
||||
$exists = $this->_coll->exists(function($k, $e) { return $e == "other"; });
|
||||
$this->assertFalse($exists);
|
||||
}
|
||||
|
||||
@ -66,39 +66,39 @@ class CollectionTest extends \Doctrine\Tests\DoctrineTestCase
|
||||
public function testContainsKey()
|
||||
{
|
||||
$this->_coll[5] = 'five';
|
||||
$this->assertEquals($this->_coll->containsKey(5), true);
|
||||
$this->assertTrue($this->_coll->containsKey(5));
|
||||
}
|
||||
|
||||
public function testContains()
|
||||
{
|
||||
$this->_coll[0] = 'test';
|
||||
$this->assertEquals($this->_coll->contains('test'), true);
|
||||
$this->assertTrue($this->_coll->contains('test'));
|
||||
}
|
||||
|
||||
public function testSearch()
|
||||
{
|
||||
$this->_coll[0] = 'test';
|
||||
$this->assertEquals($this->_coll->search('test'), 0);
|
||||
$this->assertEquals(0, $this->_coll->search('test'));
|
||||
}
|
||||
|
||||
public function testGet()
|
||||
{
|
||||
$this->_coll[0] = 'test';
|
||||
$this->assertEquals($this->_coll->get(0), 'test');
|
||||
$this->assertEquals('test', $this->_coll->get(0));
|
||||
}
|
||||
|
||||
public function testGetKeys()
|
||||
{
|
||||
$this->_coll[] = 'one';
|
||||
$this->_coll[] = 'two';
|
||||
$this->assertEquals($this->_coll->getKeys(), array(0, 1));
|
||||
$this->assertEquals(array(0, 1), $this->_coll->getKeys());
|
||||
}
|
||||
|
||||
public function testGetElements()
|
||||
{
|
||||
$this->_coll[] = 'one';
|
||||
$this->_coll[] = 'two';
|
||||
$this->assertEquals($this->_coll->getElements(), array('one', 'two'));
|
||||
$this->assertEquals(array('one', 'two'), $this->_coll->getElements());
|
||||
}
|
||||
|
||||
public function testCount()
|
||||
@ -113,15 +113,15 @@ class CollectionTest extends \Doctrine\Tests\DoctrineTestCase
|
||||
{
|
||||
$this->_coll[] = 'one';
|
||||
$this->_coll[] = 'two';
|
||||
$this->assertEquals($this->_coll->forAll(function($key, $element) { return is_string($element); }), true);
|
||||
$this->assertEquals($this->_coll->forAll(function($key, $element) { return is_array($element); }), false);
|
||||
$this->assertEquals($this->_coll->forAll(function($k, $e) { return is_string($e); }), true);
|
||||
$this->assertEquals($this->_coll->forAll(function($k, $e) { return is_array($e); }), false);
|
||||
}
|
||||
|
||||
public function testPartition()
|
||||
{
|
||||
$this->_coll[] = true;
|
||||
$this->_coll[] = false;
|
||||
$partition = $this->_coll->partition(function($key, $element) { return $element == true; });
|
||||
$partition = $this->_coll->partition(function($k, $e) { return $e == true; });
|
||||
$this->assertEquals($partition[0][0], true);
|
||||
$this->assertEquals($partition[1][0], false);
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
|
||||
*/
|
||||
public function quote($input, $type = null)
|
||||
{
|
||||
if ($type === 'string') {
|
||||
if (is_string($input)) {
|
||||
return "'" . $input . "'";
|
||||
}
|
||||
return $input;
|
||||
|
9
tests/Doctrine/Tests/Mocks/MockTreeWalker.php
Normal file
9
tests/Doctrine/Tests/Mocks/MockTreeWalker.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\Mocks;
|
||||
|
||||
class MockTreeWalker extends \Doctrine\ORM\Query\TreeWalkerAdapter
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -32,6 +32,14 @@ class CompanyPerson
|
||||
*/
|
||||
private $spouse;
|
||||
|
||||
/**
|
||||
* @ManyToMany(targetEntity="CompanyPerson")
|
||||
* @JoinTable(name="company_persons_friends",
|
||||
joinColumns={{"name"="person_id", "referencedColumnName"="id"}},
|
||||
inverseJoinColumns={{"name"="friend_id", "referencedColumnName"="id"}})
|
||||
*/
|
||||
private $friends;
|
||||
|
||||
public function getId() {
|
||||
return $this->id;
|
||||
}
|
||||
@ -48,6 +56,20 @@ class CompanyPerson
|
||||
return $this->spouse;
|
||||
}
|
||||
|
||||
public function getFriends() {
|
||||
return $this->friends;
|
||||
}
|
||||
|
||||
public function addFriend(CompanyPerson $friend) {
|
||||
if ( ! $this->friends) {
|
||||
$this->friends = new \Doctrine\Common\Collections\Collection;
|
||||
}
|
||||
if ( ! $this->friends->contains($friend)) {
|
||||
$this->friends->add($friend);
|
||||
$friend->addFriend($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function setSpouse(CompanyPerson $spouse) {
|
||||
if ($spouse !== $this->spouse) {
|
||||
$this->spouse = $spouse;
|
||||
|
@ -65,28 +65,6 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals(100000, $entities[0]->getSalary());
|
||||
|
||||
$this->_em->clear();
|
||||
/*
|
||||
$query = $this->_em->createQuery("select r,o from Doctrine\Tests\ORM\Functional\RelatedEntity r join r.owner o");
|
||||
|
||||
$entities = $query->getResultList();
|
||||
$this->assertEquals(1, count($entities));
|
||||
$this->assertTrue($entities[0] instanceof RelatedEntity);
|
||||
$this->assertTrue(is_numeric($entities[0]->getId()));
|
||||
$this->assertEquals('theRelatedOne', $entities[0]->getName());
|
||||
$this->assertTrue($entities[0]->getOwner() instanceof ChildEntity);
|
||||
$this->assertEquals('thedata', $entities[0]->getOwner()->getData());
|
||||
$this->assertSame($entities[0], $entities[0]->getOwner()->getRelatedEntity());
|
||||
|
||||
$query = $this->_em->createQuery("update Doctrine\Tests\ORM\Functional\ChildEntity e set e.data = 'newdata'");
|
||||
|
||||
$affected = $query->execute();
|
||||
$this->assertEquals(1, $affected);
|
||||
|
||||
$query = $this->_em->createQuery("delete Doctrine\Tests\ORM\Functional\ParentEntity e");
|
||||
|
||||
$affected = $query->execute();
|
||||
$this->assertEquals(2, $affected);
|
||||
*/
|
||||
}
|
||||
|
||||
public function testMultiLevelUpdateAndFind() {
|
||||
@ -149,4 +127,37 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
$this->assertEquals('John Smith', $result[0]->getSpouse()->getName());
|
||||
$this->assertSame($result[0], $result[0]->getSpouse()->getSpouse());
|
||||
}
|
||||
|
||||
public function testSelfReferencingManyToMany()
|
||||
{
|
||||
$person1 = new CompanyPerson;
|
||||
$person1->setName('Roman');
|
||||
|
||||
$person2 = new CompanyPerson;
|
||||
$person2->setName('Jonathan');
|
||||
|
||||
$person1->addFriend($person2);
|
||||
|
||||
$this->assertEquals(1, count($person1->getFriends()));
|
||||
$this->assertEquals(1, count($person2->getFriends()));
|
||||
|
||||
|
||||
$this->_em->save($person1);
|
||||
$this->_em->save($person2);
|
||||
|
||||
$this->_em->flush();
|
||||
|
||||
$this->_em->clear();
|
||||
|
||||
$query = $this->_em->createQuery('select p, f from Doctrine\Tests\Models\Company\CompanyPerson p join p.friends f where p.name=?1');
|
||||
$query->setParameter(1, 'Roman');
|
||||
|
||||
$result = $query->getResultList();
|
||||
$this->assertEquals(1, count($result));
|
||||
$this->assertEquals(1, count($result[0]->getFriends()));
|
||||
$this->assertEquals('Roman', $result[0]->getName());
|
||||
|
||||
$friends = $result[0]->getFriends();
|
||||
$this->assertEquals('Jonathan', $friends[0]->getName());
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,9 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
|
||||
{
|
||||
try {
|
||||
$query = $this->_em->createQuery($dql);
|
||||
$parserResult = $query->parse();
|
||||
$parser = new \Doctrine\ORM\Query\Parser($query);
|
||||
$parser->setSqlTreeWalker(new \Doctrine\Tests\Mocks\MockTreeWalker);
|
||||
$parserResult = $parser->parse();
|
||||
} catch (\Exception $e) {
|
||||
if ($debug) {
|
||||
echo $e->getTraceAsString() . PHP_EOL;
|
||||
@ -30,15 +32,15 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
|
||||
try {
|
||||
$query = $this->_em->createQuery($dql);
|
||||
$query->setDql($dql);
|
||||
$parserResult = $query->parse();
|
||||
$parser = new \Doctrine\ORM\Query\Parser($query);
|
||||
$parser->setSqlTreeWalker(new \Doctrine\Tests\Mocks\MockTreeWalker);
|
||||
$parserResult = $parser->parse();
|
||||
$this->fail('No syntax errors were detected, when syntax errors were expected');
|
||||
} catch (\Exception $e) {
|
||||
//echo $e->getMessage() . PHP_EOL;
|
||||
if ($debug) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
echo $e->getTraceAsString() . PHP_EOL;
|
||||
}
|
||||
// It was expected!
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,4 +321,9 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
|
||||
{
|
||||
$this->assertValidDql('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id > SOME (SELECT u2.id FROM Doctrine\Tests\Models\CMS\CmsUser u2 WHERE u2.name = u.name)');
|
||||
}
|
||||
|
||||
public function testMemberOfExpression()
|
||||
{
|
||||
$this->assertValidDql('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE :param MEMBER OF u.phonenumbers');
|
||||
}
|
||||
}
|
@ -182,7 +182,7 @@ class LexerTest extends \Doctrine\Tests\OrmTestCase
|
||||
$lexer->moveNext();
|
||||
$token = $lexer->lookahead;
|
||||
$this->assertEquals(Lexer::T_STRING, $token['type']);
|
||||
$this->assertEquals("'This is a string.'", $token['value']);
|
||||
$this->assertEquals("This is a string.", $token['value']);
|
||||
}
|
||||
|
||||
public function testScannerRecognizesStringContainingSingleQuotes()
|
||||
@ -191,7 +191,7 @@ class LexerTest extends \Doctrine\Tests\OrmTestCase
|
||||
$lexer->moveNext();
|
||||
$token = $lexer->lookahead;
|
||||
$this->assertEquals(Lexer::T_STRING, $token['type']);
|
||||
$this->assertEquals("'abc''defg'''", $token['value']);
|
||||
$this->assertEquals("abc'defg'", $token['value']);
|
||||
}
|
||||
|
||||
public function testScannerRecognizesInputParameter()
|
||||
@ -269,7 +269,7 @@ class LexerTest extends \Doctrine\Tests\OrmTestCase
|
||||
'position' => 47
|
||||
),
|
||||
array(
|
||||
'value' => "'Jack O''Neil'",
|
||||
'value' => "Jack O'Neil",
|
||||
'type' => Lexer::T_STRING,
|
||||
'position' => 49
|
||||
)
|
||||
|
@ -21,7 +21,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
$query->free();
|
||||
} catch (Doctrine_Exception $e) {
|
||||
echo $e->getMessage();
|
||||
echo $e->getTraceAsString(); die();
|
||||
echo $e->getTraceAsString();
|
||||
$this->fail($e->getMessage());
|
||||
}
|
||||
}
|
||||
@ -91,7 +91,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'select u from Doctrine\Tests\Models\Forum\ForumUser u where u.username = :name',
|
||||
'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ WHERE f0_.username = :name'
|
||||
'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ WHERE f0_.username = ?'
|
||||
);
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'select u from Doctrine\Tests\Models\Forum\ForumUser u where u.username = :name and u.username = :name2',
|
||||
'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ WHERE f0_.username = :name AND f0_.username = :name2'
|
||||
'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ WHERE f0_.username = ? AND f0_.username = ?'
|
||||
);
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'select u from Doctrine\Tests\Models\Forum\ForumUser u where (u.username = :name OR u.username = :name2) AND u.id = :id',
|
||||
'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ WHERE (f0_.username = :name OR f0_.username = :name2) AND f0_.id = :id'
|
||||
'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ WHERE (f0_.username = ? OR f0_.username = ?) AND f0_.id = ?'
|
||||
);
|
||||
}
|
||||
|
||||
@ -244,7 +244,44 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testExistsExpressionInWhereCorrelatedSubqueryAssocCondition()
|
||||
public function testMemberOfExpression()
|
||||
{
|
||||
// "Get all users who have $phone as a phonenumber." (*cough* doesnt really make sense...)
|
||||
$q1 = $this->_em->createQuery('SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE :param MEMBER OF u.phonenumbers');
|
||||
$phone = new \Doctrine\Tests\Models\CMS\CmsPhonenumber;
|
||||
$phone->phonenumber = 101;
|
||||
$q1->setParameter('param', $phone);
|
||||
|
||||
$this->assertEquals(
|
||||
'SELECT c0_.id AS id0 FROM cms_users c0_ WHERE EXISTS (SELECT 1 FROM cms_phonenumbers c1_ WHERE c0_.id = c1_.user_id AND c1_.phonenumber = ?)',
|
||||
$q1->getSql()
|
||||
);
|
||||
|
||||
// "Get all users who are members of $group."
|
||||
$q2 = $this->_em->createQuery('SELECT u.id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE :param MEMBER OF u.groups');
|
||||
$group = new \Doctrine\Tests\Models\CMS\CmsGroup;
|
||||
$group->id = 101;
|
||||
$q2->setParameter('param', $group);
|
||||
|
||||
$this->assertEquals(
|
||||
'SELECT c0_.id AS id0 FROM cms_users c0_ WHERE EXISTS (SELECT 1 FROM cms_users_groups c1_ INNER JOIN cms_groups c2_ ON c1_.user_id = c0_.id WHERE c1_.group_id = c2_.id AND c2_.id = ?)',
|
||||
$q2->getSql()
|
||||
);
|
||||
|
||||
// "Get all persons who have $person as a friend."
|
||||
// Tough one: Many-many self-referencing ("friends") with class table inheritance
|
||||
$q3 = $this->_em->createQuery('SELECT p.id FROM Doctrine\Tests\Models\Company\CompanyPerson p WHERE :param MEMBER OF p.friends');
|
||||
$person = new \Doctrine\Tests\Models\Company\CompanyPerson;
|
||||
$this->_em->getClassMetadata(get_class($person))->setIdentifierValues($person, 101);
|
||||
$q3->setParameter('param', $person);
|
||||
|
||||
$this->assertEquals(
|
||||
'SELECT c0_.id AS id0, c0_.discr AS discr1 FROM company_persons c0_ LEFT JOIN company_employees c1_ ON c0_.id = c1_.id LEFT JOIN company_managers c2_ ON c0_.id = c2_.id WHERE EXISTS (SELECT 1 FROM company_persons_friends c3_ INNER JOIN company_persons c4_ ON c3_.person_id = c0_.id WHERE c3_.friend_id = c4_.id AND c4_.id = ?)',
|
||||
$q3->getSql()
|
||||
);
|
||||
}
|
||||
|
||||
/*public function testExistsExpressionInWhereCorrelatedSubqueryAssocCondition()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
// DQL
|
||||
@ -261,5 +298,5 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
. ')'
|
||||
|
||||
);
|
||||
}
|
||||
}*/
|
||||
}
|
@ -67,6 +67,7 @@ class OrmFunctionalTestCase extends OrmTestCase
|
||||
$conn->exec('DELETE FROM cms_users');
|
||||
}
|
||||
if (isset($this->_usedModelSets['company'])) {
|
||||
$conn->exec('DELETE FROM company_persons_friends');
|
||||
$conn->exec('DELETE FROM company_managers');
|
||||
$conn->exec('DELETE FROM company_employees');
|
||||
$conn->exec('DELETE FROM company_persons');
|
||||
@ -99,7 +100,7 @@ class OrmFunctionalTestCase extends OrmTestCase
|
||||
|
||||
$classes = array();
|
||||
foreach ($this->_usedModelSets as $setName => $bool) {
|
||||
if ( ! isset(self::$_tablesCreated[$setName]) || $forceCreateTables) {
|
||||
if ( ! isset(self::$_tablesCreated[$setName])/* || $forceCreateTables*/) {
|
||||
foreach (self::$_modelSets[$setName] as $className) {
|
||||
$classes[] = $this->_em->getClassMetadata($className);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user