TupleComparisonTest.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  5. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  6. *
  7. * Licensed under The MIT License
  8. * For full copyright and license information, please see the LICENSE.txt
  9. * Redistributions of files must retain the above copyright notice.
  10. *
  11. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  12. * @link https://cakephp.org CakePHP(tm) Project
  13. * @since 3.0.0
  14. * @license https://opensource.org/licenses/mit-license.php MIT License
  15. */
  16. namespace Cake\Test\TestCase\Database\Expression;
  17. use Cake\Database\Expression\QueryExpression;
  18. use Cake\Database\Expression\TupleComparison;
  19. use Cake\Database\ValueBinder;
  20. use Cake\TestSuite\TestCase;
  21. use InvalidArgumentException;
  22. /**
  23. * Tests TupleComparison class
  24. */
  25. class TupleComparisonTest extends TestCase
  26. {
  27. /**
  28. * Tests generating a function with no arguments
  29. */
  30. public function testSimpleTuple(): void
  31. {
  32. $f = new TupleComparison(['field1', 'field2'], [1, 2], ['integer', 'integer'], '=');
  33. $binder = new ValueBinder();
  34. $this->assertSame('(field1, field2) = (:tuple0, :tuple1)', $f->sql($binder));
  35. $this->assertSame(1, $binder->bindings()[':tuple0']['value']);
  36. $this->assertSame(2, $binder->bindings()[':tuple1']['value']);
  37. $this->assertSame('integer', $binder->bindings()[':tuple0']['type']);
  38. $this->assertSame('integer', $binder->bindings()[':tuple1']['type']);
  39. }
  40. /**
  41. * Tests generating tuples in the fields side containing expressions
  42. */
  43. public function testTupleWithExpressionFields(): void
  44. {
  45. $field1 = new QueryExpression(['a' => 1]);
  46. $f = new TupleComparison([$field1, 'field2'], [4, 5], ['integer', 'integer'], '>');
  47. $binder = new ValueBinder();
  48. $this->assertSame('(a = :c0, field2) > (:tuple1, :tuple2)', $f->sql($binder));
  49. $this->assertSame(1, $binder->bindings()[':c0']['value']);
  50. $this->assertSame(4, $binder->bindings()[':tuple1']['value']);
  51. $this->assertSame(5, $binder->bindings()[':tuple2']['value']);
  52. }
  53. /**
  54. * Tests generating tuples in the values side containing expressions
  55. */
  56. public function testTupleWithExpressionValues(): void
  57. {
  58. $value1 = new QueryExpression(['a' => 1]);
  59. $f = new TupleComparison(['field1', 'field2'], [$value1, 2], ['integer', 'integer'], '=');
  60. $binder = new ValueBinder();
  61. $this->assertSame('(field1, field2) = (a = :c0, :tuple1)', $f->sql($binder));
  62. $this->assertSame(1, $binder->bindings()[':c0']['value']);
  63. $this->assertSame(2, $binder->bindings()[':tuple1']['value']);
  64. }
  65. /**
  66. * Tests generating tuples using the IN conjunction
  67. */
  68. public function testTupleWithInComparison(): void
  69. {
  70. $f = new TupleComparison(
  71. ['field1', 'field2'],
  72. [[1, 2], [3, 4]],
  73. ['integer', 'integer'],
  74. 'IN'
  75. );
  76. $binder = new ValueBinder();
  77. $this->assertSame('(field1, field2) IN ((:tuple0,:tuple1), (:tuple2,:tuple3))', $f->sql($binder));
  78. $this->assertSame(1, $binder->bindings()[':tuple0']['value']);
  79. $this->assertSame(2, $binder->bindings()[':tuple1']['value']);
  80. $this->assertSame(3, $binder->bindings()[':tuple2']['value']);
  81. $this->assertSame(4, $binder->bindings()[':tuple3']['value']);
  82. }
  83. /**
  84. * Tests traversing
  85. */
  86. public function testTraverse(): void
  87. {
  88. $value1 = new QueryExpression(['a' => 1]);
  89. $field2 = new QueryExpression(['b' => 2]);
  90. $f = new TupleComparison(['field1', $field2], [$value1, 2], ['integer', 'integer'], '=');
  91. $expressions = [];
  92. $collector = function ($e) use (&$expressions): void {
  93. $expressions[] = $e;
  94. };
  95. $f->traverse($collector);
  96. $this->assertCount(4, $expressions);
  97. $this->assertSame($field2, $expressions[0]);
  98. $this->assertSame($value1, $expressions[2]);
  99. $f = new TupleComparison(
  100. ['field1', $field2],
  101. [[1, 2], [3, $value1]],
  102. ['integer', 'integer'],
  103. 'IN'
  104. );
  105. $expressions = [];
  106. $f->traverse($collector);
  107. $this->assertCount(4, $expressions);
  108. $this->assertSame($field2, $expressions[0]);
  109. $this->assertSame($value1, $expressions[2]);
  110. }
  111. /**
  112. * Tests that a single ExpressionInterface can be used as the value for
  113. * comparison
  114. */
  115. public function testValueAsSingleExpression(): void
  116. {
  117. $value = new QueryExpression('SELECT 1, 1');
  118. $f = new TupleComparison(['field1', 'field2'], $value);
  119. $binder = new ValueBinder();
  120. $this->assertSame('(field1, field2) = (SELECT 1, 1)', $f->sql($binder));
  121. }
  122. /**
  123. * Tests that a single ExpressionInterface can be used as the field for
  124. * comparison
  125. */
  126. public function testFieldAsSingleExpression(): void
  127. {
  128. $value = [1, 1];
  129. $f = new TupleComparison(new QueryExpression('a, b'), $value);
  130. $binder = new ValueBinder();
  131. $this->assertSame('(a, b) = (:tuple0, :tuple1)', $f->sql($binder));
  132. }
  133. public function testMultiTupleComparisonRequiresMultiTupleValue(): void
  134. {
  135. $this->expectException(InvalidArgumentException::class);
  136. $this->expectExceptionMessage('Multi-tuple comparisons require a multi-tuple value, single-tuple given.');
  137. new TupleComparison(
  138. ['field1', 'field2'],
  139. [1, 1],
  140. ['integer', 'integer'],
  141. 'IN'
  142. );
  143. }
  144. public function testSingleTupleComparisonRequiresSingleTupleValue(): void
  145. {
  146. $this->expectException(InvalidArgumentException::class);
  147. $this->expectExceptionMessage('Single-tuple comparisons require a single-tuple value, multi-tuple given.');
  148. new TupleComparison(
  149. ['field1', 'field2'],
  150. [[1, 1], [2, 2]],
  151. ['integer', 'integer'],
  152. '='
  153. );
  154. }
  155. }