[BUGFIX] Autoloader Cache is not updated
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_db.php
index 32272fc..3d614e4 100644 (file)
 <?php
 /***************************************************************
-*  Copyright notice
-*
-*  (c) 2004-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
-*  All rights reserved
-*
-*  This script is part of the TYPO3 project. The TYPO3 project is
-*  free software; you can redistribute it and/or modify
-*  it under the terms of the GNU General Public License as published by
-*  the Free Software Foundation; either version 2 of the License, or
-*  (at your option) any later version.
-*
-*  The GNU General Public License can be found at
-*  http://www.gnu.org/copyleft/gpl.html.
-*  A copy is found in the textfile GPL.txt and important notices to the license
-*  from the author is found in LICENSE.txt distributed with these scripts.
-*
-*
-*  This script is distributed in the hope that it will be useful,
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*  GNU General Public License for more details.
-*
-*  This copyright notice MUST APPEAR in all copies of the script!
-***************************************************************/
-/**
- * Contains the class "t3lib_db" containing functions for building SQL queries
- * and mysql wrappers, thus providing a foundational API to all database
- * interaction.
- * This class is instantiated globally as $TYPO3_DB in TYPO3 scripts.
- *
- * $Id$
- *
- * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
- */
-/**
- * [CLASS/FUNCTION INDEX of SCRIPT]
- *
- *
- *
- *  138: class t3lib_DB
- *
- *              SECTION: Query execution
- *  175:     function exec_INSERTquery($table,$fields_values,$no_quote_fields=FALSE)
- *  192:     function exec_UPDATEquery($table,$where,$fields_values,$no_quote_fields=FALSE)
- *  206:     function exec_DELETEquery($table,$where)
- *  225:     function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='')
- *  250:     function exec_SELECT_mm_query($select,$local_table,$mm_table,$foreign_table,$whereClause='',$groupBy='',$orderBy='',$limit='')
- *  278:     function exec_SELECT_queryArray($queryParts)
- *  301:     function exec_SELECTgetRows($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='',$uidIndexField='')
+ *  Copyright notice
  *
- *              SECTION: Query building
- *  346:     function INSERTquery($table,$fields_values,$no_quote_fields=FALSE)
- *  381:     function UPDATEquery($table,$where,$fields_values,$no_quote_fields=FALSE)
- *  422:     function DELETEquery($table,$where)
- *  451:     function SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='')
- *  492:     function listQuery($field, $value, $table)
- *  506:     function searchQuery($searchWords,$fields,$table)
+ *  (c) 2004-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
+ *  All rights reserved
  *
- *              SECTION: Various helper functions
- *  552:     function fullQuoteStr($str, $table)
- *  569:     function fullQuoteArray($arr, $table, $noQuote=FALSE)
- *  596:     function quoteStr($str, $table)
- *  612:     function escapeStrForLike($str, $table)
- *  625:     function cleanIntArray($arr)
- *  641:     function cleanIntList($list)
- *  655:     function stripOrderBy($str)
- *  669:     function stripGroupBy($str)
- *  681:     function splitGroupOrderLimit($str)
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
  *
- *              SECTION: MySQL wrapper functions
- *  749:     function sql($db,$query)
- *  763:     function sql_query($query)
- *  776:     function sql_error()
- *  788:     function sql_num_rows($res)
- *  800:     function sql_fetch_assoc($res)
- *  813:     function sql_fetch_row($res)
- *  825:     function sql_free_result($res)
- *  836:     function sql_insert_id()
- *  847:     function sql_affected_rows()
- *  860:     function sql_data_seek($res,$seek)
- *  873:     function sql_field_type($res,$pointer)
- *  887:     function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password)
- *  915:     function sql_select_db($TYPO3_db)
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
  *
- *              SECTION: SQL admin functions
- *  947:     function admin_get_dbs()
- *  965:     function admin_get_tables()
- *  984:     function admin_get_fields($tableName)
- * 1002:     function admin_get_keys($tableName)
- * 1020:     function admin_query($query)
  *
- *              SECTION: Connecting service
- * 1048:     function connectDB()
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
  *
- *              SECTION: Debugging
- * 1086:     function debug($func)
- *
- * TOTAL FUNCTIONS: 42
- * (This index is automatically created/updated by the extension "extdeveval")
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+/**
+ * Contains the class "t3lib_db" containing functions for building SQL queries
+ * and mysql wrappers, thus providing a foundational API to all database
+ * interaction.
+ * This class is instantiated globally as $TYPO3_DB in TYPO3 scripts.
  *
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
  */
 
 
-
-
-
-
-
-
-
-
-
-
 /**
  * TYPO3 "database wrapper" class (new in 3.6.0)
  * This class contains
  *
  * USE:
  * In all TYPO3 scripts the global variable $TYPO3_DB is an instance of this class. Use that.
- * Eg.                 $GLOBALS['TYPO3_DB']->sql_fetch_assoc()
+ * Eg.          $GLOBALS['TYPO3_DB']->sql_fetch_assoc()
  *
- * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
  * @package TYPO3
  * @subpackage t3lib
  */
@@ -141,10 +62,10 @@ class t3lib_DB {
 
 
                // Debug:
-       var $debugOutput = FALSE;               // Set "TRUE" if you want database errors outputted.
-       var $debug_lastBuiltQuery = '';         // Internally: Set to last built query (not necessarily executed...)
-       var $store_lastBuiltQuery = FALSE;      // Set "TRUE" if you want the last built query to be stored in $debug_lastBuiltQuery independent of $this->debugOutput
-       var $explainOutput = 0;                 // Set this to 1 to get queries explained (devIPmask must match). Set the value to 2 to the same but disregarding the devIPmask. There is an alternative option to enable explain output in the admin panel under "TypoScript", which will produce much nicer output, but only works in FE.
+       var $debugOutput = FALSE; // Set "TRUE" or "1" if you want database errors outputted. Set to "2" if you also want successful database actions outputted.
+       var $debug_lastBuiltQuery = ''; // Internally: Set to last built query (not necessarily executed...)
+       var $store_lastBuiltQuery = FALSE; // Set "TRUE" if you want the last built query to be stored in $debug_lastBuiltQuery independent of $this->debugOutput
+       var $explainOutput = 0; // Set this to 1 to get queries explained (devIPmask must match). Set the value to 2 to the same but disregarding the devIPmask. There is an alternative option to enable explain output in the admin panel under "TypoScript", which will produce much nicer output, but only works in FE.
 
                // Default link identifier:
        var $link = FALSE;
@@ -152,7 +73,15 @@ class t3lib_DB {
                // Default character set, applies unless character set or collation are explicitely set
        var $default_charset = 'utf8';
 
+       /**
+        * @var t3lib_DB_preProcessQueryHook[]
+        */
+       protected $preProcessHookObjects = array();
 
+       /**
+        * @var t3lib_DB_postProcessQueryHook[]
+        */
+       protected $postProcessHookObjects = array();
 
 
        /************************************
@@ -183,6 +112,9 @@ class t3lib_DB {
                if ($this->debugOutput) {
                        $this->debug('exec_INSERTquery');
                }
+               foreach ($this->postProcessHookObjects as $hookObject) {
+                       $hookObject->exec_INSERTquery_postProcessAction($table, $fields_values, $no_quote_fields, $this);
+               }
                return $res;
        }
 
@@ -200,6 +132,9 @@ class t3lib_DB {
                if ($this->debugOutput) {
                        $this->debug('exec_INSERTmultipleRows');
                }
+               foreach ($this->postProcessHookObjects as $hookObject) {
+                       $hookObject->exec_INSERTmultipleRows_postProcessAction($table, $fields, $rows, $no_quote_fields, $this);
+               }
                return $res;
        }
 
@@ -219,6 +154,9 @@ class t3lib_DB {
                if ($this->debugOutput) {
                        $this->debug('exec_UPDATEquery');
                }
+               foreach ($this->postProcessHookObjects as $hookObject) {
+                       $hookObject->exec_UPDATEquery_postProcessAction($table, $where, $fields_values, $no_quote_fields, $this);
+               }
                return $res;
        }
 
@@ -235,6 +173,9 @@ class t3lib_DB {
                if ($this->debugOutput) {
                        $this->debug('exec_DELETEquery');
                }
+               foreach ($this->postProcessHookObjects as $hookObject) {
+                       $hookObject->exec_DELETEquery_postProcessAction($table, $where, $this);
+               }
                return $res;
        }
 
@@ -245,7 +186,7 @@ class t3lib_DB {
         *
         * @param       string          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 ...". Required value.
-        * @param       string          Optional additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself! DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
+        * @param       string          additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself! DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
         * @param       string          Optional GROUP BY field(s), if none, supply blank string.
         * @param       string          Optional ORDER BY field(s), if none, supply blank string.
         * @param       string          Optional LIMIT value ([begin,]max), if none, supply blank string.
@@ -269,7 +210,7 @@ class t3lib_DB {
         * Creates and executes a SELECT query, selecting fields ($select) from two/three tables joined
         * Use $mm_table together with $local_table or $foreign_table to select over two tables. Or use all three tables to select the full MM-relation.
         * The JOIN is done with [$local_table].uid <--> [$mm_table].uid_local  / [$mm_table].uid_foreign <--> [$foreign_table].uid
-        * The function is very useful for selecting MM-relations between tables adhering to the MM-format used by TCE (TYPO3 Core Engine). See the section on $TCA in Inside TYPO3 for more details.
+        * The function is very useful for selecting MM-relations between tables adhering to the MM-format used by TCE (TYPO3 Core Engine). See the section on $GLOBALS['TCA'] in Inside TYPO3 for more details.
         *
         * Usage: 12 (spec. ext. sys_action, sys_messages, sys_todos)
         *
@@ -300,14 +241,14 @@ class t3lib_DB {
                }
 
                return $this->exec_SELECTquery(
-                                       $select,
-                                       $tables,
-                                               // whereClauseMightContainGroupOrderBy
-                                       $mmWhere . ' ' . $whereClause,
-                                       $groupBy,
-                                       $orderBy,
-                                       $limit
-                               );
+                       $select,
+                       $tables,
+                               // whereClauseMightContainGroupOrderBy
+                               $mmWhere . ' ' . $whereClause,
+                       $groupBy,
+                       $orderBy,
+                       $limit
+               );
        }
 
        /**
@@ -356,7 +297,9 @@ class t3lib_DB {
                                        $output[$tempRow[$uidIndexField]] = $tempRow;
                                }
                        } else {
-                               while ($output[] = $this->sql_fetch_assoc($res));
+                               while ($output[] = $this->sql_fetch_assoc($res)) {
+                                       ;
+                               }
                                array_pop($output);
                        }
                        $this->sql_free_result($res);
@@ -365,17 +308,47 @@ class t3lib_DB {
        }
 
        /**
+        * Creates and executes a SELECT SQL-statement AND gets a result set and returns an array with a single record in.
+        * LIMIT is automatically set to 1 and can not be overridden.
+        *
+        * @param string $select_fields: List of fields to select from the table.
+        * @param string $from_table: Table(s) from which to select.
+        * @param string $where_clause: Optional additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
+        * @param string $groupBy: Optional GROUP BY field(s), if none, supply blank string.
+        * @param string $orderBy: Optional ORDER BY field(s), if none, supply blank string.
+        * @param boolean $numIndex: If set, the result will be fetched with sql_fetch_row, otherwise sql_fetch_assoc will be used.
+        * @return array Single row or NULL if it fails.
+        */
+       public function exec_SELECTgetSingleRow($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $numIndex = FALSE) {
+               $res = $this->exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, '1');
+               if ($this->debugOutput) {
+                       $this->debug('exec_SELECTquery');
+               }
+
+               $output = NULL;
+               if ($res) {
+                       if ($numIndex) {
+                               $output = $this->sql_fetch_row($res);
+                       } else {
+                               $output = $this->sql_fetch_assoc($res);
+                       }
+                       $this->sql_free_result($res);
+               }
+               return $output;
+       }
+
+       /**
         * Counts the number of rows in a table.
         *
         * @param       string          $field: Name of the field to use in the COUNT() expression (e.g. '*')
         * @param       string          $table: Name of the table to count rows for
         * @param       string          $where: (optional) WHERE statement of the query
-        * @return      mixed           Number of rows counter (integer) or false if something went wrong (boolean)
+        * @return      mixed           Number of rows counter (integer) or FALSE if something went wrong (boolean)
         */
        public function exec_SELECTcountRows($field, $table, $where = '') {
-               $count = false;
+               $count = FALSE;
                $resultSet = $this->exec_SELECTquery('COUNT(' . $field . ')', $table, $where);
-               if ($resultSet !== false) {
+               if ($resultSet !== FALSE) {
                        list($count) = $this->sql_fetch_row($resultSet);
                        $this->sql_free_result($resultSet);
                }
@@ -384,7 +357,7 @@ class t3lib_DB {
 
        /**
         * Truncates a table.
-        * 
+        *
         * @param       string          Database tablename
         * @return      mixed           Result from handler
         */
@@ -393,19 +366,13 @@ class t3lib_DB {
                if ($this->debugOutput) {
                        $this->debug('exec_TRUNCATEquery');
                }
+               foreach ($this->postProcessHookObjects as $hookObject) {
+                       $hookObject->exec_TRUNCATEquery_postProcessAction($table, $this);
+               }
                return $res;
        }
 
 
-
-
-
-
-
-
-
-
-
        /**************************************
         *
         * Query building
@@ -419,21 +386,24 @@ class t3lib_DB {
         * @param       string          See exec_INSERTquery()
         * @param       array           See exec_INSERTquery()
         * @param       string/array            See fullQuoteArray()
-        * @return      string          Full SQL query for INSERT (unless $fields_values does not contain any elements in which case it will be false)
+        * @return      string          Full SQL query for INSERT (unless $fields_values does not contain any elements in which case it will be FALSE)
         */
        function INSERTquery($table, $fields_values, $no_quote_fields = FALSE) {
 
                        // Table and fieldnames should be "SQL-injection-safe" when supplied to this
                        // function (contrary to values in the arrays which may be insecure).
                if (is_array($fields_values) && count($fields_values)) {
+                       foreach ($this->preProcessHookObjects as $hookObject) {
+                               $hookObject->INSERTquery_preProcessAction($table, $fields_values, $no_quote_fields, $this);
+                       }
 
                                // quote and escape values
                        $fields_values = $this->fullQuoteArray($fields_values, $table, $no_quote_fields);
 
                                // Build query:
                        $query = 'INSERT INTO ' . $table .
-                               '(' . implode(',', array_keys($fields_values)) . ') VALUES ' .
-                               '(' . implode(',', $fields_values) . ')';
+                                       ' (' . implode(',', array_keys($fields_values)) . ') VALUES ' .
+                                       '(' . implode(',', $fields_values) . ')';
 
                                // Return query:
                        if ($this->debugOutput || $this->store_lastBuiltQuery) {
@@ -450,15 +420,19 @@ class t3lib_DB {
         * @param       array           Field names
         * @param       array           Table rows. Each row should be an array with field values mapping to $fields
         * @param       string/array            See fullQuoteArray()
-        * @return      string          Full SQL query for INSERT (unless $rows does not contain any elements in which case it will be false)
+        * @return      string          Full SQL query for INSERT (unless $rows does not contain any elements in which case it will be FALSE)
         */
        public function INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = FALSE) {
                        // Table and fieldnames should be "SQL-injection-safe" when supplied to this
                        // function (contrary to values in the arrays which may be insecure).
                if (count($rows)) {
+                       foreach ($this->preProcessHookObjects as $hookObject) {
+                               $hookObject->INSERTmultipleRows_preProcessAction($table, $fields, $rows, $no_quote_fields, $this);
+                       }
+
                                // Build query:
                        $query = 'INSERT INTO ' . $table .
-                               ' (' . implode(', ', $fields) . ') VALUES ';
+                                       ' (' . implode(', ', $fields) . ') VALUES ';
 
                        $rowSQL = array();
                        foreach ($rows as $row) {
@@ -486,36 +460,40 @@ class t3lib_DB {
         * @param       string          See exec_UPDATEquery()
         * @param       array           See exec_UPDATEquery()
         * @param       array           See fullQuoteArray()
-        * @return      string          Full SQL query for UPDATE (unless $fields_values does not contain any elements in which case it will be false)
+        * @return      string          Full SQL query for UPDATE
         */
        function UPDATEquery($table, $where, $fields_values, $no_quote_fields = FALSE) {
-
                        // Table and fieldnames should be "SQL-injection-safe" when supplied to this
                        // function (contrary to values in the arrays which may be insecure).
                if (is_string($where)) {
+                       foreach ($this->preProcessHookObjects as $hookObject) {
+                               $hookObject->UPDATEquery_preProcessAction($table, $where, $fields_values, $no_quote_fields, $this);
+                       }
+
+                       $fields = array();
                        if (is_array($fields_values) && count($fields_values)) {
 
                                        // quote and escape values
                                $nArr = $this->fullQuoteArray($fields_values, $table, $no_quote_fields);
 
-                               $fields = array();
                                foreach ($nArr as $k => $v) {
-                                       $fields[] = $k.'='.$v;
+                                       $fields[] = $k . '=' . $v;
                                }
+                       }
 
-                                       // Build query:
-                               $query = 'UPDATE ' . $table . ' SET ' . implode(',', $fields) .
+                               // Build query:
+                       $query = 'UPDATE ' . $table . ' SET ' . implode(',', $fields) .
                                        (strlen($where) > 0 ? ' WHERE ' . $where : '');
 
-                                       // Return query:
-                               if ($this->debugOutput || $this->store_lastBuiltQuery) {
-                                       $this->debug_lastBuiltQuery = $query;
-                               }
-                               return $query;
+                       if ($this->debugOutput || $this->store_lastBuiltQuery) {
+                               $this->debug_lastBuiltQuery = $query;
                        }
+                       return $query;
                } else {
-                       die('<strong>TYPO3 Fatal Error:</strong> "Where" clause argument for UPDATE ' .
-                               'query was not a string in $this->UPDATEquery() !');
+                       throw new InvalidArgumentException(
+                               'TYPO3 Fatal Error: "Where" clause argument for UPDATE query was not a string in $this->UPDATEquery() !',
+                               1270853880
+                       );
                }
        }
 
@@ -529,18 +507,23 @@ class t3lib_DB {
         */
        function DELETEquery($table, $where) {
                if (is_string($where)) {
+                       foreach ($this->preProcessHookObjects as $hookObject) {
+                               $hookObject->DELETEquery_preProcessAction($table, $where, $this);
+                       }
 
                                // Table and fieldnames should be "SQL-injection-safe" when supplied to this function
                        $query = 'DELETE FROM ' . $table .
-                               (strlen($where) > 0 ? ' WHERE ' . $where : '');
+                                       (strlen($where) > 0 ? ' WHERE ' . $where : '');
 
                        if ($this->debugOutput || $this->store_lastBuiltQuery) {
                                $this->debug_lastBuiltQuery = $query;
                        }
                        return $query;
                } else {
-                       die('<strong>TYPO3 Fatal Error:</strong> "Where" clause argument for DELETE ' .
-                               'query was not a string in $this->DELETEquery() !');
+                       throw new InvalidArgumentException(
+                               'TYPO3 Fatal Error: "Where" clause argument for DELETE query was not a string in $this->DELETEquery() !',
+                               1270853881
+                       );
                }
        }
 
@@ -561,7 +544,7 @@ class t3lib_DB {
                        // Table and fieldnames should be "SQL-injection-safe" when supplied to this function
                        // Build basic query:
                $query = 'SELECT ' . $select_fields . ' FROM ' . $from_table .
-                       (strlen($where_clause) > 0 ? ' WHERE ' . $where_clause : '');
+                               (strlen($where_clause) > 0 ? ' WHERE ' . $where_clause : '');
 
                        // Group by:
                $query .= (strlen($groupBy) > 0 ? ' GROUP BY ' . $groupBy : '');
@@ -582,7 +565,7 @@ class t3lib_DB {
        /**
         * Creates a SELECT SQL-statement to be used as subquery within another query.
         * BEWARE: This method should not be overriden within DBAL to prevent quoting from happening.
-        * 
+        *
         * @param       string          $select_fields: List of fields to select from the table.
         * @param       string          $from_table: Table from which to select.
         * @param       string          $where_clause: Conditional WHERE statement
@@ -592,7 +575,7 @@ class t3lib_DB {
                        // Table and fieldnames should be "SQL-injection-safe" when supplied to this function
                        // Build basic query:
                $query = 'SELECT ' . $select_fields . ' FROM ' . $from_table .
-                       (strlen($where_clause) > 0 ? ' WHERE ' . $where_clause : '');
+                               (strlen($where_clause) > 0 ? ' WHERE ' . $where_clause : '');
 
                        // Return query:
                if ($this->debugOutput || $this->store_lastBuiltQuery) {
@@ -604,11 +587,15 @@ class t3lib_DB {
 
        /**
         * Creates a TRUNCATE TABLE SQL-statement
-        * 
+        *
         * @param       string          See exec_TRUNCATEquery()
         * @return      string          Full SQL query for TRUNCATE TABLE
         */
        public function TRUNCATEquery($table) {
+               foreach ($this->preProcessHookObjects as $hookObject) {
+                       $hookObject->TRUNCATEquery_preProcessAction($table, $this);
+               }
+
                        // Table should be "SQL-injection-safe" when supplied to this function
                        // Build basic query:
                $query = 'TRUNCATE TABLE ' . $table;
@@ -625,8 +612,9 @@ class t3lib_DB {
         * Returns a WHERE clause that can find a value ($value) in a list field ($field)
         * For instance a record in the database might contain a list of numbers,
         * "34,234,5" (with no spaces between). This query would be able to select that
-        * record based on the value "34", "234" or "5" regardless of their positioni in
+        * record based on the value "34", "234" or "5" regardless of their position in
         * the list (left, middle or right).
+        * The value must not contain a comma (,)
         * Is nice to look up list-relations to records or files in TYPO3 database tables.
         *
         * @param       string          Field name
@@ -634,13 +622,13 @@ class t3lib_DB {
         * @param       string          Table in which we are searching (for DBAL detection of quoteStr() method)
         * @return      string          WHERE clause for a query
         */
-       function listQuery($field, $value, $table) {
+       public function listQuery($field, $value, $table) {
+               $value = (string) $value;
+               if (strpos(',', $value) !== FALSE) {
+                       throw new InvalidArgumentException('$value must not contain a comma (,) in $this->listQuery() !', 1294585862);
+               }
                $pattern = $this->quoteStr($value, $table);
-               $patternForLike = $this->escapeStrForLike($pattern, $table);
-               $where = '(' . $field . ' LIKE \'%,' . $patternForLike . ',%\' OR  ' .
-                       $field . ' LIKE \'' . $patternForLike . ',%\' OR ' .
-                       $field . ' LIKE \'%,' . $patternForLike . '\' OR ' .
-                       $field . '=\'' . $pattern . '\')';
+               $where = 'FIND_IN_SET(\'' . $pattern . '\',' . $field . ')';
                return $where;
        }
 
@@ -655,27 +643,82 @@ class t3lib_DB {
        function searchQuery($searchWords, $fields, $table) {
                $queryParts = array();
 
-               foreach($searchWords as $sw) {
+               foreach ($searchWords as $sw) {
                        $like = ' LIKE \'%' . $this->quoteStr($sw, $table) . '%\'';
                        $queryParts[] = $table . '.' . implode($like . ' OR ' . $table . '.', $fields) . $like;
                }
                $query = '(' . implode(') AND (', $queryParts) . ')';
-               return $query ;
+               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()) {
+               $query = $this->SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
+               $preparedStatement = t3lib_div::makeInstance('t3lib_db_PreparedStatement', $query, $from_table, array());
+               /* @var $preparedStatement t3lib_db_PreparedStatement */
 
+                       // Bind values to parameters
+               foreach ($input_parameters as $key => $value) {
+                       $preparedStatement->bindValue($key, $value, t3lib_db_PreparedStatement::PARAM_AUTOTYPE);
+               }
 
+                       // Return prepared statement
+               return $preparedStatement;
+       }
 
+       /**
+        * Creates a SELECT prepared SQL statement based on input query parts array
+        *
+        * @param array Query parts array
+        * @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_SELECTqueryArray(array $queryParts, array $input_parameters = array()) {
+               return $this->prepare_SELECTquery(
+                       $queryParts['SELECT'],
+                       $queryParts['FROM'],
+                       $queryParts['WHERE'],
+                       $queryParts['GROUPBY'],
+                       $queryParts['ORDERBY'],
+                       $queryParts['LIMIT'],
+                       $input_parameters
+               );
+       }
 
-
-
-
-
-
-
-
+       /**
+        * Executes a prepared query.
+        * This method may only be called by t3lib_db_PreparedStatement.
+        *
+        * @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 private
+        */
+       public function exec_PREPAREDquery($query, array $queryComponents) {
+               $res = mysql_query($query, $this->link);
+               if ($this->debugOutput) {
+                       $this->debug('stmt_execute', $query);
+               }
+               return $res;
+       }
 
 
        /**************************************
@@ -719,7 +762,7 @@ class t3lib_DB {
                        $noQuote = FALSE;
                }
 
-               foreach($arr as $k => $v) {
+               foreach ($arr as $k => $v) {
                        if ($noQuote === FALSE || !in_array($k, $noQuote)) {
                                $arr[$k] = $this->fullQuoteStr($v, $table);
                        }
@@ -752,7 +795,7 @@ class t3lib_DB {
         * @see quoteStr()
         */
        function escapeStrForLike($str, $table) {
-               return preg_replace('/[_%]/', '\\\$0', $str);
+               return addcslashes($str, '_%');
        }
 
        /**
@@ -765,7 +808,7 @@ class t3lib_DB {
         * @see cleanIntList()
         */
        function cleanIntArray($arr) {
-               foreach($arr as $k => $v) {
+               foreach ($arr as $k => $v) {
                        $arr[$k] = intval($arr[$k]);
                }
                return $arr;
@@ -860,19 +903,6 @@ class t3lib_DB {
        }
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
        /**************************************
         *
         * MySQL wrapper functions
@@ -882,28 +912,9 @@ class t3lib_DB {
 
        /**
         * Executes query
-        * mysql() wrapper function
-        * Usage count/core: 0
-        *
-        * @param       string          Database name
-        * @param       string          Query to execute
-        * @return      pointer         Result pointer / DBAL object
-        * @deprecated since TYPO3 3.6, will be removed in TYPO3 4.5
-        * @see sql_query()
-        */
-       function sql($db, $query) {
-               t3lib_div::logDeprecatedFunction();
-
-               $res = mysql_query($query, $this->link);
-               if ($this->debugOutput) {
-                       $this->debug('sql', $query);
-               }
-               return $res;
-       }
-
-       /**
-        * Executes query
         * mysql_query() wrapper function
+        * Beware: Use of this method should be avoided as it is experimentally supported by DBAL. You should consider
+        *         using exec_SELECTquery() and similar methods instead.
         * Usage count/core: 1
         *
         * @param       string          Query to execute
@@ -1069,7 +1080,7 @@ class t3lib_DB {
         * @param       string          Password to connect with.
         * @return      pointer         Returns a positive MySQL persistent link identifier on success, or FALSE on error.
         */
-       function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password)   {
+       function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password) {
                        // mysql_error() is tied to an established connection
                        // if the connection fails we need a different method to get the error message
                @ini_set('track_errors', 1);
@@ -1077,27 +1088,25 @@ class t3lib_DB {
 
                        // check if MySQL extension is loaded
                if (!extension_loaded('mysql')) {
-                       $header = 'Database Error';
-                       $message = 'It seems that MySQL support for PHP is not installed!';
-                       t3lib_timeTrack::debug_typo3PrintError($header, $message, false, t3lib_div::getIndpEnv('TYPO3_SITE_URL'));
-                       exit;
+                       $message = 'Database Error: It seems that MySQL support for PHP is not installed!';
+                       throw new RuntimeException($message, 1271492606);
                }
 
                        // Check for client compression
                $isLocalhost = ($TYPO3_db_host == 'localhost' || $TYPO3_db_host == '127.0.0.1');
                if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect']) {
                        if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['dbClientCompress'] && !$isLocalhost) {
-                                       // We use PHP's default value for 4th parameter (new_link), which is false.
+                                       // We use PHP's default value for 4th parameter (new_link), which is FALSE.
                                        // See PHP sources, for example: file php-5.2.5/ext/mysql/php_mysql.c,
                                        // function php_mysql_do_connect(), near line 525
-                               $this->link = @mysql_connect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password, false, MYSQL_CLIENT_COMPRESS);
+                               $this->link = @mysql_connect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password, FALSE, MYSQL_CLIENT_COMPRESS);
                        } else {
                                $this->link = @mysql_connect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password);
                        }
                } else {
                        if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['dbClientCompress'] && !$isLocalhost) {
                                        // See comment about 4th parameter in block above
-                               $this->link = @mysql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password, false, MYSQL_CLIENT_COMPRESS);
+                               $this->link = @mysql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password, MYSQL_CLIENT_COMPRESS);
                        } else {
                                $this->link = @mysql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password);
                        }
@@ -1109,27 +1118,54 @@ class t3lib_DB {
 
                if (!$this->link) {
                        t3lib_div::sysLog('Could not connect to MySQL server ' . $TYPO3_db_host .
-                               ' with user ' . $TYPO3_db_username . ': ' . $error_msg,
+                                       ' with user ' . $TYPO3_db_username . ': ' . $error_msg,
                                'Core',
                                4
                        );
                } else {
-                       $setDBinit = t3lib_div::trimExplode(chr(10), $GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit'], TRUE);
+                       $setDBinit = t3lib_div::trimExplode(LF, str_replace("' . LF . '", LF, $GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit']), TRUE);
                        foreach ($setDBinit as $v) {
                                if (mysql_query($v, $this->link) === FALSE) {
                                        t3lib_div::sysLog('Could not initialize DB connection with query "' . $v .
-                                               '": ' . mysql_error($this->link),
+                                                       '": ' . mysql_error($this->link),
                                                'Core',
                                                3
                                        );
                                }
                        }
+                       $this->setSqlMode();
                }
 
                return $this->link;
        }
 
        /**
+        * Fixes the SQL mode by unsetting NO_BACKSLASH_ESCAPES if found.
+        *
+        * @return void
+        */
+       protected function setSqlMode() {
+               $resource = $this->sql_query('SELECT @@SESSION.sql_mode;');
+               if (is_resource($resource)) {
+                       $result = $this->sql_fetch_row($resource);
+                       if (isset($result[0]) && $result[0] && strpos($result[0], 'NO_BACKSLASH_ESCAPES') !== FALSE) {
+                               $modes = array_diff(
+                                       t3lib_div::trimExplode(',', $result[0]),
+                                       array('NO_BACKSLASH_ESCAPES')
+                               );
+                               $query = 'SET sql_mode=\'' . mysql_real_escape_string(implode(',', $modes)) . '\';';
+                               $success = $this->sql_query($query);
+
+                               t3lib_div::sysLog(
+                                       'NO_BACKSLASH_ESCAPES could not be removed from SQL mode: ' . $this->sql_error(),
+                                       'Core',
+                                       3
+                               );
+                       }
+               }
+       }
+
+       /**
         * Select a MySQL database
         * mysql_select_db() wrapper function
         * Usage count/core: 8
@@ -1141,7 +1177,7 @@ class t3lib_DB {
                $ret = @mysql_select_db($TYPO3_db, $this->link);
                if (!$ret) {
                        t3lib_div::sysLog('Could not select MySQL database ' . $TYPO3_db . ': ' .
-                               mysql_error(),
+                                       mysql_error(),
                                'Core',
                                4
                        );
@@ -1150,14 +1186,6 @@ class t3lib_DB {
        }
 
 
-
-
-
-
-
-
-
-
        /**************************************
         *
         * SQL admin functions
@@ -1295,16 +1323,6 @@ class t3lib_DB {
        }
 
 
-
-
-
-
-
-
-
-
-
-
        /******************************
         *
         * Connecting service
@@ -1314,33 +1332,64 @@ class t3lib_DB {
        /**
         * Connects to database for TYPO3 sites:
         *
+        * @param string $host
+        * @param string $user
+        * @param string $password
+        * @param string $db
         * @return      void
         */
-       function connectDB() {
-               if ($this->sql_pconnect(TYPO3_db_host, TYPO3_db_username, TYPO3_db_password)) {
-                       if (!TYPO3_db) {
-                               die('No database selected');
-                               exit;
-                       } elseif (!$this->sql_select_db(TYPO3_db)) {
-                               die('Cannot connect to the current database, "' . TYPO3_db . '"');
-                               exit;
+       function connectDB($host = TYPO3_db_host, $user = TYPO3_db_username, $password = TYPO3_db_password, $db = TYPO3_db) {
+                       // If no db is given we throw immediately. This is a sign for a fresh (not configured)
+                       // TYPO3 installation and is used in FE to redirect to 1-2-3 install tool
+               if (!$db) {
+                       throw new RuntimeException(
+                               'TYPO3 Fatal Error: No database selected!',
+                               1270853882
+                       );
+               }
+
+               if ($this->sql_pconnect($host, $user, $password)) {
+                       if (!$this->sql_select_db($db)) {
+                               throw new RuntimeException(
+                                       'TYPO3 Fatal Error: Cannot connect to the current database, "' . $db . '"!',
+                                       1270853883
+                               );
                        }
                } else {
-                       die('The current username, password or host was not accepted when the ' .
-                               'connection to the database was attempted to be established!');
-                       exit;
+                       throw new RuntimeException(
+                               'TYPO3 Fatal Error: The current username, password or host was not accepted when the connection to the database was attempted to be established!',
+                               1270853884
+                       );
                }
-       }
-
-
-
-
-
-
-
 
+                       // Prepare user defined objects (if any) for hooks which extend query methods
+               $this->preProcessHookObjects = array();
+               $this->postProcessHookObjects = array();
+               if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_db.php']['queryProcessors'])) {
+                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_db.php']['queryProcessors'] as $classRef) {
+                               $hookObject = t3lib_div::getUserObj($classRef);
 
+                               if (!($hookObject instanceof t3lib_DB_preProcessQueryHook || $hookObject instanceof t3lib_DB_postProcessQueryHook)) {
+                                       throw new UnexpectedValueException('$hookObject must either implement interface t3lib_DB_preProcessQueryHook or interface t3lib_DB_postProcessQueryHook', 1299158548);
+                               }
+                               if ($hookObject instanceof t3lib_DB_preProcessQueryHook) {
+                                       $this->preProcessHookObjects[] = $hookObject;
+                               }
+                               if ($hookObject instanceof t3lib_DB_postProcessQueryHook) {
+                                       $this->postProcessHookObjects[] = $hookObject;
+                               }
+                       }
+               }
+       }
 
+       /**
+        * Checks if database is connected
+        *
+        * @return boolean
+        */
+       public function isConnected() {
+               return is_resource($this->link);
+       }
 
 
        /******************************
@@ -1356,18 +1405,19 @@ class t3lib_DB {
         * @param       string          Last query if not last built query
         * @return      void
         */
-       function debug($func, $query='') {
+       function debug($func, $query = '') {
 
                $error = $this->sql_error();
-               if ($error) {
+               if ($error || (int)$this->debugOutput === 2) {
                        debug(
                                array(
                                        'caller' => 't3lib_DB::' . $func,
                                        'ERROR' => $error,
                                        'lastBuiltQuery' => ($query ? $query : $this->debug_lastBuiltQuery),
-                                       'debug_backtrace' => t3lib_div::debug_trail(),
+                                       'debug_backtrace' => t3lib_utility_Debug::debugTrail(),
                                ),
-                               'SQL debug'
+                               $func,
+                                       is_object($GLOBALS['error']) && @is_callable(array($GLOBALS['error'], 'debug')) ? '' : 'DB Error'
                        );
                }
        }
@@ -1376,7 +1426,7 @@ class t3lib_DB {
         * Checks if recordset is valid and writes debugging inormation into devLog if not.
         *
         * @param       resource        $res    Recordset
-        * @return      boolean <code>false</code> if recordset is not valid
+        * @return      boolean <code>FALSE</code> if recordset is not valid
         */
        function debug_check_recordset($res) {
                if (!$res) {
@@ -1392,9 +1442,9 @@ class t3lib_DB {
                                }
                        }
                        $msg .= ': function t3lib_DB->' . $trace[0]['function'] . ' called from file ' .
-                               substr($trace[0]['file'], strlen(PATH_site) + 2) . ' in line ' .
-                               $trace[0]['line'];
-                       t3lib_div::sysLog($msg.'. Use a devLog extension to get more details.', 'Core/t3lib_db', 3);
+                                       substr($trace[0]['file'], strlen(PATH_site) + 2) . ' in line ' .
+                                       $trace[0]['line'];
+                       t3lib_div::sysLog($msg . '. Use a devLog extension to get more details.', 'Core/t3lib_db', 3);
                                // Send to devLog if enabled
                        if (TYPO3_DLOG) {
                                $debugLogData = array(
@@ -1422,24 +1472,24 @@ class t3lib_DB {
         * @param       string          SQL query
         * @param       string          Table(s) from which to select. This is what comes right after "FROM ...". Required value.
         * @param       integer         Number of resulting rows
-        * @return      boolean         True if explain was run, false otherwise
+        * @return      boolean         TRUE if explain was run, FALSE otherwise
         */
        protected function explain($query, $from_table, $row_count) {
 
-               if ((int)$this->explainOutput == 1 || ((int)$this->explainOutput == 2 &&
-                       t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'), $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']))
-                       ) {
+               if ((int) $this->explainOutput == 1 || ((int) $this->explainOutput == 2 &&
+                               t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'), $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']))
+               ) {
                                // raw HTML output
                        $explainMode = 1;
-               } elseif ((int)$this->explainOutput == 3 && is_object($GLOBALS['TT'])) {
+               } elseif ((int) $this->explainOutput == 3 && is_object($GLOBALS['TT'])) {
                                // embed the output into the TS admin panel
                        $explainMode = 2;
                } else {
-                       return false;
+                       return FALSE;
                }
 
                $error = $this->sql_error();
-               $trail = t3lib_div::debug_trail();
+               $trail = t3lib_utility_Debug::debugTrail();
 
                $explain_tables = array();
                $explain_output = array();
@@ -1456,7 +1506,7 @@ class t3lib_DB {
                        // Notice: Rows are skipped if there is only one result, or if no conditions are set
                if ($explain_output[0]['rows'] > 1 || t3lib_div::inList('ALL', $explain_output[0]['type'])) {
                                // only enable output if it's really useful
-                       $debug = true;
+                       $debug = TRUE;
 
                        foreach ($explain_tables as $table) {
                                $tableRes = $this->sql_query('SHOW TABLE STATUS LIKE \'' . $table . '\'');
@@ -1473,25 +1523,11 @@ class t3lib_DB {
                                $this->sql_free_result($tableRes);
                        }
                } else {
-                       $debug = false;
+                       $debug = FALSE;
                }
 
                if ($debug) {
-                       if ($explainMode == 1) {
-                               t3lib_div::debug('QUERY: ' . $query);
-                               t3lib_div::debug(array('Debug trail:' => $trail), 'Row count: ' . $row_count);
-
-                               if ($error) {
-                                       t3lib_div::debug($error);
-                               }
-                               if (count($explain_output)) {
-                                       t3lib_div::debug($explain_output);
-                               }
-                               if (count($indices_output)) {
-                                       t3lib_div::debugRows($indices_output);
-                               }
-
-                       } elseif ($explainMode == 2) {
+                       if ($explainMode) {
                                $data = array();
                                $data['query'] = $query;
                                $data['trail'] = $trail;
@@ -1506,19 +1542,24 @@ class t3lib_DB {
                                if (count($indices_output)) {
                                        $data['indices'] = $indices_output;
                                }
-                               $GLOBALS['TT']->setTSselectQuery($data);
+
+                               if ($explainMode == 1) {
+                                       t3lib_utility_Debug::debug($data, 'Tables: ' . $from_table, 'DB SQL EXPLAIN');
+                               } elseif ($explainMode == 2) {
+                                       $GLOBALS['TT']->setTSselectQuery($data);
+                               }
                        }
-                       return true;
+                       return TRUE;
                }
 
-               return false;
+               return FALSE;
        }
 
 }
 
 
-if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_db.php'])       {
-       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_db.php']);
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_db.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_db.php']);
 }
 
 ?>
\ No newline at end of file