TYPO3 CMS  TYPO3_7-6
DatabaseConnectionTest.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
18 
23 {
27  protected $subject;
28 
32  protected function setUp()
33  {
34  $GLOBALS['TYPO3_LOADED_EXT'] = [];
35 
37  $subject = $this->getAccessibleMock(\TYPO3\CMS\Dbal\Database\DatabaseConnection::class, ['getFieldInfoCache'], [], '', false);
38 
39  // Disable caching
40  $mockCacheFrontend = $this->getMock(\TYPO3\CMS\Core\Cache\Frontend\PhpFrontend::class, [], [], '', false);
41  $subject->expects($this->any())->method('getFieldInfoCache')->will($this->returnValue($mockCacheFrontend));
42 
43  // Inject SqlParser - Its logic is tested with the tests, too.
44  $sqlParser = $this->getAccessibleMock(\TYPO3\CMS\Dbal\Database\SqlParser::class, ['dummy'], [], '', false);
45  $sqlParser->_set('databaseConnection', $subject);
46  $subject->SQLparser = $sqlParser;
47 
48  // Mock away schema migration service from install tool
49  $installerSqlMock = $this->getMock(\TYPO3\CMS\Install\Service\SqlSchemaMigrationService::class, ['getFieldDefinitions_fileContent'], [], '', false);
50  $installerSqlMock->expects($this->any())->method('getFieldDefinitions_fileContent')->will($this->returnValue([]));
51  $subject->_set('installerSql', $installerSqlMock);
52 
53  // Inject DBMS specifics
54  $subject->_set('dbmsSpecifics', GeneralUtility::makeInstance(\TYPO3\CMS\Dbal\Database\Specifics\NullSpecifics::class));
55 
56  $subject->initialize();
57  $subject->lastHandlerKey = '_DEFAULT';
58 
59  $this->subject = $subject;
60  }
61 
69  protected function createFakeExtension($tableDefinition)
70  {
71  // Prepare a fake extension configuration
72  $ext_tables = GeneralUtility::tempnam('ext_tables');
73  if (!GeneralUtility::writeFile($ext_tables, $tableDefinition)) {
74  throw new \RuntimeException('Can\'t write temporary ext_tables file.');
75  }
76  $this->testFilesToDelete[] = $ext_tables;
77  $GLOBALS['TYPO3_LOADED_EXT'] = [
78  'test_dbal' => [
79  'ext_tables.sql' => $ext_tables
80  ]
81  ];
82  // Append our test table to the list of existing tables
83  $this->subject->initialize();
84  }
85 
89  public function tableWithMappingIsDetected()
90  {
91  $dbalConfiguration = [
92  'mapping' => [
93  'cf_cache_hash' => [],
94  ],
95  ];
96 
98  $subject = $this->getAccessibleMock(\TYPO3\CMS\Dbal\Database\DatabaseConnection::class, ['getFieldInfoCache'], [], '', false);
99 
100  $mockCacheFrontend = $this->getMock(\TYPO3\CMS\Core\Cache\Frontend\PhpFrontend::class, [], [], '', false);
101  $subject->expects($this->any())->method('getFieldInfoCache')->will($this->returnValue($mockCacheFrontend));
102 
103  $sqlParser = $this->getAccessibleMock(\TYPO3\CMS\Dbal\Database\SqlParser::class, ['dummy'], [], '', false);
104  $sqlParser->_set('databaseConnection', $subject);
105  $subject->SQLparser = $sqlParser;
106 
107  $installerSqlMock = $this->getMock(\TYPO3\CMS\Install\Service\SqlSchemaMigrationService::class, [], [], '', false);
108  $subject->_set('installerSql', $installerSqlMock);
109  $schemaMigrationResult = [
110  'cf_cache_pages' => [],
111  ];
112  $installerSqlMock->expects($this->once())->method('getFieldDefinitions_fileContent')->will($this->returnValue($schemaMigrationResult));
113 
114  $subject->conf = $dbalConfiguration;
115  $subject->initialize();
116  $subject->lastHandlerKey = '_DEFAULT';
117 
118  $this->assertFalse($subject->_call('map_needMapping', 'cf_cache_pages'));
119  $cfCacheHashNeedsMapping = $subject->_call('map_needMapping', 'cf_cache_hash');
120  $this->assertEquals('cf_cache_hash', $cfCacheHashNeedsMapping[0]['table']);
121  }
122 
128  {
129  $handlerMock = $this->getMock('\ADODB_mock', ['MetaTables'], [], '', false);
130  $handlerMock->expects($this->any())->method('MetaTables')->will($this->returnValue(['cf_cache_hash']));
131  $this->subject->handlerCfg['_DEFAULT']['type'] = 'adodb';
132  $this->subject->handlerInstance['_DEFAULT'] = $handlerMock;
133 
134  $actual = $this->subject->admin_get_tables();
135  $expected = ['cf_cache_hash' => ['Name' => 'cf_cache_hash']];
136  $this->assertSame($expected, $actual);
137  }
138 
144  {
145  $result = $this->subject->SELECTquery('*', 'sys_refindex, tx_dam_file_tracking', 'sys_refindex.tablename = \'tx_dam_file_tracking\'' . ' AND sys_refindex.ref_string LIKE CONCAT(tx_dam_file_tracking.file_path, tx_dam_file_tracking.file_name)');
146  $expected = 'SELECT * FROM sys_refindex, tx_dam_file_tracking WHERE sys_refindex.tablename = \'tx_dam_file_tracking\'';
147  $expected .= ' AND sys_refindex.ref_string LIKE CONCAT(tx_dam_file_tracking.file_path, tx_dam_file_tracking.file_name)';
148  $this->assertEquals($expected, $this->cleanSql($result));
149  }
150 
156  {
157  $this->createFakeExtension('
158  CREATE TABLE tx_test_dbal (
159  foo double default \'0\',
160  foobar int default \'0\'
161  );
162  ');
163  $data = [
164  'foo' => 99.12,
165  'foobar' => -120
166  ];
167  $result = $this->subject->INSERTquery('tx_test_dbal', $data);
168  $expected = 'INSERT INTO tx_test_dbal ( foo, foobar ) VALUES ( \'99.12\', \'-120\' )';
169  $this->assertEquals($expected, $this->cleanSql($result));
170  }
171 
177  {
178  if (!is_int(9223372036854775806)) {
179  $this->markTestSkipped('Test skipped because running on 32 bit system.');
180  }
181  $this->createFakeExtension('
182  CREATE TABLE tx_test_dbal (
183  foo int default \'0\',
184  foobar bigint default \'0\'
185  );
186  ');
187  $data = [
188  'foo' => 9223372036854775807,
189  'foobar' => 9223372036854775807
190  ];
191  $result = $this->subject->INSERTquery('tx_test_dbal', $data);
192  $expected = 'INSERT INTO tx_test_dbal ( foo, foobar ) VALUES ( \'9223372036854775807\', \'9223372036854775807\' )';
193  $this->assertEquals($expected, $this->cleanSql($result));
194  }
195 
200  {
201  $fields = ['uid', 'pid', 'title', 'body'];
202  $rows = [
203  ['1', '2', 'Title #1', 'Content #1'],
204  ['3', '4', 'Title #2', 'Content #2'],
205  ['5', '6', 'Title #3', 'Content #3']
206  ];
207  $result = $this->subject->INSERTmultipleRows('tt_content', $fields, $rows);
208  $expected = 'INSERT INTO tt_content (uid, pid, title, body) VALUES ';
209  $expected .= '(\'1\', \'2\', \'Title #1\', \'Content #1\'), ';
210  $expected .= '(\'3\', \'4\', \'Title #2\', \'Content #2\'), ';
211  $expected .= '(\'5\', \'6\', \'Title #3\', \'Content #3\')';
212  $this->assertEquals($expected, $this->cleanSql($result));
213  }
214 
218  public function sqlForSelectMmQuery()
219  {
220  $result = $this->subject->SELECT_mm_query('*', 'sys_category', 'sys_category_record_mm', 'tt_content', 'AND sys_category.uid = 1', '', 'sys_category.title DESC');
221  $expected = 'SELECT * FROM sys_category,sys_category_record_mm,tt_content WHERE sys_category.uid=sys_category_record_mm.uid_local AND tt_content.uid=sys_category_record_mm.uid_foreign AND sys_category.uid = 1 ORDER BY sys_category.title DESC';
222  $this->assertEquals($expected, $result);
223  }
224 
230  {
231  $result = $this->subject->SELECTquery('*', 'pages', 'MIN(uid) IN (1,2,3,4)');
232  $expected = 'SELECT * FROM pages WHERE MIN(uid) IN (1,2,3,4)';
233  $this->assertEquals($expected, $this->cleanSql($result));
234  }
235 
241  {
242  $result = $this->subject->SELECTquery('*', 'pages', 'MAX(uid) IN (1,2,3,4)');
243  $expected = 'SELECT * FROM pages WHERE MAX(uid) IN (1,2,3,4)';
244  $this->assertEquals($expected, $this->cleanSql($result));
245  }
246 
252  {
253  $result = $this->subject->SELECTquery('uid', 'sys_category', 'FIND_IN_SET(\'0\',parent) != 0 OR CAST(parent AS CHAR) = \'\'');
254  $expected = 'SELECT uid FROM sys_category WHERE FIND_IN_SET(\'0\',parent) != 0 OR CAST(parent AS CHAR) = \'\'';
255  $this->assertEquals($expected, $this->cleanSql($result));
256  }
257 
262  public function likeBinaryOperatorIsKept()
263  {
264  $result = $this->cleanSql($this->subject->SELECTquery('*', 'tt_content', 'bodytext LIKE BINARY \'test\''));
265  $expected = 'SELECT * FROM tt_content WHERE bodytext LIKE BINARY \'test\'';
266  $this->assertEquals($expected, $this->cleanSql($result));
267  }
268 
273  public function notLikeBinaryOperatorIsKept()
274  {
275  $result = $this->cleanSql($this->subject->SELECTquery('*', 'tt_content', 'bodytext NOT LIKE BINARY \'test\''));
276  $expected = 'SELECT * FROM tt_content WHERE bodytext NOT LIKE BINARY \'test\'';
277  $this->assertEquals($expected, $this->cleanSql($result));
278  }
279 
281  // Tests concerning prepared queries
283 
288  {
289  $sql = 'SELECT * FROM cache WHERE tag = :tag1 OR tag = :tag10 OR tag = :tag100';
290  $parameterValues = [
291  ':tag1' => 'tag-one',
292  ':tag10' => 'tag-two',
293  ':tag100' => 'tag-three'
294  ];
295  $className = self::buildAccessibleProxy(\TYPO3\CMS\Core\Database\PreparedStatement::class);
296  $query = $sql;
297  $precompiledQueryParts = [];
298  $statement = new $className($sql, 'cache');
299  $statement->bindValues($parameterValues);
300  $parameters = $statement->_get('parameters');
301  $statement->_callRef('convertNamedPlaceholdersToQuestionMarks', $query, $parameters, $precompiledQueryParts);
302  $expectedQuery = 'SELECT * FROM cache WHERE tag = ? OR tag = ? OR tag = ?';
303  $expectedParameterValues = [
304  0 => [
306  'value' => 'tag-one',
307  ],
308  1 => [
310  'value' => 'tag-two',
311  ],
312  2 => [
314  'value' => 'tag-three',
315  ],
316  ];
317  $this->assertEquals($expectedQuery, $query);
318  $this->assertEquals($expectedParameterValues, $parameters);
319  }
320 
322  // Tests concerning indexes
324 
330  public function equivalentIndexDefinitionRemovesLengthInformation($indexSQL, $expected)
331  {
332  $result = $this->subject->getEquivalentIndexDefinition($indexSQL);
333  $this->assertSame($expected, $result);
334  }
335 
340  {
341  return [
342  ['KEY (foo,bar(199))', 'KEY (foo,bar)'],
343  ['KEY (foo(199), bar)', 'KEY (foo, bar)'],
344  ['KEY (foo(199),bar(199))', 'KEY (foo,bar)'],
345  ];
346  }
347 }
static tempnam($filePrefix, $fileSuffix='')
getAccessibleMock( $originalClassName, $methods=[], array $arguments=[], $mockClassName='', $callOriginalConstructor=true, $callOriginalClone=true, $callAutoload=true)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
$sql
Definition: server.php:84
static writeFile($file, $content, $changePermissions=false)