Fixed bug #15580: Add calls to logDeprecatedFunction() for more deprecated functions...
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_db.php
index e48221f..00b1bdf 100644 (file)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2004-2009 Kasper Skaarhoj (kasperYYYY@typo3.com)
+*  (c) 2004-2010 Kasper Skårhøj (kasperYYYY@typo3.com)
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -32,7 +32,7 @@
  *
  * $Id$
  *
- * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
  */
 /**
  * [CLASS/FUNCTION INDEX of SCRIPT]
  * In all TYPO3 scripts the global variable $TYPO3_DB is an instance of this class. Use that.
  * 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
  */
@@ -382,6 +382,20 @@ class t3lib_DB {
                return $count;
        }
 
+       /**
+        * Truncates a table.
+        *
+        * @param       string          Database tablename
+        * @return      mixed           Result from handler
+        */
+       public function exec_TRUNCATEquery($table) {
+               $res = mysql_query($this->TRUNCATEquery($table), $this->link);
+               if ($this->debugOutput) {
+                       $this->debug('exec_TRUNCATEquery');
+               }
+               return $res;
+       }
+
 
 
 
@@ -444,16 +458,16 @@ class t3lib_DB {
                if (count($rows)) {
                                // Build query:
                        $query = 'INSERT INTO ' . $table .
-                               '(' . implode(',', $fields) . ') VALUES ';
+                               ' (' . implode(', ', $fields) . ') VALUES ';
 
                        $rowSQL = array();
                        foreach ($rows as $row) {
                                        // quote and escape values
                                $row = $this->fullQuoteArray($row, $table, $no_quote_fields);
-                               $rowSQL[] = '( ' . implode(',', $row) . ') ';
+                               $rowSQL[] = '(' . implode(', ', $row) . ')';
                        }
 
-                       $query .= implode(',', $rowSQL);
+                       $query .= implode(', ', $rowSQL);
 
                                // Return query:
                        if ($this->debugOutput || $this->store_lastBuiltQuery) {
@@ -472,36 +486,36 @@ 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)) {
+                       $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;
                                }
+                       }
 
-                                       // Build query:
-                               $query = 'UPDATE ' . $table . ' SET ' . implode(',', $fields) .
-                                       (strlen($where) > 0 ? ' WHERE ' . $where : '');
+                               // 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
+                       );
                }
        }
 
@@ -525,8 +539,10 @@ class t3lib_DB {
                        }
                        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
+                       );
                }
        }
 
@@ -568,7 +584,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
@@ -589,11 +605,31 @@ 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) {
+                       // Table should be "SQL-injection-safe" when supplied to this function
+                       // Build basic query:
+               $query = 'TRUNCATE TABLE ' . $table;
+
+                       // Return query:
+               if ($this->debugOutput || $this->store_lastBuiltQuery) {
+                       $this->debug_lastBuiltQuery = $query;
+               }
+
+               return $query;
+       }
+
+       /**
         * 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
@@ -601,13 +637,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() !');
+               }
                $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;
        }
 
@@ -640,6 +676,79 @@ class t3lib_DB {
 
 
 
+       /**************************************
+        *
+        * 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 +828,7 @@ class t3lib_DB {
         * @see quoteStr()
         */
        function escapeStrForLike($str, $table) {
-               return preg_replace('/[_%]/', '\\\$0', $str);
+               return addcslashes($str, '_%');
        }
 
        /**
@@ -855,7 +964,7 @@ class t3lib_DB {
         * @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
+        * @deprecated since TYPO3 3.6, will be removed in TYPO3 4.6
         * @see sql_query()
         */
        function sql($db, $query) {
@@ -1044,10 +1153,8 @@ 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
@@ -1064,7 +1171,7 @@ class t3lib_DB {
                } 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);
                        }
@@ -1081,7 +1188,7 @@ class t3lib_DB {
                                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 .
@@ -1281,32 +1388,41 @@ 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 ($this->sql_pconnect($host, $user, $password)) {
+                       if (!$db) {
+                               throw new RuntimeException(
+                                       'TYPO3 Fatal Error: No database selected!',
+                                       1270853882
+                               );
+                       } elseif (!$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
+                       );
                }
        }
 
-
-
-
-
-
-
-
-
+       /**
+        * Checks if database is connected
+        *
+        * @return boolean
+        */
+       public function isConnected() {
+               return is_resource($this->link);
+       }
 
 
 
@@ -1326,15 +1442,16 @@ class t3lib_DB {
        function debug($func, $query='') {
 
                $error = $this->sql_error();
-               if ($error) {
+               if ($error || $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'
                        );
                }
        }
@@ -1406,7 +1523,7 @@ class t3lib_DB {
                }
 
                $error = $this->sql_error();
-               $trail = t3lib_div::debug_trail();
+               $trail = t3lib_utility_Debug::debugTrail();
 
                $explain_tables = array();
                $explain_output = array();
@@ -1426,34 +1543,25 @@ class t3lib_DB {
                        $debug = true;
 
                        foreach ($explain_tables as $table) {
-                               $res = $this->sql_query('SHOW INDEX FROM ' . $table, $this->link);
-                               if (is_resource($res)) {
-                                       while ($tempRow = $this->sql_fetch_assoc($res)) {
-                                               $indices_output[] = $tempRow;
+                               $tableRes = $this->sql_query('SHOW TABLE STATUS LIKE \'' . $table . '\'');
+                               $isTable = $this->sql_num_rows($tableRes);
+                               if ($isTable) {
+                                       $res = $this->sql_query('SHOW INDEX FROM ' . $table, $this->link);
+                                       if (is_resource($res)) {
+                                               while ($tempRow = $this->sql_fetch_assoc($res)) {
+                                                       $indices_output[] = $tempRow;
+                                               }
+                                               $this->sql_free_result($res);
                                        }
-                                       $this->sql_free_result($res);
                                }
+                               $this->sql_free_result($tableRes);
                        }
                } else {
                        $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;
@@ -1468,7 +1576,12 @@ 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;
                }