|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
declare(strict_types=1); |
|
4
|
|
|
|
|
5
|
|
|
namespace Yiisoft\Db\Tests; |
|
6
|
|
|
|
|
7
|
|
|
use PHPUnit\Framework\TestCase; |
|
8
|
|
|
use Yiisoft\Cache\Dependency\TagDependency; |
|
9
|
|
|
use Yiisoft\Db\Command\CommandInterface; |
|
10
|
|
|
use Yiisoft\Db\Command\Param; |
|
11
|
|
|
use Yiisoft\Db\Command\ParamInterface; |
|
12
|
|
|
use Yiisoft\Db\Driver\PDO\ConnectionPDOInterface; |
|
13
|
|
|
use Yiisoft\Db\Exception\Exception; |
|
14
|
|
|
use Yiisoft\Db\Exception\InvalidCallException; |
|
15
|
|
|
use Yiisoft\Db\Exception\InvalidConfigException; |
|
16
|
|
|
use Yiisoft\Db\Exception\InvalidParamException; |
|
17
|
|
|
use Yiisoft\Db\Exception\NotSupportedException; |
|
18
|
|
|
use Yiisoft\Db\Expression\Expression; |
|
19
|
|
|
use Yiisoft\Db\Query\Data\DataReader; |
|
20
|
|
|
use Yiisoft\Db\QueryBuilder\QueryBuilder; |
|
21
|
|
|
use Yiisoft\Db\Schema\Schema; |
|
22
|
|
|
use Yiisoft\Db\Schema\SchemaBuilderTrait; |
|
23
|
|
|
use Yiisoft\Db\Tests\Support\Assert; |
|
24
|
|
|
use Yiisoft\Db\Tests\Support\DbHelper; |
|
25
|
|
|
use Yiisoft\Db\Tests\Support\TestTrait; |
|
26
|
|
|
|
|
27
|
|
|
abstract class AbstractCommandTest extends TestCase |
|
28
|
|
|
{ |
|
29
|
|
|
use SchemaBuilderTrait; |
|
30
|
|
|
use TestTrait; |
|
31
|
|
|
|
|
32
|
|
|
protected ConnectionPDOInterface $db; |
|
33
|
|
|
protected string $upsertTestCharCast = ''; |
|
34
|
|
|
|
|
35
|
|
|
public function testAddCheck(): void |
|
36
|
|
|
{ |
|
37
|
|
|
$db = $this->getConnection(); |
|
38
|
|
|
|
|
39
|
|
|
$command = $db->createCommand(); |
|
40
|
|
|
$sql = $command->addCheck('name', 'table', 'id > 0')->getSql(); |
|
41
|
|
|
|
|
42
|
|
|
$this->assertSame( |
|
43
|
|
|
<<<SQL |
|
44
|
|
|
ALTER TABLE `table` ADD CONSTRAINT `name` CHECK (id > 0) |
|
45
|
|
|
SQL, |
|
46
|
|
|
$sql |
|
47
|
|
|
); |
|
48
|
|
|
} |
|
49
|
|
|
|
|
50
|
|
|
public function testAddColumn(): void |
|
51
|
|
|
{ |
|
52
|
|
|
$db = $this->getConnection(); |
|
53
|
|
|
|
|
54
|
|
|
$command = $db->createCommand(); |
|
55
|
|
|
$sql = $command->addColumn('table', 'column', Schema::TYPE_INTEGER)->getSql(); |
|
56
|
|
|
|
|
57
|
|
|
$this->assertSame( |
|
58
|
|
|
<<<SQL |
|
59
|
|
|
ALTER TABLE `table` ADD `column` integer |
|
60
|
|
|
SQL, |
|
61
|
|
|
$sql |
|
62
|
|
|
); |
|
63
|
|
|
} |
|
64
|
|
|
|
|
65
|
|
|
public function testAddCommentOnColumn(): void |
|
66
|
|
|
{ |
|
67
|
|
|
$db = $this->getConnection(); |
|
68
|
|
|
|
|
69
|
|
|
$command = $db->createCommand(); |
|
70
|
|
|
$sql = $command->addCommentOnColumn('table', 'column', 'comment')->getSql(); |
|
71
|
|
|
|
|
72
|
|
|
$this->assertSame( |
|
73
|
|
|
<<<SQL |
|
74
|
|
|
COMMENT ON COLUMN `table`.`column` IS 'comment' |
|
75
|
|
|
SQL, |
|
76
|
|
|
$sql |
|
77
|
|
|
); |
|
78
|
|
|
} |
|
79
|
|
|
|
|
80
|
|
|
public function testAddCommentOnTable(): void |
|
81
|
|
|
{ |
|
82
|
|
|
$db = $this->getConnection(); |
|
83
|
|
|
|
|
84
|
|
|
$command = $db->createCommand(); |
|
85
|
|
|
$sql = $command->addCommentOnTable('table', 'comment')->getSql(); |
|
86
|
|
|
|
|
87
|
|
|
$this->assertSame( |
|
88
|
|
|
<<<SQL |
|
89
|
|
|
COMMENT ON TABLE `table` IS 'comment' |
|
90
|
|
|
SQL, |
|
91
|
|
|
$sql |
|
92
|
|
|
); |
|
93
|
|
|
} |
|
94
|
|
|
|
|
95
|
|
|
public function testAddDefaultValue(): void |
|
96
|
|
|
{ |
|
97
|
|
|
$db = $this->getConnection(); |
|
98
|
|
|
|
|
99
|
|
|
$command = $db->createCommand(); |
|
100
|
|
|
|
|
101
|
|
|
$this->expectException(NotsupportedException::class); |
|
102
|
|
|
$this->expectExceptionMessage( |
|
103
|
|
|
'Yiisoft\Db\Tests\Support\Stubs\DDLQueryBuilder does not support adding default value constraints.' |
|
104
|
|
|
); |
|
105
|
|
|
|
|
106
|
|
|
$command->addDefaultValue('name', 'table', 'column', 'value')->getSql(); |
|
107
|
|
|
} |
|
108
|
|
|
|
|
109
|
|
|
public function testAddForeignKey(): void |
|
110
|
|
|
{ |
|
111
|
|
|
$db = $this->getConnection(); |
|
112
|
|
|
|
|
113
|
|
|
$command = $db->createCommand(); |
|
114
|
|
|
$sql = $command->addForeignKey('name', 'table', 'column', 'ref_table', 'ref_column')->getSql(); |
|
115
|
|
|
|
|
116
|
|
|
$this->assertSame( |
|
117
|
|
|
<<<SQL |
|
118
|
|
|
ALTER TABLE `table` ADD CONSTRAINT `name` FOREIGN KEY (`column`) REFERENCES `ref_table` (`ref_column`) |
|
119
|
|
|
SQL, |
|
120
|
|
|
$sql |
|
121
|
|
|
); |
|
122
|
|
|
|
|
123
|
|
|
$sql = $command->addForeignKey('name', 'table', 'column', 'ref_table', 'ref_column', 'CASCADE')->getSql(); |
|
124
|
|
|
|
|
125
|
|
|
$this->assertSame( |
|
126
|
|
|
<<<SQL |
|
127
|
|
|
ALTER TABLE `table` ADD CONSTRAINT `name` FOREIGN KEY (`column`) REFERENCES `ref_table` (`ref_column`) ON DELETE CASCADE |
|
128
|
|
|
SQL, |
|
129
|
|
|
$sql |
|
130
|
|
|
); |
|
131
|
|
|
|
|
132
|
|
|
$sql = $command |
|
133
|
|
|
->addForeignKey('name', 'table', 'column', 'ref_table', 'ref_column', 'CASCADE', 'CASCADE') |
|
134
|
|
|
->getSql(); |
|
135
|
|
|
|
|
136
|
|
|
$this->assertSame( |
|
137
|
|
|
<<<SQL |
|
138
|
|
|
ALTER TABLE `table` ADD CONSTRAINT `name` FOREIGN KEY (`column`) REFERENCES `ref_table` (`ref_column`) ON DELETE CASCADE ON UPDATE CASCADE |
|
139
|
|
|
SQL, |
|
140
|
|
|
$sql |
|
141
|
|
|
); |
|
142
|
|
|
} |
|
143
|
|
|
|
|
144
|
|
|
public function testAddPrimaryKey(): void |
|
145
|
|
|
{ |
|
146
|
|
|
$db = $this->getConnection(); |
|
147
|
|
|
|
|
148
|
|
|
$command = $db->createCommand(); |
|
149
|
|
|
$sql = $command->addPrimaryKey('name', 'table', 'column')->getSql(); |
|
150
|
|
|
|
|
151
|
|
|
$this->assertSame( |
|
152
|
|
|
<<<SQL |
|
153
|
|
|
ALTER TABLE `table` ADD CONSTRAINT `name` PRIMARY KEY (`column`) |
|
154
|
|
|
SQL, |
|
155
|
|
|
$sql |
|
156
|
|
|
); |
|
157
|
|
|
|
|
158
|
|
|
$sql = $command->addPrimaryKey('name', 'table', ['column1', 'column2'])->getSql(); |
|
159
|
|
|
|
|
160
|
|
|
$this->assertSame( |
|
161
|
|
|
<<<SQL |
|
162
|
|
|
ALTER TABLE `table` ADD CONSTRAINT `name` PRIMARY KEY (`column1`, `column2`) |
|
163
|
|
|
SQL, |
|
164
|
|
|
$sql |
|
165
|
|
|
); |
|
166
|
|
|
} |
|
167
|
|
|
|
|
168
|
|
|
public function testAddUnique(): void |
|
169
|
|
|
{ |
|
170
|
|
|
$db = $this->getConnection(); |
|
171
|
|
|
|
|
172
|
|
|
$command = $db->createCommand(); |
|
173
|
|
|
$sql = $command->addUnique('name', 'table', 'column')->getSql(); |
|
174
|
|
|
|
|
175
|
|
|
$this->assertSame( |
|
176
|
|
|
<<<SQL |
|
177
|
|
|
ALTER TABLE `table` ADD CONSTRAINT `name` UNIQUE (`column`) |
|
178
|
|
|
SQL, |
|
179
|
|
|
$sql |
|
180
|
|
|
); |
|
181
|
|
|
|
|
182
|
|
|
$sql = $command->addUnique('name', 'table', ['column1', 'column2'])->getSql(); |
|
183
|
|
|
|
|
184
|
|
|
$this->assertSame( |
|
185
|
|
|
<<<SQL |
|
186
|
|
|
ALTER TABLE `table` ADD CONSTRAINT `name` UNIQUE (`column1`, `column2`) |
|
187
|
|
|
SQL, |
|
188
|
|
|
$sql |
|
189
|
|
|
); |
|
190
|
|
|
} |
|
191
|
|
|
|
|
192
|
|
|
public function testAlterColumn(): void |
|
193
|
|
|
{ |
|
194
|
|
|
$db = $this->getConnection(); |
|
195
|
|
|
|
|
196
|
|
|
$command = $db->createCommand(); |
|
197
|
|
|
$sql = $command->alterColumn('table', 'column', Schema::TYPE_INTEGER)->getSql(); |
|
198
|
|
|
|
|
199
|
|
|
$this->assertSame( |
|
200
|
|
|
<<<SQL |
|
201
|
|
|
ALTER TABLE `table` CHANGE `column` `column` integer |
|
202
|
|
|
SQL, |
|
203
|
|
|
$sql |
|
204
|
|
|
); |
|
205
|
|
|
} |
|
206
|
|
|
|
|
207
|
|
|
public function testBatchInsert(): void |
|
208
|
|
|
{ |
|
209
|
|
|
$db = $this->getConnection(); |
|
210
|
|
|
|
|
211
|
|
|
$command = $db->createCommand(); |
|
212
|
|
|
|
|
213
|
|
|
$this->expectException(NotsupportedException::class); |
|
214
|
|
|
$this->expectExceptionMessage( |
|
215
|
|
|
'Yiisoft\Db\Tests\Support\Stubs\Schema::loadTableSchema() is not supported by core-db.' |
|
216
|
|
|
); |
|
217
|
|
|
|
|
218
|
|
|
$command->batchInsert( |
|
219
|
|
|
'table', |
|
220
|
|
|
['column1', 'column2'], |
|
221
|
|
|
[ |
|
222
|
|
|
['value1', 'value2'], |
|
223
|
|
|
['value3', 'value4'], |
|
224
|
|
|
] |
|
225
|
|
|
)->getSql(); |
|
226
|
|
|
} |
|
227
|
|
|
|
|
228
|
|
|
public function testBindValues(): void |
|
229
|
|
|
{ |
|
230
|
|
|
$db = $this->getConnection(); |
|
231
|
|
|
|
|
232
|
|
|
$command = $db->createCommand(); |
|
233
|
|
|
|
|
234
|
|
|
$values = ['int' => 1, 'string' => 'str']; |
|
235
|
|
|
$command->bindValues($values); |
|
236
|
|
|
$bindedValues = $command->getParams(false); |
|
237
|
|
|
|
|
238
|
|
|
$this->assertIsArray($bindedValues); |
|
239
|
|
|
$this->assertContainsOnlyInstancesOf(ParamInterface::class, $bindedValues); |
|
240
|
|
|
$this->assertCount(2, $bindedValues); |
|
241
|
|
|
|
|
242
|
|
|
$param = new Param('str', 99); |
|
243
|
|
|
$command->bindValues(['param' => $param]); |
|
244
|
|
|
$bindedValues = $command->getParams(false); |
|
245
|
|
|
|
|
246
|
|
|
$this->assertIsArray($bindedValues); |
|
247
|
|
|
$this->assertContainsOnlyInstancesOf(ParamInterface::class, $bindedValues); |
|
248
|
|
|
$this->assertCount(3, $bindedValues); |
|
249
|
|
|
$this->assertSame($param, $bindedValues['param']); |
|
250
|
|
|
$this->assertNotEquals($param, $bindedValues['int']); |
|
251
|
|
|
|
|
252
|
|
|
/* Replace test */ |
|
253
|
|
|
$command->bindValues(['int' => $param]); |
|
254
|
|
|
$bindedValues = $command->getParams(false); |
|
255
|
|
|
|
|
256
|
|
|
$this->assertIsArray($bindedValues); |
|
257
|
|
|
$this->assertContainsOnlyInstancesOf(ParamInterface::class, $bindedValues); |
|
258
|
|
|
$this->assertCount(3, $bindedValues); |
|
259
|
|
|
$this->assertSame($param, $bindedValues['int']); |
|
260
|
|
|
} |
|
261
|
|
|
|
|
262
|
|
|
public function testCache(): void |
|
263
|
|
|
{ |
|
264
|
|
|
$db = $this->getConnection(); |
|
265
|
|
|
|
|
266
|
|
|
$tagDependency = new TagDependency('tag'); |
|
267
|
|
|
$command = $db->createCommand(); |
|
268
|
|
|
$command->cache(100, $tagDependency); |
|
269
|
|
|
|
|
270
|
|
|
$this->assertInstanceOf(CommandInterface::class, $command); |
|
271
|
|
|
$this->assertSame(100, Assert::getInaccessibleProperty($command, 'queryCacheDuration')); |
|
272
|
|
|
$this->assertSame($tagDependency, Assert::getInaccessibleProperty($command, 'queryCacheDependency')); |
|
273
|
|
|
} |
|
274
|
|
|
|
|
275
|
|
|
public function testCheckIntegrity(): void |
|
276
|
|
|
{ |
|
277
|
|
|
$db = $this->getConnection(); |
|
278
|
|
|
|
|
279
|
|
|
$command = $db->createCommand(); |
|
280
|
|
|
|
|
281
|
|
|
$this->expectException(NotsupportedException::class); |
|
282
|
|
|
$this->expectExceptionMessage( |
|
283
|
|
|
'Yiisoft\Db\Tests\Support\Stubs\DDLQueryBuilder does not support enabling/disabling integrity check.' |
|
284
|
|
|
); |
|
285
|
|
|
|
|
286
|
|
|
$command->checkIntegrity('schema', 'table')->getSql(); |
|
287
|
|
|
} |
|
288
|
|
|
|
|
289
|
|
|
public function testConstruct(): void |
|
290
|
|
|
{ |
|
291
|
|
|
$db = $this->getConnection(); |
|
292
|
|
|
|
|
293
|
|
|
$command = $db->createCommand(); |
|
294
|
|
|
|
|
295
|
|
|
$this->assertEmpty($command->getSql()); |
|
296
|
|
|
|
|
297
|
|
|
$sql = <<<SQL |
|
298
|
|
|
SELECT * FROM customer WHERE name=:name |
|
299
|
|
|
SQL; |
|
300
|
|
|
$command = $db->createCommand($sql, [':name' => 'John']); |
|
301
|
|
|
|
|
302
|
|
|
$this->assertSame($sql, $command->getSql()); |
|
303
|
|
|
$this->assertSame([':name' => 'John'], $command->getParams()); |
|
304
|
|
|
} |
|
305
|
|
|
|
|
306
|
|
|
public function testCreateIndex(): void |
|
307
|
|
|
{ |
|
308
|
|
|
$db = $this->getConnection(); |
|
309
|
|
|
|
|
310
|
|
|
$command = $db->createCommand(); |
|
311
|
|
|
|
|
312
|
|
|
$sql = $command->createIndex('name', 'table', 'column')->getSql(); |
|
313
|
|
|
|
|
314
|
|
|
$this->assertSame( |
|
315
|
|
|
<<<SQL |
|
316
|
|
|
CREATE INDEX `name` ON `table` (`column`) |
|
317
|
|
|
SQL, |
|
318
|
|
|
$sql |
|
319
|
|
|
); |
|
320
|
|
|
|
|
321
|
|
|
$sql = $command->createIndex('name', 'table', ['column1', 'column2'])->getSql(); |
|
322
|
|
|
|
|
323
|
|
|
$this->assertSame( |
|
324
|
|
|
<<<SQL |
|
325
|
|
|
CREATE INDEX `name` ON `table` (`column1`, `column2`) |
|
326
|
|
|
SQL, |
|
327
|
|
|
$sql |
|
328
|
|
|
); |
|
329
|
|
|
|
|
330
|
|
|
$sql = $command->createIndex('name', 'table', ['column1', 'column2'], QueryBuilder::INDEX_UNIQUE)->getSql(); |
|
331
|
|
|
|
|
332
|
|
|
$this->assertSame( |
|
333
|
|
|
<<<SQL |
|
334
|
|
|
CREATE UNIQUE INDEX `name` ON `table` (`column1`, `column2`) |
|
335
|
|
|
SQL, |
|
336
|
|
|
$sql |
|
337
|
|
|
); |
|
338
|
|
|
|
|
339
|
|
|
$sql = $command->createIndex('name', 'table', ['column1', 'column2'], 'FULLTEXT')->getSql(); |
|
340
|
|
|
|
|
341
|
|
|
$this->assertSame( |
|
342
|
|
|
<<<SQL |
|
343
|
|
|
CREATE FULLTEXT INDEX `name` ON `table` (`column1`, `column2`) |
|
344
|
|
|
SQL, |
|
345
|
|
|
$sql |
|
346
|
|
|
); |
|
347
|
|
|
|
|
348
|
|
|
$sql = $command->createIndex('name', 'table', ['column1', 'column2'], 'SPATIAL')->getSql(); |
|
349
|
|
|
|
|
350
|
|
|
$this->assertSame( |
|
351
|
|
|
<<<SQL |
|
352
|
|
|
CREATE SPATIAL INDEX `name` ON `table` (`column1`, `column2`) |
|
353
|
|
|
SQL, |
|
354
|
|
|
$sql |
|
355
|
|
|
); |
|
356
|
|
|
|
|
357
|
|
|
$sql = $command->createIndex('name', 'table', ['column1', 'column2'], 'BITMAP')->getSql(); |
|
358
|
|
|
|
|
359
|
|
|
$this->assertSame( |
|
360
|
|
|
<<<SQL |
|
361
|
|
|
CREATE BITMAP INDEX `name` ON `table` (`column1`, `column2`) |
|
362
|
|
|
SQL, |
|
363
|
|
|
$sql |
|
364
|
|
|
); |
|
365
|
|
|
} |
|
366
|
|
|
|
|
367
|
|
|
public function testCreateTable(): void |
|
368
|
|
|
{ |
|
369
|
|
|
$this->db = $this->getConnectionWithData(); |
|
370
|
|
|
|
|
371
|
|
|
$command = $this->db->createCommand(); |
|
372
|
|
|
|
|
373
|
|
|
$expected = DbHelper::replaceQuotes( |
|
374
|
|
|
<<<SQL |
|
375
|
|
|
CREATE TABLE [[test_table]] ( |
|
376
|
|
|
\t[[id]] pk, |
|
377
|
|
|
\t[[name]] string(255) NOT NULL, |
|
378
|
|
|
\t[[email]] string(255) NOT NULL, |
|
379
|
|
|
\t[[address]] string(255) NOT NULL, |
|
380
|
|
|
\t[[status]] integer NOT NULL, |
|
381
|
|
|
\t[[profile_id]] integer NOT NULL, |
|
382
|
|
|
\t[[created_at]] timestamp NOT NULL, |
|
383
|
|
|
\t[[updated_at]] timestamp NOT NULL |
|
384
|
|
|
) CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB |
|
385
|
|
|
SQL, |
|
386
|
|
|
$this->db->getName(), |
|
387
|
|
|
); |
|
388
|
|
|
$columns = [ |
|
389
|
|
|
'id' => $this->primaryKey(5), |
|
390
|
|
|
'name' => $this->string(255)->notNull(), |
|
391
|
|
|
'email' => $this->string(255)->notNull(), |
|
392
|
|
|
'address' => $this->string(255)->notNull(), |
|
393
|
|
|
'status' => $this->integer()->notNull(), |
|
394
|
|
|
'profile_id' => $this->integer()->notNull(), |
|
395
|
|
|
'created_at' => $this->timestamp()->notNull(), |
|
396
|
|
|
'updated_at' => $this->timestamp()->notNull(), |
|
397
|
|
|
]; |
|
398
|
|
|
$options = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; |
|
399
|
|
|
$sql = $command->createTable('test_table', $columns, $options)->getSql(); |
|
400
|
|
|
|
|
401
|
|
|
Assert::equalsWithoutLE($expected, $sql); |
|
402
|
|
|
} |
|
403
|
|
|
|
|
404
|
|
|
public function testCreateView(): void |
|
405
|
|
|
{ |
|
406
|
|
|
$db = $this->getConnection(); |
|
407
|
|
|
|
|
408
|
|
|
$command = $db->createCommand(); |
|
409
|
|
|
|
|
410
|
|
|
$sql = $command->createView( |
|
411
|
|
|
'view', |
|
412
|
|
|
<<<SQL |
|
413
|
|
|
SELECT * FROM table |
|
414
|
|
|
SQL, |
|
415
|
|
|
)->getSql(); |
|
416
|
|
|
|
|
417
|
|
|
$this->assertSame( |
|
418
|
|
|
<<<SQL |
|
419
|
|
|
CREATE VIEW `view` AS SELECT * FROM table |
|
420
|
|
|
SQL, |
|
421
|
|
|
$sql |
|
422
|
|
|
); |
|
423
|
|
|
} |
|
424
|
|
|
|
|
425
|
|
|
public function testDataReaderCreationException(): void |
|
426
|
|
|
{ |
|
427
|
|
|
$db = $this->getConnection(); |
|
428
|
|
|
|
|
429
|
|
|
$this->expectException(InvalidParamException::class); |
|
430
|
|
|
$this->expectExceptionMessage('The PDOStatement cannot be null.'); |
|
431
|
|
|
|
|
432
|
|
|
$sql = 'SELECT * FROM {{customer}}'; |
|
433
|
|
|
new DataReader($db->createCommand($sql)); |
|
434
|
|
|
} |
|
435
|
|
|
|
|
436
|
|
|
public function testDelete(): void |
|
437
|
|
|
{ |
|
438
|
|
|
$db = $this->getConnection(); |
|
439
|
|
|
|
|
440
|
|
|
$command = $db->createCommand(); |
|
441
|
|
|
$sql = $command->delete('table', ['column' => 'value'])->getSql(); |
|
442
|
|
|
|
|
443
|
|
|
$this->assertSame( |
|
444
|
|
|
<<<SQL |
|
445
|
|
|
DELETE FROM `table` WHERE `column`=:qp0 |
|
446
|
|
|
SQL, |
|
447
|
|
|
$sql |
|
448
|
|
|
); |
|
449
|
|
|
} |
|
450
|
|
|
|
|
451
|
|
|
public function testDropCheck(): void |
|
452
|
|
|
{ |
|
453
|
|
|
$db = $this->getConnection(); |
|
454
|
|
|
|
|
455
|
|
|
$command = $db->createCommand(); |
|
456
|
|
|
$sql = $command->dropCheck('name', 'table')->getSql(); |
|
457
|
|
|
|
|
458
|
|
|
$this->assertSame( |
|
459
|
|
|
<<<SQL |
|
460
|
|
|
ALTER TABLE `table` DROP CONSTRAINT `name` |
|
461
|
|
|
SQL, |
|
462
|
|
|
$sql |
|
463
|
|
|
); |
|
464
|
|
|
} |
|
465
|
|
|
|
|
466
|
|
|
public function testDropColumn(): void |
|
467
|
|
|
{ |
|
468
|
|
|
$db = $this->getConnection(); |
|
469
|
|
|
|
|
470
|
|
|
$command = $db->createCommand(); |
|
471
|
|
|
$sql = $command->dropColumn('table', 'column')->getSql(); |
|
472
|
|
|
|
|
473
|
|
|
$this->assertSame( |
|
474
|
|
|
<<<SQL |
|
475
|
|
|
ALTER TABLE `table` DROP COLUMN `column` |
|
476
|
|
|
SQL, |
|
477
|
|
|
$sql |
|
478
|
|
|
); |
|
479
|
|
|
} |
|
480
|
|
|
|
|
481
|
|
|
public function testDropCommentFromColumn(): void |
|
482
|
|
|
{ |
|
483
|
|
|
$db = $this->getConnection(); |
|
484
|
|
|
|
|
485
|
|
|
$command = $db->createCommand(); |
|
486
|
|
|
$sql = $command->dropCommentFromColumn('table', 'column')->getSql(); |
|
487
|
|
|
|
|
488
|
|
|
$this->assertSame( |
|
489
|
|
|
<<<SQL |
|
490
|
|
|
COMMENT ON COLUMN `table`.`column` IS NULL |
|
491
|
|
|
SQL, |
|
492
|
|
|
$sql |
|
493
|
|
|
); |
|
494
|
|
|
} |
|
495
|
|
|
|
|
496
|
|
|
public function testDropCommentFromTable(): void |
|
497
|
|
|
{ |
|
498
|
|
|
$db = $this->getConnection(); |
|
499
|
|
|
|
|
500
|
|
|
$command = $db->createCommand(); |
|
501
|
|
|
$sql = $command->dropCommentFromTable('table')->getSql(); |
|
502
|
|
|
|
|
503
|
|
|
$this->assertSame( |
|
504
|
|
|
<<<SQL |
|
505
|
|
|
COMMENT ON TABLE `table` IS NULL |
|
506
|
|
|
SQL, |
|
507
|
|
|
$sql |
|
508
|
|
|
); |
|
509
|
|
|
} |
|
510
|
|
|
|
|
511
|
|
|
public function testDropDefaultValue(): void |
|
512
|
|
|
{ |
|
513
|
|
|
$db = $this->getConnection(); |
|
514
|
|
|
|
|
515
|
|
|
$command = $db->createCommand(); |
|
516
|
|
|
|
|
517
|
|
|
$this->expectException(NotsupportedException::class); |
|
518
|
|
|
$this->expectExceptionMessage( |
|
519
|
|
|
'Yiisoft\Db\Tests\Support\Stubs\DDLQueryBuilder does not support dropping default value constraints.' |
|
520
|
|
|
); |
|
521
|
|
|
|
|
522
|
|
|
$command->dropDefaultValue('table', 'column')->getSql(); |
|
523
|
|
|
} |
|
524
|
|
|
|
|
525
|
|
|
public function testDropForeingKey(): void |
|
526
|
|
|
{ |
|
527
|
|
|
$db = $this->getConnection(); |
|
528
|
|
|
|
|
529
|
|
|
$command = $db->createCommand(); |
|
530
|
|
|
$sql = $command->dropForeignKey('name', 'table')->getSql(); |
|
531
|
|
|
|
|
532
|
|
|
$this->assertSame( |
|
533
|
|
|
<<<SQL |
|
534
|
|
|
ALTER TABLE `table` DROP CONSTRAINT `name` |
|
535
|
|
|
SQL, |
|
536
|
|
|
$sql |
|
537
|
|
|
); |
|
538
|
|
|
} |
|
539
|
|
|
|
|
540
|
|
|
public function testDropIndex(): void |
|
541
|
|
|
{ |
|
542
|
|
|
$db = $this->getConnection(); |
|
543
|
|
|
|
|
544
|
|
|
$command = $db->createCommand(); |
|
545
|
|
|
$sql = $command->dropIndex('name', 'table')->getSql(); |
|
546
|
|
|
|
|
547
|
|
|
$this->assertSame( |
|
548
|
|
|
<<<SQL |
|
549
|
|
|
DROP INDEX `name` ON `table` |
|
550
|
|
|
SQL, |
|
551
|
|
|
$sql |
|
552
|
|
|
); |
|
553
|
|
|
} |
|
554
|
|
|
|
|
555
|
|
|
public function testDropPrimaryKey(): void |
|
556
|
|
|
{ |
|
557
|
|
|
$db = $this->getConnection(); |
|
558
|
|
|
|
|
559
|
|
|
$command = $db->createCommand(); |
|
560
|
|
|
$sql = $command->dropPrimaryKey('name', 'table')->getSql(); |
|
561
|
|
|
|
|
562
|
|
|
$this->assertSame( |
|
563
|
|
|
<<<SQL |
|
564
|
|
|
ALTER TABLE `table` DROP CONSTRAINT `name` |
|
565
|
|
|
SQL, |
|
566
|
|
|
$sql |
|
567
|
|
|
); |
|
568
|
|
|
} |
|
569
|
|
|
|
|
570
|
|
|
public function testDropTable(): void |
|
571
|
|
|
{ |
|
572
|
|
|
$db = $this->getConnection(); |
|
573
|
|
|
|
|
574
|
|
|
$command = $db->createCommand(); |
|
575
|
|
|
$sql = $command->dropTable('table')->getSql(); |
|
576
|
|
|
|
|
577
|
|
|
$this->assertSame( |
|
578
|
|
|
<<<SQL |
|
579
|
|
|
DROP TABLE `table` |
|
580
|
|
|
SQL, |
|
581
|
|
|
$sql |
|
582
|
|
|
); |
|
583
|
|
|
} |
|
584
|
|
|
|
|
585
|
|
|
public function testDropView(): void |
|
586
|
|
|
{ |
|
587
|
|
|
$db = $this->getConnection(); |
|
588
|
|
|
|
|
589
|
|
|
$command = $db->createCommand(); |
|
590
|
|
|
$sql = $command->dropView('view')->getSql(); |
|
591
|
|
|
|
|
592
|
|
|
$this->assertSame( |
|
593
|
|
|
<<<SQL |
|
594
|
|
|
DROP VIEW `view` |
|
595
|
|
|
SQL, |
|
596
|
|
|
$sql |
|
597
|
|
|
); |
|
598
|
|
|
} |
|
599
|
|
|
|
|
600
|
|
|
public function testDropUnique(): void |
|
601
|
|
|
{ |
|
602
|
|
|
$db = $this->getConnection(); |
|
603
|
|
|
|
|
604
|
|
|
$command = $db->createCommand(); |
|
605
|
|
|
$sql = $command->dropUnique('name', 'table')->getSql(); |
|
606
|
|
|
|
|
607
|
|
|
$this->assertSame( |
|
608
|
|
|
<<<SQL |
|
609
|
|
|
ALTER TABLE `table` DROP CONSTRAINT `name` |
|
610
|
|
|
SQL, |
|
611
|
|
|
$sql |
|
612
|
|
|
); |
|
613
|
|
|
} |
|
614
|
|
|
|
|
615
|
|
|
public function testExecute(): void |
|
616
|
|
|
{ |
|
617
|
|
|
$db = $this->getConnectionWithData(); |
|
618
|
|
|
|
|
619
|
|
|
$command = $db->createCommand( |
|
620
|
|
|
<<<SQL |
|
621
|
|
|
SELECT * FROM {{customer}} WHERE id=:id |
|
622
|
|
|
SQL, |
|
623
|
|
|
[ |
|
624
|
|
|
':id' => 1, |
|
625
|
|
|
] |
|
626
|
|
|
); |
|
627
|
|
|
|
|
628
|
|
|
$this->expectException(NotsupportedException::class); |
|
629
|
|
|
$this->expectExceptionMessage( |
|
630
|
|
|
'Yiisoft\Db\Tests\Support\Stubs\Command does not support internalExecute() by core-db.' |
|
631
|
|
|
); |
|
632
|
|
|
|
|
633
|
|
|
$command->execute(); |
|
634
|
|
|
} |
|
635
|
|
|
|
|
636
|
|
|
public function testExecuteResetSequence(): void |
|
637
|
|
|
{ |
|
638
|
|
|
$db = $this->getConnection(); |
|
639
|
|
|
|
|
640
|
|
|
$command = $db->createCommand(); |
|
641
|
|
|
|
|
642
|
|
|
$this->expectException(NotsupportedException::class); |
|
643
|
|
|
$this->expectExceptionMessage( |
|
644
|
|
|
'Yiisoft\Db\Tests\Support\Stubs\DMLQueryBuilder does not support resetting sequence.' |
|
645
|
|
|
); |
|
646
|
|
|
|
|
647
|
|
|
$command->executeResetSequence('table')->getSql(); |
|
648
|
|
|
} |
|
649
|
|
|
|
|
650
|
|
|
public function testExecuteWithSqlEmtpy(): void |
|
651
|
|
|
{ |
|
652
|
|
|
$db = $this->getConnection(); |
|
653
|
|
|
|
|
654
|
|
|
$command = $db->createCommand(); |
|
655
|
|
|
|
|
656
|
|
|
$this->assertSame(0, $command->execute()); |
|
657
|
|
|
} |
|
658
|
|
|
|
|
659
|
|
|
public function testGetParams(): void |
|
660
|
|
|
{ |
|
661
|
|
|
$db = $this->getConnection(); |
|
662
|
|
|
|
|
663
|
|
|
$command = $db->createCommand(); |
|
664
|
|
|
$values = [ |
|
665
|
|
|
'int' => 1, |
|
666
|
|
|
'string' => 'str', |
|
667
|
|
|
]; |
|
668
|
|
|
$command->bindValues($values); |
|
669
|
|
|
$bindedValues = $command->getParams(false); |
|
670
|
|
|
|
|
671
|
|
|
$this->assertIsArray($bindedValues); |
|
672
|
|
|
$this->assertContainsOnlyInstancesOf(ParamInterface::class, $bindedValues); |
|
673
|
|
|
$this->assertCount(2, $bindedValues); |
|
674
|
|
|
|
|
675
|
|
|
$param = new Param('str', 99); |
|
676
|
|
|
$command->bindValues(['param' => $param]); |
|
677
|
|
|
$bindedValues = $command->getParams(false); |
|
678
|
|
|
|
|
679
|
|
|
$this->assertIsArray($bindedValues); |
|
680
|
|
|
$this->assertContainsOnlyInstancesOf(ParamInterface::class, $bindedValues); |
|
681
|
|
|
$this->assertCount(3, $bindedValues); |
|
682
|
|
|
$this->assertEquals($param, $bindedValues['param']); |
|
683
|
|
|
$this->assertNotEquals($param, $bindedValues['int']); |
|
684
|
|
|
|
|
685
|
|
|
/* Replace test */ |
|
686
|
|
|
$command->bindValues(['int' => $param]); |
|
687
|
|
|
$bindedValues = $command->getParams(false); |
|
688
|
|
|
|
|
689
|
|
|
$this->assertIsArray($bindedValues); |
|
690
|
|
|
$this->assertContainsOnlyInstancesOf(ParamInterface::class, $bindedValues); |
|
691
|
|
|
$this->assertCount(3, $bindedValues); |
|
692
|
|
|
$this->assertEquals($param, $bindedValues['int']); |
|
693
|
|
|
} |
|
694
|
|
|
|
|
695
|
|
|
/** |
|
696
|
|
|
* Test command getRawSql. |
|
697
|
|
|
* |
|
698
|
|
|
* @dataProvider \Yiisoft\Db\Tests\Provider\CommandProvider::rawSql() |
|
699
|
|
|
* |
|
700
|
|
|
* @throws Exception |
|
701
|
|
|
* @throws InvalidConfigException |
|
702
|
|
|
* @throws NotSupportedException |
|
703
|
|
|
* |
|
704
|
|
|
* {@see https://github.com/yiisoft/yii2/issues/8592} |
|
705
|
|
|
*/ |
|
706
|
|
|
public function testGetRawSql(string $sql, array $params, string $expectedRawSql): void |
|
707
|
|
|
{ |
|
708
|
|
|
$db = $this->getConnection(); |
|
709
|
|
|
|
|
710
|
|
|
$command = $db->createCommand($sql, $params); |
|
711
|
|
|
|
|
712
|
|
|
$this->assertSame($expectedRawSql, $command->getRawSql()); |
|
713
|
|
|
} |
|
714
|
|
|
|
|
715
|
|
|
public function testGetSetSql(): void |
|
716
|
|
|
{ |
|
717
|
|
|
$db = $this->getConnection(); |
|
718
|
|
|
|
|
719
|
|
|
$sql = <<<SQL |
|
720
|
|
|
SELECT * FROM customer |
|
721
|
|
|
SQL; |
|
722
|
|
|
$command = $db->createCommand($sql); |
|
723
|
|
|
$this->assertSame($sql, $command->getSql()); |
|
724
|
|
|
|
|
725
|
|
|
$sql2 = <<<SQL |
|
726
|
|
|
SELECT * FROM order |
|
727
|
|
|
SQL; |
|
728
|
|
|
$command->setSql($sql2); |
|
729
|
|
|
$this->assertSame($sql2, $command->getSql()); |
|
730
|
|
|
} |
|
731
|
|
|
|
|
732
|
|
|
public function testInsert(): void |
|
733
|
|
|
{ |
|
734
|
|
|
$db = $this->getConnectionWithData(); |
|
735
|
|
|
|
|
736
|
|
|
$this->expectException(NotsupportedException::class); |
|
737
|
|
|
$this->expectExceptionMessage( |
|
738
|
|
|
'Yiisoft\Db\Tests\Support\Stubs\Schema::loadTableSchema() is not supported by core-db.' |
|
739
|
|
|
); |
|
740
|
|
|
|
|
741
|
|
|
$command = $db->createCommand(); |
|
742
|
|
|
$command |
|
743
|
|
|
->insert('{{customer}}', ['email' => '[email protected]', 'name' => 'test', 'address' => 'test address']) |
|
744
|
|
|
->execute(); |
|
745
|
|
|
} |
|
746
|
|
|
|
|
747
|
|
|
public function testLastInsertIdException(): void |
|
748
|
|
|
{ |
|
749
|
|
|
$db = $this->getConnection(); |
|
750
|
|
|
|
|
751
|
|
|
$db->close(); |
|
752
|
|
|
|
|
753
|
|
|
$this->expectException(InvalidCallException::class); |
|
754
|
|
|
|
|
755
|
|
|
$db->getLastInsertID(); |
|
756
|
|
|
} |
|
757
|
|
|
|
|
758
|
|
|
public function testNoCache(): void |
|
759
|
|
|
{ |
|
760
|
|
|
$db = $this->getConnection(); |
|
761
|
|
|
|
|
762
|
|
|
$command = $db->createCommand()->noCache(); |
|
763
|
|
|
|
|
764
|
|
|
$this->assertSame(-1, Assert::getInaccessibleProperty($command, 'queryCacheDuration')); |
|
765
|
|
|
$this->assertInstanceOf(CommandInterface::class, $command); |
|
766
|
|
|
} |
|
767
|
|
|
|
|
768
|
|
|
public function testQuery(): void |
|
769
|
|
|
{ |
|
770
|
|
|
$db = $this->getConnectionWithData(); |
|
771
|
|
|
|
|
772
|
|
|
$command = $db->createCommand( |
|
773
|
|
|
<<<SQL |
|
774
|
|
|
SELECT * FROM {{customer}} WHERE id=:id |
|
775
|
|
|
SQL, |
|
776
|
|
|
[ |
|
777
|
|
|
':id' => 1, |
|
778
|
|
|
] |
|
779
|
|
|
); |
|
780
|
|
|
|
|
781
|
|
|
$this->expectException(NotsupportedException::class); |
|
782
|
|
|
$this->expectExceptionMessage( |
|
783
|
|
|
'Yiisoft\Db\Tests\Support\Stubs\Command does not support internalExecute() by core-db.' |
|
784
|
|
|
); |
|
785
|
|
|
|
|
786
|
|
|
$command->query(); |
|
787
|
|
|
} |
|
788
|
|
|
|
|
789
|
|
|
public function testQueryAll(): void |
|
790
|
|
|
{ |
|
791
|
|
|
$db = $this->getConnectionWithData(); |
|
792
|
|
|
|
|
793
|
|
|
$command = $db->createCommand( |
|
794
|
|
|
<<<SQL |
|
795
|
|
|
SELECT * FROM {{customer}} WHERE id=:id |
|
796
|
|
|
SQL, |
|
797
|
|
|
[ |
|
798
|
|
|
':id' => 1, |
|
799
|
|
|
] |
|
800
|
|
|
); |
|
801
|
|
|
|
|
802
|
|
|
$this->expectException(NotsupportedException::class); |
|
803
|
|
|
$this->expectExceptionMessage( |
|
804
|
|
|
'Yiisoft\Db\Tests\Support\Stubs\Command does not support internalExecute() by core-db.' |
|
805
|
|
|
); |
|
806
|
|
|
|
|
807
|
|
|
$command->queryAll(); |
|
808
|
|
|
} |
|
809
|
|
|
|
|
810
|
|
|
public function testPrepareCancel(): void |
|
811
|
|
|
{ |
|
812
|
|
|
$db = $this->getConnectionWithData(); |
|
813
|
|
|
|
|
814
|
|
|
$command = $db->createCommand( |
|
815
|
|
|
<<<SQL |
|
816
|
|
|
SELECT * FROM {{customer}} |
|
817
|
|
|
SQL |
|
818
|
|
|
); |
|
819
|
|
|
|
|
820
|
|
|
$this->assertNull($command->getPdoStatement()); |
|
821
|
|
|
|
|
822
|
|
|
$command->prepare(); |
|
823
|
|
|
|
|
824
|
|
|
$this->assertNotNull($command->getPdoStatement()); |
|
825
|
|
|
|
|
826
|
|
|
$command->cancel(); |
|
827
|
|
|
|
|
828
|
|
|
$this->assertNull($command->getPdoStatement()); |
|
|
|
|
|
|
829
|
|
|
} |
|
830
|
|
|
|
|
831
|
|
|
public function testRenameColumn(): void |
|
832
|
|
|
{ |
|
833
|
|
|
$db = $this->getConnection(); |
|
834
|
|
|
|
|
835
|
|
|
$sql = $db->createCommand()->renameColumn('table', 'oldname', 'newname')->getSql(); |
|
836
|
|
|
|
|
837
|
|
|
$this->assertSame( |
|
838
|
|
|
<<<SQL |
|
839
|
|
|
ALTER TABLE `table` RENAME COLUMN `oldname` TO `newname` |
|
840
|
|
|
SQL, |
|
841
|
|
|
$sql, |
|
842
|
|
|
); |
|
843
|
|
|
} |
|
844
|
|
|
|
|
845
|
|
|
public function testRenameTable(): void |
|
846
|
|
|
{ |
|
847
|
|
|
$db = $this->getConnection(); |
|
848
|
|
|
|
|
849
|
|
|
$sql = $db->createCommand()->renameTable('table', 'newname')->getSql(); |
|
850
|
|
|
|
|
851
|
|
|
$this->assertSame( |
|
852
|
|
|
<<<SQL |
|
853
|
|
|
RENAME TABLE `table` TO `newname` |
|
854
|
|
|
SQL, |
|
855
|
|
|
$sql, |
|
856
|
|
|
); |
|
857
|
|
|
} |
|
858
|
|
|
|
|
859
|
|
|
public function testResetSequence(): void |
|
860
|
|
|
{ |
|
861
|
|
|
$db = $this->getConnection(); |
|
862
|
|
|
|
|
863
|
|
|
$this->expectException(NotSupportedException::class); |
|
864
|
|
|
$this->expectExceptionMessage( |
|
865
|
|
|
'Yiisoft\Db\Tests\Support\Stubs\DMLQueryBuilder does not support resetting sequence.' |
|
866
|
|
|
); |
|
867
|
|
|
|
|
868
|
|
|
$db->createCommand()->resetSequence('table', 5)->getSql(); |
|
869
|
|
|
} |
|
870
|
|
|
|
|
871
|
|
|
public function testSetRawSql(): void |
|
872
|
|
|
{ |
|
873
|
|
|
$db = $this->getConnection(); |
|
874
|
|
|
|
|
875
|
|
|
$command = $db->createCommand(); |
|
876
|
|
|
$command->setRawSql( |
|
877
|
|
|
<<<SQL |
|
878
|
|
|
SELECT 123 |
|
879
|
|
|
SQL |
|
880
|
|
|
); |
|
881
|
|
|
|
|
882
|
|
|
$this->assertSame('SELECT 123', $command->getRawSql()); |
|
883
|
|
|
} |
|
884
|
|
|
|
|
885
|
|
|
public function testSetRetryHandler(): void |
|
886
|
|
|
{ |
|
887
|
|
|
$db = $this->getConnection(); |
|
888
|
|
|
|
|
889
|
|
|
$command = $db->createCommand(); |
|
890
|
|
|
|
|
891
|
|
|
$handler = static fn (): bool => true; |
|
892
|
|
|
|
|
893
|
|
|
Assert::invokeMethod($command, 'setRetryHandler', [$handler]); |
|
894
|
|
|
|
|
895
|
|
|
$this->assertSame($handler, Assert::getInaccessibleProperty($command, 'retryHandler')); |
|
896
|
|
|
} |
|
897
|
|
|
|
|
898
|
|
|
public function testTruncateTable(): void |
|
899
|
|
|
{ |
|
900
|
|
|
$db = $this->getConnectionWithData(); |
|
901
|
|
|
|
|
902
|
|
|
$command = $db->createCommand(); |
|
903
|
|
|
$sql = $command->truncateTable('table')->getSql(); |
|
904
|
|
|
|
|
905
|
|
|
$this->assertSame( |
|
906
|
|
|
<<<SQL |
|
907
|
|
|
TRUNCATE TABLE `table` |
|
908
|
|
|
SQL, |
|
909
|
|
|
$sql, |
|
910
|
|
|
); |
|
911
|
|
|
} |
|
912
|
|
|
|
|
913
|
|
|
/** |
|
914
|
|
|
* @dataProvider \Yiisoft\Db\Tests\Provider\CommandProvider::upsert() |
|
915
|
|
|
* |
|
916
|
|
|
* @throws Exception |
|
917
|
|
|
* @throws InvalidConfigException |
|
918
|
|
|
* @throws NotSupportedException |
|
919
|
|
|
*/ |
|
920
|
|
|
public function testUpsert(array $firstData, array $secondData): void |
|
|
|
|
|
|
921
|
|
|
{ |
|
922
|
|
|
$db = $this->getConnectionWithData(); |
|
923
|
|
|
|
|
924
|
|
|
$command = $db->createCommand(); |
|
925
|
|
|
|
|
926
|
|
|
$this->expectException(NotSupportedException::class); |
|
927
|
|
|
$this->expectExceptionMessage( |
|
928
|
|
|
'Yiisoft\Db\Tests\Support\Stubs\DMLQueryBuilder does not support upsert.' |
|
929
|
|
|
); |
|
930
|
|
|
|
|
931
|
|
|
$command->upsert('table', $firstData)->getSql(); |
|
932
|
|
|
} |
|
933
|
|
|
|
|
934
|
|
|
protected function performAndCompareUpsertResult(ConnectionPDOInterface $db, array $data): void |
|
935
|
|
|
{ |
|
936
|
|
|
$params = $data['params']; |
|
937
|
|
|
$expected = $data['expected'] ?? $params[1]; |
|
938
|
|
|
|
|
939
|
|
|
$command = $db->createCommand(); |
|
940
|
|
|
call_user_func_array([$command, 'upsert'], $params); |
|
941
|
|
|
$command->execute(); |
|
942
|
|
|
|
|
943
|
|
|
$actual = $this->getQuery($db) |
|
944
|
|
|
->select(['email', 'address' => new Expression($this->upsertTestCharCast), 'status']) |
|
945
|
|
|
->from('T_upsert') |
|
946
|
|
|
->one(); |
|
947
|
|
|
$this->assertEquals($expected, $actual, $this->upsertTestCharCast); |
|
948
|
|
|
} |
|
949
|
|
|
} |
|
950
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.