[TASK] MySQLi for DBAL
[Packages/TYPO3.CMS.git] / typo3 / sysext / dbal / Tests / Unit / Database / DatabaseConnectionTest.php
1 <?php
2 namespace TYPO3\CMS\Dbal\Tests\Unit\Database;
3
4 /**
5 * Testcase for class DatabaseConnection.
6 *
7 * @author Xavier Perseguers <xavier@typo3.org>
8 */
9 class DatabaseConnectionTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
10
11 /**
12 * @var array
13 */
14 protected $temporaryFiles;
15
16 /**
17 * Prepares the environment before running a test.
18 */
19 public function setUp() {
20 $this->temporaryFiles = array();
21 $GLOBALS['TYPO3_LOADED_EXT'] = array();
22 $GLOBALS['TYPO3_DB'] = $this->getAccessibleMock('TYPO3\\CMS\\Dbal\\Database\\DatabaseConnection', array('admin_get_charsets'));
23 $GLOBALS['TYPO3_DB']->expects($this->any())->method('admin_get_charsets')->will($this->returnValue(array('utf8' => array())));
24 $GLOBALS['TYPO3_DB']->initialize();
25 $GLOBALS['TYPO3_DB']->lastHandlerKey = '_DEFAULT';
26 }
27
28 /**
29 * Cleans up the environment after running a test.
30 */
31 public function tearDown() {
32 // Clear DBAL-generated cache files
33 $GLOBALS['TYPO3_DB']->clearCachedFieldInfo();
34 // Delete temporary files
35 foreach ($this->temporaryFiles as $filename) {
36 unlink($filename);
37 }
38 parent::tearDown();
39 }
40
41 /**
42 * Cleans a SQL query.
43 *
44 * @param mixed $sql
45 * @return mixed (string or array)
46 */
47 private function cleanSql($sql) {
48 if (!is_string($sql)) {
49 return $sql;
50 }
51 $sql = str_replace('
52 ', ' ', $sql);
53 $sql = preg_replace('/\\s+/', ' ', $sql);
54 return trim($sql);
55 }
56
57 /**
58 * Creates a fake extension with a given table definition.
59 *
60 * @param string $tableDefinition SQL script to create the extension's tables
61 * @throws \RuntimeException
62 * @return void
63 */
64 protected function createFakeExtension($tableDefinition) {
65 // Prepare a fake extension configuration
66 $ext_tables = \TYPO3\CMS\Core\Utility\GeneralUtility::tempnam('ext_tables');
67 if (!\TYPO3\CMS\Core\Utility\GeneralUtility::writeFile($ext_tables, $tableDefinition)) {
68 throw new \RuntimeException('Can\'t write temporary ext_tables file.');
69 }
70 $this->temporaryFiles[] = $ext_tables;
71 $GLOBALS['TYPO3_LOADED_EXT'] = array('test_dbal' => array(
72 'ext_tables.sql' => $ext_tables
73 ));
74 // Append our test table to the list of existing tables
75 $GLOBALS['TYPO3_DB']->clearCachedFieldInfo();
76 $GLOBALS['TYPO3_DB']->initialize();
77 }
78
79 /**
80 * @test
81 * @see http://forge.typo3.org/issues/21502
82 */
83 public function concatCanBeParsedAfterLikeOperator() {
84 $query = $this->cleanSql($GLOBALS['TYPO3_DB']->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)'));
85 $expected = 'SELECT * FROM sys_refindex, tx_dam_file_tracking WHERE sys_refindex.tablename = \'tx_dam_file_tracking\'';
86 $expected .= ' AND sys_refindex.ref_string LIKE CONCAT(tx_dam_file_tracking.file_path, tx_dam_file_tracking.file_name)';
87 $this->assertEquals($expected, $query);
88 }
89
90 /**
91 * @test
92 * @see http://forge.typo3.org/issues/20346
93 */
94 public function floatNumberCanBeStoredInDatabase() {
95 $this->createFakeExtension('
96 CREATE TABLE tx_test_dbal (
97 foo double default \'0\',
98 foobar int default \'0\'
99 );
100 ');
101 $data = array(
102 'foo' => 99.12,
103 'foobar' => -120
104 );
105 $query = $this->cleanSql($GLOBALS['TYPO3_DB']->INSERTquery('tx_test_dbal', $data));
106 $expected = 'INSERT INTO tx_test_dbal ( foo, foobar ) VALUES ( \'99.12\', \'-120\' )';
107 $this->assertEquals($expected, $query);
108 }
109
110 /**
111 * @test
112 * @see http://forge.typo3.org/issues/20427
113 */
114 public function positive64BitIntegerIsSupported() {
115 $this->createFakeExtension('
116 CREATE TABLE tx_test_dbal (
117 foo int default \'0\',
118 foobar bigint default \'0\'
119 );
120 ');
121 $data = array(
122 'foo' => 9223372036854775807,
123 'foobar' => 9223372036854775807
124 );
125 $query = $this->cleanSql($GLOBALS['TYPO3_DB']->INSERTquery('tx_test_dbal', $data));
126 $expected = 'INSERT INTO tx_test_dbal ( foo, foobar ) VALUES ( \'9223372036854775807\', \'9223372036854775807\' )';
127 $this->assertEquals($expected, $query);
128 }
129
130 /**
131 * @test
132 * @see http://forge.typo3.org/issues/20427
133 */
134 public function negative64BitIntegerIsSupported() {
135 $this->markTestSkipped('This test causes problems on some systems.');
136 $this->createFakeExtension('
137 CREATE TABLE tx_test_dbal (
138 foo int default \'0\',
139 foobar bigint default \'0\'
140 );
141 ');
142 $data = array(
143 'foo' => -9.2233720368548E+18,
144 'foobar' => -9.2233720368548E+18
145 );
146 $query = $this->cleanSql($GLOBALS['TYPO3_DB']->INSERTquery('tx_test_dbal', $data));
147 $expected = 'INSERT INTO tx_test_dbal ( foo, foobar ) VALUES ( \'-9223372036854775808\', \'-9223372036854775808\' )';
148 $this->assertEquals($expected, $query);
149 }
150
151 /**
152 * @test
153 */
154 public function sqlForInsertWithMultipleRowsIsValid() {
155 $fields = array('uid', 'pid', 'title', 'body');
156 $rows = array(
157 array('1', '2', 'Title #1', 'Content #1'),
158 array('3', '4', 'Title #2', 'Content #2'),
159 array('5', '6', 'Title #3', 'Content #3')
160 );
161 $query = $this->cleanSql($GLOBALS['TYPO3_DB']->INSERTmultipleRows('tt_content', $fields, $rows));
162 $expected = 'INSERT INTO tt_content (uid, pid, title, body) VALUES ';
163 $expected .= '(\'1\', \'2\', \'Title #1\', \'Content #1\'), ';
164 $expected .= '(\'3\', \'4\', \'Title #2\', \'Content #2\'), ';
165 $expected .= '(\'5\', \'6\', \'Title #3\', \'Content #3\')';
166 $this->assertEquals($expected, $query);
167 }
168
169 /**
170 * @test
171 * @see http://forge.typo3.org/issues/16708
172 */
173 public function minFunctionAndInOperatorCanBeParsed() {
174 $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery('*', 'pages', 'MIN(uid) IN (1,2,3,4)'));
175 $expected = 'SELECT * FROM pages WHERE MIN(uid) IN (1,2,3,4)';
176 $this->assertEquals($expected, $query);
177 }
178
179 /**
180 * @test
181 * @see http://forge.typo3.org/issues/16708
182 */
183 public function maxFunctionAndInOperatorCanBeParsed() {
184 $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery('*', 'pages', 'MAX(uid) IN (1,2,3,4)'));
185 $expected = 'SELECT * FROM pages WHERE MAX(uid) IN (1,2,3,4)';
186 $this->assertEquals($expected, $query);
187 }
188
189 /**
190 * @test
191 * @see http://forge.typo3.org/issues/21514
192 */
193 public function likeBinaryOperatorIsKept() {
194 $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery('*', 'tt_content', 'bodytext LIKE BINARY \'test\''));
195 $expected = 'SELECT * FROM tt_content WHERE bodytext LIKE BINARY \'test\'';
196 $this->assertEquals($expected, $query);
197 }
198
199 /**
200 * @test
201 * @see http://forge.typo3.org/issues/21514
202 */
203 public function notLikeBinaryOperatorIsKept() {
204 $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery('*', 'tt_content', 'bodytext NOT LIKE BINARY \'test\''));
205 $expected = 'SELECT * FROM tt_content WHERE bodytext NOT LIKE BINARY \'test\'';
206 $this->assertEquals($expected, $query);
207 }
208
209 ///////////////////////////////////////
210 // Tests concerning prepared queries
211 ///////////////////////////////////////
212 /**
213 * @test
214 * @see http://forge.typo3.org/issues/23374
215 */
216 public function similarNamedParametersAreProperlyReplaced() {
217 $sql = 'SELECT * FROM cache WHERE tag = :tag1 OR tag = :tag10 OR tag = :tag100';
218 $parameterValues = array(
219 ':tag1' => 'tag-one',
220 ':tag10' => 'tag-two',
221 ':tag100' => 'tag-three'
222 );
223 $className = self::buildAccessibleProxy('TYPO3\\CMS\\Core\\Database\\PreparedStatement');
224 $query = $sql;
225 $precompiledQueryParts = array();
226 $statement = new $className($sql, 'cache');
227 $statement->bindValues($parameterValues);
228 $parameters = $statement->_get('parameters');
229 $statement->_callRef('replaceValuesInQuery', $query, $precompiledQueryParts, $parameters);
230 $expected = 'SELECT * FROM cache WHERE tag = \'tag-one\' OR tag = \'tag-two\' OR tag = \'tag-three\'';
231 $this->assertEquals($expected, $query);
232 }
233
234 }