43451caf06e3aa6e812dd367cb3e79081250eda2
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Database / Query / BulkInsertTest.php
1 <?php
2 declare(strict_types=1);
3 namespace TYPO3\CMS\Core\Tests\Unit\Database\Query;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use TYPO3\CMS\Core\Database\Connection;
19 use TYPO3\CMS\Core\Database\Query\BulkInsertQuery;
20 use TYPO3\CMS\Core\Tests\Unit\Database\Mocks\MockPlatform;
21
22 class BulkInsertTest extends \TYPO3\Components\TestingFramework\Core\UnitTestCase
23 {
24 /**
25 * @var Connection
26 */
27 protected $connection;
28
29 /**
30 * @var \Doctrine\DBAL\Platforms\AbstractPlatform
31 */
32 protected $platform;
33
34 /**
35 * @var string
36 */
37 protected $testTable = 'testTable';
38
39 /**
40 * Create a new database connection mock object for every test.
41 *
42 * @return void
43 */
44 protected function setUp()
45 {
46 parent::setUp();
47
48 $this->connection = $this->createMock(Connection::class);
49
50 $this->connection->expects($this->any())
51 ->method('quoteIdentifier')
52 ->will($this->returnArgument(0));
53 $this->connection->expects($this->any())
54 ->method('getDatabasePlatform')
55 ->will($this->returnValue(new MockPlatform()));
56 }
57
58 /**
59 * @test
60 */
61 public function getSQLWithoutSpecifiedValuesThrowsException()
62 {
63 $this->expectException(\LogicException::class);
64 $this->expectExceptionMessage('You need to add at least one set of values before generating the SQL.');
65
66 $query = new BulkInsertQuery($this->connection, $this->testTable);
67
68 $query->getSQL();
69 }
70
71 /**
72 * @test
73 */
74 public function insertWithoutColumnAndTypeSpecification()
75 {
76 $query = new BulkInsertQuery($this->connection, $this->testTable);
77
78 $query->addValues([]);
79
80 $this->assertSame("INSERT INTO {$this->testTable} VALUES ()", (string)$query);
81 $this->assertSame([], $query->getParameters());
82 $this->assertSame([], $query->getParameterTypes());
83 }
84
85 public function insertWithoutColumnSpecification()
86 {
87 $query = new BulkInsertQuery($this->connection, $this->testTable);
88
89 $query->addValues([], [Connection::PARAM_BOOL]);
90
91 $this->assertSame("INSERT INTO {$this->testTable} VALUES ()", (string)$query);
92 $this->assertSame([], $query->getParameters());
93 $this->assertSame([], $query->getParameterTypes());
94 }
95
96 /**
97 * @test
98 */
99 public function singleInsertWithoutColumnSpecification()
100 {
101 $query = new BulkInsertQuery($this->connection, $this->testTable);
102
103 $query->addValues(['bar', 'baz', 'named' => 'bloo']);
104
105 $this->assertSame("INSERT INTO {$this->testTable} VALUES (?, ?, ?)", (string)$query);
106 $this->assertSame(['bar', 'baz', 'bloo'], $query->getParameters());
107 $this->assertSame([null, null, null], $query->getParameterTypes());
108
109 $query = new BulkInsertQuery($this->connection, $this->testTable);
110
111 $query->addValues(
112 ['bar', 'baz', 'named' => 'bloo'],
113 ['named' => Connection::PARAM_BOOL, null, Connection::PARAM_INT]
114 );
115
116 $this->assertSame("INSERT INTO {$this->testTable} VALUES (?, ?, ?)", (string)$query);
117 $this->assertSame(['bar', 'baz', 'bloo'], $query->getParameters());
118 $this->assertSame([null, Connection::PARAM_INT, Connection::PARAM_BOOL], $query->getParameterTypes());
119 }
120
121 /**
122 * @test
123 */
124 public function multiInsertWithoutColumnSpecification()
125 {
126 $query = new BulkInsertQuery($this->connection, $this->testTable);
127
128 $query->addValues([]);
129 $query->addValues(['bar', 'baz']);
130 $query->addValues(['bar', 'baz', 'bloo']);
131 $query->addValues(['bar', 'baz', 'named' => 'bloo']);
132
133 $this->assertSame("INSERT INTO {$this->testTable} VALUES (), (?, ?), (?, ?, ?), (?, ?, ?)", (string)$query);
134 $this->assertSame(['bar', 'baz', 'bar', 'baz', 'bloo', 'bar', 'baz', 'bloo'], $query->getParameters());
135 $this->assertSame([null, null, null, null, null, null, null, null], $query->getParameterTypes());
136
137 $query = new BulkInsertQuery($this->connection, $this->testTable);
138
139 $query->addValues([], [Connection::PARAM_INT]);
140 $query->addValues(['bar', 'baz'], [1 => Connection::PARAM_BOOL]);
141 $query->addValues(['bar', 'baz', 'bloo'], [Connection::PARAM_INT, null, Connection::PARAM_BOOL]);
142 $query->addValues(
143 ['bar', 'baz', 'named' => 'bloo'],
144 ['named' => Connection::PARAM_INT, null, Connection::PARAM_BOOL]
145 );
146
147 $this->assertSame("INSERT INTO {$this->testTable} VALUES (), (?, ?), (?, ?, ?), (?, ?, ?)", (string)$query);
148 $this->assertSame(['bar', 'baz', 'bar', 'baz', 'bloo', 'bar', 'baz', 'bloo'], $query->getParameters());
149 $this->assertSame(
150 [
151 null,
152 Connection::PARAM_BOOL,
153 Connection::PARAM_INT,
154 null,
155 Connection::PARAM_BOOL,
156 null,
157 Connection::PARAM_BOOL,
158 Connection::PARAM_INT
159 ],
160 $query->getParameterTypes()
161 );
162 }
163
164 /**
165 * @test
166 */
167 public function singleInsertWithColumnSpecificationAndPositionalTypeValues()
168 {
169 $query = new BulkInsertQuery($this->connection, $this->testTable, ['bar', 'baz']);
170
171 $query->addValues(['bar', 'baz']);
172
173 $this->assertSame("INSERT INTO {$this->testTable} (bar, baz) VALUES (?, ?)", (string)$query);
174 $this->assertSame(['bar', 'baz'], $query->getParameters());
175 $this->assertSame([null, null], $query->getParameterTypes());
176
177 $query = new BulkInsertQuery($this->connection, $this->testTable, ['bar', 'baz']);
178
179 $query->addValues(['bar', 'baz'], [1 => Connection::PARAM_BOOL]);
180
181 $this->assertSame("INSERT INTO {$this->testTable} (bar, baz) VALUES (?, ?)", (string)$query);
182 $this->assertSame(['bar', 'baz'], $query->getParameters());
183 $this->assertSame([null, Connection::PARAM_BOOL], $query->getParameterTypes());
184 }
185
186 /**
187 * @test
188 */
189 public function singleInsertWithColumnSpecificationAndNamedTypeValues()
190 {
191 $query = new BulkInsertQuery($this->connection, $this->testTable, ['bar', 'baz']);
192
193 $query->addValues(['baz' => 'baz', 'bar' => 'bar']);
194
195 $this->assertSame("INSERT INTO {$this->testTable} (bar, baz) VALUES (?, ?)", (string)$query);
196 $this->assertSame(['bar', 'baz'], $query->getParameters());
197 $this->assertSame([null, null], $query->getParameterTypes());
198
199 $query = new BulkInsertQuery($this->connection, $this->testTable, ['bar', 'baz']);
200
201 $query->addValues(['baz' => 'baz', 'bar' => 'bar'], [null, Connection::PARAM_INT]);
202
203 $this->assertSame("INSERT INTO {$this->testTable} (bar, baz) VALUES (?, ?)", (string)$query);
204 $this->assertSame(['bar', 'baz'], $query->getParameters());
205 $this->assertSame([null, Connection::PARAM_INT], $query->getParameterTypes());
206 }
207
208 /**
209 * @test
210 */
211 public function singleInsertWithColumnSpecificationAndMixedTypeValues()
212 {
213 $query = new BulkInsertQuery($this->connection, $this->testTable, ['bar', 'baz']);
214
215 $query->addValues([1 => 'baz', 'bar' => 'bar']);
216
217 $this->assertSame("INSERT INTO {$this->testTable} (bar, baz) VALUES (?, ?)", (string)$query);
218 $this->assertSame(['bar', 'baz'], $query->getParameters());
219 $this->assertSame([null, null], $query->getParameterTypes());
220
221 $query = new BulkInsertQuery($this->connection, $this->testTable, ['bar', 'baz']);
222
223 $query->addValues([1 => 'baz', 'bar' => 'bar'], [Connection::PARAM_INT, Connection::PARAM_BOOL]);
224
225 $this->assertSame("INSERT INTO {$this->testTable} (bar, baz) VALUES (?, ?)", (string)$query);
226 $this->assertSame(['bar', 'baz'], $query->getParameters());
227 $this->assertSame([Connection::PARAM_INT, Connection::PARAM_BOOL], $query->getParameterTypes());
228 }
229
230 /**
231 * @test
232 */
233 public function multiInsertWithColumnSpecification()
234 {
235 $query = new BulkInsertQuery($this->connection, $this->testTable, ['bar', 'baz']);
236
237 $query->addValues(['bar', 'baz']);
238 $query->addValues([1 => 'baz', 'bar' => 'bar']);
239 $query->addValues(['bar', 'baz' => 'baz']);
240 $query->addValues(['bar' => 'bar', 'baz' => 'baz']);
241
242 $this->assertSame(
243 "INSERT INTO {$this->testTable} (bar, baz) VALUES (?, ?), (?, ?), (?, ?), (?, ?)",
244 (string)$query
245 );
246 $this->assertSame(['bar', 'baz', 'bar', 'baz', 'bar', 'baz', 'bar', 'baz'], $query->getParameters());
247 $this->assertSame([null, null, null, null, null, null, null, null], $query->getParameterTypes());
248
249 $query = new BulkInsertQuery($this->connection, $this->testTable, ['bar', 'baz']);
250
251 $query->addValues(['bar', 'baz'], ['baz' => Connection::PARAM_BOOL, 'bar' => Connection::PARAM_INT]);
252 $query->addValues([1 => 'baz', 'bar' => 'bar'], [1 => Connection::PARAM_BOOL, 'bar' => Connection::PARAM_INT]);
253 $query->addValues(['bar', 'baz' => 'baz'], [null, null]);
254 $query->addValues(
255 ['bar' => 'bar', 'baz' => 'baz'],
256 ['bar' => Connection::PARAM_INT, 'baz' => Connection::PARAM_BOOL]
257 );
258
259 $this->assertSame(
260 "INSERT INTO {$this->testTable} (bar, baz) VALUES (?, ?), (?, ?), (?, ?), (?, ?)",
261 (string)$query
262 );
263 $this->assertSame(['bar', 'baz', 'bar', 'baz', 'bar', 'baz', 'bar', 'baz'], $query->getParameters());
264 $this->assertSame(
265 [
266 Connection::PARAM_INT,
267 Connection::PARAM_BOOL,
268 Connection::PARAM_INT,
269 Connection::PARAM_BOOL,
270 null,
271 null,
272 Connection::PARAM_INT,
273 Connection::PARAM_BOOL,
274 ],
275 $query->getParameterTypes()
276 );
277 }
278
279 /**
280 * @test
281 */
282 public function emptyInsertWithColumnSpecificationThrowsException()
283 {
284 $this->expectException(\InvalidArgumentException::class);
285 $this->expectExceptionMessage('No value specified for column bar (index 0).');
286
287 $query = new BulkInsertQuery($this->connection, $this->testTable, ['bar', 'baz']);
288 $query->addValues([]);
289 }
290
291 /**
292 * @test
293 */
294 public function insertWithColumnSpecificationAndMultipleValuesForColumnThrowsException()
295 {
296 $this->expectException(\InvalidArgumentException::class);
297 $this->expectExceptionMessage('Multiple values specified for column baz (index 1).');
298
299 $query = new BulkInsertQuery($this->connection, $this->testTable, ['bar', 'baz']);
300 $query->addValues(['bar', 'baz', 'baz' => 666]);
301 }
302
303 /**
304 * @test
305 */
306 public function insertWithColumnSpecificationAndMultipleTypesForColumnThrowsException()
307 {
308 $this->expectException(\InvalidArgumentException::class);
309 $this->expectExceptionMessage('Multiple types specified for column baz (index 1).');
310
311 $query = new BulkInsertQuery($this->connection, $this->testTable, ['bar', 'baz']);
312 $query->addValues(['bar', 'baz'],
313 [Connection::PARAM_INT, Connection::PARAM_INT, 'baz' => Connection::PARAM_STR]);
314 }
315
316 /**
317 * @test
318 */
319 public function executeWithMaxInsertRowsPerStatementExceededThrowsException()
320 {
321 $this->expectException(\LogicException::class);
322 $this->expectExceptionMessage('You can only insert 10 rows in a single INSERT statement with platform "mock".');
323
324 /** @var \PHPUnit_Framework_MockObject_MockObject|BulkInsertQuery $subject */
325 $subject = $this->getAccessibleMock(
326 BulkInsertQuery::class,
327 ['getInsertMaxRows'],
328 [$this->connection, $this->testTable],
329 ''
330 );
331
332 $subject->expects($this->any())
333 ->method('getInsertMaxRows')
334 ->will($this->returnValue(10));
335
336 for ($i = 0; $i <= 10; $i++) {
337 $subject->addValues([]);
338 }
339
340 $subject->execute();
341 }
342 }