TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
ConnectionTest.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types=1);
3 namespace TYPO3\CMS\Core\Tests\Unit\Database;
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 Doctrine\DBAL\Driver\Mysqli\MysqliConnection;
19 use Doctrine\DBAL\Statement;
20 use Prophecy\Prophecy\ObjectProphecy;
27 
33 {
37  protected $connection;
38 
42  protected $platform;
43 
47  protected $testTable = 'testTable';
48 
54  protected function setUp()
55  {
56  parent::setUp();
57 
58  $this->connection = $this->getMockBuilder(Connection::class)
59  ->disableOriginalConstructor()
60  ->setMethods(
61  [
62  'connect',
63  'executeQuery',
64  'executeUpdate',
65  'getDatabasePlatform',
66  'getDriver',
67  'getExpressionBuilder',
68  'getWrappedConnection',
69  ]
70  )
71  ->getMock();
72 
73  $this->connection->expects($this->any())
74  ->method('getExpressionBuilder')
75  ->will($this->returnValue(GeneralUtility::makeInstance(ExpressionBuilder::class, $this->connection)));
76 
77  $this->connection->expects($this->any())
78  ->method('connect');
79 
80  $this->connection->expects($this->any())
81  ->method('getDatabasePlatform')
82  ->will($this->returnValue(new MockPlatform()));
83  }
84 
89  {
90  $this->assertInstanceOf(QueryBuilder::class, $this->connection->createQueryBuilder());
91  }
92 
96  public function quoteIdentifierDataProvider()
97  {
98  return [
99  'SQL star' => [
100  '*',
101  '*',
102  ],
103  'fieldname' => [
104  'aField',
105  '"aField"',
106  ],
107  'whitespace' => [
108  'with blanks',
109  '"with blanks"',
110  ],
111  'double quotes' => [
112  '"double" quotes',
113  '"""double"" quotes"',
114  ],
115  'single quotes' => [
116  "'single'",
117  '"\'single\'"',
118 
119  ],
120  'multiple double quotes' => [
121  '""multiple""',
122  '"""""multiple"""""',
123  ],
124  'multiple single quotes' => [
125  "''multiple''",
126  '"\'\'multiple\'\'"',
127  ],
128  'backticks' => [
129  '`backticks`',
130  '"`backticks`"',
131  ],
132  'slashes' => [
133  '/slashes/',
134  '"/slashes/"',
135  ],
136  'backslashes' => [
137  '\\backslashes\\',
138  '"\\backslashes\\"',
139  ],
140  ];
141  }
142 
149  public function quoteIdentifier(string $input, string $expected)
150  {
151  $this->assertSame($expected, $this->connection->quoteIdentifier($input));
152  }
153 
157  public function quoteIdentifiers()
158  {
159  $input = [
160  'aField',
161  'anotherField',
162  ];
163 
164  $expected = [
165  '"aField"',
166  '"anotherField"',
167  ];
168 
169  $this->assertSame($expected, $this->connection->quoteIdentifiers($input));
170  }
171 
175  public function insertQueriesDataProvider()
176  {
177  return [
178  'single value' => [
179  ['aTestTable', ['aField' => 'aValue']],
180  'INSERT INTO "aTestTable" ("aField") VALUES (?)',
181  ['aValue'],
182  [],
183  ],
184  'multiple values' => [
185  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue']],
186  'INSERT INTO "aTestTable" ("aField", "bField") VALUES (?, ?)',
187  ['aValue', 'bValue'],
188  [],
189  ],
190  'with types' => [
191  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue'], [Connection::PARAM_STR, Connection::PARAM_STR]],
192  'INSERT INTO "aTestTable" ("aField", "bField") VALUES (?, ?)',
193  ['aValue', 'bValue'],
195  ],
196  ];
197  }
198 
207  public function insertQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
208  {
209  $this->connection->expects($this->once())
210  ->method('executeUpdate')
211  ->with($expectedQuery, $expectedValues, $expectedTypes)
212  ->will($this->returnValue(1));
213 
214  $this->connection->insert(...$args);
215  }
216 
220  public function bulkInsert()
221  {
222  $this->connection->expects($this->once())
223  ->method('executeUpdate')
224  ->with('INSERT INTO "aTestTable" ("aField") VALUES (?), (?)', ['aValue', 'anotherValue'])
225  ->will($this->returnValue(2));
226 
227  $this->connection->bulkInsert('aTestTable', [['aField' => 'aValue'], ['aField' => 'anotherValue']], ['aField']);
228  }
229 
233  public function updateQueriesDataProvider()
234  {
235  return [
236  'single value' => [
237  ['aTestTable', ['aField' => 'aValue'], ['uid' => 1]],
238  'UPDATE "aTestTable" SET "aField" = ? WHERE "uid" = ?',
239  ['aValue', 1],
240  [],
241  ],
242  'multiple values' => [
243  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue'], ['uid' => 1]],
244  'UPDATE "aTestTable" SET "aField" = ?, "bField" = ? WHERE "uid" = ?',
245  ['aValue', 'bValue', 1],
246  [],
247  ],
248  'with types' => [
249  ['aTestTable', ['aField' => 'aValue'], ['uid' => 1], [Connection::PARAM_STR]],
250  'UPDATE "aTestTable" SET "aField" = ? WHERE "uid" = ?',
251  ['aValue', 1],
253  ],
254  ];
255  }
256 
265  public function updateQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
266  {
267  $this->connection->expects($this->once())
268  ->method('executeUpdate')
269  ->with($expectedQuery, $expectedValues, $expectedTypes)
270  ->will($this->returnValue(1));
271 
272  $this->connection->update(...$args);
273  }
274 
278  public function deleteQueriesDataProvider()
279  {
280  return [
281  'single condition' => [
282  ['aTestTable', ['aField' => 'aValue']],
283  'DELETE FROM "aTestTable" WHERE "aField" = ?',
284  ['aValue'],
285  [],
286  ],
287  'multiple conditions' => [
288  ['aTestTable', ['aField' => 'aValue', 'bField' => 'bValue']],
289  'DELETE FROM "aTestTable" WHERE "aField" = ? AND "bField" = ?',
290  ['aValue', 'bValue'],
291  [],
292  ],
293  'with types' => [
294  ['aTestTable', ['aField' => 'aValue'], [Connection::PARAM_STR]],
295  'DELETE FROM "aTestTable" WHERE "aField" = ?',
296  ['aValue'],
298  ],
299  ];
300  }
301 
310  public function deleteQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
311  {
312  $this->connection->expects($this->once())
313  ->method('executeUpdate')
314  ->with($expectedQuery, $expectedValues, $expectedTypes)
315  ->will($this->returnValue(1));
316 
317  $this->connection->delete(...$args);
318  }
319 
330  public function selectQueriesDataProvider()
331  {
332  return [
333  'all columns' => [
334  [['*'], 'aTable'],
335  'SELECT * FROM "aTable"',
336  [],
337  ],
338  'subset of columns' => [
339  [['aField', 'anotherField'], 'aTable'],
340  'SELECT "aField", "anotherField" FROM "aTable"',
341  [],
342  ],
343  'conditions' => [
344  [['*'], 'aTable', ['aField' => 'aValue']],
345  'SELECT * FROM "aTable" WHERE "aField" = :dcValue1',
346  ['dcValue1' => 'aValue'],
347  ],
348  'grouping' => [
349  [['*'], 'aTable', [], ['aField']],
350  'SELECT * FROM "aTable" GROUP BY "aField"',
351  [],
352  ],
353  'ordering' => [
354  [['*'], 'aTable', [], [], ['aField' => 'ASC']],
355  'SELECT * FROM "aTable" ORDER BY "aField" ASC',
356  [],
357  ],
358  'limit' => [
359  [['*'], 'aTable', [], [], [], 1],
360  'SELECT * FROM "aTable" LIMIT 1 OFFSET 0',
361  [],
362  ],
363  'offset' => [
364  [['*'], 'aTable', [], [], [], 1, 10],
365  'SELECT * FROM "aTable" LIMIT 1 OFFSET 10',
366  [],
367  ],
368  'everything' => [
369  [
370  ['aField', 'anotherField'],
371  'aTable',
372  ['aField' => 'aValue'],
373  ['anotherField'],
374  ['aField' => 'ASC'],
375  1,
376  10,
377  ],
378  'SELECT "aField", "anotherField" FROM "aTable" WHERE "aField" = :dcValue1 ' .
379  'GROUP BY "anotherField" ORDER BY "aField" ASC LIMIT 1 OFFSET 10',
380  ['dcValue1' => 'aValue'],
381  ],
382  ];
383  }
384 
392  public function selectQueries(array $args, string $expectedQuery, array $expectedParameters)
393  {
394  $resultStatement = $this->createMock(Statement::class);
395 
396  $this->connection->expects($this->once())
397  ->method('executeQuery')
398  ->with($expectedQuery, $expectedParameters)
399  ->will($this->returnValue($resultStatement));
400 
401  $this->connection->select(...$args);
402  }
403 
414  public function countQueriesDataProvider()
415  {
416  return [
417  'all columns' => [
418  ['*', 'aTable', []],
419  'SELECT COUNT(*) FROM "aTable"',
420  [],
421  ],
422  'specified columns' => [
423  ['aField', 'aTable', []],
424  'SELECT COUNT("aField") FROM "aTable"',
425  [],
426  ],
427  'conditions' => [
428  ['aTable.aField', 'aTable', ['aField' => 'aValue']],
429  'SELECT COUNT("aTable"."aField") FROM "aTable" WHERE "aField" = :dcValue1',
430  ['dcValue1' => 'aValue'],
431  ],
432  ];
433  }
434 
442  public function countQueries(array $args, string $expectedQuery, array $expectedParameters)
443  {
444  $resultStatement = $this->createMock(Statement::class);
445 
446  $resultStatement->expects($this->once())
447  ->method('fetchColumn')
448  ->with(0)
449  ->will($this->returnValue(0));
450 
451  $this->connection->expects($this->once())
452  ->method('executeQuery')
453  ->with($expectedQuery, $expectedParameters)
454  ->will($this->returnValue($resultStatement));
455 
456  $this->connection->count(...$args);
457  }
458 
462  public function truncateQuery()
463  {
464  $this->connection->expects($this->once())
465  ->method('executeUpdate')
466  ->with('TRUNCATE "aTestTable"')
467  ->will($this->returnValue(0));
468 
469  $this->connection->truncate('aTestTable', false);
470  }
471 
475  public function getServerVersionReportsPlatformVersion()
476  {
478  $driverProphet = $this->prophesize(\Doctrine\DBAL\Driver\Mysqli\Driver::class);
479  $driverProphet->willImplement(\Doctrine\DBAL\VersionAwarePlatformDriver::class);
480 
482  $wrappedConnectionProphet = $this->prophesize(\Doctrine\DBAL\Driver\Mysqli\MysqliConnection::class);
483  $wrappedConnectionProphet->willImplement(\Doctrine\DBAL\Driver\ServerInfoAwareConnection::class);
484  $wrappedConnectionProphet->requiresQueryForServerVersion()->willReturn(false);
485  $wrappedConnectionProphet->getServerVersion()->willReturn('5.7.11');
486 
487  $this->connection->expects($this->any())
488  ->method('getDriver')
489  ->willReturn($driverProphet->reveal());
490  $this->connection->expects($this->any())
491  ->method('getWrappedConnection')
492  ->willReturn($wrappedConnectionProphet->reveal());
493 
494  $this->assertSame('mock 5.7.11', $this->connection->getServerVersion());
495  }
496 }
countQueries(array $args, string $expectedQuery, array $expectedParameters)
updateQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
deleteQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
selectQueries(array $args, string $expectedQuery, array $expectedParameters)
insertQueries(array $args, string $expectedQuery, array $expectedValues, array $expectedTypes)
static makeInstance($className,...$constructorArguments)
quoteIdentifier(string $input, string $expected)