Total Complexity | 57 |
Total Lines | 1091 |
Duplicated Lines | 0 % |
Changes | 10 | ||
Bugs | 4 | Features | 0 |
Complex classes like QueryBuilderTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use QueryBuilderTest, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
24 | final class QueryBuilderTest extends TestCase |
||
25 | { |
||
26 | use SchemaBuilderTrait; |
||
27 | |||
28 | private ConnectionInterface $db; |
||
29 | private QueryBuilderInterface $queryBuilder; |
||
30 | private Mock $mock; |
||
31 | |||
32 | public function setUp(): void |
||
33 | { |
||
34 | parent::setUp(); |
||
35 | |||
36 | $this->mock = new Mock(); |
||
37 | $this->db = $this->mock->connection(); |
||
38 | $this->queryBuilder = $this->mock->queryBuilder(); |
||
39 | } |
||
40 | |||
41 | public function tearDown(): void |
||
42 | { |
||
43 | parent::tearDown(); |
||
44 | |||
45 | unset($this->queryBuilder, $this->mock); |
||
46 | } |
||
47 | |||
48 | /** |
||
49 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::addDropChecks() |
||
50 | */ |
||
51 | public function testAddDropCheck(string $sql, Closure $builder): void |
||
52 | { |
||
53 | $this->assertSame($this->mock->quoter()->quoteSql($sql), $builder($this->queryBuilder)); |
||
54 | } |
||
55 | |||
56 | /** |
||
57 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::addDropForeignKeys() |
||
58 | */ |
||
59 | public function testAddDropForeignKey(string $sql, Closure $builder): void |
||
60 | { |
||
61 | $this->assertSame($this->mock->quoter()->quoteSql($sql), $builder($this->queryBuilder)); |
||
62 | } |
||
63 | |||
64 | /** |
||
65 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::addDropPrimaryKeys() |
||
66 | */ |
||
67 | public function testAddDropPrimaryKey(string $sql, Closure $builder): void |
||
68 | { |
||
69 | $this->assertSame($this->mock->quoter()->quoteSql($sql), $builder($this->queryBuilder)); |
||
70 | } |
||
71 | |||
72 | /** |
||
73 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::addDropUniques() |
||
74 | */ |
||
75 | public function testAddDropUnique(string $sql, Closure $builder): void |
||
78 | } |
||
79 | |||
80 | public function testAddColumn(): void |
||
81 | { |
||
82 | $this->assertSame( |
||
83 | <<<SQL |
||
84 | ALTER TABLE `user` ADD `age` integer |
||
85 | SQL, |
||
86 | $this->queryBuilder->addColumn('user', 'age', 'integer') |
||
87 | ); |
||
88 | } |
||
89 | |||
90 | public function testsAddCommentOnColumn(): void |
||
91 | { |
||
92 | $this->assertSame( |
||
93 | <<<SQL |
||
94 | COMMENT ON COLUMN `user`.`name` IS 'This is a comment' |
||
95 | SQL, |
||
96 | $this->queryBuilder->addCommentOnColumn('user', 'name', 'This is a comment') |
||
97 | ); |
||
98 | } |
||
99 | |||
100 | public function testsAddCommentOnTable(): void |
||
101 | { |
||
102 | $this->assertSame( |
||
103 | <<<SQL |
||
104 | COMMENT ON TABLE `user` IS 'This is a comment' |
||
105 | SQL, |
||
106 | $this->queryBuilder->addCommentOnTable('user', 'This is a comment') |
||
107 | ); |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::alterColumn() |
||
112 | */ |
||
113 | public function testAlterColumn( |
||
114 | string $table, |
||
115 | string $column, |
||
116 | ColumnSchemaBuilder|string $type, |
||
117 | string $expected |
||
118 | ): void { |
||
119 | $sql = $this->queryBuilder->alterColumn($table, $column, $type); |
||
120 | $this->assertSame($expected, $sql); |
||
121 | } |
||
122 | |||
123 | /** |
||
124 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::batchInsert() |
||
125 | */ |
||
126 | public function testBatchInsert( |
||
127 | string $table, |
||
128 | array $columns, |
||
129 | array $value, |
||
130 | string|null $expected, |
||
131 | array $expectedParams = [] |
||
132 | ): void { |
||
133 | $params = []; |
||
134 | $sql = $this->queryBuilder->batchInsert($table, $columns, $value, $params); |
||
135 | |||
136 | $this->assertSame($expected, $sql); |
||
137 | $this->assertSame($expectedParams, $params); |
||
138 | } |
||
139 | |||
140 | public function testBuildColumnsWithString(): void |
||
141 | { |
||
142 | $columns = '(id)'; |
||
143 | |||
144 | $this->assertSame($columns, $this->queryBuilder->buildColumns($columns)); |
||
145 | } |
||
146 | |||
147 | public function testBuildColumnsWithArray(): void |
||
148 | { |
||
149 | $columns = [ |
||
150 | 'id', |
||
151 | 'name', |
||
152 | 'email', |
||
153 | 'address', |
||
154 | 'status', |
||
155 | ]; |
||
156 | |||
157 | $expected = '`id`, `name`, `email`, `address`, `status`'; |
||
158 | |||
159 | $this->assertSame($expected, $this->queryBuilder->buildColumns($columns)); |
||
160 | } |
||
161 | |||
162 | public function testBuildColumnsWithExpression(): void |
||
163 | { |
||
164 | $columns = [ |
||
165 | 'id', |
||
166 | 'name', |
||
167 | 'email', |
||
168 | 'address', |
||
169 | 'status', |
||
170 | new Expression('COUNT(*)'), |
||
171 | ]; |
||
172 | |||
173 | $expected = '`id`, `name`, `email`, `address`, `status`, COUNT(*)'; |
||
174 | |||
175 | $this->assertSame($expected, $this->queryBuilder->buildColumns($columns)); |
||
176 | } |
||
177 | |||
178 | /** |
||
179 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::buildConditions() |
||
180 | */ |
||
181 | public function testBuildCondition( |
||
182 | array|ExpressionInterface|string $conditions, |
||
183 | string $expected, |
||
184 | array $expectedParams = [] |
||
185 | ): void { |
||
186 | $query = $this->mock->query()->where($conditions); |
||
187 | [$sql, $params] = $this->queryBuilder->build($query); |
||
188 | |||
189 | $this->assertSame( |
||
190 | 'SELECT *' . ( |
||
191 | empty($expected) ? '' : ' WHERE ' . DbHelper::replaceQuotes( |
||
192 | $expected, |
||
193 | $this->mock->getDriverName(), |
||
194 | ) |
||
195 | ), |
||
196 | $sql, |
||
197 | ); |
||
198 | $this->assertSame($expectedParams, $params); |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::buildFilterCondition() |
||
203 | */ |
||
204 | public function testBuildFilterCondition(array $condition, string $expected, array $expectedParams): void |
||
219 | } |
||
220 | |||
221 | /** |
||
222 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::buildFrom() |
||
223 | */ |
||
224 | public function testBuildFrom(string $table, string $expected): void |
||
225 | { |
||
226 | $params = []; |
||
227 | $sql = $this->queryBuilder->buildFrom([$table], $params); |
||
228 | $replacedQuotes = DbHelper::replaceQuotes($expected, $this->mock->getDriverName()); |
||
229 | |||
230 | $this->assertIsString($replacedQuotes); |
||
231 | $this->assertSame('FROM ' . $replacedQuotes, $sql); |
||
232 | } |
||
233 | |||
234 | public function testBuildLimit(): void |
||
235 | { |
||
236 | $query = $this->mock->query()->limit(10); |
||
237 | [$sql, $params] = $this->queryBuilder->build($query); |
||
238 | |||
239 | $this->assertSame('SELECT * LIMIT 10', $sql); |
||
240 | $this->assertSame([], $params); |
||
241 | } |
||
242 | |||
243 | public function testBuildOffset(): void |
||
244 | { |
||
245 | $query = $this->mock->query()->offset(10); |
||
246 | [$sql, $params] = $this->queryBuilder->build($query); |
||
247 | |||
248 | $this->assertSame('SELECT * OFFSET 10', $sql); |
||
249 | $this->assertSame([], $params); |
||
250 | } |
||
251 | |||
252 | public function testBuildSelectColumnWithoutParentheses(): void |
||
253 | { |
||
254 | $params = []; |
||
255 | $sql = $this->queryBuilder->buildSelect(['1'], $params); |
||
256 | |||
257 | $this->assertSame('SELECT `1`', $sql); |
||
258 | } |
||
259 | |||
260 | public function testBuildSelectOptions(): void |
||
261 | { |
||
262 | $query = $this->mock->query()->selectOption('DISTINCT'); |
||
263 | [$sql, $params] = $this->queryBuilder->build($query); |
||
264 | |||
265 | $this->assertSame('SELECT DISTINCT *', $sql); |
||
266 | $this->assertSame([], $params); |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * This test contains three select queries connected with UNION and UNION ALL constructions. |
||
271 | * It could be useful to use "phpunit --group=db --filter testBuildUnion" command for run it. |
||
272 | */ |
||
273 | public function testBuildUnion(): void |
||
274 | { |
||
275 | $expectedQuerySql = DbHelper::replaceQuotes( |
||
276 | <<<SQL |
||
277 | (SELECT [[id]] FROM [[TotalExample]] [[t1]] WHERE (w > 0) AND (x < 2)) UNION ( SELECT [[id]] FROM [[TotalTotalExample]] [[t2]] WHERE w > 5 ) UNION ALL ( SELECT [[id]] FROM [[TotalTotalExample]] [[t3]] WHERE w = 3 ) |
||
278 | SQL, |
||
279 | $this->mock->getDriverName(), |
||
280 | ); |
||
281 | |||
282 | $secondQuery = $this->mock |
||
283 | ->query() |
||
284 | ->select('id') |
||
285 | ->from('TotalTotalExample t2') |
||
286 | ->where('w > 5'); |
||
287 | |||
288 | $thirdQuery = $this->mock |
||
289 | ->query() |
||
290 | ->select('id') |
||
291 | ->from('TotalTotalExample t3') |
||
292 | ->where('w = 3'); |
||
293 | |||
294 | $query = $this->mock |
||
295 | ->query() |
||
296 | ->select('id') |
||
297 | ->from('TotalExample t1') |
||
298 | ->where(['and', 'w > 0', 'x < 2']) |
||
299 | ->union($secondQuery) |
||
300 | ->union($thirdQuery, true); |
||
301 | |||
302 | [$actualQuerySql, $queryParams] = $this->queryBuilder->build($query); |
||
303 | |||
304 | $this->assertSame($expectedQuerySql, $actualQuerySql); |
||
305 | $this->assertSame([], $queryParams); |
||
306 | } |
||
307 | |||
308 | public function testBuildWithQuery(): void |
||
309 | { |
||
310 | $expectedQuerySql = DbHelper::replaceQuotes( |
||
311 | <<<SQL |
||
312 | WITH a1 AS (SELECT [[id]] FROM [[t1]] WHERE expr = 1), a2 AS ((SELECT [[id]] FROM [[t2]] INNER JOIN [[a1]] ON t2.id = a1.id WHERE expr = 2) UNION ( SELECT [[id]] FROM [[t3]] WHERE expr = 3 )) SELECT * FROM [[a2]] |
||
313 | SQL, |
||
314 | $this->mock->getDriverName(), |
||
315 | ); |
||
316 | |||
317 | $with1Query = $this->mock |
||
318 | ->query() |
||
319 | ->select('id') |
||
320 | ->from('t1') |
||
321 | ->where('expr = 1'); |
||
322 | |||
323 | $with2Query = $this->mock |
||
324 | ->query() |
||
325 | ->select('id') |
||
326 | ->from('t2') |
||
327 | ->innerJoin('a1', 't2.id = a1.id') |
||
328 | ->where('expr = 2'); |
||
329 | |||
330 | $with3Query = $this->mock |
||
331 | ->query() |
||
332 | ->select('id') |
||
333 | ->from('t3') |
||
334 | ->where('expr = 3'); |
||
335 | |||
336 | $query = $this->mock |
||
337 | ->query() |
||
338 | ->withQuery($with1Query, 'a1') |
||
339 | ->withQuery($with2Query->union($with3Query), 'a2') |
||
340 | ->from('a2'); |
||
341 | |||
342 | [$actualQuerySql, $queryParams] = $this->queryBuilder->build($query); |
||
343 | |||
344 | $this->assertSame($expectedQuerySql, $actualQuerySql); |
||
345 | $this->assertSame([], $queryParams); |
||
346 | } |
||
347 | |||
348 | public function testBuildWithQueryRecursive(): void |
||
349 | { |
||
350 | $expectedQuerySql = DbHelper::replaceQuotes( |
||
351 | <<<SQL |
||
352 | WITH RECURSIVE a1 AS (SELECT [[id]] FROM [[t1]] WHERE expr = 1) SELECT * FROM [[a1]] |
||
353 | SQL, |
||
354 | $this->mock->getDriverName(), |
||
355 | ); |
||
356 | |||
357 | $with1Query = $this->mock |
||
358 | ->query() |
||
359 | ->select('id') |
||
360 | ->from('t1') |
||
361 | ->where('expr = 1'); |
||
362 | |||
363 | $query = $this->mock |
||
364 | ->query() |
||
365 | ->withQuery($with1Query, 'a1', true) |
||
366 | ->from('a1'); |
||
367 | |||
368 | [$actualQuerySql, $queryParams] = $this->queryBuilder->build($query); |
||
369 | |||
370 | $this->assertSame($expectedQuerySql, $actualQuerySql); |
||
371 | $this->assertSame([], $queryParams); |
||
372 | } |
||
373 | |||
374 | /** |
||
375 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::buildWhereExists() |
||
376 | */ |
||
377 | public function testBuildWhereExists(string $cond, string $expectedQuerySql): void |
||
378 | { |
||
379 | $expectedQueryParams = []; |
||
380 | $subQuery = $this->mock->query()->select('1')->from('Website w'); |
||
381 | $query = $this->mock->query()->select('id')->from('TotalExample t')->where([$cond, $subQuery]); |
||
382 | |||
383 | [$actualQuerySql, $actualQueryParams] = $this->queryBuilder->build($query); |
||
384 | |||
385 | $this->assertSame($expectedQuerySql, $actualQuerySql); |
||
386 | $this->assertSame($expectedQueryParams, $actualQueryParams); |
||
387 | } |
||
388 | |||
389 | public function testBuildWhereExistsWithArrayParameters(): void |
||
390 | { |
||
391 | $expectedQuerySql = DbHelper::replaceQuotes( |
||
392 | <<<SQL |
||
393 | SELECT [[id]] FROM [[TotalExample]] [[t]] WHERE (EXISTS (SELECT [[1]] FROM [[Website]] [[w]] WHERE (w.id = t.website_id) AND (([[w]].[[merchant_id]]=:qp0) AND ([[w]].[[user_id]]=:qp1)))) AND ([[t]].[[some_column]]=:qp2) |
||
394 | SQL, |
||
395 | $this->mock->getDriverName(), |
||
396 | ); |
||
397 | |||
398 | $expectedQueryParams = [':qp0' => 6, ':qp1' => 210, ':qp2' => 'asd']; |
||
399 | |||
400 | $subQuery = $this->mock |
||
401 | ->query() |
||
402 | ->select('1') |
||
403 | ->from('Website w') |
||
404 | ->where('w.id = t.website_id') |
||
405 | ->andWhere(['w.merchant_id' => 6, 'w.user_id' => 210]); |
||
406 | |||
407 | $query = $this->mock |
||
408 | ->query() |
||
409 | ->select('id') |
||
410 | ->from('TotalExample t') |
||
411 | ->where(['exists', $subQuery]) |
||
412 | ->andWhere(['t.some_column' => 'asd']); |
||
413 | |||
414 | [$actualQuerySql, $queryParams] = $this->queryBuilder->build($query); |
||
415 | |||
416 | $this->assertSame($expectedQuerySql, $actualQuerySql); |
||
417 | $this->assertSame($expectedQueryParams, $queryParams); |
||
418 | } |
||
419 | |||
420 | public function testBuildWhereExistsWithParameters(): void |
||
421 | { |
||
422 | $expectedQuerySql = DbHelper::replaceQuotes( |
||
423 | <<<SQL |
||
424 | SELECT [[id]] FROM [[TotalExample]] [[t]] WHERE (EXISTS (SELECT [[1]] FROM [[Website]] [[w]] WHERE (w.id = t.website_id) AND (w.merchant_id = :merchant_id))) AND (t.some_column = :some_value) |
||
425 | SQL, |
||
426 | $this->mock->getDriverName(), |
||
427 | ); |
||
428 | |||
429 | $expectedQueryParams = [':some_value' => 'asd', ':merchant_id' => 6]; |
||
430 | |||
431 | $subQuery = $this->mock |
||
432 | ->query() |
||
433 | ->select('1') |
||
434 | ->from('Website w') |
||
435 | ->where('w.id = t.website_id') |
||
436 | ->andWhere('w.merchant_id = :merchant_id', [':merchant_id' => 6]); |
||
437 | |||
438 | $query = $this->mock |
||
439 | ->query() |
||
440 | ->select('id') |
||
441 | ->from('TotalExample t') |
||
442 | ->where(['exists', $subQuery]) |
||
443 | ->andWhere('t.some_column = :some_value', [':some_value' => 'asd']); |
||
444 | |||
445 | [$actualQuerySql, $queryParams] = $this->queryBuilder->build($query); |
||
446 | |||
447 | $this->assertSame($expectedQuerySql, $actualQuerySql); |
||
448 | $this->assertSame($expectedQueryParams, $queryParams); |
||
449 | } |
||
450 | |||
451 | /** |
||
452 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::createDropIndex() |
||
453 | */ |
||
454 | public function testCreateDropIndex(string $sql, Closure $builder): void |
||
455 | { |
||
456 | $this->assertSame($this->mock->quoter()->quoteSql($sql), $builder($this->queryBuilder)); |
||
457 | } |
||
458 | |||
459 | public function testsCreateTable(): void |
||
460 | { |
||
461 | $expected = DbHelper::replaceQuotes( |
||
462 | <<<SQL |
||
463 | CREATE TABLE [[test_table]] ( |
||
464 | \t[[id]] pk, |
||
465 | \t[[name]] string(255) NOT NULL, |
||
466 | \t[[email]] string(255) NOT NULL, |
||
467 | \t[[address]] string(255) NOT NULL, |
||
468 | \t[[status]] integer NOT NULL, |
||
469 | \t[[profile_id]] integer NOT NULL, |
||
470 | \t[[created_at]] timestamp NOT NULL, |
||
471 | \t[[updated_at]] timestamp NOT NULL |
||
472 | ) CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB |
||
473 | SQL, |
||
474 | $this->mock->getDriverName(), |
||
475 | ); |
||
476 | |||
477 | $columns = [ |
||
478 | 'id' => $this->primaryKey(5), |
||
479 | 'name' => $this->string(255)->notNull(), |
||
480 | 'email' => $this->string(255)->notNull(), |
||
481 | 'address' => $this->string(255)->notNull(), |
||
482 | 'status' => $this->integer()->notNull(), |
||
483 | 'profile_id' => $this->integer()->notNull(), |
||
484 | 'created_at' => $this->timestamp()->notNull(), |
||
485 | 'updated_at' => $this->timestamp()->notNull(), |
||
486 | ]; |
||
487 | |||
488 | $options = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; |
||
489 | |||
490 | $sql = $this->queryBuilder->createTable('test_table', $columns, $options); |
||
491 | |||
492 | Assert::equalsWithoutLE($expected, $sql); |
||
493 | } |
||
494 | |||
495 | public function testComplexSelect(): void |
||
496 | { |
||
497 | $expressionString = DbHelper::replaceQuotes( |
||
498 | <<<SQL |
||
499 | case t.Status_Id when 1 then 'Acknowledge' when 2 then 'No Action' else 'Unknown Action' END as [[Next Action]] |
||
500 | SQL, |
||
501 | $this->mock->getDriverName(), |
||
502 | ); |
||
503 | |||
504 | $expected = DbHelper::replaceQuotes( |
||
505 | <<<SQL |
||
506 | SELECT [[t]].[[id]] AS [[ID]], [[gsm]].[[username]] AS [[GSM]], [[part]].[[Part]], [[t]].[[Part_Cost]] AS [[Part Cost]], st_x(location::geometry) AS [[lon]], case t.Status_Id when 1 then 'Acknowledge' when 2 then 'No Action' else 'Unknown Action' END as [[Next Action]] FROM [[tablename]] |
||
507 | SQL, |
||
508 | $this->mock->getDriverName(), |
||
509 | ); |
||
510 | |||
511 | $this->assertIsString($expressionString); |
||
512 | |||
513 | $query = $this->mock |
||
514 | ->query() |
||
515 | ->select( |
||
516 | [ |
||
517 | 'ID' => 't.id', |
||
518 | 'gsm.username as GSM', |
||
519 | 'part.Part', |
||
520 | 'Part Cost' => 't.Part_Cost', |
||
521 | 'st_x(location::geometry) as lon', |
||
522 | new Expression($expressionString), |
||
523 | ] |
||
524 | ) |
||
525 | ->from('tablename'); |
||
526 | |||
527 | [$sql, $params] = $this->queryBuilder->build($query); |
||
528 | |||
529 | $this->assertSame($expected, $sql); |
||
530 | $this->assertEmpty($params); |
||
531 | } |
||
532 | |||
533 | public function testCreateView(): void |
||
534 | { |
||
535 | $expected = DbHelper::replaceQuotes( |
||
536 | <<<SQL |
||
537 | CREATE VIEW [[test_view]] AS SELECT [[id]], [[name]] FROM [[test_table]] |
||
538 | SQL, |
||
539 | $this->mock->getDriverName(), |
||
540 | ); |
||
541 | |||
542 | $sql = $this->queryBuilder->createView( |
||
543 | 'test_view', |
||
544 | $this->mock->query()->select(['id', 'name'])->from('test_table'), |
||
545 | ); |
||
546 | |||
547 | $this->assertSame($expected, $sql); |
||
548 | } |
||
549 | |||
550 | public function testCreateViewWithParams(): void |
||
551 | { |
||
552 | $expected = DbHelper::replaceQuotes( |
||
553 | <<<SQL |
||
554 | CREATE VIEW `test_view` AS SELECT `id`, `name` FROM `test_table` WHERE `id`=1 |
||
555 | SQL, |
||
556 | $this->mock->getDriverName(), |
||
557 | ); |
||
558 | |||
559 | $sql = $this->queryBuilder->createView( |
||
560 | 'test_view', |
||
561 | $this->mock->query()->select(['id', 'name'])->from('test_table')->where(['id' => 1]), |
||
562 | ); |
||
563 | |||
564 | $this->assertSame($expected, $sql); |
||
565 | } |
||
566 | |||
567 | /** |
||
568 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::delete() |
||
569 | */ |
||
570 | public function testDelete(string $table, array|string $condition, string $expectedSQL, array $expectedParams): void |
||
571 | { |
||
572 | $actualParams = []; |
||
573 | $actualSQL = $this->queryBuilder->delete($table, $condition, $actualParams); |
||
574 | |||
575 | $this->assertSame($expectedSQL, $actualSQL); |
||
576 | $this->assertSame($expectedParams, $actualParams); |
||
577 | } |
||
578 | |||
579 | public function testDropColumn(): void |
||
580 | { |
||
581 | $expected = DbHelper::replaceQuotes( |
||
582 | <<<SQL |
||
583 | ALTER TABLE [[test_table]] DROP COLUMN [[test_column]] |
||
584 | SQL, |
||
585 | $this->mock->getDriverName(), |
||
586 | ); |
||
587 | |||
588 | $sql = $this->queryBuilder->dropColumn('test_table', 'test_column'); |
||
589 | |||
590 | $this->assertSame($expected, $sql); |
||
591 | } |
||
592 | |||
593 | public function testdropCommentFromColumn(): void |
||
594 | { |
||
595 | $expected = DbHelper::replaceQuotes( |
||
596 | <<<SQL |
||
597 | COMMENT ON COLUMN `test_table`.`test_column` IS NULL |
||
598 | SQL, |
||
599 | $this->mock->getDriverName(), |
||
600 | ); |
||
601 | |||
602 | $sql = $this->queryBuilder->dropCommentFromColumn('test_table', 'test_column'); |
||
603 | |||
604 | $this->assertSame($expected, $sql); |
||
605 | } |
||
606 | |||
607 | public function testsdropCommentFromTable(): void |
||
608 | { |
||
609 | $expected = DbHelper::replaceQuotes( |
||
610 | <<<SQL |
||
611 | COMMENT ON TABLE `test_table` IS NULL |
||
612 | SQL, |
||
613 | $this->mock->getDriverName(), |
||
614 | ); |
||
615 | |||
616 | $sql = $this->queryBuilder->dropCommentFromTable('test_table'); |
||
617 | |||
618 | $this->assertSame($expected, $sql); |
||
619 | } |
||
620 | |||
621 | public function testDropTable(): void |
||
633 | } |
||
634 | |||
635 | public function testDropView(): void |
||
636 | { |
||
637 | $expected = DbHelper::replaceQuotes( |
||
638 | <<<SQL |
||
639 | DROP VIEW [[test_view]] |
||
640 | SQL, |
||
641 | $this->mock->getDriverName(), |
||
642 | ); |
||
643 | |||
644 | $sql = $this->queryBuilder->dropView('test_view'); |
||
645 | |||
646 | $this->assertSame($expected, $sql); |
||
647 | } |
||
648 | |||
649 | /** |
||
650 | * {@see https://github.com/yiisoft/yii2/issues/10869} |
||
651 | */ |
||
652 | public function testFromIndexHint(): void |
||
653 | { |
||
654 | $query = $this->mock->query()->from([new Expression('{{%user}} USE INDEX (primary)')]); |
||
655 | |||
656 | [$sql, $params] = $this->queryBuilder->build($query); |
||
657 | |||
658 | $expected = DbHelper::replaceQuotes( |
||
659 | <<<SQL |
||
660 | SELECT * FROM {{%user}} USE INDEX (primary) |
||
661 | SQL, |
||
662 | $this->mock->getDriverName(), |
||
663 | ); |
||
664 | |||
665 | $this->assertSame($expected, $sql); |
||
666 | $this->assertEmpty($params); |
||
667 | |||
668 | $query = $this->mock |
||
669 | ->query() |
||
670 | ->from([new Expression('{{user}} {{t}} FORCE INDEX (primary) IGNORE INDEX FOR ORDER BY (i1)')]) |
||
671 | ->leftJoin(['p' => 'profile'], 'user.id = profile.user_id USE INDEX (i2)'); |
||
672 | |||
673 | [$sql, $params] = $this->queryBuilder->build($query); |
||
674 | |||
675 | $expected = DbHelper::replaceQuotes( |
||
676 | <<<SQL |
||
677 | SELECT * FROM {{user}} {{t}} FORCE INDEX (primary) IGNORE INDEX FOR ORDER BY (i1) LEFT JOIN [[profile]] [[p]] ON user.id = profile.user_id USE INDEX (i2) |
||
678 | SQL, |
||
679 | $this->mock->getDriverName(), |
||
680 | ); |
||
681 | |||
682 | $this->assertSame($expected, $sql); |
||
683 | $this->assertEmpty($params); |
||
684 | } |
||
685 | |||
686 | public function testFromSubquery(): void |
||
687 | { |
||
688 | /* subquery */ |
||
689 | $subquery = $this->mock->query()->from('user')->where('account_id = accounts.id'); |
||
690 | $query = $this->mock->query()->from(['activeusers' => $subquery]); |
||
691 | |||
692 | /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */ |
||
693 | [$sql, $params] = $this->queryBuilder->build($query); |
||
694 | |||
695 | $expected = DbHelper::replaceQuotes( |
||
696 | <<<SQL |
||
697 | SELECT * FROM (SELECT * FROM [[user]] WHERE account_id = accounts.id) [[activeusers]] |
||
698 | SQL, |
||
699 | $this->mock->getDriverName(), |
||
700 | ); |
||
701 | |||
702 | $this->assertSame($expected, $sql); |
||
703 | $this->assertEmpty($params); |
||
704 | |||
705 | /* subquery with params */ |
||
706 | $subquery = $this->mock->query()->from('user')->where('account_id = :id', ['id' => 1]); |
||
707 | $query = $this->mock->query()->from(['activeusers' => $subquery])->where('abc = :abc', ['abc' => 'abc']); |
||
708 | |||
709 | /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */ |
||
710 | [$sql, $params] = $this->queryBuilder->build($query); |
||
711 | |||
712 | $expected = DbHelper::replaceQuotes( |
||
713 | <<<SQL |
||
714 | SELECT * FROM (SELECT * FROM [[user]] WHERE account_id = :id) [[activeusers]] WHERE abc = :abc |
||
715 | SQL, |
||
716 | $this->mock->getDriverName(), |
||
717 | ); |
||
718 | |||
719 | $this->assertSame($expected, $sql); |
||
720 | $this->assertSame(['abc' => 'abc', 'id' => 1], $params); |
||
721 | |||
722 | /* simple subquery */ |
||
723 | $subquery = '(SELECT * FROM user WHERE account_id = accounts.id)'; |
||
724 | $query = $this->mock->query()->from(['activeusers' => $subquery]); |
||
725 | |||
726 | /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */ |
||
727 | [$sql, $params] = $this->queryBuilder->build($query); |
||
728 | |||
729 | $expected = DbHelper::replaceQuotes( |
||
730 | <<<SQL |
||
731 | SELECT * FROM (SELECT * FROM user WHERE account_id = accounts.id) [[activeusers]] |
||
732 | SQL, |
||
733 | $this->mock->getDriverName(), |
||
734 | ); |
||
735 | |||
736 | $this->assertSame($expected, $sql); |
||
737 | $this->assertEmpty($params); |
||
738 | } |
||
739 | |||
740 | public function testGroupBy(): void |
||
810 | } |
||
811 | |||
812 | /** |
||
813 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::insert() |
||
814 | */ |
||
815 | public function testInsert( |
||
816 | string $table, |
||
817 | array|QueryInterface $columns, |
||
818 | array $params, |
||
819 | string $expectedSQL, |
||
820 | array $expectedParams |
||
821 | ): void { |
||
822 | $this->assertSame($expectedSQL, $this->queryBuilder->insert($table, $columns, $params)); |
||
823 | $this->assertSame($expectedParams, $params); |
||
824 | } |
||
825 | |||
826 | /** |
||
827 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::insertEx() |
||
828 | */ |
||
829 | public function testInsertEx( |
||
830 | string $table, |
||
831 | array|QueryInterface $columns, |
||
832 | array $params, |
||
833 | string $expectedSQL, |
||
834 | array $expectedParams |
||
835 | ): void { |
||
836 | $this->assertSame($expectedSQL, $this->queryBuilder->insertEx($table, $columns, $params)); |
||
837 | $this->assertSame($expectedParams, $params); |
||
838 | } |
||
839 | |||
840 | /** |
||
841 | * {@see https://github.com/yiisoft/yii2/issues/15653} |
||
842 | */ |
||
843 | public function testIssue15653(): void |
||
844 | { |
||
845 | $query = $this->mock->query()->from('admin_user')->where(['is_deleted' => false]); |
||
846 | $query->where([])->andWhere(['in', 'id', ['1', '0']]); |
||
847 | |||
848 | [$sql, $params] = $this->queryBuilder->build($query); |
||
849 | |||
850 | $this->assertSame( |
||
851 | DbHelper::replaceQuotes( |
||
852 | <<<SQL |
||
853 | SELECT * FROM [[admin_user]] WHERE [[id]] IN (:qp0, :qp1) |
||
854 | SQL, |
||
855 | $this->mock->getDriverName(), |
||
856 | ), |
||
857 | $sql, |
||
858 | ); |
||
859 | $this->assertSame([':qp0' => '1', ':qp1' => '0'], $params); |
||
860 | } |
||
861 | |||
862 | public function testOrderBy(): void |
||
863 | { |
||
864 | /* simple string */ |
||
865 | $query = $this->mock->query()->select('*')->from('operations')->orderBy('name ASC, date DESC'); |
||
866 | |||
867 | [$sql, $params] = $this->queryBuilder->build($query); |
||
868 | |||
869 | $expected = DbHelper::replaceQuotes( |
||
870 | <<<SQL |
||
871 | SELECT * FROM [[operations]] ORDER BY [[name]], [[date]] DESC |
||
872 | SQL, |
||
873 | $this->mock->getDriverName(), |
||
874 | ); |
||
875 | |||
876 | $this->assertSame($expected, $sql); |
||
877 | $this->assertEmpty($params); |
||
878 | |||
879 | /* array syntax */ |
||
880 | $query = $this->mock->query()->select('*')->from('operations')->orderBy(['name' => SORT_ASC, 'date' => SORT_DESC]); |
||
881 | |||
882 | [$sql, $params] = $this->queryBuilder->build($query); |
||
883 | |||
884 | $expected = DbHelper::replaceQuotes( |
||
885 | <<<SQL |
||
886 | SELECT * FROM [[operations]] ORDER BY [[name]], [[date]] DESC |
||
887 | SQL, |
||
888 | $this->mock->getDriverName(), |
||
889 | ); |
||
890 | |||
891 | $this->assertSame($expected, $sql); |
||
892 | $this->assertEmpty($params); |
||
893 | |||
894 | /* expression */ |
||
895 | $query = $this->mock |
||
896 | ->query() |
||
897 | ->select('*') |
||
898 | ->from('operations') |
||
899 | ->where('account_id = accounts.id') |
||
900 | ->orderBy(new Expression('SUBSTR(name, 3, 4) DESC, x ASC')); |
||
901 | |||
902 | [$sql, $params] = $this->queryBuilder->build($query); |
||
903 | |||
904 | $expected = DbHelper::replaceQuotes( |
||
905 | <<<SQL |
||
906 | SELECT * FROM [[operations]] WHERE account_id = accounts.id ORDER BY SUBSTR(name, 3, 4) DESC, x ASC |
||
907 | SQL, |
||
908 | $this->mock->getDriverName(), |
||
909 | ); |
||
910 | |||
911 | $this->assertSame($expected, $sql); |
||
912 | $this->assertEmpty($params); |
||
913 | |||
914 | /* expression with params */ |
||
915 | $query = $this->mock |
||
916 | ->query() |
||
917 | ->select('*') |
||
918 | ->from('operations') |
||
919 | ->orderBy(new Expression('SUBSTR(name, 3, :to) DESC, x ASC', [':to' => 4])); |
||
920 | |||
921 | [$sql, $params] = $this->queryBuilder->build($query); |
||
922 | |||
923 | $expected = DbHelper::replaceQuotes( |
||
924 | <<<SQL |
||
925 | SELECT * FROM [[operations]] ORDER BY SUBSTR(name, 3, :to) DESC, x ASC |
||
926 | SQL, |
||
927 | $this->mock->getDriverName(), |
||
928 | ); |
||
929 | |||
930 | $this->assertSame($expected, $sql); |
||
931 | $this->assertSame([':to' => 4], $params); |
||
932 | } |
||
933 | |||
934 | public function testRenameColumn(): void |
||
935 | { |
||
936 | $sql = $this->queryBuilder->renameColumn('alpha', 'string_identifier', 'string_identifier_test'); |
||
937 | $this->assertSame( |
||
938 | <<<SQL |
||
939 | ALTER TABLE `alpha` RENAME COLUMN `string_identifier` TO `string_identifier_test` |
||
940 | SQL, |
||
941 | $sql, |
||
942 | ); |
||
943 | |||
944 | $sql = $this->queryBuilder->renameColumn('alpha', 'string_identifier_test', 'string_identifier'); |
||
945 | $this->assertSame( |
||
946 | <<<SQL |
||
947 | ALTER TABLE `alpha` RENAME COLUMN `string_identifier_test` TO `string_identifier` |
||
948 | SQL, |
||
949 | $sql, |
||
950 | ); |
||
951 | } |
||
952 | |||
953 | public function testRenameTable(): void |
||
962 | ); |
||
963 | } |
||
964 | |||
965 | public function testSelectExpression(): void |
||
966 | { |
||
967 | $query = $this->mock->query()->select(new Expression('1 AS ab'))->from('tablename'); |
||
968 | |||
969 | [$sql, $params] = $this->queryBuilder->build($query); |
||
970 | |||
971 | $expected = DbHelper::replaceQuotes( |
||
972 | <<<SQL |
||
973 | SELECT 1 AS ab FROM [[tablename]] |
||
974 | SQL, |
||
975 | $this->mock->getDriverName(), |
||
976 | ); |
||
977 | |||
978 | $this->assertSame($expected, $sql); |
||
979 | $this->assertEmpty($params); |
||
980 | |||
981 | $query = $this->mock |
||
982 | ->query() |
||
983 | ->select(new Expression('1 AS ab')) |
||
984 | ->addSelect(new Expression('2 AS cd')) |
||
985 | ->addSelect(['ef' => new Expression('3')]) |
||
986 | ->from('tablename'); |
||
987 | |||
988 | [$sql, $params] = $this->queryBuilder->build($query); |
||
989 | |||
990 | $expected = DbHelper::replaceQuotes( |
||
991 | <<<SQL |
||
992 | SELECT 1 AS ab, 2 AS cd, 3 AS [[ef]] FROM [[tablename]] |
||
993 | SQL, |
||
994 | $this->mock->getDriverName(), |
||
995 | ); |
||
996 | |||
997 | $this->assertSame($expected, $sql); |
||
998 | $this->assertEmpty($params); |
||
999 | |||
1000 | $query = $this->mock |
||
1001 | ->query() |
||
1002 | ->select(new Expression('SUBSTR(name, 0, :len)', [':len' => 4])) |
||
1003 | ->from('tablename'); |
||
1004 | |||
1005 | [$sql, $params] = $this->queryBuilder->build($query); |
||
1006 | |||
1007 | $expected = DbHelper::replaceQuotes( |
||
1008 | <<<SQL |
||
1009 | SELECT SUBSTR(name, 0, :len) FROM [[tablename]] |
||
1010 | SQL, |
||
1011 | $this->mock->getDriverName(), |
||
1012 | ); |
||
1013 | |||
1014 | $this->assertSame($expected, $sql); |
||
1015 | $this->assertSame([':len' => 4], $params); |
||
1016 | } |
||
1017 | |||
1018 | public function testSelectExists(): void |
||
1019 | { |
||
1020 | $sql = $this->queryBuilder->selectExists('SELECT 1 FROM `table` WHERE `id` = 1'); |
||
1021 | |||
1022 | $this->assertSame('SELECT EXISTS(SELECT 1 FROM `table` WHERE `id` = 1)', $sql); |
||
1023 | } |
||
1024 | |||
1025 | public function testSelectSubquery(): void |
||
1026 | { |
||
1027 | $expected = DbHelper::replaceQuotes( |
||
1028 | <<<SQL |
||
1029 | SELECT *, (SELECT COUNT(*) FROM [[operations]] WHERE account_id = accounts.id) AS [[operations_count]] FROM [[accounts]] |
||
1030 | SQL, |
||
1031 | $this->mock->getDriverName(), |
||
1032 | ); |
||
1033 | |||
1034 | $subquery = $this->mock |
||
1035 | ->query() |
||
1036 | ->select('COUNT(*)') |
||
1037 | ->from('operations') |
||
1038 | ->where('account_id = accounts.id'); |
||
1039 | |||
1040 | $query = $this->mock |
||
1041 | ->query() |
||
1042 | ->select('*') |
||
1043 | ->from('accounts') |
||
1044 | ->addSelect(['operations_count' => $subquery]); |
||
1045 | |||
1046 | [$sql, $params] = $this->queryBuilder->build($query); |
||
1047 | |||
1048 | $this->assertSame($expected, $sql); |
||
1049 | $this->assertEmpty($params); |
||
1050 | } |
||
1051 | |||
1052 | public function testSetConditionClasses(): void |
||
1059 | } |
||
1060 | |||
1061 | public function testSelectExpressionBuilder(): void |
||
1062 | { |
||
1063 | $this->queryBuilder->setExpressionBuilders(['stdClass' => stdClass::class]); |
||
1064 | $dqlBuilder = Assert::getInaccessibleProperty($this->queryBuilder, 'dqlBuilder'); |
||
1065 | $expressionBuilders = Assert::getInaccessibleProperty($dqlBuilder, 'expressionBuilders'); |
||
1066 | |||
1067 | $this->assertSame(stdClass::class, $expressionBuilders['stdClass']); |
||
1068 | } |
||
1069 | |||
1070 | public function testSetSeparator(): void |
||
1089 | } |
||
1090 | |||
1091 | public function testTruncateTable(): void |
||
1092 | { |
||
1093 | $sql = $this->queryBuilder->truncateTable('table'); |
||
1094 | |||
1095 | $this->assertSame('TRUNCATE TABLE `table`', $sql); |
||
1096 | |||
1097 | $sql = $this->queryBuilder->truncateTable('table2'); |
||
1098 | |||
1099 | $this->assertSame('TRUNCATE TABLE `table2`', $sql); |
||
1100 | } |
||
1101 | |||
1102 | /** |
||
1103 | * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::update() |
||
1104 | */ |
||
1105 | public function testUpdate( |
||
1106 | string $table, |
||
1107 | array $columns, |
||
1108 | array|string $condition, |
||
1109 | string $expectedSQL, |
||
1110 | array $expectedParams |
||
1111 | ): void { |
||
1112 | $actualParams = []; |
||
1113 | $this->assertSame($expectedSQL, $this->queryBuilder->update($table, $columns, $condition, $actualParams)); |
||
1114 | $this->assertSame($expectedParams, $actualParams); |
||
1115 | } |
||
1116 | } |
||
1117 |