TYPO3 CMS  TYPO3_8-7
ConnectionTest.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
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 
26 
30 class ConnectionTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
31 {
35  protected $connection;
36 
40  protected $platform;
41 
45  protected $testTable = 'testTable';
46 
50  protected function setUp()
51  {
52  parent::setUp();
53 
54  $this->connection = $this->getMockBuilder(Connection::class)
55  ->disableOriginalConstructor()
56  ->setMethods(
57  [
58  'connect',
59  'executeQuery',
60  'executeUpdate',
61  'getDatabasePlatform',
62  'getDriver',
63  'getExpressionBuilder',
64  'getWrappedConnection',
65  ]
66  )
67  ->getMock();
68 
69  $this->connection->expects($this->any())
70  ->method('getExpressionBuilder')
71  ->will($this->returnValue(GeneralUtility::makeInstance(ExpressionBuilder::class, $this->connection)));
72 
73  $this->connection->expects($this->any())
74  ->method('connect');
75 
76  $this->connection->expects($this->any())
77  ->method('getDatabasePlatform')
78  ->will($this->returnValue(new MockPlatform()));
79  }
80 
85  {
86  $this->assertInstanceOf(QueryBuilder::class, $this->connection->createQueryBuilder());
87  }
88 
92  public function quoteIdentifierDataProvider()
93  {
94  return [
95  'SQL star' => [
96  '*',
97  '*',
98  ],
99  'fieldname' => [
100  'aField',
101  '"aField"',
102  ],
103  'whitespace' => [
104  'with blanks',
105  '"with blanks"',
106  ],
107  'double quotes' => [
108  '"double" quotes',
109  '"""double"" quotes"',
110  ],
111  'single quotes' => [
112  "'single'",
113  '"\'single\'"',
114 
115  ],
116  'multiple double quotes' => [
117  '""multiple""',
118  '"""""multiple"""""',
119  ],
120  'multiple single quotes' => [
121  "''multiple''",
122  '"\'\'multiple\'\'"',
123  ],
124  'backticks' => [
125  '`backticks`',
126  '"`backticks`"',
127  ],
128  'slashes' => [
129  '/slashes/',
130  '"/slashes/"',
131  ],
132  'backslashes' => [
133  '\\backslashes\\',
134  '"\\backslashes\\"',
135  ],
136  ];
137  }
138 
145  public function quoteIdentifier(string $input, string $expected)
146  {
147  $this->assertSame($expected, $this->connection->quoteIdentifier($input));
148  }
149 
153  public function quoteIdentifiers()
154  {
155  $input = [
156  'aField',
157  'anotherField',
158  ];
159 
160  $expected = [
161  '"aField"',
162  '"anotherField"',
163  ];
164 
165  $this->assertSame($expected, $this->connection->quoteIdentifiers($input));
166  }
167 
171  public function insertQueriesDataProvider()
172  {
173  return [
174  'single value' => [
175  ['aTestTable', ['aField' => 'aValue']],
176  'INSERT INTO "aTestTable" ("aField") VALUES (?)',
177  ['aValue'],
178  [],
179  ],
180  'multiple values' => [
181  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue']],
182  'INSERT INTO "aTestTable" ("aField", "bField") VALUES (?, ?)',
183  ['aValue', 'bValue'],
184  [],
185  ],
186  'with types' => [
187  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue'], [Connection::PARAM_STR, Connection::PARAM_STR]],
188  'INSERT INTO "aTestTable" ("aField", "bField") VALUES (?, ?)',
189  ['aValue', 'bValue'],
191  ],
192  'with types for field' => [
193  [
194  'aTestTable',
195  ['aField' => 123, 'bField' => 'bValue'],
196  ['aField' => Connection::PARAM_INT, 'bField' => Connection::PARAM_LOB]
197  ],
198  'INSERT INTO "aTestTable" ("aField", "bField") VALUES (?, ?)',
199  [123, 'bValue'],
201  ],
202  ];
203  }
204 
213  public function insertQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
214  {
215  $this->connection->expects($this->once())
216  ->method('executeUpdate')
217  ->with($expectedQuery, $expectedValues, $expectedTypes)
218  ->will($this->returnValue(1));
219 
220  $this->connection->insert(...$args);
221  }
222 
226  public function bulkInsert()
227  {
228  $this->connection->expects($this->once())
229  ->method('executeUpdate')
230  ->with('INSERT INTO "aTestTable" ("aField") VALUES (?), (?)', ['aValue', 'anotherValue'])
231  ->will($this->returnValue(2));
232 
233  $this->connection->bulkInsert('aTestTable', [['aField' => 'aValue'], ['aField' => 'anotherValue']], ['aField']);
234  }
235 
239  public function updateQueriesDataProvider()
240  {
241  return [
242  'single value' => [
243  ['aTestTable', ['aField' => 'aValue'], ['uid' => 1]],
244  'UPDATE "aTestTable" SET "aField" = ? WHERE "uid" = ?',
245  ['aValue', 1],
246  [],
247  ],
248  'multiple values' => [
249  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue'], ['uid' => 1]],
250  'UPDATE "aTestTable" SET "aField" = ?, "bField" = ? WHERE "uid" = ?',
251  ['aValue', 'bValue', 1],
252  [],
253  ],
254  'with types' => [
255  ['aTestTable', ['aField' => 'aValue'], ['uid' => 1], [Connection::PARAM_STR]],
256  'UPDATE "aTestTable" SET "aField" = ? WHERE "uid" = ?',
257  ['aValue', 1],
259  ],
260  'with types for field' => [
261  ['aTestTable', ['aField' => 'aValue'], ['uid' => 1], ['aField' => Connection::PARAM_LOB]],
262  'UPDATE "aTestTable" SET "aField" = ? WHERE "uid" = ?',
263  ['aValue', 1],
265  ],
266  ];
267  }
268 
277  public function updateQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
278  {
279  $this->connection->expects($this->once())
280  ->method('executeUpdate')
281  ->with($expectedQuery, $expectedValues, $expectedTypes)
282  ->will($this->returnValue(1));
283 
284  $this->connection->update(...$args);
285  }
286 
290  public function deleteQueriesDataProvider()
291  {
292  return [
293  'single condition' => [
294  ['aTestTable', ['aField' => 'aValue']],
295  'DELETE FROM "aTestTable" WHERE "aField" = ?',
296  ['aValue'],
297  [],
298  ],
299  'multiple conditions' => [
300  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue']],
301  'DELETE FROM "aTestTable" WHERE "aField" = ? AND "bField" = ?',
302  ['aValue', 'bValue'],
303  [],
304  ],
305  'with types' => [
306  ['aTestTable', ['aField' => 'aValue'], [Connection::PARAM_STR]],
307  'DELETE FROM "aTestTable" WHERE "aField" = ?',
308  ['aValue'],
310  ],
311  'with types for field' => [
312  ['aTestTable', ['aField' => 'aValue'], ['aField' => Connection::PARAM_STR]],
313  'DELETE FROM "aTestTable" WHERE "aField" = ?',
314  ['aValue'],
316  ],
317  ];
318  }
319 
328  public function deleteQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
329  {
330  $this->connection->expects($this->once())
331  ->method('executeUpdate')
332  ->with($expectedQuery, $expectedValues, $expectedTypes)
333  ->will($this->returnValue(1));
334 
335  $this->connection->delete(...$args);
336  }
337 
348  public function selectQueriesDataProvider()
349  {
350  return [
351  'all columns' => [
352  [['*'], 'aTable'],
353  'SELECT * FROM "aTable"',
354  [],
355  ],
356  'subset of columns' => [
357  [['aField', 'anotherField'], 'aTable'],
358  'SELECT "aField", "anotherField" FROM "aTable"',
359  [],
360  ],
361  'conditions' => [
362  [['*'], 'aTable', ['aField' => 'aValue']],
363  'SELECT * FROM "aTable" WHERE "aField" = :dcValue1',
364  ['dcValue1' => 'aValue'],
365  ],
366  'grouping' => [
367  [['*'], 'aTable', [], ['aField']],
368  'SELECT * FROM "aTable" GROUP BY "aField"',
369  [],
370  ],
371  'ordering' => [
372  [['*'], 'aTable', [], [], ['aField' => 'ASC']],
373  'SELECT * FROM "aTable" ORDER BY "aField" ASC',
374  [],
375  ],
376  'limit' => [
377  [['*'], 'aTable', [], [], [], 1],
378  'SELECT * FROM "aTable" LIMIT 1 OFFSET 0',
379  [],
380  ],
381  'offset' => [
382  [['*'], 'aTable', [], [], [], 1, 10],
383  'SELECT * FROM "aTable" LIMIT 1 OFFSET 10',
384  [],
385  ],
386  'everything' => [
387  [
388  ['aField', 'anotherField'],
389  'aTable',
390  ['aField' => 'aValue'],
391  ['anotherField'],
392  ['aField' => 'ASC'],
393  1,
394  10,
395  ],
396  'SELECT "aField", "anotherField" FROM "aTable" WHERE "aField" = :dcValue1 ' .
397  'GROUP BY "anotherField" ORDER BY "aField" ASC LIMIT 1 OFFSET 10',
398  ['dcValue1' => 'aValue'],
399  ],
400  ];
401  }
402 
410  public function selectQueries(array $args, string $expectedQuery, array $expectedParameters)
411  {
412  $resultStatement = $this->createMock(Statement::class);
413 
414  $this->connection->expects($this->once())
415  ->method('executeQuery')
416  ->with($expectedQuery, $expectedParameters)
417  ->will($this->returnValue($resultStatement));
418 
419  $this->connection->select(...$args);
420  }
421 
432  public function countQueriesDataProvider()
433  {
434  return [
435  'all columns' => [
436  ['*', 'aTable', []],
437  'SELECT COUNT(*) FROM "aTable"',
438  [],
439  ],
440  'specified columns' => [
441  ['aField', 'aTable', []],
442  'SELECT COUNT("aField") FROM "aTable"',
443  [],
444  ],
445  'conditions' => [
446  ['aTable.aField', 'aTable', ['aField' => 'aValue']],
447  'SELECT COUNT("aTable"."aField") FROM "aTable" WHERE "aField" = :dcValue1',
448  ['dcValue1' => 'aValue'],
449  ],
450  ];
451  }
452 
460  public function countQueries(array $args, string $expectedQuery, array $expectedParameters)
461  {
462  $resultStatement = $this->createMock(Statement::class);
463 
464  $resultStatement->expects($this->once())
465  ->method('fetchColumn')
466  ->with(0)
467  ->will($this->returnValue(0));
468 
469  $this->connection->expects($this->once())
470  ->method('executeQuery')
471  ->with($expectedQuery, $expectedParameters)
472  ->will($this->returnValue($resultStatement));
473 
474  $this->connection->count(...$args);
475  }
476 
480  public function truncateQuery()
481  {
482  $this->connection->expects($this->once())
483  ->method('executeUpdate')
484  ->with('TRUNCATE "aTestTable"')
485  ->will($this->returnValue(0));
486 
487  $this->connection->truncate('aTestTable', false);
488  }
489 
493  public function getServerVersionReportsPlatformVersion()
494  {
496  $driverProphet = $this->prophesize(\Doctrine\DBAL\Driver\Mysqli\Driver::class);
497  $driverProphet->willImplement(\Doctrine\DBAL\VersionAwarePlatformDriver::class);
498 
500  $wrappedConnectionProphet = $this->prophesize(\Doctrine\DBAL\Driver\Mysqli\MysqliConnection::class);
501  $wrappedConnectionProphet->willImplement(\Doctrine\DBAL\Driver\ServerInfoAwareConnection::class);
502  $wrappedConnectionProphet->requiresQueryForServerVersion()->willReturn(false);
503  $wrappedConnectionProphet->getServerVersion()->willReturn('5.7.11');
504 
505  $this->connection->expects($this->any())
506  ->method('getDriver')
507  ->willReturn($driverProphet->reveal());
508  $this->connection->expects($this->any())
509  ->method('getWrappedConnection')
510  ->willReturn($wrappedConnectionProphet->reveal());
511 
512  $this->assertSame('mock 5.7.11', $this->connection->getServerVersion());
513  }
514 }
insertQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
countQueries(array $args, string $expectedQuery, array $expectedParameters)
updateQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
selectQueries(array $args, string $expectedQuery, array $expectedParameters)
quoteIdentifier(string $input, string $expected)
static makeInstance($className,... $constructorArguments)
deleteQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)