2009-06-12 08:14:29 +00:00
< ? php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Abstract database driver class .
*
* @ package moodlecore
* @ subpackage DML
* @ copyright 2008 Petr Skoda ( http :// skodak . org )
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
2008-05-15 21:40:00 +00:00
2008-05-25 22:21:01 +00:00
require_once ( $CFG -> libdir . '/dml/database_column_info.php' );
2008-09-02 20:32:03 +00:00
require_once ( $CFG -> libdir . '/dml/moodle_recordset.php' );
2008-05-25 22:21:01 +00:00
2008-06-15 11:35:25 +00:00
/// GLOBAL CONSTANTS /////////////////////////////////////////////////////////
2008-10-28 22:31:26 +00:00
/** Bitmask, indicates :name type parameters are supported by db backend. */
2008-06-15 11:35:25 +00:00
define ( 'SQL_PARAMS_NAMED' , 1 );
2008-10-28 22:31:26 +00:00
/** Bitmask, indicates ? type parameters are supported by db backend. */
2008-06-15 11:35:25 +00:00
define ( 'SQL_PARAMS_QM' , 2 );
2008-10-28 22:31:26 +00:00
/** Bitmask, indicates $1, $2, ... type parameters are supported by db backend. */
2008-06-15 11:35:25 +00:00
define ( 'SQL_PARAMS_DOLLAR' , 4 );
2008-10-28 22:31:26 +00:00
/** Normal select query, reading only */
define ( 'SQL_QUERY_SELECT' , 1 );
/** Insert select query, writing */
define ( 'SQL_QUERY_INSERT' , 2 );
/** Update select query, writing */
define ( 'SQL_QUERY_UPDATE' , 3 );
/** Query changing db structure, writing */
define ( 'SQL_QUERY_STRUCTURE' , 4 );
/** Auxiliary query done by driver, setting connection config, getting table info, etc. */
define ( 'SQL_QUERY_AUX' , 5 );
2008-05-15 21:40:00 +00:00
/**
* Abstract class representing moodle database interface .
*/
abstract class moodle_database {
2009-06-12 08:27:19 +00:00
/** @var database_manager db manager which allows db structure modifications */
2008-05-15 21:40:00 +00:00
protected $database_manager ;
2009-06-12 08:27:19 +00:00
/** @var array cache of column info */
2008-05-25 09:31:38 +00:00
protected $columns = array (); // I wish we had a shared memory cache for this :-(
2009-06-12 08:27:19 +00:00
/** @var array cache of table info */
2009-01-12 18:10:50 +00:00
protected $tables = null ;
2008-05-25 09:31:38 +00:00
2008-05-15 21:40:00 +00:00
// db connection options
2009-06-12 08:27:19 +00:00
/** @var string db host name */
2008-05-15 21:40:00 +00:00
protected $dbhost ;
2009-06-12 08:27:19 +00:00
/** @var string db host user */
2008-05-15 21:40:00 +00:00
protected $dbuser ;
2009-06-12 08:27:19 +00:00
/** @var string db host password */
2008-05-15 21:40:00 +00:00
protected $dbpass ;
2009-06-12 08:27:19 +00:00
/** @var string db name */
2008-05-15 21:40:00 +00:00
protected $dbname ;
2009-06-12 08:27:19 +00:00
/** @var string table prefix */
2008-05-15 21:40:00 +00:00
protected $prefix ;
2009-06-12 08:27:19 +00:00
/** @var array Database or driver specific options, such as sockets or TCPIP db connections */
2009-02-07 10:20:33 +00:00
protected $dboptions ;
2008-05-15 21:40:00 +00:00
2009-06-12 08:27:19 +00:00
/** @var bool true means non-moodle external database used.*/
2009-02-07 10:20:33 +00:00
protected $external ;
2008-05-19 18:02:33 +00:00
2009-06-12 08:27:19 +00:00
/** @var int The database reads (performance counter).*/
2008-06-16 21:01:54 +00:00
protected $reads = 0 ;
2009-06-12 08:27:19 +00:00
/** @var int The database writes (performance counter).*/
2008-06-16 21:01:54 +00:00
protected $writes = 0 ;
2009-06-12 08:27:19 +00:00
/** @var int Debug level */
2008-11-21 20:09:13 +00:00
protected $debug = 0 ;
2009-06-12 08:27:19 +00:00
/** @var string last query sql */
2008-11-04 23:07:14 +00:00
protected $last_sql ;
2009-06-12 08:27:19 +00:00
/** @var array last query parameters */
2008-11-04 23:07:14 +00:00
protected $last_params ;
2009-06-12 08:27:19 +00:00
/** @var int last query type */
2008-11-04 23:07:14 +00:00
protected $last_type ;
2009-06-12 08:27:19 +00:00
/** @var string last extra info */
2008-11-04 23:07:14 +00:00
protected $last_extrainfo ;
2009-06-13 10:16:29 +00:00
/** @var float last time in seconds with milisocond precision */
protected $last_time ;
/** @var bool flag indicating loggin of query in progress, prevents infinite loops */
private $loggingquery = false ;
2008-05-15 21:40:00 +00:00
2009-06-12 08:27:19 +00:00
/** @var bool true if db used for db sessions */
2009-01-17 14:31:29 +00:00
protected $used_for_db_sessions = false ;
2009-01-16 17:27:36 +00:00
2009-06-12 08:27:19 +00:00
/** @var bool Flag indicating transaction in progress */
2009-06-12 07:55:44 +00:00
protected $intransaction = false ;
2009-06-12 08:27:19 +00:00
/** @var int internal temporary variable */
2008-11-06 18:36:50 +00:00
private $fix_sql_params_i ;
2008-05-15 21:40:00 +00:00
/**
2008-05-19 18:02:33 +00:00
* Contructor - instantiates the database , specifying if it ' s external ( connect to other systems ) or no ( Moodle DB )
* note this has effect to decide if prefix checks must be performed or no
* @ param bool true means external database used
2008-05-15 21:40:00 +00:00
*/
2008-05-19 18:02:33 +00:00
public function __construct ( $external = false ) {
$this -> external = $external ;
}
2008-05-15 21:40:00 +00:00
2008-10-28 12:02:13 +00:00
/**
* Destructor - cleans up and flushes everything needed .
*/
2009-05-26 14:46:01 +00:00
public function __destruct () {
2008-10-28 12:02:13 +00:00
$this -> dispose ();
}
2008-05-15 21:40:00 +00:00
/**
2008-05-19 18:02:33 +00:00
* Detects if all needed PHP stuff installed .
* Note : can be used before connect ()
* @ return mixed true if ok , string if something
2008-05-15 21:40:00 +00:00
*/
2008-05-19 18:02:33 +00:00
public abstract function driver_installed ();
2008-05-15 21:40:00 +00:00
/**
* Returns database table prefix
2008-05-19 18:02:33 +00:00
* Note : can be used before connect ()
2008-05-15 21:40:00 +00:00
* @ return string database table prefix
*/
public function get_prefix () {
return $this -> prefix ;
}
2008-07-24 12:21:19 +00:00
/**
2008-09-02 20:32:03 +00:00
* Loads and returns a database instance with the specified type and library .
2008-07-24 12:21:19 +00:00
* @ param string $type database type of the driver ( mysql , postgres7 , mssql , etc )
2008-09-02 20:32:03 +00:00
* @ param string $library database library of the driver ( adodb , pdo , native , etc )
* @ return moodle_database driver object or null if error
2008-07-24 12:21:19 +00:00
*/
2008-09-02 20:32:03 +00:00
public static function get_driver_instance ( $type , $library ) {
2008-07-24 12:21:19 +00:00
global $CFG ;
2008-09-02 20:32:03 +00:00
$classname = $type . '_' . $library . '_moodle_database' ;
$libfile = " $CFG->libdir /dml/ $classname .php " ;
if ( ! file_exists ( $libfile )) {
return null ;
}
require_once ( $libfile );
return new $classname ();
2008-07-24 12:21:19 +00:00
}
2008-05-15 21:40:00 +00:00
/**
2008-05-19 18:02:33 +00:00
* Returns database family type - describes SQL dialect
* Note : can be used before connect ()
* @ return string db family name ( mysql , postgres , mssql , oracle , etc . )
*/
public abstract function get_dbfamily ();
/**
* Returns more specific database driver type
* Note : can be used before connect ()
2008-05-15 21:40:00 +00:00
* @ return string db type mysql , mysqli , postgres7
*/
protected abstract function get_dbtype ();
2008-06-22 22:53:40 +00:00
/**
* Returns general database library name
* Note : can be used before connect ()
* @ return string db type adodb , pdo , native
*/
protected abstract function get_dblibrary ();
2008-05-15 21:40:00 +00:00
/**
2008-05-19 18:02:33 +00:00
* Returns localised database type name
* Note : can be used before connect ()
* @ return string
2008-05-15 21:40:00 +00:00
*/
2008-05-19 18:02:33 +00:00
public abstract function get_name ();
/**
2009-02-07 10:20:33 +00:00
* Returns localised database configuration help .
2008-05-19 18:02:33 +00:00
* Note : can be used before connect ()
* @ return string
*/
2009-02-07 10:20:33 +00:00
public abstract function get_configuration_help ();
2008-05-15 21:40:00 +00:00
/**
2009-02-07 10:20:33 +00:00
* Returns localised database description
2008-05-19 18:02:33 +00:00
* Note : can be used before connect ()
* @ return string
*/
2009-02-07 10:20:33 +00:00
public abstract function get_configuration_hints ();
2008-06-22 22:53:40 +00:00
2009-02-07 10:20:33 +00:00
/**
* Returns db related part of config . php
* @ return object
*/
public function export_dbconfig () {
2008-06-22 22:53:40 +00:00
$cfg = new stdClass ();
$cfg -> dbtype = $this -> get_dbtype ();
$cfg -> dblibrary = $this -> get_dblibrary ();
$cfg -> dbhost = $this -> dbhost ;
$cfg -> dbname = $this -> dbname ;
$cfg -> dbuser = $this -> dbuser ;
$cfg -> dbpass = $this -> dbpass ;
$cfg -> prefix = $this -> prefix ;
if ( $this -> dboptions ) {
$cfg -> dboptions = $this -> dboptions ;
}
return $cfg ;
}
2008-05-19 18:02:33 +00:00
/**
* Connect to db
* Must be called before other methods .
* @ param string $dbhost
* @ param string $dbuser
* @ param string $dbpass
* @ param string $dbname
* @ param mixed $prefix string means moodle db prefix , false used for external databases where prefix not used
* @ param array $dboptions driver specific options
2008-11-22 01:16:52 +00:00
* @ return bool true
* @ throws dml_connection_exception if error
2008-05-15 21:40:00 +00:00
*/
2008-10-27 22:21:34 +00:00
public abstract function connect ( $dbhost , $dbuser , $dbpass , $dbname , $prefix , array $dboptions = null );
2008-05-19 18:02:33 +00:00
2008-06-22 22:53:40 +00:00
/**
* Store various database settings
* @ param string $dbhost
* @ param string $dbuser
* @ param string $dbpass
* @ param string $dbname
* @ param mixed $prefix string means moodle db prefix , false used for external databases where prefix not used
* @ param array $dboptions driver specific options
* @ return void
*/
2008-10-27 22:21:34 +00:00
protected function store_settings ( $dbhost , $dbuser , $dbpass , $dbname , $prefix , array $dboptions = null ) {
2008-06-22 22:53:40 +00:00
$this -> dbhost = $dbhost ;
$this -> dbuser = $dbuser ;
$this -> dbpass = $dbpass ;
$this -> dbname = $dbname ;
$this -> prefix = $prefix ;
$this -> dboptions = ( array ) $dboptions ;
}
2008-06-09 20:22:11 +00:00
/**
* Attempt to create the database
* @ param string $dbhost
* @ param string $dbuser
* @ param string $dbpass
* @ param string $dbname
*
* @ return bool success
*/
2009-02-07 10:20:33 +00:00
public function create_database ( $dbhost , $dbuser , $dbpass , $dbname , array $dboptions = null ) {
2008-06-09 20:22:11 +00:00
return false ;
}
2008-05-25 19:56:34 +00:00
/**
* Close database connection and release all resources
* and memory ( especially circular memory references ) .
* Do NOT use connect () again , create a new instance if needed .
*/
public function dispose () {
2009-06-12 07:55:44 +00:00
if ( $this -> intransaction ) {
2009-06-13 15:59:55 +00:00
// unfortunately we can not access global $CFG any more and can not print debug
error_log ( 'Active database transaction detected when disposing database!' );
2009-06-12 07:55:44 +00:00
}
2009-01-16 17:27:36 +00:00
if ( $this -> used_for_db_sessions ) {
// this is needed because we need to save session to db before closing it
2009-01-17 15:25:08 +00:00
session_get_instance () -> write_close ();
2009-01-17 14:31:29 +00:00
$this -> used_for_db_sessions = false ;
2009-01-16 17:27:36 +00:00
}
2008-05-25 19:56:34 +00:00
if ( $this -> database_manager ) {
$this -> database_manager -> dispose ();
$this -> database_manager = null ;
}
2008-10-28 12:02:13 +00:00
$this -> columns = array ();
2009-01-12 18:10:50 +00:00
$this -> tables = null ;
2008-05-25 19:56:34 +00:00
}
2008-10-28 22:31:26 +00:00
/**
* Called before each db query .
* @ param string $sql
* @ param array array of parameters
* @ param int $type type of query
2008-10-29 23:55:16 +00:00
* @ param mixed $extrainfo driver specific extra information
2008-10-28 22:31:26 +00:00
* @ return void
*/
2008-10-29 23:55:16 +00:00
protected function query_start ( $sql , array $params = null , $type , $extrainfo = null ) {
2009-06-13 10:16:29 +00:00
if ( $this -> loggingquery ) {
return ;
}
2008-11-04 23:07:14 +00:00
$this -> last_sql = $sql ;
$this -> last_params = $params ;
$this -> last_type = $type ;
$this -> last_extrainfo = $extrainfo ;
2009-06-13 10:16:29 +00:00
$this -> last_time = microtime ( true );
2008-11-04 23:07:14 +00:00
2008-10-29 23:55:16 +00:00
switch ( $type ) {
case SQL_QUERY_SELECT :
case SQL_QUERY_AUX :
$this -> reads ++ ;
break ;
case SQL_QUERY_INSERT :
case SQL_QUERY_UPDATE :
case SQL_QUERY_STRUCTURE :
$this -> writes ++ ;
}
2008-11-04 23:07:14 +00:00
$this -> print_debug ( $sql , $params );
2008-10-28 22:31:26 +00:00
}
/**
* Called immediately after each db query .
* @ param mixed db specific result
* @ return void
*/
2008-10-29 23:55:16 +00:00
protected function query_end ( $result ) {
2009-06-13 10:16:29 +00:00
if ( $this -> loggingquery ) {
return ;
}
2009-06-13 15:59:55 +00:00
if ( $result !== false ) {
$this -> query_log ();
// free memory
$this -> last_sql = null ;
$this -> last_params = null ;
return ;
}
// remember current info, log queries may alter it
2009-06-13 10:16:29 +00:00
$type = $this -> last_type ;
$sql = $this -> last_sql ;
$params = $this -> last_params ;
$time = microtime ( true ) - $this -> last_time ;
2009-06-13 15:59:55 +00:00
$error = $this -> get_last_error ();
2009-06-13 10:16:29 +00:00
2009-06-13 15:59:55 +00:00
$this -> query_log ( $error );
2009-06-13 10:16:29 +00:00
2009-06-13 15:59:55 +00:00
switch ( $type ) {
2008-11-04 23:07:14 +00:00
case SQL_QUERY_SELECT :
case SQL_QUERY_AUX :
2009-06-13 10:16:29 +00:00
throw new dml_read_exception ( $error , $sql , $params );
2008-11-04 23:07:14 +00:00
case SQL_QUERY_INSERT :
case SQL_QUERY_UPDATE :
2009-06-13 10:16:29 +00:00
throw new dml_write_exception ( $error , $sql , $params );
2008-11-05 10:45:45 +00:00
case SQL_QUERY_STRUCTURE :
$this -> get_manager (); // includes ddl exceptions classes ;-)
2009-06-13 10:16:29 +00:00
throw new ddl_change_structure_exception ( $error , $sql );
}
}
/**
2009-06-13 15:59:55 +00:00
* Log ast database query if requested
2009-06-13 10:16:29 +00:00
* @ param mixed string error or false if not error
* @ return void
*/
2009-06-13 15:59:55 +00:00
public function query_log ( $error = false ) {
2009-06-13 10:16:29 +00:00
$logall = ! empty ( $this -> dboptions [ 'logall' ]);
$logslow = ! empty ( $this -> dboptions [ 'logslow' ]) ? $this -> dboptions [ 'logslow' ] : false ;
$logerrors = ! empty ( $this -> dboptions [ 'logerrors' ]);
$iserror = ( $error !== false );
2009-06-13 15:59:55 +00:00
$time = microtime ( true ) - $this -> last_time ;
2009-06-13 10:16:29 +00:00
if ( $logall or ( $logslow and ( $logslow < ( $time + 0.00001 ))) or ( $iserror and $logerrors )) {
$this -> loggingquery = true ;
try {
2009-06-13 15:59:55 +00:00
$backtrace = debug_backtrace ();
if ( $backtrace ) {
//remove query_log()
array_shift ( $backtrace );
}
if ( $backtrace ) {
//remove query_end()
array_shift ( $backtrace );
}
$log = new object ();
$log -> qtype = $this -> last_type ;
$log -> sqltext = $this -> last_sql ;
$log -> sqlparams = var_export (( array ) $this -> last_params , true );
$log -> error = ( int ) $iserror ;
$log -> info = $iserror ? $error : null ;
2009-06-26 09:06:16 +00:00
$log -> backtrace = format_backtrace ( $backtrace , true );
2009-06-13 15:59:55 +00:00
$log -> exectime = $time ;
$log -> timelogged = time ();
$this -> insert_record ( 'log_queries' , $log );
2009-06-13 10:16:29 +00:00
} catch ( Exception $ignored ) {
}
$this -> loggingquery = false ;
2008-11-04 23:07:14 +00:00
}
2008-10-28 22:31:26 +00:00
}
2008-05-19 18:02:33 +00:00
/**
* Returns database server info array
* @ return array
*/
public abstract function get_server_info ();
/**
* Returns supported query parameter types
* @ return bitmask
*/
protected abstract function allowed_param_types ();
2008-05-15 21:40:00 +00:00
/**
* Returns last error reported by database engine .
*/
public abstract function get_last_error ();
2008-10-18 22:35:42 +00:00
/**
* Print sql debug info
* @ param string $sql query which caused problems
* @ param array $params optional query parameters
* @ param mixed $obj optional library specific object
*/
protected function print_debug ( $sql , array $params = null , $obj = null ) {
if ( ! $this -> get_debug ()) {
return ;
}
2009-06-13 09:16:30 +00:00
if ( CLI_SCRIPT ) {
echo " -------------------------------- \n " ;
echo $sql . " \n " ;
if ( ! is_null ( $params )) {
echo " [ " . var_export ( $params , true ) . " ] \n " ;
}
echo " -------------------------------- \n " ;
} else {
echo " <hr /> \n " ;
echo s ( $sql ) . " \n " ;
if ( ! is_null ( $params )) {
echo " [ " . s ( var_export ( $params , true )) . " ] \n " ;
}
echo " <hr /> \n " ;
2008-10-18 22:35:42 +00:00
}
2008-05-15 21:40:00 +00:00
}
2008-11-22 19:32:16 +00:00
/**
* Returns SQL WHERE conditions .
*
* @ param array conditions - must not contain numeric indexes
* @ return array sql part and params
*/
protected function where_clause ( array $conditions = null ) {
$allowed_types = $this -> allowed_param_types ();
if ( empty ( $conditions )) {
return array ( '' , array ());
}
$where = array ();
$params = array ();
foreach ( $conditions as $key => $value ) {
if ( is_int ( $key )) {
throw new dml_exception ( 'invalidnumkey' );
}
if ( is_null ( $value )) {
$where [] = " $key IS NULL " ;
} else {
if ( $allowed_types & SQL_PARAMS_NAMED ) {
$where [] = " $key = : $key " ;
$params [ $key ] = $value ;
} else {
$where [] = " $key = ? " ;
$params [] = $value ;
}
}
}
$where = implode ( " AND " , $where );
return array ( $where , $params );
}
2008-12-15 02:13:11 +00:00
/**
* Returns SQL WHERE conditions for the ... _list methods .
*
* @ param string $field the name of a field .
* @ param array $values the values field might take .
* @ return array sql part and params
*/
protected function where_clause_list ( $field , array $values ) {
$params = array ();
$select = array ();
$values = ( array ) $values ;
foreach ( $values as $value ) {
if ( is_bool ( $value )) {
$value = ( int ) $value ;
}
if ( is_null ( $value )) {
$select [] = " $field IS NULL " ;
} else {
$select [] = " $field = ? " ;
$params [] = $value ;
}
}
$select = implode ( " OR " , $select );
return array ( $select , $params );
}
2008-05-15 21:40:00 +00:00
/**
* Constructs IN () or = sql fragment
* @ param mixed $items single or array of values
2008-07-04 12:05:04 +00:00
* @ param int $type bound param type SQL_PARAMS_QM or SQL_PARAMS_NAMED
2008-05-15 21:40:00 +00:00
* @ param string named param placeholder start
2008-05-24 20:42:40 +00:00
* @ param bool true means equal , false not equal
2008-05-15 21:40:00 +00:00
* @ return array - $sql and $params
*/
2008-05-24 20:42:40 +00:00
public function get_in_or_equal ( $items , $type = SQL_PARAMS_QM , $start = 'param0000' , $equal = true ) {
2008-05-15 21:40:00 +00:00
if ( $type == SQL_PARAMS_QM ) {
if ( ! is_array ( $items ) or count ( $items ) == 1 ) {
2008-05-24 20:42:40 +00:00
$sql = $equal ? '= ?' : '<> ?' ;
2008-05-24 13:05:34 +00:00
$items = ( array ) $items ;
$params = array_values ( $items );
2008-05-15 21:40:00 +00:00
} else {
2008-05-24 20:42:40 +00:00
if ( $equal ) {
$sql = 'IN (' . implode ( ',' , array_fill ( 0 , count ( $items ), '?' )) . ')' ;
} else {
$sql = 'NOT IN (' . implode ( ',' , array_fill ( 0 , count ( $items ), '?' )) . ')' ;
}
2008-05-15 21:40:00 +00:00
$params = array_values ( $items );
}
} else if ( $type == SQL_PARAMS_NAMED ) {
2008-05-24 13:05:34 +00:00
if ( ! is_array ( $items )){
2008-05-24 20:42:40 +00:00
$sql = $equal ? " = : $start " : " <> : $start " ;
2008-05-15 21:40:00 +00:00
$params = array ( $start => $items );
2008-05-24 13:05:34 +00:00
} else if ( count ( $items ) == 1 ) {
2008-05-24 20:42:40 +00:00
$sql = $equal ? " = : $start " : " <> : $start " ;
2008-05-24 13:05:34 +00:00
$item = reset ( $items );
$params = array ( $start => $item );
2008-05-15 21:40:00 +00:00
} else {
$params = array ();
$sql = array ();
foreach ( $items as $item ) {
$params [ $start ] = $item ;
2008-05-24 20:42:40 +00:00
$sql [] = ':' . $start ++ ;
}
if ( $equal ) {
$sql = 'IN (' . implode ( ',' , $sql ) . ')' ;
} else {
$sql = 'NOT IN (' . implode ( ',' , $sql ) . ')' ;
2008-05-15 21:40:00 +00:00
}
}
} else {
2008-10-25 17:43:45 +00:00
throw new dml_exception ( 'typenotimplement' );
2008-05-15 21:40:00 +00:00
}
return array ( $sql , $params );
}
2008-06-07 14:41:01 +00:00
/**
* Converts short table name { tablename } to real table name
* @ param string sql
* @ return string sql
*/
protected function fix_table_names ( $sql ) {
return preg_replace ( '/\{([a-z][a-z0-9_]*)\}/' , $this -> prefix . '$1' , $sql );
}
2008-11-06 18:36:50 +00:00
/** Internal function */
private function _fix_sql_params_dollar_callback ( $match ) {
$this -> fix_sql_params_i ++ ;
return " \$ " . $this -> fix_sql_params_i ;
}
2008-05-15 21:40:00 +00:00
/**
* Normalizes sql query parameters and verifies parameters .
* @ param string $sql query or part of it
* @ param array $params query parameters
*/
public function fix_sql_params ( $sql , array $params = null ) {
$params = ( array ) $params ; // mke null array if needed
$allowed_types = $this -> allowed_param_types ();
// convert table names
2008-06-07 14:41:01 +00:00
$sql = $this -> fix_table_names ( $sql );
2008-05-15 21:40:00 +00:00
2008-05-21 14:59:33 +00:00
// NICOLAS C: Fixed regexp for negative backwards lookahead of double colons. Thanks for Sam Marshall's help
$named_count = preg_match_all ( '/(?<!:):[a-z][a-z0-9_]*/' , $sql , $named_matches ); // :: used in pgsql casts
$dollar_count = preg_match_all ( '/\$[1-9][0-9]*/' , $sql , $dollar_matches );
2008-05-15 21:40:00 +00:00
$q_count = substr_count ( $sql , '?' );
$count = 0 ;
if ( $named_count ) {
$type = SQL_PARAMS_NAMED ;
$count = $named_count ;
}
2008-05-21 14:59:33 +00:00
if ( $dollar_count ) {
2008-05-15 21:40:00 +00:00
if ( $count ) {
2008-10-25 17:43:45 +00:00
throw new dml_exception ( 'mixedtypesqlparam' );
2008-05-15 21:40:00 +00:00
}
2008-05-21 14:59:33 +00:00
$type = SQL_PARAMS_DOLLAR ;
$count = $dollar_count ;
2008-05-15 21:40:00 +00:00
}
if ( $q_count ) {
if ( $count ) {
2008-10-25 17:43:45 +00:00
throw new dml_exception ( 'mixedtypesqlparam' );
2008-05-15 21:40:00 +00:00
}
$type = SQL_PARAMS_QM ;
$count = $q_count ;
}
if ( ! $count ) {
// ignore params
if ( $allowed_types & SQL_PARAMS_NAMED ) {
return array ( $sql , array (), SQL_PARAMS_NAMED );
} else if ( $allowed_types & SQL_PARAMS_QM ) {
return array ( $sql , array (), SQL_PARAMS_QM );
} else {
2008-05-21 14:59:33 +00:00
return array ( $sql , array (), SQL_PARAMS_DOLLAR );
2008-05-15 21:40:00 +00:00
}
}
if ( $count > count ( $params )) {
2008-10-29 06:54:32 +00:00
$a = new stdClass ;
$a -> expected = $count ;
$a -> actual = count ( $params );
throw new dml_exception ( 'invalidqueryparam' , $a );
2008-05-15 21:40:00 +00:00
}
2008-11-19 23:20:46 +00:00
$target_type = $allowed_types ;
2008-05-15 21:40:00 +00:00
if ( $type & $allowed_types ) { // bitwise AND
if ( $count == count ( $params )) {
if ( $type == SQL_PARAMS_QM ) {
return array ( $sql , array_values ( $params ), SQL_PARAMS_QM ); // 0-based array required
} else {
2008-05-21 14:59:33 +00:00
//better do the validation of names below
2008-05-15 21:40:00 +00:00
}
}
// needs some fixing or validation - there might be more params than needed
$target_type = $type ;
}
if ( $type == SQL_PARAMS_NAMED ) {
$finalparams = array ();
foreach ( $named_matches [ 0 ] as $key ) {
$key = trim ( $key , ':' );
if ( ! array_key_exists ( $key , $params )) {
2008-11-18 04:22:57 +00:00
throw new dml_exception ( 'missingkeyinsql' , $key , '' );
2008-05-15 21:40:00 +00:00
}
$finalparams [ $key ] = $params [ $key ];
}
if ( $count != count ( $finalparams )) {
2008-10-25 17:43:45 +00:00
throw new dml_exception ( 'duplicateparaminsql' );
2008-05-15 21:40:00 +00:00
}
if ( $target_type & SQL_PARAMS_QM ) {
2008-05-21 14:59:33 +00:00
$sql = preg_replace ( '/(?<!:):[a-z][a-z0-9_]*/' , '?' , $sql );
2008-05-15 21:40:00 +00:00
return array ( $sql , array_values ( $finalparams ), SQL_PARAMS_QM ); // 0-based required
} else if ( $target_type & SQL_PARAMS_NAMED ) {
return array ( $sql , $finalparams , SQL_PARAMS_NAMED );
2008-05-21 14:59:33 +00:00
} else { // $type & SQL_PARAMS_DOLLAR
2008-11-06 18:36:50 +00:00
//lambda-style functions eat memory - we use globals instead :-(
$this -> fix_sql_params_i = 0 ;
$sql = preg_replace_callback ( '/(?<!:):[a-z][a-z0-9_]*/' , array ( $this , '_fix_sql_params_dollar_callback' ), $sql );
2008-10-26 12:45:05 +00:00
return array ( $sql , array_values ( $finalparams ), SQL_PARAMS_DOLLAR ); // 0-based required
2008-05-15 21:40:00 +00:00
}
2008-05-21 14:59:33 +00:00
} else if ( $type == SQL_PARAMS_DOLLAR ) {
2008-10-26 12:45:05 +00:00
if ( $target_type & SQL_PARAMS_DOLLAR ) {
return array ( $sql , array_values ( $params ), SQL_PARAMS_DOLLAR ); // 0-based required
2008-10-27 12:00:04 +00:00
} else if ( $target_type & SQL_PARAMS_QM ) {
$sql = preg_replace ( '/\$[0-9]+/' , '?' , $sql );
return array ( $sql , array_values ( $params ), SQL_PARAMS_QM ); // 0-based required
} else { //$target_type & SQL_PARAMS_NAMED
$sql = preg_replace ( '/\$([0-9]+)/' , ':param\\1' , $sql );
$finalparams = array ();
foreach ( $params as $key => $param ) {
$key ++ ;
$finalparams [ 'param' . $key ] = $param ;
}
return array ( $sql , $finalparams , SQL_PARAMS_NAMED );
2008-10-26 12:45:05 +00:00
}
2008-05-15 21:40:00 +00:00
} else { // $type == SQL_PARAMS_QM
if ( count ( $params ) != $count ) {
$params = array_slice ( $params , 0 , $count );
}
if ( $target_type & SQL_PARAMS_QM ) {
return array ( $sql , array_values ( $params ), SQL_PARAMS_QM ); // 0-based required
} else if ( $target_type & SQL_PARAMS_NAMED ) {
$finalparams = array ();
2008-12-04 11:52:53 +00:00
$pname = 'param0' ;
2008-05-15 21:40:00 +00:00
$parts = explode ( '?' , $sql );
$sql = array_shift ( $parts );
foreach ( $parts as $part ) {
$param = array_shift ( $params );
$pname ++ ;
$sql .= ':' . $pname . $part ;
$finalparams [ $pname ] = $param ;
}
return array ( $sql , $finalparams , SQL_PARAMS_NAMED );
2008-05-21 14:59:33 +00:00
} else { // $type & SQL_PARAMS_DOLLAR
2008-11-06 18:36:50 +00:00
//lambda-style functions eat memory - we use globals instead :-(
$this -> fix_sql_params_i = 0 ;
$sql = preg_replace_callback ( '/\?/' , array ( $this , '_fix_sql_params_dollar_callback' ), $sql );
2008-10-26 12:45:05 +00:00
return array ( $sql , array_values ( $params ), SQL_PARAMS_DOLLAR ); // 0-based required
2008-05-15 21:40:00 +00:00
}
}
}
/**
2008-05-25 22:22:57 +00:00
* Return tables in database WITHOUT current prefix
* @ return array of table names in lowercase and without prefix
2008-05-15 21:40:00 +00:00
*/
2009-01-12 18:10:50 +00:00
public abstract function get_tables ( $usecache = true );
2008-05-15 21:40:00 +00:00
/**
2008-05-25 22:25:17 +00:00
* Return table indexes - everything lowercased
2008-05-15 21:40:00 +00:00
* @ return array of arrays
*/
public abstract function get_indexes ( $table );
/**
* Returns datailed information about columns in table . This information is cached internally .
* @ param string $table name
2008-05-25 09:31:38 +00:00
* @ param bool $usecache
2008-05-15 21:40:00 +00:00
* @ return array array of database_column_info objects indexed with column names
*/
2008-05-25 09:31:38 +00:00
public abstract function get_columns ( $table , $usecache = true );
2008-05-15 21:40:00 +00:00
/**
* Reset internal column details cache
* @ param string $table - empty means all , or one if name of table given
* @ return void
*/
2009-01-12 18:10:50 +00:00
public function reset_caches () {
2008-06-12 15:18:11 +00:00
$this -> columns = array ();
2009-01-12 18:10:50 +00:00
$this -> tables = null ;
2008-05-25 09:31:38 +00:00
}
2008-05-15 21:40:00 +00:00
/**
* Returns sql generator used for db manipulation .
* Used mostly in upgrade . php scripts .
* @ return object database_manager instance
*/
public function get_manager () {
global $CFG ;
if ( ! $this -> database_manager ) {
2008-08-30 18:48:39 +00:00
require_once ( $CFG -> libdir . '/ddllib.php' );
2008-05-15 21:40:00 +00:00
$classname = $this -> get_dbfamily () . '_sql_generator' ;
require_once ( " $CFG->libdir /ddl/ $classname .php " );
$generator = new $classname ( $this );
$this -> database_manager = new database_manager ( $this , $generator );
}
return $this -> database_manager ;
}
/**
* Attempt to change db encoding toUTF - 8 if poossible
* @ return bool success
*/
public function change_db_encoding () {
return false ;
}
/**
* Is db in unicode mode ?
* @ return bool
*/
public function setup_is_unicodedb () {
return true ;
}
/**
* Enable / disable very detailed debugging
* @ param bool $state
*/
2008-11-21 20:09:13 +00:00
public function set_debug ( $state ) {
$this -> debug = $state ;
}
2008-05-15 21:40:00 +00:00
/**
* Returns debug status
* @ return bool $state
*/
2008-11-21 20:09:13 +00:00
public function get_debug () {
return $this -> debug ;
}
2008-05-15 21:40:00 +00:00
/**
* Enable / disable detailed sql logging
* @ param bool $state
*/
2008-11-21 20:09:13 +00:00
public function set_logging ( $state ) {
2009-06-13 09:16:30 +00:00
// adodb sql logging shares one table without prefix per db - this is no longer acceptable :-(
2008-11-21 20:09:13 +00:00
// we must create one table shared by all drivers
}
2008-05-15 21:40:00 +00:00
/**
* Do NOT use in code , to be used by database_manager only !
* @ param string $sql query
2008-11-21 20:09:13 +00:00
* @ return bool true
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public abstract function change_database_structure ( $sql );
/**
* Execute general sql query . Should be used only when no other method suitable .
* Do NOT use this to make changes in db structure , use database_manager :: execute_sql () instead !
* @ param string $sql query
* @ param array $params query parameters
2008-11-21 20:09:13 +00:00
* @ return bool true
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public abstract function execute ( $sql , array $params = null );
/**
2008-07-25 18:41:35 +00:00
* Get a number of records as a moodle_recordset where all the given conditions met .
2008-05-15 21:40:00 +00:00
*
* Selects records from the table $table .
*
* If specified , only records meeting $conditions .
*
* If specified , the results will be sorted as specified by $sort . This
* is added to the SQL as " ORDER BY $sort " . Example values of $sort
* mightbe " time ASC " or " time DESC " .
*
* If $fields is specified , only those fields are returned .
*
* Since this method is a little less readable , use of it should be restricted to
* code where it ' s possible there might be large datasets being returned . For known
* small datasets use get_records - it leads to simpler code .
*
* If you only want some of the records , specify $limitfrom and $limitnum .
* The query will skip the first $limitfrom records ( according to the sort
* order ) and then return the next $limitnum records . If either of $limitfrom
* or $limitnum is specified , both must be present .
*
* The return value is a moodle_recordset
* if the query succeeds . If an error occurrs , false is returned .
*
* @ param string $table the table to query .
* @ param array $conditions optional array $fieldname => requestedvalue with AND in between
* @ param string $sort an order to sort the results in ( optional , a valid SQL ORDER BY parameter ) .
* @ param string $fields a comma separated list of fields to return ( optional , by default all fields are returned ) .
* @ param int $limitfrom return a subset of records , starting at this point ( optional , required if $limitnum is set ) .
* @ param int $limitnum return a subset comprising this many records ( optional , required if $limitfrom is set ) .
2008-11-21 20:09:13 +00:00
* @ return object moodle_recordset instance
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_recordset ( $table , array $conditions = null , $sort = '' , $fields = '*' , $limitfrom = 0 , $limitnum = 0 ) {
list ( $select , $params ) = $this -> where_clause ( $conditions );
return $this -> get_recordset_select ( $table , $select , $params , $sort , $fields , $limitfrom , $limitnum );
}
/**
2008-07-25 18:41:35 +00:00
* Get a number of records as a moodle_recordset where one field match one list of values .
2008-05-15 21:40:00 +00:00
*
* Only records where $field takes one of the values $values are returned .
2008-06-18 14:53:01 +00:00
* $values must be an array of values .
2008-05-15 21:40:00 +00:00
*
* Other arguments and the return type as for @ see function get_recordset .
*
* @ param string $table the table to query .
* @ param string $field a field to check ( optional ) .
* @ param array $values array of values the field must have
* @ param string $sort an order to sort the results in ( optional , a valid SQL ORDER BY parameter ) .
* @ param string $fields a comma separated list of fields to return ( optional , by default all fields are returned ) .
* @ param int $limitfrom return a subset of records , starting at this point ( optional , required if $limitnum is set ) .
* @ param int $limitnum return a subset comprising this many records ( optional , required if $limitfrom is set ) .
2008-11-21 20:09:13 +00:00
* @ return object moodle_recordset instance
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_recordset_list ( $table , $field , array $values , $sort = '' , $fields = '*' , $limitfrom = 0 , $limitnum = 0 ) {
2008-12-15 02:13:11 +00:00
list ( $select , $params ) = $this -> where_clause_list ( $field , $values );
2008-12-15 21:41:09 +00:00
if ( empty ( $select )) {
$select = '? = ?' ; /// Fake condition, won't return rows ever. MDL-17645
$params = array ( 1 , 2 );
}
2008-06-14 00:00:26 +00:00
return $this -> get_recordset_select ( $table , $select , $params , $sort , $fields , $limitfrom , $limitnum );
2008-05-15 21:40:00 +00:00
}
/**
2008-07-25 18:41:35 +00:00
* Get a number of records as a moodle_recordset which match a particular WHERE clause .
2008-05-15 21:40:00 +00:00
*
* If given , $select is used as the SELECT parameter in the SQL query ,
* otherwise all records from the table are returned .
*
* Other arguments and the return type as for @ see function get_recordset .
*
* @ param string $table the table to query .
* @ param string $select A fragment of SQL to be used in a where clause in the SQL call .
* @ param array $params array of sql parameters
* @ param string $sort an order to sort the results in ( optional , a valid SQL ORDER BY parameter ) .
* @ param string $fields a comma separated list of fields to return ( optional , by default all fields are returned ) .
* @ param int $limitfrom return a subset of records , starting at this point ( optional , required if $limitnum is set ) .
* @ param int $limitnum return a subset comprising this many records ( optional , required if $limitfrom is set ) .
2008-11-21 20:09:13 +00:00
* @ return object moodle_recordset instance
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_recordset_select ( $table , $select , array $params = null , $sort = '' , $fields = '*' , $limitfrom = 0 , $limitnum = 0 ) {
2008-12-05 00:10:27 +00:00
$sql = " SELECT $fields FROM { " . $table . " } " ;
2008-05-15 21:40:00 +00:00
if ( $select ) {
2008-12-05 00:10:27 +00:00
$sql .= " WHERE $select " ;
2008-05-15 21:40:00 +00:00
}
if ( $sort ) {
2008-12-05 00:10:27 +00:00
$sql .= " ORDER BY $sort " ;
2008-05-15 21:40:00 +00:00
}
2008-12-05 00:10:27 +00:00
return $this -> get_recordset_sql ( $sql , $params , $limitfrom , $limitnum );
2008-05-15 21:40:00 +00:00
}
/**
2008-07-25 18:41:35 +00:00
* Get a number of records as a moodle_recordset using a SQL statement .
*
2008-05-15 21:40:00 +00:00
* Since this method is a little less readable , use of it should be restricted to
* code where it ' s possible there might be large datasets being returned . For known
* small datasets use get_records_sql - it leads to simpler code .
*
* The return type is as for @ see function get_recordset .
*
* @ param string $sql the SQL select query to execute .
* @ param array $params array of sql parameters
* @ param int $limitfrom return a subset of records , starting at this point ( optional , required if $limitnum is set ) .
* @ param int $limitnum return a subset comprising this many records ( optional , required if $limitfrom is set ) .
2008-11-21 20:09:13 +00:00
* @ return object moodle_recordset instance
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public abstract function get_recordset_sql ( $sql , array $params = null , $limitfrom = 0 , $limitnum = 0 );
/**
2008-07-25 17:51:37 +00:00
* Get a number of records as an array of objects where all the given conditions met .
2008-05-15 21:40:00 +00:00
*
* If the query succeeds and returns at least one record , the
* return value is an array of objects , one object for each
* record found . The array key is the value from the first
* column of the result set . The object associated with that key
* has a member variable for each column of the results .
*
* @ param string $table the table to query .
* @ param array $conditions optional array $fieldname => requestedvalue with AND in between
* @ param string $sort an order to sort the results in ( optional , a valid SQL ORDER BY parameter ) .
* @ param string $fields a comma separated list of fields to return ( optional , by default
* all fields are returned ) . The first field will be used as key for the
* array so must be a unique field such as 'id' .
* @ param int $limitfrom return a subset of records , starting at this point ( optional , required if $limitnum is set ) .
* @ param int $limitnum return a subset comprising this many records ( optional , required if $limitfrom is set ) .
2008-11-21 20:09:13 +00:00
* @ return array of objects indexed by first column
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_records ( $table , array $conditions = null , $sort = '' , $fields = '*' , $limitfrom = 0 , $limitnum = 0 ) {
list ( $select , $params ) = $this -> where_clause ( $conditions );
return $this -> get_records_select ( $table , $select , $params , $sort , $fields , $limitfrom , $limitnum );
}
/**
2008-07-25 17:51:37 +00:00
* Get a number of records as an array of objects where one field match one list of values .
2008-05-15 21:40:00 +00:00
*
* Return value as for @ see function get_records .
*
* @ param string $table The database table to be checked against .
* @ param string $field The field to search
* @ param string $values array of values
* @ param string $sort Sort order ( as valid SQL sort parameter )
* @ param string $fields A comma separated list of fields to be returned from the chosen table . If specified ,
* the first field should be a unique one such as 'id' since it will be used as a key in the associative
* array .
2008-11-21 20:09:13 +00:00
* @ return array of objects indexed by first column
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
2008-06-01 15:42:48 +00:00
public function get_records_list ( $table , $field , array $values , $sort = '' , $fields = '*' , $limitfrom = 0 , $limitnum = 0 ) {
2008-12-15 02:13:11 +00:00
list ( $select , $params ) = $this -> where_clause_list ( $field , $values );
2008-06-01 15:42:48 +00:00
if ( empty ( $select )) {
// nothing to return
return array ();
}
2008-05-15 21:40:00 +00:00
return $this -> get_records_select ( $table , $select , $params , $sort , $fields , $limitfrom , $limitnum );
}
/**
2008-07-25 17:51:37 +00:00
* Get a number of records as an array of objects which match a particular WHERE clause .
2008-05-15 21:40:00 +00:00
*
* Return value as for @ see function get_records .
*
* @ param string $table the table to query .
* @ param string $select A fragment of SQL to be used in a where clause in the SQL call .
* @ param array $params array of sql parameters
* @ param string $sort an order to sort the results in ( optional , a valid SQL ORDER BY parameter ) .
* @ param string $fields a comma separated list of fields to return
* ( optional , by default all fields are returned ) . The first field will be used as key for the
* array so must be a unique field such as 'id' .
* @ param int $limitfrom return a subset of records , starting at this point ( optional , required if $limitnum is set ) .
* @ param int $limitnum return a subset comprising this many records ( optional , required if $limitfrom is set ) .
2008-11-21 20:09:13 +00:00
* @ return array of objects indexed by first column
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_records_select ( $table , $select , array $params = null , $sort = '' , $fields = '*' , $limitfrom = 0 , $limitnum = 0 ) {
if ( $select ) {
$select = " WHERE $select " ;
}
if ( $sort ) {
$sort = " ORDER BY $sort " ;
}
return $this -> get_records_sql ( " SELECT $fields FROM { $this -> prefix } $table $select $sort " , $params , $limitfrom , $limitnum );
}
/**
2008-07-25 17:51:37 +00:00
* Get a number of records as an array of objects using a SQL statement .
2008-05-15 21:40:00 +00:00
*
* Return value as for @ see function get_records .
*
* @ param string $sql the SQL select query to execute . The first column of this SELECT statement
* must be a unique value ( usually the 'id' field ), as it will be used as the key of the
* returned array .
* @ param array $params array of sql parameters
* @ param int $limitfrom return a subset of records , starting at this point ( optional , required if $limitnum is set ) .
* @ param int $limitnum return a subset comprising this many records ( optional , required if $limitfrom is set ) .
2008-11-21 20:09:13 +00:00
* @ return array of objects indexed by first column
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public abstract function get_records_sql ( $sql , array $params = null , $limitfrom = 0 , $limitnum = 0 );
/**
2008-07-25 17:51:37 +00:00
* Get the first two columns from a number of records as an associative array where all the given conditions met .
2008-05-15 21:40:00 +00:00
*
* Arguments as for @ see function get_recordset .
*
* If no errors occur the return value
* is an associative whose keys come from the first field of each record ,
* and whose values are the corresponding second fields .
* False is returned if an error occurs .
*
* @ param string $table the table to query .
* @ param array $conditions optional array $fieldname => requestedvalue with AND in between
* @ param string $sort an order to sort the results in ( optional , a valid SQL ORDER BY parameter ) .
* @ param string $fields a comma separated list of fields to return - the number of fields should be 2 !
* @ param int $limitfrom return a subset of records , starting at this point ( optional , required if $limitnum is set ) .
* @ param int $limitnum return a subset comprising this many records ( optional , required if $limitfrom is set ) .
2008-11-21 20:09:13 +00:00
* @ return array an associative array
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_records_menu ( $table , array $conditions = null , $sort = '' , $fields = '*' , $limitfrom = 0 , $limitnum = 0 ) {
$menu = array ();
if ( $records = $this -> get_records ( $table , $conditions , $sort , $fields , $limitfrom , $limitnum )) {
foreach ( $records as $record ) {
$record = ( array ) $record ;
$key = array_shift ( $record );
$value = array_shift ( $record );
$menu [ $key ] = $value ;
}
}
return $menu ;
}
/**
2008-07-25 17:51:37 +00:00
* Get the first two columns from a number of records as an associative array which match a particular WHERE clause .
2008-05-15 21:40:00 +00:00
*
* Arguments as for @ see function get_recordset_select .
* Return value as for @ see function get_records_menu .
*
* @ param string $table The database table to be checked against .
* @ param string $select A fragment of SQL to be used in a where clause in the SQL call .
* @ param array $params array of sql parameters
* @ param string $sort Sort order ( optional ) - a valid SQL order parameter
* @ param string $fields A comma separated list of fields to be returned from the chosen table - the number of fields should be 2 !
* @ param int $limitfrom return a subset of records , starting at this point ( optional , required if $limitnum is set ) .
* @ param int $limitnum return a subset comprising this many records ( optional , required if $limitfrom is set ) .
2008-11-21 20:09:13 +00:00
* @ return array an associative array
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_records_select_menu ( $table , $select , array $params = null , $sort = '' , $fields = '*' , $limitfrom = 0 , $limitnum = 0 ) {
$menu = array ();
if ( $records = $this -> get_records_select ( $table , $select , $params , $sort , $fields , $limitfrom , $limitnum )) {
foreach ( $records as $record ) {
2008-06-04 09:14:17 +00:00
$record = ( array ) $record ;
$key = array_shift ( $record );
$value = array_shift ( $record );
2008-05-15 21:40:00 +00:00
$menu [ $key ] = $value ;
}
}
return $menu ;
}
/**
2008-07-25 17:51:37 +00:00
* Get the first two columns from a number of records as an associative array using a SQL statement .
2008-05-15 21:40:00 +00:00
*
* Arguments as for @ see function get_recordset_sql .
* Return value as for @ see function get_records_menu .
*
* @ param string $sql The SQL string you wish to be executed .
* @ param array $params array of sql parameters
* @ param int $limitfrom return a subset of records , starting at this point ( optional , required if $limitnum is set ) .
* @ param int $limitnum return a subset comprising this many records ( optional , required if $limitfrom is set ) .
2008-11-21 20:09:13 +00:00
* @ return array an associative array
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_records_sql_menu ( $sql , array $params = null , $limitfrom = 0 , $limitnum = 0 ) {
$menu = array ();
if ( $records = $this -> get_records_sql ( $sql , $params , $limitfrom , $limitnum )) {
foreach ( $records as $record ) {
2008-06-04 09:14:17 +00:00
$record = ( array ) $record ;
$key = array_shift ( $record );
$value = array_shift ( $record );
2008-05-15 21:40:00 +00:00
$menu [ $key ] = $value ;
}
}
return $menu ;
}
/**
2008-07-25 17:51:37 +00:00
* Get a single database record as an object where all the given conditions met .
2008-05-15 21:40:00 +00:00
*
* @ param string $table The table to select from .
* @ param array $conditions optional array $fieldname => requestedvalue with AND in between
* @ param string $fields A comma separated list of fields to be returned from the chosen table .
* @ param bool $ignoremultiple ignore multiple records if found
2008-11-21 20:09:13 +00:00
* @ return maixed a fieldset object containing the first mathcing record or false if not found
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_record ( $table , array $conditions , $fields = '*' , $ignoremultiple = false ) {
list ( $select , $params ) = $this -> where_clause ( $conditions );
return $this -> get_record_select ( $table , $select , $params , $fields , $ignoremultiple );
}
/**
2008-07-25 17:51:37 +00:00
* Get a single database record as an object which match a particular WHERE clause .
2008-05-15 21:40:00 +00:00
*
* @ param string $table The database table to be checked against .
* @ param string $select A fragment of SQL to be used in a where clause in the SQL call .
* @ param array $params array of sql parameters
* @ param string $fields A comma separated list of fields to be returned from the chosen table .
* @ param bool $ignoremultiple ignore multiple records if found
2008-11-21 20:09:13 +00:00
* @ return maixed a fieldset object containing the first mathcing record or false if not found
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_record_select ( $table , $select , array $params = null , $fields = '*' , $ignoremultiple = false ) {
if ( $select ) {
$select = " WHERE $select " ;
}
return $this -> get_record_sql ( " SELECT $fields FROM { $this -> prefix } $table $select " , $params , $ignoremultiple );
}
/**
2008-07-25 17:51:37 +00:00
* Get a single database record as an object using a SQL statement .
2008-05-15 21:40:00 +00:00
*
* The SQL statement should normally only return one record . In debug mode
* you will get a warning if more records are found . In non - debug mode ,
* it just returns the first record .
*
* Use get_records_sql () if more matches possible !
*
* @ param string $sql The SQL string you wish to be executed , should normally only return one record .
* @ param array $params array of sql parameters
* @ param bool $ignoremultiple ignore multiple records if found
2008-11-21 20:09:13 +00:00
* @ return maixed a fieldset object containing the first mathcing record or false if not found
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_record_sql ( $sql , array $params = null , $ignoremultiple = false ) {
$count = $ignoremultiple ? 1 : 2 ;
2008-10-27 15:30:38 +00:00
if ( ! $records = $this -> get_records_sql ( $sql , $params , 0 , $count )) {
2008-11-21 20:09:13 +00:00
// not found
2008-05-15 21:40:00 +00:00
return false ;
}
2008-10-27 15:30:38 +00:00
if ( ! $ignoremultiple and count ( $records ) > 1 ) {
2008-05-15 21:40:00 +00:00
debugging ( 'Error: mdb->get_record() found more than one record!' );
}
2008-10-27 15:30:38 +00:00
$return = reset ( $records );
2008-05-15 21:40:00 +00:00
return $return ;
}
/**
2008-07-25 17:51:37 +00:00
* Get a single field value from a table record where all the given conditions met .
2008-05-15 21:40:00 +00:00
*
* @ param string $table the table to query .
* @ param string $return the field to return the value of .
* @ param array $conditions optional array $fieldname => requestedvalue with AND in between
2008-11-21 20:09:13 +00:00
* @ return mixed the specified value false if not found
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_field ( $table , $return , array $conditions ) {
list ( $select , $params ) = $this -> where_clause ( $conditions );
return $this -> get_field_select ( $table , $return , $select , $params );
}
/**
2008-07-25 17:51:37 +00:00
* Get a single field value from a table record which match a particular WHERE clause .
2008-05-15 21:40:00 +00:00
*
* @ param string $table the table to query .
* @ param string $return the field to return the value of .
* @ param string $select A fragment of SQL to be used in a where clause returning one row with one column
* @ param array $params array of sql parameters
2008-11-21 20:09:13 +00:00
* @ return mixed the specified value false if not found
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_field_select ( $table , $return , $select , array $params = null ) {
if ( $select ) {
$select = " WHERE $select " ;
}
2008-06-20 09:40:03 +00:00
return $this -> get_field_sql ( " SELECT $return FROM { " . $table . " } $select " , $params );
2008-05-15 21:40:00 +00:00
}
/**
2008-07-25 18:41:35 +00:00
* Get a single field value ( first field ) using a SQL statement .
2008-05-15 21:40:00 +00:00
*
* @ param string $table the table to query .
* @ param string $return the field to return the value of .
* @ param string $sql The SQL query returning one row with one column
* @ param array $params array of sql parameters
2008-11-21 20:09:13 +00:00
* @ return mixed the specified value false if not found
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_field_sql ( $sql , array $params = null ) {
2008-10-27 15:30:38 +00:00
if ( $records = $this -> get_records_sql ( $sql , $params , 0 , 1 )) {
$record = reset ( $records );
$record = ( array ) $record ;
return reset ( $record ); // first column
2008-05-15 21:40:00 +00:00
}
return false ;
}
/**
2008-07-25 18:41:35 +00:00
* Selects records and return values of chosen field as an array which match a particular WHERE clause .
2008-05-15 21:40:00 +00:00
*
* @ param string $table the table to query .
* @ param string $return the field we are intered in
* @ param string $select A fragment of SQL to be used in a where clause in the SQL call .
* @ param array $params array of sql parameters
2008-11-21 20:09:13 +00:00
* @ return mixed array of values
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function get_fieldset_select ( $table , $return , $select , array $params = null ) {
if ( $select ) {
$select = " WHERE $select " ;
}
return $this -> get_fieldset_sql ( " SELECT $return FROM { $this -> prefix } $table $select " , $params );
}
/**
2008-07-25 18:41:35 +00:00
* Selects records and return values ( first field ) as an array using a SQL statement .
2008-05-15 21:40:00 +00:00
*
* @ param string $sql The SQL query
* @ param array $params array of sql parameters
2008-11-21 20:09:13 +00:00
* @ return mixed array of values
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public abstract function get_fieldset_sql ( $sql , array $params = null );
/**
* Insert new record into database , as fast as possible , no safety checks , lobs not supported .
* @ param string $table name
* @ param mixed $params data record as object or array
* @ param bool $returnit return it of inserted record
* @ param bool $bulk true means repeated inserts expected
2008-08-25 21:00:47 +00:00
* @ param bool $customsequence true if 'id' included in $params , disables $returnid
2008-11-21 20:09:13 +00:00
* @ return mixed true or new id
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
2008-08-25 21:00:47 +00:00
public abstract function insert_record_raw ( $table , $params , $returnid = true , $bulk = false , $customsequence = false );
2008-05-15 21:40:00 +00:00
/**
2008-07-25 17:51:37 +00:00
* Insert a record into a table and return the " id " field if required .
*
2008-05-15 21:40:00 +00:00
* Some conversions and safety checks are carried out . Lobs are supported .
* If the return ID isn ' t required , then this just reports success as true / false .
* $data is an object containing needed data
* @ param string $table The database table to be inserted into
* @ param object $data A data object with values for one or more fields in the record
* @ param bool $returnid Should the id of the newly created record entry be returned ? If this option is not requested then true / false is returned .
2008-11-21 20:09:13 +00:00
* @ return mixed true or new id
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public abstract function insert_record ( $table , $dataobject , $returnid = true , $bulk = false );
2008-08-25 21:00:47 +00:00
/**
* Import a record into a table , id field is required .
* Safety checks are NOT carried out . Lobs are supported .
*
* @ param string $table name of database table to be inserted into
* @ param object $dataobject A data object with values for one or more fields in the record
2008-11-21 20:09:13 +00:00
* @ return bool true
* @ throws dml_exception if error
2008-08-25 21:00:47 +00:00
*/
public abstract function import_record ( $table , $dataobject );
2008-05-15 21:40:00 +00:00
/**
* Update record in database , as fast as possible , no safety checks , lobs not supported .
* @ param string $table name
* @ param mixed $params data record as object or array
* @ param bool true means repeated updates expected
2008-11-21 20:09:13 +00:00
* @ return bool true
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public abstract function update_record_raw ( $table , $params , $bulk = false );
/**
* Update a record in a table
*
* $dataobject is an object containing needed data
* Relies on $dataobject having a variable " id " to
* specify the record to update
*
* @ param string $table The database table to be checked against .
* @ param object $dataobject An object with contents equal to fieldname => fieldvalue . Must have an entry for 'id' to map to the table specified .
* @ param bool true means repeated updates expected
2008-11-21 20:09:13 +00:00
* @ return bool true
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public abstract function update_record ( $table , $dataobject , $bulk = false );
/**
2008-07-25 17:51:37 +00:00
* Set a single field in every table record where all the given conditions met .
2008-05-15 21:40:00 +00:00
*
* @ param string $table The database table to be checked against .
* @ param string $newfield the field to set .
* @ param string $newvalue the value to set the field to .
* @ param array $conditions optional array $fieldname => requestedvalue with AND in between
2008-11-21 20:09:13 +00:00
* @ return bool true
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function set_field ( $table , $newfield , $newvalue , array $conditions = null ) {
list ( $select , $params ) = $this -> where_clause ( $conditions );
return $this -> set_field_select ( $table , $newfield , $newvalue , $select , $params );
}
/**
2008-07-25 17:51:37 +00:00
* Set a single field in every table record which match a particular WHERE clause .
2008-05-15 21:40:00 +00:00
*
* @ param string $table The database table to be checked against .
* @ param string $newfield the field to set .
* @ param string $newvalue the value to set the field to .
* @ param string $select A fragment of SQL to be used in a where clause in the SQL call .
* @ param array $params array of sql parameters
2008-11-21 20:09:13 +00:00
* @ return bool true
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public abstract function set_field_select ( $table , $newfield , $newvalue , $select , array $params = null );
/**
* Count the records in a table where all the given conditions met .
*
* @ param string $table The table to query .
* @ param array $conditions optional array $fieldname => requestedvalue with AND in between
* @ return int The count of records returned from the specified criteria .
2008-11-21 20:09:13 +00:00
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
2008-06-01 14:08:44 +00:00
public function count_records ( $table , array $conditions = null ) {
2008-05-15 21:40:00 +00:00
list ( $select , $params ) = $this -> where_clause ( $conditions );
return $this -> count_records_select ( $table , $select , $params );
}
/**
* Count the records in a table which match a particular WHERE clause .
*
* @ param string $table The database table to be checked against .
* @ param string $select A fragment of SQL to be used in a WHERE clause in the SQL call .
* @ param array $params array of sql parameters
* @ param string $countitem The count string to be used in the SQL call . Default is COUNT ( 'x' ) .
* @ return int The count of records returned from the specified criteria .
2008-11-21 20:09:13 +00:00
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function count_records_select ( $table , $select , array $params = null , $countitem = " COUNT('x') " ) {
if ( $select ) {
$select = " WHERE $select " ;
}
return $this -> count_records_sql ( " SELECT $countitem FROM { $this -> prefix } $table $select " , $params );
}
/**
* Get the result of a SQL SELECT COUNT ( ... ) query .
*
* Given a query that counts rows , return that count . ( In fact ,
* given any query , return the first field of the first record
* returned . However , this method should only be used for the
* intended purpose . ) If an error occurrs , 0 is returned .
*
* @ param string $sql The SQL string you wish to be executed .
* @ param array $params array of sql parameters
2008-11-21 20:09:13 +00:00
* @ return int the count
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function count_records_sql ( $sql , array $params = null ) {
if ( $count = $this -> get_field_sql ( $sql , $params )) {
return $count ;
} else {
return 0 ;
}
}
/**
* Test whether a record exists in a table where all the given conditions met .
*
* The record to test is specified by giving up to three fields that must
* equal the corresponding values .
*
* @ param string $table The table to check .
* @ param array $conditions optional array $fieldname => requestedvalue with AND in between
* @ return bool true if a matching record exists , else false .
2008-11-21 20:09:13 +00:00
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function record_exists ( $table , array $conditions ) {
list ( $select , $params ) = $this -> where_clause ( $conditions );
return $this -> record_exists_select ( $table , $select , $params );
}
/**
* Test whether any records exists in a table which match a particular WHERE clause .
*
* @ param string $table The database table to be checked against .
* @ param string $select A fragment of SQL to be used in a WHERE clause in the SQL call .
* @ param array $params array of sql parameters
* @ return bool true if a matching record exists , else false .
2008-11-21 20:09:13 +00:00
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function record_exists_select ( $table , $select , array $params = null ) {
if ( $select ) {
$select = " WHERE $select " ;
}
return $this -> record_exists_sql ( " SELECT 'x' FROM { $this -> prefix } $table $select " , $params );
}
/**
* Test whether a SQL SELECT statement returns any records .
*
* This function returns true if the SQL statement executes
* without any errors and returns at least one record .
*
* @ param string $sql The SQL statement to execute .
* @ param array $params array of sql parameters
* @ return bool true if the SQL executes without errors and returns at least one record .
2008-11-21 20:09:13 +00:00
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public function record_exists_sql ( $sql , array $params = null ) {
if ( $mrs = $this -> get_recordset_sql ( $sql , $params , 0 , 1 )) {
$return = $mrs -> valid ();
$mrs -> close ();
return $return ;
}
return false ;
}
/**
* Delete the records from a table where all the given conditions met .
2008-05-31 15:32:28 +00:00
* If conditions not specified , table is truncated .
2008-05-15 21:40:00 +00:00
*
* @ param string $table the table to delete from .
* @ param array $conditions optional array $fieldname => requestedvalue with AND in between
2008-11-21 20:09:13 +00:00
* @ return bool true .
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
2008-05-31 15:32:28 +00:00
public function delete_records ( $table , array $conditions = null ) {
if ( is_null ( $conditions )) {
return $this -> execute ( " TRUNCATE TABLE { " . $table . " } " );
}
2008-05-15 21:40:00 +00:00
list ( $select , $params ) = $this -> where_clause ( $conditions );
return $this -> delete_records_select ( $table , $select , $params );
}
2008-12-15 02:13:11 +00:00
/**
* Delete the records from a table where one field match one list of values .
*
* @ param string $table the table to delete from .
* @ param string $field The field to search
* @ param string $values array of values
* @ return bool true .
* @ throws dml_exception if error
*/
2008-12-15 21:41:09 +00:00
public function delete_records_list ( $table , $field , array $values ) {
2008-12-15 02:13:11 +00:00
list ( $select , $params ) = $this -> where_clause_list ( $field , $values );
if ( empty ( $select )) {
// nothing to delete
2008-12-15 21:41:09 +00:00
return true ;
2008-12-15 02:13:11 +00:00
}
return $this -> delete_records_select ( $table , $select , $params );
}
2008-05-15 21:40:00 +00:00
/**
2008-07-25 17:51:37 +00:00
* Delete one or more records from a table which match a particular WHERE clause .
2008-05-15 21:40:00 +00:00
*
* @ param string $table The database table to be checked against .
* @ param string $select A fragment of SQL to be used in a where clause in the SQL call ( used to define the selection criteria ) .
* @ param array $params array of sql parameters
2008-11-21 20:09:13 +00:00
* @ return bool true .
* @ throws dml_exception if error
2008-05-15 21:40:00 +00:00
*/
public abstract function delete_records_select ( $table , $select , array $params = null );
/// sql contructs
2008-11-22 19:32:16 +00:00
/**
* Returns the FROM clause required by some DBs in all SELECT statements .
*
* To be used in queries not having FROM clause to provide cross_db
* Most DBs don 't need it, hence the default is ' '
*/
public function sql_null_from_clause () {
return '' ;
}
2008-05-15 21:40:00 +00:00
/**
* Returns the SQL text to be used in order to perform one bitwise AND operation
* between 2 integers .
2009-01-07 18:55:32 +00:00
*
* NOTE : The SQL result is a number and can not be used directly in
* SQL condition , please compare it to some number to get a bool !!
*
2008-05-15 21:40:00 +00:00
* @ param integer int1 first integer in the operation
* @ param integer int2 second integer in the operation
2009-01-07 18:55:32 +00:00
* @ return string the piece of SQL code to be used in your statement
2008-05-15 21:40:00 +00:00
*/
public function sql_bitand ( $int1 , $int2 ) {
return '((' . $int1 . ') & (' . $int2 . '))' ;
}
/**
* Returns the SQL text to be used in order to perform one bitwise NOT operation
* with 1 integer .
2008-07-25 23:31:08 +00:00
*
2008-05-15 21:40:00 +00:00
* @ param integer int1 integer in the operation
* @ return string the piece of SQL code to be used in your statement .
*/
public function sql_bitnot ( $int1 ) {
return '(~(' . $int1 . '))' ;
}
/**
* Returns the SQL text to be used in order to perform one bitwise OR operation
* between 2 integers .
2008-07-25 23:31:08 +00:00
*
2009-01-07 18:55:32 +00:00
* NOTE : The SQL result is a number and can not be used directly in
* SQL condition , please compare it to some number to get a bool !!
*
2008-05-15 21:40:00 +00:00
* @ param integer int1 first integer in the operation
* @ param integer int2 second integer in the operation
* @ return string the piece of SQL code to be used in your statement .
*/
public function sql_bitor ( $int1 , $int2 ) {
return '((' . $int1 . ') | (' . $int2 . '))' ;
}
/**
* Returns the SQL text to be used in order to perform one bitwise XOR operation
* between 2 integers .
2008-07-25 23:31:08 +00:00
*
2009-01-07 18:55:32 +00:00
* NOTE : The SQL result is a number and can not be used directly in
* SQL condition , please compare it to some number to get a bool !!
*
2008-05-15 21:40:00 +00:00
* @ param integer int1 first integer in the operation
* @ param integer int2 second integer in the operation
* @ return string the piece of SQL code to be used in your statement .
*/
public function sql_bitxor ( $int1 , $int2 ) {
return '((' . $int1 . ') ^ (' . $int2 . '))' ;
}
2008-11-26 08:19:45 +00:00
/**
* Returns the SQL text to be used in order to perform module '%'
* opration - remainder after division
*
* @ param integer int1 first integer in the operation
* @ param integer int2 second integer in the operation
* @ return string the piece of SQL code to be used in your statement .
*/
public function sql_modulo ( $int1 , $int2 ) {
return '((' . $int1 . ') % (' . $int2 . '))' ;
}
2008-06-28 18:25:25 +00:00
/**
2008-07-25 23:31:08 +00:00
* Returns the correct CEIL expression applied to fieldname .
*
2008-06-28 18:25:25 +00:00
* @ param string fieldname the field ( or expression ) we are going to ceil
* @ return string the piece of SQL code to be used in your ceiling statement
* Most DB use CEIL (), hence it ' s the default .
*/
public function sql_ceil ( $fieldname ) {
return ' CEIL(' . $fieldname . ')' ;
}
2008-05-15 21:40:00 +00:00
/**
* Returns the SQL to be used in order to CAST one CHAR column to INTEGER .
*
* Be aware that the CHAR column you ' re trying to cast contains really
* int values or the RDBMS will throw an error !
*
* @ param string fieldname the name of the field to be casted
* @ param boolean text to specify if the original column is one TEXT ( CLOB ) column ( true ) . Defaults to false .
* @ return string the piece of SQL code to be used in your statement .
*/
public function sql_cast_char2int ( $fieldname , $text = false ) {
return ' ' . $fieldname . ' ' ;
}
2008-05-31 14:35:58 +00:00
/**
* Returns the SQL to be used in order to CAST one CHAR column to REAL number .
*
* Be aware that the CHAR column you ' re trying to cast contains really
* numbers or the RDBMS will throw an error !
*
* @ param string fieldname the name of the field to be casted
* @ param boolean text to specify if the original column is one TEXT ( CLOB ) column ( true ) . Defaults to false .
* @ return string the piece of SQL code to be used in your statement .
*/
public function sql_cast_char2real ( $fieldname , $text = false ) {
return ' ' . $fieldname . ' ' ;
}
2009-04-10 09:33:26 +00:00
/**
* Returns the SQL to be used in order to an UNSIGNED INTEGER column to SIGNED .
*
* ( Only MySQL needs this . MySQL things that 1 * - 1 = 18446744073709551615
* if the 1 comes from an unsigned column ) .
*
* @ param string fieldname the name of the field to be cast
* @ return string the piece of SQL code to be used in your statement .
*/
public function sql_cast_2signed ( $fieldname ) {
return ' ' . $fieldname . ' ' ;
}
2008-05-15 21:40:00 +00:00
/**
* Returns the SQL text to be used to compare one TEXT ( clob ) column with
* one varchar column , because some RDBMS doesn ' t support such direct
* comparisons .
2008-07-25 23:31:08 +00:00
*
2008-05-15 21:40:00 +00:00
* @ param string fieldname the name of the TEXT field we need to order by
* @ param string number of chars to use for the ordering ( defaults to 32 )
* @ return string the piece of SQL code to be used in your statement .
*/
public function sql_compare_text ( $fieldname , $numchars = 32 ) {
return $this -> sql_order_by_text ( $fieldname , $numchars );
}
2008-11-22 19:32:16 +00:00
/**
* Returns the proper SQL to do LIKE in a case - insensitive way .
*
* Note the LIKE are case sensitive for Oracle . Oracle 10 g is required to use
* the caseinsensitive search using regexp_like () or NLS_COMP = LINGUISTIC :- (
* See http :// docs . moodle . org / en / XMLDB_Problems #Case-insensitive_searches
*
* @ return string
*/
public function sql_ilike () {
return 'LIKE' ;
}
2008-05-15 21:40:00 +00:00
/**
* Returns the proper SQL to do CONCAT between the elements passed
2008-06-09 18:48:28 +00:00
* Can take many parameters
2008-05-15 21:40:00 +00:00
*
* @ param string $element
* @ return string
*/
public abstract function sql_concat ();
/**
* Returns the proper SQL to do CONCAT between the elements passed
* with a given separator
*
* @ param string $separator
* @ param array $elements
* @ return string
*/
public abstract function sql_concat_join ( $separator = " ' ' " , $elements = array ());
/**
* Returns the proper SQL ( for the dbms in use ) to concatenate $firstname and $lastname
2008-07-25 23:31:08 +00:00
* TODO : Does this really need to be here ? Eloy 20070727.
2008-05-15 21:40:00 +00:00
*
* @ param string $firstname User ' s first name
* @ param string $lastname User ' s last name
* @ return string
*/
function sql_fullname ( $first = 'firstname' , $last = 'lastname' ) {
return $this -> sql_concat ( $first , " ' ' " , $last );
}
/**
* Returns the SQL text to be used to order by one TEXT ( clob ) column , because
* some RDBMS doesn ' t support direct ordering of such fields .
2008-07-25 23:31:08 +00:00
*
2008-05-15 21:40:00 +00:00
* Note that the use or queries being ordered by TEXT columns must be minimised ,
* because it ' s really slooooooow .
* @ param string fieldname the name of the TEXT field we need to order by
* @ param string number of chars to use for the ordering ( defaults to 32 )
* @ return string the piece of SQL code to be used in your statement .
*/
public function sql_order_by_text ( $fieldname , $numchars = 32 ) {
return $fieldname ;
}
2009-02-15 23:17:56 +00:00
/**
* Returns the SQL text to be used to calculate the length in characters of one expression .
* @ param string fieldname or expression to calculate its length in characters .
* @ return string the piece of SQL code to be used in the statement .
*/
public function sql_length ( $fieldname ) {
return ' LENGTH(' . $fieldname . ')' ;
}
2008-05-15 21:40:00 +00:00
/**
2008-07-25 23:31:08 +00:00
* Returns the proper substr () function for each DB .
2008-10-28 15:11:10 +00:00
* NOTE : this was originally returning only function name
2008-07-25 23:31:08 +00:00
*
2008-10-28 15:11:10 +00:00
* @ param string $expr some string field , no aggregates
* @ param mixed $start integer or expresion evaluating to int ( 1 based value ; first char has index 1 )
* @ param mixed $length optional integer or expresion evaluating to int
* @ return string sql fragment
2008-05-15 21:40:00 +00:00
*/
2008-10-28 15:11:10 +00:00
public function sql_substr ( $expr , $start , $length = false ) {
if ( count ( func_get_args ()) < 2 ) {
throw new coding_exception ( 'moodle_database::sql_substr() requires at least two parameters' , 'Originaly this function was only returning name of SQL substring function, it now requires all parameters.' );
}
if ( $length === false ) {
2008-10-28 17:57:51 +00:00
return " SUBSTR( $expr , $start ) " ;
2008-10-28 15:11:10 +00:00
} else {
return " SUBSTR( $expr , $start , $length ) " ;
}
}
2008-05-15 21:40:00 +00:00
2008-08-20 06:51:46 +00:00
/**
* Returns the SQL for returning searching one string for the location of another .
2008-08-25 12:52:49 +00:00
* Note , there is no guarantee which order $needle , $haystack will be in
2008-08-20 06:51:46 +00:00
* the resulting SQL , so when using this method , and both arguments contain
* placeholders , you should use named placeholders .
* @ param string $needle the SQL expression that will be searched for .
* @ param string $haystack the SQL expression that will be searched in .
* @ return string the required SQL
*/
public function sql_position ( $needle , $haystack ) {
// Implementation using standard SQL.
return " POSITION(( $needle ) IN ( $haystack )) " ;
}
2008-05-15 21:40:00 +00:00
/**
* Returns the empty string char used by every supported DB . To be used when
* we are searching for that values in our queries . Only Oracle uses this
* for now ( will be out , once we migrate to proper NULLs if that days arrives )
*/
function sql_empty () {
return '' ;
}
/**
* Returns the proper SQL to know if one field is empty .
*
* Note that the function behavior strongly relies on the
* parameters passed describing the field so , please , be accurate
* when speciffying them .
*
* Also , note that this function is not suitable to look for
* fields having NULL contents at all . It ' s all for empty values !
*
* This function should be applied in all the places where conditins of
* the type :
*
* ... AND fieldname = '' ;
*
* are being used . Final result should be :
*
* ... AND ' . sql_isempty(' tablename ', ' fieldname ' , true / false , true / false );
*
* ( see parameters description below )
*
* @ param string $tablename name of the table ( without prefix ) . Not used for now but can be
* necessary in the future if we want to use some introspection using
* meta information against the DB . /// TODO ///
* @ param string $fieldname name of the field we are going to check
* @ param boolean $nullablefield to specify if the field us nullable ( true ) or no ( false ) in the DB
* @ param boolean $textfield to specify if it is a text ( also called clob ) field ( true ) or a varchar one ( false )
* @ return string the sql code to be added to check for empty values
*/
public function sql_isempty ( $tablename , $fieldname , $nullablefield , $textfield ) {
return " $fieldname = '' " ;
}
/**
* Returns the proper SQL to know if one field is not empty .
*
* Note that the function behavior strongly relies on the
* parameters passed describing the field so , please , be accurate
* when speciffying them .
*
* This function should be applied in all the places where conditions of
* the type :
*
* ... AND fieldname != '' ;
*
* are being used . Final result should be :
*
* ... AND ' . sql_isnotempty(' tablename ', ' fieldname ' , true / false , true / false );
*
* ( see parameters description below )
*
* @ param string $tablename name of the table ( without prefix ) . Not used for now but can be
* necessary in the future if we want to use some introspection using
* meta information against the DB . /// TODO ///
* @ param string $fieldname name of the field we are going to check
* @ param boolean $nullablefield to specify if the field us nullable ( true ) or no ( false ) in the DB
* @ param boolean $textfield to specify if it is a text ( also called clob ) field ( true ) or a varchar one ( false )
* @ return string the sql code to be added to check for non empty values
*/
public function sql_isnotempty ( $tablename , $fieldname , $nullablefield , $textfield ) {
return ' ( NOT ' . $this -> sql_isempty ( $tablename , $fieldname , $nullablefield , $textfield ) . ') ' ;
}
2008-05-25 20:43:46 +00:00
/**
* Does this driver suppoer regex syntax when searching
*/
public function sql_regex_supported () {
return false ;
}
/**
* Return regex positive or negative match sql
* @ param bool $positivematch
* @ return string or empty if not supported
*/
public function sql_regex ( $positivematch = true ) {
return '' ;
}
2008-05-15 21:40:00 +00:00
/// transactions
2009-06-13 10:16:29 +00:00
/**
* Returns true if transaction in progress
* @ return bool
*/
function is_transaction_started () {
return $this -> intransaction ;
}
2008-05-15 21:40:00 +00:00
/**
* on DBs that support it , switch to transaction mode and begin a transaction
* you ' ll need to ensure you call commit_sql () or your changes * will * be lost .
*
* this is _very_ useful for massive updates
2009-06-12 07:55:44 +00:00
*
* Please note only one level of transactions is supported , please do not use
* transaction in moodle core ! Transaction are intended for web services
* enrolment and auth synchronisation scripts , etc .
*
* @ return bool success
2008-05-15 21:40:00 +00:00
*/
public function begin_sql () {
2009-06-12 07:55:44 +00:00
if ( $this -> intransaction ) {
debugging ( 'Transaction already in progress' );
return false ;
}
$this -> intransaction = true ;
return true ;
2008-05-15 21:40:00 +00:00
}
/**
* on DBs that support it , commit the transaction
2009-06-12 07:55:44 +00:00
* @ return bool success
2008-05-15 21:40:00 +00:00
*/
public function commit_sql () {
2009-06-12 07:55:44 +00:00
if ( ! $this -> intransaction ) {
debugging ( 'Transaction not in progress' );
return false ;
}
$this -> intransaction = false ;
return true ;
2008-05-15 21:40:00 +00:00
}
/**
* on DBs that support it , rollback the transaction
2009-06-12 07:55:44 +00:00
* @ return bool success
2008-05-15 21:40:00 +00:00
*/
public function rollback_sql () {
2009-06-12 07:55:44 +00:00
if ( ! $this -> intransaction ) {
debugging ( 'Transaction not in progress' );
return false ;
}
$this -> intransaction = false ;
return true ;
2008-05-15 21:40:00 +00:00
}
2008-06-16 21:01:54 +00:00
2009-01-16 23:02:24 +00:00
/// session locking
2009-06-12 08:27:19 +00:00
/**
* Is session lock supported in this driver ?
* @ return bool
*/
2009-01-17 14:31:29 +00:00
public function session_lock_supported () {
return false ;
}
2009-06-12 08:27:19 +00:00
/**
* Obtain session lock
* @ param int $rowid id of the row with session record
* @ return success
*/
2009-01-17 12:12:48 +00:00
public function get_session_lock ( $rowid ) {
2009-01-17 14:31:29 +00:00
$this -> used_for_db_sessions = true ;
2009-01-16 23:02:24 +00:00
}
2009-06-12 08:27:19 +00:00
/**
* Release session lock
* @ param int $rowid id of the row with session record
* @ return success
*/
2009-01-17 12:12:48 +00:00
public function release_session_lock ( $rowid ) {
2009-01-16 23:02:24 +00:00
}
2008-06-18 08:26:41 +00:00
/// performance and logging
2008-06-18 08:26:40 +00:00
/**
* Returns number of reads done by this database
* @ return int
*/
2008-06-16 21:01:54 +00:00
public function perf_get_reads () {
return $this -> reads ;
}
2008-06-18 08:26:40 +00:00
/**
* Returns number of writes done by this database
* @ return int
*/
2008-06-16 21:01:54 +00:00
public function perf_get_writes () {
return $this -> writes ;
}
2008-06-18 08:26:40 +00:00
/**
* Returns number of queries done by this database
* @ return int
*/
public function perf_get_queries () {
return $this -> writes + $this -> reads ;
}
2008-05-15 21:40:00 +00:00
}