3 * @version $Id: database.php 1982 2009-06-15 06:59:55Z fishbone $
4 * @package Joomla.Framework
6 * @copyright Copyright (C) 2005 - 2008 Open Source Matters. All rights reserved.
7 * @license GNU/GPL, see LICENSE.php
8 * Joomla! is free software. This version may have been modified pursuant
9 * to the GNU General Public License, and as distributed it includes or
10 * is derivative of works licensed under the GNU General Public License or
11 * other free or open source software licenses.
12 * See COPYRIGHT.php for copyright notices and details.
15 // Check to ensure this file is within the rest of the framework
16 //defined('JPATH_BASE') or die();
19 * Database connector class
22 * @package Joomla.Framework
23 * @subpackage Database
26 class JDatabase extends JObject
29 * The database driver name
36 * The query sql string
43 * The database error number
50 * The database error message
57 * The prefix used on all database tables
61 var $_table_prefix = '';
64 * The connector resource
71 * The last query cursor
85 * The limit for the query
92 * The for offset for the limit
99 * The number of queries performed by the object instance
113 * The null/zero date string
117 var $_nullDate = null;
120 * Quote for named objects
124 var $_nameQuote = null;
136 * The fields that are to be quote
144 * Legacy compatibility
149 var $_hasQuoted = null;
152 * Database object constructor
155 * @param array List of options used to configure the connection
158 function __construct( $options )
160 $prefix = array_key_exists('prefix', $options) ? $options['prefix'] : 'jos_';
162 // Determine utf-8 support
163 // $this->_utf = $this->hasUTF();
165 //Set charactersets (needed for MySQL 4.1.2+)
170 $this->_table_prefix = $prefix;
172 $this->_errorNum = 0;
173 $this->_log = array();
174 $this->_quoted = array();
175 $this->_hasQuoted = false;
177 // Register faked "destructor" in PHP4 to close all connections we might have made
178 if (version_compare(PHP_VERSION, '5') == -1) {
179 register_shutdown_function(array(&$this, '__destruct'));
184 * Returns a reference to the global Database object, only creating it
185 * if it doesn't already exist.
187 * The 'driver' entry in the parameters array specifies the database driver
188 * to be used (defaults to 'mysql' if omitted). All other parameters are
189 * database driver dependent.
191 * @param array Parameters to be passed to the database driver
192 * @return JDatabase A database object
195 function &getInstance( $options = array() )
199 if (!isset( $instances )) {
200 $instances = array();
203 $signature = serialize( $options );
205 if (empty($instances[$signature]))
208 $driver = array_key_exists('driver', $options) ? $options['driver'] : 'mysql';
209 $select = array_key_exists('select', $options) ? $options['select'] : true;
210 $database = array_key_exists('database', $options) ? $options['database'] : null;
212 $driver = preg_replace('/[^A-Z0-9_\.-]/i', '', $driver);
213 $path = dirname(__FILE__).DS.'database'.DS.$driver.'.php';
215 if (file_exists($path)) {
218 JError::setErrorHandling(E_ERROR, 'die'); //force error type to die
219 $error = JError::raiseError( 500, JTEXT::_('Unable to load Database Driver:') .$driver);
223 $adapter = 'JDatabase'.$driver;
224 $instance = new $adapter($options);
226 if ( $error = $instance->getErrorMsg() )
228 JError::setErrorHandling(E_ERROR, 'ignore'); //force error type to die
229 $error = JError::raiseError( 500, JTEXT::_('Unable to connect to the database:') .$error);
234 $instances[$signature] = & $instance;
236 $instances[$signature] = new JDatabase($options);
239 return $instances[$signature];
243 * Database object destructor
250 function __destruct()
256 * Get the database connectors
259 * @return array An array of available session handlers
261 function getConnectors()
264 jimport('joomla.filesystem.folder');
265 $handlers = JFolder::files(dirname(__FILE__).DS.'database', '.php$');
268 foreach($handlers as $handler)
270 $name = substr($handler, 0, strrpos($handler, '.'));
271 $class = 'JDatabase'.ucfirst($name);
273 if(!class_exists($class)) {
274 require_once(dirname(__FILE__).DS.'database'.DS.$name.'.php');
277 if(call_user_func_array( array( trim($class), 'test' ), null)) {
287 * Test to see if the MySQLi connector is available
291 * @return boolean True on success, false otherwise.
299 * Determines if the connection to the server is active.
305 /*function connected()
311 * Determines UTF support
318 /*function hasUTF() {
323 * Custom settings for UTF support
329 /*function setUTF() {
333 * Adds a field or array of field names to the list that are to be quoted
336 * @param mixed Field name or array of names
339 function addQuoted( $quoted )
341 if (is_string( $quoted )) {
342 $this->_quoted[] = $quoted;
344 $this->_quoted = array_merge( $this->_quoted, (array)$quoted );
346 $this->_hasQuoted = true;
350 * Splits a string of queries into an array of individual queries
353 * @param string The queries to split
354 * @return array queries
356 function splitSql( $queries )
361 $end = strlen($queries);
362 $query_split = array();
363 for($i=0;$i<$end;$i++) {
364 $current = substr($queries,$i,1);
365 if(($current == '"' || $current == '\'')) {
367 while(substr($queries,$i - $n + 1, 1) == '\\' && $n < $i) {
372 if($current == $open_char) {
378 $open_char = $current;
382 if(($current == ';' && !$open)|| $i == $end - 1) {
383 $query_split[] = substr($queries, $start, ($i - $start + 1));
394 * Checks if field name needs to be quoted
397 * @param string The field name
400 function isQuoted( $fieldName )
402 if ($this->_hasQuoted) {
403 return in_array( $fieldName, $this->_quoted );
410 * Sets the debug level on or off
413 * @param int 0 = off, 1 = on
415 function debug( $level ) {
416 $this->_debug = intval( $level );
420 * Get the database UTF-8 support
426 function getUTFSupport() {
431 * Get the error number
434 * @return int The error number for the most recent query
436 function getErrorNum() {
437 return $this->_errorNum;
442 * Get the error message
445 * @return string The error message for the most recent query
447 function getErrorMsg($escaped = false)
450 return addslashes($this->_errorMsg);
452 return $this->_errorMsg;
457 * Get a database escaped string
459 * @param string The string to be escaped
460 * @param boolean Optional parameter to provide extra escaping
465 function getEscaped( $text, $extra = false )
471 * Get a database error log
482 * Get the total number of queries made
487 function getTicker( )
489 return $this->_ticker;
493 * Quote an identifier name (field, table, etc)
496 * @param string The name
497 * @return string The quoted name
499 function nameQuote( $s )
501 // Only quote if the name is not using dot-notation
502 if (strpos( $s, '.' ) === false)
504 $q = $this->_nameQuote;
505 if (strlen( $q ) == 1) {
508 return $q{0} . $s . $q{1};
516 * Get the database table prefix
519 * @return string The database prefix
523 return $this->_table_prefix;
527 * Get the database null date
530 * @return string Quoted null/zero date string
532 function getNullDate()
534 return $this->_nullDate;
538 * Sets the SQL query string for later execution.
540 * This function replaces a string identifier <var>$prefix</var> with the
541 * string held is the <var>_table_prefix</var> class variable.
544 * @param string The SQL query
545 * @param string The offset to start selection
546 * @param string The number of results to return
547 * @param string The common table prefix
549 function setQuery( $sql, $offset = 0, $limit = 0, $prefix='#__' )
551 $this->_sql = $this->replacePrefix( $sql, $prefix );
552 $this->_limit = (int) $limit;
553 $this->_offset = (int) $offset;
557 * This function replaces a string identifier <var>$prefix</var> with the
558 * string held is the <var>_table_prefix</var> class variable.
561 * @param string The SQL query
562 * @param string The common table prefix
564 function replacePrefix( $sql, $prefix='#__' )
575 while ($startPos < $n) {
576 $ip = strpos($sql, $prefix, $startPos);
581 $j = strpos( $sql, "'", $startPos );
582 $k = strpos( $sql, '"', $startPos );
583 if (($k !== FALSE) && (($k < $j) || ($j === FALSE))) {
594 $literal .= str_replace( $prefix, $this->_table_prefix,substr( $sql, $startPos, $j - $startPos ) );
603 // quote comes first, find end of quote
605 $k = strpos( $sql, $quoteChar, $j );
611 while ($l >= 0 && $sql{$l} == '\\') {
613 $escaped = !$escaped;
622 // error in the query - no end quote; ignore it
625 $literal .= substr( $sql, $startPos, $k - $startPos + 1 );
628 if ($startPos < $n) {
629 $literal .= substr( $sql, $startPos, $n - $startPos );
635 * Get the active query
638 * @return string The current value of the internal SQL vairable
650 * @return mixed A database resource if successful, FALSE if not.
658 * Get the affected rows by the most recent query
662 * @return int The number of affected rows in the previous operation
665 function getAffectedRows()
671 * Execute a batch query
675 * @return mixed A database resource if successful, FALSE if not.
677 function queryBatch( $abort_on_error=true, $p_transaction_safe = false)
683 * Diagnostic function
694 * Get the number of rows returned by the most recent query
698 * @param object Database resource
699 * @return int The number of rows
701 function getNumRows( $cur=null )
707 * This method loads the first field of the first row returned by the query.
711 * @return The value returned in the query or null if the query failed.
713 function loadResult()
719 * Load an array of single field results into an array
723 function loadResultArray($numinarray = 0)
729 * Fetch a result row as an associative array
739 * Load a associactive list of database rows
743 * @param string The field name of a primary key
744 * @return array If key is empty as sequential list of returned records.
746 function loadAssocList( $key='' )
752 * This global function loads the first row of a query into an object
759 function loadObject( )
765 * Load a list of database objects
769 * @param string The field name of a primary key
770 * @return array If <var>key</var> is empty as sequential list of returned records.
772 * If <var>key</var> is not empty then the returned array is indexed by the value
773 * the database key. Returns <var>null</var> if the query fails.
775 function loadObjectList( $key='' )
781 * Load the first row returned by the query
785 * @return The first row of the query.
793 * Load a list of database rows (numeric column indexing)
795 * If <var>key</var> is not empty then the returned array is indexed by the value
796 * the database key. Returns <var>null</var> if the query fails.
800 * @param string The field name of a primary key
803 function loadRowList( $key='' )
809 * Inserts a row into a table based on an objects properties
810 * @param string The name of the table
811 * @param object An object whose properties match table fields
812 * @param string The name of the primary key. If provided the object property is updated.
814 function insertObject( $table, &$object, $keyName = NULL )
820 * Update an object in the database
829 function updateObject( $table, &$object, $keyName, $updateNulls=true )
835 * Print out an error statement
837 * @param boolean If TRUE, displays the last SQL statement sent to the database
838 * @return string A standised error message
840 function stderr( $showSQL = false )
842 if ( $this->_errorNum != 0 ) {
843 return "DB function failed with error number $this->_errorNum"
844 ."<br /><font color=\"red\">$this->_errorMsg</font>"
845 .($showSQL ? "<br />SQL = <pre>$this->_sql</pre>" : '');
847 return "DB function reports no errors";
852 * Get the ID generated from the previous INSERT operation
864 * Get the database collation
868 * @return string Collation in use
870 function getCollation()
876 * Get the version of the database connector
880 function getVersion()
882 return 'Not available for this connector';
886 * List tables in a database
890 * @return array A list of all the tables in the database
892 function getTableList()
898 * Shows the CREATE TABLE statement that creates the given tables
902 * @param array|string A table name or a list of table names
903 * @return array A list the create SQL for the tables
905 function getTableCreate( $tables )
911 * Retrieves information about the given tables
915 * @param array|string A table name or a list of table names
916 * @param boolean Only return field types, default true
917 * @return array An array of fields by table
919 function getTableFields( $tables, $typeonly = true )
925 // ADODB Compatibility Functions
929 * Get a quoted database escaped string
931 * @param string A string
932 * @param boolean Default true to escape string, false to leave the string unchanged
936 function Quote( $text, $escaped = true )
938 return '\''.($escaped ? $this->getEscaped( $text ) : $text).'\'';
942 * ADODB compatability function
948 function GetCol( $query )
950 $this->setQuery( $query );
951 return $this->loadResultArray();
955 * ADODB compatability function
962 function Execute( $query )
964 jimport( 'joomla.database.recordset' );
966 $query = trim( $query );
967 $this->setQuery( $query );
968 if (eregi( '^select', $query )) {
969 $result = $this->loadRowList();
970 return new JRecordSet( $result );
972 $result = $this->query();
973 if ($result === false) {
976 return new JRecordSet( array() );
982 * ADODB compatability function
987 function SelectLimit( $query, $count, $offset=0 )
989 jimport( 'joomla.database.recordset' );
991 $this->setQuery( $query, $offset, $count );
992 $result = $this->loadRowList();
993 return new JRecordSet( $result );
997 * ADODB compatability function
1002 function PageExecute( $sql, $nrows, $page, $inputarr=false, $secs2cache=0 )
1004 jimport( 'joomla.database.recordset' );
1006 $this->setQuery( $sql, $page*$nrows, $nrows );
1007 $result = $this->loadRowList();
1008 return new JRecordSet( $result );
1011 * ADODB compatability function
1018 function GetRow( $query )
1020 $this->setQuery( $query );
1021 $result = $this->loadRowList();
1026 * ADODB compatability function
1033 function GetOne( $query )
1035 $this->setQuery( $query );
1036 $result = $this->loadResult();
1041 * ADODB compatability function
1045 function BeginTrans()
1050 * ADODB compatability function
1054 function RollbackTrans()
1059 * ADODB compatability function
1063 function CommitTrans()
1068 * ADODB compatability function
1074 return $this->getErrorMsg();
1078 * ADODB compatability function
1084 return $this->getErrorNum();
1088 * ADODB compatability function
1092 function GenID( $foo1=null, $foo2=null )