aboutsummaryrefslogtreecommitdiff
path: root/engine/lib/database.php
diff options
context:
space:
mode:
Diffstat (limited to 'engine/lib/database.php')
-rw-r--r--engine/lib/database.php1308
1 files changed, 666 insertions, 642 deletions
diff --git a/engine/lib/database.php b/engine/lib/database.php
index ff74c3655..0faa6f029 100644
--- a/engine/lib/database.php
+++ b/engine/lib/database.php
@@ -1,657 +1,681 @@
<?php
+/**
+ * Elgg database
+ * Contains database connection and transfer functionality
+ *
+ * @package Elgg
+ * @subpackage Core
- /**
- * Elgg database
- * Contains database connection and transfer functionality
- *
- * @package Elgg
- * @subpackage Core
-
- * @author Curverider Ltd
-
- * @link http://elgg.org/
- */
-
- $DB_PROFILE = array();
- $DB_QUERY_CACHE = array();
- $DB_DELAYED_QUERIES = array();
-
- /**
- * 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"
- */
- 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]));
- $dbhost = $CONFIG->db[$dblinkname][$index]->dbhost;
- $dbuser = $CONFIG->db[$dblinkname][$index]->dbuser;
- $dbpass = $CONFIG->db[$dblinkname][$index]->dbpass;
- $dbname = $CONFIG->db[$dblinkname][$index]->dbname;
- } else {
- $dbhost = $CONFIG->db[$dblinkname]->dbhost;
- $dbuser = $CONFIG->db[$dblinkname]->dbuser;
- $dbpass = $CONFIG->db[$dblinkname]->dbpass;
- $dbname = $CONFIG->db[$dblinkname]->dbname;
- }
- } else {
- $dbhost = $CONFIG->dbhost;
- $dbuser = $CONFIG->dbuser;
- $dbpass = $CONFIG->dbpass;
- $dbname = $CONFIG->dbname;
- }
-
- // Connect to database
- if (!$dblink[$dblinkname] = mysql_connect($CONFIG->dbhost, $CONFIG->dbuser, $CONFIG->dbpass, true))
- throw new DatabaseException(sprintf(elgg_echo('DatabaseException:WrongCredentials'), $CONFIG->dbuser, $CONFIG->dbhost, $CONFIG->debug ? $CONFIG->dbpass : "****"));
- if (!mysql_select_db($CONFIG->dbname, $dblink[$dblinkname]))
- throw new DatabaseException(sprintf(elgg_echo('DatabaseException:NoConnect'), $CONFIG->dbname));
-
- // Set DB for UTF8
- mysql_query("SET NAMES utf8");
-
- // Set up cache
- if ((!$DB_QUERY_CACHE) && (!$CONFIG->db_disable_query_cache))
- $DB_QUERY_CACHE = new ElggStaticVariableCache('db_query_cache'); //array();
- //$DB_QUERY_CACHE = select_default_memcache('db_query_cache'); //array();
-
- //if ($DB_QUERY_CACHE instanceof ElggMemcache)
- // $DB_QUERY_CACHE->setDefaultExpiry(30);
- }
-
- /**
- * Establish all 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
- *
- */
-
- function setup_db_connections() {
-
- // Get configuration and globalise database link
- global $CONFIG, $dblink;
-
- if (!empty($CONFIG->db->split)) {
- establish_db_link('read');
- establish_db_link('write');
- } else {
- establish_db_link('readwrite');
- }
-
+ * @author Curverider Ltd
+
+ * @link http://elgg.org/
+ */
+
+$DB_PROFILE = array();
+$DB_QUERY_CACHE = array();
+$DB_DELAYED_QUERIES = array();
+
+/**
+ * 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"
+ */
+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]));
+ $dbhost = $CONFIG->db[$dblinkname][$index]->dbhost;
+ $dbuser = $CONFIG->db[$dblinkname][$index]->dbuser;
+ $dbpass = $CONFIG->db[$dblinkname][$index]->dbpass;
+ $dbname = $CONFIG->db[$dblinkname][$index]->dbname;
+ } else {
+ $dbhost = $CONFIG->db[$dblinkname]->dbhost;
+ $dbuser = $CONFIG->db[$dblinkname]->dbuser;
+ $dbpass = $CONFIG->db[$dblinkname]->dbpass;
+ $dbname = $CONFIG->db[$dblinkname]->dbname;
}
-
- /**
- * Shutdown hook to display profiling information about db (debug mode)
- */
- function db_profiling_shutdown_hook()
- {
- global $CONFIG, $DB_PROFILE, $dbcalls;
-
- if (isset($CONFIG->debug) && $CONFIG->debug)
- {
- error_log("***************** DB PROFILING ********************");
-
- $DB_PROFILE = array_count_values($DB_PROFILE);
-
- foreach ($DB_PROFILE as $k => $v)
- error_log("$v times: '$k' ");
-
- error_log("DB Queries for this page: $dbcalls");
- error_log("***************************************************");
+ } else {
+ $dbhost = $CONFIG->dbhost;
+ $dbuser = $CONFIG->dbuser;
+ $dbpass = $CONFIG->dbpass;
+ $dbname = $CONFIG->dbname;
+ }
+
+ // Connect to database
+ if (!$dblink[$dblinkname] = mysql_connect($CONFIG->dbhost, $CONFIG->dbuser, $CONFIG->dbpass, true)) {
+ $msg = sprintf(elgg_echo('DatabaseException:WrongCredentials'),
+ $CONFIG->dbuser, $CONFIG->dbhost, $CONFIG->debug ? $CONFIG->dbpass : "****");
+ throw new DatabaseException($msg);
+ }
+ if (!mysql_select_db($CONFIG->dbname, $dblink[$dblinkname])) {
+ $msg = sprintf(elgg_echo('DatabaseException:NoConnect'), $CONFIG->dbname);
+ throw new DatabaseException($msg);
+ }
+
+ // Set DB for UTF8
+ mysql_query("SET NAMES utf8");
+
+ // Set up cache
+ if ((!$DB_QUERY_CACHE) && (!$CONFIG->db_disable_query_cache)) {
+ $DB_QUERY_CACHE = new ElggStaticVariableCache('db_query_cache'); //array();
+ //$DB_QUERY_CACHE = select_default_memcache('db_query_cache'); //array();
+ }
+}
+
+/**
+ * Establish all 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
+ *
+ */
+function setup_db_connections() {
+ // Get configuration and globalise database link
+ global $CONFIG, $dblink;
+
+ if (!empty($CONFIG->db->split)) {
+ establish_db_link('read');
+ establish_db_link('write');
+ } else {
+ establish_db_link('readwrite');
+ }
+}
+
+/**
+ * Shutdown hook to display profiling information about db (debug mode)
+ */
+function db_profiling_shutdown_hook() {
+ global $CONFIG, $DB_PROFILE, $dbcalls;
+
+ if (isset($CONFIG->debug) && $CONFIG->debug) {
+ error_log("***************** DB PROFILING ********************");
+
+ $DB_PROFILE = array_count_values($DB_PROFILE);
+
+ foreach ($DB_PROFILE as $k => $v) {
+ error_log("$v times: '$k' ");
}
+
+ error_log("DB Queries for this page: $dbcalls");
+ error_log("***************************************************");
}
-
- /**
- * Execute any delayed queries.
- */
- function db_delayedexecution_shutdown_hook()
- {
- global $DB_DELAYED_QUERIES, $CONFIG;
-
- foreach ($DB_DELAYED_QUERIES as $query_details) {
- $result = execute_query($query_details['q'], $query_details['l']); // use one of our db functions so it is included in profiling.
-
- try {
- 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
- if (isset($CONFIG->debug) && $CONFIG->debug) error_log($e);
+}
+
+/**
+ * Execute any delayed queries.
+ */
+function db_delayedexecution_shutdown_hook() {
+ global $DB_DELAYED_QUERIES, $CONFIG;
+
+ foreach ($DB_DELAYED_QUERIES as $query_details) {
+ // use one of our db functions so it is included in profiling.
+ $result = execute_query($query_details['q'], $query_details['l']);
+
+ try {
+ 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
+ if (isset($CONFIG->debug) && $CONFIG->debug) {
+ error_log($e);
}
}
}
-
- /**
- * Alias to setup_db_connections, for use in the event handler
- *
- * @param string $event The event type
- * @param string $object_type The object type
- * @param mixed $object Used for nothing in this context
- */
- function init_db($event, $object_type, $object = null) {
- register_shutdown_function('db_delayedexecution_shutdown_hook');
- register_shutdown_function('db_profiling_shutdown_hook');
- //setup_db_connections(); // [Marcus Povey 20090213: Db connection moved to first db connection attempt]
- return true;
+}
+
+/**
+ * Alias to setup_db_connections, for use in the event handler
+ *
+ * @param string $event The event type
+ * @param string $object_type The object type
+ * @param mixed $object Used for nothing in this context
+ */
+function init_db($event, $object_type, $object = null) {
+ 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
+ *
+ * @param string $dblinktype The type of link we want - "read", "write" or "readwrite" (the default)
+ * @return object Database link
+ */
+function get_db_link($dblinktype) {
+ global $dblink;
+
+ if (isset($dblink[$dblinktype])) {
+ return $dblink[$dblinktype];
+ } else if (isset($dblink['readwrite'])) {
+ return $dblink['readwrite'];
+ }
+ else {
+ setup_db_connections();
+ return get_db_link($dblinktype);
+ }
+}
+
+/**
+ * Explain a given query, useful for debug.
+ */
+function explain_query($query, $link) {
+ if ($result = execute_query("explain " . $query, $link)) {
+ return mysql_fetch_object($result);
+ }
+
+ return false;
+}
+
+/**
+ * Execute a query.
+ *
+ * @param string $query The query
+ * @param link $dblink the DB link
+ * @return Returns a the result of mysql_query
+ */
+function execute_query($query, $dblink) {
+ global $CONFIG, $dbcalls, $DB_PROFILE, $DB_QUERY_CACHE;
+
+ $dbcalls++;
+
+ //if ((isset($CONFIG->debug)) && ($CONFIG->debug==true))
+ $DB_PROFILE[] = $query;
+
+ $result = mysql_query($query, $dblink);
+ if ($DB_QUERY_CACHE) {
+ $DB_QUERY_CACHE[$query] = -1; // Set initial cache to -1
+ }
+
+ if (mysql_errno($dblink)) {
+ throw new DatabaseException(mysql_error($dblink) . " QUERY: " . $query);
+ }
+
+ return $result;
+}
+
+/**
+ * Queue a query for execution after all output has been sent to the user.
+ *
+ * You can specify a handler function if you care about the result. This function will accept
+ * the raw result from mysql_query();
+ *
+ * @param string $query The query to execute
+ * @param resource $dblink The database link to use
+ * @param string $handler The handler
+ */
+function execute_delayed_query($query, $dblink, $handler = "") {
+ global $DB_DELAYED_QUERIES;
+
+ if (!isset($DB_DELAYED_QUERIES)) {
+ $DB_DELAYED_QUERIES = array();
+ }
+
+ // Construct delayed query
+ $delayed_query = array();
+ $delayed_query['q'] = $query;
+ $delayed_query['l'] = $dblink;
+ $delayed_query['h'] = $handler;
+
+ $DB_DELAYED_QUERIES[] = $delayed_query;
+
+ return true;
+}
+
+/**
+ * Write wrapper for execute_delayed_query()
+ *
+ * @param string $query The query to execute
+ * @param string $handler The handler if you care about the result.
+ */
+function execute_delayed_write_query($query, $handler = "") {
+ return execute_delayed_query($query, get_db_link('write'), $handler);
+}
+
+/**
+ * Read wrapper for execute_delayed_query()
+ *
+ * @param string $query The query to execute
+ * @param string $handler The handler if you care about the result.
+ */
+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
+ * @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
+ */
+function get_data($query, $callback = "") {
+ global $CONFIG, $DB_QUERY_CACHE;
+
+ // Is cached?
+ if ($DB_QUERY_CACHE) {
+ $cached_query = $DB_QUERY_CACHE[$query];
+ }
+
+ if ((isset($cached_query)) && ($cached_query)) {
+ if ((isset($CONFIG->debug)) && ($CONFIG->debug==true)) {
+ error_log ("$query results returned from cache");
}
-
- /**
- * Gets the appropriate db link for the operation mode requested
- *
- * @param string $dblinktype The type of link we want - "read", "write" or "readwrite" (the default)
- * @return object Database link
- */
- function get_db_link($dblinktype) {
-
- global $dblink;
-
-
- if (isset($dblink[$dblinktype])) {
- return $dblink[$dblinktype];
- } else if (isset($dblink['readwrite'])) {
- return $dblink['readwrite'];
+
+ if ($cached_query === -1) {
+ // Last time this query returned nothing, so return an empty array
+ return array();
+ }
+
+ return $cached_query;
+ }
+
+ $dblink = get_db_link('read');
+ $resultarray = array();
+
+ if ($result = execute_query("$query", $dblink)) {
+ while ($row = mysql_fetch_object($result)) {
+ if (!empty($callback) && is_callable($callback)) {
+ $row = $callback($row);
}
- else
- {
- setup_db_connections();
- return get_db_link($dblinktype);
+ if ($row) {
+ $resultarray[] = $row;
}
}
-
- /**
- * Explain a given query, useful for debug.
- */
- function explain_query($query, $link)
- {
- if ($result = execute_query("explain " . $query, $link)) {
- return mysql_fetch_object($result);
- }
-
- return false;
- }
-
- /**
- * Execute a query.
- *
- * @param string $query The query
- * @param link $dblink the DB link
- * @return Returns a the result of mysql_query
- */
- function execute_query($query, $dblink)
- {
- global $CONFIG, $dbcalls, $DB_PROFILE, $DB_QUERY_CACHE;
-
- $dbcalls++;
-
- //if ((isset($CONFIG->debug)) && ($CONFIG->debug==true))
- $DB_PROFILE[] = $query;
-
- $result = mysql_query($query, $dblink);
- if ($DB_QUERY_CACHE) $DB_QUERY_CACHE[$query] = -1; // Set initial cache to -1
-
- if (mysql_errno($dblink))
- throw new DatabaseException(mysql_error($dblink) . " QUERY: " . $query);
-
- return $result;
-
+ }
+
+ if (empty($resultarray)) {
+ if ((isset($CONFIG->debug)) && ($CONFIG->debug==true)) {
+ error_log("WARNING: DB query \"$query\" returned no results.");
+ return false;
}
-
- /**
- * Queue a query for execution after all output has been sent to the user.
- *
- * You can specify a handler function if you care about the result. This function will accept
- * the raw result from mysql_query();
- *
- * @param string $query The query to execute
- * @param resource $dblink The database link to use
- * @param string $handler The handler
- */
- function execute_delayed_query($query, $dblink, $handler = "")
- {
- global $DB_DELAYED_QUERIES;
-
- if (!isset($DB_DELAYED_QUERIES))
- $DB_DELAYED_QUERIES = array();
-
- // Construct delayed query
- $delayed_query = array();
- $delayed_query['q'] = $query;
- $delayed_query['l'] = $dblink;
- $delayed_query['h'] = $handler;
-
- $DB_DELAYED_QUERIES[] = $delayed_query;
-
- return true;
+ }
+
+ if ((isset($CONFIG->debug)) && ($CONFIG->debug==true)) {
+ error_log("$query results cached");
+ }
+
+ // Cache result
+ if ($DB_QUERY_CACHE) {
+ $DB_QUERY_CACHE[$query] = $resultarray;
+ }
+
+ return $resultarray;
+}
+
+/**
+ * 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
+ */
+
+function get_data_row($query, $callback = "") {
+ global $CONFIG, $DB_QUERY_CACHE;
+
+ // Is cached
+ if ($DB_QUERY_CACHE) {
+ $cached_query = $DB_QUERY_CACHE[$query];
+ }
+
+ if ((isset($cached_query)) && ($cached_query)) {
+ if ((isset($CONFIG->debug)) && ($CONFIG->debug==true)) {
+ error_log ("$query results returned from cache");
}
-
- /**
- * Write wrapper for execute_delayed_query()
- *
- * @param string $query The query to execute
- * @param string $handler The handler if you care about the result.
- */
- function execute_delayed_write_query($query, $handler = "") { return execute_delayed_query($query, get_db_link('write'), $handler); }
-
- /**
- * Read wrapper for execute_delayed_query()
- *
- * @param string $query The query to execute
- * @param string $handler The handler if you care about the result.
- */
- 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
- * @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
- */
-
- function get_data($query, $callback = "") {
-
- global $CONFIG, $DB_QUERY_CACHE;
-
- // Is cached?
- if ($DB_QUERY_CACHE) $cached_query = $DB_QUERY_CACHE[$query];
- if ((isset($cached_query)) && ($cached_query)) {
- if ((isset($CONFIG->debug)) && ($CONFIG->debug==true))
- error_log ("$query results returned from cache");
-
- if ($cached_query === -1)
- return array(); // Last time this query returned nothing, so return an empty array
-
- return $cached_query;
- }
-
- $dblink = get_db_link('read');
-
- $resultarray = array();
-
- if ($result = execute_query("$query", $dblink)) {
- while ($row = mysql_fetch_object($result)) {
- if (!empty($callback) && is_callable($callback)) {
- $row = $callback($row);
- }
- if ($row) $resultarray[] = $row;
- }
- }
-
- if (empty($resultarray)) {
- if ((isset($CONFIG->debug)) && ($CONFIG->debug==true))
- error_log("WARNING: DB query \"$query\" returned no results.");
-
- return false;
- }
-
- // Cache result
- if ((isset($CONFIG->debug)) && ($CONFIG->debug==true))
- error_log("$query results cached");
- if ($DB_QUERY_CACHE) $DB_QUERY_CACHE[$query] = $resultarray;
-
- return $resultarray;
- }
-
- /**
- * 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
- */
-
- function get_data_row($query, $callback = "") {
-
- global $CONFIG, $DB_QUERY_CACHE;
-
- // Is cached
- if ($DB_QUERY_CACHE) $cached_query = $DB_QUERY_CACHE[$query];
- if ((isset($cached_query)) && ($cached_query)) {
- if ((isset($CONFIG->debug)) && ($CONFIG->debug==true))
- error_log ("$query results returned from cache");
-
- if ($cached_query === -1)
- return false; // Last time this query returned nothing, so return false
-
- return $cached_query;
- }
-
- $dblink = get_db_link('read');
-
- if ($result = execute_query("$query", $dblink)) {
-
- $row = mysql_fetch_object($result);
-
- // Cache result (even if query returned no data
- if ((isset($CONFIG->debug)) && ($CONFIG->debug==true))
- error_log("$query results cached");
- if ($DB_QUERY_CACHE) $DB_QUERY_CACHE[$query] = $row;
-
- if (!empty($callback) && is_callable($callback)) {
- $row = $callback($row);
- }
-
- if ($row) return $row;
- }
-
- if ((isset($CONFIG->debug)) && ($CONFIG->debug==true))
- error_log("WARNING: DB query \"$query\" returned no results.");
-
- return false;
- }
-
- /**
- * Use this function to insert database data; returns id or false
- *
- * @param mixed $query The query to run.
- * @return int $id the database id of the inserted row.
- */
-
- function insert_data($query) {
-
- global $CONFIG, $DB_QUERY_CACHE;
-
- $dblink = get_db_link('write');
-
- // Invalidate query cache
- if ($DB_QUERY_CACHE) $DB_QUERY_CACHE->clear();
- if ((isset($CONFIG->debug)) && ($CONFIG->debug==true))
- error_log("Query cache invalidated");
-
- if (execute_query("$query", $dblink))
- return mysql_insert_id($dblink);
-
-
+
+ if ($cached_query === -1) {
+ // Last time this query returned nothing, so return false
+ //@todo fix me this should return array().
return false;
- }
-
- /**
- * Update database data
- *
- * @param mixed $query The query to run.
- * @return int|false Either the number of affected rows, or false on failure
- */
-
- function update_data($query) {
-
- global $CONFIG, $DB_QUERY_CACHE;
-
- $dblink = get_db_link('write');
-
- // Invalidate query cache
- if ($DB_QUERY_CACHE) $DB_QUERY_CACHE->clear();
- if ((isset($CONFIG->debug)) && ($CONFIG->debug==true))
- error_log("Query cache invalidated");
-
- if (execute_query("$query", $dblink))
- return true; //return mysql_affected_rows();
-
- return false;
-
- }
-
- /**
- * Use this function to delete data
- *
- * @param mixed $query The SQL query to run
- * @return int|false Either the number of affected rows, or false on failure
- */
-
- function delete_data($query) {
-
- global $CONFIG, $DB_QUERY_CACHE;
-
- $dblink = get_db_link('write');
-
- // Invalidate query cache
- if ($DB_QUERY_CACHE) $DB_QUERY_CACHE->clear();
- if ((isset($CONFIG->debug)) && ($CONFIG->debug==true))
- error_log("Query cache invalidated");
-
- if (execute_query("$query", $dblink))
- return mysql_affected_rows($dblink);
-
- return false;
- }
-
-
- /**
- * Get the tables currently installed in the Elgg database
- *
- * @return array List of tables
- */
- function get_db_tables() {
- global $CONFIG;
- static $tables, $count;
-
- if (isset($tables)) {
- return $tables;
- }
-
- try{
- $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;
- }
-
- $tables = array();
-
- if (is_array($result) && !empty($result)) {
- foreach($result as $row) {
- $row = (array) $row;
- if (is_array($row) && !empty($row))
- foreach($row as $element) {
- $tables[] = $element;
- }
- }
- }
- else
- return false;
-
- return $tables;
- }
-
- /**
- * Run an optimize query on a mysql tables. Useful for executing after major data changes.
- *
- */
- function optimize_table($table)
- {
- $table = sanitise_string($table);
- return update_data("optimize table $table");
- }
-
- /**
- * Get the last database error for a particular database link
- *
- * @param database link $dblink
- * @return string Database error message
- */
- function get_db_error($dblink) {
- return mysql_error($dblink);
- }
-
- /**
- * Runs a full database script from disk
- *
- * @uses $CONFIG
- * @param string $scriptlocation The full path to the script
- */
- function run_sql_script($scriptlocation) {
-
- if ($script = file_get_contents($scriptlocation)) {
-
- global $CONFIG;
-
- $errors = array();
-
- $script = preg_replace('/\-\-.*\n/', '', $script);
- $sql_statements = preg_split('/;[\n\r]+/', $script);
- foreach($sql_statements as $statement) {
- $statement = trim($statement);
- $statement = str_replace("prefix_",$CONFIG->dbprefix,$statement);
- if (!empty($statement)) {
- try {
- $result = update_data($statement);
- } catch (DatabaseException $e) {
- $errors[] = $e->getMessage();
- }
- }
- }
- if (!empty($errors)) {
- $errortxt = "";
- foreach($errors as $error)
- $errortxt .= " {$error};";
- throw new DatabaseException(elgg_echo('DatabaseException:DBSetupIssues') . $errortxt);
- }
-
- } else {
- throw new DatabaseException(sprintf(elgg_echo('DatabaseException:ScriptNotFound'), $scriptlocation));
- }
-
- }
-
- /**
- * Upgrade the database schema in an ordered sequence.
- *
- * Makes use of schema upgrade files
- *
- * This is a about as core as it comes, so don't start running this from your plugins!
- *
- * @param int $version The version you are upgrading from (usually given in the Elgg version format of YYYYMMDDXX - see version.php for example)
- * @param string $fromdir Optional directory to load upgrades from (default: engine/schema/upgrades/)
- * @return bool
- */
- function db_upgrade($version, $fromdir = "") {
-
- global $CONFIG;
-
- // Elgg and its database must be installed to upgrade it!
- if (!is_db_installed() || !is_installed()) return false;
-
- $version = (int) $version;
- if (!$fromdir)
- $fromdir = $CONFIG->path . 'engine/schema/upgrades/';
-
- if ($handle = opendir($fromdir)) {
-
- $sqlupgrades = array();
-
- while ($sqlfile = readdir($handle)) {
-
- if (!is_dir($fromdir . $sqlfile)) {
- if (preg_match('/([0-9]*)\.sql/',$sqlfile,$matches)) {
- $sql_version = (int) $matches[1];
- if ($sql_version > $version) {
- $sqlupgrades[] = $sqlfile;
- }
- }
- }
-
- }
-
- asort($sqlupgrades);
- if (sizeof($sqlupgrades) > 0) {
- foreach($sqlupgrades as $sqlfile) {
- try {
- run_sql_script($fromdir . $sqlfile);
- } catch (DatabaseException $e) {
- error_log($e->getmessage());
- }
- }
- }
-
- }
-
- return true;
- }
-
- /**
- * This function, called by validate_platform(), will check whether the installed version of
- * MySQL meets the minimum required.
- *
- * TODO: If multiple dbs are supported check which db is supported and use the appropriate code to validate
- * the appropriate version.
- *
- * @return bool
- */
- function db_check_version()
- {
- $version = mysql_get_server_info();
-
- $points = explode('.', $version);
-
- if ($points[0] < 5)
- return false;
-
- return true;
- }
-
- /**
- * Sanitise a string for database use, but with the option of escaping extra characters.
- */
- function sanitise_string_special($string, $extra_escapeable = '')
- {
- $string = sanitise_string($string);
-
- for ($n = 0; $n < strlen($extra_escapeable); $n++)
- $string = str_replace($extra_escapeable[$n], "\\" . $extra_escapeable[$n], $string);
-
- return $string;
- }
-
- /**
- * Sanitise a string for database use
- *
- * @param string $string The string to sanitise
- * @return string Sanitised string
- */
- function sanitise_string($string) {
- return mysql_real_escape_string(trim($string));
- }
-
- /**
- * Wrapper function for alternate English spelling
- *
- * @param string $string The string to sanitise
- * @return string Sanitised string
- * @uses sanitise_string
- */
- function sanitize_string($string) {
- return sanitise_string($string);
- }
-
- /**
- * Sanitises an integer for database use
- *
- * @param int $int
- * @return int Sanitised integer
- */
- function sanitise_int($int) {
- return (int) $int;
- }
-
- /**
- * Wrapper function for alternate English spelling
- *
- * @param int $int
- * @return int Sanitised integer
- * @uses sanitise_string
- */
- function sanitize_int($int) {
- return (int) $int;
- }
-
- // Stuff for initialisation
-
- register_elgg_event_handler('boot','system','init_db',0);
-
-?>
+ }
+
+ return $cached_query;
+ }
+
+ $dblink = get_db_link('read');
+
+ if ($result = execute_query("$query", $dblink)) {
+ $row = mysql_fetch_object($result);
+
+ // Cache result (even if query returned no data)
+ if ((isset($CONFIG->debug)) && ($CONFIG->debug==true)) {
+ error_log("$query results cached");
+ }
+
+ if ($DB_QUERY_CACHE) {
+ $DB_QUERY_CACHE[$query] = $row;
+ }
+
+ if (!empty($callback) && is_callable($callback)) {
+ $row = $callback($row);
+ }
+
+ if ($row) {
+ return $row;
+ }
+ }
+
+ if ((isset($CONFIG->debug)) && ($CONFIG->debug==true)) {
+ error_log("WARNING: DB query \"$query\" returned no results.");
+ }
+
+ return false;
+}
+
+/**
+ * Use this function to insert database data; returns id or false
+ *
+ * @param mixed $query The query to run.
+ * @return int $id the database id of the inserted row.
+ */
+function insert_data($query) {
+ global $CONFIG, $DB_QUERY_CACHE;
+
+ $dblink = get_db_link('write');
+
+ // Invalidate query cache
+ if ($DB_QUERY_CACHE) {
+ $DB_QUERY_CACHE->clear();
+ }
+
+ if ((isset($CONFIG->debug)) && ($CONFIG->debug==true)) {
+ error_log("Query cache invalidated");
+ }
+
+ if (execute_query("$query", $dblink)) {
+ return mysql_insert_id($dblink);
+ }
+
+ return false;
+}
+
+/**
+ * Update database data
+ *
+ * @param mixed $query The query to run.
+ * @return Bool on success
+ */
+function update_data($query) {
+ global $CONFIG, $DB_QUERY_CACHE;
+
+ $dblink = get_db_link('write');
+
+ // Invalidate query cache
+ if ($DB_QUERY_CACHE) {
+ $DB_QUERY_CACHE->clear();
+ }
+
+ if ((isset($CONFIG->debug)) && ($CONFIG->debug==true)) {
+ error_log("Query cache invalidated");
+ }
+
+ if (execute_query("$query", $dblink)) {
+ // @todo why is this comment out?
+ //return mysql_affected_rows();
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Use this function to delete data
+ *
+ * @param mixed $query The SQL query to run
+ * @return int|false Either the number of affected rows, or false on failure
+ */
+function delete_data($query) {
+ global $CONFIG, $DB_QUERY_CACHE;
+
+ $dblink = get_db_link('write');
+
+ // Invalidate query cache
+ if ($DB_QUERY_CACHE) {
+ $DB_QUERY_CACHE->clear();
+ }
+
+ if ((isset($CONFIG->debug)) && ($CONFIG->debug==true)) {
+ error_log("Query cache invalidated");
+ }
+
+ if (execute_query("$query", $dblink)) {
+ return mysql_affected_rows($dblink);
+ }
+
+ return false;
+}
+
+
+/**
+ * Get the tables currently installed in the Elgg database
+ *
+ * @return array List of tables
+ */
+function get_db_tables() {
+ global $CONFIG;
+ static $tables;
+
+ if (isset($tables)) {
+ return $tables;
+ }
+
+ try{
+ $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;
+ }
+
+ $tables = array();
+
+ if (is_array($result) && !empty($result)) {
+ foreach($result as $row) {
+ $row = (array) $row;
+ if (is_array($row) && !empty($row))
+ foreach($row as $element) {
+ $tables[] = $element;
+ }
+ }
+ } else {
+ return false;
+ }
+
+ return $tables;
+}
+
+/**
+ * Run an optimize query on a mysql tables. Useful for executing after major data changes.
+ *
+ */
+function optimize_table($table) {
+ $table = sanitise_string($table);
+ return update_data("optimize table $table");
+}
+
+/**
+ * Get the last database error for a particular database link
+ *
+ * @param database link $dblink
+ * @return string Database error message
+ */
+function get_db_error($dblink) {
+ return mysql_error($dblink);
+}
+
+/**
+ * Runs a full database script from disk
+ *
+ * @uses $CONFIG
+ * @param string $scriptlocation The full path to the script
+ */
+function run_sql_script($scriptlocation) {
+ if ($script = file_get_contents($scriptlocation)) {
+ global $CONFIG;
+
+ $errors = array();
+
+ $script = preg_replace('/\-\-.*\n/', '', $script);
+ $sql_statements = preg_split('/;[\n\r]+/', $script);
+ foreach($sql_statements as $statement) {
+ $statement = trim($statement);
+ $statement = str_replace("prefix_",$CONFIG->dbprefix,$statement);
+ if (!empty($statement)) {
+ try {
+ $result = update_data($statement);
+ } catch (DatabaseException $e) {
+ $errors[] = $e->getMessage();
+ }
+ }
+ }
+ if (!empty($errors)) {
+ $errortxt = "";
+ foreach($errors as $error)
+ $errortxt .= " {$error};";
+ throw new DatabaseException(elgg_echo('DatabaseException:DBSetupIssues') . $errortxt);
+ }
+ } else {
+ throw new DatabaseException(sprintf(elgg_echo('DatabaseException:ScriptNotFound'), $scriptlocation));
+ }
+}
+
+/**
+ * Upgrade the database schema in an ordered sequence.
+ *
+ * Makes use of schema upgrade files
+ *
+ * This is a about as core as it comes, so don't start running this from your plugins!
+ *
+ * @param int $version The version you are upgrading from (usually given in the Elgg version format of YYYYMMDDXX - see version.php for example)
+ * @param string $fromdir Optional directory to load upgrades from (default: engine/schema/upgrades/)
+ * @return bool
+ */
+function db_upgrade($version, $fromdir = "") {
+ global $CONFIG;
+
+ // Elgg and its database must be installed to upgrade it!
+ if (!is_db_installed() || !is_installed()) {
+ return false;
+ }
+
+ $version = (int) $version;
+
+ if (!$fromdir) {
+ $fromdir = $CONFIG->path . 'engine/schema/upgrades/';
+ }
+
+ if ($handle = opendir($fromdir)) {
+ $sqlupgrades = array();
+
+ while ($sqlfile = readdir($handle)) {
+ if (!is_dir($fromdir . $sqlfile)) {
+ if (preg_match('/([0-9]*)\.sql/',$sqlfile,$matches)) {
+ $sql_version = (int) $matches[1];
+ if ($sql_version > $version) {
+ $sqlupgrades[] = $sqlfile;
+ }
+ }
+ }
+ }
+
+ asort($sqlupgrades);
+
+ if (sizeof($sqlupgrades) > 0) {
+ foreach($sqlupgrades as $sqlfile) {
+ try {
+ run_sql_script($fromdir . $sqlfile);
+ } catch (DatabaseException $e) {
+ error_log($e->getmessage());
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+ * This function, called by validate_platform(), will check whether the installed version of
+ * MySQL meets the minimum required.
+ *
+ * TODO: If multiple dbs are supported check which db is supported and use the appropriate code to validate
+ * the appropriate version.
+ *
+ * @return bool
+ */
+function db_check_version() {
+ $version = mysql_get_server_info();
+ $points = explode('.', $version);
+
+ if ($points[0] < 5) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Sanitise a string for database use, but with the option of escaping extra characters.
+ */
+function sanitise_string_special($string, $extra_escapeable = '') {
+ $string = sanitise_string($string);
+
+ for ($n = 0; $n < strlen($extra_escapeable); $n++) {
+ $string = str_replace($extra_escapeable[$n], "\\" . $extra_escapeable[$n], $string);
+ }
+
+ return $string;
+}
+
+/**
+ * Sanitise a string for database use
+ *
+ * @param string $string The string to sanitise
+ * @return string Sanitised string
+ */
+function sanitise_string($string) {
+ // @todo does this really need the trim?
+ // there are times when you might want trailing / preceeding white space.
+ return mysql_real_escape_string(trim($string));
+}
+
+/**
+ * Wrapper function for alternate English spelling
+ *
+ * @param string $string The string to sanitise
+ * @return string Sanitised string
+ * @uses sanitise_string
+ */
+function sanitize_string($string) {
+ return sanitise_string($string);
+}
+
+/**
+ * Sanitises an integer for database use
+ *
+ * @param int $int
+ * @return int Sanitised integer
+ */
+function sanitise_int($int) {
+ return (int) $int;
+}
+
+/**
+ * Wrapper function for alternate English spelling
+ *
+ * @param int $int
+ * @return int Sanitised integer
+ * @uses sanitise_string
+ */
+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