class.t3lib_db.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2004-2010 Kasper Skaarhoj (kasperYYYY@typo3.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00027 /**
00028  * Contains the class "t3lib_db" containing functions for building SQL queries
00029  * and mysql wrappers, thus providing a foundational API to all database
00030  * interaction.
00031  * This class is instantiated globally as $TYPO3_DB in TYPO3 scripts.
00032  *
00033  * $Id: class.t3lib_db.php 8197 2010-07-16 13:33:16Z xperseguers $
00034  *
00035  * @author  Kasper Skaarhoj <kasperYYYY@typo3.com>
00036  */
00037 /**
00038  * [CLASS/FUNCTION INDEX of SCRIPT]
00039  *
00040  *
00041  *
00042  *  138: class t3lib_DB
00043  *
00044  *              SECTION: Query execution
00045  *  175:     function exec_INSERTquery($table,$fields_values,$no_quote_fields=FALSE)
00046  *  192:     function exec_UPDATEquery($table,$where,$fields_values,$no_quote_fields=FALSE)
00047  *  206:     function exec_DELETEquery($table,$where)
00048  *  225:     function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='')
00049  *  250:     function exec_SELECT_mm_query($select,$local_table,$mm_table,$foreign_table,$whereClause='',$groupBy='',$orderBy='',$limit='')
00050  *  278:     function exec_SELECT_queryArray($queryParts)
00051  *  301:     function exec_SELECTgetRows($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='',$uidIndexField='')
00052  *
00053  *              SECTION: Query building
00054  *  346:     function INSERTquery($table,$fields_values,$no_quote_fields=FALSE)
00055  *  381:     function UPDATEquery($table,$where,$fields_values,$no_quote_fields=FALSE)
00056  *  422:     function DELETEquery($table,$where)
00057  *  451:     function SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='')
00058  *  492:     function listQuery($field, $value, $table)
00059  *  506:     function searchQuery($searchWords,$fields,$table)
00060  *
00061  *              SECTION: Various helper functions
00062  *  552:     function fullQuoteStr($str, $table)
00063  *  569:     function fullQuoteArray($arr, $table, $noQuote=FALSE)
00064  *  596:     function quoteStr($str, $table)
00065  *  612:     function escapeStrForLike($str, $table)
00066  *  625:     function cleanIntArray($arr)
00067  *  641:     function cleanIntList($list)
00068  *  655:     function stripOrderBy($str)
00069  *  669:     function stripGroupBy($str)
00070  *  681:     function splitGroupOrderLimit($str)
00071  *
00072  *              SECTION: MySQL wrapper functions
00073  *  749:     function sql($db,$query)
00074  *  763:     function sql_query($query)
00075  *  776:     function sql_error()
00076  *  788:     function sql_num_rows($res)
00077  *  800:     function sql_fetch_assoc($res)
00078  *  813:     function sql_fetch_row($res)
00079  *  825:     function sql_free_result($res)
00080  *  836:     function sql_insert_id()
00081  *  847:     function sql_affected_rows()
00082  *  860:     function sql_data_seek($res,$seek)
00083  *  873:     function sql_field_type($res,$pointer)
00084  *  887:     function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password)
00085  *  915:     function sql_select_db($TYPO3_db)
00086  *
00087  *              SECTION: SQL admin functions
00088  *  947:     function admin_get_dbs()
00089  *  965:     function admin_get_tables()
00090  *  984:     function admin_get_fields($tableName)
00091  * 1002:     function admin_get_keys($tableName)
00092  * 1020:     function admin_query($query)
00093  *
00094  *              SECTION: Connecting service
00095  * 1048:     function connectDB()
00096  *
00097  *              SECTION: Debugging
00098  * 1086:     function debug($func)
00099  *
00100  * TOTAL FUNCTIONS: 42
00101  * (This index is automatically created/updated by the extension "extdeveval")
00102  *
00103  */
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 /**
00117  * TYPO3 "database wrapper" class (new in 3.6.0)
00118  * This class contains
00119  * - abstraction functions for executing INSERT/UPDATE/DELETE/SELECT queries ("Query execution"; These are REQUIRED for all future connectivity to the database, thus ensuring DBAL compliance!)
00120  * - functions for building SQL queries (INSERT/UPDATE/DELETE/SELECT) ("Query building"); These are transitional functions for building SQL queries in a more automated way. Use these to build queries instead of doing it manually in your code!
00121  * - mysql() wrapper functions; These are transitional functions. By a simple search/replace you should be able to substitute all mysql*() calls with $GLOBALS['TYPO3_DB']->sql*() and your application will work out of the box. YOU CANNOT (legally) use any mysql functions not found as wrapper functions in this class!
00122  * See the Project Coding Guidelines (doc_core_cgl) for more instructions on best-practise
00123  *
00124  * This class is not in itself a complete database abstraction layer but can be extended to be a DBAL (by extensions, see "dbal" for example)
00125  * ALL connectivity to the database in TYPO3 must be done through this class!
00126  * The points of this class are:
00127  * - To direct all database calls through this class so it becomes possible to implement DBAL with extensions.
00128  * - To keep it very easy to use for developers used to MySQL in PHP - and preserve as much performance as possible when TYPO3 is used with MySQL directly...
00129  * - To create an interface for DBAL implemented by extensions; (Eg. making possible escaping characters, clob/blob handling, reserved words handling)
00130  * - Benchmarking the DB bottleneck queries will become much easier; Will make it easier to find optimization possibilities.
00131  *
00132  * USE:
00133  * In all TYPO3 scripts the global variable $TYPO3_DB is an instance of this class. Use that.
00134  * Eg.      $GLOBALS['TYPO3_DB']->sql_fetch_assoc()
00135  *
00136  * @author  Kasper Skaarhoj <kasperYYYY@typo3.com>
00137  * @package TYPO3
00138  * @subpackage t3lib
00139  */
00140 class t3lib_DB {
00141 
00142 
00143         // Debug:
00144     var $debugOutput = FALSE;       // Set "TRUE" if you want database errors outputted.
00145     var $debug_lastBuiltQuery = '';     // Internally: Set to last built query (not necessarily executed...)
00146     var $store_lastBuiltQuery = FALSE;  // Set "TRUE" if you want the last built query to be stored in $debug_lastBuiltQuery independent of $this->debugOutput
00147     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.
00148 
00149         // Default link identifier:
00150     var $link = FALSE;
00151 
00152         // Default character set, applies unless character set or collation are explicitely set
00153     var $default_charset = 'utf8';
00154 
00155 
00156 
00157 
00158     /************************************
00159      *
00160      * Query execution
00161      *
00162      * These functions are the RECOMMENDED DBAL functions for use in your applications
00163      * Using these functions will allow the DBAL to use alternative ways of accessing data (contrary to if a query is returned!)
00164      * They compile a query AND execute it immediately and then return the result
00165      * This principle heightens our ability to create various forms of DBAL of the functions.
00166      * Generally: We want to return a result pointer/object, never queries.
00167      * Also, having the table name together with the actual query execution allows us to direct the request to other databases.
00168      *
00169      **************************************/
00170 
00171     /**
00172      * Creates and executes an INSERT SQL-statement for $table from the array with field/value pairs $fields_values.
00173      * Using this function specifically allows us to handle BLOB and CLOB fields depending on DB
00174      * Usage count/core: 47
00175      *
00176      * @param   string      Table name
00177      * @param   array       Field values as key=>value pairs. Values will be escaped internally. Typically you would fill an array like "$insertFields" with 'fieldname'=>'value' and pass it to this function as argument.
00178      * @param   string/array        See fullQuoteArray()
00179      * @return  pointer     MySQL result pointer / DBAL object
00180      */
00181     function exec_INSERTquery($table, $fields_values, $no_quote_fields = FALSE) {
00182         $res = mysql_query($this->INSERTquery($table, $fields_values, $no_quote_fields), $this->link);
00183         if ($this->debugOutput) {
00184             $this->debug('exec_INSERTquery');
00185         }
00186         return $res;
00187     }
00188 
00189     /**
00190      * Creates and executes an INSERT SQL-statement for $table with multiple rows.
00191      *
00192      * @param   string      Table name
00193      * @param   array       Field names
00194      * @param   array       Table rows. Each row should be an array with field values mapping to $fields
00195      * @param   string/array        See fullQuoteArray()
00196      * @return  pointer     MySQL result pointer / DBAL object
00197      */
00198     public function exec_INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = FALSE) {
00199         $res = mysql_query($this->INSERTmultipleRows($table, $fields, $rows, $no_quote_fields), $this->link);
00200         if ($this->debugOutput) {
00201             $this->debug('exec_INSERTmultipleRows');
00202         }
00203         return $res;
00204     }
00205 
00206     /**
00207      * Creates and executes an UPDATE SQL-statement for $table where $where-clause (typ. 'uid=...') from the array with field/value pairs $fields_values.
00208      * Using this function specifically allow us to handle BLOB and CLOB fields depending on DB
00209      * Usage count/core: 50
00210      *
00211      * @param   string      Database tablename
00212      * @param   string      WHERE clause, eg. "uid=1". NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
00213      * @param   array       Field values as key=>value pairs. Values will be escaped internally. Typically you would fill an array like "$updateFields" with 'fieldname'=>'value' and pass it to this function as argument.
00214      * @param   string/array        See fullQuoteArray()
00215      * @return  pointer     MySQL result pointer / DBAL object
00216      */
00217     function exec_UPDATEquery($table, $where, $fields_values, $no_quote_fields = FALSE) {
00218         $res = mysql_query($this->UPDATEquery($table, $where, $fields_values, $no_quote_fields), $this->link);
00219         if ($this->debugOutput) {
00220             $this->debug('exec_UPDATEquery');
00221         }
00222         return $res;
00223     }
00224 
00225     /**
00226      * Creates and executes a DELETE SQL-statement for $table where $where-clause
00227      * Usage count/core: 40
00228      *
00229      * @param   string      Database tablename
00230      * @param   string      WHERE clause, eg. "uid=1". NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
00231      * @return  pointer     MySQL result pointer / DBAL object
00232      */
00233     function exec_DELETEquery($table, $where) {
00234         $res = mysql_query($this->DELETEquery($table, $where), $this->link);
00235         if ($this->debugOutput) {
00236             $this->debug('exec_DELETEquery');
00237         }
00238         return $res;
00239     }
00240 
00241     /**
00242      * Creates and executes a SELECT SQL-statement
00243      * Using this function specifically allow us to handle the LIMIT feature independently of DB.
00244      * Usage count/core: 340
00245      *
00246      * @param   string      List of fields to select from the table. This is what comes right after "SELECT ...". Required value.
00247      * @param   string      Table(s) from which to select. This is what comes right after "FROM ...". Required value.
00248      * @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!
00249      * @param   string      Optional GROUP BY field(s), if none, supply blank string.
00250      * @param   string      Optional ORDER BY field(s), if none, supply blank string.
00251      * @param   string      Optional LIMIT value ([begin,]max), if none, supply blank string.
00252      * @return  pointer     MySQL result pointer / DBAL object
00253      */
00254     function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '') {
00255         $query = $this->SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
00256         $res = mysql_query($query, $this->link);
00257 
00258         if ($this->debugOutput) {
00259             $this->debug('exec_SELECTquery');
00260         }
00261         if ($this->explainOutput) {
00262             $this->explain($query, $from_table, $this->sql_num_rows($res));
00263         }
00264 
00265         return $res;
00266     }
00267 
00268     /**
00269      * Creates and executes a SELECT query, selecting fields ($select) from two/three tables joined
00270      * 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.
00271      * The JOIN is done with [$local_table].uid <--> [$mm_table].uid_local  / [$mm_table].uid_foreign <--> [$foreign_table].uid
00272      * 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.
00273      *
00274      * Usage: 12 (spec. ext. sys_action, sys_messages, sys_todos)
00275      *
00276      * @param   string      Field list for SELECT
00277      * @param   string      Tablename, local table
00278      * @param   string      Tablename, relation table
00279      * @param   string      Tablename, foreign table
00280      * @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! You have to prepend 'AND ' to this parameter yourself!
00281      * @param   string      Optional GROUP BY field(s), if none, supply blank string.
00282      * @param   string      Optional ORDER BY field(s), if none, supply blank string.
00283      * @param   string      Optional LIMIT value ([begin,]max), if none, supply blank string.
00284      * @return  pointer     MySQL result pointer / DBAL object
00285      * @see exec_SELECTquery()
00286      */
00287     function exec_SELECT_mm_query($select, $local_table, $mm_table, $foreign_table, $whereClause = '', $groupBy = '', $orderBy = '', $limit = '') {
00288         if ($foreign_table == $local_table) {
00289             $foreign_table_as = $foreign_table . uniqid('_join');
00290         }
00291 
00292         $mmWhere = $local_table ? $local_table . '.uid=' . $mm_table . '.uid_local' : '';
00293         $mmWhere .= ($local_table AND $foreign_table) ? ' AND ' : '';
00294 
00295         $tables = ($local_table ? $local_table . ',' : '') . $mm_table;
00296 
00297         if ($foreign_table) {
00298             $mmWhere .= ($foreign_table_as ? $foreign_table_as : $foreign_table) . '.uid=' . $mm_table . '.uid_foreign';
00299             $tables .= ',' . $foreign_table . ($foreign_table_as ? ' AS ' . $foreign_table_as : '');
00300         }
00301 
00302         return $this->exec_SELECTquery(
00303                     $select,
00304                     $tables,
00305                         // whereClauseMightContainGroupOrderBy
00306                     $mmWhere . ' ' . $whereClause,
00307                     $groupBy,
00308                     $orderBy,
00309                     $limit
00310                 );
00311     }
00312 
00313     /**
00314      * Executes a select based on input query parts array
00315      *
00316      * Usage: 9
00317      *
00318      * @param   array       Query parts array
00319      * @return  pointer     MySQL select result pointer / DBAL object
00320      * @see exec_SELECTquery()
00321      */
00322     function exec_SELECT_queryArray($queryParts) {
00323         return $this->exec_SELECTquery(
00324             $queryParts['SELECT'],
00325             $queryParts['FROM'],
00326             $queryParts['WHERE'],
00327             $queryParts['GROUPBY'],
00328             $queryParts['ORDERBY'],
00329             $queryParts['LIMIT']
00330         );
00331     }
00332 
00333     /**
00334      * Creates and executes a SELECT SQL-statement AND traverse result set and returns array with records in.
00335      *
00336      * @param   string      See exec_SELECTquery()
00337      * @param   string      See exec_SELECTquery()
00338      * @param   string      See exec_SELECTquery()
00339      * @param   string      See exec_SELECTquery()
00340      * @param   string      See exec_SELECTquery()
00341      * @param   string      See exec_SELECTquery()
00342      * @param   string      If set, the result array will carry this field names value as index. Requires that field to be selected of course!
00343      * @return  array       Array of rows.
00344      */
00345     function exec_SELECTgetRows($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '', $uidIndexField = '') {
00346         $res = $this->exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);
00347         if ($this->debugOutput) {
00348             $this->debug('exec_SELECTquery');
00349         }
00350 
00351         if (!$this->sql_error()) {
00352             $output = array();
00353 
00354             if ($uidIndexField) {
00355                 while ($tempRow = $this->sql_fetch_assoc($res)) {
00356                     $output[$tempRow[$uidIndexField]] = $tempRow;
00357                 }
00358             } else {
00359                 while ($output[] = $this->sql_fetch_assoc($res));
00360                 array_pop($output);
00361             }
00362             $this->sql_free_result($res);
00363         }
00364         return $output;
00365     }
00366 
00367     /**
00368      * Counts the number of rows in a table.
00369      *
00370      * @param   string      $field: Name of the field to use in the COUNT() expression (e.g. '*')
00371      * @param   string      $table: Name of the table to count rows for
00372      * @param   string      $where: (optional) WHERE statement of the query
00373      * @return  mixed       Number of rows counter (integer) or false if something went wrong (boolean)
00374      */
00375     public function exec_SELECTcountRows($field, $table, $where = '') {
00376         $count = false;
00377         $resultSet = $this->exec_SELECTquery('COUNT(' . $field . ')', $table, $where);
00378         if ($resultSet !== false) {
00379             list($count) = $this->sql_fetch_row($resultSet);
00380             $this->sql_free_result($resultSet);
00381         }
00382         return $count;
00383     }
00384 
00385     /**
00386      * Truncates a table.
00387      *
00388      * @param   string      Database tablename
00389      * @return  mixed       Result from handler
00390      */
00391     public function exec_TRUNCATEquery($table) {
00392         $res = mysql_query($this->TRUNCATEquery($table), $this->link);
00393         if ($this->debugOutput) {
00394             $this->debug('exec_TRUNCATEquery');
00395         }
00396         return $res;
00397     }
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409     /**************************************
00410      *
00411      * Query building
00412      *
00413      **************************************/
00414 
00415     /**
00416      * Creates an INSERT SQL-statement for $table from the array with field/value pairs $fields_values.
00417      * Usage count/core: 4
00418      *
00419      * @param   string      See exec_INSERTquery()
00420      * @param   array       See exec_INSERTquery()
00421      * @param   string/array        See fullQuoteArray()
00422      * @return  string      Full SQL query for INSERT (unless $fields_values does not contain any elements in which case it will be false)
00423      */
00424     function INSERTquery($table, $fields_values, $no_quote_fields = FALSE) {
00425 
00426             // Table and fieldnames should be "SQL-injection-safe" when supplied to this
00427             // function (contrary to values in the arrays which may be insecure).
00428         if (is_array($fields_values) && count($fields_values)) {
00429 
00430                 // quote and escape values
00431             $fields_values = $this->fullQuoteArray($fields_values, $table, $no_quote_fields);
00432 
00433                 // Build query:
00434             $query = 'INSERT INTO ' . $table .
00435                 '(' . implode(',', array_keys($fields_values)) . ') VALUES ' .
00436                 '(' . implode(',', $fields_values) . ')';
00437 
00438                 // Return query:
00439             if ($this->debugOutput || $this->store_lastBuiltQuery) {
00440                 $this->debug_lastBuiltQuery = $query;
00441             }
00442             return $query;
00443         }
00444     }
00445 
00446     /**
00447      * Creates an INSERT SQL-statement for $table with multiple rows.
00448      *
00449      * @param   string      Table name
00450      * @param   array       Field names
00451      * @param   array       Table rows. Each row should be an array with field values mapping to $fields
00452      * @param   string/array        See fullQuoteArray()
00453      * @return  string      Full SQL query for INSERT (unless $rows does not contain any elements in which case it will be false)
00454      */
00455     public function INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = FALSE) {
00456             // Table and fieldnames should be "SQL-injection-safe" when supplied to this
00457             // function (contrary to values in the arrays which may be insecure).
00458         if (count($rows)) {
00459                 // Build query:
00460             $query = 'INSERT INTO ' . $table .
00461                 ' (' . implode(', ', $fields) . ') VALUES ';
00462 
00463             $rowSQL = array();
00464             foreach ($rows as $row) {
00465                     // quote and escape values
00466                 $row = $this->fullQuoteArray($row, $table, $no_quote_fields);
00467                 $rowSQL[] = '(' . implode(', ', $row) . ')';
00468             }
00469 
00470             $query .= implode(', ', $rowSQL);
00471 
00472                 // Return query:
00473             if ($this->debugOutput || $this->store_lastBuiltQuery) {
00474                 $this->debug_lastBuiltQuery = $query;
00475             }
00476 
00477             return $query;
00478         }
00479     }
00480 
00481     /**
00482      * Creates an UPDATE SQL-statement for $table where $where-clause (typ. 'uid=...') from the array with field/value pairs $fields_values.
00483      * Usage count/core: 6
00484      *
00485      * @param   string      See exec_UPDATEquery()
00486      * @param   string      See exec_UPDATEquery()
00487      * @param   array       See exec_UPDATEquery()
00488      * @param   array       See fullQuoteArray()
00489      * @return  string      Full SQL query for UPDATE
00490      */
00491     function UPDATEquery($table, $where, $fields_values, $no_quote_fields = FALSE) {
00492             // Table and fieldnames should be "SQL-injection-safe" when supplied to this
00493             // function (contrary to values in the arrays which may be insecure).
00494         if (is_string($where)) {
00495             $fields = array();
00496             if (is_array($fields_values) && count($fields_values)) {
00497 
00498                     // quote and escape values
00499                 $nArr = $this->fullQuoteArray($fields_values, $table, $no_quote_fields);
00500 
00501                 foreach ($nArr as $k => $v) {
00502                     $fields[] = $k.'='.$v;
00503                 }
00504             }
00505 
00506                 // Build query:
00507             $query = 'UPDATE ' . $table . ' SET ' . implode(',', $fields) .
00508                 (strlen($where) > 0 ? ' WHERE ' . $where : '');
00509 
00510             if ($this->debugOutput || $this->store_lastBuiltQuery) {
00511                 $this->debug_lastBuiltQuery = $query;
00512             }
00513             return $query;
00514         } else {
00515             throw new InvalidArgumentException(
00516                 'TYPO3 Fatal Error: "Where" clause argument for UPDATE query was not a string in $this->UPDATEquery() !',
00517                 1270853880
00518             );
00519         }
00520     }
00521 
00522     /**
00523      * Creates a DELETE SQL-statement for $table where $where-clause
00524      * Usage count/core: 3
00525      *
00526      * @param   string      See exec_DELETEquery()
00527      * @param   string      See exec_DELETEquery()
00528      * @return  string      Full SQL query for DELETE
00529      */
00530     function DELETEquery($table, $where) {
00531         if (is_string($where)) {
00532 
00533                 // Table and fieldnames should be "SQL-injection-safe" when supplied to this function
00534             $query = 'DELETE FROM ' . $table .
00535                 (strlen($where) > 0 ? ' WHERE ' . $where : '');
00536 
00537             if ($this->debugOutput || $this->store_lastBuiltQuery) {
00538                 $this->debug_lastBuiltQuery = $query;
00539             }
00540             return $query;
00541         } else {
00542             throw new InvalidArgumentException(
00543                 'TYPO3 Fatal Error: "Where" clause argument for DELETE query was not a string in $this->DELETEquery() !',
00544                 1270853881
00545             );
00546         }
00547     }
00548 
00549     /**
00550      * Creates a SELECT SQL-statement
00551      * Usage count/core: 11
00552      *
00553      * @param   string      See exec_SELECTquery()
00554      * @param   string      See exec_SELECTquery()
00555      * @param   string      See exec_SELECTquery()
00556      * @param   string      See exec_SELECTquery()
00557      * @param   string      See exec_SELECTquery()
00558      * @param   string      See exec_SELECTquery()
00559      * @return  string      Full SQL query for SELECT
00560      */
00561     function SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '') {
00562 
00563             // Table and fieldnames should be "SQL-injection-safe" when supplied to this function
00564             // Build basic query:
00565         $query = 'SELECT ' . $select_fields . ' FROM ' . $from_table .
00566             (strlen($where_clause) > 0 ? ' WHERE ' . $where_clause : '');
00567 
00568             // Group by:
00569         $query .= (strlen($groupBy) > 0 ? ' GROUP BY ' . $groupBy : '');
00570 
00571             // Order by:
00572         $query .= (strlen($orderBy) > 0 ? ' ORDER BY ' . $orderBy : '');
00573 
00574             // Group by:
00575         $query .= (strlen($limit) > 0 ? ' LIMIT ' . $limit : '');
00576 
00577             // Return query:
00578         if ($this->debugOutput || $this->store_lastBuiltQuery) {
00579             $this->debug_lastBuiltQuery = $query;
00580         }
00581         return $query;
00582     }
00583 
00584     /**
00585      * Creates a SELECT SQL-statement to be used as subquery within another query.
00586      * BEWARE: This method should not be overriden within DBAL to prevent quoting from happening.
00587      *
00588      * @param   string      $select_fields: List of fields to select from the table.
00589      * @param   string      $from_table: Table from which to select.
00590      * @param   string      $where_clause: Conditional WHERE statement
00591      * @return  string      Full SQL query for SELECT
00592      */
00593     public function SELECTsubquery($select_fields, $from_table, $where_clause) {
00594             // Table and fieldnames should be "SQL-injection-safe" when supplied to this function
00595             // Build basic query:
00596         $query = 'SELECT ' . $select_fields . ' FROM ' . $from_table .
00597             (strlen($where_clause) > 0 ? ' WHERE ' . $where_clause : '');
00598 
00599             // Return query:
00600         if ($this->debugOutput || $this->store_lastBuiltQuery) {
00601             $this->debug_lastBuiltQuery = $query;
00602         }
00603 
00604         return $query;
00605     }
00606 
00607     /**
00608      * Creates a TRUNCATE TABLE SQL-statement
00609      *
00610      * @param   string      See exec_TRUNCATEquery()
00611      * @return  string      Full SQL query for TRUNCATE TABLE
00612      */
00613     public function TRUNCATEquery($table) {
00614             // Table should be "SQL-injection-safe" when supplied to this function
00615             // Build basic query:
00616         $query = 'TRUNCATE TABLE ' . $table;
00617 
00618             // Return query:
00619         if ($this->debugOutput || $this->store_lastBuiltQuery) {
00620             $this->debug_lastBuiltQuery = $query;
00621         }
00622 
00623         return $query;
00624     }
00625 
00626     /**
00627      * Returns a WHERE clause that can find a value ($value) in a list field ($field)
00628      * For instance a record in the database might contain a list of numbers,
00629      * "34,234,5" (with no spaces between). This query would be able to select that
00630      * record based on the value "34", "234" or "5" regardless of their position in
00631      * the list (left, middle or right).
00632      * The value must not contain a comma (,)
00633      * Is nice to look up list-relations to records or files in TYPO3 database tables.
00634      *
00635      * @param   string      Field name
00636      * @param   string      Value to find in list
00637      * @param   string      Table in which we are searching (for DBAL detection of quoteStr() method)
00638      * @return  string      WHERE clause for a query
00639      */
00640     public function listQuery($field, $value, $table) {
00641         if (strpos(',', $value) !== FALSE) {
00642             throw new InvalidArgumentException('$value must not contain a comma (,) in $this->listQuery() !');
00643         }
00644         $pattern = $this->quoteStr($value, $table);
00645         $where = 'FIND_IN_SET(\'' . $pattern . '\',' . $field . ')';
00646         return $where;
00647     }
00648 
00649     /**
00650      * Returns a WHERE clause which will make an AND search for the words in the $searchWords array in any of the fields in array $fields.
00651      *
00652      * @param   array       Array of search words
00653      * @param   array       Array of fields
00654      * @param   string      Table in which we are searching (for DBAL detection of quoteStr() method)
00655      * @return  string      WHERE clause for search
00656      */
00657     function searchQuery($searchWords, $fields, $table) {
00658         $queryParts = array();
00659 
00660         foreach($searchWords as $sw) {
00661             $like = ' LIKE \'%' . $this->quoteStr($sw, $table) . '%\'';
00662             $queryParts[] = $table . '.' . implode($like . ' OR ' . $table . '.', $fields) . $like;
00663         }
00664         $query = '(' . implode(') AND (', $queryParts) . ')';
00665         return $query ;
00666     }
00667 
00668 
00669 
00670 
00671 
00672 
00673 
00674 
00675 
00676 
00677 
00678 
00679 
00680 
00681 
00682 
00683     /**************************************
00684      *
00685      * Various helper functions
00686      *
00687      * Functions recommended to be used for
00688      * - escaping values,
00689      * - cleaning lists of values,
00690      * - stripping of excess ORDER BY/GROUP BY keywords
00691      *
00692      **************************************/
00693 
00694     /**
00695      * Escaping and quoting values for SQL statements.
00696      * Usage count/core: 100
00697      *
00698      * @param   string      Input string
00699      * @param   string      Table name for which to quote string. Just enter the table that the field-value is selected from (and any DBAL will look up which handler to use and then how to quote the string!).
00700      * @return  string      Output string; Wrapped in single quotes and quotes in the string (" / ') and \ will be backslashed (or otherwise based on DBAL handler)
00701      * @see quoteStr()
00702      */
00703     function fullQuoteStr($str, $table) {
00704         return '\'' . mysql_real_escape_string($str, $this->link) . '\'';
00705     }
00706 
00707     /**
00708      * Will fullquote all values in the one-dimensional array so they are ready to "implode" for an sql query.
00709      *
00710      * @param   array       Array with values (either associative or non-associative array)
00711      * @param   string      Table name for which to quote
00712      * @param   string/array        List/array of keys NOT to quote (eg. SQL functions) - ONLY for associative arrays
00713      * @return  array       The input array with the values quoted
00714      * @see cleanIntArray()
00715      */
00716     function fullQuoteArray($arr, $table, $noQuote = FALSE) {
00717         if (is_string($noQuote)) {
00718             $noQuote = explode(',', $noQuote);
00719             // sanity check
00720         } elseif (!is_array($noQuote)) {
00721             $noQuote = FALSE;
00722         }
00723 
00724         foreach($arr as $k => $v) {
00725             if ($noQuote === FALSE || !in_array($k, $noQuote)) {
00726                 $arr[$k] = $this->fullQuoteStr($v, $table);
00727             }
00728         }
00729         return $arr;
00730     }
00731 
00732     /**
00733      * Substitution for PHP function "addslashes()"
00734      * Use this function instead of the PHP addslashes() function when you build queries - this will prepare your code for DBAL.
00735      * NOTICE: You must wrap the output of this function in SINGLE QUOTES to be DBAL compatible. Unless you have to apply the single quotes yourself you should rather use ->fullQuoteStr()!
00736      *
00737      * Usage count/core: 20
00738      *
00739      * @param   string      Input string
00740      * @param   string      Table name for which to quote string. Just enter the table that the field-value is selected from (and any DBAL will look up which handler to use and then how to quote the string!).
00741      * @return  string      Output string; Quotes (" / ') and \ will be backslashed (or otherwise based on DBAL handler)
00742      * @see quoteStr()
00743      */
00744     function quoteStr($str, $table) {
00745         return mysql_real_escape_string($str, $this->link);
00746     }
00747 
00748     /**
00749      * Escaping values for SQL LIKE statements.
00750      *
00751      * @param   string      Input string
00752      * @param   string      Table name for which to escape string. Just enter the table that the field-value is selected from (and any DBAL will look up which handler to use and then how to quote the string!).
00753      * @return  string      Output string; % and _ will be escaped with \ (or otherwise based on DBAL handler)
00754      * @see quoteStr()
00755      */
00756     function escapeStrForLike($str, $table) {
00757         return preg_replace('/[_%]/', '\\\$0', $str);
00758     }
00759 
00760     /**
00761      * Will convert all values in the one-dimensional array to integers.
00762      * Useful when you want to make sure an array contains only integers before imploding them in a select-list.
00763      * Usage count/core: 7
00764      *
00765      * @param   array       Array with values
00766      * @return  array       The input array with all values passed through intval()
00767      * @see cleanIntList()
00768      */
00769     function cleanIntArray($arr) {
00770         foreach($arr as $k => $v) {
00771             $arr[$k] = intval($arr[$k]);
00772         }
00773         return $arr;
00774     }
00775 
00776     /**
00777      * Will force all entries in the input comma list to integers
00778      * Useful when you want to make sure a commalist of supposed integers really contain only integers; You want to know that when you don't trust content that could go into an SQL statement.
00779      * Usage count/core: 6
00780      *
00781      * @param   string      List of comma-separated values which should be integers
00782      * @return  string      The input list but with every value passed through intval()
00783      * @see cleanIntArray()
00784      */
00785     function cleanIntList($list) {
00786         return implode(',', t3lib_div::intExplode(',', $list));
00787     }
00788 
00789     /**
00790      * Removes the prefix "ORDER BY" from the input string.
00791      * This function is used when you call the exec_SELECTquery() function and want to pass the ORDER BY parameter by can't guarantee that "ORDER BY" is not prefixed.
00792      * Generally; This function provides a work-around to the situation where you cannot pass only the fields by which to order the result.
00793      * Usage count/core: 11
00794      *
00795      * @param   string      eg. "ORDER BY title, uid"
00796      * @return  string      eg. "title, uid"
00797      * @see exec_SELECTquery(), stripGroupBy()
00798      */
00799     function stripOrderBy($str) {
00800         return preg_replace('/^ORDER[[:space:]]+BY[[:space:]]+/i', '', trim($str));
00801     }
00802 
00803     /**
00804      * Removes the prefix "GROUP BY" from the input string.
00805      * This function is used when you call the SELECTquery() function and want to pass the GROUP BY parameter by can't guarantee that "GROUP BY" is not prefixed.
00806      * Generally; This function provides a work-around to the situation where you cannot pass only the fields by which to order the result.
00807      * Usage count/core: 1
00808      *
00809      * @param   string      eg. "GROUP BY title, uid"
00810      * @return  string      eg. "title, uid"
00811      * @see exec_SELECTquery(), stripOrderBy()
00812      */
00813     function stripGroupBy($str) {
00814         return preg_replace('/^GROUP[[:space:]]+BY[[:space:]]+/i', '', trim($str));
00815     }
00816 
00817     /**
00818      * Takes the last part of a query, eg. "... uid=123 GROUP BY title ORDER BY title LIMIT 5,2" and splits each part into a table (WHERE, GROUPBY, ORDERBY, LIMIT)
00819      * Work-around function for use where you know some userdefined end to an SQL clause is supplied and you need to separate these factors.
00820      * Usage count/core: 13
00821      *
00822      * @param   string      Input string
00823      * @return  array
00824      */
00825     function splitGroupOrderLimit($str) {
00826             // Prepending a space to make sure "[[:space:]]+" will find a space there
00827             // for the first element.
00828         $str = ' ' . $str;
00829             // Init output array:
00830         $wgolParts = array(
00831             'WHERE' => '',
00832             'GROUPBY' => '',
00833             'ORDERBY' => '',
00834             'LIMIT' => '',
00835         );
00836 
00837             // Find LIMIT:
00838         $reg = array();
00839         if (preg_match('/^(.*)[[:space:]]+LIMIT[[:space:]]+([[:alnum:][:space:],._]+)$/i', $str, $reg)) {
00840             $wgolParts['LIMIT'] = trim($reg[2]);
00841             $str = $reg[1];
00842         }
00843 
00844             // Find ORDER BY:
00845         $reg = array();
00846         if (preg_match('/^(.*)[[:space:]]+ORDER[[:space:]]+BY[[:space:]]+([[:alnum:][:space:],._]+)$/i', $str, $reg)) {
00847             $wgolParts['ORDERBY'] = trim($reg[2]);
00848             $str = $reg[1];
00849         }
00850 
00851             // Find GROUP BY:
00852         $reg = array();
00853         if (preg_match('/^(.*)[[:space:]]+GROUP[[:space:]]+BY[[:space:]]+([[:alnum:][:space:],._]+)$/i', $str, $reg)) {
00854             $wgolParts['GROUPBY'] = trim($reg[2]);
00855             $str = $reg[1];
00856         }
00857 
00858             // Rest is assumed to be "WHERE" clause:
00859         $wgolParts['WHERE'] = $str;
00860 
00861         return $wgolParts;
00862     }
00863 
00864 
00865 
00866 
00867 
00868 
00869 
00870 
00871 
00872 
00873 
00874 
00875 
00876 
00877 
00878     /**************************************
00879      *
00880      * MySQL wrapper functions
00881      * (For use in your applications)
00882      *
00883      **************************************/
00884 
00885     /**
00886      * Executes query
00887      * mysql() wrapper function
00888      * Usage count/core: 0
00889      *
00890      * @param   string      Database name
00891      * @param   string      Query to execute
00892      * @return  pointer     Result pointer / DBAL object
00893      * @deprecated since TYPO3 3.6, will be removed in TYPO3 4.5
00894      * @see sql_query()
00895      */
00896     function sql($db, $query) {
00897         t3lib_div::logDeprecatedFunction();
00898 
00899         $res = mysql_query($query, $this->link);
00900         if ($this->debugOutput) {
00901             $this->debug('sql', $query);
00902         }
00903         return $res;
00904     }
00905 
00906     /**
00907      * Executes query
00908      * mysql_query() wrapper function
00909      * Usage count/core: 1
00910      *
00911      * @param   string      Query to execute
00912      * @return  pointer     Result pointer / DBAL object
00913      */
00914     function sql_query($query) {
00915         $res = mysql_query($query, $this->link);
00916         if ($this->debugOutput) {
00917             $this->debug('sql_query', $query);
00918         }
00919         return $res;
00920     }
00921 
00922     /**
00923      * Returns the error status on the last sql() execution
00924      * mysql_error() wrapper function
00925      * Usage count/core: 32
00926      *
00927      * @return  string      MySQL error string.
00928      */
00929     function sql_error() {
00930         return mysql_error($this->link);
00931     }
00932 
00933     /**
00934      * Returns the error number on the last sql() execution
00935      * mysql_errno() wrapper function
00936      *
00937      * @return  int     MySQL error number.
00938      */
00939     function sql_errno() {
00940         return mysql_errno($this->link);
00941     }
00942 
00943     /**
00944      * Returns the number of selected rows.
00945      * mysql_num_rows() wrapper function
00946      * Usage count/core: 85
00947      *
00948      * @param   pointer     MySQL result pointer (of SELECT query) / DBAL object
00949      * @return  integer     Number of resulting rows
00950      */
00951     function sql_num_rows($res) {
00952         if ($this->debug_check_recordset($res)) {
00953             return mysql_num_rows($res);
00954         } else {
00955             return FALSE;
00956         }
00957     }
00958 
00959     /**
00960      * Returns an associative array that corresponds to the fetched row, or FALSE if there are no more rows.
00961      * mysql_fetch_assoc() wrapper function
00962      * Usage count/core: 307
00963      *
00964      * @param   pointer     MySQL result pointer (of SELECT query) / DBAL object
00965      * @return  array       Associative array of result row.
00966      */
00967     function sql_fetch_assoc($res) {
00968         if ($this->debug_check_recordset($res)) {
00969             return mysql_fetch_assoc($res);
00970         } else {
00971             return FALSE;
00972         }
00973     }
00974 
00975     /**
00976      * Returns an array that corresponds to the fetched row, or FALSE if there are no more rows.
00977      * The array contains the values in numerical indices.
00978      * mysql_fetch_row() wrapper function
00979      * Usage count/core: 56
00980      *
00981      * @param   pointer     MySQL result pointer (of SELECT query) / DBAL object
00982      * @return  array       Array with result rows.
00983      */
00984     function sql_fetch_row($res) {
00985         if ($this->debug_check_recordset($res)) {
00986             return mysql_fetch_row($res);
00987         } else {
00988             return FALSE;
00989         }
00990     }
00991 
00992     /**
00993      * Free result memory
00994      * mysql_free_result() wrapper function
00995      * Usage count/core: 3
00996      *
00997      * @param   pointer     MySQL result pointer to free / DBAL object
00998      * @return  boolean     Returns TRUE on success or FALSE on failure.
00999      */
01000     function sql_free_result($res) {
01001         if ($this->debug_check_recordset($res)) {
01002             return mysql_free_result($res);
01003         } else {
01004             return FALSE;
01005         }
01006     }
01007 
01008     /**
01009      * Get the ID generated from the previous INSERT operation
01010      * mysql_insert_id() wrapper function
01011      * Usage count/core: 13
01012      *
01013      * @return  integer     The uid of the last inserted record.
01014      */
01015     function sql_insert_id() {
01016         return mysql_insert_id($this->link);
01017     }
01018 
01019     /**
01020      * Returns the number of rows affected by the last INSERT, UPDATE or DELETE query
01021      * mysql_affected_rows() wrapper function
01022      * Usage count/core: 1
01023      *
01024      * @return  integer     Number of rows affected by last query
01025      */
01026     function sql_affected_rows() {
01027         return mysql_affected_rows($this->link);
01028     }
01029 
01030     /**
01031      * Move internal result pointer
01032      * mysql_data_seek() wrapper function
01033      * Usage count/core: 3
01034      *
01035      * @param   pointer     MySQL result pointer (of SELECT query) / DBAL object
01036      * @param   integer     Seek result number.
01037      * @return  boolean     Returns TRUE on success or FALSE on failure.
01038      */
01039     function sql_data_seek($res, $seek) {
01040         if ($this->debug_check_recordset($res)) {
01041             return mysql_data_seek($res, $seek);
01042         } else {
01043             return FALSE;
01044         }
01045     }
01046 
01047     /**
01048      * Get the type of the specified field in a result
01049      * mysql_field_type() wrapper function
01050      * Usage count/core: 2
01051      *
01052      * @param   pointer     MySQL result pointer (of SELECT query) / DBAL object
01053      * @param   integer     Field index.
01054      * @return  string      Returns the name of the specified field index
01055      */
01056     function sql_field_type($res, $pointer) {
01057         if ($this->debug_check_recordset($res)) {
01058             return mysql_field_type($res, $pointer);
01059         } else {
01060             return FALSE;
01061         }
01062     }
01063 
01064     /**
01065      * Open a (persistent) connection to a MySQL server
01066      * mysql_pconnect() wrapper function
01067      * Usage count/core: 12
01068      *
01069      * @param   string      Database host IP/domain
01070      * @param   string      Username to connect with.
01071      * @param   string      Password to connect with.
01072      * @return  pointer     Returns a positive MySQL persistent link identifier on success, or FALSE on error.
01073      */
01074     function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password)   {
01075             // mysql_error() is tied to an established connection
01076             // if the connection fails we need a different method to get the error message
01077         @ini_set('track_errors', 1);
01078         @ini_set('html_errors', 0);
01079 
01080             // check if MySQL extension is loaded
01081         if (!extension_loaded('mysql')) {
01082             $message = 'Database Error: It seems that MySQL support for PHP is not installed!';
01083             throw new RuntimeException($message, 1271492606);
01084         }
01085 
01086             // Check for client compression
01087         $isLocalhost = ($TYPO3_db_host == 'localhost' || $TYPO3_db_host == '127.0.0.1');
01088         if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect']) {
01089             if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['dbClientCompress'] && !$isLocalhost) {
01090                     // We use PHP's default value for 4th parameter (new_link), which is false.
01091                     // See PHP sources, for example: file php-5.2.5/ext/mysql/php_mysql.c,
01092                     // function php_mysql_do_connect(), near line 525
01093                 $this->link = @mysql_connect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password, false, MYSQL_CLIENT_COMPRESS);
01094             } else {
01095                 $this->link = @mysql_connect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password);
01096             }
01097         } else {
01098             if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['dbClientCompress'] && !$isLocalhost) {
01099                     // See comment about 4th parameter in block above
01100                 $this->link = @mysql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password, false, MYSQL_CLIENT_COMPRESS);
01101             } else {
01102                 $this->link = @mysql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password);
01103             }
01104         }
01105 
01106         $error_msg = $php_errormsg;
01107         @ini_restore('track_errors');
01108         @ini_restore('html_errors');
01109 
01110         if (!$this->link) {
01111             t3lib_div::sysLog('Could not connect to MySQL server ' . $TYPO3_db_host .
01112                 ' with user ' . $TYPO3_db_username . ': ' . $error_msg,
01113                 'Core',
01114                 4
01115             );
01116         } else {
01117             $setDBinit = t3lib_div::trimExplode(LF, str_replace("' . LF . '", LF, $GLOBALS['TYPO3_CONF_VARS']['SYS']['setDBinit']), TRUE);
01118             foreach ($setDBinit as $v) {
01119                 if (mysql_query($v, $this->link) === FALSE) {
01120                     t3lib_div::sysLog('Could not initialize DB connection with query "' . $v .
01121                         '": ' . mysql_error($this->link),
01122                         'Core',
01123                         3
01124                     );
01125                 }
01126             }
01127         }
01128 
01129         return $this->link;
01130     }
01131 
01132     /**
01133      * Select a MySQL database
01134      * mysql_select_db() wrapper function
01135      * Usage count/core: 8
01136      *
01137      * @param   string      Database to connect to.
01138      * @return  boolean     Returns TRUE on success or FALSE on failure.
01139      */
01140     function sql_select_db($TYPO3_db) {
01141         $ret = @mysql_select_db($TYPO3_db, $this->link);
01142         if (!$ret) {
01143             t3lib_div::sysLog('Could not select MySQL database ' . $TYPO3_db . ': ' .
01144                 mysql_error(),
01145                 'Core',
01146                 4
01147             );
01148         }
01149         return $ret;
01150     }
01151 
01152 
01153 
01154 
01155 
01156 
01157 
01158 
01159 
01160 
01161     /**************************************
01162      *
01163      * SQL admin functions
01164      * (For use in the Install Tool and Extension Manager)
01165      *
01166      **************************************/
01167 
01168     /**
01169      * Listing databases from current MySQL connection. NOTICE: It WILL try to select those databases and thus break selection of current database.
01170      * This is only used as a service function in the (1-2-3 process) of the Install Tool.
01171      * In any case a lookup should be done in the _DEFAULT handler DBMS then.
01172      * Use in Install Tool only!
01173      * Usage count/core: 1
01174      *
01175      * @return  array       Each entry represents a database name
01176      */
01177     function admin_get_dbs() {
01178         $dbArr = array();
01179         $db_list = mysql_list_dbs($this->link);
01180         while ($row = mysql_fetch_object($db_list)) {
01181             if ($this->sql_select_db($row->Database)) {
01182                 $dbArr[] = $row->Database;
01183             }
01184         }
01185         return $dbArr;
01186     }
01187 
01188     /**
01189      * Returns the list of tables from the default database, TYPO3_db (quering the DBMS)
01190      * In a DBAL this method should 1) look up all tables from the DBMS  of
01191      * the _DEFAULT handler and then 2) add all tables *configured* to be managed by other handlers
01192      * Usage count/core: 2
01193      *
01194      * @return  array       Array with tablenames as key and arrays with status information as value
01195      */
01196     function admin_get_tables() {
01197         $whichTables = array();
01198 
01199         $tables_result = mysql_query('SHOW TABLE STATUS FROM `' . TYPO3_db . '`', $this->link);
01200         if (!mysql_error()) {
01201             while ($theTable = mysql_fetch_assoc($tables_result)) {
01202                 $whichTables[$theTable['Name']] = $theTable;
01203             }
01204 
01205             $this->sql_free_result($tables_result);
01206         }
01207 
01208         return $whichTables;
01209     }
01210 
01211     /**
01212      * Returns information about each field in the $table (quering the DBMS)
01213      * In a DBAL this should look up the right handler for the table and return compatible information
01214      * This function is important not only for the Install Tool but probably for
01215      * DBALs as well since they might need to look up table specific information
01216      * in order to construct correct queries. In such cases this information should
01217      * probably be cached for quick delivery.
01218      *
01219      * @param   string      Table name
01220      * @return  array       Field information in an associative array with fieldname => field row
01221      */
01222     function admin_get_fields($tableName) {
01223         $output = array();
01224 
01225         $columns_res = mysql_query('SHOW COLUMNS FROM `' . $tableName . '`', $this->link);
01226         while ($fieldRow = mysql_fetch_assoc($columns_res)) {
01227             $output[$fieldRow['Field']] = $fieldRow;
01228         }
01229 
01230         $this->sql_free_result($columns_res);
01231 
01232         return $output;
01233     }
01234 
01235     /**
01236      * Returns information about each index key in the $table (quering the DBMS)
01237      * In a DBAL this should look up the right handler for the table and return compatible information
01238      *
01239      * @param   string      Table name
01240      * @return  array       Key information in a numeric array
01241      */
01242     function admin_get_keys($tableName) {
01243         $output = array();
01244 
01245         $keyRes = mysql_query('SHOW KEYS FROM `' . $tableName . '`', $this->link);
01246         while ($keyRow = mysql_fetch_assoc($keyRes)) {
01247             $output[] = $keyRow;
01248         }
01249 
01250         $this->sql_free_result($keyRes);
01251 
01252         return $output;
01253     }
01254 
01255     /**
01256      * Returns information about the character sets supported by the current DBM
01257      * This function is important not only for the Install Tool but probably for
01258      * DBALs as well since they might need to look up table specific information
01259      * in order to construct correct queries. In such cases this information should
01260      * probably be cached for quick delivery.
01261      *
01262      * This is used by the Install Tool to convert tables tables with non-UTF8 charsets
01263      * Use in Install Tool only!
01264      *
01265      * @return  array       Array with Charset as key and an array of "Charset", "Description", "Default collation", "Maxlen" as values
01266      */
01267     function admin_get_charsets() {
01268         $output = array();
01269 
01270         $columns_res = mysql_query('SHOW CHARACTER SET', $this->link);
01271         if ($columns_res) {
01272             while (($row = mysql_fetch_assoc($columns_res))) {
01273                 $output[$row['Charset']] = $row;
01274             }
01275 
01276             $this->sql_free_result($columns_res);
01277         }
01278 
01279         return $output;
01280     }
01281 
01282     /**
01283      * mysql() wrapper function, used by the Install Tool and EM for all queries regarding management of the database!
01284      * Usage count/core: 10
01285      *
01286      * @param   string      Query to execute
01287      * @return  pointer     Result pointer
01288      */
01289     function admin_query($query) {
01290         $res = mysql_query($query, $this->link);
01291         if ($this->debugOutput) {
01292             $this->debug('admin_query', $query);
01293         }
01294         return $res;
01295     }
01296 
01297 
01298 
01299 
01300 
01301 
01302 
01303 
01304 
01305 
01306 
01307 
01308     /******************************
01309      *
01310      * Connecting service
01311      *
01312      ******************************/
01313 
01314     /**
01315      * Connects to database for TYPO3 sites:
01316      *
01317      * @param string $host
01318      * @param string $user
01319      * @param string $password
01320      * @param string $db
01321      * @return  void
01322      */
01323     function connectDB($host = TYPO3_db_host, $user = TYPO3_db_username, $password = TYPO3_db_password, $db = TYPO3_db) {
01324         if ($this->sql_pconnect($host, $user, $password)) {
01325             if (!$db) {
01326                 throw new RuntimeException(
01327                     'TYPO3 Fatal Error: No database selected!',
01328                     1270853882
01329                 );
01330             } elseif (!$this->sql_select_db($db)) {
01331                 throw new RuntimeException(
01332                     'TYPO3 Fatal Error: Cannot connect to the current database, "' . $db . '"!',
01333                     1270853883
01334                 );
01335             }
01336         } else {
01337             throw new RuntimeException(
01338                 'TYPO3 Fatal Error: The current username, password or host was not accepted when the connection to the database was attempted to be established!',
01339                 1270853884
01340             );
01341         }
01342     }
01343 
01344     /**
01345      * Checks if database is connected
01346      *
01347      * @return boolean
01348      */
01349     public function isConnected() {
01350         return is_resource($this->link);
01351     }
01352 
01353 
01354 
01355     /******************************
01356      *
01357      * Debugging
01358      *
01359      ******************************/
01360 
01361     /**
01362      * Debug function: Outputs error if any
01363      *
01364      * @param   string      Function calling debug()
01365      * @param   string      Last query if not last built query
01366      * @return  void
01367      */
01368     function debug($func, $query='') {
01369 
01370         $error = $this->sql_error();
01371         if ($error) {
01372             debug(
01373                 array(
01374                     'caller' => 't3lib_DB::' . $func,
01375                     'ERROR' => $error,
01376                     'lastBuiltQuery' => ($query ? $query : $this->debug_lastBuiltQuery),
01377                     'debug_backtrace' => t3lib_div::debug_trail(),
01378                 ),
01379                 $func,
01380                 is_object($GLOBALS['error']) && @is_callable(array($GLOBALS['error'], 'debug')) ? '' : 'DB Error'
01381             );
01382         }
01383     }
01384 
01385     /**
01386      * Checks if recordset is valid and writes debugging inormation into devLog if not.
01387      *
01388      * @param   resource    $res    Recordset
01389      * @return  boolean <code>false</code> if recordset is not valid
01390      */
01391     function debug_check_recordset($res) {
01392         if (!$res) {
01393             $trace = FALSE;
01394             $msg = 'Invalid database result resource detected';
01395             $trace = debug_backtrace();
01396             array_shift($trace);
01397             $cnt = count($trace);
01398             for ($i = 0; $i < $cnt; $i++) {
01399                     // complete objects are too large for the log
01400                 if (isset($trace['object'])) {
01401                     unset($trace['object']);
01402                 }
01403             }
01404             $msg .= ': function t3lib_DB->' . $trace[0]['function'] . ' called from file ' .
01405                 substr($trace[0]['file'], strlen(PATH_site) + 2) . ' in line ' .
01406                 $trace[0]['line'];
01407             t3lib_div::sysLog($msg.'. Use a devLog extension to get more details.', 'Core/t3lib_db', 3);
01408                 // Send to devLog if enabled
01409             if (TYPO3_DLOG) {
01410                 $debugLogData = array(
01411                     'SQL Error' => $this->sql_error(),
01412                     'Backtrace' => $trace,
01413                 );
01414                 if ($this->debug_lastBuiltQuery) {
01415                     $debugLogData = array('SQL Query' => $this->debug_lastBuiltQuery) + $debugLogData;
01416                 }
01417                 t3lib_div::devLog($msg . '.', 'Core/t3lib_db', 3, $debugLogData);
01418             }
01419 
01420             return FALSE;
01421         }
01422         return TRUE;
01423     }
01424 
01425     /**
01426      * Explain select queries
01427      * If $this->explainOutput is set, SELECT queries will be explained here. Only queries with more than one possible result row will be displayed.
01428      * The output is either printed as raw HTML output or embedded into the TS admin panel (checkbox must be enabled!)
01429      *
01430      * TODO: Feature is not DBAL-compliant
01431      *
01432      * @param   string      SQL query
01433      * @param   string      Table(s) from which to select. This is what comes right after "FROM ...". Required value.
01434      * @param   integer     Number of resulting rows
01435      * @return  boolean     True if explain was run, false otherwise
01436      */
01437     protected function explain($query, $from_table, $row_count) {
01438 
01439         if ((int)$this->explainOutput == 1 || ((int)$this->explainOutput == 2 &&
01440             t3lib_div::cmpIP(t3lib_div::getIndpEnv('REMOTE_ADDR'), $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']))
01441             ) {
01442                 // raw HTML output
01443             $explainMode = 1;
01444         } elseif ((int)$this->explainOutput == 3 && is_object($GLOBALS['TT'])) {
01445                 // embed the output into the TS admin panel
01446             $explainMode = 2;
01447         } else {
01448             return false;
01449         }
01450 
01451         $error = $this->sql_error();
01452         $trail = t3lib_div::debug_trail();
01453 
01454         $explain_tables = array();
01455         $explain_output = array();
01456         $res = $this->sql_query('EXPLAIN ' . $query, $this->link);
01457         if (is_resource($res)) {
01458             while ($tempRow = $this->sql_fetch_assoc($res)) {
01459                 $explain_output[] = $tempRow;
01460                 $explain_tables[] = $tempRow['table'];
01461             }
01462             $this->sql_free_result($res);
01463         }
01464 
01465         $indices_output = array();
01466             // Notice: Rows are skipped if there is only one result, or if no conditions are set
01467         if ($explain_output[0]['rows'] > 1 || t3lib_div::inList('ALL', $explain_output[0]['type'])) {
01468                 // only enable output if it's really useful
01469             $debug = true;
01470 
01471             foreach ($explain_tables as $table) {
01472                 $tableRes = $this->sql_query('SHOW TABLE STATUS LIKE \'' . $table . '\'');
01473                 $isTable = $this->sql_num_rows($tableRes);
01474                 if ($isTable) {
01475                     $res = $this->sql_query('SHOW INDEX FROM ' . $table, $this->link);
01476                     if (is_resource($res)) {
01477                         while ($tempRow = $this->sql_fetch_assoc($res)) {
01478                             $indices_output[] = $tempRow;
01479                         }
01480                         $this->sql_free_result($res);
01481                     }
01482                 }
01483                 $this->sql_free_result($tableRes);
01484             }
01485         } else {
01486             $debug = false;
01487         }
01488 
01489         if ($debug) {
01490             if ($explainMode) {
01491                 $data = array();
01492                 $data['query'] = $query;
01493                 $data['trail'] = $trail;
01494                 $data['row_count'] = $row_count;
01495 
01496                 if ($error) {
01497                     $data['error'] = $error;
01498                 }
01499                 if (count($explain_output)) {
01500                     $data['explain'] = $explain_output;
01501                 }
01502                 if (count($indices_output)) {
01503                     $data['indices'] = $indices_output;
01504                 }
01505 
01506                 if ($explainMode == 1) {
01507                     t3lib_div::debug($data, 'Tables: ' . $from_table, 'DB SQL EXPLAIN');
01508                 } elseif ($explainMode == 2) {
01509                     $GLOBALS['TT']->setTSselectQuery($data);
01510                 }
01511             }
01512             return true;
01513         }
01514 
01515         return false;
01516     }
01517 
01518 }
01519 
01520 
01521 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_db.php'])    {
01522     include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_db.php']);
01523 }
01524 
01525 ?>

Generated on Sat Jul 24 04:17:16 2010 for TYPO3 API by  doxygen 1.4.7