WhereInWalker.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <?php
  2. /**
  3. * Doctrine ORM
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE. This license can also be viewed
  9. * at http://hobodave.com/license.txt
  10. *
  11. * @category DoctrineExtensions
  12. * @package DoctrineExtensions\Paginate
  13. * @author David Abdemoulaie <dave@hobodave.com>
  14. * @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/)
  15. * @license http://hobodave.com/license.txt New BSD License
  16. */
  17. namespace Doctrine\ORM\Tools\Pagination;
  18. use Doctrine\ORM\Query\AST\ArithmeticExpression,
  19. Doctrine\ORM\Query\AST\SimpleArithmeticExpression,
  20. Doctrine\ORM\Query\TreeWalkerAdapter,
  21. Doctrine\ORM\Query\AST\SelectStatement,
  22. Doctrine\ORM\Query\AST\PathExpression,
  23. Doctrine\ORM\Query\AST\InExpression,
  24. Doctrine\ORM\Query\AST\NullComparisonExpression,
  25. Doctrine\ORM\Query\AST\InputParameter,
  26. Doctrine\ORM\Query\AST\ConditionalPrimary,
  27. Doctrine\ORM\Query\AST\ConditionalTerm,
  28. Doctrine\ORM\Query\AST\ConditionalExpression,
  29. Doctrine\ORM\Query\AST\ConditionalFactor,
  30. Doctrine\ORM\Query\AST\WhereClause;
  31. /**
  32. * Replaces the whereClause of the AST with a WHERE id IN (:foo_1, :foo_2) equivalent
  33. *
  34. * @category DoctrineExtensions
  35. * @package DoctrineExtensions\Paginate
  36. * @author David Abdemoulaie <dave@hobodave.com>
  37. * @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/)
  38. * @license http://hobodave.com/license.txt New BSD License
  39. */
  40. class WhereInWalker extends TreeWalkerAdapter
  41. {
  42. /**
  43. * ID Count hint name
  44. */
  45. const HINT_PAGINATOR_ID_COUNT = 'doctrine.id.count';
  46. /**
  47. * Primary key alias for query
  48. */
  49. const PAGINATOR_ID_ALIAS = 'dpid';
  50. /**
  51. * Replaces the whereClause in the AST
  52. *
  53. * Generates a clause equivalent to WHERE IN (:dpid_1, :dpid_2, ...)
  54. *
  55. * The parameter namespace (dpid) is defined by
  56. * the PAGINATOR_ID_ALIAS
  57. *
  58. * The total number of parameters is retrieved from
  59. * the HINT_PAGINATOR_ID_COUNT query hint
  60. *
  61. * @param SelectStatement $AST
  62. * @return void
  63. */
  64. public function walkSelectStatement(SelectStatement $AST)
  65. {
  66. $rootComponents = array();
  67. foreach ($this->_getQueryComponents() AS $dqlAlias => $qComp) {
  68. $isParent = array_key_exists('parent', $qComp)
  69. && $qComp['parent'] === null
  70. && $qComp['nestingLevel'] == 0
  71. ;
  72. if ($isParent) {
  73. $rootComponents[] = array($dqlAlias => $qComp);
  74. }
  75. }
  76. if (count($rootComponents) > 1) {
  77. throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction");
  78. }
  79. $root = reset($rootComponents);
  80. $parentName = key($root);
  81. $parent = current($root);
  82. $pathExpression = new PathExpression(
  83. PathExpression::TYPE_STATE_FIELD, $parentName, $parent['metadata']->getSingleIdentifierFieldName()
  84. );
  85. $pathExpression->type = PathExpression::TYPE_STATE_FIELD;
  86. $count = $this->_getQuery()->getHint(self::HINT_PAGINATOR_ID_COUNT);
  87. if ($count > 0) {
  88. $arithmeticExpression = new ArithmeticExpression();
  89. $arithmeticExpression->simpleArithmeticExpression = new SimpleArithmeticExpression(
  90. array($pathExpression)
  91. );
  92. $expression = new InExpression($arithmeticExpression);
  93. $ns = self::PAGINATOR_ID_ALIAS;
  94. for ($i = 1; $i <= $count; $i++) {
  95. $expression->literals[] = new InputParameter(":{$ns}_$i");
  96. }
  97. } else {
  98. $expression = new NullComparisonExpression($pathExpression);
  99. $expression->not = false;
  100. }
  101. $conditionalPrimary = new ConditionalPrimary;
  102. $conditionalPrimary->simpleConditionalExpression = $expression;
  103. if ($AST->whereClause) {
  104. if ($AST->whereClause->conditionalExpression instanceof ConditionalTerm) {
  105. $AST->whereClause->conditionalExpression->conditionalFactors[] = $conditionalPrimary;
  106. } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalPrimary) {
  107. $AST->whereClause->conditionalExpression = new ConditionalExpression(array(
  108. new ConditionalTerm(array(
  109. $AST->whereClause->conditionalExpression,
  110. $conditionalPrimary
  111. ))
  112. ));
  113. } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalExpression) {
  114. $tmpPrimary = new ConditionalPrimary;
  115. $tmpPrimary->conditionalExpression = $AST->whereClause->conditionalExpression;
  116. $AST->whereClause->conditionalExpression = new ConditionalTerm(array(
  117. $tmpPrimary,
  118. $conditionalPrimary
  119. ));
  120. }
  121. } else {
  122. $AST->whereClause = new WhereClause(
  123. new ConditionalExpression(array(
  124. new ConditionalTerm(array(
  125. $conditionalPrimary
  126. ))
  127. ))
  128. );
  129. }
  130. }
  131. }