TupleComparisonTranslatorTrait.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.0
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Database\Dialect;
  16. use Cake\Database\Expression\IdentifierExpression;
  17. use Cake\Database\Expression\QueryExpression;
  18. use Cake\Database\Expression\TupleComparison;
  19. use Cake\Database\Query;
  20. /**
  21. * Provides a translator method for tuple comparisons
  22. *
  23. * @internal
  24. */
  25. trait TupleComparisonTranslatorTrait
  26. {
  27. /**
  28. * Receives a TupleExpression and changes it so that it conforms to this
  29. * SQL dialect.
  30. *
  31. * It transforms expressions looking like '(a, b) IN ((c, d), (e, f)' into an
  32. * equivalent expression of the form '((a = c) AND (b = d)) OR ((a = e) AND (b = f))'.
  33. *
  34. * It can also transform transform expressions where the right hand side is a query
  35. * selecting the same amount of columns as the elements in the left hand side of
  36. * the expression:
  37. *
  38. * (a, b) IN (SELECT c, d FROM a_table) is transformed into
  39. *
  40. * 1 = (SELECT 1 FROM a_table WHERE (a = c) AND (b = d))
  41. *
  42. * @param \Cake\Database\Expression\TupleComparison $expression The expression to transform
  43. * @param \Cake\Database\Query $query The query to update.
  44. * @return void
  45. */
  46. protected function _transformTupleComparison(TupleComparison $expression, $query)
  47. {
  48. $fields = $expression->getField();
  49. if (!is_array($fields)) {
  50. return;
  51. }
  52. $value = $expression->getValue();
  53. $op = $expression->getOperator();
  54. $true = new QueryExpression('1');
  55. if ($value instanceof Query) {
  56. $selected = array_values($value->clause('select'));
  57. foreach ($fields as $i => $field) {
  58. $value->andWhere([$field . " $op" => new IdentifierExpression($selected[$i])]);
  59. }
  60. $value->select($true, true);
  61. $expression->setField($true);
  62. $expression->setOperator('=');
  63. return;
  64. }
  65. $surrogate = $query->getConnection()
  66. ->newQuery()
  67. ->select($true);
  68. if (!is_array(current($value))) {
  69. $value = [$value];
  70. }
  71. $conditions = ['OR' => []];
  72. foreach ($value as $tuple) {
  73. $item = [];
  74. foreach (array_values($tuple) as $i => $value) {
  75. $item[] = [$fields[$i] => $value];
  76. }
  77. $conditions['OR'][] = $item;
  78. }
  79. $surrogate->where($conditions);
  80. $expression->setField($true);
  81. $expression->setValue($surrogate);
  82. $expression->setOperator('=');
  83. }
  84. }