TYPO3 API  SVNRelease
sqlParserGeneralTest.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003  *  Copyright notice
00004  *
00005  *  (c) 2009 Xavier Perseguers <typo3@perseguers.ch>
00006  *  All rights reserved
00007  *
00008  *  This script is part of the TYPO3 project. The TYPO3 project is
00009  *  free software; you can redistribute it and/or modify
00010  *  it under the terms of the GNU General Public License as published by
00011  *  the Free Software Foundation; either version 2 of the License, or
00012  *  (at your option) any later version.
00013  *
00014  *  The GNU General Public License can be found at
00015  *  http://www.gnu.org/copyleft/gpl.html.
00016  *
00017  *  This script is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  *  GNU General Public License for more details.
00021  *
00022  *  This copyright notice MUST APPEAR in all copies of the script!
00023  ***************************************************************/
00024 
00025 
00026 require_once('BaseTestCase.php');
00027 
00028 /**
00029  * Testcase for class ux_t3lib_sqlparser
00030  *
00031  * $Id$
00032  *
00033  * @author Xavier Perseguers <typo3@perseguers.ch>
00034  *
00035  * @package TYPO3
00036  * @subpackage dbal
00037  */
00038 class sqlParserGeneralTest extends BaseTestCase {
00039 
00040     /**
00041      * @var ux_t3lib_sqlparser (extended to make protected methods public)
00042      */
00043     protected $fixture;
00044 
00045     /**
00046      * Prepares the environment before running a test.
00047      */
00048     public function setUp() {
00049         $className = self::buildAccessibleProxy('ux_t3lib_sqlparser');
00050         $this->fixture = new $className;
00051     }
00052 
00053     /**
00054      * Cleans up the environment after running a test.
00055      */
00056     public function tearDown() {
00057         unset($this->fixture);
00058     }
00059 
00060     /**
00061      * Cleans a SQL query.
00062      *
00063      * @param mixed $sql
00064      * @return mixed (string or array)
00065      */
00066     private function cleanSql($sql) {
00067         if (!is_string($sql)) {
00068             return $sql;
00069         }
00070 
00071         $sql = str_replace("\n", ' ', $sql);
00072         $sql = preg_replace('/\s+/', ' ', $sql);
00073         return trim($sql);
00074     }
00075 
00076     /**
00077      * @test
00078      */
00079     public function canExtractPartsOfAQuery() {
00080         $parseString = "SELECT   *\nFROM pages WHERE pid IN (1,2,3,4)";
00081         $regex = '^SELECT[[:space:]]+(.*)[[:space:]]+';
00082         $trimAll = TRUE;
00083         $fields = $this->fixture->_callRef('nextPart', $parseString, $regex, $trimAll);
00084 
00085         $this->assertEquals(
00086             '*',
00087             $fields
00088         );
00089         $this->assertEquals(
00090             'FROM pages WHERE pid IN (1,2,3,4)',
00091             $parseString
00092         );
00093 
00094         $regex = '^FROM ([^)]+) WHERE';
00095         $table = $this->fixture->_callRef('nextPart', $parseString, $regex);
00096 
00097         $this->assertEquals(
00098             'pages',
00099             $table
00100         );
00101         $this->assertEquals(
00102             'pages WHERE pid IN (1,2,3,4)',
00103             $parseString
00104         );
00105     }
00106 
00107     /**
00108      * @test
00109      */
00110     public function canGetIntegerValue() {
00111         $parseString = '1024';
00112         $value = $this->fixture->_callRef('getValue', $parseString);
00113         $expected = array(1024);
00114 
00115         $this->assertEquals($expected, $value);
00116     }
00117 
00118     /**
00119      * @test
00120      * @see http://bugs.typo3.org/view.php?id=13104
00121      */
00122     public function canGetStringValue() {
00123         $parseString = '"some owner\\\'s string"';
00124         $value = $this->fixture->_callRef('getValue', $parseString);
00125         $expected = array('some owner\'s string', '"');
00126 
00127         $this->assertEquals($expected, $value);
00128     }
00129 
00130     /**
00131      * @test
00132      * @see http://bugs.typo3.org/view.php?id=13104
00133      */
00134     public function canGetStringValueWithSingleQuote() {
00135         $parseString = "'some owner\'s string'";
00136         $value = $this->fixture->_callRef('getValue', $parseString);
00137         $expected = array('some owner\'s string', "'");
00138 
00139         $this->assertEquals($expected, $value);
00140     }
00141 
00142     /**
00143      * @test
00144      * @see http://bugs.typo3.org/view.php?id=13104
00145      */
00146     public function canGetStringValueWithDoubleQuote() {
00147         $parseString = '"the \"owner\" is here"';
00148         $value = $this->fixture->_callRef('getValue', $parseString);
00149         $expected = array('the "owner" is here', '"');
00150 
00151         $this->assertEquals($expected, $value);
00152     }
00153 
00154     /**
00155      * @test
00156      */
00157     public function canGetListOfValues() {
00158         $parseString = '( 1,   2, 3  ,4)';
00159         $operator = 'IN';
00160         $values = $this->fixture->_callRef('getValue', $parseString, $operator);
00161         $expected = array(
00162             array(1),
00163             array(2),
00164             array(3),
00165             array(4)
00166         );
00167 
00168         $this->assertEquals($expected, $values);
00169     }
00170 
00171     /**
00172      * @test
00173      */
00174     public function parseWhereClauseReturnsArray() {
00175         $parseString = 'uid IN (1,2) AND (starttime < ' . time() . ' OR cruser_id + 10 < 20)';
00176         $where = $this->fixture->parseWhereClause($parseString);
00177 
00178         $this->assertTrue(is_array($where), $where);
00179         $this->assertTrue(empty($parseString), 'parseString is not empty');
00180     }
00181 
00182     /**
00183      * @test
00184      */
00185     public function canSelectAllFieldsFromPages() {
00186         $sql = 'SELECT * FROM pages';
00187         $expected = $sql;
00188         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00189 
00190         $this->assertEquals($expected, $actual);
00191     }
00192 
00193     /**
00194      * @test
00195      * http://bugs.typo3.org/view.php?id=13504
00196      */
00197     public function canParseTruncateTable() {
00198         $sql = 'TRUNCATE TABLE be_users';
00199         $expected = $sql;
00200         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00201 
00202         $this->assertEquals($expected, $actual);
00203     }
00204 
00205     /**
00206      * @test
00207      * @see http://bugs.typo3.org/view.php?id=13412
00208      */
00209     public function canParseAndCompileBetweenOperator() {
00210         $parseString = '((scheduled BETWEEN 1265068628 AND 1265068828 ) OR scheduled <= 1265068728) AND NOT exec_time AND NOT process_id AND page_id=1 AND parameters_hash = \'854e9a2a77\'';
00211         $where = $this->fixture->parseWhereClause($parseString);
00212 
00213         $this->assertTrue(is_array($where), $where);
00214         $this->assertTrue(empty($parseString), 'parseString is not empty');
00215 
00216         $whereClause = $this->cleanSql($this->fixture->compileWhereClause($where));
00217         $expected = '((scheduled BETWEEN 1265068628 AND 1265068828) OR scheduled <= 1265068728) AND NOT exec_time AND NOT process_id AND page_id = 1 AND parameters_hash = \'854e9a2a77\'';
00218         $this->assertEquals($expected, $whereClause);
00219     }
00220 
00221     /**
00222      * @test
00223      * http://bugs.typo3.org/view.php?id=13430
00224      */
00225     public function canParseInsertWithoutSpaceAfterValues() {
00226         $parseString = "INSERT INTO static_country_zones VALUES('483', '0', 'NL', 'NLD', '528', 'DR', 'Drenthe', '');";
00227         $components = $this->fixture->_callRef('parseINSERT', $parseString);
00228 
00229         $this->assertTrue(is_array($components), $components);
00230         $insert = $this->cleanSql($this->fixture->_callRef('compileINSERT', $components));
00231         $expected = "INSERT INTO static_country_zones VALUES ('483', '0', 'NL', 'NLD', '528', 'DR', 'Drenthe', '')";
00232         $this->assertEquals($expected, $insert);
00233     }
00234 
00235     /**
00236      * @test
00237      * http://bugs.typo3.org/view.php?id=13430
00238      */
00239     public function canParseInsertWithSpaceAfterValues() {
00240         $parseString = "INSERT INTO static_country_zones VALUES ('483', '0', 'NL', 'NLD', '528', 'DR', 'Drenthe', '');";
00241         $components = $this->fixture->_callRef('parseINSERT', $parseString);
00242 
00243         $this->assertTrue(is_array($components), $components);
00244         $insert = $this->cleanSql($this->fixture->_callRef('compileINSERT', $components));
00245         $expected = "INSERT INTO static_country_zones VALUES ('483', '0', 'NL', 'NLD', '528', 'DR', 'Drenthe', '')";
00246         $this->assertEquals($expected, $insert);
00247     }
00248 
00249     /**
00250      * @test
00251      */
00252     public function canParseInsertWithFields() {
00253         $parseString = 'INSERT INTO static_territories (uid, pid, tr_iso_nr, tr_parent_iso_nr, tr_name_en) ';
00254         $parseString .= "VALUES ('1', '0', '2', '0', 'Africa');";
00255         $components = $this->fixture->_callRef('parseINSERT', $parseString);
00256 
00257         $this->assertTrue(is_array($components), $components);
00258         $insert = $this->cleanSql($this->fixture->_callRef('compileINSERT', $components));
00259         $expected = 'INSERT INTO static_territories (uid, pid, tr_iso_nr, tr_parent_iso_nr, tr_name_en) ';
00260         $expected .= "VALUES ('1', '0', '2', '0', 'Africa')";
00261         $this->assertEquals($expected, $insert);
00262     }
00263 
00264     /**
00265      * @test
00266      * http://bugs.typo3.org/view.php?id=13209
00267      */
00268     public function canParseExtendedInsert() {
00269         $parseString = "INSERT INTO static_territories VALUES ('1', '0', '2', '0', 'Africa'),('2', '0', '9', '0', 'Oceania')," .
00270                 "('3', '0', '19', '0', 'Americas'),('4', '0', '142', '0', 'Asia');";
00271         $components = $this->fixture->_callRef('parseINSERT', $parseString);
00272 
00273         $this->assertTrue(is_array($components), $components);
00274         $insert = $this->cleanSql($this->fixture->_callRef('compileINSERT', $components));
00275         $expected = "INSERT INTO static_territories VALUES ('1', '0', '2', '0', 'Africa'), ('2', '0', '9', '0', 'Oceania'), " .
00276                 "('3', '0', '19', '0', 'Americas'), ('4', '0', '142', '0', 'Asia')";
00277         $this->assertEquals($expected, $insert);
00278     }
00279 
00280     /**
00281      * @test
00282      * http://bugs.typo3.org/view.php?id=13209
00283      */
00284     public function canParseExtendedInsertWithFields() {
00285         $parseString = 'INSERT INTO static_territories (uid, pid, tr_iso_nr, tr_parent_iso_nr, tr_name_en) ';
00286         $parseString .= "VALUES ('1', '0', '2', '0', 'Africa'),('2', '0', '9', '0', 'Oceania');";
00287         $components = $this->fixture->_callRef('parseINSERT', $parseString);
00288 
00289         $this->assertTrue(is_array($components), $components);
00290         $insert = $this->cleanSql($this->fixture->_callRef('compileINSERT', $components));
00291         $expected = 'INSERT INTO static_territories (uid, pid, tr_iso_nr, tr_parent_iso_nr, tr_name_en) ';
00292         $expected .= "VALUES ('1', '0', '2', '0', 'Africa'), ('2', '0', '9', '0', 'Oceania')";
00293         $this->assertEquals($expected, $insert);
00294     }
00295 
00296     /**
00297      * @test
00298      * @see http://bugs.typo3.org/view.php?id=6196
00299      */
00300     public function canParseIfNullOperator() {
00301         $parseString = 'IFNULL(tt_news_cat_mm.uid_foreign,0) IN (21,22)';
00302         $whereParts = $this->fixture->parseWhereClause($parseString);
00303 
00304         $this->assertTrue(is_array($whereParts), $whereParts);
00305         $this->assertTrue(empty($parseString), 'parseString is not empty');
00306     }
00307 
00308     /**
00309      * @test
00310      * @see http://bugs.typo3.org/view.php?id=6196
00311      */
00312     public function canParseIfNullOperatorWithAdditionalClauses() {
00313         $parseString = '1=1 AND IFNULL(tt_news_cat_mm.uid_foreign,0) IN (21,22) AND tt_news.sys_language_uid IN (0,-1) ';
00314         $parseString .= 'AND tt_news.pid > 0 AND tt_news.pid IN (61) AND tt_news.deleted=0 AND tt_news.t3ver_state<=0 ';
00315         $parseString .= 'AND tt_news.hidden=0 AND tt_news.starttime<=1266065460 AND (tt_news.endtime=0 OR tt_news.endtime>1266065460) ';
00316         $parseString .= 'AND (tt_news.fe_group=\'\' OR tt_news.fe_group IS NULL OR tt_news.fe_group=\'0\' ';
00317         $parseString .= 'OR (tt_news.fe_group LIKE \'%,0,%\' OR tt_news.fe_group LIKE \'0,%\' OR tt_news.fe_group LIKE \'%,0\' ';
00318         $parseString .= 'OR tt_news.fe_group=\'0\') OR (tt_news.fe_group LIKE \'%,-1,%\' OR tt_news.fe_group LIKE \'-1,%\' ';
00319         $parseString .= 'OR tt_news.fe_group LIKE \'%,-1\' OR tt_news.fe_group=\'-1\'))';
00320         $whereParts = $this->fixture->parseWhereClause($parseString);
00321 
00322         $this->assertTrue(is_array($whereParts), $whereParts);
00323         $this->assertTrue(empty($parseString), 'parseString is not empty');
00324     }
00325 
00326     /**
00327      * @test
00328      * @see http://bugs.typo3.org/view.php?id=6196
00329      */
00330     public function canCompileIfNullOperator() {
00331         $parseString = 'SELECT * FROM tx_irfaq_q_cat_mm WHERE IFNULL(tx_irfaq_q_cat_mm.uid_foreign,0) = 1';
00332         $components = $this->fixture->_callRef('parseSELECT', $parseString);
00333 
00334         $this->assertTrue(is_array($components), $components);
00335         $select = $this->cleanSql($this->fixture->_callRef('compileSELECT', $components));
00336         $expected = 'SELECT * FROM tx_irfaq_q_cat_mm WHERE IFNULL(tx_irfaq_q_cat_mm.uid_foreign, 0) = 1';
00337         $this->assertEquals($expected, $select);
00338     }
00339 
00340     /**
00341      * @test
00342      * @see http://bugs.typo3.org/view.php?id=14456
00343      */
00344     public function canParseAlterEngineStatement() {
00345         $parseString = 'ALTER TABLE tx_realurl_pathcache ENGINE=InnoDB';
00346         $components = $this->fixture->_callRef('parseALTERTABLE', $parseString);
00347 
00348         $this->assertTrue(is_array($components), $components);
00349         $alterTable = $this->cleanSql($this->fixture->_callRef('compileALTERTABLE', $components));
00350         $expected = 'ALTER TABLE tx_realurl_pathcache ENGINE = InnoDB';
00351         $this->assertTrue(is_array($alterTable), $alterTable);
00352         $this->assertEquals($expected, $alterTable[0]);
00353     }
00354 
00355     /**
00356      * @test
00357      * @see http://bugs.typo3.org/view.php?id=14496
00358      */
00359     public function canParseAlterCharacterSetStatement() {
00360         $parseString = 'ALTER TABLE `index_phash` DEFAULT CHARACTER SET utf8';
00361         $components = $this->fixture->_callRef('parseALTERTABLE', $parseString);
00362 
00363         $this->assertTrue(is_array($components), $components);
00364         $alterTable = $this->cleanSql($this->fixture->_callRef('compileALTERTABLE', $components));
00365         $expected = 'ALTER TABLE index_phash DEFAULT CHARACTER SET utf8';
00366         $this->assertTrue(is_array($alterTable), $alterTable);
00367         $this->assertEquals($expected, $alterTable[0]);
00368     }
00369 
00370     /**
00371      * @test
00372      * @see http://bugs.typo3.org/view.php?id=14985
00373      */
00374     public function canParseFindInSetStatement() {
00375         $parseString = 'SELECT * FROM fe_users WHERE FIND_IN_SET(10, usergroup)';
00376         $components = $this->fixture->_callRef('parseSELECT', $parseString);
00377 
00378         $this->assertTrue(is_array($components), $components);
00379         $selectTable = $this->cleanSql($this->fixture->_callRef('compileSELECT', $components));
00380         $expected = 'SELECT * FROM fe_users WHERE FIND_IN_SET(10, usergroup)';
00381         $this->assertEquals($expected, $selectTable);
00382     }
00383 
00384     ///////////////////////////////////////
00385     // Tests concerning JOINs
00386     ///////////////////////////////////////
00387 
00388     /**
00389      * @test
00390      */
00391     public function parseFromTablesWithInnerJoinReturnsArray() {
00392         $parseString = 'be_users INNER JOIN pages ON pages.cruser_id = be_users.uid';
00393         $tables = $this->fixture->parseFromTables($parseString);
00394 
00395         $this->assertTrue(is_array($tables), $tables);
00396         $this->assertTrue(empty($parseString), 'parseString is not empty');
00397     }
00398 
00399     /**
00400      * @test
00401      */
00402     public function parseFromTablesWithLeftOuterJoinReturnsArray() {
00403         $parseString = 'be_users LEFT OUTER JOIN pages ON be_users.uid = pages.cruser_id';
00404         $tables = $this->fixture->parseFromTables($parseString);
00405 
00406         $this->assertTrue(is_array($tables), $tables);
00407         $this->assertTrue(empty($parseString), 'parseString is not empty');
00408     }
00409 
00410     /**
00411      * @test
00412      * @see http://bugs.typo3.org/view.php?id=12596
00413      */
00414     public function parseFromTablesWithRightOuterJoinReturnsArray() {
00415         $parseString = 'tx_powermail_fieldsets RIGHT JOIN tt_content ON tx_powermail_fieldsets.tt_content = tt_content.uid';
00416         $tables = $this->fixture->parseFromTables($parseString);
00417 
00418         $this->assertTrue(is_array($tables), $tables);
00419         $this->assertTrue(empty($parseString), 'parseString is not empty');
00420     }
00421 
00422     /**
00423      * @test
00424      */
00425     public function parseFromTablesWithMultipleJoinsReturnsArray() {
00426         $parseString = 'be_users LEFT OUTER JOIN pages ON be_users.uid = pages.cruser_id INNER JOIN cache_pages cp ON cp.page_id = pages.uid';
00427         $tables = $this->fixture->parseFromTables($parseString);
00428 
00429         $this->assertTrue(is_array($tables), $tables);
00430         $this->assertTrue(empty($parseString), 'parseString is not empty');
00431     }
00432 
00433     /**
00434      * @test
00435      * @see http://bugs.typo3.org/view.php?id=12596
00436      */
00437     public function parseFromTablesWithMultipleJoinsAndParenthesesReturnsArray() {
00438         $parseString = 'tx_powermail_fieldsets RIGHT JOIN tt_content ON tx_powermail_fieldsets.tt_content = tt_content.uid LEFT JOIN tx_powermail_fields ON tx_powermail_fieldsets.uid = tx_powermail_fields.fieldset';
00439         $tables = $this->fixture->parseFromTables($parseString);
00440 
00441         $this->assertTrue(is_array($tables), $tables);
00442         $this->assertTrue(empty($parseString), 'parseString is not empty');
00443     }
00444 
00445     /**
00446      * @test
00447      */
00448     public function canUseInnerJoinInSelect() {
00449         $sql = 'SELECT pages.uid, be_users.username FROM be_users INNER JOIN pages ON pages.cruser_id = be_users.uid';
00450         $expected = 'SELECT pages.uid, be_users.username FROM be_users INNER JOIN pages ON pages.cruser_id=be_users.uid';
00451         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00452 
00453         $this->assertEquals($expected, $actual);
00454     }
00455 
00456     /**
00457      * @test
00458      */
00459     public function canUseMultipleInnerJoinsInSelect() {
00460         $sql = 'SELECT * FROM tt_news_cat INNER JOIN tt_news_cat_mm ON tt_news_cat.uid = tt_news_cat_mm.uid_foreign INNER JOIN tt_news ON tt_news.uid = tt_news_cat_mm.uid_local';
00461         $expected = 'SELECT * FROM tt_news_cat INNER JOIN tt_news_cat_mm ON tt_news_cat.uid=tt_news_cat_mm.uid_foreign INNER JOIN tt_news ON tt_news.uid=tt_news_cat_mm.uid_local';
00462         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00463 
00464         $this->assertEquals($expected, $actual);
00465     }
00466 
00467     /**
00468      * @test
00469      * @see http://bugs.typo3.org/view.php?id=14182
00470      */
00471     public function canParseMultipleJoinConditions() {
00472         $sql = 'SELECT * FROM T1 LEFT OUTER JOIN T2 ON T2.pid = T1.uid AND T2.size = 4 WHERE T1.cr_userid = 1';
00473         $expected = 'SELECT * FROM T1 LEFT OUTER JOIN T2 ON T2.pid=T1.uid AND T2.size=4 WHERE T1.cr_userid = 1';
00474         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00475 
00476         $this->assertEquals($expected, $actual);
00477     }
00478 
00479     /**
00480      * @test
00481      * @see http://bugs.typo3.org/view.php?id=14182
00482      */
00483     public function canParseMultipleJoinConditionsWithLessThanOperator() {
00484         $sql = 'SELECT * FROM T1 LEFT OUTER JOIN T2 ON T2.size < 4 OR T2.pid = T1.uid WHERE T1.cr_userid = 1';
00485         $expected = 'SELECT * FROM T1 LEFT OUTER JOIN T2 ON T2.size<4 OR T2.pid=T1.uid WHERE T1.cr_userid = 1';
00486         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00487 
00488         $this->assertEquals($expected, $actual);
00489     }
00490 
00491     ///////////////////////////////////////
00492     // Tests concerning DB management
00493     ///////////////////////////////////////
00494 
00495     /**
00496      * @test
00497      * @see http://bugs.typo3.org/view.php?id=4466
00498      */
00499     public function indexMayContainALengthRestrictionInCreateTable() {
00500         $parseString = '
00501             CREATE TABLE tx_realurl_uniqalias (
00502                 uid int(11) NOT NULL auto_increment,
00503                 tstamp int(11) DEFAULT \'0\' NOT NULL,
00504                 tablename varchar(60) DEFAULT \'\' NOT NULL,
00505                 field_alias varchar(255) DEFAULT \'\' NOT NULL,
00506                 field_id varchar(60) DEFAULT \'\' NOT NULL,
00507                 value_alias varchar(255) DEFAULT \'\' NOT NULL,
00508                 value_id int(11) DEFAULT \'0\' NOT NULL,
00509                 lang int(11) DEFAULT \'0\' NOT NULL,
00510                 expire int(11) DEFAULT \'0\' NOT NULL,
00511 
00512                 PRIMARY KEY (uid),
00513                 KEY tablename (tablename),
00514                 KEY bk_realurl01 (field_alias,field_id,value_id,lang,expire),
00515                 KEY bk_realurl02 (tablename,field_alias,field_id,value_alias(220),expire)
00516             );
00517         ';
00518 
00519         $createTables = $this->fixture->_callRef('parseCREATETABLE', $parseString);
00520         $this->assertTrue(is_array($createTables), $createTables);
00521     }
00522 
00523     /**
00524      * @test
00525      * @see http://bugs.typo3.org/view.php?id=16501
00526      */
00527     public function indexMayBeCreatedOnMultipleColumns() {
00528         $sql = '
00529             CREATE TABLE sys_registry (
00530                 uid int(11) unsigned NOT NULL auto_increment,
00531                 entry_namespace varchar(128) DEFAULT \'\' NOT NULL,
00532                 entry_key varchar(128) DEFAULT \'\' NOT NULL,
00533                 entry_value blob,
00534                 PRIMARY KEY (uid),
00535                 UNIQUE KEY entry_identifier (entry_namespace,entry_key)
00536             )
00537         ';
00538         $parseString = $sql;
00539 
00540         $createTables = $this->fixture->_callRef('parseCREATETABLE', $parseString);
00541         $this->assertTrue(is_array($createTables), $createTables);
00542 
00543         $actual = $this->fixture->_callRef('compileCREATETABLE', $createTables);
00544         $this->assertEquals($this->cleanSql($sql), $this->cleanSql($actual[0]));
00545     }
00546 
00547     /**
00548      * @test
00549      * @see http://bugs.typo3.org/view.php?id=12829
00550      */
00551     public function indexMayContainALengthRestrictionInAlterTable() {
00552         $parseString = 'ALTER TABLE tx_realurl_uniqalias ADD KEY bk_realurl02 (tablename,field_alias,field_id,value_alias(220),expire)';
00553         $alterTables = $this->fixture->_callRef('parseALTERTABLE', $parseString);
00554         $this->assertTrue(is_array($alterTables), $alterTables);
00555     }
00556 
00557     /**
00558      * @test
00559      * @see http://bugs.typo3.org/view.php?id=2186
00560      */
00561     public function canParseUniqueIndexCreation() {
00562         $sql = 'ALTER TABLE static_territories ADD UNIQUE uid (uid)';
00563         $expected = $sql;
00564         $alterTables = $this->fixture->_callRef('parseALTERTABLE', $sql);
00565         $queries = $this->fixture->compileSQL($alterTables);
00566 
00567         $this->assertTrue(is_array($queries), $queries);
00568         $this->assertTrue(count($queries) == 1, $queries);
00569         $this->assertEquals($expected, $queries[0]);
00570     }
00571 
00572     ///////////////////////////////////////
00573     // Tests concerning subqueries
00574     ///////////////////////////////////////
00575 
00576     /**
00577      * @test
00578      * @see http://bugs.typo3.org/view.php?id=12758
00579      */
00580     public function inWhereClauseSupportsSubquery() {
00581         $parseString = 'process_id IN (SELECT process_id FROM tx_crawler_process WHERE active=0 AND deleted=0)';
00582         $whereParts = $this->fixture->parseWhereClause($parseString);
00583 
00584         $this->assertTrue(is_array($whereParts), $whereParts);
00585         $this->assertTrue(empty($parseString), 'parseString is not empty');
00586     }
00587 
00588     /**
00589      * @test
00590      * @see http://bugs.typo3.org/view.php?id=12758
00591      */
00592     public function inWhereClauseWithSubqueryIsProperlyCompiled() {
00593         $sql = 'SELECT * FROM tx_crawler_queue WHERE process_id IN (SELECT process_id FROM tx_crawler_process WHERE active=0 AND deleted=0)';
00594         $expected = 'SELECT * FROM tx_crawler_queue WHERE process_id IN (SELECT process_id FROM tx_crawler_process WHERE active = 0 AND deleted = 0)';
00595         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00596 
00597         $this->assertEquals($expected, $actual);
00598     }
00599 
00600     /**
00601      * @test
00602      * @see http://bugs.typo3.org/view.php?id=12758
00603      */
00604     public function whereClauseSupportsExistsKeyword() {
00605         $parseString = 'EXISTS (SELECT * FROM tx_crawler_queue WHERE tx_crawler_queue.process_id = tx_crawler_process.process_id AND tx_crawler_queue.exec_time = 0)';
00606         $whereParts = $this->fixture->parseWhereClause($parseString);
00607 
00608         $this->assertTrue(is_array($whereParts), $whereParts);
00609         $this->assertTrue(empty($parseString), 'parseString is not empty');
00610     }
00611 
00612     /**
00613      * @test
00614      * @see http://bugs.typo3.org/view.php?id=12758
00615      */
00616     public function existsClauseIsProperlyCompiled() {
00617         $sql = 'SELECT * FROM tx_crawler_process WHERE active = 0 AND NOT EXISTS (SELECT * FROM tx_crawler_queue WHERE tx_crawler_queue.process_id = tx_crawler_process.process_id AND tx_crawler_queue.exec_time = 0)';
00618         $expected = 'SELECT * FROM tx_crawler_process WHERE active = 0 AND NOT EXISTS (SELECT * FROM tx_crawler_queue WHERE tx_crawler_queue.process_id = tx_crawler_process.process_id AND tx_crawler_queue.exec_time = 0)';
00619         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00620 
00621         $this->assertEquals($expected, $actual);
00622     }
00623 
00624     ///////////////////////////////////////
00625     // Tests concerning advanced operators
00626     ///////////////////////////////////////
00627 
00628     /**
00629      * @test
00630      * @see http://bugs.typo3.org/view.php?id=13135
00631      */
00632     public function caseWithBooleanConditionIsSupportedInFields() {
00633         $parseString = 'CASE WHEN 1>0 THEN 2 ELSE 1 END AS foo, other_column';
00634         $fieldList = $this->fixture->parseFieldList($parseString);
00635 
00636         $this->assertTrue(is_array($fieldList), $fieldList);
00637         $this->assertTrue(empty($parseString), 'parseString is not empty');
00638     }
00639 
00640     /**
00641      * @test
00642      * @see http://bugs.typo3.org/view.php?id=13135
00643      */
00644     public function caseWithBooleanConditionIsProperlyCompiled() {
00645         $sql = 'SELECT CASE WHEN 1>0 THEN 2 ELSE 1 END AS foo, other_column FROM mytable';
00646         $expected = 'SELECT CASE WHEN 1 > 0 THEN 2 ELSE 1 END AS foo, other_column FROM mytable';
00647         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00648 
00649         $this->assertEquals($expected, $actual);
00650     }
00651 
00652     /**
00653      * @test
00654      * @see http://bugs.typo3.org/view.php?id=13135
00655      */
00656     public function caseWithMultipleWhenIsSupportedInFields() {
00657         $parseString = 'CASE column WHEN 1 THEN \'one\' WHEN 2 THEN \'two\' ELSE \'out of range\' END AS number';
00658         $fieldList = $this->fixture->parseFieldList($parseString);
00659 
00660         $this->assertTrue(is_array($fieldList), $fieldList);
00661         $this->assertTrue(empty($parseString), 'parseString is not empty');
00662     }
00663 
00664     /**
00665      * @test
00666      * @see http://bugs.typo3.org/view.php?id=13135
00667      */
00668     public function caseWithMultipleWhenIsProperlyCompiled() {
00669         $sql = 'SELECT CASE column WHEN 1 THEN \'one\' WHEN 2 THEN \'two\' ELSE \'out of range\' END AS number FROM mytable';
00670         $expected = 'SELECT CASE column WHEN 1 THEN \'one\' WHEN 2 THEN \'two\' ELSE \'out of range\' END AS number FROM mytable';
00671         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00672 
00673         $this->assertEquals($expected, $actual);
00674     }
00675 
00676     /**
00677      * @test
00678      * @see http://bugs.typo3.org/view.php?id=13134
00679      */
00680     public function locateIsSupported() {
00681         $sql = 'SELECT * FROM tx_templavoila_tmplobj WHERE LOCATE(\'(fce)\', datastructure)>0';
00682         $expected = 'SELECT * FROM tx_templavoila_tmplobj WHERE LOCATE(\'(fce)\', datastructure) > 0';
00683         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00684 
00685         $this->assertEquals($expected, $actual);
00686     }
00687 
00688     /**
00689      * @test
00690      * @see http://bugs.typo3.org/view.php?id=13134
00691      */
00692     public function locateWithPositionIsSupported() {
00693         $sql = 'SELECT * FROM tx_templavoila_tmplobj WHERE LOCATE(\'(fce)\'  , datastructure  ,10)>0';
00694         $expected = 'SELECT * FROM tx_templavoila_tmplobj WHERE LOCATE(\'(fce)\', datastructure, 10) > 0';
00695         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00696 
00697         $this->assertEquals($expected, $actual);
00698     }
00699 
00700     /**
00701      * @test
00702      * @see http://bugs.typo3.org/view.php?id=13134
00703      * @see http://bugs.typo3.org/view.php?id=13135
00704      */
00705     public function locateWithinCaseIsSupported() {
00706         $sql = 'SELECT *, CASE WHEN LOCATE(\'(fce)\', datastructure)>0 THEN 2 ELSE 1 END AS scope FROM tx_templavoila_tmplobj';
00707         $expected = 'SELECT *, CASE WHEN LOCATE(\'(fce)\', datastructure) > 0 THEN 2 ELSE 1 END AS scope FROM tx_templavoila_tmplobj';
00708         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00709 
00710         $this->assertEquals($expected, $actual);
00711     }
00712 
00713     ///////////////////////////////////////
00714     // Tests concerning prepared queries
00715     ///////////////////////////////////////
00716 
00717     /**
00718      * @test
00719      * @see http://bugs.typo3.org/view.php?id=15457
00720      */
00721     public function namedPlaceholderIsSupported() {
00722         $sql = 'SELECT * FROM pages WHERE pid = :pid ORDER BY title';
00723         $expected = 'SELECT * FROM pages WHERE pid = :pid ORDER BY title';
00724         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00725 
00726         $this->assertEquals($expected, $actual);
00727     }
00728 
00729     /**
00730      * @test
00731      * @see http://bugs.typo3.org/view.php?id=15457
00732      */
00733     public function questionMarkPlaceholderIsSupported() {
00734         $sql = 'SELECT * FROM pages WHERE pid = ? ORDER BY title';
00735         $expected = 'SELECT * FROM pages WHERE pid = ? ORDER BY title';
00736         $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
00737 
00738         $this->assertEquals($expected, $actual);
00739     }
00740 
00741     /**
00742      * @test
00743      * @see http://bugs.typo3.org/view.php?id=15457
00744      */
00745     public function parametersAreReferenced() {
00746         $sql = 'SELECT * FROM pages WHERE pid = :pid1 OR pid = :pid2';
00747         $components = $this->fixture->_callRef('parseSELECT', $sql);
00748 
00749         $this->assertTrue(is_array($components['parameters']), 'References to parameters not found');
00750         $this->assertEquals(2, count($components['parameters']));
00751         $this->assertTrue(is_array($components['parameters']), 'References to parameters not found');
00752         $this->assertTrue(isset($components['parameters'][':pid1']));
00753         $this->assertTrue(isset($components['parameters'][':pid2']));
00754     }
00755 
00756     /**
00757      * @test
00758      * @see http://bugs.typo3.org/view.php?id=15457
00759      */
00760     public function sameParameterIsReferencedInSubquery() {
00761         $sql = 'SELECT * FROM pages WHERE uid = :pageId OR uid IN (SELECT uid FROM pages WHERE pid = :pageId)';
00762         $pageId = 12;
00763 
00764         $components = $this->fixture->_callRef('parseSELECT', $sql);
00765         $components['parameters'][':pageId'][0] = $pageId;
00766         $query = $this->cleanSql($this->fixture->_callRef('compileSELECT', $components));
00767         $expected = 'SELECT * FROM pages WHERE uid = 12 OR uid IN (SELECT uid FROM pages WHERE pid = 12)';
00768 
00769         $this->assertEquals($expected, $query);
00770     }
00771 
00772     /**
00773      * @test
00774      * @see http://bugs.typo3.org/view.php?id=15457
00775      */
00776     public function namedParametersMayBeSafelyReplaced() {
00777         $sql = 'SELECT * FROM pages WHERE pid = :pid AND title NOT LIKE \':pid\'';
00778         $pid = 12;
00779 
00780         $components = $this->fixture->_callRef('parseSELECT', $sql);
00781         $components['parameters'][':pid'][0] = $pid;
00782         $query = $this->cleanSql($this->fixture->_callRef('compileSELECT', $components));
00783         $expected = 'SELECT * FROM pages WHERE pid = ' . $pid . ' AND title NOT LIKE \':pid\'';
00784 
00785         $this->assertEquals($expected, $query);
00786     }
00787 
00788     /**
00789      * @test
00790      * @see http://bugs.typo3.org/view.php?id=15457
00791      */
00792     public function questionMarkParametersMayBeSafelyReplaced() {
00793         $sql = 'SELECT * FROM pages WHERE pid = ? AND timestamp < ? AND title != \'How to test?\'';
00794         $parameterValues = array(12, 1281782690);
00795 
00796         $components = $this->fixture->_callRef('parseSELECT', $sql);
00797         for ($i = 0; $i < count($components['parameters']['?']); $i++) {
00798             $components['parameters']['?'][$i][0] = $parameterValues[$i];
00799         }
00800         $query = $this->cleanSql($this->fixture->_callRef('compileSELECT', $components));
00801         $expected = 'SELECT * FROM pages WHERE pid = 12 AND timestamp < 1281782690 AND title != \'How to test?\'';
00802 
00803         $this->assertEquals($expected, $query);
00804     }
00805 }
00806 
00807 ?>