Raised DBAL to version 1.2.0alpha1
authorXavier Perseguers <typo3@perseguers.ch>
Mon, 23 Aug 2010 13:59:24 +0000 (13:59 +0000)
committerXavier Perseguers <typo3@perseguers.ch>
Mon, 23 Aug 2010 13:59:24 +0000 (13:59 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@8647 709f56b5-9817-0410-a4d7-c38de5d9e867

24 files changed:
ChangeLog
typo3/sysext/dbal/ChangeLog
typo3/sysext/dbal/class.ux_db_list_extra.php
typo3/sysext/dbal/class.ux_t3lib_db.php
typo3/sysext/dbal/class.ux_t3lib_sqlparser.php
typo3/sysext/dbal/doc/manual.sxw
typo3/sysext/dbal/ext_emconf.php
typo3/sysext/dbal/handlers/class.tx_dbal_handler_openoffice.php
typo3/sysext/dbal/handlers/class.tx_dbal_handler_rawmysql.php
typo3/sysext/dbal/handlers/class.tx_dbal_handler_xmldb.php
typo3/sysext/dbal/last_synched_target
typo3/sysext/dbal/lib/class.tx_dbal_sqlengine.php
typo3/sysext/dbal/lib/class.tx_dbal_tsparserext.php
typo3/sysext/dbal/mod1/index.php
typo3/sysext/dbal/res/postgresql/postgresql-compatibility.sql
typo3/sysext/dbal/tests/BaseTestCase.php
typo3/sysext/dbal/tests/FakeDbConnection.php
typo3/sysext/dbal/tests/dbGeneralTest.php
typo3/sysext/dbal/tests/dbMssqlTest.php
typo3/sysext/dbal/tests/dbOracleTest.php
typo3/sysext/dbal/tests/dbPostgresqlTest.php
typo3/sysext/dbal/tests/fixtures/mssql.config.php
typo3/sysext/dbal/tests/fixtures/oci8.config.php
typo3/sysext/dbal/tests/sqlParserGeneralTest.php

index 86a5e1f..99aa5d7 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,6 @@
 2010-08-23  Xavier Perseguers  <typo3@perseguers.ch>
 
+       * Raised DBAL to version 1.2.0alpha1
        * Fixed bug #15528: Add unit tests for t3lib_db_PreparedStatement (thanks to Helmut Hummel)
        * Fixed bug #15527: Enhance t3lib_db_PreparedStatement (thanks to Helmut Hummel)
 
index 05244d6..eb91dc4 100644 (file)
@@ -1,10 +1,50 @@
+2010-08-23  Xavier Perseguers  <typo3@perseguers.ch>
+
+       * Set version to 1.2.0alpha1
+
+2010-08-19  Xavier Perseguers  <typo3@perseguers.ch>
+
+       * Added unit test for feature #15457
+       * Added feature #15457: Add support for prepared queries
+
+2010-08-14  Xavier Perseguers  <typo3@perseguers.ch>
+
+       * Code cleanup with useless blank spaces at end of line
+
+2010-08-08  Xavier Perseguers  <typo3@perseguers.ch>
+
+       * Added unit test for bug #15253: NOT LIKE is not remapped using dbms_lob.instr with Oracle
+       * Fixed bug #12535: DAM-related: Element browser crashes as where-clause cannot be parsed
+
+2010-07-27  Xavier Perseguers  <typo3@perseguers.ch>
+
+       * Fixed bug #15160: Queries should only be parsed once
+
+2010-07-17  Xavier Perseguers  <typo3@perseguers.ch>
+
+       * Updated PHP documentation
+
+2010-07-16  Xavier Perseguers  <typo3@perseguers.ch>
+
+       * Added unit test for bug #14818: t3lib_db->listQuery() performance
+       * Fixed bug #14985: FIND_IN_SET should be used isntead of complicated LIKE where clause
+
+2010-07-11  Xavier Perseguers  <typo3@perseguers.ch>
+
+       * Fixed bug #15045: Trailing newlines after php closing tag
+
+2010-06-27  Xavier Perseguers  <typo3@perseguers.ch>
+
+       * Synchronized @deprecated annotations with Core
+
 2010-06-22  Jeff Segars  <jeff@webempoweredchurch.org>
 
-       * Fixed bug #14814: Improve install tool texts.
+       * Fixed bug #14814: Improve install tool texts
 
-2010-06-13  Xavier Perseguers  <typo3@perseguers.ch>
+2010-06-19  Xavier Perseguers  <typo3@perseguers.ch>
 
-       * Set version to 1.1.7 (TYPO3 4.4i RC1)
+       * Fixed bug #3855: Log number of returned or affected rows
+       * Updated copyright year in manual
 
 2010-06-12  Xavier Perseguers  <typo3@perseguers.ch>
 
 
        * Fixed bug #7015: t3lib_DB displays wrong SQL in error case
 
-2010-05-28  Xavier Perseguers  <typo3@perseguers.ch>
-
-       * Set version to 1.1.6 (TYPO3 4.4 beta3)
-
 2010-05-27  Xavier Perseguers  <typo3@perseguers.ch>
 
        * Fixed bug #14496: SQL parser does not handle ALTER TABLE with character set operation
 
 2010-05-03  Xavier Perseguers  <typo3@perseguers.ch>
 
-       * Set version to 1.1.5 (TYPO3 4.4 beta2)
        * Fixed 1-2-3 installer crash when having only mysql available
 
-2010-05-02  Xavier Perseguers  <typo3@perseguers.ch>
-
-       * Set version to 1.1.4 (TYPO3 4.4 beta2)
-
 2010-05-01  Xavier Perseguers  <typo3@perseguers.ch>
 
        * Fixed bug #14274: Some exception are not caught when trying to install DBAL in 1-2-3 Install Tool process
        * Fixed bug #2186: Error installing static_info_tables
        * Fixed bug #14265: Driver dropdown in install tool should be hidden when only MySQL is available
 
-2010-04-30  Xavier Perseguers  <typo3@perseguers.ch>
-
-       * Set version to 1.1.3
-
 2010-04-29  Xavier Perseguers  <typo3@perseguers.ch>
 
        * Added autoloader for Install Tool
index dcb6c82..4833d99 100644 (file)
@@ -2,8 +2,8 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 1999-2010 Kasper Skaarhoj (kasperYYYY@typo3.com)
-*  (c) 2006-2010 Karsten Dambekalns <karsten@typo3.org>
+*  (c) 1999-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
+*  (c) 2006-2009 Karsten Dambekalns <karsten@typo3.org>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -28,7 +28,7 @@
 /**
  * Include file extending localRecordList for DBAL compatibility
  *
- * $Id: class.ux_db_list_extra.php 25913 2009-10-27 14:20:41Z xperseguers $
+ * $Id: class.ux_db_list_extra.php 30032 2010-02-14 23:14:56Z xperseguers $
  *
  * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
  * @author     Karsten Dambekalns <k.dambekalns@fishfarm.de>
index 9212f63..eeda2b4 100644 (file)
@@ -2,8 +2,8 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2004-2010 Kasper Skaarhoj (kasperYYYY@typo3.com)
-*  (c) 2004-2010 Karsten Dambekalns <karsten@typo3.org>
+*  (c) 2004-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
+*  (c) 2004-2009 Karsten Dambekalns <karsten@typo3.org>
 *  (c) 2009-2010 Xavier Perseguers <typo3@perseguers.ch>
 *  All rights reserved
 *
@@ -29,7 +29,7 @@
 /**
  * Contains a database abstraction layer class for TYPO3
  *
- * $Id: class.ux_t3lib_db.php 29977 2010-02-13 13:18:32Z xperseguers $
+ * $Id: class.ux_t3lib_db.php 37006 2010-08-19 16:40:34Z xperseguers $
  *
  * @author     Kasper Skaarhoj <kasper@typo3.com>
  * @author     Karsten Dambekalns <k.dambekalns@fishfarm.de>
@@ -690,8 +690,11 @@ class ux_t3lib_DB extends t3lib_DB {
 
                        // Map table / field names if needed:
                $ORIG_tableName = $from_table;  // Saving table names in $ORIG_from_table since $from_table is transformed beneath:
-               if ($tableArray = $this->map_needMapping($ORIG_tableName)) {
-                       $this->map_remapSELECTQueryParts($select_fields,$from_table,$where_clause,$groupBy,$orderBy);   // Variables passed by reference!
+               $parsedFromTable = array();
+               $remappedParameters = array();
+               if ($tableArray = $this->map_needMapping($ORIG_tableName, FALSE, $parsedFromTable)) {
+                       $from = $parsedFromTable ? $parsedFromTable : $from_table;
+                       $remappedParameters = $this->map_remapSELECTQueryParts($select_fields, $from, $where_clause, $groupBy, $orderBy);
                }
 
                        // Get handler key and select API:
@@ -699,7 +702,10 @@ class ux_t3lib_DB extends t3lib_DB {
                $hType = (string)$this->handlerCfg[$this->lastHandlerKey]['type'];
                switch ($hType) {
                        case 'native':
-                               $this->lastQuery = $this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit);
+                               if (count($remappedParameters) > 0) {
+                                       list($select_fields, $from_table, $where_clause, $groupBy, $orderBy) = $this->compileSelectParameters($remappedParameters);
+                               }
+                               $this->lastQuery = $this->SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
                                $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
                                $this->resourceIdToTableNameMap[(string)$sqlResult] = $ORIG_tableName;
                                break;
@@ -714,10 +720,18 @@ class ux_t3lib_DB extends t3lib_DB {
                                                $offset = 0;
                                        }
 
-                                       $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->SelectLimit($this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy), $numrows, $offset);
+                                       if (count($remappedParameters) > 0) {
+                                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->SelectLimit($this->SELECTqueryFromArray($remappedParameters), $numrows, $offset);
+                                       } else {
+                                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->SelectLimit($this->SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy), $numrows, $offset);
+                                       }
                                        $this->lastQuery = $sqlResult->sql;
                                } else {
-                                       $this->lastQuery = $this->SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy);
+                                       if (count($remappedParameters) > 0) {
+                                               $this->lastQuery = $this->SELECTqueryFromArray($remappedParameters);
+                                       } else {
+                                               $this->lastQuery = $this->SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy);
+                                       }
                                        $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_Execute($this->lastQuery);
                                }
 
@@ -725,7 +739,10 @@ class ux_t3lib_DB extends t3lib_DB {
                                $sqlResult->TYPO3_DBAL_tableList = $ORIG_tableName;
                                break;
                        case 'userdefined':
-                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit);
+                               if (count($remappedParameters) > 0) {
+                                       list($select_fields, $from_table, $where_clause, $groupBy, $orderBy) = $this->compileSelectParameters($remappedParameters);
+                               }
+                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
                                if (is_object($sqlResult)) {
                                        $sqlResult->TYPO3_DBAL_handlerType = 'userdefined';     // Setting handler type in result object (for later recognition!)
                                        $sqlResult->TYPO3_DBAL_tableList = $ORIG_tableName;
@@ -738,14 +755,18 @@ class ux_t3lib_DB extends t3lib_DB {
                }
 
                if ($this->debug) {
+                       $data = array(
+                               'handlerType' => $hType,
+                               'args' => array($from_table, $select_fields, $where_clause, $groupBy, $orderBy, $limit),
+                               'ORIG_from_table' => $ORIG_tableName,
+                       );
+                       if ($this->conf['debugOptions']['numberRows']) {
+                               $data['numberRows'] = $this->sql_num_rows($sqlResult);
+                       }
                        $this->debugHandler(
                                'exec_SELECTquery',
                                t3lib_div::milliseconds()-$pt,
-                               array(
-                                       'handlerType' => $hType,
-                                       'args' => array($from_table,$select_fields,$where_clause,$groupBy,$orderBy,$limit),
-                                       'ORIG_from_table' => $ORIG_tableName
-                               )
+                               $data
                        );
                }
 
@@ -1127,6 +1148,60 @@ class ux_t3lib_DB extends t3lib_DB {
        }
 
        /**
+        * Creates a SELECT SQL-statement to be used with an ADOdb backend.
+        *
+        * @param       array           parsed parameters: array($select_fields, $from_table, $where_clause, $groupBy, $orderBy)
+        * @return      string          Full SQL query for SELECT
+        */
+       protected function SELECTqueryFromArray(array $params) {
+                       // $select_fields
+               $params[0] = $this->_quoteFieldNames($params[0]);
+                       // $from_table
+               $params[1] = $this->_quoteFromTables($params[1]);
+                       // $where_clause
+               if (count($params[2]) > 0) {
+                       $params[2] = $this->_quoteWhereClause($params[2]);
+               }
+                       // $group_by
+               if (count($params[3]) > 0) {
+                       $params[3] = $this->_quoteGroupBy($params[3]);
+               }
+                       // $order_by
+               if (count($params[4]) > 0) {
+                       $params[4] = $this->_quoteOrderBy($params[4]);
+               }
+
+                       // Compile the SELECT parameters
+               list($select_fields, $from_table, $where_clause, $groupBy, $orderBy) = $this->compileSelectParameters($params);
+
+                       // Call parent method to build actual query
+               $query = parent::SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy);
+
+               if ($this->debugOutput || $this->store_lastBuiltQuery) {
+                       $this->debug_lastBuiltQuery = $query;
+               }
+
+               return $query;
+       }
+
+       /**
+        * Compiles and returns an array of SELECTquery parameters (without $limit) to
+        * be used with SELECTquery() or exec_SELECTquery().
+        *
+        * @param array $params
+        * @return array array($select_fields, $from_table, $where_clause, $groupBy, $orderBy)
+        */
+       protected function compileSelectParameters(array $params) {
+               $select_fields = $this->SQLparser->compileFieldList($params[0]);
+               $from_table = $this->SQLparser->compileFromTables($params[1]);
+               $where_clause = (count($params[2]) > 0) ? $this->SQLparser->compileWhereClause($params[2]) : '';
+               $groupBy = (count($params[3]) > 0) ? $this->SQLparser->compileFieldList($params[3]) : '';
+               $orderBy = (count($params[4]) > 0) ? $this->SQLparser->compileFieldList($params[4]) : '';
+
+               return array($select_fields, $from_table, $where_clause, $groupBy, $orderBy);
+       }
+
+       /**
         * Creates a TRUNCATE TABLE SQL-statement
         *
         * @param       string          See exec_TRUNCATEquery()
@@ -1145,6 +1220,284 @@ class ux_t3lib_DB extends t3lib_DB {
                return $query;
        }
 
+       /**************************************
+        *
+        * Prepared Query Support
+        *
+        **************************************/
+
+       /**
+        * Creates a SELECT prepared SQL statement.
+        *
+        * @param string See exec_SELECTquery()
+        * @param string See exec_SELECTquery()
+        * @param string See exec_SELECTquery()
+        * @param string See exec_SELECTquery()
+        * @param string See exec_SELECTquery()
+        * @param string See exec_SELECTquery()
+        * @param array $input_parameters An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as t3lib_db_PreparedStatement::PARAM_AUTOTYPE.
+        * @return t3lib_db_PreparedStatement Prepared statement
+        */
+       public function prepare_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '', array $input_parameters = array()) {
+               if ($this->debug) {
+                       $pt = t3lib_div::milliseconds();
+               }
+
+                       // Map table / field names if needed:
+               $ORIG_tableName = $from_table;  // Saving table names in $ORIG_from_table since $from_table is transformed beneath:
+               $parsedFromTable = array();
+               $queryComponents = array();
+               if ($tableArray = $this->map_needMapping($ORIG_tableName, FALSE, $parsedFromTable)) {
+                       $from = $parsedFromTable ? $parsedFromTable : $from_table;
+                       $components = $this->map_remapSELECTQueryParts($select_fields, $from, $where_clause, $groupBy, $orderBy);
+                       $queryComponents['SELECT']     = $components[0];
+                       $queryComponents['FROM']       = $components[1];
+                       $queryComponents['WHERE']      = $components[2];
+                       $queryComponents['GROUPBY']    = $components[3];
+                       $queryComponents['ORDERBY']    = $components[4];
+                       $queryComponents['parameters'] = $components[5];
+               } else {
+                       $queryComponents = $this->getQueryComponents($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
+               }
+
+               $queryComponents['ORIG_tableName'] = $ORIG_tableName;
+
+               if (!$this->runningNative()) {
+                               // Quotes all fields
+                       $queryComponents['SELECT']  = $this->_quoteFieldNames($queryComponents['SELECT']);
+                       $queryComponents['FROM']    = $this->_quoteFromTables($queryComponents['FROM']);
+                       $queryComponents['WHERE']   = $this->_quoteWhereClause($queryComponents['WHERE']);
+                       $queryComponents['GROUPBY'] = $this->_quoteGroupBy($queryComponents['GROUPBY']);
+                       $queryComponents['ORDERBY'] = $this->_quoteOrderBy($queryComponents['ORDERBY']);
+               }
+
+               $precompiledParts = $this->precompileSELECTquery($queryComponents);
+
+               $preparedStatement = t3lib_div::makeInstance('t3lib_db_PreparedStatement', '', $from_table, $precompiledParts);
+               /* @var $preparedStatement t3lib_db_PreparedStatement */
+
+                       // Bind values to parameters
+               foreach ($input_parameters as $key => $value) {
+                       $preparedStatement->bindValue($key, $value, t3lib_db_PreparedStatement::PARAM_AUTOTYPE);
+               }
+
+               if ($this->debug) {
+                       $data = array(
+                               'args' => array($from_table, $select_fields, $where_clause, $groupBy, $orderBy, $limit, $input_parameters),
+                               'ORIG_from_table' => $ORIG_tableName,
+                       );
+                       $this->debugHandler(
+                               'prepare_SELECTquery',
+                               t3lib_div::milliseconds() - $pt,
+                               $data
+                       );
+               }
+
+                       // Return prepared statement
+               return $preparedStatement;
+       }
+
+       /**
+        * Returns the parsed query components.
+        *
+        * @param string $select_fields
+        * @param string $from_table
+        * @param string $where_clause
+        * @param string $groupBy
+        * @param string $orderBy
+        * @param string $limit
+        * @return array
+        */
+       protected function getQueryComponents($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit) {
+               $queryComponents = array(
+                       'SELECT'     => '',
+                       'FROM'       => '',
+                       'WHERE'      => '',
+                       'GROUPBY'    => '',
+                       'ORDERBY'    => '',
+                       'LIMIT'      => '',
+                       'parameters' =>  array(),
+               );
+
+               $this->lastHandlerKey = $this->handler_getFromTableList($from_table);
+               $hType = (string)$this->handlerCfg[$this->lastHandlerKey]['type'];
+               if ($hType === 'adodb' && $this->runningADOdbDriver('postgres')) {
+                               // Possibly rewrite the LIMIT to be PostgreSQL-compatible
+                       $splitLimit = t3lib_div::intExplode(',', $limit);               // Splitting the limit values:
+                       if ($splitLimit[1]) {   // If there are two parameters, do mapping differently than otherwise:
+                               $numrows = $splitLimit[1];
+                               $offset = $splitLimit[0];
+                               $limit = $numrows . ' OFFSET ' . $offset;
+                       }
+               }
+               $queryComponents['LIMIT'] = $limit;
+
+               $queryComponents['SELECT'] = $this->SQLparser->parseFieldList($select_fields);
+               if ($this->SQLparser->parse_error) {
+                       die($this->SQLparser->parse_error . ' in ' . __FILE__ . ' : ' . __LINE__);
+               }
+
+               $queryComponents['FROM'] = $this->SQLparser->parseFromTables($from_table);
+
+               $queryComponents['WHERE'] = $this->SQLparser->parseWhereClause($where_clause, '', $queryComponents['parameters']);
+               if (!is_array($queryComponents['WHERE'])) {
+                       die('Could not parse where clause in ' . __FILE__ . ' : ' . __LINE__);
+               }
+
+               $queryComponents['GROUPBY'] = $this->SQLparser->parseFieldList($groupBy);
+               $queryComponents['ORDERBY'] = $this->SQLparser->parseFieldList($orderBy);
+
+                       // Return the query components
+               return $queryComponents;
+       }
+
+       /**
+        * Precompiles a SELECT prepared SQL statement.
+        *
+        * @param array $components
+        * @return array Precompiled SQL statement
+        */
+       protected function precompileSELECTquery(array $components) {
+               $parameterWrap = '__' . dechex(time()) . '__';
+               foreach ($components['parameters'] as $key => $params) {
+                       if ($key === '?') {
+                               foreach ($params as $index => $param) {
+                                       $components['parameters'][$key][$index][0] = $parameterWrap . $param[0] . $parameterWrap;
+                               }
+                       } else {
+                               $components['parameters'][$key][0] = $parameterWrap . $params[0] . $parameterWrap;
+                       }
+               }
+
+               $select_fields = $this->SQLparser->compileFieldList($components['SELECT']);
+               $from_table    = $this->SQLparser->compileFromTables($components['FROM']);
+               $where_clause  = $this->SQLparser->compileWhereClause($components['WHERE']);
+               $groupBy       = $this->SQLparser->compileFieldList($components['GROUPBY']);
+               $orderBy       = $this->SQLparser->compileFieldList($components['ORDERBY']);
+               $limit         = $components['LIMIT'];
+               $precompiledParts = array();
+
+               $this->lastHandlerKey = $this->handler_getFromTableList($components['ORIG_tableName']);
+               $hType = (string)$this->handlerCfg[$this->lastHandlerKey]['type'];
+               $precompiledParts['handler'] = $hType;
+               $precompiledParts['ORIG_tableName'] = $components['ORIG_tableName'];
+
+               switch ($hType) {
+                       case 'native':
+                               $query = parent::SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
+                               $precompiledParts['queryParts'] = explode($parameterWrap, $query);
+                               break;
+                       case 'adodb':
+                               $query = parent::SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy);
+                               $precompiledParts['queryParts'] = explode($parameterWrap, $query);
+                               $precompiledParts['LIMIT'] = $limit;
+                               break;
+                       case 'userdefined':
+                               $precompiledParts['queryParts'] = array(
+                                       'SELECT'  => $select_fields,
+                                       'FROM'    => $from_table,
+                                       'WHERE'   => $where_clause,
+                                       'GROUPBY' => $groupBy,
+                                       'ORDERBY' => $orderBy,
+                                       'LIMIT'   => $limit,
+                               );
+                               break;
+               }
+
+               return $precompiledParts;
+       }
+
+       /**
+        * Executes a prepared query.
+        *
+        * @param string $query The query to execute
+        * @param array $queryComponents The components of the query to execute
+        * @return pointer MySQL result pointer / DBAL object
+        * @access protected This method may only be called by t3lib_db_PreparedStatement
+        */
+       public function exec_PREPAREDquery($query, array $precompiledParts) {
+               if ($this->debug) {
+                       $pt = t3lib_div::milliseconds();
+               }
+
+                       // Get handler key and select API:
+               switch ($precompiledParts['handler']) {
+                       case 'native':
+                               $this->lastQuery = $query;
+                               $sqlResult = mysql_query($this->lastQuery, $this->handlerInstance[$this->lastHandlerKey]['link']);
+                               $this->resourceIdToTableNameMap[(string)$sqlResult] = $precompiledParts['ORIG_tableName'];
+                               break;
+                       case 'adodb':
+                               $limit = $precompiledParts['LIMIT'];
+                               if ($this->runningADOdbDriver('postgres')) {
+                                               // Possibly rewrite the LIMIT to be PostgreSQL-compatible
+                                       $splitLimit = t3lib_div::intExplode(',', $limit);               // Splitting the limit values:
+                                       if ($splitLimit[1]) {   // If there are two parameters, do mapping differently than otherwise:
+                                               $numrows = $splitLimit[1];
+                                               $offset = $splitLimit[0];
+                                               $limit = $numrows . ' OFFSET ' . $offset;
+                                       }
+                               }
+                               if ($limit != '') {
+                                       $splitLimit = t3lib_div::intExplode(',', $limit);               // Splitting the limit values:
+                                       if ($splitLimit[1]) {   // If there are two parameters, do mapping differently than otherwise:
+                                               $numrows = $splitLimit[1];
+                                               $offset = $splitLimit[0];
+                                       } else {
+                                               $numrows = $splitLimit[0];
+                                               $offset = 0;
+                                       }
+
+                                       $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->SelectLimit($query, $numrows, $offset);
+                                       $this->lastQuery = $sqlResult->sql;
+                               } else {
+                                       $this->lastQuery = $query;
+                                       $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->_Execute($this->lastQuery);
+                               }
+
+                               $sqlResult->TYPO3_DBAL_handlerType = 'adodb';   // Setting handler type in result object (for later recognition!)
+                               $sqlResult->TYPO3_DBAL_tableList = $precompiledParts['ORIG_tableName'];
+                               break;
+                       case 'userdefined':
+                               $queryParts = $precompiledParts['queryParts'];
+                               $sqlResult = $this->handlerInstance[$this->lastHandlerKey]->exec_SELECTquery(
+                                       $queryParts['SELECT'],
+                                       $queryParts['FROM'],
+                                       $queryParts['WHERE'],
+                                       $queryParts['GROUPBY'],
+                                       $queryParts['ORDERBY'],
+                                       $queryParts['LIMIT']
+                               );
+                               if (is_object($sqlResult)) {
+                                       $sqlResult->TYPO3_DBAL_handlerType = 'userdefined';     // Setting handler type in result object (for later recognition!)
+                                       $sqlResult->TYPO3_DBAL_tableList = $precompiledParts['ORIG_tableName'];
+                               }
+                               break;
+               }
+
+               if ($this->printErrors && $this->sql_error()) {
+                       debug(array($this->lastQuery, $this->sql_error()));
+               }
+
+               if ($this->debug) {
+                       $data = array(
+                               'handlerType' => $precompiledParts['handler'],
+                               'args' => $precompiledParts,
+                               'ORIG_from_table' => $precompiledParts['ORIG_tableName'],
+                       );
+                       if ($this->conf['debugOptions']['numberRows']) {
+                               $data['numberRows'] = $this->sql_num_rows($sqlResult);
+                       }
+                       $this->debugHandler(
+                               'exec_PREPAREDquery',
+                               t3lib_div::milliseconds() - $pt,
+                               $data
+                       );
+               }
+
+                       // Return result handler.
+               return $sqlResult;
+       }
 
        /**************************************
        *
@@ -1282,7 +1635,7 @@ class ux_t3lib_DB extends t3lib_DB {
        /**
         * Quotes the field (and table) names within a where clause with the quote character suitable for the DB being used
         *
-        * @param       string          A where clause that can e parsed by parseWhereClause
+        * @param       string          A where clause that can be parsed by parseWhereClause
         * @return      string          Usable where clause with quoted field/table names
         */
        public function quoteWhereClause($where_clause) {
@@ -1316,6 +1669,15 @@ class ux_t3lib_DB extends t3lib_DB {
                                        case 'EXISTS':
                                                $where_clause[$k]['func']['subquery'] = $this->quoteSELECTsubquery($v['func']['subquery']);
                                                break;
+                                       case 'FIND_IN_SET':
+                                                       // quoteStr that will be used for Oracle
+                                               $pattern = str_replace($where_clause[$k]['func']['str'][1], '\\' . $where_clause[$k]['func']['str'][1], $where_clause[$k]['func']['str'][0]);
+                                                       // table is not really needed and may in fact be empty in real statements
+                                                       // but it's not overriden from t3lib_db at the moment...
+                                               $patternForLike = $this->escapeStrForLike($pattern, $where_clause[$k]['func']['table']);
+                                               $where_clause[$k]['func']['str_like'] = $patternForLike;
+
+                                               // BEWARE: no break here to have next statements too
                                        case 'IFNULL':
                                        case 'LOCATE':
                                                if ($where_clause[$k]['func']['table'] != '') {
@@ -1324,7 +1686,7 @@ class ux_t3lib_DB extends t3lib_DB {
                                                if ($where_clause[$k]['func']['field'] != '') {
                                                        $where_clause[$k]['func']['field'] = $this->quoteName($v['func']['field']);
                                                }
-                                       break;
+                                               break;
                                }
                        } else {
                                if ($where_clause[$k]['table'] != '') {
@@ -1367,47 +1729,74 @@ class ux_t3lib_DB extends t3lib_DB {
        }
 
        /**
-        * [Describe function...]
+        * Quotes the field (and table) names within a group by clause with the quote
+        * character suitable for the DB being used
         *
-        * @param       [type]          $$groupBy: ...
-        * @return      [type]          ...
+        * @param       string          A group by clause that can by parsed by parseFieldList
+        * @return      string          Usable group by clause with quoted field/table names
         */
        protected function quoteGroupBy($groupBy) {
                if ($groupBy === '') return '';
                if ($this->runningNative()) return $groupBy;
 
                $groupBy = $this->SQLparser->parseFieldList($groupBy);
+               $groupBy = $this->_quoteGroupBy($groupBy);
+
+               return $this->SQLparser->compileFieldList($groupBy);
+       }
+
+       /**
+        * Quotes field names in a SQL GROUP BY clause acccording to DB rules
+        *
+        * @param       array           $groupBy The parsed GROUP BY clause to quote
+        * @return      array
+        * @see quoteGroupBy()
+        */
+       protected function _quoteGroupBy(array $groupBy) {
                foreach ($groupBy as $k => $v) {
                        $groupBy[$k]['field'] = $this->quoteName($groupBy[$k]['field']);
                        if ($groupBy[$k]['table'] != '') {
                                $groupBy[$k]['table'] = $this->quoteName($groupBy[$k]['table']);
                        }
                }
-               return $this->SQLparser->compileFieldList($groupBy);
+               return $groupBy;
        }
 
        /**
-        * [Describe function...]
+        * Quotes the field (and table) names within an order by clause with the quote
+        * character suitable for the DB being used
         *
-        * @param       [type]          $$orderBy: ...
-        * @return      [type]          ...
+        * @param       string          An order by clause that can by parsed by parseFieldList
+        * @return      string          Usable order by clause with quoted field/table names
         */
        protected function quoteOrderBy($orderBy) {
                if ($orderBy === '') return '';
                if ($this->runningNative()) return $orderBy;
 
                $orderBy = $this->SQLparser->parseFieldList($orderBy);
+               $orderBy = $this->_quoteOrderBy($orderBy);
+
+               return $this->SQLparser->compileFieldList($orderBy);
+       }
+
+       /**
+        * Quotes field names in a SQL ORDER BY clause acccording to DB rules
+        *
+        * @param       array           $orderBy The parsed ORDER BY clause to quote
+        * @return      array
+        * @see quoteOrderBy()
+        */
+       protected function _quoteOrderBy(array $orderBy) {
                foreach ($orderBy as $k => $v) {
                        $orderBy[$k]['field'] = $this->quoteName($orderBy[$k]['field']);
                        if ($orderBy[$k]['table'] != '') {
                                $orderBy[$k]['table'] = $this->quoteName($orderBy[$k]['table']);
                        }
                }
-               return $this->SQLparser->compileFieldList($orderBy);
+               return $orderBy;
        }
 
 
-
        /**************************************
        *
        * Various helper functions
@@ -2016,7 +2405,6 @@ class ux_t3lib_DB extends t3lib_DB {
         * @param       string          Username to connect with.
         * @param       string          Password to connect with.
         * @return      mixed           Returns handler connection value
-        * @deprecated since TYPO3 4.1
         * @see handler_init()
         */
        public function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password) {
@@ -2036,7 +2424,6 @@ class ux_t3lib_DB extends t3lib_DB {
         *
         * @param       string          Database to connect to.
         * @return      boolean         Always returns TRUE; function is obsolete, database selection is made in handler_init() function!
-        * @deprecated since TYPO3 4.1
         */
        public function sql_select_db($TYPO3_db) {
                return TRUE;
@@ -2666,15 +3053,17 @@ class ux_t3lib_DB extends t3lib_DB {
         *
         * @param       string          List of tables in query
         * @param       boolean         If TRUE, it will check only if FIELDs are configured and ignore the mapped table name if any.
+        * @param       array           Parsed list of tables, should be passed as reference to be reused and prevent double parsing
         * @return      mixed           Returns an array of table names (parsed version of input table) if mapping is needed, otherwise just FALSE.
         */
-       protected function map_needMapping($tableList, $fieldMappingOnly = FALSE) {
+       protected function map_needMapping($tableList, $fieldMappingOnly = FALSE, array &$parsedTableList = array()) {
                $key = $tableList.'|'.$fieldMappingOnly;
                if (!isset($this->cache_mappingFromTableList[$key])) {
                        $this->cache_mappingFromTableList[$key] = FALSE;        // Default:
 
                        $tables = $this->SQLparser->parseFromTables($tableList);
                        if (is_array($tables)) {
+                               $parsedTableList = $tables;
                                foreach ($tables as $tableCfg) {
                                        if ($fieldMappingOnly) {
                                                if (is_array($this->mapping[$tableCfg['table']]['mapFieldNames'])) {
@@ -2756,9 +3145,8 @@ class ux_t3lib_DB extends t3lib_DB {
 
        /**
         * Remaps table/field names in a SELECT query's parts
-        * Notice: All arguments are passed by reference!
         *
-        * @param       string          List of fields to select from the table. This is what comes right after "SELECT ...". Required value.
+        * @param       mixed           Either parsed list of tables (SQLparser->parseFromTables()) or list of fields to select from the table. This is what comes right after "SELECT ...". Required value.
         * @param       string          Table(s) from which to select. This is what comes right after "FROM ...". Require value.
         * @param       string          Where clause. This is what comes right after "WHERE ...". Can be blank.
         * @param       string          Group by field(s)
@@ -2766,12 +3154,12 @@ class ux_t3lib_DB extends t3lib_DB {
         * @return      void
         * @see exec_SELECTquery()
         */
-       protected function map_remapSELECTQueryParts(&$select_fields, &$from_table, &$where_clause, &$groupBy, &$orderBy) {
+       protected function map_remapSELECTQueryParts($select_fields, $from_table, $where_clause, $groupBy, $orderBy) {
                        // Backup current mapping as it may be altered if aliases on mapped tables are found
                $backupMapping = $this->mapping;
 
                        // Tables:
-               $tables = $this->SQLparser->parseFromTables($from_table);
+               $tables = is_array($from_table) ? $from_table : $this->SQLparser->parseFromTables($from_table);
                $defaultTable = $tables[0]['table'];
                        // Prepare mapping for aliased tables. This will copy the definition of the original table name.
                        // The alias is prefixed with a database-incompatible character to prevent naming clash with real table name
@@ -2828,30 +3216,29 @@ class ux_t3lib_DB extends t3lib_DB {
                                }
                        }
                }
-               $from_table = $this->SQLparser->compileFromTables($tables);
+               $fromParts = $tables;
 
                        // Where clause:
-               $whereParts = $this->SQLparser->parseWhereClause($where_clause);
-               $this->map_sqlParts($whereParts,$defaultTable);
-               $where_clause = $this->SQLparser->compileWhereClause($whereParts, FALSE);
+               $parameterReferences = array();
+               $whereParts = $this->SQLparser->parseWhereClause($where_clause, '', $parameterReferences);
+               $this->map_sqlParts($whereParts, $defaultTable);
 
                        // Select fields:
-               $expFields = $this->SQLparser->parseFieldList($select_fields);
-               $this->map_sqlParts($expFields,$defaultTable);
-               $select_fields = $this->SQLparser->compileFieldList($expFields, FALSE, FALSE);
+               $selectParts = $this->SQLparser->parseFieldList($select_fields);
+               $this->map_sqlParts($selectParts, $defaultTable);
 
                        // Group By fields
-               $expFields = $this->SQLparser->parseFieldList($groupBy);
-               $this->map_sqlParts($expFields,$defaultTable);
-               $groupBy = $this->SQLparser->compileFieldList($expFields);
+               $groupByParts = $this->SQLparser->parseFieldList($groupBy);
+               $this->map_sqlParts($groupByParts, $defaultTable);
 
                        // Order By fields
-               $expFields = $this->SQLparser->parseFieldList($orderBy);
-               $this->map_sqlParts($expFields,$defaultTable);
-               $orderBy = $this->SQLparser->compileFieldList($expFields);
+               $orderByParts = $this->SQLparser->parseFieldList($orderBy);
+               $this->map_sqlParts($orderByParts, $defaultTable);
 
                        // Restore the original mapping
                $this->mapping = $backupMapping;
+
+               return array($selectParts, $fromParts, $whereParts, $groupByParts, $orderByParts, $parameterReferences);
        }
 
        /**
@@ -2940,6 +3327,7 @@ class ux_t3lib_DB extends t3lib_DB {
                                                case 'EXISTS':
                                                        $this->map_subquery($sqlPartArray[$k]['func']['subquery']);
                                                        break;
+                                               case 'FIND_IN_SET':
                                                case 'IFNULL':
                                                case 'LOCATE':
                                                                // For the field, look for table mapping (generic):
@@ -3213,10 +3601,24 @@ class ux_t3lib_DB extends t3lib_DB {
                        }
 
                                // if lastQuery is empty (for whatever reason) at least log inData.args
-                       if (empty($this->lastQuery))
-                               $query = implode(' ',$inData['args']);
-                       else
+                       if (empty($this->lastQuery)) {
+                               $query = implode(' ', $inData['args']);
+                       } else {
                                $query = $this->lastQuery;
+                       }
+
+                       if ($this->conf['debugOptions']['numberRows']) {
+                               switch ($function) {
+                                       case 'exec_INSERTquery':
+                                       case 'exec_UPDATEquery':
+                                       case 'exec_DELETEquery':
+                                               $data['numberRows'] = $this->sql_affected_rows();
+                                               break;
+                                       case 'exec_SELECTquery':
+                                               $data['numberRows'] = $inData['numberRows'];
+                                               break;
+                               }
+                       }
 
                        if ($this->conf['debugOptions']['backtrace']) {
                                $backtrace = debug_backtrace();
index 541c109..34d66c2 100644 (file)
@@ -2,8 +2,8 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2004-2010 Kasper Skaarhoj (kasperYYYY@typo3.com)
-*  (c) 2004-2010 Karsten Dambekalns <karsten@typo3.org>
+*  (c) 2004-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
+*  (c) 2004-2009 Karsten Dambekalns <karsten@typo3.org>
 *  (c) 2009-2010 Xavier Perseguers <typo3@perseguers.ch>
 *  All rights reserved
 *
@@ -29,7 +29,7 @@
 /**
  * PHP SQL engine
  *
- * $Id: class.ux_t3lib_sqlparser.php 29977 2010-02-13 13:18:32Z xperseguers $
+ * $Id: class.ux_t3lib_sqlparser.php 36759 2010-08-14 15:55:24Z xperseguers $
  *
  * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
  * @author     Karsten Dambekalns <k.dambekalns@fishfarm.de>
@@ -490,6 +490,67 @@ class ux_t3lib_sqlparser extends t3lib_sqlparser {
                                                                $output .= ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
                                                                $output .= ', ' . $v['func']['default'][1] . $this->compileAddslashes($v['func']['default'][0]) . $v['func']['default'][1];
                                                                $output .= ')';
+                                                       } elseif (isset($v['func']) && $v['func']['type'] === 'FIND_IN_SET') {
+                                                               $output = ' ' . trim($v['modifier']) . ' ';
+                                                               if ($functionMapping) {
+                                                                       switch (TRUE) {
+                                                                               case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('mssql')):
+                                                                                       $field = ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
+                                                                                       if (!isset($v['func']['str_like'])) {
+                                                                                               $v['func']['str_like'] = $v['func']['str'][0];
+                                                                                       }
+                                                                                       $output .= '\',\'+' . $field . '+\',\' LIKE \'%,' . $v['func']['str_like'] . ',%\'';
+                                                                                       break;
+                                                                               case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('oci8')):
+                                                                                       $field = ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
+                                                                                       if (!isset($v['func']['str_like'])) {
+                                                                                               $v['func']['str_like'] = $v['func']['str'][0];
+                                                                                       }
+                                                                                       $output .= '\',\'||' . $field . '||\',\' LIKE \'%,' . $v['func']['str_like'] . ',%\'';
+                                                                                       break;
+                                                                               case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('postgres')):
+                                                                                       $output .= ' FIND_IN_SET(';
+                                                                                       $output .= $v['func']['str'][1] . $v['func']['str'][0] . $v['func']['str'][1];
+                                                                                       $output .= ', ' . ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
+                                                                                       $output .= ') != 0';
+                                                                                       break;
+                                                                               default:
+                                                                                       $field = ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
+                                                                                       if (!isset($v['func']['str_like'])) {
+                                                                                               $v['func']['str_like'] = $v['func']['str'][0];
+                                                                                       }
+                                                                                       $output .= '('
+                                                                                               . $field . ' LIKE \'%,' . $v['func']['str_like'] . ',%\''
+                                                                                               . ' OR ' . $field . ' LIKE \'' . $v['func']['str_like'] . ',%\''
+                                                                                               . ' OR ' . $field . ' LIKE \'%,' . $v['func']['str_like'] . '\''
+                                                                                               . ' OR ' . $field . '= ' . $v['func']['str'][1] . $v['func']['str'][0] . $v['func']['str'][1]
+                                                                                               . ')';
+                                                                                       break;
+                                                                       }
+                                                               } else /* !$functionMapping */ {
+                                                                       switch (TRUE) {
+                                                                               case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('mssql')):
+                                                                               case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('oci8')):
+                                                                               case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('postgres')):
+                                                                                       $output .= ' FIND_IN_SET(';
+                                                                                       $output .= $v['func']['str'][1] . $v['func']['str'][0] . $v['func']['str'][1];
+                                                                                       $output .= ', ' . ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
+                                                                                       $output .= ')';
+                                                                                       break;
+                                                                               default:
+                                                                                       $field = ($v['func']['table'] ? $v['func']['table'] . '.' : '') . $v['func']['field'];
+                                                                                       if (!isset($v['func']['str_like'])) {
+                                                                                               $v['func']['str_like'] = $v['func']['str'][0];
+                                                                                       }
+                                                                                       $output .= '('
+                                                                                               . $field . ' LIKE \'%,' . $v['func']['str_like'] . ',%\''
+                                                                                               . ' OR ' . $field . ' LIKE \'' . $v['func']['str_like'] . ',%\''
+                                                                                               . ' OR ' . $field . ' LIKE \'%,' . $v['func']['str_like'] . '\''
+                                                                                               . ' OR ' . $field . '= ' . $v['func']['str'][1] . $v['func']['str'][0] . $v['func']['str'][1]
+                                                                                               . ')';
+                                                                                       break;
+                                                                       }
+                                                               }
                                                        } else {
 
                                                                        // Set field/table with modifying prefix if any:
@@ -514,15 +575,16 @@ class ux_t3lib_sqlparser extends t3lib_sqlparser {
                                                                        } else {
                                                                                $output .= $v['calc_value'][1] . $this->compileAddslashes($v['calc_value'][0]) . $v['calc_value'][1];
                                                                        }
-                                                               } elseif (!($GLOBALS['TYPO3_DB']->runningADOdbDriver('oci8') && $v['comparator'] === 'LIKE' && $functionMapping)) {
+                                                               } elseif (!($GLOBALS['TYPO3_DB']->runningADOdbDriver('oci8') && preg_match('/(NOT )?LIKE( BINARY)?/', $v['comparator']) && $functionMapping)) {
                                                                        $output .= trim(($v['table'] ? $v['table'] . '.' : '') . $v['field']);
                                                                }
                                                        }
 
                                                                // Set comparator:
                                                        if ($v['comparator']) {
+                                                               $isLikeOperator = preg_match('/(NOT )?LIKE( BINARY)?/', $v['comparator']);
                                                                switch (TRUE) {
-                                                                       case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('oci8') && $v['comparator'] === 'LIKE' && $functionMapping):
+                                                                       case ($GLOBALS['TYPO3_DB']->runningADOdbDriver('oci8') && $isLikeOperator && $functionMapping):
                                                                                                // Oracle cannot handle LIKE on CLOB fields - sigh
                                                                                        if (isset($v['value']['operator'])) {
                                                                                                $values = array();
@@ -533,6 +595,9 @@ class ux_t3lib_sqlparser extends t3lib_sqlparser {
                                                                                        } else {
                                                                                                $compareValue = $v['value'][1] . $this->compileAddslashes(trim($v['value'][0], '%')) . $v['value'][1];
                                                                                        }
+                                                                                       if (t3lib_div::isFirstPartOfStr($v['comparator'], 'NOT')) {
+                                                                                               $output .= 'NOT ';
+                                                                                       }
                                                                                                // To be on the safe side
                                                                                        $isLob = TRUE;
                                                                                        if ($v['table']) {
@@ -549,6 +614,32 @@ class ux_t3lib_sqlparser extends t3lib_sqlparser {
                                                                                        }
                                                                                break;
                                                                        default:
+                                                                               if ($isLikeOperator && $functionMapping) {
+                                                                                       if ($GLOBALS['TYPO3_DB']->runningADOdbDriver('postgres') ||
+                                                                                               $GLOBALS['TYPO3_DB']->runningADOdbDriver('postgres64') ||
+                                                                                               $GLOBALS['TYPO3_DB']->runningADOdbDriver('postgres7') ||
+                                                                                               $GLOBALS['TYPO3_DB']->runningADOdbDriver('postgres8')) {
+
+                                                                                                       // Remap (NOT)? LIKE to (NOT)? ILIKE
+                                                                                                       // and (NOT)? LIKE BINARY to (NOT)? LIKE
+                                                                                               switch ($v['comparator']) {
+                                                                                                       // Remap (NOT)? LIKE to (NOT)? ILIKE
+                                                                                                       case 'LIKE':
+                                                                                                               $v['comparator'] = 'ILIKE';
+                                                                                                               break;
+                                                                                                       case 'NOT LIKE':
+                                                                                                               $v['comparator'] = 'NOT ILIKE';
+                                                                                                               break;
+                                                                                                       default:
+                                                                                                               $v['comparator'] = str_replace(' BINARY', '', $v['comparator']);
+                                                                                                               break;
+                                                                                               }
+                                                                                       } else {
+                                                                                                       // No more BINARY operator
+                                                                                               $v['comparator'] = str_replace(' BINARY', '', $v['comparator']);
+                                                                                       }
+                                                                               }
+
                                                                                $output .= ' ' . $v['comparator'];
 
                                                                                        // Detecting value type; list or plain:
index 564403b..fa2f4a8 100644 (file)
Binary files a/typo3/sysext/dbal/doc/manual.sxw and b/typo3/sysext/dbal/doc/manual.sxw differ
index 7a26faa..85af6ed 100644 (file)
@@ -3,7 +3,7 @@
 ########################################################################
 # Extension Manager/Repository config file for ext "dbal".
 #
-# Auto generated 22-06-2010 17:18
+# Auto generated 23-08-2010 15:51
 #
 # Manual updates:
 # Only the data in the array - everything else is removed by next
@@ -32,13 +32,13 @@ $EM_CONF[$_EXTKEY] = array(
        'author_company' => '',
        'CGLcompliance' => '',
        'CGLcompliance_note' => '',
-       'version' => '1.1.7',
-       '_md5_values_when_last_written' => 'a:43:{s:9:"ChangeLog";s:4:"ba81";s:28:"class.tx_dbal_autoloader.php";s:4:"4781";s:29:"class.tx_dbal_installtool.php";s:4:"ffb8";s:26:"class.ux_db_list_extra.php";s:4:"7af1";s:21:"class.ux_t3lib_db.php";s:4:"5d57";s:28:"class.ux_t3lib_sqlparser.php";s:4:"4b4e";s:16:"ext_autoload.php";s:4:"821a";s:21:"ext_conf_template.txt";s:4:"f5cf";s:12:"ext_icon.gif";s:4:"c9ba";s:17:"ext_localconf.php";s:4:"afdd";s:14:"ext_tables.php";s:4:"8414";s:14:"ext_tables.sql";s:4:"1f95";s:19:"last_synched_target";s:4:"5d1b";s:27:"doc/class.tslib_fe.php.diff";s:4:"0083";s:14:"doc/manual.sxw";s:4:"b022";s:45:"handlers/class.tx_dbal_handler_openoffice.php";s:4:"8b11";s:43:"handlers/class.tx_dbal_handler_rawmysql.php";s:4:"c024";s:40:"handlers/class.tx_dbal_handler_xmldb.php";s:4:"a9bb";s:31:"lib/class.tx_dbal_sqlengine.php";s:4:"2ed1";s:33:"lib/class.tx_dbal_tsparserext.php";s:4:"862d";s:14:"mod1/clear.gif";s:4:"cc11";s:13:"mod1/conf.php";s:4:"6e63";s:14:"mod1/index.php";s:4:"0bd5";s:18:"mod1/locallang.xml";s:4:"0b57";s:22:"mod1/locallang_mod.xml";s:4:"86ef";s:19:"mod1/moduleicon.gif";s:4:"2b8f";s:10:"res/README";s:4:"be19";s:26:"res/Templates/install.html";s:4:"62c9";s:30:"res/oracle/indexed_search.diff";s:4:"ec81";s:23:"res/oracle/realurl.diff";s:4:"86da";s:25:"res/oracle/scheduler.diff";s:4:"7c06";s:27:"res/oracle/templavoila.diff";s:4:"1fd5";s:43:"res/postgresql/postgresql-compatibility.sql";s:4:"034c";s:22:"tests/BaseTestCase.php";s:4:"9e07";s:26:"tests/FakeDbConnection.php";s:4:"35f0";s:23:"tests/dbGeneralTest.php";s:4:"9bfc";s:21:"tests/dbMssqlTest.php";s:4:"4cbc";s:22:"tests/dbOracleTest.php";s:4:"16b6";s:26:"tests/dbPostgresqlTest.php";s:4:"27cd";s:30:"tests/sqlParserGeneralTest.php";s:4:"5953";s:31:"tests/fixtures/mssql.config.php";s:4:"0ec8";s:30:"tests/fixtures/oci8.config.php";s:4:"4a1a";s:36:"tests/fixtures/postgresql.config.php";s:4:"2296";}',
+       'version' => '1.2.0alpha1',
+       '_md5_values_when_last_written' => 'a:42:{s:9:"ChangeLog";s:4:"0ba7";s:28:"class.tx_dbal_autoloader.php";s:4:"8cd0";s:29:"class.tx_dbal_installtool.php";s:4:"29b5";s:26:"class.ux_db_list_extra.php";s:4:"60d9";s:21:"class.ux_t3lib_db.php";s:4:"6801";s:28:"class.ux_t3lib_sqlparser.php";s:4:"586b";s:16:"ext_autoload.php";s:4:"bd13";s:21:"ext_conf_template.txt";s:4:"f5cf";s:12:"ext_icon.gif";s:4:"c9ba";s:17:"ext_localconf.php";s:4:"5ece";s:14:"ext_tables.php";s:4:"b187";s:14:"ext_tables.sql";s:4:"1f95";s:27:"doc/class.tslib_fe.php.diff";s:4:"0083";s:14:"doc/manual.sxw";s:4:"57b6";s:45:"handlers/class.tx_dbal_handler_openoffice.php";s:4:"8556";s:43:"handlers/class.tx_dbal_handler_rawmysql.php";s:4:"ef52";s:40:"handlers/class.tx_dbal_handler_xmldb.php";s:4:"3ec1";s:31:"lib/class.tx_dbal_sqlengine.php";s:4:"75be";s:33:"lib/class.tx_dbal_tsparserext.php";s:4:"df12";s:14:"mod1/clear.gif";s:4:"cc11";s:13:"mod1/conf.php";s:4:"6e63";s:14:"mod1/index.php";s:4:"4a5e";s:18:"mod1/locallang.xml";s:4:"0b57";s:22:"mod1/locallang_mod.xml";s:4:"86ef";s:19:"mod1/moduleicon.gif";s:4:"2b8f";s:10:"res/README";s:4:"be19";s:26:"res/Templates/install.html";s:4:"62c9";s:30:"res/oracle/indexed_search.diff";s:4:"ec81";s:23:"res/oracle/realurl.diff";s:4:"86da";s:25:"res/oracle/scheduler.diff";s:4:"7c06";s:27:"res/oracle/templavoila.diff";s:4:"1fd5";s:43:"res/postgresql/postgresql-compatibility.sql";s:4:"bbff";s:22:"tests/BaseTestCase.php";s:4:"33db";s:26:"tests/FakeDbConnection.php";s:4:"cf49";s:23:"tests/dbGeneralTest.php";s:4:"dba5";s:21:"tests/dbMssqlTest.php";s:4:"a0f3";s:22:"tests/dbOracleTest.php";s:4:"2ff5";s:26:"tests/dbPostgresqlTest.php";s:4:"2f3f";s:30:"tests/sqlParserGeneralTest.php";s:4:"74b4";s:31:"tests/fixtures/mssql.config.php";s:4:"0e31";s:30:"tests/fixtures/oci8.config.php";s:4:"6c8a";s:36:"tests/fixtures/postgresql.config.php";s:4:"f13a";}',
        'constraints' => array(
                'depends' => array(
                        'adodb' => '5.10.0-',
                        'php' => '5.2.0-0.0.0',
-                       'typo3' => '4.4.0-4.4.99',
+                       'typo3' => '4.4.0beta1-0.0.0',
                ),
                'conflicts' => array(
                ),
index 9adc021..154a9cf 100644 (file)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2004-2010 Kasper Skaarhoj (kasper@typo3.com)
+*  (c) 2004-2009 Kasper Skaarhoj (kasper@typo3.com)
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -27,7 +27,7 @@
 /**
  * Contains an example DBAL handler class
  *
- * $Id: class.tx_dbal_handler_openoffice.php 28898 2010-01-16 14:32:35Z xperseguers $
+ * $Id: class.tx_dbal_handler_openoffice.php 35523 2010-07-11 14:04:44Z xperseguers $
  *
  * @author     Kasper Skaarhoj <kasper@typo3.com>
  */
index 8e1f873..8ac957b 100644 (file)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2004-2010 Kasper Skaarhoj (kasper@typo3.com)
+*  (c) 2004-2009 Kasper Skaarhoj (kasper@typo3.com)
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -27,7 +27,7 @@
 /**
  * Contains an example DBAL handler class
  *
- * $Id: class.tx_dbal_handler_rawmysql.php 25889 2009-10-27 10:09:11Z xperseguers $
+ * $Id: class.tx_dbal_handler_rawmysql.php 35523 2010-07-11 14:04:44Z xperseguers $
  *
  * @author     Kasper Skaarhoj <kasper@typo3.com>
  */
index 68d3677..95c672d 100644 (file)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2004-2010 Kasper Skaarhoj (kasper@typo3.com)
+*  (c) 2004-2009 Kasper Skaarhoj (kasper@typo3.com)
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -27,7 +27,7 @@
 /**
  * Contains an example DBAL handler class
  *
- * $Id: class.tx_dbal_handler_xmldb.php 25889 2009-10-27 10:09:11Z xperseguers $
+ * $Id: class.tx_dbal_handler_xmldb.php 35523 2010-07-11 14:04:44Z xperseguers $
  *
  * @author     Kasper Skaarhoj <kasper@typo3.com>
  */
index 34db8d8..edd0c31 100644 (file)
@@ -1 +1 @@
-https://svn.typo3.org/TYPO3v4/Extensions/dbal/tags/1.1.7/
+https://svn.typo3.org/TYPO3v4/Extensions/dbal/tags/1.2.0alpha1/
index eb61e04..d6e0421 100644 (file)
@@ -3,7 +3,7 @@
 *  Copyright notice
 *
 *  (c) 2009-2010 Xavier Perseguers <typo3@perseguers.ch>
-*  (c) 2004-2010 Kasper Skaarhoj <kasperYYYY@typo3.com>
+*  (c) 2004-2009 Kasper Skaarhoj <kasperYYYY@typo3.com>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -30,7 +30,7 @@
 /**
  * PHP SQL engine
  *
- * $Id: class.tx_dbal_sqlengine.php 28572 2010-01-08 17:13:29Z xperseguers $
+ * $Id: class.tx_dbal_sqlengine.php 35523 2010-07-11 14:04:44Z xperseguers $
  *
  * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
  * @author Xavier Perseguers <typo3@perseguers.ch>
index ac797b3..a0bec1c 100644 (file)
@@ -29,7 +29,7 @@
 /**
  * Class that renders fields for the Extension Manager configuration.
  *
- * $Id: class.tx_dbal_tsparserext.php 28572 2010-01-08 17:13:29Z xperseguers $
+ * $Id: class.tx_dbal_tsparserext.php 36759 2010-08-14 15:55:24Z xperseguers $
  * @author Xavier Perseguers <typo3@perseguers.ch>
  *
  * @package TYPO3
index 5473607..8b32363 100644 (file)
@@ -2,8 +2,8 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2004-2010 Kasper Skaarhoj (kasperYYYY@typo3.com)
-*  (c) 2004-2010 Karsten Dambekalns (karsten@typo3.org)
+*  (c) 2004-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
+*  (c) 2004-2009 Karsten Dambekalns (karsten@typo3.org)
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
index f2f52ad..8b31aa4 100644 (file)
@@ -13,7 +13,7 @@
 -- Note: You may consider having a look at project mysqlcompat on http://pgfoundry.org/projects/mysqlcompat
 --       and report in DBAL bugtracker if you need another compatibility operator added.
 --
--- $Id: postgresql-compatibility.sql 29977 2010-02-13 13:18:32Z xperseguers $
+-- $Id: postgresql-compatibility.sql 35742 2010-07-16 13:22:56Z xperseguers $
 -- R. van Twisk <typo3@rvt.dds.nl>
 
 
@@ -77,6 +77,28 @@ RETURNS anyelement AS $$
 SELECT COALESCE($1, $2)
 $$ IMMUTABLE STRICT LANGUAGE SQL;
 
+-- FIND_IN_SET
+-- FIND_IN_SET()
+CREATE OR REPLACE FUNCTION find_in_set(text, text)
+RETURNS integer AS $$
+DECLARE
+       list text[];
+       len integer;
+BEGIN
+       IF $2 = '' THEN
+               RETURN 0;
+       END IF;
+       list := pg_catalog.string_to_array($2, ',');
+       len := pg_catalog.array_upper(list, 1);
+       FOR i IN 1..len LOOP
+               IF list[i] = $1 THEN
+                       RETURN i;
+               END IF;
+       END LOOP;
+       RETURN 0;
+END;
+$$ STRICT IMMUTABLE LANGUAGE PLPGSQL;
+
 -- Remove Compatibility operators
 --
 --DROP OPERATOR ~~ (integer,text);
index 95af056..dba0fdd 100644 (file)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2009-2010 Robert Lemke <robert@typo3.org>
+*  (c) 2009 Robert Lemke <robert@typo3.org>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -28,7 +28,7 @@
  * Subclass this base class if you want to take advantage of the framework
  * capabilities.
  *
- * $Id: BaseTestCase.php 27006 2009-11-25 22:08:07Z xperseguers $
+ * $Id: BaseTestCase.php 36760 2010-08-14 15:58:41Z xperseguers $
  *
  * @author Robert Lemke <robert@typo3.org>
  *
index 95b43c4..a1cc177 100644 (file)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2009-2010 Xavier Perseguers <typo3@perseguers.ch>
+*  (c) 2009 Xavier Perseguers <typo3@perseguers.ch>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -26,7 +26,7 @@
 /**
  * Fake ADOdb connection factory.
  *
- * $Id: FakeDbConnection.php 27006 2009-11-25 22:08:07Z xperseguers $
+ * $Id: FakeDbConnection.php 36760 2010-08-14 15:58:41Z xperseguers $
  *
  * @author Xavier Perseguers <typo3@perseguers.ch>
  *
index fcc9488..1b37702 100644 (file)
@@ -62,7 +62,7 @@ class dbGeneralTest extends BaseTestCase {
                $this->db = $GLOBALS['TYPO3_DB'];
                $this->temporaryFiles = array();
 
-               $className =  self::buildAccessibleProxy('ux_t3lib_db');
+               $className = self::buildAccessibleProxy('ux_t3lib_db');
                $GLOBALS['TYPO3_DB'] = new $className;
                $GLOBALS['TYPO3_DB']->lastHandlerKey = '_DEFAULT';
        }
@@ -242,5 +242,61 @@ class dbGeneralTest extends BaseTestCase {
                $expected = 'SELECT * FROM pages WHERE MAX(uid) IN (1,2,3,4)';
                $this->assertEquals($expected, $query);
        }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=12535
+        */
+       public function likeBinaryOperatorIsKept() {
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery(
+                       '*',
+                       'tt_content',
+                       'bodytext LIKE BINARY \'test\''
+               ));
+               $expected = 'SELECT * FROM tt_content WHERE bodytext LIKE BINARY \'test\'';
+               $this->assertEquals($expected, $query);
+       }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=12535
+        */
+       public function notLikeBinaryOperatorIsKept() {
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery(
+                       '*',
+                       'tt_content',
+                       'bodytext NOT LIKE BINARY \'test\''
+               ));
+               $expected = 'SELECT * FROM tt_content WHERE bodytext NOT LIKE BINARY \'test\'';
+               $this->assertEquals($expected, $query);
+       }
+
+       ///////////////////////////////////////
+       // Tests concerning prepared queries
+       ///////////////////////////////////////
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=15457
+        */
+       public function similarNamedParametersAreProperlyReplaced() {
+               $sql = 'SELECT * FROM cache WHERE tag = :tag1 OR tag = :tag10 OR tag = :tag100';
+               $parameterValues = array(
+                       ':tag1'   => 'tag-one',
+                       ':tag10'  => 'tag-two',
+                       ':tag100' => 'tag-three',
+               );
+
+               $className = self::buildAccessibleProxy('t3lib_db_PreparedStatement');
+               $query = $sql;
+               $precompiledQueryParts = array();
+               $statement = new $className($sql, 'cache');
+               $statement->bindValues($parameterValues);
+               $parameters = $statement->_get('parameters');
+
+               $statement->_callRef('replaceValuesInQuery', $query, $precompiledQueryParts, $parameters);
+               $expected = 'SELECT * FROM cache WHERE tag = \'tag-one\' OR tag = \'tag-two\' OR tag = \'tag-three\'';
+               $this->assertEquals($expected, $query);
+       }
 }
 ?>
\ No newline at end of file
index 17885fe..f86ff2c 100644 (file)
@@ -127,6 +127,20 @@ class dbMssqlTest extends BaseTestCase {
                }
        }
 
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=14985
+        */
+       public function findInSetIsProperlyRemapped() {
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery(
+                       '*',
+                       'fe_users',
+                       'FIND_IN_SET(10, usergroup)'
+               ));
+               $expected = 'SELECT * FROM "fe_users" WHERE \',\'+"usergroup"+\',\' LIKE \'%,10,%\'';
+               $this->assertEquals($expected, $query);
+       }
+
        ///////////////////////////////////////
        // Tests concerning remapping with
        // external (non-TYPO3) databases
@@ -143,8 +157,8 @@ class dbMssqlTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT "MemberID", "FirstName", "LastName" FROM "Members" WHERE 0 = 0 AND 1 = 1';
                $this->assertEquals($expected, $query);
@@ -202,8 +216,8 @@ class dbMssqlTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT *, CASE WHEN CHARINDEX(\'(fce)\', "ds", 4) > 0 THEN 2 ELSE 1 END AS "scope" FROM "tx_templavoila_tmplobj" WHERE 1 = 1';
                $this->assertEquals($expected, $query);
@@ -223,8 +237,8 @@ class dbMssqlTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT *, CASE WHEN CHARINDEX(\'(fce)\', "tx_templavoila_tmplobj"."ds", 4) > 0 THEN 2 ELSE 1 END AS "scope" FROM "tx_templavoila_tmplobj" WHERE 1 = 1';
                $this->assertEquals($expected, $query);
index 35ad84b..a61309a 100644 (file)
@@ -362,8 +362,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT * FROM "ext_tt_news_cat"';
                $expected .= ' INNER JOIN "ext_tt_news_cat_mm" ON "ext_tt_news_cat"."cat_uid"="ext_tt_news_cat_mm"."uid_foreign"';
@@ -383,8 +383,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT "tstamp", "script", SUM("exec_time") AS "calc_sum", COUNT(*) AS "qrycount", MAX("errorflag") AS "error" FROM "tx_dbal_debuglog" WHERE 1 = 1';
                $this->assertEquals($expected, $query);
@@ -401,8 +401,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT MAX("ext_tt_news_cat"."cat_uid") AS "biggest_id" FROM "ext_tt_news_cat"';
                $expected .= ' INNER JOIN "ext_tt_news_cat_mm" ON "ext_tt_news_cat"."cat_uid"="ext_tt_news_cat_mm"."uid_foreign"';
@@ -423,8 +423,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT * FROM "sys_refindex", "tx_dam_file_tracking" WHERE "sys_refindex"."tablename" = \'tx_dam_file_tracking\'';
                $expected .= ' AND (instr("sys_refindex"."ref_string", CONCAT("tx_dam_file_tracking"."path","tx_dam_file_tracking"."filename"),1,1) > 0)';
@@ -442,8 +442,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = 'cpg_categories.pos';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT "cpg_categories"."uid", "cpg_categories"."name" FROM "cpg_categories", "my_pages" WHERE "my_pages"."page_uid" = "cpg_categories"."page_id"';
                $expected .= ' AND "my_pages"."deleted" = 0 AND 1 = 1 ORDER BY "cpg_categories"."pos"';
@@ -461,8 +461,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT "news"."news_uid" FROM "ext_tt_news" AS "news" WHERE "news"."news_uid" = 1';
                $this->assertEquals($expected, $query);
@@ -482,8 +482,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT "tt_news_cat"."news_uid" FROM "ext_tt_news" AS "tt_news_cat" WHERE "tt_news_cat"."news_uid" = 1';
                $this->assertEquals($expected, $query);
@@ -501,7 +501,7 @@ class dbOracleTest extends BaseTestCase {
                $orderBy      = '';
 
                        // First call to possibly alter (in memory) the mapping from localconf.php
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
 
                $selectFields = 'uid';
                $fromTables   = 'foo';
@@ -509,8 +509,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT "uid" FROM "foo" WHERE "uid" = 1';
                $this->assertEquals($expected, $query);
@@ -529,8 +529,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT "cat"."cat_uid", "cat_mm"."local_uid", "news"."news_uid"';
                $expected .= ' FROM "ext_tt_news_cat" AS "cat"';
@@ -551,8 +551,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = 'foo.uid';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT "foo"."news_uid" FROM "ext_tt_news" AS "foo"';
                $expected .= ' INNER JOIN "ext_tt_news_cat_mm" ON "ext_tt_news_cat_mm"."local_uid"="foo"."news_uid"';
@@ -574,8 +574,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = 'foo.uid';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT "foo"."news_uid" FROM "ext_tt_news" AS "foo"';
                $expected .= ' INNER JOIN "ext_tt_news_cat_mm" ON "ext_tt_news_cat_mm"."local_uid"="foo"."news_uid"';
@@ -600,8 +600,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT "foo"."news_uid" FROM "ext_tt_news" AS "foo"';
                $expected .= ' WHERE "news_uid" IN (';
@@ -623,8 +623,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = 'pages.uid';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT "pages"."news_uid" FROM "ext_tt_news" AS "pages"';
                $expected .= ' INNER JOIN "ext_tt_news_cat_mm" AS "cat_mm" ON "cat_mm"."local_uid"="pages"."news_uid"';
@@ -659,6 +659,28 @@ class dbOracleTest extends BaseTestCase {
 
        /**
         * @test
+        * @see http://bugs.typo3.org/view.php?id=15253
+        */
+       public function notLikeIsRemappedAccordingToFieldType() {
+               $select = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery(
+                       '*',
+                       'tt_content',
+                       'tt_content.bodytext NOT LIKE \'foo%\''
+               ));
+               $expected = 'SELECT * FROM "tt_content" WHERE NOT (dbms_lob.instr("tt_content"."bodytext", \'foo\',1,1) > 0)';
+               $this->assertEquals($expected, $select);
+
+               $select = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery(
+                       '*',
+                       'fe_users',
+                       'fe_users.usergroup NOT LIKE \'2\''
+               ));
+               $expected = 'SELECT * FROM "fe_users" WHERE NOT (instr("fe_users"."usergroup", \'2\',1,1) > 0)';
+               $this->assertEquals($expected, $select);
+       }
+
+       /**
+        * @test
         * @see http://bugs.typo3.org/view.php?id=14479
         */
        public function instrIsUsedForCEOnPages() {
@@ -810,8 +832,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT * FROM "tx_crawler_queue" WHERE "process_id" IN (SELECT "ps_id" FROM "tx_crawler_ps" WHERE "is_active" = 0 AND "deleted" = 0)';
                $this->assertEquals($expected, $query);
@@ -913,8 +935,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT * FROM "tx_crawler_ps" WHERE "is_active" = 0 AND NOT EXISTS (';
                $expected .= 'SELECT * FROM "tx_crawler_queue" WHERE "tx_crawler_queue"."process_id" = "tx_crawler_ps"."ps_id" AND "tx_crawler_queue"."exec_time" = 0';
@@ -959,8 +981,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT "ps_id", CASE "is_active" WHEN 1 THEN \'one\' WHEN 2 THEN \'two\' ELSE \'out of range\' END AS "number" ';
                $expected .= 'FROM "tx_crawler_ps" WHERE 1 = 1';
@@ -982,8 +1004,8 @@ class dbOracleTest extends BaseTestCase {
                $groupBy      = '';
                $orderBy      = '';
 
-               $GLOBALS['TYPO3_DB']->_callRef('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
-               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery($selectFields, $fromTables, $whereClause, $groupBy, $orderBy));
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
 
                $expected = 'SELECT "ps_id", CASE "ext_tt_news"."news_uid" WHEN 1 THEN \'one\' WHEN 2 THEN \'two\' ELSE \'out of range\' END AS "number" ';
                $expected .= 'FROM "tx_crawler_ps", "ext_tt_news" WHERE 1 = 1';
@@ -1037,5 +1059,65 @@ class dbOracleTest extends BaseTestCase {
                $expected = 'SELECT * FROM "tt_news_cat_mm" WHERE NVL("tt_news_cat_mm"."uid_foreign", 0) IN (21,22)';
                $this->assertEquals($expected, $query);
        }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=14985
+        */
+       public function findInSetIsProperlyRemapped() {
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery(
+                       '*',
+                       'fe_users',
+                       'FIND_IN_SET(10, usergroup)'
+               ));
+               $expected = 'SELECT * FROM "fe_users" WHERE \',\'||"usergroup"||\',\' LIKE \'%,10,%\'';
+               $this->assertEquals($expected, $query);
+       }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=14985
+        */
+       public function findInSetFieldIsProperlyRemapped() {
+               $selectFields = 'fe_group';
+               $fromTables   = 'tt_news';
+               $whereClause  = 'FIND_IN_SET(10, fe_group)';
+               $groupBy      = '';
+               $orderBy      = '';
+
+               $remappedParameters = $GLOBALS['TYPO3_DB']->_call('map_remapSELECTQueryParts', $selectFields, $fromTables, $whereClause, $groupBy, $orderBy);
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->_call('SELECTqueryFromArray', $remappedParameters));
+
+               $expected = 'SELECT "usergroup" FROM "ext_tt_news" WHERE \',\'||"ext_tt_news"."usergroup"||\',\' LIKE \'%,10,%\'';
+               $this->assertEquals($expected, $query);
+       }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=14818
+        */
+       public function listQueryIsProperlyRemapped() {
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery(
+                       '*',
+                       'fe_users',
+                       $GLOBALS['TYPO3_DB']->listQuery('usergroup', 10, 'fe_users')
+               ));
+               $expected = 'SELECT * FROM "fe_users" WHERE \',\'||"usergroup"||\',\' LIKE \'%,10,%\'';
+               $this->assertEquals($expected, $query);
+       }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=12535
+        */
+       public function likeBinaryOperatorIsRemoved() {
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery(
+                       '*',
+                       'tt_content',
+                       'bodytext LIKE BINARY \'test\''
+               ));
+               $expected = 'SELECT * FROM "tt_content" WHERE (dbms_lob.instr("bodytext", \'test\',1,1) > 0)';
+               $this->assertEquals($expected, $query);
+       }
 }
 ?>
\ No newline at end of file
index 4d3209b..6d5a800 100644 (file)
@@ -160,5 +160,75 @@ class dbPostgresqlTest extends BaseTestCase {
                $expected = 'SELECT * FROM "be_users" WHERE 1 = 1 LIMIT 40 OFFSET 20';
                $this->assertEquals($expected, $query);
        }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=14985
+        */
+       public function findInSetIsProperlyRemapped() {
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery(
+                       '*',
+                       'fe_users',
+                       'FIND_IN_SET(10, usergroup)'
+               ));
+               $expected = 'SELECT * FROM "fe_users" WHERE FIND_IN_SET(10, "usergroup") != 0';
+               $this->assertEquals($expected, $query);
+       }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=12535
+        */
+       public function likeBinaryOperatorIsRemappedToLike() {
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery(
+                       '*',
+                       'tt_content',
+                       'bodytext LIKE BINARY \'test\''
+               ));
+               $expected = 'SELECT * FROM "tt_content" WHERE "bodytext" LIKE \'test\'';
+               $this->assertEquals($expected, $query);
+       }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=12535
+        */
+       public function notLikeBinaryOperatorIsRemappedToNotLike() {
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery(
+                       '*',
+                       'tt_content',
+                       'bodytext NOT LIKE BINARY \'test\''
+               ));
+               $expected = 'SELECT * FROM "tt_content" WHERE "bodytext" NOT LIKE \'test\'';
+               $this->assertEquals($expected, $query);
+       }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=12535
+        */
+       public function likeOperatorIsRemappedToIlike() {
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery(
+                       '*',
+                       'tt_content',
+                       'bodytext LIKE \'test\''
+               ));
+               $expected = 'SELECT * FROM "tt_content" WHERE "bodytext" ILIKE \'test\'';
+               $this->assertEquals($expected, $query);
+       }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=12535
+        */
+       public function notLikeOperatorIsRemappedToNotIlike() {
+               $query = $this->cleanSql($GLOBALS['TYPO3_DB']->SELECTquery(
+                       '*',
+                       'tt_content',
+                       'bodytext NOT LIKE \'test\''
+               ));
+               $expected = 'SELECT * FROM "tt_content" WHERE "bodytext" NOT ILIKE \'test\'';
+               $this->assertEquals($expected, $query);
+       }
 }
 ?>
\ No newline at end of file
index 66152eb..133de08 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * MS SQL configuration
  *
- * $Id: mssql.config.php 29886 2010-02-09 21:39:29Z xperseguers $
+ * $Id: mssql.config.php 36760 2010-08-14 15:58:41Z xperseguers $
  *
  * @author Xavier Perseguers <typo3@perseguers.ch>
  *
index 45a34c9..149df81 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * Oracle configuration
  *
- * $Id: oci8.config.php 27125 2009-11-29 17:21:28Z xperseguers $
+ * $Id: oci8.config.php 36760 2010-08-14 15:58:41Z xperseguers $
  *
  * @author Xavier Perseguers <typo3@perseguers.ch>
  *
@@ -44,7 +44,8 @@ $TYPO3_CONF_VARS['EXTCONF']['dbal']['mapping'] = array(
        'tt_news' => array(
                'mapTableName' => 'ext_tt_news',
                'mapFieldNames' => array(
-                       'uid' => 'news_uid',
+                       'uid'      => 'news_uid',
+                       'fe_group' => 'usergroup',
                ),
        ),
        'tt_news_cat' => array(
index 54adc07..eba6932 100644 (file)
@@ -367,6 +367,20 @@ class sqlParserGeneralTest extends BaseTestCase {
                $this->assertEquals($expected, $alterTable[0]);
        }
 
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=14985
+        */
+       public function canParseFindInSetStatement() {
+               $parseString = 'SELECT * FROM fe_users WHERE FIND_IN_SET(10, usergroup)';
+               $components = $this->fixture->_callRef('parseSELECT', $parseString);
+
+               $this->assertTrue(is_array($components), $components);
+               $selectTable = $this->cleanSql($this->fixture->_callRef('compileSELECT', $components));
+               $expected = 'SELECT * FROM fe_users WHERE FIND_IN_SET(10, usergroup)';
+               $this->assertEquals($expected, $selectTable);
+       }
+
        ///////////////////////////////////////
        // Tests concerning JOINs
        ///////////////////////////////////////
@@ -671,5 +685,98 @@ class sqlParserGeneralTest extends BaseTestCase {
 
                $this->assertEquals($expected, $actual);
        }
+
+       ///////////////////////////////////////
+       // Tests concerning prepared queries
+       ///////////////////////////////////////
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=15457
+        */
+       public function namedPlaceholderIsSupported() {
+               $sql = 'SELECT * FROM pages WHERE pid = :pid ORDER BY title';
+               $expected = 'SELECT * FROM pages WHERE pid = :pid ORDER BY title';
+               $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
+
+               $this->assertEquals($expected, $actual);
+       }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=15457
+        */
+       public function questionMarkPlaceholderIsSupported() {
+               $sql = 'SELECT * FROM pages WHERE pid = ? ORDER BY title';
+               $expected = 'SELECT * FROM pages WHERE pid = ? ORDER BY title';
+               $actual = $this->cleanSql($this->fixture->debug_testSQL($sql));
+
+               $this->assertEquals($expected, $actual);
+       }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=15457
+        */
+       public function parametersAreReferenced() {
+               $sql = 'SELECT * FROM pages WHERE pid = :pid1 OR pid = :pid2';
+               $components = $this->fixture->_callRef('parseSELECT', $sql);
+
+               $this->assertTrue(is_array($components['parameters']), 'References to parameters not found');
+               $this->assertEquals(2, count($components['parameters']));
+               $this->assertTrue(is_array($components['parameters']), 'References to parameters not found');
+               $this->assertTrue(isset($components['parameters'][':pid1']));
+               $this->assertTrue(isset($components['parameters'][':pid2']));
+       }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=15457
+        */
+       public function sameParameterIsReferencedInSubquery() {
+               $sql = 'SELECT * FROM pages WHERE uid = :pageId OR uid IN (SELECT uid FROM pages WHERE pid = :pageId)';
+               $pageId = 12;
+
+               $components = $this->fixture->_callRef('parseSELECT', $sql);
+               $components['parameters'][':pageId'][0] = $pageId;
+               $query = $this->cleanSql($this->fixture->_callRef('compileSELECT', $components));
+               $expected = 'SELECT * FROM pages WHERE uid = 12 OR uid IN (SELECT uid FROM pages WHERE pid = 12)';
+
+               $this->assertEquals($expected, $query);
+       }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=15457
+        */
+       public function namedParametersMayBeSafelyReplaced() {
+               $sql = 'SELECT * FROM pages WHERE pid = :pid AND title NOT LIKE \':pid\'';
+               $pid = 12;
+
+               $components = $this->fixture->_callRef('parseSELECT', $sql);
+               $components['parameters'][':pid'][0] = $pid;
+               $query = $this->cleanSql($this->fixture->_callRef('compileSELECT', $components));
+               $expected = 'SELECT * FROM pages WHERE pid = ' . $pid . ' AND title NOT LIKE \':pid\'';
+
+               $this->assertEquals($expected, $query);
+       }
+
+       /**
+        * @test
+        * @see http://bugs.typo3.org/view.php?id=15457
+        */
+       public function questionMarkParametersMayBeSafelyReplaced() {
+               $sql = 'SELECT * FROM pages WHERE pid = ? AND timestamp < ? AND title != \'How to test?\'';
+               $parameterValues = array(12, 1281782690);
+
+               $components = $this->fixture->_callRef('parseSELECT', $sql);
+               for ($i = 0; $i < count($components['parameters']['?']); $i++) {
+                       $components['parameters']['?'][$i][0] = $parameterValues[$i];
+               }
+               $query = $this->cleanSql($this->fixture->_callRef('compileSELECT', $components));
+               $expected = 'SELECT * FROM pages WHERE pid = 12 AND timestamp < 1281782690 AND title != \'How to test?\'';
+
+               $this->assertEquals($expected, $query);
+       }
 }
 ?>
\ No newline at end of file