Merge branch 'master' of github.com:doctrine/doctrine2
This commit is contained in:
commit
2f00db08e1
@ -393,7 +393,7 @@ class ClassMetadataFactory
|
||||
if ( ! $definition) {
|
||||
$sequenceName = $class->getTableName() . '_' . $class->getSingleIdentifierColumnName() . '_seq';
|
||||
$definition['sequenceName'] = $this->_targetPlatform->fixSchemaElementName($sequenceName);
|
||||
$definition['allocationSize'] = 10;
|
||||
$definition['allocationSize'] = 1;
|
||||
$definition['initialValue'] = 1;
|
||||
$class->setSequenceGeneratorDefinition($definition);
|
||||
}
|
||||
|
@ -61,48 +61,52 @@ class Lexer extends \Doctrine\Common\Lexer
|
||||
const T_BETWEEN = 107;
|
||||
const T_BOTH = 108;
|
||||
const T_BY = 109;
|
||||
const T_COUNT = 110;
|
||||
const T_DELETE = 111;
|
||||
const T_DESC = 112;
|
||||
const T_DISTINCT = 113;
|
||||
const T_EMPTY = 114;
|
||||
const T_ESCAPE = 115;
|
||||
const T_EXISTS = 116;
|
||||
const T_FALSE = 117;
|
||||
const T_FROM = 118;
|
||||
const T_GROUP = 119;
|
||||
const T_HAVING = 120;
|
||||
const T_IN = 121;
|
||||
const T_INDEX = 122;
|
||||
const T_INNER = 123;
|
||||
const T_INSTANCE = 124;
|
||||
const T_IS = 125;
|
||||
const T_JOIN = 126;
|
||||
const T_LEADING = 127;
|
||||
const T_LEFT = 128;
|
||||
const T_LIKE = 129;
|
||||
const T_MAX = 130;
|
||||
const T_MEMBER = 131;
|
||||
const T_MIN = 132;
|
||||
const T_NOT = 133;
|
||||
const T_NULL = 134;
|
||||
const T_OF = 135;
|
||||
const T_OR = 136;
|
||||
const T_ORDER = 137;
|
||||
const T_OUTER = 138;
|
||||
const T_SELECT = 139;
|
||||
const T_SET = 140;
|
||||
const T_SIZE = 141;
|
||||
const T_SOME = 142;
|
||||
const T_SUM = 143;
|
||||
const T_TRAILING = 144;
|
||||
const T_TRUE = 145;
|
||||
const T_UPDATE = 146;
|
||||
const T_WHERE = 147;
|
||||
const T_WITH = 148;
|
||||
const T_PARTIAL = 149;
|
||||
const T_MOD = 150;
|
||||
|
||||
const T_CASE = 110;
|
||||
const T_COALESCE = 111;
|
||||
const T_COUNT = 112;
|
||||
const T_DELETE = 113;
|
||||
const T_DESC = 114;
|
||||
const T_DISTINCT = 115;
|
||||
const T_EMPTY = 116;
|
||||
const T_ESCAPE = 117;
|
||||
const T_EXISTS = 118;
|
||||
const T_FALSE = 119;
|
||||
const T_FROM = 120;
|
||||
const T_GROUP = 121;
|
||||
const T_HAVING = 122;
|
||||
const T_IN = 123;
|
||||
const T_INDEX = 124;
|
||||
const T_INNER = 125;
|
||||
const T_INSTANCE = 126;
|
||||
const T_IS = 127;
|
||||
const T_JOIN = 128;
|
||||
const T_LEADING = 129;
|
||||
const T_LEFT = 130;
|
||||
const T_LIKE = 131;
|
||||
const T_MAX = 132;
|
||||
const T_MEMBER = 133;
|
||||
const T_MIN = 134;
|
||||
const T_NOT = 135;
|
||||
const T_NULL = 136;
|
||||
const T_NULLIF = 137;
|
||||
const T_OF = 138;
|
||||
const T_OR = 139;
|
||||
const T_ORDER = 140;
|
||||
const T_OUTER = 141;
|
||||
const T_SELECT = 142;
|
||||
const T_SET = 143;
|
||||
const T_SIZE = 144;
|
||||
const T_SOME = 145;
|
||||
const T_SUM = 146;
|
||||
const T_TRAILING = 147;
|
||||
const T_TRUE = 148;
|
||||
const T_UPDATE = 149;
|
||||
const T_WHEN = 150;
|
||||
const T_WHERE = 151;
|
||||
const T_WITH = 153;
|
||||
const T_PARTIAL = 154;
|
||||
const T_MOD = 155;
|
||||
|
||||
/**
|
||||
* Creates a new query scanner object.
|
||||
*
|
||||
|
@ -397,6 +397,45 @@ class Parser
|
||||
return $peek;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek beyond the matched closing parenthesis and return the first token after that one.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function _peekBeyondClosingParenthesis()
|
||||
{
|
||||
$token = $this->_lexer->peek();
|
||||
$numUnmatched = 1;
|
||||
|
||||
while ($numUnmatched > 0 && $token !== null) {
|
||||
if ($token['value'] == ')') {
|
||||
--$numUnmatched;
|
||||
} else if ($token['value'] == '(') {
|
||||
++$numUnmatched;
|
||||
}
|
||||
|
||||
$token = $this->_lexer->peek();
|
||||
}
|
||||
|
||||
$this->_lexer->resetPeek();
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given token indicates a mathematical operator.
|
||||
*
|
||||
* @return boolean TRUE is the token is a mathematical operator, FALSE otherwise.
|
||||
*/
|
||||
private function _isMathOperator($token)
|
||||
{
|
||||
if (in_array($token['value'], array("+", "-", "/", "*"))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the next-next (after lookahead) token starts a function.
|
||||
*
|
||||
@ -451,7 +490,7 @@ class Parser
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the given <tt>IdentificationVariable</tt> is a semantically correct.
|
||||
* Validates that the given <tt>IdentificationVariable</tt> is semantically correct.
|
||||
* It must exist in query components list.
|
||||
*
|
||||
* @return void
|
||||
@ -486,6 +525,12 @@ class Parser
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the given <tt>PartialObjectExpression</tt> is semantically correct.
|
||||
* It must exist in query components list.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function _processDeferredPartialObjectExpressions()
|
||||
{
|
||||
foreach ($this->_deferredPartialObjectExpressions as $deferredItem) {
|
||||
@ -511,7 +556,7 @@ class Parser
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the given <tt>ResultVariable</tt> is a semantically correct.
|
||||
* Validates that the given <tt>ResultVariable</tt> is semantically correct.
|
||||
* It must exist in query components list.
|
||||
*
|
||||
* @return void
|
||||
@ -547,7 +592,7 @@ class Parser
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the given <tt>PathExpression</tt> is a semantically correct for grammar rules:
|
||||
* Validates that the given <tt>PathExpression</tt> is semantically correct for grammar rules:
|
||||
*
|
||||
* AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression
|
||||
* SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression
|
||||
@ -1537,7 +1582,7 @@ class Parser
|
||||
$peek = $this->_lexer->peek(); // lookahead => token after the token after the '.'
|
||||
$this->_lexer->resetPeek();
|
||||
|
||||
if ($peek['value'] == '+' || $peek['value'] == '-' || $peek['value'] == '/' || $peek['value'] == '*') {
|
||||
if ($this->_isMathOperator($peek)) {
|
||||
return $this->SimpleArithmeticExpression();
|
||||
}
|
||||
|
||||
@ -1545,6 +1590,14 @@ class Parser
|
||||
} else if ($lookahead == Lexer::T_INTEGER || $lookahead == Lexer::T_FLOAT) {
|
||||
return $this->SimpleArithmeticExpression();
|
||||
} else if ($this->_isFunction()) {
|
||||
// We may be in an ArithmeticExpression (find the matching ")" and inspect for Math operator)
|
||||
$this->_lexer->peek(); // "("
|
||||
$peek = $this->_peekBeyondClosingParenthesis();
|
||||
|
||||
if ($this->_isMathOperator($peek)) {
|
||||
return $this->SimpleArithmeticExpression();
|
||||
}
|
||||
|
||||
return $this->FunctionDeclaration();
|
||||
} else if ($lookahead == Lexer::T_STRING) {
|
||||
return $this->StringPrimary();
|
||||
@ -1603,7 +1656,12 @@ class Parser
|
||||
$expression = $this->SimpleArithmeticExpression();
|
||||
}
|
||||
} else if ($this->_isFunction()) {
|
||||
if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
|
||||
$this->_lexer->peek(); // "("
|
||||
$beyond = $this->_peekBeyondClosingParenthesis();
|
||||
|
||||
if ($this->_isMathOperator($beyond)) {
|
||||
$expression = $this->ScalarExpression();
|
||||
} else if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
|
||||
$expression = $this->AggregateExpression();
|
||||
} else {
|
||||
// Shortcut: ScalarExpression => Function
|
||||
@ -1644,26 +1702,51 @@ class Parser
|
||||
}
|
||||
|
||||
/**
|
||||
* SimpleSelectExpression ::= StateFieldPathExpression | IdentificationVariable | (AggregateExpression [["AS"] AliasResultVariable])
|
||||
* SimpleSelectExpression ::=
|
||||
* StateFieldPathExpression | IdentificationVariable |
|
||||
* ((AggregateExpression | "(" Subselect ")" | ScalarExpression) [["AS"] AliasResultVariable])
|
||||
*
|
||||
* @return \Doctrine\ORM\Query\AST\SimpleSelectExpression
|
||||
*/
|
||||
public function SimpleSelectExpression()
|
||||
{
|
||||
if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) {
|
||||
// SingleValuedPathExpression | IdentificationVariable
|
||||
$glimpse = $this->_lexer->glimpse();
|
||||
$peek = $this->_lexer->glimpse();
|
||||
|
||||
if ($glimpse['type'] == Lexer::T_DOT) {
|
||||
return new AST\SimpleSelectExpression($this->StateFieldPathExpression());
|
||||
if ($peek['value'] != '(' && $this->_lexer->lookahead['type'] === Lexer::T_IDENTIFIER) {
|
||||
// SingleValuedPathExpression | IdentificationVariable
|
||||
if ($peek['value'] == '.') {
|
||||
$expression = $this->StateFieldPathExpression();
|
||||
} else {
|
||||
$expression = $this->IdentificationVariable();
|
||||
}
|
||||
|
||||
$this->match(Lexer::T_IDENTIFIER);
|
||||
return new AST\SimpleSelectExpression($expression);
|
||||
} else if ($this->_lexer->lookahead['value'] == '(') {
|
||||
if ($peek['type'] == Lexer::T_SELECT) {
|
||||
// Subselect
|
||||
$this->match(Lexer::T_OPEN_PARENTHESIS);
|
||||
$expression = $this->Subselect();
|
||||
$this->match(Lexer::T_CLOSE_PARENTHESIS);
|
||||
} else {
|
||||
// Shortcut: ScalarExpression => SimpleArithmeticExpression
|
||||
$expression = $this->SimpleArithmeticExpression();
|
||||
}
|
||||
|
||||
return new AST\SimpleSelectExpression($this->_lexer->token['value']);
|
||||
return new AST\SimpleSelectExpression($expression);
|
||||
}
|
||||
|
||||
$expr = new AST\SimpleSelectExpression($this->AggregateExpression());
|
||||
$this->_lexer->peek();
|
||||
$beyond = $this->_peekBeyondClosingParenthesis();
|
||||
|
||||
if ($this->_isMathOperator($beyond)) {
|
||||
$expression = $this->ScalarExpression();
|
||||
} else if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
|
||||
$expression = $this->AggregateExpression();
|
||||
} else {
|
||||
$expression = $this->FunctionDeclaration();
|
||||
}
|
||||
|
||||
$expr = new AST\SimpleSelectExpression($expression);
|
||||
|
||||
if ($this->_lexer->isNextToken(Lexer::T_AS)) {
|
||||
$this->match(Lexer::T_AS);
|
||||
@ -1869,23 +1952,6 @@ class Parser
|
||||
}
|
||||
}
|
||||
|
||||
private function _peekBeyondClosingParenthesis()
|
||||
{
|
||||
$numUnmatched = 1;
|
||||
$token = $this->_lexer->peek();
|
||||
while ($numUnmatched > 0 && $token !== null) {
|
||||
if ($token['value'] == ')') {
|
||||
--$numUnmatched;
|
||||
} else if ($token['value'] == '(') {
|
||||
++$numUnmatched;
|
||||
}
|
||||
$token = $this->_lexer->peek();
|
||||
}
|
||||
$this->_lexer->resetPeek();
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* EmptyCollectionComparisonExpression ::= CollectionValuedPathExpression "IS" ["NOT"] "EMPTY"
|
||||
*
|
||||
@ -2355,13 +2421,13 @@ class Parser
|
||||
}
|
||||
|
||||
/**
|
||||
* InExpression ::= StateFieldPathExpression ["NOT"] "IN" "(" (InParameter {"," InParameter}* | Subselect) ")"
|
||||
* InExpression ::= SingleValuedPathExpression ["NOT"] "IN" "(" (InParameter {"," InParameter}* | Subselect) ")"
|
||||
*
|
||||
* @return \Doctrine\ORM\Query\AST\InExpression
|
||||
*/
|
||||
public function InExpression()
|
||||
{
|
||||
$inExpression = new AST\InExpression($this->StateFieldPathExpression());
|
||||
$inExpression = new AST\InExpression($this->SingleValuedPathExpression());
|
||||
|
||||
if ($this->_lexer->isNextToken(Lexer::T_NOT)) {
|
||||
$this->match(Lexer::T_NOT);
|
||||
|
@ -1106,7 +1106,7 @@ class SqlWalker implements TreeWalker
|
||||
$expr = $simpleSelectExpression->expression;
|
||||
|
||||
if ($expr instanceof AST\PathExpression) {
|
||||
$sql .= ' ' . $this->walkPathExpression($expr);
|
||||
$sql .= $this->walkPathExpression($expr);
|
||||
} else if ($expr instanceof AST\AggregateExpression) {
|
||||
if ( ! $simpleSelectExpression->fieldIdentificationVariable) {
|
||||
$alias = $this->_scalarResultCounter++;
|
||||
@ -1114,17 +1114,55 @@ class SqlWalker implements TreeWalker
|
||||
$alias = $simpleSelectExpression->fieldIdentificationVariable;
|
||||
}
|
||||
|
||||
$sql .= ' ' . $this->walkAggregateExpression($expr) . ' AS dctrn__' . $alias;
|
||||
$sql .= $this->walkAggregateExpression($expr) . ' AS dctrn__' . $alias;
|
||||
} else if ($expr instanceof AST\Subselect) {
|
||||
if ( ! $simpleSelectExpression->fieldIdentificationVariable) {
|
||||
$alias = $this->_scalarResultCounter++;
|
||||
} else {
|
||||
$alias = $simpleSelectExpression->fieldIdentificationVariable;
|
||||
}
|
||||
|
||||
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||
$sql .= '(' . $this->walkSubselect($expr) . ') AS ' . $columnAlias;
|
||||
$this->_scalarResultAliasMap[$alias] = $columnAlias;
|
||||
} else if ($expr instanceof AST\Functions\FunctionNode) {
|
||||
if ( ! $simpleSelectExpression->fieldIdentificationVariable) {
|
||||
$alias = $this->_scalarResultCounter++;
|
||||
} else {
|
||||
$alias = $simpleSelectExpression->fieldIdentificationVariable;
|
||||
}
|
||||
|
||||
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||
$sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias;
|
||||
$this->_scalarResultAliasMap[$alias] = $columnAlias;
|
||||
} else if (
|
||||
$expr instanceof AST\SimpleArithmeticExpression ||
|
||||
$expr instanceof AST\ArithmeticTerm ||
|
||||
$expr instanceof AST\ArithmeticFactor ||
|
||||
$expr instanceof AST\ArithmeticPrimary
|
||||
) {
|
||||
if ( ! $simpleSelectExpression->fieldIdentificationVariable) {
|
||||
$alias = $this->_scalarResultCounter++;
|
||||
} else {
|
||||
$alias = $simpleSelectExpression->fieldIdentificationVariable;
|
||||
}
|
||||
|
||||
$columnAlias = 'sclr' . $this->_aliasCounter++;
|
||||
$sql .= $this->walkSimpleArithmeticExpression($expr) . ' AS ' . $columnAlias;
|
||||
$this->_scalarResultAliasMap[$alias] = $columnAlias;
|
||||
} else {
|
||||
// IdentificationVariable
|
||||
// FIXME: Composite key support, or select all columns? Does that make sense
|
||||
// in a subquery?
|
||||
$class = $this->_queryComponents[$expr]['metadata'];
|
||||
$sql .= ' ' . $this->getSqlTableAlias($class->getTableName(), $expr) . '.'
|
||||
. $class->getQuotedColumnName($class->identifier[0], $this->_platform);
|
||||
$tableAlias = $this->getSqlTableAlias($class->getTableName(), $expr);
|
||||
$first = true;
|
||||
|
||||
foreach ($class->identifier as $identifier) {
|
||||
if ($first) $first = false; else $sql .= ', ';
|
||||
$sql .= $tableAlias . '.' . $class->getQuotedColumnName($identifier, $this->_platform);
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
return ' ' . $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -513,7 +513,7 @@ public function <methodName>()
|
||||
$methods[] = $code;
|
||||
}
|
||||
} else if ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) {
|
||||
if ($associationMapping->isOwningSide) {
|
||||
if ($associationMapping['isOwningSide']) {
|
||||
if ($code = $this->_generateEntityStubMethod($metadata, 'set', $associationMapping['fieldName'], $associationMapping['targetEntity'])) {
|
||||
$methods[] = $code;
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
|
||||
}
|
||||
|
||||
$parser = new \Doctrine\ORM\Query\Parser($query);
|
||||
|
||||
// We do NOT test SQL output here. That only unnecessarily slows down the tests!
|
||||
$parser->setCustomOutputTreeWalker('Doctrine\Tests\Mocks\MockTreeWalker');
|
||||
|
||||
@ -134,6 +135,16 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->assertValidDql('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id NOT IN (1)');
|
||||
}
|
||||
|
||||
public function testInExpressionWithSingleValuedAssociationPathExpression()
|
||||
{
|
||||
$this->assertValidDql("SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u WHERE u.avatar IN (?1, ?2)");
|
||||
}
|
||||
|
||||
public function testInvalidInExpressionWithCollectionValuedAssociationPathExpression()
|
||||
{
|
||||
$this->assertInvalidDql("SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.phonenumbers IN (?1, ?2)");
|
||||
}
|
||||
|
||||
public function testInstanceOfExpressionSupportedInWherePart()
|
||||
{
|
||||
$this->assertValidDql('SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF Doctrine\Tests\Models\Company\CompanyEmployee');
|
||||
@ -225,15 +236,25 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->assertValidDql("SELECT u.name, (SELECT COUNT(p.phonenumber) FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE p.phonenumber = 1234) pcount FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = 'jon'");
|
||||
}
|
||||
|
||||
/*public function testSubselectInSelectPart2()
|
||||
public function testArithmeticExpressionInSelectPart()
|
||||
{
|
||||
$this->assertValidDql("SELECT SUM(u.id) / COUNT(u.id) FROM Doctrine\Tests\Models\CMS\CmsUser u");
|
||||
}*/
|
||||
}
|
||||
|
||||
/*public function testSubselectInSelectPart3()
|
||||
public function testArithmeticExpressionInSubselectPart()
|
||||
{
|
||||
$this->assertValidDql("SELECT (SELECT SUM(u.id) / COUNT(u.id) FROM Doctrine\Tests\Models\CMS\CmsUser u2) value FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = 'jon'");
|
||||
}*/
|
||||
}
|
||||
|
||||
public function testArithmeticExpressionWithParenthesisInSubselectPart()
|
||||
{
|
||||
$this->assertValidDql("SELECT (SELECT (SUM(u.id) / COUNT(u.id)) FROM Doctrine\Tests\Models\CMS\CmsUser u2) value FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = 'jon'");
|
||||
}
|
||||
|
||||
public function testDuplicateAliasInSubselectPart()
|
||||
{
|
||||
$this->assertInvalidDql("SELECT (SELECT SUM(u.id) / COUNT(u.id) AS foo FROM Doctrine\Tests\Models\CMS\CmsUser u2) foo FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = 'jon'");
|
||||
}
|
||||
|
||||
public function testPositionalInputParameter()
|
||||
{
|
||||
@ -377,6 +398,11 @@ 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 testArithmeticExpressionWithoutParenthesisInWhereClause()
|
||||
{
|
||||
$this->assertValidDql('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE SIZE(u.phonenumbers) + 1 > 10');
|
||||
}
|
||||
|
||||
public function testMemberOfExpression()
|
||||
{
|
||||
$this->assertValidDql('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE :param MEMBER OF u.phonenumbers');
|
||||
|
@ -15,6 +15,14 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->_em = $this->_getTestEntityManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert a valid SQL generation.
|
||||
*
|
||||
* @param string $dqlToBeTested
|
||||
* @param string $sqlToBeConfirmed
|
||||
* @param array $queryHints
|
||||
* @param array $queryParams
|
||||
*/
|
||||
public function assertSqlGeneration($dqlToBeTested, $sqlToBeConfirmed, array $queryHints = array(), array $queryParams = array())
|
||||
{
|
||||
try {
|
||||
@ -38,6 +46,39 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asser an invalid SQL generation.
|
||||
*
|
||||
* @param string $dqlToBeTested
|
||||
* @param string $expectedException
|
||||
* @param array $queryHints
|
||||
* @param array $queryParams
|
||||
*/
|
||||
public function assertInvalidSqlGeneration($dqlToBeTested, $expectedException, array $queryHints = array(), array $queryParams = array())
|
||||
{
|
||||
$this->setExpectedException($expectedException);
|
||||
|
||||
$query = $this->_em->createQuery($dqlToBeTested);
|
||||
|
||||
foreach ($queryParams AS $name => $value) {
|
||||
$query->setParameter($name, $value);
|
||||
}
|
||||
|
||||
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
|
||||
->useQueryCache(false);
|
||||
|
||||
foreach ($queryHints AS $name => $value) {
|
||||
$query->setHint($name, $value);
|
||||
}
|
||||
|
||||
$sql = $query->getSql();
|
||||
$query->free();
|
||||
|
||||
// If we reached here, test failed
|
||||
$this->fail($sql);
|
||||
}
|
||||
|
||||
|
||||
public function testSupportsSelectForAllFields()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
@ -102,6 +143,33 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testSelectCorrelatedSubqueryComplexMathematicalExpression()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT (SELECT (count(p.phonenumber)+5)*10 FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p JOIN p.user ui WHERE ui.id = u.id) AS c FROM Doctrine\Tests\Models\CMS\CmsUser u',
|
||||
'SELECT (SELECT (count(c0_.phonenumber) + 5) * 10 AS sclr1 FROM cms_phonenumbers c0_ INNER JOIN cms_users c1_ ON c0_.user_id = c1_.id WHERE c1_.id = c2_.id) AS sclr0 FROM cms_users c2_'
|
||||
);
|
||||
}
|
||||
|
||||
public function testSelectComplexMathematicalExpression()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT (count(p.phonenumber)+5)*10 FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p JOIN p.user ui WHERE ui.id = ?1',
|
||||
'SELECT (count(c0_.phonenumber) + 5) * 10 AS sclr0 FROM cms_phonenumbers c0_ INNER JOIN cms_users c1_ ON c0_.user_id = c1_.id WHERE c1_.id = ?'
|
||||
);
|
||||
}
|
||||
|
||||
/* NOT (YET?) SUPPORTED.
|
||||
Can be supported if SimpleSelectExpresion supports SingleValuedPathExpression instead of StateFieldPathExpression.
|
||||
|
||||
public function testSingleAssociationPathExpressionInSubselect()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT (SELECT p.user FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p WHERE p.user = u) user_id FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1',
|
||||
'SELECT (SELECT c0_.user_id FROM cms_phonenumbers c0_ WHERE c0_.user_id = c1_.id) AS sclr0 FROM cms_users c1_ WHERE c1_.id = ?'
|
||||
);
|
||||
}*/
|
||||
|
||||
public function testSupportsOrderByWithAscAsDefault()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
@ -347,6 +415,23 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testInExpressionWithSingleValuedAssociationPathExpressionInWherePart()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u WHERE u.avatar IN (?1, ?2)',
|
||||
'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ WHERE f0_.avatar_id IN (?, ?)'
|
||||
);
|
||||
}
|
||||
|
||||
public function testInvalidInExpressionWithSingleValuedAssociationPathExpressionOnInverseSide()
|
||||
{
|
||||
// We do not support SingleValuedAssociationPathExpression on inverse side
|
||||
$this->assertInvalidSqlGeneration(
|
||||
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.address IN (?1, ?2)",
|
||||
"Doctrine\ORM\Query\QueryException"
|
||||
);
|
||||
}
|
||||
|
||||
public function testSupportsConcatFunctionForMysqlAndPostgresql()
|
||||
{
|
||||
$connMock = $this->_em->getConnection();
|
||||
|
Loading…
x
Reference in New Issue
Block a user