Passed
Branch main (45b422)
by Andreas
01:40
created

PDOStatementTest::testFetchBound()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
c 0
b 0
f 0
rs 9.44
cc 3
nc 4
nop 0
1
<?php
2
/**
3
 * Licensed to CRATE Technology GmbH("Crate") under one or more contributor
4
 * license agreements.  See the NOTICE file distributed with this work for
5
 * additional information regarding copyright ownership.  Crate licenses
6
 * this file to you under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.  You may
8
 * obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
15
 * License for the specific language governing permissions and limitations
16
 * under the License.
17
 *
18
 * However, if you have executed another commercial license agreement
19
 * with Crate these terms will supersede the license and you may use the
20
 * software solely pursuant to the terms of the relevant commercial agreement.
21
 */
22
23
namespace CrateIntegrationTest\PDO;
24
25
use Crate\PDO\PDO;
26
use Crate\Stdlib\CrateConst;
27
28
/**
29
 * Class PDOStatementTest
30
 *
31
 * @coversNothing
32
 *
33
 * @group integration
34
 */
35
class PDOStatementTest extends AbstractIntegrationTest
36
{
37
    public function testFetchColumn()
38
    {
39
        $this->insertRows(5);
40
41
        $statement = $this->pdo->prepare('SELECT id FROM test_table');
42
        $result = [];
43
44
45
        while ($columnValue = $statement->fetchColumn()) {
46
            $result[] = $columnValue;
47
        }
48
49
        $this->assertEquals([1, 2, 3, 4, 5], $result);
50
    }
51
52
    public function testFetchBound()
53
    {
54
        $expected = [
55
            ['id' => 1, 'name' => 'first'],
56
            ['id' => 2, 'name' => 'second'],
57
            ['id' => 3, 'name' => 'third'],
58
        ];
59
60
        foreach ($expected as $row) {
61
            $this->insertRow($row['id'], $row['name']);
62
        }
63
64
        $id    = null;
65
        $name  = null;
66
        $index = 0;
67
68
        $statement = $this->pdo->prepare('SELECT id, name FROM test_table');
69
        $statement->bindColumn('id', $id);
70
        $statement->bindColumn('name', $name);
71
72
        while ($row = $statement->fetch(PDO::FETCH_BOUND)) {
73
74
            $this->assertEquals($expected[$index]['id'], $id);
75
            $this->assertEquals($expected[$index]['name'], $name);
76
77
            $index++;
78
        }
79
80
        $this->assertEquals(3, $index);
81
    }
82
83
    public function testFetchAllWithNumStyle()
84
    {
85
        $expected = [
86
            [1, 'first'],
87
            [2, 'second'],
88
            [3, 'third'],
89
        ];
90
91
        foreach ($expected as $row) {
92
            $this->insertRow($row[0], $row[1]);
93
        }
94
95
        $statement = $this->pdo->prepare('SELECT id, name FROM test_table');
96
        $statement->execute();
97
98
        $this->assertEquals($expected, $statement->fetchAll(PDO::FETCH_NUM));
99
    }
100
101
    public function testFetchAllWithAssocStyle()
102
    {
103
        $expected = [
104
            ['id' => 1, 'name' => 'first'],
105
            ['id' => 2, 'name' => 'second'],
106
            ['id' => 3, 'name' => 'third'],
107
        ];
108
109
        foreach ($expected as $row) {
110
            $this->insertRow($row['id'], $row['name']);
111
        }
112
113
        $statement = $this->pdo->prepare('SELECT id, name FROM test_table');
114
        $statement->execute();
115
116
        $this->assertEquals($expected, $statement->fetchAll(PDO::FETCH_ASSOC));
117
    }
118
119
    public function testFetchAllWithObjectStyle()
120
    {
121
        $expected = [
122
            (object)['id' => 1, 'name' => 'first'],
123
            (object)['id' => 2, 'name' => 'second'],
124
            (object)['id' => 3, 'name' => 'third'],
125
        ];
126
127
        foreach ($expected as $row) {
128
            $this->insertRow($row->id, $row->name);
129
        }
130
131
        $statement = $this->pdo->prepare('SELECT id, name FROM test_table');
132
        $statement->execute();
133
134
        $this->assertEquals($expected, $statement->fetchAll(PDO::FETCH_OBJ));
135
    }
136
137
    public function testFetchSameColumnTwiceWithAssocStyle()
138
    {
139
        $this->insertRows(3);
140
        $expected = [
141
            ['id' => 1, 'id' => 1],
142
            ['id' => 2, 'id' => 2],
143
            ['id' => 3, 'id' => 3],
144
        ];
145
146
        $statement = $this->pdo->prepare('SELECT id, id FROM test_table');
147
        $statement->execute();
148
149
        $this->assertEquals($expected, $statement->fetchAll(PDO::FETCH_ASSOC));
150
    }
151
152
    public function testFetchAllWithBothStyle()
153
    {
154
        $expected = [
155
            [0 => 1, 'id' => 1, 1 => 'first', 'name' => 'first'],
156
            [0 => 2, 'id' => 2, 1 => 'second', 'name' => 'second'],
157
            [0 => 3, 'id' => 3, 1 => 'third', 'name' => 'third'],
158
        ];
159
160
        foreach ($expected as $row) {
161
            $this->insertRow($row['id'], $row['name']);
162
        }
163
164
        $statement = $this->pdo->prepare('SELECT id, name FROM test_table');
165
        $statement->execute();
166
167
        // In theory this should be assertSame, but implementing that would be incredibly slow
168
        $this->assertEquals($expected, $statement->fetchAll(PDO::FETCH_BOTH));
169
    }
170
171
    public function testFetchAllWithFuncStyle()
172
    {
173
        $expected = [
174
            ['id' => 1, 'name' => 'first'],
175
            ['id' => 2, 'name' => 'second'],
176
            ['id' => 3, 'name' => 'third'],
177
        ];
178
179
        foreach ($expected as $row) {
180
            $this->insertRow($row['id'], $row['name']);
181
        }
182
183
        $statement = $this->pdo->prepare('SELECT id, name FROM test_table');
184
        $statement->execute();
185
186
        $index    = 0;
187
        $callback = function ($id, $name) {
188
            return sprintf('%d:%s', $id, $name);
189
        };
190
191
        $resultSet = $statement->fetchAll(PDO::FETCH_FUNC, $callback);
192
193
        foreach ($resultSet as $result) {
194
            $this->assertEquals(sprintf('%d:%s', $expected[$index]['id'], $expected[$index]['name']), $result);
195
            $index++;
196
        }
197
198
        $this->assertEquals(count($expected), $index);
199
    }
200
201
    public function testBindParam()
202
    {
203
        $expected = [
204
            ['id' => 1, 'name' => 'first'],
205
            ['id' => 2, 'name' => 'second'],
206
            ['id' => 3, 'name' => 'third'],
207
        ];
208
209
        foreach ($expected as $row) {
210
            $this->insertRow($row['id'], $row['name']);
211
        }
212
213
        $name = 'second';
214
        $statement = $this->pdo->prepare('SELECT * FROM test_table where name = ?');
215
        $statement->bindParam(1, $name);
216
        $statement->execute();
217
        $this->assertEquals(1, $statement->rowCount());
218
219
        $resultSet = $statement->fetchAll(PDO::FETCH_NAMED);
220
        $this->assertEquals(2, $resultSet[0]['id']);
221
        $this->assertEquals($name, $resultSet[0]['name']);
222
    }
223
224
    public function testBindNamedParam()
225
    {
226
        $expected = [
227
            ['id' => 1, 'name' => 'first'],
228
            ['id' => 2, 'name' => 'second'],
229
            ['id' => 3, 'name' => 'third'],
230
        ];
231
232
        foreach ($expected as $row) {
233
            $this->insertRow($row['id'], $row['name']);
234
        }
235
236
        $name = 'second';
237
        $id = 2;
238
        $sql = 'SELECT * FROM test_table where name = :name and id = :id';
239
240
        $statement = $this->pdo->prepare($sql);
241
        $statement->bindParam('name', $name);
242
        $statement->bindParam('id', $id);
243
        $statement->execute();
244
        $this->assertEquals(1, $statement->rowCount());
245
246
        $resultSet = $statement->fetchAll(PDO::FETCH_NAMED);
247
        $this->assertEquals(2, $resultSet[0]['id']);
248
        $this->assertEquals($name, $resultSet[0]['name']);
249
250
        $statement = $this->pdo->prepare($sql);
251
        $statement->bindParam(':name', $name);
252
        $statement->bindParam(':id', $id);
253
        $statement->execute();
254
        $this->assertEquals(1, $statement->rowCount());
255
256
        $resultSet = $statement->fetchAll(PDO::FETCH_NAMED);
257
        $this->assertEquals(2, $resultSet[0]['id']);
258
        $this->assertEquals($name, $resultSet[0]['name']);
259
    }
260
261
    public function testBindNamedParamUnordered()
262
    {
263
        $this->insertRows(2);
264
265
        $statement = $this->pdo->prepare('UPDATE test_table SET name = concat(name, :name) where id = :id');
266
        $statement->bindValue(':id', 1);
267
        $statement->bindValue(':name', '_abc');
268
        $statement->execute();
269
270
        $this->pdo->exec('REFRESH TABLE test_table');
271
272
        $statement = $this->pdo->prepare('SELECT name FROM test_table WHERE ID=1');
273
        $resultSet = $statement->fetch();
274
        $this->assertEquals('hello world_abc', $resultSet[0]);
275
    }
276
277
    public function testBindNamedParamMultiple()
278
    {
279
        $this->pdo->exec("INSERT INTO test_table (id, name, int_type) VALUES (1, 'hello', 1), (2, 'world', 1), (3, 'hello', 2), (4, 'world', 3)");
280
        $this->pdo->exec("REFRESH TABLE test_table");
281
282
        $statement = $this->pdo->prepare('update test_table set name = concat(name, :name) where int_type = :int_type and name != :name');
283
        $statement->bindValue(':int_type', 1, PDO::PARAM_INT);
284
        $statement->bindValue(':name', 'world', PDO::PARAM_STR);
285
        $statement->execute();
286
287
        $this->pdo->exec("REFRESH TABLE test_table");
288
289
        $statement = $this->pdo->prepare("SELECT id, name, int_type FROM test_table WHERE id=1");
290
        $resultSet = $statement->fetch();
291
        $this->assertEquals(1, $resultSet[0]);
292
        $this->assertEquals('helloworld', $resultSet[1]);
293
        $this->assertEquals(1, $resultSet[2]);
294
    }
295
296
    public function testBindValue()
297
    {
298
        $expected = [
299
            ['id' => 1, 'name' => 'first'],
300
            ['id' => 2, 'name' => 'second'],
301
            ['id' => 3, 'name' => 'third'],
302
        ];
303
304
        foreach ($expected as $row) {
305
            $this->insertRow($row['id'], $row['name']);
306
        }
307
308
        $statement = $this->pdo->prepare('SELECT * FROM test_table where name = ?');
309
        $statement->bindValue(1, 'second');
310
        $statement->execute();
311
        $this->assertEquals(1, $statement->rowCount());
312
313
        $resultSet = $statement->fetchAll(PDO::FETCH_NAMED);
314
        $this->assertEquals(2, $resultSet[0]['id']);
315
        $this->assertEquals('second', $resultSet[0]['name']);
316
    }
317
318
    public function testArrayValue()
319
    {
320
        $statement = $this->pdo->prepare('INSERT INTO test_table (id, array_type, object_type) VALUES(?, ?, ?)');
321
        $statement->bindValue(1, 1, PDO::PARAM_INT);
322
        $statement->bindValue(2, [1, 2], PDO::PARAM_ARRAY);
323
        $statement->bindValue(3, ["foo" => "bar"], PDO::PARAM_OBJECT);
324
        $statement->execute();
325
        $this->assertEquals(1, $statement->rowCount());
326
327
        $this->pdo->exec('REFRESH TABLE test_table');
328
329
        $statement = $this->pdo->prepare('SELECT id, array_type, object_type FROM test_table');
330
        $resultSet = $statement->fetchAll(PDO::FETCH_ASSOC);
331
        $this->assertEquals(1, $resultSet[0]['id']);
332
        $this->assertEquals([1, 2], $resultSet[0]['array_type']);
333
        $this->assertEquals(["foo" => "bar"], $resultSet[0]['object_type']);
334
    }
335
336
    public function testInsertNull()
337
    {
338
        $statement = $this->pdo->prepare('INSERT INTO test_table (id, name) VALUES (6, NULL)');
339
        $statement->execute();
340
341
        $this->pdo->exec('REFRESH TABLE test_table');
342
343
        $statement = $this->pdo->prepare('SELECT * FROM test_table');
344
        $resultSet = $statement->fetchAll(PDO::FETCH_NAMED);
345
346
        $this->assertEquals(6, $resultSet[0]['id']);
347
        $this->assertEquals(NULL, $resultSet[0]['name']);
348
349
    }
350
351
    public function testInvalidInsert()
352
    {
353
        $statement = $this->pdo->prepare("INSERT INTO test_table (name) VALUES ('hello')");
354
        $statement->execute();
355
356
        $this->assertEquals(4000, $statement->errorCode());
357
358
        list ($ansiSQLError, $driverError, $driverMessage) = $statement->errorInfo();
359
360
        $this->assertEquals(42000, $ansiSQLError);
361
        $this->assertEquals(CrateConst::ERR_INVALID_SQL, $driverError);
362
        $this->assertStringContainsString('SQLParseException[Column `id` is required but is missing from the insert statement]', $driverMessage);
363
    }
364
365
    public function testNullParamBinding()
366
    {
367
        $statement = $this->pdo->prepare('INSERT INTO test_table (id, name) VALUES (6, ?)');
368
        $statement->bindValue(1, NULL, PDO::PARAM_STR);
369
        $statement->execute();
370
371
        $this->pdo->exec('REFRESH TABLE test_table');
372
373
        $statement = $this->pdo->prepare('SELECT * FROM test_table');
374
        $resultSet = $statement->fetchAll(PDO::FETCH_NAMED);
375
376
        $this->assertEquals(6, $resultSet[0]['id']);
377
        $this->assertEquals(NULL, $resultSet[0]['name']);
378
379
    }
380
381
    public function testInvalidInsertWithNullParamBinding()
382
    {
383
384
        $value = NULL;
385
386
        $statement = $this->pdo->prepare('INSERT INTO test_table (name) VALUES (?)');
387
        $statement->bindParam(1, $value);
388
        $statement->execute();
389
390
        $this->assertEquals(4000, $statement->errorCode());
391
392
        list ($ansiSQLError, $driverError, $driverMessage) = $statement->errorInfo();
393
394
        $this->assertEquals(42000, $ansiSQLError);
395
        $this->assertEquals(CrateConst::ERR_INVALID_SQL, $driverError);
396
        $this->assertStringContainsString('SQLParseException[Column `id` is required but is missing from the insert statement]', $driverMessage);
397
398
    }
399
400
}
401