Passed
Pull Request — master (#380)
by Wilmer
04:47 queued 01:51
created

CommonConnectionTest::testExecute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 15
nc 1
nop 0
dl 0
loc 24
rs 9.7666
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Tests\Common;
6
7
use Psr\Log\NullLogger;
8
use Yiisoft\Db\Connection\ConnectionInterface;
9
use Yiisoft\Db\Exception\Exception;
10
use Yiisoft\Db\Tests\AbstractConnectionTest;
11
use Yiisoft\Db\Tests\Support\Assert;
12
use Yiisoft\Db\Tests\Support\TestTrait;
13
14
/**
15
 * @group mssql
16
 * @group mysql
17
 * @group pgsql
18
 * @group oracle
19
 * @group sqlite
20
 */
21
abstract class CommonConnectionTest extends AbstractConnectionTest
22
{
23
    use TestTrait;
24
25
    public function testExecute(): void
26
    {
27
        $db = $this->getConnectionWithData();
28
29
        $sql = <<<SQL
30
        INSERT INTO {{customer}}([[email]], [[name]], [[address]]) VALUES ('[email protected]', 'user4', 'address4')
31
        SQL;
32
        $command = $db->createCommand($sql);
33
34
        $this->assertSame(1, $command->execute());
35
36
        $sql = <<<SQL
37
        SELECT COUNT(*) FROM {{customer}} WHERE [[name]] = 'user4'
38
        SQL;
39
        $command = $db->createCommand($sql);
40
41
        $this->assertEquals(1, $command->queryScalar());
42
43
        $command = $db->createCommand('bad SQL');
44
45
        $this->expectException(Exception::class);
46
        $this->expectExceptionMessage('SQLSTATE[HY000]: General error: 1 near "bad": syntax error');
47
48
        $command->execute();
49
    }
50
51
    public function testExceptionContainsRawQuery(): void
52
    {
53
        $db = $this->getConnection();
54
55
        /* profiling and logging */
56
        $db->createCommand()->createTable('qlog1', ['id' => 'pk'])->execute();
57
        $db->setEmulatePrepare(true);
58
        $logger = $this->getLogger();
59
        $profiler = $this->getProfiler();
60
        $db->setLogger($logger);
61
        $db->setProfiler($profiler);
62
63
        $this->runExceptionTest($db);
64
65
        /* profiling only */
66
        $db->setLogger(new NullLogger());
67
        $db->setProfiler($profiler);
68
69
        $this->runExceptionTest($db);
70
71
        /* logging only */
72
        $db->setLogger($logger);
73
        $db->notProfiler();
74
75
        $this->runExceptionTest($db);
76
77
        /* disabled */
78
        $db->setLogger(new NullLogger());
79
        $db->notProfiler();
80
81
        $this->runExceptionTest($db);
82
    }
83
84
    public function testGetTableSchema(): void
85
    {
86
        $db = $this->getConnection();
87
88
        $this->assertNull($db->getTableSchema('non_existing_table'));
89
    }
90
91
    public function testLoggerProfiler(): void
92
    {
93
        $db = $this->getConnection();
94
95
        foreach (['qlog1', 'qlog2', 'qlog3', 'qlog4'] as $table) {
96
            if ($db->getTableSchema($table, true) !== null) {
97
                $db->createCommand()->dropTable($table)->execute();
98
            }
99
        }
100
101
        $logger = $this->getLogger();
102
        $profiler = $this->getProfiler();
103
        /* profiling and logging */
104
        $db->setLogger($logger);
105
        $db->setProfiler($profiler);
106
107
        $this->assertNotNull($logger);
108
        $this->assertNotNull($profiler);
109
110
        $logger->flush();
111
        $profiler->flush();
112
        $db->createCommand()->createTable('qlog1', ['id' => 'pk'])->execute();
113
114
        $this->assertCount(1, Assert::getInaccessibleProperty($logger, 'messages'));
115
        $this->assertCount(1, Assert::getInaccessibleProperty($profiler, 'messages'));
116
        $this->assertNotNull($db->getTableSchema('qlog1', true));
117
118
        $logger->flush();
119
        $profiler->flush();
120
        $db->createCommand('SELECT * FROM {{qlog1}}')->queryAll();
121
122
        $this->assertCount(1, Assert::getInaccessibleProperty($logger, 'messages'));
123
        $this->assertCount(1, Assert::getInaccessibleProperty($profiler, 'messages'));
124
125
        /* profiling only */
126
        $db->setLogger(new NullLogger());
127
        $db->setProfiler($profiler);
128
        $logger->flush();
129
        $profiler->flush();
130
        $db->createCommand()->createTable('qlog2', ['id' => 'pk'])->execute();
131
132
        $this->assertCount(0, Assert::getInaccessibleProperty($logger, 'messages'));
133
        $this->assertCount(1, Assert::getInaccessibleProperty($profiler, 'messages'));
134
        $this->assertNotNull($db->getTableSchema('qlog2', true));
135
136
        $logger->flush();
137
        $profiler->flush();
138
        $db->createCommand('SELECT * FROM {{qlog2}}')->queryAll();
139
140
        $this->assertCount(0, Assert::getInaccessibleProperty($logger, 'messages'));
141
        $this->assertCount(1, Assert::getInaccessibleProperty($profiler, 'messages'));
142
143
        /* logging only */
144
        $db->setLogger($logger);
145
        $db->notProfiler();
146
        $logger->flush();
147
        $profiler->flush();
148
        $db->createCommand()->createTable('qlog3', ['id' => 'pk'])->execute();
149
150
        $this->assertCount(1, Assert::getInaccessibleProperty($logger, 'messages'));
151
        $this->assertCount(0, Assert::getInaccessibleProperty($profiler, 'messages'));
152
        $this->assertNotNull($db->getTableSchema('qlog3', true));
153
154
        $logger->flush();
155
        $profiler->flush();
156
        $db->createCommand('SELECT * FROM {{qlog3}}')->queryAll();
157
158
        $this->assertCount(1, Assert::getInaccessibleProperty($logger, 'messages'));
159
        $this->assertCount(0, Assert::getInaccessibleProperty($profiler, 'messages'));
160
161
        /* disabled */
162
        $db->setLogger(new NullLogger());
163
        $db->notProfiler();
164
        $logger->flush();
165
        $profiler->flush();
166
        $db->createCommand()->createTable('qlog4', ['id' => 'pk'])->execute();
167
168
        $this->assertNotNull($db->getTableSchema('qlog4', true));
169
        $this->assertCount(0, Assert::getInaccessibleProperty($logger, 'messages'));
170
        $this->assertCount(0, Assert::getInaccessibleProperty($profiler, 'messages'));
171
172
        $db->createCommand('SELECT * FROM {{qlog4}}')->queryAll();
173
174
        $this->assertCount(0, Assert::getInaccessibleProperty($logger, 'messages'));
175
        $this->assertCount(0, Assert::getInaccessibleProperty($profiler, 'messages'));
176
    }
177
178
    public function testNotProfiler(): void
179
    {
180
        $db = $this->getConnection();
181
182
        if ($db->getTableSchema('notProfiler1', true) !== null) {
183
            $db->createCommand()->dropTable('notProfiler1')->execute();
184
        }
185
186
        if ($db->getTableSchema('notProfiler2', true) !== null) {
187
            $db->createCommand()->dropTable('notProfiler2')->execute();
188
        }
189
190
        $profiler = $this->getProfiler();
191
        $db->notProfiler();
192
        $profiler->flush();
193
        $db->createCommand()->createTable('notProfiler1', ['id' => 'pk'])->execute();
194
195
        $this->assertCount(0, Assert::getInaccessibleProperty($profiler, 'messages'));
196
197
        $db->setProfiler($profiler);
198
        $db->createCommand()->createTable('notProfiler2', ['id' => 'pk'])->execute();
199
200
        $this->assertCount(1, Assert::getInaccessibleProperty($profiler, 'messages'));
201
    }
202
203
    public function testPartialRollbackTransactionsWithSavePoints(): void
204
    {
205
        $db = $this->getConnectionWithData();
206
207
        $db->open();
208
        $transaction = $db->beginTransaction();
209
210
        $this->assertSame(1, $transaction->getLevel());
211
212
        $db->createCommand()->insert('profile', ['description' => 'test transaction1'])->execute();
213
        $transaction->begin();
214
215
        $this->assertSame(2, $transaction->getLevel());
216
217
        $db->createCommand()->insert('profile', ['description' => 'test transaction2'])->execute();
218
        $transaction->rollBack();
219
220
        $this->assertSame(1, $transaction->getLevel());
221
        $this->assertTrue($transaction->isActive());
222
223
        $db->createCommand()->insert('profile', ['description' => 'test transaction3'])->execute();
224
        $transaction->commit();
225
226
        $this->assertSame(0, $transaction->getLevel());
227
        $this->assertFalse($transaction->isActive());
228
        $this->assertNull($db->getTransaction());
229
        $this->assertEquals(
230
            1,
231
            $db->createCommand(
232
                <<<SQL
233
                SELECT COUNT(*) FROM {{profile}} WHERE [[description]] = 'test transaction1'
234
                SQL
235
            )->queryScalar(),
236
        );
237
        $this->assertEquals(
238
            0,
239
            $db->createCommand(
240
                <<<SQL
241
                SELECT COUNT(*) FROM {{profile}} WHERE [[description]] = 'test transaction2'
242
                SQL
243
            )->queryScalar()
244
        );
245
        $this->assertEquals(
246
            1,
247
            $db->createCommand(
248
                <<<SQL
249
                SELECT COUNT(*) FROM {{profile}} WHERE [[description]] = 'test transaction3'
250
                SQL
251
            )->queryScalar(),
252
        );
253
    }
254
255
    public function testRollbackTransactionsWithSavePoints(): void
256
    {
257
        $db = $this->getConnectionWithData();
258
259
        $db->open();
260
        $transaction = $db->beginTransaction();
261
262
        $this->assertSame(1, $transaction->getLevel());
263
264
        $db->createCommand()->insert('profile', ['description' => 'test transaction'])->execute();
265
        $transaction->begin();
266
267
        $this->assertSame(2, $transaction->getLevel());
268
269
        $db->createCommand()->insert('profile', ['description' => 'test transaction'])->execute();
270
        $transaction->rollBack();
271
272
        $this->assertSame(1, $transaction->getLevel());
273
        $this->assertTrue($transaction->isActive());
274
275
        $db->createCommand()->insert('profile', ['description' => 'test transaction'])->execute();
276
        $transaction->rollBack();
277
278
        $this->assertSame(0, $transaction->getLevel());
279
        $this->assertFalse($transaction->isActive());
280
        $this->assertNull($db->getTransaction());
281
        $this->assertEquals(
282
            0,
283
            $db->createCommand(
284
                <<<SQL
285
                SELECT COUNT(*) FROM {{profile}} WHERE [[description]] = 'test transaction'
286
                SQL
287
            )->queryScalar(),
288
        );
289
    }
290
291
    public function testTransaction(): void
292
    {
293
        $db = $this->getConnectionWithData();
294
295
        $db->setLogger($this->getLogger());
296
297
        $this->assertNull($db->getTransaction());
298
299
        $transaction = $db->beginTransaction();
300
301
        $this->assertNotNull($db->getTransaction());
302
        $this->assertTrue($transaction->isActive());
303
304
        $db->createCommand()->insert('profile', ['description' => 'test transaction'])->execute();
305
        $transaction->rollBack();
306
307
        $this->assertFalse($transaction->isActive());
308
        $this->assertNull($db->getTransaction());
309
        $this->assertEquals(
310
            0,
311
            $db->createCommand(
312
                <<<SQL
313
                SELECT COUNT(*) FROM {{profile}} WHERE [[description]] = 'test transaction'
314
                SQL
315
            )->queryScalar()
316
        );
317
318
        $transaction = $db->beginTransaction();
319
        $db->createCommand()->insert('profile', ['description' => 'test transaction'])->execute();
320
        $transaction->commit();
321
322
        $this->assertFalse($transaction->isActive());
323
        $this->assertNull($db->getTransaction());
324
        $this->assertEquals(
325
            1,
326
            $db->createCommand(
327
                <<<SQL
328
                SELECT COUNT(*) FROM {{profile}} WHERE [[description]] = 'test transaction'
329
                SQL
330
            )->queryScalar(),
331
        );
332
    }
333
334
    public function testTransactionShortcutCorrect(): void
335
    {
336
        $db = $this->getConnectionWithData();
337
338
        $result = $db->transaction(static function () use ($db) {
339
            $db->createCommand()->insert('profile', ['description' => 'test transaction shortcut'])->execute();
340
            return true;
341
        });
342
343
        $this->assertTrue($result, 'transaction shortcut valid value should be returned from callback');
344
345
        $profilesCount = $db->createCommand(
346
            "SELECT COUNT(*) FROM {{profile}} WHERE [[description]] = 'test transaction shortcut'"
347
        )->queryScalar();
348
349
        $this->assertEquals(1, $profilesCount, 'profile should be inserted in transaction shortcut');
350
    }
351
352
    private function runExceptionTest(ConnectionInterface $db): void
353
    {
354
        $thrown = false;
355
356
        try {
357
            $db->createCommand(
358
                <<<SQL
359
                INSERT INTO qlog1(a) VALUES(:a)
360
                SQL,
361
                [':a' => 1]
362
            )->execute();
363
        } catch (Exception $e) {
364
            $this->assertStringContainsString(
365
                <<<SQL
366
                INSERT INTO qlog1(a) VALUES(:a)
367
                SQL,
368
                $e->getMessage(),
369
                'Exceptions message should contain raw SQL query: ' . $e
370
            );
371
372
            $thrown = true;
373
        }
374
375
        $this->assertTrue($thrown, 'An exception should have been thrown by the command.');
376
377
        $thrown = false;
378
379
        try {
380
            $db->createCommand(
381
                <<<SQL
382
                SELECT * FROM qlog1 WHERE id=:a ORDER BY nonexistingcolumn
383
                SQL,
384
                [':a' => 1]
385
            )->queryAll();
386
        } catch (Exception $e) {
387
            $this->assertStringContainsString(
388
                <<<SQL
389
                SELECT * FROM qlog1 WHERE id=:a ORDER BY nonexistingcolumn
390
                SQL,
391
                $e->getMessage(),
392
                'Exceptions message should contain raw SQL query: ' . $e
393
            );
394
395
            $thrown = true;
396
        }
397
398
        $this->assertTrue($thrown, 'An exception should have been thrown by the command.');
399
    }
400
}
401