]> gitweb.fluxo.info Git - lorea/elgg.git/commitdiff
Refs #2450: Documentation added for database functions.
authorbrettp <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>
Wed, 8 Sep 2010 19:49:19 +0000 (19:49 +0000)
committerbrettp <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>
Wed, 8 Sep 2010 19:49:19 +0000 (19:49 +0000)
git-svn-id: http://code.elgg.org/elgg/trunk@6919 36083f99-b078-4883-b0ff-0f9b5a30f544

engine/lib/database.php

index 798f3ef591d3ffb4a050b5751a2262c47cbcb251..d39fb11518f1f35cae0e3ead5ae12820776977b6 100644 (file)
@@ -1,32 +1,83 @@
 <?php
 /**
- * Elgg database
- * Contains database connection and transfer functionality
+ * Elgg database procedural code.
+ *
+ * Includes functions for establishing and retrieving a database link,
+ * reading data, writing data, upgrading DB schemas, and sanitizing input.
  *
  * @package Elgg
  * @subpackage Core
-
- * @author Curverider Ltd
-
- * @link http://elgg.org/
  */
 
+/**
+ * Query cache for all queries.
+ *
+ * Each query and its results are stored in this array as:
+ * <code>
+ * $DB_QUERY_CACHE[$query] => array(result1, result2, ... resultN)
+ * </code>
+ *
+ * @global array $DB_QUERY_CACHE
+ */
 $DB_QUERY_CACHE = array();
+
+/**
+ * Queries to be executed upon shutdown.
+ *
+ * These queries are saved to an array and executed using
+ * a function registered by register_shutdown_function().
+ *
+ * Queries are saved as an array in the format:
+ * <code>
+ * $DB_DELAYED_QUERIES[] = array(
+ *     'q' => str $query,
+ *     'l' => resource $dblink,
+ *     'h' => str $handler // a callback function
+ * );
+ * </code>
+ *
+ * @see db_delayedexecution_shutdown_hook()
+ * @see execute_delayed_query()
+ * @see init_db()
+ * @see register_shutdown_function()
+ * @global array $DB_DELAYED_QUERIES
+ */
 $DB_DELAYED_QUERIES = array();
 
 /**
+ * Database connection resources.
+ *
+ * Each database link created with establish_db_link($name) is stored in
+ * $dblink as $dblink[$name] => resource.  Use get_db_link($name) to retrieve it.
+ *
+ * @global array $dblink
+ */
+$dblink = array();
+
+/**
+ * Database call count
+ *
+ * Each call to the database increments this counter.
+ *
+ * @global integer $dbcalls
+ */
+$dbcalls = 0;
+
+/**
+ * Establish a connection to the database servser
+ *
  * Connect to the database server and use the Elgg database for a particular database link
  *
- * @param string $dblinkname Default "readwrite"; you can change this to set up additional global database links, eg "read" and "write"
+ * @param string $dblinkname The type of database connection. Used to identify the resource. eg "read", "write", or "readwrite".
+ * @uses $CONFIG
+ * @uses $dblink
+ * @uses $DB_QUERY_CACHE
+ * @uses $dbcalls;
  */
 function establish_db_link($dblinkname = "readwrite") {
        // Get configuration, and globalise database link
        global $CONFIG, $dblink, $DB_QUERY_CACHE, $dbcalls;
 
-       if (!isset($dblink)) {
-               $dblink = array();
-       }
-
        if ($dblinkname != "readwrite" && isset($CONFIG->db[$dblinkname])) {
                if (is_array($CONFIG->db[$dblinkname])) {
                        $index = rand(0,sizeof($CONFIG->db[$dblinkname]));
@@ -53,6 +104,7 @@ function establish_db_link($dblinkname = "readwrite") {
                                $CONFIG->dbuser, $CONFIG->dbhost, "****");
                throw new DatabaseException($msg);
        }
+
        if (!mysql_select_db($CONFIG->dbname, $dblink[$dblinkname])) {
                $msg = sprintf(elgg_echo('DatabaseException:NoConnect'), $CONFIG->dbname);
                throw new DatabaseException($msg);
@@ -68,20 +120,21 @@ function establish_db_link($dblinkname = "readwrite") {
 
        // Set up cache if global not initialized and query cache not turned off
        if ((!$DB_QUERY_CACHE) && (!$db_cache_off)) {
-               $DB_QUERY_CACHE = new ElggStaticVariableCache('db_query_cache'); //array();
-               //$DB_QUERY_CACHE = select_default_memcache('db_query_cache'); //array();
+               $DB_QUERY_CACHE = new ElggStaticVariableCache('db_query_cache');
        }
 }
 
 /**
- * Establish all database connections
+ * Establish database connections
  *
  * If the configuration has been set up for multiple read/write databases, set those
- * links up separately; otherwise just create the one database link
+ * links up separately; otherwise just create the one database link.
  *
+ * @uses $CONFIG
+ * @uses $dblink
+ * @uses establish_db_link
  */
 function setup_db_connections() {
-       // Get configuration and globalise database link
        global $CONFIG, $dblink;
 
        if (!empty($CONFIG->db->split)) {
@@ -93,7 +146,11 @@ function setup_db_connections() {
 }
 
 /**
- * Shutdown hook to display profiling information about db (debug mode)
+ * Display profiling information about db at NOTICE debug level upon shutdown.
+ *
+ * @uses $dbcalls
+ * @uses init_db()
+ * @uses register_shutdown_function()
  */
 function db_profiling_shutdown_hook() {
        global $dbcalls;
@@ -103,7 +160,12 @@ function db_profiling_shutdown_hook() {
 }
 
 /**
- * Execute any delayed queries.
+ * Execute any delayed queries upon shutdown.
+ *
+ * @uses $DB_DELAYED_QUERIES
+ * @uses $CONFIG
+ * @uses init_db()
+ * @uses register_shutdown_function()
  */
 function db_delayedexecution_shutdown_hook() {
        global $DB_DELAYED_QUERIES, $CONFIG;
@@ -116,31 +178,42 @@ function db_delayedexecution_shutdown_hook() {
                        if ((isset($query_details['h'])) && (is_callable($query_details['h']))) {
                                $query_details['h']($result);
                        }
-               } catch (Exception $e) { // Suppress all errors since these can't be delt with here
+               } catch (Exception $e) {
+                       // Suppress all errors since these can't be dealt with here
                        elgg_log($e, 'WARNING');
                }
        }
 }
 
 /**
- * Alias to setup_db_connections, for use in the event handler
+ * Registers shutdown functions for database profiling and delayed queries.
+ *
+ * NB: Database connections are established upon first call to database.
  *
  * @param string $event The event type
  * @param string $object_type The object type
  * @param mixed $object Used for nothing in this context
+ * @elgg_event_handler boot system
  */
-function init_db($event, $object_type, $object = null) {
+function init_db() {
        register_shutdown_function('db_delayedexecution_shutdown_hook');
        register_shutdown_function('db_profiling_shutdown_hook');
-       // [Marcus Povey 20090213: Db connection moved to first db connection attempt]
+
        return true;
 }
 
 /**
- * Gets the appropriate db link for the operation mode requested
+ * Returns (if required, also creates) a database link resource.
+ *
+ * Database link resources are stored in the {@link $dblink} global.  These
+ * resources are created by {@link setup_db_connections()}, which is called if
+ * no links exist.
  *
- * @param string $dblinktype The type of link we want - "read", "write" or "readwrite" (the default)
+ * @param string $dblinktype The type of link we want: "read", "write" or "readwrite".
  * @return object Database link
+ * @uses setup_db_connections()
+ * @uses get_db_link()
+ * @uses $dblink
  */
 function get_db_link($dblinktype) {
        global $dblink;
@@ -149,30 +222,42 @@ function get_db_link($dblinktype) {
                return $dblink[$dblinktype];
        } else if (isset($dblink['readwrite'])) {
                return $dblink['readwrite'];
-       }
-       else {
+       } else {
                setup_db_connections();
                return get_db_link($dblinktype);
        }
 }
 
 /**
- * Explain a given query, useful for debug.
+ * Execute an EXPLAIN for $query.
+ *
+ * @param str $query The query to explain
+ * @param mixed $link The database link resource to user.
+ * @return mixed An object of the query's result, or FALSE
+ * @uses execute_query()
  */
 function explain_query($query, $link) {
        if ($result = execute_query("explain " . $query, $link)) {
                return mysql_fetch_object($result);
        }
 
-       return false;
+       return FALSE;
 }
 
 /**
  * Execute a query.
  *
+ * {@link $dbcalls} is incremented and $query is executed via {@link mysql_query()}.
+ * The query is saved into the {@link $DB_QUERY_CACHE}.  If there is an SQL error,
+ * a {@link DatabaseException} is thrown.
+ *
  * @param string $query The query
  * @param link $dblink the DB link
- * @return Returns a the result of mysql_query
+ * @return The result of mysql_query()
+ * @uses $CONFIG
+ * @uses $dbcalls
+ * @uses $DB_QUERY_CACHE
+ * @throws DatabaseException
  */
 function execute_query($query, $dblink) {
        global $CONFIG, $dbcalls, $DB_QUERY_CACHE;
@@ -192,14 +277,14 @@ function execute_query($query, $dblink) {
 }
 
 /**
- * Queue a query for execution after all output has been sent to the user.
+ * Queue a query for execution upon shutdown.
  *
  * You can specify a handler function if you care about the result. This function will accept
- * the raw result from mysql_query();
+ * the raw result from {@link mysql_query()}.
  *
  * @param string $query The query to execute
  * @param resource $dblink The database link to use
- * @param string $handler The handler
+ * @param string $handler A callback function to pass the results array to
  */
 function execute_delayed_query($query, $dblink, $handler = "") {
        global $DB_DELAYED_QUERIES;
@@ -216,7 +301,7 @@ function execute_delayed_query($query, $dblink, $handler = "") {
 
        $DB_DELAYED_QUERIES[] = $delayed_query;
 
-       return true;
+       return TRUE;
 }
 
 /**
@@ -224,6 +309,8 @@ function execute_delayed_query($query, $dblink, $handler = "") {
  *
  * @param string $query The query to execute
  * @param string $handler The handler if you care about the result.
+ * @uses execute_delayed_query()
+ * @uses get_db_link()
  */
 function execute_delayed_write_query($query, $handler = "") {
        return execute_delayed_query($query, get_db_link('write'), $handler);
@@ -234,16 +321,31 @@ function execute_delayed_write_query($query, $handler = "") {
  *
  * @param string $query The query to execute
  * @param string $handler The handler if you care about the result.
+ * @uses execute_delayed_query()
+ * @uses get_db_link()
  */
 function execute_delayed_read_query($query, $handler = "") {
        return execute_delayed_query($query, get_db_link('read'), $handler);
 }
 
 /**
- * Use this function to get data from the database
+ * Retrieve rows from the database.
+ *
+ * Queries are executed with {@link execute_query()} and results
+ * are retrieved with {@link mysql_fetch_object()}.  If a callback
+ * function $callback is defined, each row will be passed as the single
+ * argument to $callback.  If no callback function is defined, the
+ * entire result set is returned as an array.
+ *
+ * If no results are matched, FALSE is returned.
+ *
  * @param mixed $query The query being passed.
- * @param string $call Optionally, the name of a function to call back to on each row (which takes $row as a single parameter)
- * @return array An array of database result objects
+ * @param string $call Optionally, the name of a function to call back to on each row
+ * @return array|false An array of database result objects or callback function results or false
+ * @uses $CONFIG
+ * @uses $DB_QUERY_CACHE
+ * @uses get_db_link()
+ * @uses execute_query()
  */
 function get_data($query, $callback = "") {
        global $CONFIG, $DB_QUERY_CACHE;
@@ -281,7 +383,7 @@ function get_data($query, $callback = "") {
        if (empty($resultarray)) {
                elgg_log("DB query \"$query\" returned no results.");
                // @todo consider changing this to return empty array #1242
-               return false;
+               return FALSE;
        }
 
        // Cache result
@@ -294,11 +396,19 @@ function get_data($query, $callback = "") {
 }
 
 /**
- * Use this function to get a single data row from the database
- * @param mixed $query The query to run.
- * @return object A single database result object
+ * Retrieve a single row from the database.
+ *
+ * Similar to {@link get_data()} but returns only the first row
+ * matched.  If a callback function $callback is specified, the row will be passed
+ * as the only argument to $callback.
+ *
+ * @param mixed $query The query to execute.
+ * @return mixed A single database result object or the result of the callback function.
+ * @uses $CONFIG
+ * @uses $DB_QUERY_CACHE
+ * @uses execute_query()
+ * @uses get_db_link()
  */
-
 function get_data_row($query, $callback = "") {
        global $CONFIG, $DB_QUERY_CACHE;
 
@@ -313,7 +423,7 @@ function get_data_row($query, $callback = "") {
                if ($cached_query === -1) {
                        // Last time this query returned nothing, so return false
                        //@todo fix me this should return array().
-                       return false;
+                       return FALSE;
                }
 
                return $cached_query;
@@ -344,10 +454,17 @@ function get_data_row($query, $callback = "") {
 }
 
 /**
- * Use this function to insert database data; returns id or false
+ * Insert a row into the database.
+ *
+ * NB: Altering the DB invalidates all queries in {@link $DB_QUERY_CACHE}.
  *
- * @param mixed $query The query to run.
- * @return int $id the database id of the inserted row.
+ * @param mixed $query The query to execute.
+ * @return int|false The database id of the inserted row if a AUTO_INCREMENT field is defined, 0 if not, and false on failure.
+ * @uses $CONFIG
+ * @uses $DB_QUERY_CACHE
+ * @uses get_db_link()
+ * @uses execute_query()
+ * @uses mysql_insert_id()
  */
 function insert_data($query) {
        global $CONFIG, $DB_QUERY_CACHE;
@@ -365,14 +482,20 @@ function insert_data($query) {
                return mysql_insert_id($dblink);
        }
 
-       return false;
+       return FALSE;
 }
 
 /**
- * Update database data
+ * Update a row in the database.
+ *
+ * NB: Altering the DB invalidates all queries in {@link $DB_QUERY_CACHE}.
  *
- * @param mixed $query The query to run.
- * @return Bool on success
+ * @param string $query The query to run.
+ * @return Bool
+ * @uses $CONFIG
+ * @uses $DB_QUERY_CACHE
+ * @uses get_db_link()
+ * @uses execute_db_query()
  */
 function update_data($query) {
        global $CONFIG, $DB_QUERY_CACHE;
@@ -386,19 +509,23 @@ function update_data($query) {
        }
 
        if (execute_query("$query", $dblink)) {
-               // @todo why is this comment out?
-               //return mysql_affected_rows();
-               return true;
+               return TRUE;
        }
 
-       return false;
+       return FALSE;
 }
 
 /**
- * Use this function to delete data
+ * Remove a row from the database.
  *
- * @param mixed $query The SQL query to run
- * @return int|false Either the number of affected rows, or false on failure
+ * NB: Altering the DB invalidates all queries in {@link $DB_QUERY_CACHE}.
+ *
+ * @param string $query The SQL query to run
+ * @return int|false The number of affected rows or false on failure
+ * @uses $CONFIG
+ * @uses $DB_QUERY_CACHE
+ * @uses execute_query()
+ * @uses mysql_affected_rows()
  */
 function delete_data($query) {
        global $CONFIG, $DB_QUERY_CACHE;
@@ -415,14 +542,17 @@ function delete_data($query) {
                return mysql_affected_rows($dblink);
        }
 
-       return false;
+       return FALSE;
 }
 
 
 /**
- * Get the tables currently installed in the Elgg database
+ * Return tables matching the database prefix {@link $CONFIG->dbprefix}% in the currently
+ * selected database.
  *
- * @return array List of tables
+ * @return array|false List of tables or false on failure
+ * @uses $CONFIG
+ * @static array $tables Tables found matching the database prefix
  */
 function get_db_tables() {
        global $CONFIG;
@@ -436,7 +566,7 @@ function get_db_tables() {
                $result = get_data("show tables like '" . $CONFIG->dbprefix . "%'");
        } catch (DatabaseException $d) {
                // Likely we can't handle an exception here, so just return false.
-               return false;
+               return FALSE;
        }
 
        $tables = array();
@@ -450,15 +580,19 @@ function get_db_tables() {
                                }
                }
        } else {
-               return false;
+               return FALSE;
        }
 
        return $tables;
 }
 
 /**
- * Run an optimize query on a mysql tables. Useful for executing after major data changes.
+ * Optimise a table.
+ *
+ * Executes an OPTIMIZE TABLE query on $table.  Useful after large DB changes.
  *
+ * @param string $table The name of the table to optimise
+ * @uses update_data()
  */
 function optimize_table($table) {
        $table = sanitise_string($table);
@@ -468,7 +602,7 @@ function optimize_table($table) {
 /**
  * Get the last database error for a particular database link
  *
- * @param database link $dblink
+ * @param resource $dblink
  * @return string Database error message
  */
 function get_db_error($dblink) {
@@ -476,10 +610,24 @@ function get_db_error($dblink) {
 }
 
 /**
- * Runs a full database script from disk
+ * Runs a full database script from disk.
+ *
+ * The file specified should be a standard SQL file as created by
+ * mysqldump or similar.  Statements must be terminated with ;
+ * and a newline character (\n or \r\n) with only one statement per line.
+ *
+ * The special string 'prefix_' is replaced with the database prefix
+ * as defined in {@link $CONFIG->dbprefix}.
+ *
+ * NB: Errors do not halt execution of the script.  If a line
+ * generates an error, the error message is saved and the
+ * next line is executed.  After the file is run, any errors
+ * are displayed as a {@link DatabaseException}
  *
- * @uses $CONFIG
  * @param string $scriptlocation The full path to the script
+ * @throws DatabaseException
+ * @uses $CONFIG
+ * @uses update_data()
  */
 function run_sql_script($scriptlocation) {
        if ($script = file_get_contents($scriptlocation)) {
@@ -487,8 +635,12 @@ function run_sql_script($scriptlocation) {
 
                $errors = array();
 
+               // Remove MySQL -- style comments
                $script = preg_replace('/\-\-.*\n/', '', $script);
+
+               // Statements must end with ; and a newline
                $sql_statements =  preg_split('/;[\n\r]+/', $script);
+
                foreach($sql_statements as $statement) {
                        $statement = trim($statement);
                        $statement = str_replace("prefix_",$CONFIG->dbprefix,$statement);
@@ -502,8 +654,9 @@ function run_sql_script($scriptlocation) {
                }
                if (!empty($errors)) {
                        $errortxt = "";
-                       foreach($errors as $error)
+                       foreach($errors as $error) {
                                $errortxt .= " {$error};";
+                       }
                        throw new DatabaseException(elgg_echo('DatabaseException:DBSetupIssues') . $errortxt);
                }
        } else {
@@ -514,14 +667,22 @@ function run_sql_script($scriptlocation) {
 /**
  * Upgrade the database schema in an ordered sequence.
  *
- * Makes use of schema upgrade files
+ * Executes all upgrade files in elgg/engine/schema/upgrades/ in sequential order.
+ * Upgrade files must be in the standard Elgg release format of YYYYMMDDII.sql
+ * where II is an incrementor starting from 01.
+ *
+ * Files that are < $version will be ignored.
  *
- * This is a about as core as it comes, so don't start running this from your plugins!
+ * NB: Plugin authors should not call this function directly.
  *
- * @param int $version The version you are upgrading from (usually given in the Elgg version format of YYYYMMDDXX - see version.php for example)
+ * @param int $version The version you are upgrading from in the format YYYYMMDDII.
  * @param string $fromdir Optional directory to load upgrades from (default: engine/schema/upgrades/)
- * @param bool $quiet If true, will suppress all error messages.  Don't use this.
+ * @param bool $quiet If true, will suppress all error messages.  Should be used only for the upgrade from version <=1.6.
  * @return bool
+ * @uses $CONFIG
+ * @uses run_sql_script()
+ * @see upgrade.php
+ * @see version.php
  */
 function db_upgrade($version, $fromdir = "", $quiet = FALSE) {
        global $CONFIG;
@@ -574,27 +735,31 @@ function db_upgrade($version, $fromdir = "", $quiet = FALSE) {
 }
 
 /**
- * This function, called by validate_platform(), will check whether the installed version of
- * MySQL meets the minimum required.
+ * Check if MySQL is at least version 5.
  *
  * @todo If multiple dbs are supported check which db is supported and use the appropriate code to validate
  * the appropriate version.
- *
  * @return bool
+ * @see mysql_get_server_info()
  */
 function db_check_version() {
        $version = mysql_get_server_info();
        $points = explode('.', $version);
 
        if ($points[0] < 5) {
-               return false;
+               return FALSE;
        }
 
-       return true;
+       return TRUE;
 }
 
 /**
  * Sanitise a string for database use, but with the option of escaping extra characters.
+ *
+ * @param string $string The string to sanitise
+ * @param string $extra_escapeable Extra characters to escape with '\\'
+ * @return string The escaped string
+ * @uses sanitise_string()
  */
 function sanitise_string_special($string, $extra_escapeable = '') {
        $string = sanitise_string($string);
@@ -607,7 +772,7 @@ function sanitise_string_special($string, $extra_escapeable = '') {
 }
 
 /**
- * Sanitise a string for database use
+ * Sanitise a string for database use.
  *
  * @param string $string The string to sanitise
  * @return string Sanitised string
@@ -623,14 +788,14 @@ function sanitise_string($string) {
  *
  * @param string $string The string to sanitise
  * @return string Sanitised string
- * @uses sanitise_string
+ * @uses sanitise_string()
  */
 function sanitize_string($string) {
        return sanitise_string($string);
 }
 
 /**
- * Sanitises an integer for database use
+ * Sanitises an integer for database use.
  *
  * @param int $int
  * @return int Sanitised integer
@@ -644,12 +809,13 @@ function sanitise_int($int) {
  *
  * @param int $int
  * @return int Sanitised integer
- * @uses sanitise_string
+ * @uses sanitise_int()
  */
 function sanitize_int($int) {
        return (int) $int;
 }
 
-// Stuff for initialisation
-
-register_elgg_event_handler('boot','system','init_db',0);
\ No newline at end of file
+/**
+ * @elgg_register_event boot system init_db
+ */
+register_elgg_event_handler('boot', 'system', 'init_db', 0);
\ No newline at end of file