ExpressionTypeCastingIntegrationTest.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The Open Group Test Suite License
  7. * Redistributions of files must retain the above copyright notice.
  8. *
  9. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  10. * @link http://cakephp.org CakePHP(tm) Project
  11. * @since 3.3.0
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13. */
  14. namespace Cake\Test\TestCase\Database;
  15. use Cake\Database\Expression\FunctionExpression;
  16. use Cake\Database\Type;
  17. use Cake\Database\Type\BinaryType;
  18. use Cake\TestSuite\TestCase;
  19. use Cake\Datasource\ConnectionManager;
  20. use Cake\Database\Driver;
  21. use Cake\Database\Type\ExpressionTypeInterface;
  22. class UuidValue
  23. {
  24. public $value;
  25. public function __construct($value)
  26. {
  27. $this->value = $value;
  28. }
  29. }
  30. class OrderedUuidType extends Type implements ExpressionTypeInterface
  31. {
  32. public function toPHP($value, Driver $d)
  33. {
  34. return new UuidValue($value);
  35. }
  36. public function toExpression($value)
  37. {
  38. $substr = function ($start, $lenght = null) use ($value) {
  39. return new FunctionExpression(
  40. 'SUBSTR',
  41. $lenght === null ? [$value, $start] : [$value, $start, $lenght],
  42. ['string', 'integer', 'integer']
  43. );
  44. };
  45. return new FunctionExpression(
  46. 'CONCAT',
  47. [$substr(15, 4), $substr(10, 4), $substr(1, 8), $substr(20, 4), $substr(25)]
  48. );
  49. }
  50. }
  51. /**
  52. * Tests for Expression objects casting values to other expressions
  53. * using the type classes
  54. *
  55. */
  56. class ExpressionTypeCastingIntegrationTest extends TestCase
  57. {
  58. public $fixtures = ['core.ordered_uuid_items'];
  59. public function setUp()
  60. {
  61. parent::setUp();
  62. $this->connection = ConnectionManager::get('test');
  63. Type::map('ordered_uuid', OrderedUuidType::class);
  64. }
  65. protected function _insert()
  66. {
  67. $query = $this->connection->newQuery();
  68. $values = $query
  69. ->insert(['id', 'published', 'name'], ['id' => 'ordered_uuid'])
  70. ->into('ordered_uuid_items')
  71. ->clause('values');
  72. $values
  73. ->values([
  74. ['id' => '481fc6d0-b920-43e0-a40d-6d1740cf8569', 'published' => 0, 'name' => 'Item 1'],
  75. ['id' => '48298a29-81c0-4c26-a7fb-413140cf8569', 'published' => 0, 'name' => 'Item 2'],
  76. ['id' => '482b7756-8da0-419a-b21f-27da40cf8569', 'published' => 0, 'name' => 'Item 3'],
  77. ]);
  78. $query->execute();
  79. }
  80. /**
  81. * Tests inserting a value that is to be converted to an expression
  82. * automatically
  83. *
  84. * @return void
  85. */
  86. public function testInsert()
  87. {
  88. $this->_insert();
  89. $query = $this->connection->newQuery()
  90. ->select('id')
  91. ->from('ordered_uuid_items')
  92. ->order('id')
  93. ->defaultTypes(['id' => 'ordered_uuid']);
  94. $query->selectTypeMap($query->typeMap());
  95. $results = $query->execute()->fetchAll('assoc');
  96. $this->assertEquals(new UuidValue('419a8da0482b7756b21f27da40cf8569'), $results[0]['id']);
  97. $this->assertEquals(new UuidValue('43e0b920481fc6d0a40d6d1740cf8569'), $results[1]['id']);
  98. $this->assertEquals(new UuidValue('4c2681c048298a29a7fb413140cf8569'), $results[2]['id']);
  99. }
  100. /**
  101. * Test selecting with a custom expression type using conditions
  102. *
  103. * @return void
  104. */
  105. public function testSelectWithConditions()
  106. {
  107. $this->_insert();
  108. $result = $this->connection->newQuery()
  109. ->select('id')
  110. ->from('ordered_uuid_items')
  111. ->where(['id' => '48298a29-81c0-4c26-a7fb-413140cf8569'], ['id' => 'ordered_uuid'])
  112. ->execute()
  113. ->fetchAll('assoc');
  114. $this->assertCount(1, $result);
  115. $this->assertEquals('4c2681c048298a29a7fb413140cf8569', $result[0]['id']);
  116. }
  117. /**
  118. * Tests using the expression type in with an IN condition
  119. *
  120. * @var string
  121. */
  122. public function testSelectWithInCondition()
  123. {
  124. $this->_insert();
  125. $result = $this->connection->newQuery()
  126. ->select('id')
  127. ->from('ordered_uuid_items')
  128. ->where(
  129. ['id' => ['48298a29-81c0-4c26-a7fb-413140cf8569', '482b7756-8da0-419a-b21f-27da40cf8569']],
  130. ['id' => 'ordered_uuid[]']
  131. )
  132. ->order('id')
  133. ->execute()
  134. ->fetchAll('assoc');
  135. $this->assertCount(2, $result);
  136. $this->assertEquals('419a8da0482b7756b21f27da40cf8569', $result[0]['id']);
  137. $this->assertEquals('419a8da0482b7756b21f27da40cf8569', $result[0]['id']);
  138. }
  139. /**
  140. * Tests using an expression type in a between condition
  141. *
  142. * @return void
  143. */
  144. public function testSelectWithBetween()
  145. {
  146. $this->_insert();
  147. $result = $this->connection->newQuery()
  148. ->select('id')
  149. ->from('ordered_uuid_items')
  150. ->where(function ($exp) {
  151. return $exp->between(
  152. 'id',
  153. '482b7756-8da0-419a-b21f-27da40cf8569',
  154. '48298a29-81c0-4c26-a7fb-413140cf8569',
  155. 'ordered_uuid'
  156. );
  157. })
  158. ->execute()
  159. ->fetchAll('assoc');
  160. $this->assertCount(3, $result);
  161. }
  162. /**
  163. * Tests using an expression type inside a function expression
  164. *
  165. * @return void
  166. */
  167. public function testSelectWithFunction()
  168. {
  169. $this->_insert();
  170. $result = $this->connection->newQuery()
  171. ->select('id')
  172. ->from('ordered_uuid_items')
  173. ->where(function ($exp, $q) {
  174. return $exp->eq(
  175. 'id',
  176. $q->func()->concat(['48298a29-81c0-4c26-a7fb', '-413140cf8569'], []),
  177. 'ordered_uuid'
  178. );
  179. })
  180. ->execute()
  181. ->fetchAll('assoc');
  182. $this->assertCount(1, $result);
  183. $this->assertEquals('4c2681c048298a29a7fb413140cf8569', $result[0]['id']);
  184. }
  185. }