Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.456 diff -u -r1.456 common.inc --- includes/common.inc 22 Jun 2005 20:19:57 -0000 1.456 +++ includes/common.inc 23 Jun 2005 18:44:00 -0000 @@ -24,6 +24,13 @@ */ define('SAVED_DELETED', 3); +define('TYPE', 1); +define('TITLE', 2); +define('VALUE', 3); +define('DEFAULT', 4); +define('WEIGHT', 5); + + /** * Set the breadcrumb trail for the current page. * Index: includes/database.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.inc,v retrieving revision 1.41 diff -u -r1.41 database.inc --- includes/database.inc 22 Jun 2005 20:19:58 -0000 1.41 +++ includes/database.inc 23 Jun 2005 18:44:00 -0000 @@ -89,27 +89,34 @@ * Drupal's configuration file. If this name is not defined, a duplicate of the * default connection is made instead. * - * Be sure to change the connection back to the default when done with custom - * code. + * Due to the advanced nature of this function, it is recommended to use a custom + * error handler when switching to a database that does not have a drupal install. + * This is because the default drupal error handler inserts errors into the database + * via the watchdog() function, and the required tables might not be present. + * + * Be sure to change the connection, and the custom error handler, back to the default + * settings when done with the custom connection. * * @param $name * The name assigned to the newly active database connection. If omitted, the * default connection will be made active. */ function db_set_active($name = 'default') { - global $db_url, $db_type, $active_db; + global $db_url, $db_type, $active_db, $active_db_name; static $db_conns; + if (is_array($db_url)) { + $connect_url = array_key_exists($name, $db_url) ? $db_url[$name] : $db_url['default']; + } + else { + $connect_url = $db_url; + } + + $db_type = substr($connect_url, 0, strpos($connect_url, '://')); + $active_db_name = $name; + if (!isset($db_conns[$name])) { // Initiate a new connection, using the named DB URL specified. - if (is_array($db_url)) { - $connect_url = array_key_exists($name, $db_url) ? $db_url[$name] : $db_url['default']; - } - else { - $connect_url = $db_url; - } - - $db_type = substr($connect_url, 0, strpos($connect_url, '://')); $handler = "includes/database.$db_type.inc"; if (is_file($handler)) { @@ -122,10 +129,39 @@ $db_conns[$name] = db_connect($connect_url); } + // Set the active connection. $active_db = $db_conns[$name]; } + +/** + * Acts as a redirection layer to execute a db api function for a database type. + * + * Allows the use of multiple databases (such as Postgres and MySQL) from within + * the same site by executing the database api function for the currently active + * database type. + * + * @param $function + * The database api function to execute. + * @param ... + * The arguments to pass to the database api function. + * + * @return + * The data returned from the relevant function. + */ +function db_invoke($function) { + global $db_type; + + $args = func_get_args(); + $function = array_shift($args); + + if (function_exists('db_'. $db_type . '_' . $function)){ + // call Drupal function + return call_user_func_array('db_'. $db_type . '_' . $function, $args); + } +} + /** * Runs a basic query in the active database. * @@ -153,7 +189,8 @@ $args[0] = $query; $query = call_user_func_array('sprintf', $args); } - return _db_query($query); + + return db_invoke('query', $query); } /** @@ -172,7 +209,153 @@ $args[0] = $query; $query = call_user_func_array('sprintf', $args); } - return _db_query($query, 1); + return db_invoke('query', $query, 1); +} + +/** + * Initialize a database connection. + */ +function db_connect($url) { + return db_invoke('connect', $url); +} + +/** + * Fetch one result row from the previous query as an object. + * + * @param $result + * A database query result resource, as returned from db_query(). + * @return + * An object representing the next row of the result. The attributes of this + * object are the table fields selected by the query. + */ +function db_fetch_object($result) { + return db_invoke('fetch_object', $result); +} + +/** + * Fetch one result row from the previous query as an array. + * + * @param $result + * A database query result resource, as returned from db_query(). + * @return + * An associative array representing the next row of the result. The keys of + * this object are the names of the table fields selected by the query, and + * the values are the field values for this result row. + */ +function db_fetch_array($result) { + return db_invoke('fetch_array', $result); +} + +/** + * Determine how many result rows were found by the preceding query. + * + * @param $result + * A database query result resource, as returned from db_query(). + * @return + * The number of result rows. + */ +function db_num_rows($result) { + return db_invoke('num_rows', $result); +} + +/** + * Return an individual result field from the previous query. + * + * Only use this function if exactly one field is being selected; otherwise, + * use db_fetch_object() or db_fetch_array(). + * + * @param $result + * A database query result resource, as returned from db_query(). + * @param $row + * The index of the row whose result is needed. + * @return + * The resulting field. + */ +function db_result($result, $row = 0) { + return db_invoke('result', $result, $row); +} + +/** + * Determine whether the previous query caused an error. + */ +function db_error() { + return db_invoke('errno'); +} + +/** + * Return a new unique ID in the given sequence. + * + * For compatibility reasons, Drupal does not use auto-numbered fields in its + * database tables. Instead, this function is used to return a new unique ID + * of the type requested. If necessary, a new sequence with the given name + * will be created. + */ +function db_next_id($name) { + return db_invoke('next_id', $name); +} + +/** + * Determine the number of rows changed by the preceding query. + */ +function db_affected_rows() { + return db_invoke('affected_rows'); +} + +/** + * Runs a limited-range query in the active database. + * + * Use this as a substitute for db_query() when a subset of the query is to be + * returned. + * User-supplied arguments to the query should be passed in as separate parameters + * so that they can be properly escaped to avoid SQL injection attacks. + * + * @param $query + * A string containing an SQL query. + * @param ... + * A variable number of arguments which are substituted into the query using + * printf() syntax. + * @param $from + * The first result row to return. + * @param $count + * The maximum number of result rows to return. + * @return + * A database query result resource, or FALSE if the query was not executed + * correctly. + */ +function db_query_range($query) { + $args = func_get_args(); + return call_user_func_array('db_invoke', array_merge(array('query_range'), $args)); +} + +/** + * Returns a properly formatted Binary Large OBject value. + * + * @param $data + * Data to encode. + * @return + * Encoded data. + */ +function db_encode_blob($data) { + return db_invoke('encode_blob', $data); +} + +/** + * Returns text from a Binary Large OBject value. + * + * @param $data + * Data to decode. + * @return + * Decoded data. + */ +function db_decode_blob($data) { + return db_invoke('decode_blob', $data); +} + +/** + * Prepare user input for use in a database query, preventing SQL injection attacks. + */ +function db_escape_string($text) { + return db_invoke('escape_string', $text); } /** Index: includes/database.mysql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.mysql.inc,v retrieving revision 1.31 diff -u -r1.31 database.mysql.inc --- includes/database.mysql.inc 22 Jun 2005 20:19:58 -0000 1.31 +++ includes/database.mysql.inc 23 Jun 2005 18:44:00 -0000 @@ -20,7 +20,7 @@ * performance, however, when the overhead to connect to your database is high * (e.g. your database and web server live on different machines). */ -function db_connect($url) { +function db_mysql_connect($url) { $url = parse_url($url); // Allow for non-standard MySQL port. @@ -44,7 +44,7 @@ /** * Helper function for db_query(). */ -function _db_query($query, $debug = 0) { +function db_mysql_query($query, $debug = 0) { global $active_db; global $queries; static $dev_query; @@ -88,7 +88,7 @@ * An object representing the next row of the result. The attributes of this * object are the table fields selected by the query. */ -function db_fetch_object($result) { +function db_mysql_fetch_object($result) { if ($result) { return mysql_fetch_object($result); } @@ -104,7 +104,7 @@ * this object are the names of the table fields selected by the query, and * the values are the field values for this result row. */ -function db_fetch_array($result) { +function db_mysql_fetch_array($result) { if ($result) { return mysql_fetch_array($result, MYSQL_ASSOC); } @@ -118,7 +118,7 @@ * @return * The number of result rows. */ -function db_num_rows($result) { +function db_mysql_num_rows($result) { if ($result) { return mysql_num_rows($result); } @@ -137,7 +137,7 @@ * @return * The resulting field. */ -function db_result($result, $row = 0) { +function db_mysql_result($result, $row = 0) { if ($result && mysql_num_rows($result) > $row) { return mysql_result($result, $row); } @@ -146,7 +146,7 @@ /** * Determine whether the previous query caused an error. */ -function db_error() { +function db_mysql_error() { return mysql_errno(); } @@ -158,7 +158,7 @@ * of the type requested. If necessary, a new sequence with the given name * will be created. */ -function db_next_id($name) { +function db_mysql_next_id($name) { $name = db_prefix_tables($name); db_query('LOCK TABLES {sequences} WRITE'); $id = db_result(db_query("SELECT id FROM {sequences} WHERE name = '%s'", $name)) + 1; @@ -171,7 +171,7 @@ /** * Determine the number of rows changed by the preceding query. */ -function db_affected_rows() { +function db_mysql_affected_rows() { return mysql_affected_rows(); } @@ -197,7 +197,7 @@ * A database query result resource, or FALSE if the query was not executed * correctly. */ -function db_query_range($query) { +function db_mysql_query_range($query) { $args = func_get_args(); $count = array_pop($args); $from = array_pop($args); @@ -213,7 +213,7 @@ $query = call_user_func_array('sprintf', $args); } $query .= ' LIMIT '. $from .', '. $count; - return _db_query($query); + return db_query($query); } /** @@ -224,7 +224,7 @@ * @return * Encoded data. */ -function db_encode_blob($data) { +function db_mysql_encode_blob($data) { return $data; } @@ -236,14 +236,14 @@ * @return * Decoded data. */ -function db_decode_blob($data) { +function db_mysql_decode_blob($data) { return $data; } /** * Prepare user input for use in a database query, preventing SQL injection attacks. */ -function db_escape_string($text) { +function db_mysql_escape_string($text) { return addslashes($text); } Index: includes/database.pgsql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.pgsql.inc,v retrieving revision 1.9 diff -u -r1.9 database.pgsql.inc --- includes/database.pgsql.inc 22 Jun 2005 20:19:58 -0000 1.9 +++ includes/database.pgsql.inc 23 Jun 2005 18:44:01 -0000 @@ -20,7 +20,7 @@ * performance, however, when the overhead to connect to your database is high * (e.g. your database and web server live on different machines). */ -function db_connect($url) { +function db_pgsql_connect($url) { $url = parse_url($url); $conn_string = ' user='. $url['user'] .' dbname='. substr($url['path'], 1) .' password='. $url['pass'] . ' host=' . $url['host']; @@ -33,7 +33,7 @@ /** * Helper function for db_query(). */ -function _db_query($query, $debug = 0) { +function db_pgsql_query($query, $debug = 0) { global $active_db, $last_result; global $queries; static $dev_query; @@ -77,7 +77,7 @@ * An object representing the next row of the result. The attributes of this * object are the table fields selected by the query. */ -function db_fetch_object($result) { +function db_pgsql_fetch_object($result) { if ($result) { return pg_fetch_object($result); } @@ -93,7 +93,7 @@ * this object are the names of the table fields selected by the query, and * the values are the field values for this result row. */ -function db_fetch_array($result) { +function db_pgsql_fetch_array($result) { if ($result) { return pg_fetch_assoc($result); } @@ -107,7 +107,7 @@ * @return * The number of result rows. */ -function db_num_rows($result) { +function db_pgsql_num_rows($result) { if ($result) { return pg_num_rows($result); } @@ -126,7 +126,7 @@ * @return * The resulting field. */ -function db_result($result, $row = 0) { +function db_pgsql_result($result, $row = 0) { if ($result && pg_num_rows($result) > $row) { $res = pg_fetch_row($result, $row); @@ -137,7 +137,7 @@ /** * Determine whether the previous query caused an error. */ -function db_error() { +function db_pgsql_error() { return pg_last_error(); } @@ -149,7 +149,7 @@ * of the type requested. If necessary, a new sequence with the given name * will be created. */ -function db_next_id($name) { +function db_pgsql_next_id($name) { $id = db_result(db_query("SELECT nextval('%s_seq')", db_prefix_tables($name))); return $id; } @@ -157,7 +157,7 @@ /** * Determine the number of rows changed by the preceding query. */ -function db_affected_rows() { +function db_pgsql_affected_rows() { global $last_result; return pg_affected_rows($last_result); } @@ -184,7 +184,7 @@ * A database query result resource, or FALSE if the query was not executed * correctly. */ -function db_query_range($query) { +function db_pgsql_query_range($query) { $args = func_get_args(); $count = array_pop($args); $from = array_pop($args); @@ -200,7 +200,7 @@ $query = call_user_func_array('sprintf', $args); } $query .= ' LIMIT '. $count .' OFFSET '. $from; - return _db_query($query); + return db_query($query); } /** @@ -211,7 +211,7 @@ * @return * Encoded data. */ -function db_encode_blob($data) { +function db_pgsql_encode_blob($data) { return addcslashes($data, "\0..\37\\"); } @@ -223,7 +223,7 @@ * @return * Decoded data. */ -function db_decode_blob($data) { +function db_pgsql_decode_blob($data) { return stripcslashes($data); } @@ -231,7 +231,7 @@ * Prepare user input for use in a database query, preventing SQL injection attacks. * Note: This function requires PostgreSQL 7.2 or later. */ -function db_escape_string($text) { +function db_pgsql_escape_string($text) { return pg_escape_string($text); }