Created
December 8, 2013 14:43
-
-
Save flip111/7858442 to your computer and use it in GitHub Desktop.
Support for STRAIGHT_JOIN in Doctrine. This does not work (yet) because not having a clean way to implement it. But making these changes in Doctrine directly will work.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* DoctrineExtensions Vendor Specific DQL Query Features | |
* | |
* LICENSE | |
* | |
* This source file is subject to the new BSD license that is bundled | |
* with this package in the file LICENSE.txt. | |
* If you did not receive a copy of the license and are unable to | |
* obtain it through the world-wide-web, please send an email | |
* to [email protected] so I can send you a copy immediately. | |
*/ | |
namespace DoctrineExtensions\Query\AST; | |
use Doctrine\ORM\Query\AST\Join; | |
/** | |
* Join ::= [["LEFT" ["OUTER"] | "INNER"] "JOIN" | "STRAIGHT_JOIN"] JoinAssociationPathExpression | |
* ["AS"] AliasIdentificationVariable [("ON" | "WITH") ConditionalExpression] | |
* | |
* @link www.doctrine-project.org | |
* @since 2.0 | |
* @author Guilherme Blanco <[email protected]> | |
* @author Jonathan Wage <[email protected]> | |
* @author Roman Borschel <[email protected]> | |
*/ | |
class MysqlJoin extends Join | |
{ | |
const JOIN_TYPE_STRAIGHT = 4; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* DoctrineExtensions Vendor Specific DQL Query Features | |
* | |
* LICENSE | |
* | |
* This source file is subject to the new BSD license that is bundled | |
* with this package in the file LICENSE.txt. | |
* If you did not receive a copy of the license and are unable to | |
* obtain it through the world-wide-web, please send an email | |
* to [email protected] so I can send you a copy immediately. | |
*/ | |
namespace DoctrineExtensions\Query; | |
use Doctrine\ORM\Query\Lexer; | |
/** | |
* Scans a DQL query for tokens. | |
* | |
* @author Guilherme Blanco <[email protected]> | |
* @author Janne Vanhala <[email protected]> | |
* @author Roman Borschel <[email protected]> | |
* @since 2.0 | |
*/ | |
class MysqlLexer extends Lexer | |
{ | |
const T_STRAIGHT_JOIN = 158; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* DoctrineExtensions Vendor Specific DQL Query Features | |
* | |
* LICENSE | |
* | |
* This source file is subject to the new BSD license that is bundled | |
* with this package in the file LICENSE.txt. | |
* If you did not receive a copy of the license and are unable to | |
* obtain it through the world-wide-web, please send an email | |
* to [email protected] so I can send you a copy immediately. | |
*/ | |
namespace DoctrineExtensions\Query; | |
use Doctrine\ORM\Query\Parser; | |
/** | |
* An LL(*) recursive-descent parser for the context-free grammar of the Doctrine Query Language. | |
* Parses a DQL query, reports any errors in it, and generates an AST. | |
* | |
* @since 2.0 | |
* @author Guilherme Blanco <[email protected]> | |
* @author Jonathan Wage <[email protected]> | |
* @author Roman Borschel <[email protected]> | |
* @author Janne Vanhala <[email protected]> | |
* @author Fabio B. Silva <[email protected]> | |
*/ | |
class MysqlParser extends Parser | |
{ | |
/** | |
* IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {Join}* | |
* | |
* @return \Doctrine\ORM\Query\AST\IdentificationVariableDeclaration | |
*/ | |
public function IdentificationVariableDeclaration() | |
{ | |
$rangeVariableDeclaration = $this->RangeVariableDeclaration(); | |
$rangeVariableDeclaration->isRoot = true; | |
$indexBy = $this->lexer->isNextToken(Lexer::T_INDEX) ? $this->IndexBy() : null; | |
$joins = array(); | |
while ( | |
$this->lexer->isNextToken(Lexer::T_LEFT) || | |
$this->lexer->isNextToken(Lexer::T_INNER) || | |
$this->lexer->isNextToken(Lexer::T_JOIN) || | |
$this->lexer->isNextToken(Lexer::T_STRAIGHT_JOIN) | |
) { | |
$joins[] = $this->Join(); | |
} | |
return new AST\IdentificationVariableDeclaration( | |
$rangeVariableDeclaration, $indexBy, $joins | |
); | |
} | |
/** | |
* Join ::= [["LEFT" ["OUTER"] | "INNER"] "JOIN" | "STRAIGHT_JOIN"] | |
* (JoinAssociationDeclaration | RangeVariableDeclaration) | |
* ["WITH" ConditionalExpression] | |
* | |
* @return \Doctrine\ORM\Query\AST\Join | |
*/ | |
public function Join() | |
{ | |
// Check Join type | |
$joinType = AST\Join::JOIN_TYPE_INNER; | |
switch (true) { | |
case ($this->lexer->isNextToken(Lexer::T_LEFT)): | |
$this->match(Lexer::T_LEFT); | |
$joinType = AST\Join::JOIN_TYPE_LEFT; | |
// Possible LEFT OUTER join | |
if ($this->lexer->isNextToken(Lexer::T_OUTER)) { | |
$this->match(Lexer::T_OUTER); | |
$joinType = AST\Join::JOIN_TYPE_LEFTOUTER; | |
} | |
$this->match(Lexer::T_JOIN); | |
break; | |
case ($this->lexer->isNextToken(Lexer::T_INNER)): | |
$this->match(Lexer::T_INNER); | |
$this->match(Lexer::T_JOIN); | |
break; | |
case ($this->lexer->isNextToken(Lexer::T_STRAIGHT_JOIN)): | |
$joinType = AST\Join::JOIN_TYPE_STRAIGHT; | |
$this->match(Lexer::T_STRAIGHT_JOIN); | |
break; | |
default: | |
// Do nothing | |
} | |
$next = $this->lexer->glimpse(); | |
$joinDeclaration = ($next['type'] === Lexer::T_DOT) ? $this->JoinAssociationDeclaration() : $this->RangeVariableDeclaration(); | |
$adhocConditions = $this->lexer->isNextToken(Lexer::T_WITH); | |
$join = new AST\Join($joinType, $joinDeclaration); | |
// Describe non-root join declaration | |
if ($joinDeclaration instanceof AST\RangeVariableDeclaration) { | |
$joinDeclaration->isRoot = false; | |
$adhocConditions = true; | |
} | |
// Check for ad-hoc Join conditions | |
if ($adhocConditions) { | |
$this->match(Lexer::T_WITH); | |
$join->conditionalExpression = $this->ConditionalExpression(); | |
} | |
return $join; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* DoctrineExtensions Vendor Specific DQL Query Features | |
* | |
* LICENSE | |
* | |
* This source file is subject to the new BSD license that is bundled | |
* with this package in the file LICENSE.txt. | |
* If you did not receive a copy of the license and are unable to | |
* obtain it through the world-wide-web, please send an email | |
* to [email protected] so I can send you a copy immediately. | |
*/ | |
namespace DoctrineExtensions\Query; | |
use Doctrine\ORM\Query\SqlWalker; | |
class MysqlWalker extends SqlWalker | |
{ | |
/** | |
* Walks down a SelectClause AST node, thereby generating the appropriate SQL. | |
* | |
* @param $selectClause | |
* @return string The SQL. | |
*/ | |
public function walkSelectClause($selectClause) | |
{ | |
$sql = parent::walkSelectClause($selectClause); | |
if ($this->getQuery()->getHint('mysqlWalker.sqlNoCache') === true) { | |
if ($selectClause->isDistinct) { | |
$sql = str_replace('SELECT DISTINCT', 'SELECT DISTINCT SQL_NO_CACHE', $sql); | |
} else { | |
$sql = str_replace('SELECT', 'SELECT SQL_NO_CACHE', $sql); | |
} | |
} | |
return $sql; | |
} | |
/** | |
* Walks down a Join AST node and creates the corresponding SQL. | |
* | |
* @param AST\Join $join | |
* | |
* @return string The SQL. | |
*/ | |
public function walkJoin($join) | |
{ | |
$joinType = $join->joinType; | |
$joinDeclaration = $join->joinAssociationDeclaration; | |
if ($joinType == AST\Join::JOIN_TYPE_LEFT || $joinType == AST\Join::JOIN_TYPE_LEFTOUTER) { | |
$sql = ' LEFT JOIN '; | |
} elseif ($joinType == AST\Join::JOIN_TYPE_STRAIGHT) { | |
$sql = ' STRAIGHT_JOIN '; | |
} else { | |
$sql = ' INNER JOIN '; | |
} | |
switch (true) { | |
case ($joinDeclaration instanceof \Doctrine\ORM\Query\AST\RangeVariableDeclaration): | |
$class = $this->em->getClassMetadata($joinDeclaration->abstractSchemaName); | |
$dqlAlias = $joinDeclaration->aliasIdentificationVariable; | |
$tableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias); | |
$condition = '(' . $this->walkConditionalExpression($join->conditionalExpression) . ')'; | |
$condExprConjunction = ($class->isInheritanceTypeJoined() && $joinType != AST\Join::JOIN_TYPE_LEFT && $joinType != AST\Join::JOIN_TYPE_LEFTOUTER) | |
? ' AND ' | |
: ' ON '; | |
$sql .= $this->walkRangeVariableDeclaration($joinDeclaration); | |
$conditions = array($condition); | |
// Apply remaining inheritance restrictions | |
$discrSql = $this->_generateDiscriminatorColumnConditionSQL(array($dqlAlias)); | |
if ($discrSql) { | |
$conditions[] = $discrSql; | |
} | |
// Apply the filters | |
$filterExpr = $this->generateFilterConditionSQL($class, $tableAlias); | |
if ($filterExpr) { | |
$conditions[] = $filterExpr; | |
} | |
$sql .= $condExprConjunction . implode(' AND ', $conditions); | |
break; | |
case ($joinDeclaration instanceof \Doctrine\ORM\Query\AST\JoinAssociationDeclaration): | |
$sql .= $this->walkJoinAssociationDeclaration($joinDeclaration, $joinType, $join->conditionalExpression); | |
break; | |
} | |
return $sql; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment