? sites/default/files Index: INSTALL.oracle.txt =================================================================== RCS file: INSTALL.oracle.txt diff -N INSTALL.oracle.txt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ INSTALL.oracle.txt 16 Jan 2008 15:38:09 -0000 @@ -0,0 +1,71 @@ +// $Id: INSTALL.oracle.txt,v 1.1 2007/12/09 17:45:21 hswong3i Exp $ + +CREATE THE Oracle DATABASE +-------------------------- + +This file describes how to create a Oracle database for Drupal. + +If you control your databases through a web-based control panel, +check its documentation, as the following instructions are for the +command line only. + +This step is only necessary if you don't already have a database +set-up (e.g. by your host). In the following examples, 'dba_user' is +an example Oracle user which has the CREATE and GRANT privileges. Use +the appropriate user name for your system. + +Optionally, you can create a new tablespace for your Drupal site +datebase. Log into sqlplus by following command: + + sqlplus dba_user + +sqlplus will prompt for the 'dba_user' database password. At the +sqlplus prompt, enter following command: + + CREATE TABLESPACE tablespace_name + DATAFILE 'file_directory_path' + SIZE filesize AUTOEXTEND ON NEXT extend_size; + +where + + 'tablespace_name' is the name of you new tablespace + 'file_directory_path' is the file location in database server + 'filesize' is the initial file size, e.g. 50K, 1000M. + 'extend_size' is the volumn for extension when data file is full + +First, you must create a new user for your Drupal site. At the +sqlplus prompt, enter the following command: + + CREATE USER username + IDENTIFIED BY "password"; + DEFAULT TABLESPACE tablespace_name; + GRANT CONNECT, RESOURCE TO username; + +where + + 'tablespace_name' is the name of you tablespace + 'username' is the username of your Oracle account + 'password' is the password required for that username + + Note: Unless your database user has all of the privileges listed + above, you will not be able to run Drupal. + +Oracle SPECIAL REQUIREMENTS +--------------------------- + +1. SYSTEM REQUIREMENT + + Oracle driver for Drupal is fully tested with below softwares: + Oracle Database 10g Release 2 (10.2.0.1.0) for Linux x86, + Zend Core for Oracle v.2 Linux x86, + Zend Framework 1.0.0, + PHP Version 5.2.3, + Apache 2.2.3 (Debian) + + You may use something newer than above, but there is no guarantee for + backward compatible. + +2. TABLE PREFIX LIMITATION + + Table prefix are limited in maximum 12 characters. Proved by testing, it + is suggested to use table prefix within 10 characters. Index: INSTALL.pgsql.txt =================================================================== RCS file: INSTALL.pgsql.txt diff -N INSTALL.pgsql.txt --- INSTALL.pgsql.txt 26 Nov 2007 16:36:42 -0000 1.7 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,28 +0,0 @@ -// $Id: INSTALL.pgsql.txt,v 1.7 2007/11/26 16:36:42 dries Exp $ - -CREATE THE PostgreSQL DATABASE ------------------------------- - -Note that the database must be created with UTF-8 (Unicode) encoding. - -1. CREATE DATABASE USER - - This step is only necessary if you don't already have a user set up (e.g. - by your host) or you want to create new user for use with Drupal only. The - following command creates a new user named "username" and asks for a - password for that user: - - createuser --pwprompt --encrypted --no-adduser --no-createdb username - - If everything works correctly, you'll see a "CREATE USER" notice. - -2. CREATE THE DRUPAL DATABASE - - This step is only necessary if you don't already have a database set up (e.g. - by your host) or you want to create new database for use with Drupal only. - The following command creates a new database named "databasename", which is - owned by previously created "username": - - createdb --encoding=UNICODE --owner=username databasename - - If everything works correctly, you'll see a "CREATE DATABASE" notice. Index: INSTALL.postgresql.txt =================================================================== RCS file: INSTALL.postgresql.txt diff -N INSTALL.postgresql.txt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ INSTALL.postgresql.txt 16 Jan 2008 15:38:09 -0000 @@ -0,0 +1,28 @@ +// $Id: INSTALL.postgresql.txt,v 1.1 2007/12/09 17:45:21 hswong3i Exp $ + +CREATE THE PostgreSQL DATABASE +------------------------------ + +Note that the database must be created with UTF-8 (Unicode) encoding. + +1. CREATE DATABASE USER + + This step is only necessary if you don't already have a user set up (e.g. + by your host) or you want to create new user for use with Drupal only. The + following command creates a new user named "username" and asks for a + password for that user: + + createuser --pwprompt --encrypted --no-adduser --no-createdb username + + If everything works correctly, you'll see a "CREATE USER" notice. + +2. CREATE THE DRUPAL DATABASE + + This step is only necessary if you don't already have a database set up (e.g. + by your host) or you want to create new database for use with Drupal only. + The following command creates a new database named "databasename", which is + owned by previously created "username": + + createdb --encoding=UNICODE --owner=username databasename + + If everything works correctly, you'll see a "CREATE DATABASE" notice. Index: MAINTAINERS.siren.txt =================================================================== RCS file: MAINTAINERS.siren.txt diff -N MAINTAINERS.siren.txt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ MAINTAINERS.siren.txt 16 Jan 2008 15:38:09 -0000 @@ -0,0 +1,24 @@ +// $Id$ + +List of maintainers +-------------------------------------------------------------------------------- + +LEGEND +====== + +- M: the maintainer +- S: status: + "supported" : someone is actually paid to look after this. + "maintained" : someone actually looks after it. + "fixes/patches" : it has a maintainer but they don't have time to + do much other than throw the odd patch in. + "orphan" : no current maintainer, but maybe you could take + the role as you write new code? +- W: website with status or information + +-------------------------------------------------------------------------------- + +Siren +M: Edison Wong +S: maintained +W: http://edin.no-ip.com/project/siren/ Index: README.siren.txt =================================================================== RCS file: README.siren.txt diff -N README.siren.txt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ README.siren.txt 16 Jan 2008 15:38:09 -0000 @@ -0,0 +1,60 @@ +// $Id$ + +WHAT IS SIREN? +-------------- + +This is my personal project besides Drupal, which try to research the +possibility of other database supporting for Drupal, e.g. Oracle, IBM DB2, +MSSQL, SQLite, etc; on the other hand, I will provide unofficial database +supporting during Drupal-6.x life cycle, and further more contribute the +research progress for Drupal-7.x. + +For more information on Siren visit +the Siren project homepage at http://edin.no-ip.com/project/siren/ + +CURRENT RESEARCH PROGRESS +------------------------- + +Besides official Drupal-6.x mysql, mysqli and pgsql, Siren also provide +pdo_mysql, pdo_pgsql and oci8 database driver supporting. According to the +needs of PDO and Oracle drivers implementation, ALL core queries and some +APIs are hacked for compatibility concern. + +3rd PARTY MODULE HACK HOWTO +--------------------------- + +Based on cross database compatibility concern, Siren come with lots of core +queries hack. Most works are done for you, and it should run across +MySQl/PgSQL/Oracle without any critical problem. + +Anyway, you will also need to apply some 3rd party module. So how to let them +work together with this unofficial core? + +1. ENCLOSE ALL TABLE/COLUMN/CONSTRAINT NAME WITH [] + + Go though you target module, and enclose all table/column/constraint name + with [] syntax, which similar as {} syntax for all table. + + This can be helped by using VI + regex: /{[A-Za-z0-9_]*} + +2. REPLACE ALL '%s' SYNTAX WITH %s + + This is very important for unofficial PDO supporting. + + This can be helped by using VI + regex: :%s/'%s'/%s/gc + +3. REMOVE ANY %% SYNTAX + + PDO don't allow inline % syntax when using with ? placeholder. + + This can be helped by using VI + regex: /%% + +4. UTILIZE ALL DB_* ABSTRACTION IF POSSIBLE + + These abstraction are mainly duel with syntax different among different DB. + +5. USE %s EVEN IT IS AN EMPTY STRING + + Using empty string as placeholder will cause problem among Oracle and + MSSQL. Escape it by using %s. Oracle and MSSQL driver will able to catch + them and replace it as required empty string placeholder internally. Index: UPGRADE.siren.txt =================================================================== RCS file: UPGRADE.siren.txt diff -N UPGRADE.siren.txt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ UPGRADE.siren.txt 16 Jan 2008 15:38:09 -0000 @@ -0,0 +1,12 @@ +// $Id$ + +UPGRADING FOR SIREN +------------------- + +As a flash new research project, Siren 1.x remove the direct upgrade handling +from Drupal 5.x. You should always use Siren for flash install. + +On the other hand, you may first upgrade your site from Drupal 5.x to +Drupal 6.x, and handle the convert from Drupal 6.x to Siren 1.x manually. +There is no guarantee about this handling, and please backup and do this with +your own risk. Index: install.php =================================================================== RCS file: /cvs/drupal/drupal/install.php,v retrieving revision 1.112 diff -u -p -r1.112 install.php --- install.php 7 Jan 2008 19:43:28 -0000 1.112 +++ install.php 16 Jan 2008 15:38:10 -0000 @@ -136,7 +136,7 @@ function install_main() { */ function install_verify_drupal() { // Read the variable manually using the @ so we don't trigger an error if it fails. - $result = @db_query("SELECT value FROM {variable} WHERE name = '%s'", 'install_task'); + $result = @db_query("SELECT [value] FROM [{variable}] WHERE [name] = %s", 'install_task'); if ($result) { return unserialize(db_result($result)); } @@ -189,7 +189,7 @@ function install_change_settings($profil include_once './includes/form.inc'; install_task_list('database'); - if ($db_url == 'mysql://username:password@localhost/databasename') { + if ($db_url == 'drupal://username:password@localhost/databasename#mysql') { $db_user = $db_pass = $db_path = ''; } elseif (!empty($db_url)) { @@ -217,6 +217,15 @@ function install_settings_form(&$form_st if (isset($db_types['mysqli'])) { unset($db_types['mysql']); } + // If both 'mysqli' and 'pdo_mysql' are available, we disable 'mysqli': + if (isset($db_types['pdo_mysql'])) { + unset($db_types['mysqli']); + } + + // If both 'pgsql' and 'pdo_pgsql' are available, we disable 'pgsql': + if (isset($db_types['pdo_pgsql'])) { + unset($db_types['pgsql']); + } if (count($db_types) == 0) { $form['no_db_types'] = array( @@ -362,7 +371,8 @@ function _install_settings_form_validate // Check database type if (!isset($form)) { $_db_url = is_array($db_url) ? $db_url['default'] : $db_url; - $db_type = substr($_db_url, 0, strpos($_db_url, '://')); + $_db_url = parse_url($_db_url); + $db_type = $_db_url['fragment']; } $databases = drupal_detect_database_types(); if (!in_array($db_type, $databases)) { @@ -370,7 +380,7 @@ function _install_settings_form_validate } else { // Verify - $db_url = $db_type .'://'. urlencode($db_user) . ($db_pass ? ':'. urlencode($db_pass) : '') .'@'. ($db_host ? urlencode($db_host) : 'localhost') . ($db_port ? ":$db_port" : '') .'/'. urlencode($db_path); + $db_url = 'drupal://'. urlencode($db_user) . ($db_pass ? ':'. urlencode($db_pass) : '') .'@'. ($db_host ? urlencode($db_host) : 'localhost') . ($db_port ? ":$db_port" : '') .'/'. urlencode($db_path) .'#'. $db_type; if (isset($form)) { form_set_value($form['_db_url'], $db_url, $form_state); } Index: update.php =================================================================== RCS file: /cvs/drupal/drupal/update.php,v retrieving revision 1.247 diff -u -p -r1.247 update.php --- update.php 7 Jan 2008 19:43:28 -0000 1.247 +++ update.php 16 Jan 2008 15:38:10 -0000 @@ -55,26 +55,26 @@ function db_add_column(&$ret, $table, $c if (array_key_exists('default', $attributes)) { if (is_null($attributes['default'])) { $default_val = 'NULL'; - $default = 'default NULL'; + $default = 'DEFAULT NULL'; } elseif ($attributes['default'] === FALSE) { $default = ''; } else { - $default_val = "$attributes[default]"; - $default = "default $attributes[default]"; + $default_val = $attributes['default']; + $default = "DEFAULT ". $attributes['default']; } } - $ret[] = update_sql("ALTER TABLE {". $table ."} ADD $column $type"); + $ret[] = update_sql("ALTER TABLE [{". $table ."}] ADD [$column] $type"); if (!empty($default)) { - $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $column SET $default"); + $ret[] = update_sql("ALTER TABLE [{". $table ."}] ALTER [$column] SET $default"); } if (!empty($not_null)) { if (!empty($default)) { - $ret[] = update_sql("UPDATE {". $table ."} SET $column = $default_val"); + $ret[] = update_sql("UPDATE [{". $table ."}] SET [$column] = $default_val"); } - $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $column SET NOT NULL"); + $ret[] = update_sql("ALTER TABLE [{". $table ."}] ALTER [$column] SET NOT NULL"); } } @@ -111,23 +111,23 @@ function db_change_column(&$ret, $table, if (array_key_exists('default', $attributes)) { if (is_null($attributes['default'])) { $default_val = 'NULL'; - $default = 'default NULL'; + $default = 'DEFAULT NULL'; } elseif ($attributes['default'] === FALSE) { $default = ''; } else { - $default_val = "$attributes[default]"; - $default = "default $attributes[default]"; + $default_val = $attributes['default']; + $default = "DEFAULT ". $attributes['default']; } } - $ret[] = update_sql("ALTER TABLE {". $table ."} RENAME $column TO ". $column ."_old"); - $ret[] = update_sql("ALTER TABLE {". $table ."} ADD $column_new $type"); - $ret[] = update_sql("UPDATE {". $table ."} SET $column_new = ". $column ."_old"); - if ($default) { $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $column_new SET $default"); } - if ($not_null) { $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $column_new SET NOT NULL"); } - $ret[] = update_sql("ALTER TABLE {". $table ."} DROP ". $column ."_old"); + $ret[] = update_sql("ALTER TABLE [{". $table ."}] RENAME [$column] TO [". $column ."_old]"); + $ret[] = update_sql("ALTER TABLE [{". $table ."}] ADD [$column_new] $type"); + $ret[] = update_sql("UPDATE [{". $table ."}] SET [$column_new] = [". $column ."_old]"); + if ($default) { $ret[] = update_sql("ALTER TABLE [{". $table ."}] ALTER [$column_new] SET $default"); } + if ($not_null) { $ret[] = update_sql("ALTER TABLE [{". $table ."}] ALTER [$column_new] SET NOT NULL"); } + $ret[] = update_sql("ALTER TABLE [{". $table ."}] DROP [". $column ."_old]"); } /** @@ -406,14 +406,14 @@ function update_create_batch_table() { function update_fix_compatibility() { $ret = array(); $incompatible = array(); - $query = db_query("SELECT name, type, status FROM {system} WHERE status = 1 AND type IN ('module','theme')"); + $query = db_query("SELECT [name], [type], [status] FROM [{system}] WHERE [status] = 1 AND [type] IN ('module', 'theme')"); while ($result = db_fetch_object($query)) { if (update_check_incompatibility($result->name, $result->type)) { $incompatible[] = $result->name; } } if (!empty($incompatible)) { - $ret[] = update_sql("UPDATE {system} SET status = 0 WHERE name IN ('". implode("','", $incompatible) ."')"); + $ret[] = update_sql("UPDATE [{system}] SET [status] = 0 WHERE [name] IN ('". implode("', '", $incompatible) ."')"); } return $ret; } Index: includes/actions.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/actions.inc,v retrieving revision 1.8 diff -u -p -r1.8 actions.inc --- includes/actions.inc 31 Dec 2007 14:51:04 -0000 1.8 +++ includes/actions.inc 16 Jan 2008 15:38:10 -0000 @@ -54,7 +54,7 @@ function actions_do($action_ids, &$objec $where_values = array(); foreach ($action_ids as $action_id) { if (is_numeric($action_id)) { - $where[] = 'OR aid = %d'; + $where[] = 'OR [aid] = %d'; $where_values[] = $action_id; } elseif (isset($available_actions[$action_id])) { @@ -68,7 +68,7 @@ function actions_do($action_ids, &$objec $where_clause = implode(' ', $where); // Strip off leading 'OR '. $where_clause = '('. strstr($where_clause, " ") .')'; - $result_db = db_query('SELECT * FROM {actions} WHERE '. $where_clause, $where_values); + $result_db = db_query('SELECT * FROM [{actions}] WHERE '. $where_clause, $where_values); while ($action = db_fetch_object($result_db)) { $actions[$action->aid] = $action->parameters ? unserialize($action->parameters) : array(); $actions[$action->aid]['callback'] = $action->callback; @@ -93,7 +93,7 @@ function actions_do($action_ids, &$objec else { // If it's a configurable action, retrieve stored parameters. if (is_numeric($action_ids)) { - $action = db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = %d", $action_ids)); + $action = db_fetch_object(db_query("SELECT * FROM [{actions}] WHERE [aid] = %d", $action_ids)); $function = $action->callback; $context = array_merge($context, unserialize($action->parameters)); $result[$action_ids] = $function($object, $context, $a1, $a2); @@ -177,7 +177,7 @@ function actions_list($reset = FALSE) { */ function actions_get_all_actions() { $actions = array(); - $result = db_query("SELECT * FROM {actions}"); + $result = db_query("SELECT * FROM [{actions}]"); while ($action = db_fetch_object($result)) { $actions[$action->aid] = array( 'callback' => $action->callback, @@ -238,7 +238,7 @@ function actions_function_lookup($hash) } // Must be an instance; must check database. - $aid = db_result(db_query("SELECT aid FROM {actions} WHERE MD5(aid) = '%s' AND parameters != ''", $hash)); + $aid = db_result(db_query("SELECT [aid] FROM [{actions}] WHERE MD5([aid]) = %s AND [parameters] != %s", $hash, '')); return $aid; } @@ -255,7 +255,7 @@ function actions_synchronize($actions_in $actions_in_code = actions_list(); } $actions_in_db = array(); - $result = db_query("SELECT * FROM {actions} WHERE parameters = ''"); + $result = db_query("SELECT * FROM [{actions}] WHERE [parameters] = %s", ''); while ($action = db_fetch_object($result)) { $actions_in_db[$action->callback] = array('aid' => $action->aid, 'description' => $action->description); } @@ -271,7 +271,7 @@ function actions_synchronize($actions_in } else { // This is a new singleton that we don't have an aid for; assign one. - db_query("INSERT INTO {actions} (aid, type, callback, parameters, description) VALUES ('%s', '%s', '%s', '%s', '%s')", $callback, $array['type'], $callback, '', $array['description']); + db_query("INSERT INTO [{actions}] ([aid], [type], [callback], [parameters], [description]) VALUES (%s, %s, %s, %s, %s)", $callback, $array['type'], $callback, '', $array['description']); watchdog('actions', "Action '%action' added.", array('%action' => filter_xss_admin($array['description']))); } } @@ -284,14 +284,14 @@ function actions_synchronize($actions_in foreach ($actions_in_db as $callback => $array) { $orphaned[] = $callback; - $placeholder[] = "'%s'"; + $placeholder[] = "%s"; } $orphans = implode(', ', $orphaned); if ($delete_orphans) { $placeholders = implode(', ', $placeholder); - $results = db_query("SELECT a.aid, a.description FROM {actions} a WHERE callback IN ($placeholders)", $orphaned); + $results = db_query("SELECT a.[aid], a.[description] FROM [{actions}] a WHERE [callback] IN ($placeholders)", $orphaned); while ($action = db_fetch_object($results)) { actions_delete($action->aid); watchdog('actions', "Removed orphaned action '%action' from database.", array('%action' => filter_xss_admin($action->description))); @@ -325,15 +325,15 @@ function actions_synchronize($actions_in function actions_save($function, $type, $params, $desc, $aid = NULL) { $serialized = serialize($params); if ($aid) { - db_query("UPDATE {actions} SET callback = '%s', type = '%s', parameters = '%s', description = '%s' WHERE aid = %d", $function, $type, $serialized, $desc, $aid); + db_query("UPDATE [{actions}] SET [callback] = %s, [type] = %s, [parameters] = %s, [description] = %s WHERE [aid] = %d", $function, $type, $serialized, $desc, $aid); watchdog('actions', 'Action %action saved.', array('%action' => $desc)); } else { // aid is the callback for singleton actions so we need to keep a // separate table for numeric aids. - db_query('INSERT INTO {actions_aid} VALUES (default)'); + db_query('INSERT INTO [{actions_aid}] VALUES (default)'); $aid = db_last_insert_id('actions_aid', 'aid'); - db_query("INSERT INTO {actions} (aid, callback, type, parameters, description) VALUES (%d, '%s', '%s', '%s', '%s')", $aid, $function, $type, $serialized, $desc); + db_query("INSERT INTO [{actions}] ([aid], [callback], [type], [parameters], [description]) VALUES (%d, %s, %s, %s, %s)", $aid, $function, $type, $serialized, $desc); watchdog('actions', 'Action %action created.', array('%action' => $desc)); } @@ -350,7 +350,7 @@ function actions_save($function, $type, * The appropriate action row from the database as an object. */ function actions_load($aid) { - return db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = %d", $aid)); + return db_fetch_object(db_query("SELECT * FROM [{actions}] WHERE [aid] = %d", $aid)); } /** @@ -360,6 +360,6 @@ function actions_load($aid) { * integer The ID of the action to delete. */ function actions_delete($aid) { - db_query("DELETE FROM {actions} WHERE aid = %d", $aid); + db_query("DELETE FROM [{actions}] WHERE [aid] = %d", $aid); module_invoke_all('actions_delete', $aid); } Index: includes/batch.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/batch.inc,v retrieving revision 1.14 diff -u -p -r1.14 batch.inc --- includes/batch.inc 20 Dec 2007 11:57:20 -0000 1.14 +++ includes/batch.inc 16 Jan 2008 15:38:10 -0000 @@ -12,7 +12,7 @@ function _batch_page() { $batch =& batch_get(); // Retrieve the current state of batch from db. - if (isset($_REQUEST['id']) && $data = db_result(db_query("SELECT batch FROM {batch} WHERE bid = %d AND token = '%s'", $_REQUEST['id'], drupal_get_token($_REQUEST['id'])))) { + if (isset($_REQUEST['id']) && $data = db_result(db_query("SELECT [batch] FROM [{batch}] WHERE [bid] = %d AND [token] = %s", $_REQUEST['id'], drupal_get_token($_REQUEST['id'])))) { $batch = unserialize($data); } else { @@ -305,7 +305,7 @@ function _batch_finished() { // Cleanup the batch table and unset the global $batch variable. if ($batch['progressive']) { - db_query("DELETE FROM {batch} WHERE bid = %d", $batch['id']); + db_query("DELETE FROM [{batch}] WHERE [bid] = %d", $batch['id']); } $_batch = $batch; $batch = NULL; @@ -349,6 +349,6 @@ function _batch_finished() { */ function _batch_shutdown() { if ($batch = batch_get()) { - db_query("UPDATE {batch} SET batch = '%s' WHERE bid = %d", serialize($batch), $batch['id']); + db_query("UPDATE [{batch}] SET [batch] = %s WHERE [bid] = %d", serialize($batch), $batch['id']); } } Index: includes/bootstrap.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v retrieving revision 1.206 diff -u -p -r1.206 bootstrap.inc --- includes/bootstrap.inc 10 Jan 2008 22:47:17 -0000 1.206 +++ includes/bootstrap.inc 16 Jan 2008 15:38:10 -0000 @@ -384,7 +384,7 @@ function drupal_get_filename($type, $nam // the database. This is required because this function is called both // before we have a database connection (i.e. during installation) and // when a database connection fails. - elseif (db_is_active() && (($file = db_result(db_query("SELECT filename FROM {system} WHERE name = '%s' AND type = '%s'", $name, $type))) && file_exists($file))) { + elseif (db_is_active() && (($file = db_result(db_query("SELECT [filename] FROM [{system}] WHERE [name] = %s AND [type] = %s", $name, $type))) && file_exists($file))) { $files[$type][$name] = $file; } else { @@ -420,7 +420,7 @@ function variable_init($conf = array()) $variables = $cached->data; } else { - $result = db_query('SELECT * FROM {variable}'); + $result = db_query('SELECT * FROM [{variable}]'); while ($variable = db_fetch_object($result)) { $variables[$variable->name] = unserialize($variable->value); } @@ -463,9 +463,9 @@ function variable_set($name, $value) { global $conf; $serialized_value = serialize($value); - db_query("UPDATE {variable} SET value = '%s' WHERE name = '%s'", $serialized_value, $name); + db_query("UPDATE [{variable}] SET [value] = %s WHERE [name] = %s", $serialized_value, $name); if (!db_affected_rows()) { - @db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')", $name, $serialized_value); + @db_query("INSERT INTO [{variable}] ([name], [value]) VALUES (%s, %s)", $name, $serialized_value); } cache_clear_all('variables', 'cache'); @@ -482,7 +482,7 @@ function variable_set($name, $value) { function variable_del($name) { global $conf; - db_query("DELETE FROM {variable} WHERE name = '%s'", $name); + db_query("DELETE FROM [{variable}] WHERE [name] = %s", $name); cache_clear_all('variables', 'cache'); unset($conf[$name]); @@ -870,7 +870,7 @@ function drupal_is_denied($type, $mask) // We deny access if the only matching records in the {access} table have // status 0 (deny). If any have status 1 (allow), or if there are no // matching records, we allow access. - $sql = "SELECT 1 FROM {access} WHERE type = '%s' AND LOWER('%s') LIKE LOWER(mask) AND status = %d"; + $sql = "SELECT 1 FROM [{access}] WHERE [type] = %s AND LOWER(%s) LIKE LOWER([mask]) AND [status] = %d"; return db_result(db_query_range($sql, $type, $mask, 0, 0, 1)) && !db_result(db_query_range($sql, $type, $mask, 1, 0, 1)); } @@ -1069,7 +1069,7 @@ function language_list($field = 'languag // Init language list if (!isset($languages)) { if (variable_get('language_count', 1) > 1 || module_exists('locale')) { - $result = db_query('SELECT * FROM {languages} ORDER BY weight ASC, name ASC'); + $result = db_query('SELECT * FROM [{languages}] ORDER BY [weight] ASC, [name] ASC'); while ($row = db_fetch_object($result)) { $languages['language'][$row->language] = $row; } Index: includes/cache.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/cache.inc,v retrieving revision 1.16 diff -u -p -r1.16 cache.inc --- includes/cache.inc 26 Nov 2007 16:19:37 -0000 1.16 +++ includes/cache.inc 16 Jan 2008 15:38:10 -0000 @@ -18,11 +18,11 @@ function cache_get($cid, $table = 'cache $cache_flush = variable_get('cache_flush', 0); if ($cache_flush && ($cache_flush + variable_get('cache_lifetime', 0) <= time())) { // Time to flush old cache data - db_query("DELETE FROM {". $table ."} WHERE expire != %d AND expire <= %d", CACHE_PERMANENT, $cache_flush); + db_query("DELETE FROM [{". $table ."}] WHERE [expire] != %d AND [expire] <= %d", CACHE_PERMANENT, $cache_flush); variable_set('cache_flush', 0); } - $cache = db_fetch_object(db_query("SELECT data, created, headers, expire, serialized FROM {". $table ."} WHERE cid = '%s'", $cid)); + $cache = db_fetch_object(db_query("SELECT [data], [created], [headers], [expire], [serialized] FROM [{". $table ."}] WHERE [cid] = %s", $cid)); if (isset($cache->data)) { // If the data is permanent or we're not enforcing a minimum cache lifetime // always return the cached data. @@ -105,9 +105,17 @@ function cache_set($cid, $data, $table = $serialized = 1; } $created = time(); - db_query("UPDATE {". $table ."} SET data = %b, created = %d, expire = %d, headers = '%s', serialized = %d WHERE cid = '%s'", $data, $created, $expire, $headers, $serialized, $cid); + $values = array( + array('field' => 'data', 'placeholder' => '%b', 'data' => $data), + array('field' => 'created', 'placeholder' => '%d', 'data' => $created), + array('field' => 'expire', 'placeholder' => '%d', 'data' => $expire), + array('field' => 'headers', 'placeholder' => "%s", 'data' => $headers), + array('field' => 'serialized', 'placeholder' => '%d', 'data' => $serialized), + ); + db_query_update($table, $values, "[cid] = %s", $cid); if (!db_affected_rows()) { - @db_query("INSERT INTO {". $table ."} (cid, data, created, expire, headers, serialized) VALUES ('%s', %b, %d, %d, '%s', %d)", $cid, $data, $created, $expire, $headers, $serialized); + $values[] = array('field' => 'cid', 'placeholder' => "%s", 'data' => $cid); + db_query_insert($table, $values); } } @@ -156,26 +164,26 @@ function cache_clear_all($cid = NULL, $t else if (time() > ($cache_flush + variable_get('cache_lifetime', 0))) { // Clear the cache for everyone, cache_flush_delay seconds have // passed since the first request to clear the cache. - db_query("DELETE FROM {". $table ."} WHERE expire != %d AND expire < %d", CACHE_PERMANENT, time()); + db_query("DELETE FROM [{". $table ."}] WHERE [expire] != %d AND [expire] < %d", CACHE_PERMANENT, time()); variable_set('cache_flush', 0); } } else { // No minimum cache lifetime, flush all temporary cache entries now. - db_query("DELETE FROM {". $table ."} WHERE expire != %d AND expire < %d", CACHE_PERMANENT, time()); + db_query("DELETE FROM [{". $table ."}] WHERE [expire] != %d AND [expire] < %d", CACHE_PERMANENT, time()); } } else { if ($wildcard) { if ($cid == '*') { - db_query("DELETE FROM {". $table ."}"); + db_query("DELETE FROM [{". $table ."}]"); } else { - db_query("DELETE FROM {". $table ."} WHERE cid LIKE '%s%%'", $cid); + db_query("DELETE FROM [{". $table ."}] WHERE [cid] LIKE %s", $cid ."%"); } } else { - db_query("DELETE FROM {". $table ."} WHERE cid = '%s'", $cid); + db_query("DELETE FROM [{". $table ."}] WHERE [cid] = %s", $cid); } } } Index: includes/common.db2.inc =================================================================== RCS file: includes/common.db2.inc diff -N includes/common.db2.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/common.db2.inc 16 Jan 2008 15:38:10 -0000 @@ -0,0 +1,397 @@ + $t('DB2 database'), + 'value' => $version, + ); + + if (version_compare($version, DRUPAL_MINIMUM_DB2) < 0) { + $form['ibm_db2']['severity'] = REQUIREMENT_ERROR; + $form['ibm_db2']['description'] = $t('Your DB2 Server is too old. Drupal requires at least DB2 %version.', array('%version' => DRUPAL_MINIMUM_DB2)); + } + + return $form; +} + +/** + * Returns the version of the database server currently in use. + * + * @return Database server version + */ +function db_version() { + $banner = db_result(db_query("SELECT SERVICE_LEVEL FROM TABLE (SYSPROC.ENV_GET_INST_INFO()) AS INSTANCEINFO")); + preg_match('/\s*v([0-9.]+)\s*/', $banner, $version); + return array_pop($version); +} + +/** + * Insert a row of record into database. + * + * @param $table + * Table to insert. + * @param $values + * An array containing the insert values. Each element of the array + * should be an associatie array with the following keys: + * - "field": The database field represented in the table column. + * - "placeholder": The placeholder of the table column, using printf() + * syntax. Valid %-modifiers are: %d, %f, %s and %b. + * - "data": The data to insert into the table column. + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_insert($table, $values) { + $fields = array(); + $placeholders = array(); + $data = array(); + foreach ($values as $value) { + $fields[] = $value['field']; + $placeholders[] = $value['placeholder']; + $data[] = $value['data']; + } + + if (!count($fields)) { + return FALSE; + } + + $query = "INSERT INTO [{". $table ."}] ([". implode('], [', $fields) ."]) VALUES (". implode(', ', $placeholders) .")"; + return db_query($query, $data); +} + +/** + * Update a row of record in database. + * + * @param $table + * Table to update. + * @param $values + * An array containing the update values. Each element of the array + * should be an associatie array with the following keys: + * - "field": The database field represented in the table column. + * - "placeholder": The placeholder of the table column, using printf() + * syntax. Valid %-modifiers are: %d, %f, %s and %b. + * - "data": The data to insert into the table column. + * @param $where_clause + * A string containing an update condition query (where clause). + * @param ... + * A variable number of arguments which are substituted into the query + * WHERE condition, using printf() syntax. Instead of a variable number + * of query arguments, you may also pass a single array containing the + * query arguments. + * + * Valid %-modifiers are: %d, %f and %s. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_update($table, $values, $where_clause = NULL) { + $args = func_get_args(); + $args = array_slice($args, 3); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + + $fields = array(); + $data = array(); + foreach ($values as $value) { + $fields[] = '['. $value['field'] .'] = '. $value['placeholder']; + $data[] = $value['data']; + } + + if (!count($fields)) { + return FALSE; + } + + $query = "UPDATE [{". $table ."}] SET ". implode(', ', $fields); + if ($where_clause) { + $query .= " WHERE ". $where_clause; + $data = array_merge($data, $args); + } + return db_query($query, $data); +} + +/** + * Delete a row of record from database. + * + * @param $table + * Table to delete. + * @param $where_clause + * A string containing an update condition query (where clause). + * @param ... + * A variable number of arguments which are substituted into the query + * WHERE condition, using printf() syntax. Instead of a variable number + * of query arguments, you may also pass a single array containing the + * query arguments. + * + * Valid %-modifiers are: %d, %f and %s. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_delete($table, $where_clause = NULL) { + $args = func_get_args(); + $args = array_slice($args, 2); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + + $data = array(); + + $query = "DELETE FROM [{". $table ."}]"; + if ($where_clause) { + $query .= " WHERE ". $where_clause; + $data = $args; + } + return db_query($query, $data); +} + +/** + * Returns the last insert id. This function is thread safe. + * + * @param $table + * The name of the table you inserted into. + * @param $field + * The name of the autoincrement field. + */ +function db_last_insert_id($table, $field) { + return db_result(db_query("SELECT SYSIBM.IDENTITY_VAL_LOCAL() FROM [{". $table ."}]")); +} + +/** + * 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. Instead of a variable number of query arguments, + * you may also pass a single array containing the query arguments. + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: use NULL as arguments substitution for %b and %c. This will be + * replaced as corresponding empty LOB value placeholder, based on the + * database specific representation. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @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(); + $count = array_pop($args); + $from = array_pop($args); + array_shift($args); + + $query = 'SELECT * FROM (SELECT [sub1].*, ROW_NUMBER() OVER() AS [line2] FROM (' . $query . ') AS [sub1]) AS [sub2] WHERE [line2] BETWEEN ' . $from . ' AND ' . ($from + $count); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + return db_query($query, $args); +} + +/** + * Runs a SELECT query and stores its results in a temporary table. + * + * Use this as a substitute for db_query() when the results need to stored + * in a temporary table. Temporary tables exist for the duration of the page + * request. + * 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. + * + * Note that if you need to know how many results were returned, you should do + * a SELECT COUNT(*) on the temporary table afterwards. db_affected_rows() do + * not give consistent result across different database types in this case. + * + * @param $query + * A string containing a normal SELECT SQL query. + * @param ... + * A variable number of arguments which are substituted into the query + * using printf() syntax. The query arguments can be enclosed in one + * array instead. + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: use NULL as arguments substitution for %b and %c. This will be + * replaced as corresponding empty LOB value placeholder, based on the + * database specific representation. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @param $table + * The name of the temporary table to select into. This name will not be + * prefixed as there is no risk of collision. + * @return + * A database query result resource, or FALSE if the query was not executed + * correctly. + */ +function db_query_temporary($query) { + $args = func_get_args(); + $tablename = array_pop($args); + array_shift($args); + + $query = 'DECLARE GLOBAL TEMPORARY TABLE ['. $tablename .'] AS (' . $query . ') DEFINITION ONLY INCLUDING IDENTITY COLUMN ATTRIBUTES INCLUDING COLUMN DEFAULTS ON COMMIT PRESERVE ROWS NOT LOGGED'; + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + return db_query($query, $args); +} + +/** + * Lock a table. + * This function automatically starts a transaction. + */ +function db_lock_table($table) { + db_query('LOCK TABLE [{'. db_escape_table($table) .'}] IN EXCLUSIVE MODE'); +} + +/** + * Unlock all locked tables. + * This function automatically commits a transaction. + */ +function db_unlock_tables() { + db_query('COMMIT'); +} + +/** + * Check if a table exists. + */ +function db_table_exists($table) { + return (bool) db_result(db_query("SELECT COUNT(TABLE_NAME) FROM SYSIBM.TABLES WHERE TABLE_NAME LIKE '{". db_escape_table($table) ."}'")); +} + +/** + * Check if a column exists in the given table. + */ +function db_column_exists($table, $column) { + return (bool) db_result(db_query("SELECT COUNT(COLUMN_NAME) FROM SYSIBM.COLUMNS WHERE TABLE_NAME LIKE '{". db_escape_table($table) ."}' AND COLUMN_NAME LIKE '" . db_escape_table($column) ."'")); +} + +/** + * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to + * the SELECT list entry of the given query and the resulting query is returned. + * This function only applies the wrapper if a DISTINCT doesn't already exist in + * the query. + * + * @param $table Table containing the field to set as DISTINCT + * @param $field Field to set as DISTINCT + * @param $query Query to apply the wrapper to + * @return SQL query with the DISTINCT wrapper surrounding the given table.field. + */ +function db_distinct_field($table, $field, $query) { + $field_to_select = 'DISTINCT (['. $table .'].['. $field .'])'; + // (? %d", $name, ip_address(), time() - 3600)); + $number = db_result(db_query("SELECT COUNT(*) FROM [{flood}] WHERE [event] = %s AND [hostname] = %s AND [timestamp] > %d", $name, ip_address(), time() - 3600)); return ($number < $threshold ? TRUE : FALSE); } @@ -3190,7 +3190,9 @@ function _drupal_initialize_schema($modu **/ function drupal_schema_fields_sql($table, $prefix = NULL) { $schema = drupal_get_schema($table); - $fields = array_keys($schema['fields']); + foreach ($schema['fields'] as $key => $value) { + $fields[] = '['. $key .']'; + } if ($prefix) { $columns = array(); foreach ($fields as $field) { @@ -3215,7 +3217,7 @@ function drupal_schema_fields_sql($table * The object to write. This is a reference, as defaults according to * the schema may be filled in on the object, as well as ID on the serial * type(s). Both array an object types may be passed. - * @param $update + * @param primary_keys * If this is an update, specify the primary keys' field names. It is the * caller's responsibility to know if a record for this object already * exists in the database. If there is only 1 key, you may pass a simple string. @@ -3226,19 +3228,15 @@ function drupal_schema_fields_sql($table * the $table. For example, $object->nid will be populated after inserting * a new node. */ -function drupal_write_record($table, &$object, $update = array()) { - // Standardize $update to an array. - if (is_string($update)) { - $update = array($update); +function drupal_write_record($table, &$object, $primary_keys = array()) { + // Standardize $primary_keys to an array. + if (!is_array($primary_keys)) { + $primary_keys = array($primary_keys); } // Convert to an object if needed. - if (is_array($object)) { + if ($array = is_array($object)) { $object = (object) $object; - $array = TRUE; - } - else { - $array = FALSE; } $schema = drupal_get_schema($table); @@ -3246,18 +3244,18 @@ function drupal_write_record($table, &$o return FALSE; } - $fields = $defs = $values = $serials = array(); - + $values = array(); + $serials = array(); // Go through our schema, build SQL, and when inserting, fill in defaults for // fields that are not set. foreach ($schema['fields'] as $field => $info) { // Special case -- skip serial types if we are updating. - if ($info['type'] == 'serial' && count($update)) { + if ($info['type'] == 'serial' && count($primary_keys)) { continue; } // For inserts, populate defaults from Schema if not already provided - if (!isset($object->$field) && !count($update) && isset($info['default'])) { + if (!isset($object->$field) && !count($primary_keys) && isset($info['default'])) { $object->$field = $info['default']; } @@ -3270,44 +3268,40 @@ function drupal_write_record($table, &$o // Build arrays for the fields, placeholders, and values in our query. if (isset($object->$field)) { - $fields[] = $field; - $placeholders[] = db_type_placeholder($info['type']); + $value['field'] = $field; + $value['placeholder'] = db_type_placeholder($info['type']); if (empty($info['serialize'])) { - $values[] = $object->$field; + $value['data'] = $object->$field; } else { - $values[] = serialize($object->$field); + $value['data'] = serialize($object->$field); } + + $values[] = $value; } } - // Build the SQL. - $query = ''; - if (!count($update)) { - $query = "INSERT INTO {". $table ."} (". implode(', ', $fields) .') VALUES ('. implode(', ', $placeholders) .')'; + // Execute the SQL. + if (!count($primary_keys)) { + $result = db_query_insert($table, $values); $return = SAVED_NEW; } else { - $query = ''; - foreach ($fields as $id => $field) { - if ($query) { - $query .= ', '; + foreach ($primary_keys as $key => $value){ + // $primary_key is NOT in key-value pair format. + if (!isset($schema['fields'][$key]) && isset($schema['fields'][$value])) { + $key = $value; + $value = $object->$key; } - $query .= $field .' = '. $placeholders[$id]; - } - - foreach ($update as $key){ - $conditions[] = "$key = ". db_type_placeholder($schema['fields'][$key]['type']); - $values[] = $object->$key; + $conditions[] = "[$key] = ". db_type_placeholder($schema['fields'][$key]['type']); + $args[] = $value; } - - $query = "UPDATE {". $table ."} SET $query WHERE ". implode(' AND ', $conditions); + $result = db_query_update($table, $values, implode(' AND ', $conditions), $args); $return = SAVED_UPDATED; } - // Execute the SQL. - if (db_query($query, $values)) { + if ($result) { if ($serials) { // Get last insert ids and fill them in. foreach ($serials as $field) { @@ -3327,6 +3321,47 @@ function drupal_write_record($table, &$o } /** + * Drop a record from the database based upon the schema. + * + * @param $table + * The name of the table; this must exist in schema API. + * @param $object + * The object to drop. This is a reference, as defaults according to + * the schema may be filled in on the object, as well as ID on the serial + * type(s). Both array an object types may be passed. + * @param primary_keys + * Specify the primary keys' field names. If there is only 1 key, you may + * pass a simple string. + * @return (boolean) Failure to write a record will return FALSE. Otherwise, + * TRUE is returned. + */ +function drupal_drop_record($table, $object, $primary_keys = array()) { + // Standardize $primary_keys to an array. + if (!is_array($primary_keys)) { + $primary_keys = array($primary_keys); + } + + // Convert to an object if needed. + if ($array = is_array($object)) { + $object = (object) $object; + } + + $schema = drupal_get_schema($table); + if (empty($schema)) { + return FALSE; + } + + // Execute the request. + foreach ($primary_keys as $key){ + $conditions[] = "[$key] = ". db_type_placeholder($schema['fields'][$key]['type']); + $args[] = $object->$key; + } + db_query_delete($table, implode(' AND ', $conditions), $args); + + return SAVED_DELETED; +} + +/** * @} End of "ingroup schemaapi". */ Index: includes/common.mysql.inc =================================================================== RCS file: includes/common.mysql.inc diff -N includes/common.mysql.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/common.mysql.inc 16 Jan 2008 15:38:11 -0000 @@ -0,0 +1,385 @@ + 0) ? "CONCAT($return)" : ''; +} + +/** + * Returns a string that is the equivalent of MySQL IFNULL or Oracle NVL. + * + * @return + * If $expr1 is not NULL, returns $expr1; otherwise it returns $expr2. + */ +function db_if_null($expr1, $expr2) { + return " IFNULL($expr1, $expr2) "; +} + +/** + * Report database status. + */ +function db_status_report($phase) { + $t = get_t(); + + $version = db_version(); + + $form['mysql'] = array( + 'title' => $t('MySQL database'), + 'value' => ($phase == 'runtime') ? l($version, 'admin/reports/status/sql') : $version, + ); + + if (version_compare($version, DRUPAL_MINIMUM_MYSQL) < 0) { + $form['mysql']['severity'] = REQUIREMENT_ERROR; + $form['mysql']['description'] = $t('Your MySQL Server is too old. Drupal requires at least MySQL %version.', array('%version' => DRUPAL_MINIMUM_MYSQL)); + } + + return $form; +} + +/** + * Returns the version of the database server currently in use. + * + * @return Database server version + */ +function db_version() { + global $active_db; + list($version) = explode('-', db_result(db_query("SELECT VERSION();"))); + return $version; +} + +/** + * Insert a row of record into database. + * + * @param $table + * Table to insert. + * @param $values + * An array containing the insert values. Each element of the array + * should be an associatie array with the following keys: + * - "field": The database field represented in the table column. + * - "placeholder": The placeholder of the table column, using printf() + * syntax. Valid %-modifiers are: %d, %f, %s and %b. + * - "data": The data to insert into the table column. + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_insert($table, $values) { + $fields = array(); + $placeholders = array(); + $data = array(); + foreach ($values as $value) { + $fields[] = $value['field']; + $placeholders[] = $value['placeholder']; + $data[] = $value['data']; + } + + if (!count($fields)) { + return FALSE; + } + + $query = "INSERT INTO [{". $table ."}] ([". implode('], [', $fields) ."]) VALUES (". implode(', ', $placeholders) .")"; + return db_query($query, $data); +} + +/** + * Update a row of record in database. + * + * @param $table + * Table to update. + * @param $values + * An array containing the update values. Each element of the array + * should be an associatie array with the following keys: + * - "field": The database field represented in the table column. + * - "placeholder": The placeholder of the table column, using printf() + * syntax. Valid %-modifiers are: %d, %f, %s and %b. + * - "data": The data to insert into the table column. + * @param $where_clause + * A string containing an update condition query (where clause). + * @param ... + * A variable number of arguments which are substituted into the query + * WHERE condition, using printf() syntax. Instead of a variable number + * of query arguments, you may also pass a single array containing the + * query arguments. + * + * Valid %-modifiers are: %d, %f and %s. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_update($table, $values, $where_clause = NULL) { + $args = func_get_args(); + $args = array_slice($args, 3); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + + $fields = array(); + $data = array(); + foreach ($values as $value) { + $fields[] = '['. $value['field'] .'] = '. $value['placeholder']; + $data[] = $value['data']; + } + + if (!count($fields)) { + return FALSE; + } + + $query = "UPDATE [{". $table ."}] SET ". implode(', ', $fields); + if ($where_clause) { + $query .= " WHERE ". $where_clause; + $data = array_merge($data, $args); + } + return db_query($query, $data); +} + +/** + * Delete a row of record from database. + * + * @param $table + * Table to delete. + * @param $where_clause + * A string containing an update condition query (where clause). + * @param ... + * A variable number of arguments which are substituted into the query + * WHERE condition, using printf() syntax. Instead of a variable number + * of query arguments, you may also pass a single array containing the + * query arguments. + * + * Valid %-modifiers are: %d, %f and %s. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_delete($table, $where_clause = NULL) { + $args = func_get_args(); + $args = array_slice($args, 2); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + + $data = array(); + + $query = "DELETE FROM [{". $table ."}]"; + if ($where_clause) { + $query .= " WHERE ". $where_clause; + $data = $args; + } + return db_query($query, $data); +} + +/** + * Returns the last insert id. + * + * @param $table + * The name of the table you inserted into. + * @param $field + * The name of the autoincrement field. + */ +function db_last_insert_id($table, $field) { + return db_result(db_query('SELECT LAST_INSERT_ID()')); +} + +/** + * 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. The query arguments can be enclosed in one + * array instead. + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @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(); + $count = array_pop($args); + $from = array_pop($args); + array_shift($args); + + $query .= ' LIMIT '. (int) $from .', '. (int) $count; + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + return db_query($query, $args); +} + +/** + * Runs a SELECT query and stores its results in a temporary table. + * + * Use this as a substitute for db_query() when the results need to stored + * in a temporary table. Temporary tables exist for the duration of the page + * request. + * 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. + * + * Note that if you need to know how many results were returned, you should do + * a SELECT COUNT(*) on the temporary table afterwards. db_affected_rows() does + * not give consistent result across different database types in this case. + * + * @param $query + * A string containing a normal SELECT SQL query. + * @param ... + * A variable number of arguments which are substituted into the query + * using printf() syntax. The query arguments can be enclosed in one + * array instead. + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @param $table + * The name of the temporary table to select into. This name will not be + * prefixed as there is no risk of collision. + * @return + * A database query result resource, or FALSE if the query was not executed + * correctly. + */ +function db_query_temporary($query) { + $args = func_get_args(); + $tablename = array_pop($args); + array_shift($args); + + $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE '. $tablename .' Engine=HEAP SELECT', $query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + return db_query($query, $args); +} + +/** + * Lock a table. + */ +function db_lock_table($table) { + db_query('LOCK TABLES [{'. db_escape_table($table) .'}] WRITE'); +} + +/** + * Unlock all locked tables. + */ +function db_unlock_tables() { + db_query('UNLOCK TABLES'); +} + +/** + * Check if a table exists. + */ +function db_table_exists($table) { + return (bool) db_fetch_object(db_query("SHOW TABLES LIKE '{". db_escape_table($table) ."}'")); +} + +/** + * Check if a column exists in the given table. + */ +function db_column_exists($table, $column) { + return (bool) db_fetch_object(db_query("SHOW COLUMNS FROM [{". db_escape_table($table) ."}] LIKE '". db_escape_table($column) ."'")); +} + +/** + * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to + * the SELECT list entry of the given query and the resulting query is returned. + * This function only applies the wrapper if a DISTINCT doesn't already exist in + * the query. + * + * @param $table Table containing the field to set as DISTINCT + * @param $field Field to set as DISTINCT + * @param $query Query to apply the wrapper to + * @return SQL query with the DISTINCT wrapper surrounding the given table.field. + */ +function db_distinct_field($table, $field, $query) { + $field_to_select = 'DISTINCT(['. $table .'].['. $field .'])'; + // (? 30) { + // Try to fetch mapping, if not exists, set it up. + $trim = variable_get('oracle_'. $match, NULL); + if (!$trim) { + // Fetch last counter, and +1 for next mapping. + $count = variable_get('_db_escape_quote', 0) + 1; + variable_set('_db_escape_quote', $count); + // Setup mapping and reverse mapping. + $trim = substr($match, 0, 30 - strlen($count)) . $count; + variable_set('oracle_'. $match, $trim); + variable_set('oracle_'. $trim, $match); + $match = $trim; + } + } + return DB_QUOTE_OPERATOR . $match . DB_QUOTE_OPERATOR; +} + +/** + * Return a portably concatenate strings. + * + * @param ... + * Variable number of string parameters. + * @return + * Portably concatenate strings. + */ +function db_concat() { + $args = func_get_args(); + return implode(DB_CONCAT_OPERATOR, $args); +} + +/** + * Returns a string that is the equivalent of MySQL IFNULL or Oracle NVL. + * + * @return + * If $expr1 is not NULL, returns $expr1; otherwise it returns $expr2. + */ +function db_if_null($expr1, $expr2) { + return " NVL($expr1, $expr2) "; +} + +/** + * Report database status. + */ +function db_status_report($phase) { + $t = get_t(); + + $version = db_version(); + + $form['oci8'] = array( + 'title' => $t('Oracle database'), + 'value' => $version, + ); + + if (version_compare($version, DRUPAL_MINIMUM_ORACLE) < 0) { + $form['oci8']['severity'] = REQUIREMENT_ERROR; + $form['oci8']['description'] = $t('Your Oracle Server is too old. Drupal requires at least Oracle %version.', array('%version' => DRUPAL_MINIMUM_ORACLE)); + } + + return $form; +} + +/** + * Returns the version of the database server currently in use. + * + * @return Database server version + */ +function db_version() { + $banner = db_result(db_query('SELECT BANNER FROM SYS.V_$VERSION')); + preg_match('/\s([0-9.]+)\s/', $banner, $version); + return array_pop($version); +} + +/** + * Insert a row of record into database. + * + * @param $table + * Table to insert. + * @param $values + * An array containing the insert values. Each element of the array + * should be an associatie array with the following keys: + * - "field": The database field represented in the table column. + * - "placeholder": The placeholder of the table column, using printf() + * syntax. Valid %-modifiers are: %d, %f, %s and %b. + * - "data": The data to insert into the table column. + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_insert($table, $values) { + $fields = array(); + $placeholders = array(); + $args = array(); + $lob_fields = array(); + $lob_placeholders = array(); + $lob_args = array(); + foreach ($values as $value) { + $fields[] = $value['field']; + switch ($value['placeholder']) { + case '%b': + $placeholders[] = 'EMPTY_BLOB()'; + $lob_fields[] = $value['field']; + $lob_placeholders[] = $value['placeholder']; + $lob_args[] = $value['data']; + break; + case '%c': + $placeholders[] = 'EMPTY_CLOB()'; + $lob_fields[] = $value['field']; + $lob_placeholders[] = $value['placeholder']; + $lob_args[] = $value['data']; + break; + default: + $placeholders[] = $value['placeholder']; + $args[] = $value['data']; + } + } + + $query = "INSERT INTO [{". $table ."}] ([". implode('], [', $fields) ."]) VALUES (". implode(', ', $placeholders) .")"; + if (count($lob_fields)) { + $query .= " RETURNING [". implode('], [', $lob_fields) ."] INTO ". implode(', ', $lob_placeholders); + $args = array_merge($args, $lob_args); + } + return db_query($query, $args); +} + +/** + * Update a row of record in database. + * + * @param $table + * Table to update. + * @param $values + * An array containing the update values. Each element of the array + * should be an associatie array with the following keys: + * - "field": The database field represented in the table column. + * - "placeholder": The placeholder of the table column, using printf() + * syntax. Valid %-modifiers are: %d, %f, %s and %b. + * - "data": The data to insert into the table column. + * @param $where_clause + * A string containing an update condition query (where clause). + * @param ... + * A variable number of arguments which are substituted into the query + * WHERE condition, using printf() syntax. Instead of a variable number + * of query arguments, you may also pass a single array containing the + * query arguments. + * + * Valid %-modifiers are: %d, %f and %s. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_update($table, $values, $where_clause = NULL) { + global $active_db, $last_result, $queries; + + $where_args = func_get_args(); + $where_args = array_slice($where_args, 3); + if (isset($where_args[0]) and is_array($where_args[0])) { // 'All arguments in one array' syntax + $where_args = $where_args[0]; + } + + $fields = array(); + $args = array(); + $lob_fields = array(); + $lob_placeholders = array(); + $lob_args = array(); + foreach ($values as $value) { + switch ($value['placeholder']) { + case '%b': + $fields[] = '['. $value['field'] .'] = EMPTY_BLOB()'; + $lob_fields[] = $value['field']; + $lob_placeholders[] = $value['placeholder']; + $lob_args[] = $value['data']; + break; + case '%c': + $fields[] = '['. $value['field'] .'] = EMPTY_CLOB()'; + $lob_fields[] = $value['field']; + $lob_placeholders[] = $value['placeholder']; + $lob_args[] = $value['data']; + break; + default: + $fields[] = '['. $value['field'] .'] = '. $value['placeholder']; + $args[] = $value['data']; + } + } + + $query = "UPDATE [{". $table ."}] SET ". implode(', ', $fields); + if ($where_clause) { + $query .= " WHERE ". $where_clause; + $args = array_merge($args, $where_args); + } + if (count($lob_fields)) { + $query .= " RETURNING [". implode('], [', $lob_fields) ."] INTO ". implode(', ', $lob_placeholders); + $args = array_merge($args, $lob_args); + } + return db_query($query, $args); +} + +/** + * Delete a row of record from database. + * + * @param $table + * Table to delete. + * @param $where_clause + * A string containing an update condition query (where clause). + * @param ... + * A variable number of arguments which are substituted into the query + * WHERE condition, using printf() syntax. Instead of a variable number + * of query arguments, you may also pass a single array containing the + * query arguments. + * + * Valid %-modifiers are: %d, %f and %s. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_delete($table, $where_clause = NULL) { + $args = func_get_args(); + $args = array_slice($args, 2); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + + $query['query'] = "DELETE FROM [{". $table ."}]"; + if ($where_clause) { + $query['query'] .= " WHERE ". $where_clause; + } + return db_query($query, $args); +} + +/** + * Returns the last insert id. This function is thread safe. + * + * @param $table + * The name of the table you inserted into. + * @param $field + * The name of the autoincrement field. + */ +function db_last_insert_id($table, $field) { + return db_result(db_query("SELECT [seq_{". $table ."}_" . $field ."].CURRVAL FROM DUAL")); +} + +/** + * 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. Instead of a variable number of query arguments, + * you may also pass a single array containing the query arguments. + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: use NULL as arguments substitution for %b and %c. This will be + * replaced as corresponding empty LOB value placeholder, based on the + * database specific representation. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @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(); + $count = array_pop($args); + $from = array_pop($args); + array_shift($args); + + $query = 'SELECT * FROM (SELECT [sub1].*, ROWNUM AS [line2] FROM ('. $query .') [sub1]) WHERE [line2] BETWEEN '. ($from + 1) .' AND '. ($from + $count); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + return db_query($query, $args); +} + +/** + * Runs a SELECT query and stores its results in a temporary table. + * + * Use this as a substitute for db_query() when the results need to stored + * in a temporary table. Temporary tables exist for the duration of the page + * request. + * 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. + * + * Note that if you need to know how many results were returned, you should do + * a SELECT COUNT(*) on the temporary table afterwards. db_affected_rows() do + * not give consistent result across different database types in this case. + * + * @param $query + * A string containing a normal SELECT SQL query. + * @param ... + * A variable number of arguments which are substituted into the query + * using printf() syntax. The query arguments can be enclosed in one + * array instead. + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: use NULL as arguments substitution for %b and %c. This will be + * replaced as corresponding empty LOB value placeholder, based on the + * database specific representation. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @param $table + * The name of the temporary table to select into. This name will not be + * prefixed as there is no risk of collision. + * @return + * A database query result resource, or FALSE if the query was not executed + * correctly. + */ +function db_query_temporary($query) { + $args = func_get_args(); + $tablename = array_pop($args); + array_shift($args); + + $query = preg_replace('/^SELECT/i', 'CREATE GLOBAL TEMPORARY TABLE ['. $tablename .'] ON COMMIT PRESERVE ROWS AS SELECT', $query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + return db_query($query, $args); +} + +/** + * Lock a table. + * This function automatically starts a transaction. + */ +function db_lock_table($table) { + db_query('LOCK TABLE [{'. db_escape_table($table) .'}] IN EXCLUSIVE MODE'); +} + +/** + * Unlock all locked tables. + * This function automatically commits a transaction. + */ +function db_unlock_tables() { + db_query('COMMIT'); +} + +/** + * Check if a table exists. + */ +function db_table_exists($table) { + return db_result(db_query("SELECT COUNT(TABLE_NAME) FROM USER_TABLES WHERE TABLE_NAME LIKE '{". db_escape_table($table) ."}'")) ? TRUE : FALSE; +} + +/** + * Check if a column exists in the given table. + */ +function db_column_exists($table, $column) { + return db_result(db_query("SELECT COUNT(COLUMN_NAME) FROM USER_TAB_COLS WHERE TABLE_NAME LIKE '{". db_escape_table($table) ."}' AND COLUMN_NAME LIKE '". db_escape_table($column) ."'")) ? TRUE : FALSE; +} + +/** + * Check if constraint exists in the given table. + */ +function db_constraint_exists($table, $fields) { + $queries = array(); + foreach ($fields as $key => $value) { + $queries[] = "SELECT CONSTRAINT_NAME FROM USER_CONS_COLUMNS WHERE TABLE_NAME LIKE '{". db_escape_table($table) ."}' AND COLUMN_NAME LIKE '". db_escape_table($value) ."'"; + } + return db_result(db_query(implode(' INTERSECT ', $queries))) ? TRUE : FALSE; +} + +/** + * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to + * the SELECT list entry of the given query and the resulting query is returned. + * This function only applies the wrapper if a DISTINCT doesn't already exist in + * the query. + * + * @param $table Table containing the field to set as DISTINCT + * @param $field Field to set as DISTINCT + * @param $query Query to apply the wrapper to + * @return SQL query with the DISTINCT wrapper surrounding the given table.field. + */ +function db_distinct_field($table, $field, $query) { + $field_to_select = 'DISTINCT (['. $table .'].['. $field .'])'; + // (? $t('PostgreSQL database'), + 'value' => $version, + ); + + if (version_compare($version, DRUPAL_MINIMUM_POSTGRESQL) < 0) { + $form['pgsql']['severity'] = REQUIREMENT_ERROR; + $form['pgsql']['description'] = $t('Your PostgreSQL Server is too old. Drupal requires at least PostgreSQL %version.', array('%version' => DRUPAL_MINIMUM_POSTGRESQL)); + } + + return $form; +} + +/** + * Returns the version of the database server currently in use. + * + * @return Database server version + */ +function db_version() { + return db_result(db_query("SHOW SERVER_VERSION")); +} + +/** + * Insert a row of record into database. + * + * @param $table + * Table to insert. + * @param $values + * An array containing the insert values. Each element of the array + * should be an associatie array with the following keys: + * - "field": The database field represented in the table column. + * - "placeholder": The placeholder of the table column, using printf() + * syntax. Valid %-modifiers are: %d, %f, %s and %b. + * - "data": The data to insert into the table column. + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_insert($table, $values) { + $fields = array(); + $placeholders = array(); + $data = array(); + foreach ($values as $value) { + $fields[] = $value['field']; + $placeholders[] = $value['placeholder']; + $data[] = $value['data']; + } + + if (!count($fields)) { + return FALSE; + } + + $query = "INSERT INTO [{". $table ."}] ([". implode('], [', $fields) ."]) VALUES (". implode(', ', $placeholders) .")"; + return db_query($query, $data); +} + +/** + * Update a row of record in database. + * + * @param $table + * Table to update. + * @param $values + * An array containing the update values. Each element of the array + * should be an associatie array with the following keys: + * - "field": The database field represented in the table column. + * - "placeholder": The placeholder of the table column, using printf() + * syntax. Valid %-modifiers are: %d, %f, %s and %b. + * - "data": The data to insert into the table column. + * @param $where_clause + * A string containing an update condition query (where clause). + * @param ... + * A variable number of arguments which are substituted into the query + * WHERE condition, using printf() syntax. Instead of a variable number + * of query arguments, you may also pass a single array containing the + * query arguments. + * + * Valid %-modifiers are: %d, %f and %s. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_update($table, $values, $where_clause = NULL) { + $args = func_get_args(); + $args = array_slice($args, 3); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + + $fields = array(); + $data = array(); + foreach ($values as $value) { + $fields[] = '['. $value['field'] .'] = '. $value['placeholder']; + $data[] = $value['data']; + } + + if (!count($fields)) { + return FALSE; + } + + $query = "UPDATE [{". $table ."}] SET ". implode(', ', $fields); + if ($where_clause) { + $query .= " WHERE ". $where_clause; + $data = array_merge($data, $args); + } + return db_query($query, $data); +} + +/** + * Delete a row of record from database. + * + * @param $table + * Table to delete. + * @param $where_clause + * A string containing an update condition query (where clause). + * @param ... + * A variable number of arguments which are substituted into the query + * WHERE condition, using printf() syntax. Instead of a variable number + * of query arguments, you may also pass a single array containing the + * query arguments. + * + * Valid %-modifiers are: %d, %f and %s. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query_delete($table, $where_clause = NULL) { + $args = func_get_args(); + $args = array_slice($args, 2); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + + $data = array(); + + $query = "DELETE FROM [{". $table ."}]"; + if ($where_clause) { + $query .= " WHERE ". $where_clause; + $data = $args; + } + return db_query($query, $data); +} + +/** + * Returns the last insert id. This function is thread safe. + * + * @param $table + * The name of the table you inserted into. + * @param $field + * The name of the autoincrement field. + */ +function db_last_insert_id($table, $field) { + return db_result(db_query("SELECT CURRVAL('{". db_escape_table($table) ."}_". db_escape_table($field) ."_seq')")); +} + +/** + * 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. Instead of a variable number of query arguments, + * you may also pass a single array containing the query arguments. + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @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(); + $count = array_pop($args); + $from = array_pop($args); + array_shift($args); + + $query .= ' LIMIT '. (int) $count .' OFFSET '. (int) $from; + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + return db_query($query, $args); +} + +/** + * Runs a SELECT query and stores its results in a temporary table. + * + * Use this as a substitute for db_query() when the results need to stored + * in a temporary table. Temporary tables exist for the duration of the page + * request. + * 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. + * + * Note that if you need to know how many results were returned, you should do + * a SELECT COUNT(*) on the temporary table afterwards. db_affected_rows() does + * not give consistent result across different database types in this case. + * + * @param $query + * A string containing a normal SELECT SQL query. + * @param ... + * A variable number of arguments which are substituted into the query + * using printf() syntax. The query arguments can be enclosed in one + * array instead. + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @param $table + * The name of the temporary table to select into. This name will not be + * prefixed as there is no risk of collision. + * @return + * A database query result resource, or FALSE if the query was not executed + * correctly. + */ +function db_query_temporary($query) { + $args = func_get_args(); + $tablename = array_pop($args); + array_shift($args); + + $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE '. $tablename .' AS SELECT', $query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + return db_query($query, $args); +} + +/** + * Lock a table. + * This function automatically starts a transaction. + */ +function db_lock_table($table) { + db_query('LOCK TABLE [{'. db_escape_table($table) .'}] IN EXCLUSIVE MODE'); +} + +/** + * Unlock all locked tables. + * This function automatically commits a transaction. + */ +function db_unlock_tables() { + db_query('COMMIT'); +} + +/** + * Check if a table exists. + */ +function db_table_exists($table) { + return (bool) db_result(db_query("SELECT COUNT(*) FROM [pg_class] WHERE [relname] = '{". db_escape_table($table) ."}'")); +} + +/** + * Check if a column exists in the given table. + */ +function db_column_exists($table, $column) { + return (bool) db_result(db_query("SELECT COUNT([pg_attribute].[attname]) FROM [pg_class], [pg_attribute] WHERE [pg_attribute].[attrelid] = [pg_class].[oid] AND [pg_class].[relname] = '{". db_escape_table($table) ."}' AND [attname] = '". db_escape_table($column) ."'")); +} + +/** + * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to + * the SELECT list entry of the given query and the resulting query is returned. + * This function only applies the wrapper if a DISTINCT doesn't already exist in + * the query. + * + * @param $table Table containing the field to set as DISTINCT + * @param $field Field to set as DISTINCT + * @param $query Query to apply the wrapper to + * @return SQL query with the DISTINCT wrapper surrounding the given table.field. + */ +function db_distinct_field($table, $field, $query) { + $field_to_select = 'DISTINCT ON (['. $table .'].['. $field ."]) [$table].[$field]"; + // (?PostgreSQL documentation.', array('%encoding' => $encoding, '@url' => 'http://www.postgresql.org/docs/7.4/interactive/multibyte.html')), 'status'); + } +} + +/** + * @} End of "ingroup database". + */ Index: includes/database.ibm_db2.inc =================================================================== RCS file: includes/database.ibm_db2.inc diff -N includes/database.ibm_db2.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/database.ibm_db2.inc 16 Jan 2008 15:38:11 -0000 @@ -0,0 +1,378 @@ + DB2_AUTOCOMMIT_ON, + // Specifies that column names are returned in natural case. + 'DB2_ATTR_CASE' => DB2_CASE_NATURAL, + // Specifies a forward-only cursor for a statement resource. + 'CURSOR' => DB2_FORWARD_ONLY + ); + + // Test connecting to the database. + $connection = @db2_connect($conn_string, '', '', $conn_options); + if (!$connection) { + $error = db2_conn_errormsg(); + _db_error_page($error); + } + + return $connection; +} + +/** + * Runs a basic query in the active database. + * + * 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. Instead of a variable number of query arguments, + * you may also pass a single array containing the query arguments. + * + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: use NULL as arguments substitution for %b and %c. This will be + * replaced as corresponding empty LOB value placeholder, based on the + * database specific representation. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query($query) { + $args = func_get_args(); + array_shift($args); + _debug_query($query); + $query = db_prefix_tables($query); + $query = db_escape_quote($query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + _db_query_callback(array('query' => $query, 'args' => $args), TRUE); + $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); + $args = _db_query_callback(NULL, TRUE); + return _db_query(array('query' => $query, 'args' => $args)); +} + +/** + * Helper function for db_query(). + */ +function _db_query($query, $debug = 0) { + global $active_db, $last_result, $queries; + static $last_stmts; + + // Expand $query if it is in array format. + $args = array(); + if (is_array($query)) { + $args = $query['args']; + $query = $query['query']; + + // Check if locator exists in query, or else unset it. + foreach ($args as $key => $value) { + if (!is_array($args[$key]) || !isset($args[$key]['locator']) || !strstr($query, $args[$key]['locator'])) { + unset($args[$key]); + } + } + } + + if (variable_get('dev_query', 0)) { + list($usec, $sec) = explode(' ', microtime()); + $timer = (float)$usec + (float)$sec; + // If devel.module query logging is enabled, prepend a comment with the username and calling function + // to the SQL string. This is useful when running mysql's SHOW PROCESSLIST to learn what exact + // code is issueing the slow query. + $bt = debug_backtrace(); + // t() may not be available yet so we don't wrap 'Anonymous' + $name = $user->uid ? $user->name : variable_get('anonymous', 'Anonymous'); + // str_replace() to prevent SQL injection via username or anonymous name. + $name = str_replace(array('*', '/'), '', $name); + $query = '/* '. $name .' : '. $bt[2]['function'] .' */ '. $query; + } + + $last_stmts = array_filter((array) $last_stmts); + $ident = md5($query); + if (isset($last_stmts[$ident])) { + // We parse this query once before, just reuse it. + $stmt = $last_stmts[$ident]; + unset($last_stmts[$ident]); + } + else { + // Perform actual query and return the result set. + $stmt = db2_prepare($active_db, $query); + } + + if ($stmt) { + // Execute the statement + $result = db2_execute($stmt, $args); + } + + if ($stmt === FALSE || $result === FALSE) { + // Indicate to drupal_error_handler that this is a database error. + ${DB_ERROR} = TRUE; + $error = db2_stmt_errormsg(); + trigger_error(check_plain($error ."\nquery: ". $query), E_USER_WARNING); + return FALSE; + } + + if (variable_get('dev_query', 0)) { + $bt = debug_backtrace(); + $query = $bt[2]['function'] ."\n". $query; + list($usec, $sec) = explode(' ', microtime()); + $stop = (float)$usec + (float)$sec; + $diff = $stop - $timer; + $queries[] = array($query, $diff); + } + + if ($debug) { + $error = db2_stmt_errormsg(); + print '

query: '. $query .'
error:'. $error .'

'; + } + + $last_result = $stmt; + return $last_result; +} + +/** + * 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, or FALSE. The attributes + * of this object are the table fields selected by the query. + */ +function db_fetch_object($result) { + if ($result) { + $object = db2_fetch_object($result); + return isset($object) ? $object : FALSE; + } +} + +/** + * 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, or FALSE. + * 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) { + if ($result) { + $array = db2_fetch_assoc($result); + return isset($array) ? $array : FALSE; + } +} + +/** + * 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(). + * @return + * The resulting field or FALSE. + */ +function db_result($result) { + if ($result && db2_fetch_array($result)) { + return $array[0]; + } + return FALSE; +} + +/** + * Determine whether the previous query caused an error. + */ +function db_error() { + $error = oci_error(); + return $error['message']; +} + +/** + * Determine the number of rows changed by the preceding query. + */ +function db_affected_rows() { + global $active_db; + return db2_stmt_errormsg($active_db); +} + +/* + * Prepare user input for use in a database query, preventing SQL injection attacks. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_escape_decimal(&$data, $locator) { + $data = array( + 'locator' => $locator, + 'data' => (int) $data, + ); + return $locator; +} + +/** + * Prepare user input for use in a database query, preventing SQL injection attacks. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_escape_float(&$data, $locator) { + $data = array( + 'locator' => $locator, + 'data' => (float) $data, + ); + return $locator; +} + +/** + * Prepare user input for use in a database query, preventing SQL injection attacks. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_escape_string(&$data, $locator) { + // Trim first 4000 characters, based on Oracle VARCHAR2(4000) limitation. + $data = preg_replace('/(.{0,4000})(.*)/', '\1', $data); + + $data = array( + 'locator' => $locator, + 'data' => $data, + ); + return $locator; +} + +/** + * Returns a properly formatted Binary Large OBject value. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_encode_blob(&$data, $locator) { + global $active_db; + $data = array( + 'locator' => $locator, + 'data' => $data, + ); + return $locator; +} + +/** + * Returns text from a Binary Large OBject value. + * + * @param $data + * Data to decode. + * @return + * Decoded data. + */ +function db_decode_blob($data) { + return $data; +} + +/** + * Returns a properly formatted Character Large OBject value. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_encode_clob(&$data, $locator) { + global $active_db; + $data = array( + 'locator' => $locator, + 'data' => $data, + ); + return $locator; +} + +/** + * Returns text from a Character Large OBject value. + * + * @param $data + * Data to decode. + * @return + * Decoded data. + */ +function db_decode_clob($data) { + return $data; +} + +/** + * @} End of "ingroup database". + */ Index: includes/database.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.inc,v retrieving revision 1.92 diff -u -p -r1.92 database.inc --- includes/database.inc 8 Jan 2008 16:03:31 -0000 1.92 +++ includes/database.inc 16 Jan 2008 15:38:11 -0000 @@ -139,14 +139,15 @@ function db_set_active($name = 'default' $connect_url = $db_url; } - $db_type = substr($connect_url, 0, strpos($connect_url, '://')); + $_connect_url = parse_url($connect_url); + $db_type = $_connect_url['fragment']; $handler = "./includes/database.$db_type.inc"; if (is_file($handler)) { include_once $handler; } else { - _db_error_page("The database type '". $db_type ."' is unsupported. Please use either 'mysql' or 'mysqli' for MySQL, or 'pgsql' for PostgreSQL databases."); + _db_error_page("The database type '". $db_type ."' is unsupported. Please use either 'mysql', 'mysqli' or 'pdo_mysql' for MySQL; 'pgsql' or 'pdo_pgsql' for PostgreSQL databases; 'oci8' for Oracle databases; 'ibm_db2' for IBM DB2 databases."); } $db_conns[$name] = db_connect($connect_url); @@ -199,23 +200,30 @@ function db_is_active() { * Helper function for db_query(). */ function _db_query_callback($match, $init = FALSE) { - static $args = NULL; + static $args = NULL, $ident = NULL, $count = 0; if ($init) { - $args = $match; - return; + if ($match) { + $count = 0; + $ident = substr(md5($match['query']), 1, 8); + $args = array_values($match['args']); + return; + } + return $args; } + $current = $count++; + $locator = ":l". $ident . $current; switch ($match[1]) { - case '%d': // We must use type casting to int to convert FALSE/NULL/(TRUE?) - return (int) array_shift($args); // We don't need db_escape_string as numbers are db-safe - case '%s': - return db_escape_string(array_shift($args)); - case '%%': - return '%'; + case '%d': + return db_escape_decimal($args[$current], $locator); case '%f': - return (float) array_shift($args); - case '%b': // binary data - return db_encode_blob(array_shift($args)); + return db_escape_float($args[$current], $locator); + case '%s': + return db_escape_string($args[$current], $locator); + case '%b': // Binary Large OBject. + return db_encode_blob($args[$current], $locator); + case '%c': // Character Large OBject. + return db_encode_clob($args[$current], $locator); } } @@ -238,7 +246,7 @@ function db_placeholders($arguments, $ty /** * Indicates the place holders that should be replaced in _db_query_callback(). */ -define('DB_QUERY_REGEXP', '/(%d|%s|%%|%f|%b)/'); +define('DB_QUERY_REGEXP', '/(%d|%f|%s|%b|%c)/'); /** * Helper function for db_rewrite_sql. @@ -260,7 +268,7 @@ define('DB_QUERY_REGEXP', '/(%d|%s|%%|%f * @return * An array: join statements, where statements, field or DISTINCT(field). */ -function _db_rewrite_sql($query = '', $primary_table = 'n', $primary_field = 'nid', $args = array()) { +function _db_rewrite_sql($query = '', $primary_table = 'n', $primary_field = '[nid]', $args = array()) { $where = array(); $join = array(); $distinct = FALSE; @@ -307,7 +315,7 @@ function _db_rewrite_sql($query = '', $p * The original query with JOIN and WHERE statements inserted from * hook_db_rewrite_sql implementations. nid is rewritten if needed. */ -function db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $args = array()) { +function db_rewrite_sql($query, $primary_table = 'n', $primary_field = '[nid]', $args = array()) { list($join, $where, $distinct) = _db_rewrite_sql($query, $primary_table, $primary_field, $args); if ($distinct) { @@ -540,15 +548,7 @@ function db_type_placeholder($type) { case 'char': case 'text': case 'datetime': - return '\'%s\''; - case 'numeric': - // For 'numeric' values, we use '%s', not '\'%s\'' as with - // string types, because numeric values should not be enclosed - // in quotes in queries (though they can be, at least on mysql - // and pgsql). Numerics should only have [0-9.+-] and - // presumably no db's "escape string" function will mess with - // those characters. return '%s'; case 'serial': @@ -560,6 +560,9 @@ function db_type_placeholder($type) { case 'blob': return '%b'; + + case 'clob': + return '%c'; } // There is no safe value to return here, so return something that Index: includes/database.mysql-common.inc =================================================================== RCS file: includes/database.mysql-common.inc diff -N includes/database.mysql-common.inc --- includes/database.mysql-common.inc 23 Dec 2007 13:22:12 -0000 1.16 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,533 +0,0 @@ - $field) { - $sql .= _db_create_field_sql($field_name, _db_process_field($field)) .", \n"; - } - - // Process keys & indexes. - $keys = _db_create_keys_sql($table); - if (count($keys)) { - $sql .= implode(", \n", $keys) .", \n"; - } - - // Remove the last comma and space. - $sql = substr($sql, 0, -3) ."\n) "; - - $sql .= $table['mysql_suffix']; - - return array($sql); -} - -function _db_create_keys_sql($spec) { - $keys = array(); - - if (!empty($spec['primary key'])) { - $keys[] = 'PRIMARY KEY ('. _db_create_key_sql($spec['primary key']) .')'; - } - if (!empty($spec['unique keys'])) { - foreach ($spec['unique keys'] as $key => $fields) { - $keys[] = 'UNIQUE KEY '. $key .' ('. _db_create_key_sql($fields) .')'; - } - } - if (!empty($spec['indexes'])) { - foreach ($spec['indexes'] as $index => $fields) { - $keys[] = 'INDEX '. $index .' ('. _db_create_key_sql($fields) .')'; - } - } - - return $keys; -} - -function _db_create_key_sql($fields) { - $ret = array(); - foreach ($fields as $field) { - if (is_array($field)) { - $ret[] = $field[0] .'('. $field[1] .')'; - } - else { - $ret[] = $field; - } - } - return implode(', ', $ret); -} - -/** - * Set database-engine specific properties for a field. - * - * @param $field - * A field description array, as specified in the schema documentation. - */ -function _db_process_field($field) { - - if (!isset($field['size'])) { - $field['size'] = 'normal'; - } - - // Set the correct database-engine specific datatype. - if (!isset($field['mysql_type'])) { - $map = db_type_map(); - $field['mysql_type'] = $map[$field['type'] .':'. $field['size']]; - } - - if ($field['type'] == 'serial') { - $field['auto_increment'] = TRUE; - } - - return $field; -} - -/** - * Create an SQL string for a field to be used in table creation or alteration. - * - * Before passing a field out of a schema definition into this function it has - * to be processed by _db_process_field(). - * - * @param $name - * Name of the field. - * @param $spec - * The field specification, as per the schema data structure format. - */ -function _db_create_field_sql($name, $spec) { - $sql = "`". $name ."` ". $spec['mysql_type']; - - if (isset($spec['length'])) { - $sql .= '('. $spec['length'] .')'; - } - elseif (isset($spec['precision']) && isset($spec['scale'])) { - $sql .= '('. $spec['scale'] .', '. $spec['precision'] .')'; - } - - if (!empty($spec['unsigned'])) { - $sql .= ' unsigned'; - } - - if (!empty($spec['not null'])) { - $sql .= ' NOT NULL'; - } - - if (!empty($spec['auto_increment'])) { - $sql .= ' auto_increment'; - } - - if (isset($spec['default'])) { - if (is_string($spec['default'])) { - $spec['default'] = "'". $spec['default'] ."'"; - } - $sql .= ' DEFAULT '. $spec['default']; - } - - if (empty($spec['not null']) && !isset($spec['default'])) { - $sql .= ' DEFAULT NULL'; - } - - return $sql; -} - -/** - * This maps a generic data type in combination with its data size - * to the engine-specific data type. - */ -function db_type_map() { - // Put :normal last so it gets preserved by array_flip. This makes - // it much easier for modules (such as schema.module) to map - // database types back into schema types. - $map = array( - 'varchar:normal' => 'VARCHAR', - 'char:normal' => 'CHAR', - - 'text:tiny' => 'SMALLTEXT', - 'text:small' => 'SMALLTEXT', - 'text:medium' => 'MEDIUMTEXT', - 'text:big' => 'LONGTEXT', - 'text:normal' => 'TEXT', - - 'serial:tiny' => 'TINYINT', - 'serial:small' => 'SMALLINT', - 'serial:medium' => 'MEDIUMINT', - 'serial:big' => 'BIGINT', - 'serial:normal' => 'INT', - - 'int:tiny' => 'TINYINT', - 'int:small' => 'SMALLINT', - 'int:medium' => 'MEDIUMINT', - 'int:big' => 'BIGINT', - 'int:normal' => 'INT', - - 'float:tiny' => 'FLOAT', - 'float:small' => 'FLOAT', - 'float:medium' => 'FLOAT', - 'float:big' => 'DOUBLE', - 'float:normal' => 'FLOAT', - - 'numeric:normal' => 'DECIMAL', - - 'blob:big' => 'LONGBLOB', - 'blob:normal' => 'BLOB', - - 'datetime:normal' => 'DATETIME', - ); - return $map; -} - -/** - * Rename a table. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be renamed. - * @param $new_name - * The new name for the table. - */ -function db_rename_table(&$ret, $table, $new_name) { - $ret[] = update_sql('ALTER TABLE {'. $table .'} RENAME TO {'. $new_name .'}'); -} - -/** - * Drop a table. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be dropped. - */ -function db_drop_table(&$ret, $table) { - $ret[] = update_sql('DROP TABLE {'. $table .'}'); -} - -/** - * Add a new field to a table. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * Name of the table to be altered. - * @param $field - * Name of the field to be added. - * @param $spec - * The field specification array, as taken from a schema definition. - * The specification may also contain the key 'initial', the newly - * created field will be set to the value of the key in all rows. - * This is most useful for creating NOT NULL columns with no default - * value in existing tables. - * @param $keys_new - * Optional keys and indexes specification to be created on the - * table along with adding the field. The format is the same as a - * table specification but without the 'fields' element. If you are - * adding a type 'serial' field, you MUST specify at least one key - * or index including it in this array. @see db_change_field for more - * explanation why. - */ -function db_add_field(&$ret, $table, $field, $spec, $keys_new = array()) { - $fixnull = FALSE; - if (!empty($spec['not null']) && !isset($spec['default'])) { - $fixnull = TRUE; - $spec['not null'] = FALSE; - } - $query = 'ALTER TABLE {'. $table .'} ADD '; - $query .= _db_create_field_sql($field, _db_process_field($spec)); - if (count($keys_new)) { - $query .= ', ADD '. implode(', ADD ', _db_create_keys_sql($keys_new)); - } - $ret[] = update_sql($query); - if (isset($spec['initial'])) { - // All this because update_sql does not support %-placeholders. - $sql = 'UPDATE {'. $table .'} SET '. $field .' = '. db_type_placeholder($spec['type']); - $result = db_query($sql, $spec['initial']); - $ret[] = array('success' => $result !== FALSE, 'query' => check_plain($sql .' ('. $spec['initial'] .')')); - } - if ($fixnull) { - $spec['not null'] = TRUE; - db_change_field($ret, $table, $field, $field, $spec); - } -} - -/** - * Drop a field. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $field - * The field to be dropped. - */ -function db_drop_field(&$ret, $table, $field) { - $ret[] = update_sql('ALTER TABLE {'. $table .'} DROP '. $field); -} - -/** - * Set the default value for a field. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $field - * The field to be altered. - * @param $default - * Default value to be set. NULL for 'default NULL'. - */ -function db_field_set_default(&$ret, $table, $field, $default) { - if ($default == NULL) { - $default = 'NULL'; - } - else { - $default = is_string($default) ? "'$default'" : $default; - } - - $ret[] = update_sql('ALTER TABLE {'. $table .'} ALTER COLUMN '. $field .' SET DEFAULT '. $default); -} - -/** - * Set a field to have no default value. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $field - * The field to be altered. - */ -function db_field_set_no_default(&$ret, $table, $field) { - $ret[] = update_sql('ALTER TABLE {'. $table .'} ALTER COLUMN '. $field .' DROP DEFAULT'); -} - -/** - * Add a primary key. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $fields - * Fields for the primary key. - */ -function db_add_primary_key(&$ret, $table, $fields) { - $ret[] = update_sql('ALTER TABLE {'. $table .'} ADD PRIMARY KEY ('. - _db_create_key_sql($fields) .')'); -} - -/** - * Drop the primary key. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - */ -function db_drop_primary_key(&$ret, $table) { - $ret[] = update_sql('ALTER TABLE {'. $table .'} DROP PRIMARY KEY'); -} - -/** - * Add a unique key. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $name - * The name of the key. - * @param $fields - * An array of field names. - */ -function db_add_unique_key(&$ret, $table, $name, $fields) { - $ret[] = update_sql('ALTER TABLE {'. $table .'} ADD UNIQUE KEY '. - $name .' ('. _db_create_key_sql($fields) .')'); -} - -/** - * Drop a unique key. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $name - * The name of the key. - */ -function db_drop_unique_key(&$ret, $table, $name) { - $ret[] = update_sql('ALTER TABLE {'. $table .'} DROP KEY '. $name); -} - -/** - * Add an index. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $name - * The name of the index. - * @param $fields - * An array of field names. - */ -function db_add_index(&$ret, $table, $name, $fields) { - $query = 'ALTER TABLE {'. $table .'} ADD INDEX '. $name .' ('. _db_create_key_sql($fields) .')'; - $ret[] = update_sql($query); -} - -/** - * Drop an index. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $name - * The name of the index. - */ -function db_drop_index(&$ret, $table, $name) { - $ret[] = update_sql('ALTER TABLE {'. $table .'} DROP INDEX '. $name); -} - -/** - * Change a field definition. - * - * IMPORTANT NOTE: To maintain database portability, you have to explicitly - * recreate all indices and primary keys that are using the changed field. - * - * That means that you have to drop all affected keys and indexes with - * db_drop_{primary_key,unique_key,index}() before calling db_change_field(). - * To recreate the keys and indices, pass the key definitions as the - * optional $keys_new argument directly to db_change_field(). - * - * For example, suppose you have: - * @code - * $schema['foo'] = array( - * 'fields' => array( - * 'bar' => array('type' => 'int', 'not null' => TRUE) - * ), - * 'primary key' => array('bar') - * ); - * @endcode - * and you want to change foo.bar to be type serial, leaving it as the - * primary key. The correct sequence is: - * @code - * db_drop_primary_key($ret, 'foo'); - * db_change_field($ret, 'foo', 'bar', 'bar', - * array('type' => 'serial', 'not null' => TRUE), - * array('primary key' => array('bar'))); - * @endcode - * - * The reasons for this are due to the different database engines: - * - * On PostgreSQL, changing a field definition involves adding a new field - * and dropping an old one which* causes any indices, primary keys and - * sequences (from serial-type fields) that use the changed field to be dropped. - * - * On MySQL, all type 'serial' fields must be part of at least one key - * or index as soon as they are created. You cannot use - * db_add_{primary_key,unique_key,index}() for this purpose because - * the ALTER TABLE command will fail to add the column without a key - * or index specification. The solution is to use the optional - * $keys_new argument to create the key or index at the same time as - * field. - * - * You could use db_add_{primary_key,unique_key,index}() in all cases - * unless you are converting a field to be type serial. You can use - * the $keys_new argument in all cases. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * Name of the table. - * @param $field - * Name of the field to change. - * @param $field_new - * New name for the field (set to the same as $field if you don't want to change the name). - * @param $spec - * The field specification for the new field. - * @param $keys_new - * Optional keys and indexes specification to be created on the - * table along with changing the field. The format is the same as a - * table specification but without the 'fields' element. - */ - -function db_change_field(&$ret, $table, $field, $field_new, $spec, $keys_new = array()) { - $sql = 'ALTER TABLE {'. $table .'} CHANGE '. $field .' '. - _db_create_field_sql($field_new, _db_process_field($spec)); - if (count($keys_new)) { - $sql .= ', ADD '. implode(', ADD ', _db_create_keys_sql($keys_new)); - } - $ret[] = update_sql($sql); -} - -/** - * Returns the last insert id. - * - * @param $table - * The name of the table you inserted into. - * @param $field - * The name of the autoincrement field. - */ -function db_last_insert_id($table, $field) { - return db_result(db_query('SELECT LAST_INSERT_ID()')); -} Index: includes/database.mysql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.mysql.inc,v retrieving revision 1.87 diff -u -p -r1.87 database.mysql.inc --- includes/database.mysql.inc 4 Jan 2008 09:31:48 -0000 1.87 +++ includes/database.mysql.inc 16 Jan 2008 15:38:11 -0000 @@ -11,51 +11,23 @@ * @{ */ -// Include functions shared between mysql and mysqli. -require_once './includes/database.mysql-common.inc'; +// Include functions shared between mysql, mysqli and pdo_mysql. +require_once './includes/common.mysql.inc'; -/** - * Report database status. - */ -function db_status_report($phase) { - $t = get_t(); - - $version = db_version(); - - $form['mysql'] = array( - 'title' => $t('MySQL database'), - 'value' => ($phase == 'runtime') ? l($version, 'admin/reports/status/sql') : $version, - ); - - if (version_compare($version, DRUPAL_MINIMUM_MYSQL) < 0) { - $form['mysql']['severity'] = REQUIREMENT_ERROR; - $form['mysql']['description'] = $t('Your MySQL Server is too old. Drupal requires at least MySQL %version.', array('%version' => DRUPAL_MINIMUM_MYSQL)); - } - - return $form; -} - -/** - * Returns the version of the database server currently in use. - * - * @return Database server version - */ -function db_version() { - list($version) = explode('-', mysql_get_server_info()); - return $version; -} +// Include schema API shared between mysql, mysqli and pdo_mysql. +require_once './includes/schema.mysql.inc'; /** * Initialize a database connection. */ function db_connect($url) { - $url = parse_url($url); - // Check if MySQL support is present in PHP - if (!function_exists('mysql_connect')) { - _db_error_page('Unable to use the MySQL database because the MySQL extension for PHP is not installed. Check your php.ini to see how you can enable it.'); + if (!(function_exists('mysql_connect') && extension_loaded('mysql'))) { + _db_error_page('Unable to use the MySQL database because the mysql extension for PHP is not installed. Check your php.ini to see how you can enable it.'); } + $url = parse_url($url); + // Decode url-encoded information in the db connection string $url['user'] = urldecode($url['user']); // Test if database url has a password. @@ -93,6 +65,43 @@ function db_connect($url) { } /** + * Runs a basic query in the active database. + * + * 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. Instead of a variable number of query arguments, + * you may also pass a single array containing the query arguments. + * + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query($query) { + $args = func_get_args(); + array_shift($args); + $query = db_prefix_tables($query); + $query = db_escape_quote($query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + _db_query_callback(array('query' => $query, 'args' => $args), TRUE); + $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); + return _db_query($query); +} + +/** * Helper function for db_query(). */ function _db_query($query, $debug = 0) { @@ -205,94 +214,26 @@ function db_affected_rows() { return mysql_affected_rows($active_db); } -/** - * 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. The query arguments can be enclosed in one - * array instead. - * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose - * in '') and %%. - * - * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, - * and TRUE values to decimal 1. - * - * @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. +/* + * Prepare user input for use in a database query, preventing SQL injection attacks. */ -function db_query_range($query) { - $args = func_get_args(); - $count = array_pop($args); - $from = array_pop($args); - array_shift($args); - - $query = db_prefix_tables($query); - if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax - $args = $args[0]; - } - _db_query_callback($args, TRUE); - $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); - $query .= ' LIMIT '. (int)$from .', '. (int)$count; - return _db_query($query); +function db_escape_decimal($data) { + return (int) $data; } /** - * Runs a SELECT query and stores its results in a temporary table. - * - * Use this as a substitute for db_query() when the results need to stored - * in a temporary table. Temporary tables exist for the duration of the page - * request. - * 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. - * - * Note that if you need to know how many results were returned, you should do - * a SELECT COUNT(*) on the temporary table afterwards. db_affected_rows() does - * not give consistent result across different database types in this case. - * - * @param $query - * A string containing a normal SELECT SQL query. - * @param ... - * A variable number of arguments which are substituted into the query - * using printf() syntax. The query arguments can be enclosed in one - * array instead. - * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose - * in '') and %%. - * - * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, - * and TRUE values to decimal 1. - * - * @param $table - * The name of the temporary table to select into. This name will not be - * prefixed as there is no risk of collision. - * @return - * A database query result resource, or FALSE if the query was not executed - * correctly. + * Prepare user input for use in a database query, preventing SQL injection attacks. */ -function db_query_temporary($query) { - $args = func_get_args(); - $tablename = array_pop($args); - array_shift($args); +function db_escape_float($data) { + return (float) $data; +} - $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE '. $tablename .' Engine=HEAP SELECT', db_prefix_tables($query)); - if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax - $args = $args[0]; - } - _db_query_callback($args, TRUE); - $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); - return _db_query($query); +/** + * Prepare user input for use in a database query, preventing SQL injection attacks. + */ +function db_escape_string($data) { + global $active_db; + return "'". mysql_real_escape_string($data, $active_db) ."'"; } /** @@ -301,7 +242,7 @@ function db_query_temporary($query) { * @param $data * Data to encode. * @return - * Encoded data. + * Encoded data. */ function db_encode_blob($data) { global $active_db; @@ -314,63 +255,35 @@ function db_encode_blob($data) { * @param $data * Data to decode. * @return - * Decoded data. + * Decoded data. */ function db_decode_blob($data) { return $data; } /** - * Prepare user input for use in a database query, preventing SQL injection attacks. + * Returns a properly formatted Character Large OBject value. + * + * @param $data + * Data to encode. + * @return + * Encoded data. */ -function db_escape_string($text) { +function db_encode_clob($data) { global $active_db; - return mysql_real_escape_string($text, $active_db); -} - -/** - * Lock a table. - */ -function db_lock_table($table) { - db_query('LOCK TABLES {'. db_escape_table($table) .'} WRITE'); -} - -/** - * Unlock all locked tables. - */ -function db_unlock_tables() { - db_query('UNLOCK TABLES'); -} - -/** - * Check if a table exists. - */ -function db_table_exists($table) { - return (bool) db_fetch_object(db_query("SHOW TABLES LIKE '{". db_escape_table($table) ."}'")); -} - -/** - * Check if a column exists in the given table. - */ -function db_column_exists($table, $column) { - return (bool) db_fetch_object(db_query("SHOW COLUMNS FROM {". db_escape_table($table) ."} LIKE '". db_escape_table($column) ."'")); + return "'". mysql_real_escape_string($data, $active_db) ."'"; } /** - * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to - * the SELECT list entry of the given query and the resulting query is returned. - * This function only applies the wrapper if a DISTINCT doesn't already exist in - * the query. + * Returns text from a Character Large Object value. * - * @param $table Table containing the field to set as DISTINCT - * @param $field Field to set as DISTINCT - * @param $query Query to apply the wrapper to - * @return SQL query with the DISTINCT wrapper surrounding the given table.field. + * @param $data + * Data to decode. + * @return + * Decoded data. */ -function db_distinct_field($table, $field, $query) { - $field_to_select = 'DISTINCT('. $table .'.'. $field .')'; - // (? $t('MySQL database'), - 'value' => ($phase == 'runtime') ? l($version, 'admin/reports/status/sql') : $version, - ); - - if (version_compare($version, DRUPAL_MINIMUM_MYSQL) < 0) { - $form['mysql']['severity'] = REQUIREMENT_ERROR; - $form['mysql']['description'] = $t('Your MySQL Server is too old. Drupal requires at least MySQL %version.', array('%version' => DRUPAL_MINIMUM_MYSQL)); - } - - return $form; -} - -/** - * Returns the version of the database server currently in use. - * - * @return Database server version - */ -function db_version() { - global $active_db; - list($version) = explode('-', mysqli_get_server_info($active_db)); - return $version; -} +// Include schema API shared between mysql, mysqli and pdo_mysql. +require_once './includes/schema.mysql.inc'; /** * Initialise a database connection. @@ -56,8 +27,8 @@ function db_version() { */ function db_connect($url) { // Check if MySQLi support is present in PHP - if (!function_exists('mysqli_init') && !extension_loaded('mysqli')) { - _db_error_page('Unable to use the MySQLi database because the MySQLi extension for PHP is not installed. Check your php.ini to see how you can enable it.'); + if (!(function_exists('mysqli_init') && extension_loaded('mysqli'))) { + _db_error_page('Unable to use the MySQL database because the mysqli extension for PHP is not installed. Check your php.ini to see how you can enable it.'); } $url = parse_url($url); @@ -91,6 +62,43 @@ function db_connect($url) { } /** + * Runs a basic query in the active database. + * + * 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. Instead of a variable number of query arguments, + * you may also pass a single array containing the query arguments. + * + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query($query) { + $args = func_get_args(); + array_shift($args); + $query = db_prefix_tables($query); + $query = db_escape_quote($query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + _db_query_callback(array('query' => $query, 'args' => $args), TRUE); + $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); + return _db_query($query); +} + +/** * Helper function for db_query(). */ function _db_query($query, $debug = 0) { @@ -205,94 +213,26 @@ function db_affected_rows() { return mysqli_affected_rows($active_db); } -/** - * 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. The query arguments can be enclosed in one - * array instead. - * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose - * in '') and %%. - * - * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, - * and TRUE values to decimal 1. - * - * @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. +/* + * Prepare user input for use in a database query, preventing SQL injection attacks. */ -function db_query_range($query) { - $args = func_get_args(); - $count = array_pop($args); - $from = array_pop($args); - array_shift($args); - - $query = db_prefix_tables($query); - if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax - $args = $args[0]; - } - _db_query_callback($args, TRUE); - $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); - $query .= ' LIMIT '. (int)$from .', '. (int)$count; - return _db_query($query); +function db_escape_decimal($data) { + return (int) $data; } /** - * Runs a SELECT query and stores its results in a temporary table. - * - * Use this as a substitute for db_query() when the results need to stored - * in a temporary table. Temporary tables exist for the duration of the page - * request. - * 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. - * - * Note that if you need to know how many results were returned, you should do - * a SELECT COUNT(*) on the temporary table afterwards. db_affected_rows() does - * not give consistent result across different database types in this case. - * - * @param $query - * A string containing a normal SELECT SQL query. - * @param ... - * A variable number of arguments which are substituted into the query - * using printf() syntax. The query arguments can be enclosed in one - * array instead. - * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose - * in '') and %%. - * - * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, - * and TRUE values to decimal 1. - * - * @param $table - * The name of the temporary table to select into. This name will not be - * prefixed as there is no risk of collision. - * @return - * A database query result resource, or FALSE if the query was not executed - * correctly. + * Prepare user input for use in a database query, preventing SQL injection attacks. */ -function db_query_temporary($query) { - $args = func_get_args(); - $tablename = array_pop($args); - array_shift($args); +function db_escape_float($data) { + return (float) $data; +} - $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE '. $tablename .' Engine=HEAP SELECT', db_prefix_tables($query)); - if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax - $args = $args[0]; - } - _db_query_callback($args, TRUE); - $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); - return _db_query($query); +/** + * Prepare user input for use in a database query, preventing SQL injection attacks. + */ +function db_escape_string($data) { + global $active_db; + return "'". mysqli_real_escape_string($active_db, $data) ."'"; } /** @@ -301,7 +241,7 @@ function db_query_temporary($query) { * @param $data * Data to encode. * @return - * Encoded data. + * Encoded data. */ function db_encode_blob($data) { global $active_db; @@ -309,71 +249,42 @@ function db_encode_blob($data) { } /** - * Returns text from a Binary Large OBject value. + * Returns text from a Binary Large Object value. * * @param $data * Data to decode. * @return - * Decoded data. + * Decoded data. */ function db_decode_blob($data) { return $data; } /** - * Prepare user input for use in a database query, preventing SQL injection attacks. + * Returns a properly formatted Character Large OBject value. + * + * @param $data + * Data to encode. + * @return + * Encoded data. */ -function db_escape_string($text) { +function db_encode_clob($data) { global $active_db; - return mysqli_real_escape_string($active_db, $text); -} - -/** - * Lock a table. - */ -function db_lock_table($table) { - db_query('LOCK TABLES {'. db_escape_table($table) .'} WRITE'); -} - -/** - * Unlock all locked tables. - */ -function db_unlock_tables() { - db_query('UNLOCK TABLES'); -} - -/** - * Check if a table exists. - */ -function db_table_exists($table) { - return (bool) db_fetch_object(db_query("SHOW TABLES LIKE '{". db_escape_table($table) ."}'")); -} - -/** - * Check if a column exists in the given table. - */ -function db_column_exists($table, $column) { - return (bool) db_fetch_object(db_query("SHOW COLUMNS FROM {". db_escape_table($table) ."} LIKE '". db_escape_table($column) ."'")); + return "'". mysqli_real_escape_string($active_db, $data) ."'"; } /** - * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to - * the SELECT list entry of the given query and the resulting query is returned. - * This function only applies the wrapper if a DISTINCT doesn't already exist in - * the query. + * Returns text from a Character Large Object value. * - * @param $table Table containing the field to set as DISTINCT - * @param $field Field to set as DISTINCT - * @param $query Query to apply the wrapper to - * @return SQL query with the DISTINCT wrapper surrounding the given table.field. + * @param $data + * Data to decode. + * @return + * Decoded data. */ -function db_distinct_field($table, $field, $query) { - $field_to_select = 'DISTINCT('. $table .'.'. $field .')'; - // (?
");
+  print_r($msg);
+  print("
"); +} + +function _debug_query($query) { + //_print($query); + + if (preg_match('/[^\[\'{a-z0-9_:]([a-z0-9_{}]{3,})[^\]\'}a-z0-9_]/Ds', $query, $matches) && !preg_match('/[0-9]/', $matches[1])) { + _print("NO []: ". $query); + _print($matches); + } + if (preg_match("/'%s'/", $query)) { + _print("OLD '%s': ". $query); + } + if (preg_match("/[ ,]''[ ,]/", $query)) { + _print("EMPTY STRING '': ". $query); + } +} + +/** + * @file + * Database interface code for Oracle database servers. + */ + +/** + * Indicates the maximum size of last_results pool. We will free old + * statements which exists this limit, in order to prevent ORA-01000 error. + */ +define('OCI8_MAX_LAST_RESULTS', 256); + +/** + * Indicates the empty string placeholder. + */ +define('OCI8_EMPTY_STRING_PLACEHOLDER', chr(1)); + +/** + * @ingroup database + * @{ + */ + +// Include functions shared between oci8 and pdo_oci. +require_once './includes/common.oracle.inc'; + +// Include schema API shared between oci8 and pdo_oci. +require_once './includes/schema.oracle.inc'; + +/** + * Initialize a database connection. + */ +function db_connect($url) { + // Check if Oracle support is present in PHP + if (!(function_exists('oci_connect') && extension_loaded('oci8'))) { + _db_error_page('Unable to use the Oracle database because the oci8 extension for PHP is not installed. Check your php.ini to see how you can enable it.'); + } + + $url = parse_url($url); + + // Decode url-encoded information in the db connection string. + $url['user'] = urldecode($url['user']); + $url['pass'] = urldecode($url['pass']); + $url['host'] = urldecode($url['host']); + $url['path'] = urldecode($url['path']); + + // Build oci8 connection string and allow for non-standard Oracle port. + $conn_string = '//'. $url['host'] . (isset($url['port']) ? ':'. $url['port'] : '') .'/'. substr($url['path'], 1); + + // Even we can indicate charset parameter for oci_connect, which will be + // used in the new connection, we will not use this feature. Therefore + // NLS_LANG environment variable will be used instead. + $connection = @oci_connect($url['user'], $url['pass'], $conn_string); + + // Test connecting to the database. + if (!$connection) { + $error = oci_error(); + _db_error_page($error['message']); + } + + return $connection; +} + +/** + * Runs a basic query in the active database. + * + * 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. Instead of a variable number of query arguments, + * you may also pass a single array containing the query arguments. + * + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: use NULL as arguments substitution for %b and %c. This will be + * replaced as corresponding empty LOB value placeholder, based on the + * database specific representation. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query($query) { + $args = func_get_args(); + array_shift($args); + _debug_query($query); + $query = db_prefix_tables($query); + $query = db_escape_quote($query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + _db_query_callback(array('query' => $query, 'args' => $args), TRUE); + $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); + $args = _db_query_callback(NULL, TRUE); + return _db_query(array('query' => $query, 'args' => $args)); +} + +/** + * Helper function for db_query(). + */ +function _db_query($query, $debug = 0) { + global $active_db, $last_result, $queries; + static $last_stmts; + + // Expand $query if it is in array format. + $args = array(); + if (is_array($query)) { + $args = $query['args']; + $query = $query['query']; + + // Check if locator exists in query, or else unset it. + foreach ($args as $key => $value) { + if (!is_array($args[$key]) || !isset($args[$key]['locator']) || !strstr($query, $args[$key]['locator'])) { + unset($args[$key]); + } + } + } + + if (variable_get('dev_query', 0)) { + list($usec, $sec) = explode(' ', microtime()); + $timer = (float)$usec + (float)$sec; + // If devel.module query logging is enabled, prepend a comment with the username and calling function + // to the SQL string. This is useful when running mysql's SHOW PROCESSLIST to learn what exact + // code is issueing the slow query. + $bt = debug_backtrace(); + // t() may not be available yet so we don't wrap 'Anonymous' + $name = $user->uid ? $user->name : variable_get('anonymous', 'Anonymous'); + // str_replace() to prevent SQL injection via username or anonymous name. + $name = str_replace(array('*', '/'), '', $name); + $query = '/* '. $name .' : '. $bt[2]['function'] .' */ '. $query; + } + + $last_stmts = array_filter((array) $last_stmts); + $ident = md5($query); + if (isset($last_stmts[$ident])) { + // We parse this query once before, just reuse it. + $stmt = $last_stmts[$ident]; + unset($last_stmts[$ident]); + } + else { + // Perform actual query and return the result set. + $stmt = oci_parse($active_db, $query); + } + + // Try to free resources associated with Oracle's cursor or statement, + // or else our conection pool may busted. + array_push($last_stmts, array($ident => $stmt)); + while (count($last_stmts) >= ORACLE_MAX_CACHE_STMT) { + @oci_free_statement(array_shift($last_stmts)); + } + + if ($stmt === FALSE) { + // Indicate to drupal_error_handler that this is a database error. + ${DB_ERROR} = TRUE; + $error = oci_error($stmt); + trigger_error(check_plain($error['message'] ."\nquery: ". $query), E_USER_WARNING); + // On error, rollback the transaction. + oci_rollback($active_db); + return FALSE; + } + + if (count($args)) { + foreach ($args as $key => $value) { + if (isset($args[$key]['obj']) && is_object($args[$key]['obj'])) { + // Bind the returned Oracle LOB locator to the PHP LOB object. + oci_bind_by_name($stmt, $args[$key]['locator'], $args[$key]['obj'], -1, $args[$key]['type']); + } + else if (isset($args[$key]['type'])) { + oci_bind_by_name($stmt, $args[$key]['locator'], $args[$key]['data'], -1, $args[$key]['type']); + } + else { + oci_bind_by_name($stmt, $args[$key]['locator'], $args[$key]['data']); + } + } + } + + // Execute the statement using OCI_DEFAULT (begin a transaction) + $result = oci_execute($stmt, OCI_DEFAULT); + if ($result === FALSE) { + // Indicate to drupal_error_handler that this is a database error. + ${DB_ERROR} = TRUE; + $error = oci_error($stmt); + trigger_error(check_plain($error['message'] ."\nquery: ". $query), E_USER_WARNING); + // On error, rollback the transaction. + oci_rollback($active_db); + return FALSE; + } + + if (count($args)) { + foreach ($args as $key => $value) { + if (isset($args[$key]['obj']) && is_object($args[$key]['obj'])) { + if (!(@$args[$key]['obj']->truncate() && @$args[$key]['obj']->save($args[$key]['data']))) { + // On error, rollback the transaction. + oci_rollback($active_db); + return FALSE; + } + } + } + } + + // On success, commit the transaction + oci_commit($active_db); + + if (count($args)) { + foreach ($args as $key => $value) { + if (isset($args[$key]['obj']) && is_object($args[$key]['obj'])) { + // Free resources + $args[$key]['obj']->free(); + } + } + } + + if (variable_get('dev_query', 0)) { + $bt = debug_backtrace(); + $query = $bt[2]['function'] ."\n". $query; + list($usec, $sec) = explode(' ', microtime()); + $stop = (float)$usec + (float)$sec; + $diff = $stop - $timer; + $queries[] = array($query, $diff); + } + + if ($debug) { + $error = oci_error($stmt); + print '

query: '. $query .'
error:'. $error['message'] .'

'; + } + + $last_result = $stmt; + return $last_result; +} + +/** + * 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, or FALSE. The attributes + * of this object are the table fields selected by the query. + */ +function db_fetch_object($result) { + if ($result) { + if ($object = oci_fetch_object($result)) { + $return = new stdClass(); + foreach ((array) $object as $key => $value) { + $column = $key; + // Preform short-to-long mapping if required. + $column = variable_get('oracle_'. $column, $column); + // Replace empty string placeholder. + $return->$column = $value != OCI8_EMPTY_STRING_PLACEHOLDER ? $value : ''; + } + return $return; + } + } + return FALSE; +} + +/** + * 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, or FALSE. + * 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) { + if ($result) { + if ($array = oci_fetch_assoc($result)) { + $return = array(); + foreach ((array) $array as $key => $value) { + $column = $key; + // Preform short-to-long mapping if required. + $column = variable_get('oracle_'. $column, $column); + // Replace empty string placeholder. + $return[$column] = $value != OCI8_EMPTY_STRING_PLACEHOLDER ? $value : ''; + } + return $return; + } + } + return FALSE; +} + +/** + * 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(). + * @return + * The resulting field or FALSE. + */ +function db_result($result) { + if ($result && oci_fetch($result)) { + if ($value = oci_result($result, 1)) { + // Replace empty string placeholder. + $return = $value != OCI8_EMPTY_STRING_PLACEHOLDER ? $value : ''; + return $return; + } + } + return FALSE; +} + +/** + * Determine whether the previous query caused an error. + */ +function db_error() { + $error = oci_error(); + return $error['message']; +} + +/** + * Determine the number of rows changed by the preceding query. + */ +function db_affected_rows() { + global $last_result; + return oci_num_rows($last_result); +} + +/* + * Prepare user input for use in a database query, preventing SQL injection attacks. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_escape_decimal(&$data, $locator) { + $data = array( + 'locator' => $locator, + 'data' => (int) $data, + 'type' => SQLT_INT, + ); + return $locator; +} + +/** + * Prepare user input for use in a database query, preventing SQL injection attacks. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_escape_float(&$data, $locator) { + $data = array( + 'locator' => $locator, + 'data' => (float) $data, + 'type' => SQLT_FLT, + ); + return $locator; +} + +/** + * Prepare user input for use in a database query, preventing SQL injection attacks. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_escape_string(&$data, $locator) { + // Replace as empty string placeholder, if not an empty string nor NULL. + $data = ($data !== '' && !is_null($data)) ? $data : ORACLE_EMPTY_STRING_PLACEHOLDER; + // Trim first 4000 characters, based on Oracle VARCHAR2(4000) limitation. + $data = preg_replace('/(.{0,4000})(.*)/', '\1', $data); + + $data = array( + 'locator' => $locator, + 'data' => $data, + 'type' => SQLT_CHR, + ); + return $locator; +} + +/** + * Returns a properly formatted Binary Large OBject value. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_encode_blob(&$data, $locator) { + global $active_db; + $data = array( + 'locator' => $locator, + 'data' => $data, + 'obj' => oci_new_descriptor($active_db, OCI_D_LOB), + 'type' => SQLT_BLOB, + ); + return $locator; +} + +/** + * Returns text from a Binary Large OBject value. + * In case of Oracle LOBs are read via LOB->load(). + * + * @param $data + * Data to decode. + * @return + * Decoded data. + */ +function db_decode_blob($data) { + return is_object($data) ? $data->load() : $data; +} + +/** + * Returns a properly formatted Character Large OBject value. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_encode_clob(&$data, $locator) { + global $active_db; + $data = array( + 'locator' => $locator, + 'data' => $data, + 'obj' => oci_new_descriptor($active_db, OCI_D_LOB), + 'type' => SQLT_CLOB, + ); + return $locator; +} + +/** + * Returns text from a Character Large OBject value. + * In case of Oracle LOBs are read via LOB->load(). + * + * @param $data + * Data to decode. + * @return + * Decoded data. + */ +function db_decode_clob($data) { + return is_object($data) ? $data->load() : $data; +} + +/** + * @} End of "ingroup database". + */ Index: includes/database.pdo_mysql.inc =================================================================== RCS file: includes/database.pdo_mysql.inc diff -N includes/database.pdo_mysql.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/database.pdo_mysql.inc 16 Jan 2008 15:38:11 -0000 @@ -0,0 +1,273 @@ +getMessage()); + } + + // Force UTF-8 + $stmt = $connection->prepare('SET NAMES "utf8"'); + $stmt->execute(); + + // Force MySQL driver will use the buffered versions of the MySQL API. + $connection->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + + return $connection; +} + +/** + * Runs a basic query in the active database. + * + * 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. Instead of a variable number of query arguments, + * you may also pass a single array containing the query arguments. + * + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query($query) { + $args = func_get_args(); + array_shift($args); + $query = db_prefix_tables($query); + $query = db_escape_quote($query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + $args = array_values($args); + $query = preg_replace(DB_QUERY_REGEXP, '?', $query); + return _db_query(array('query' => $query, 'args' => $args)); +} + +/** + * Helper function for db_query(). + */ +function _db_query($query, $debug = 0) { + global $active_db, $last_result, $queries, $user; + + // Expand $query if it is in array format. + $args = array(); + if (is_array($query)) { + $args = $query['args']; + $query = $query['query']; + + // Check if arguments match number of placeholders, or else unset it. + $args = array_slice($args, 0, preg_match_all('/\?/', $query, $matches)); + } + + if (variable_get('dev_query', 0)) { + list($usec, $sec) = explode(' ', microtime()); + $timer = (float)$usec + (float)$sec; + // If devel.module query logging is enabled, prepend a comment with the username and calling function + // to the SQL string. This is useful when running mysql's SHOW PROCESSLIST to learn what exact + // code is issueing the slow query. + $bt = debug_backtrace(); + // t() may not be available yet so we don't wrap 'Anonymous' + $name = $user->uid ? $user->name : variable_get('anonymous', 'Anonymous'); + // str_replace() to prevent SQL injection via username or anonymous name. + $name = str_replace(array('*', '/'), '', $name); + $query = '/* '. $name .' : '. $bt[2]['function'] .' */ '. $query; + } + + $last_result = $active_db->prepare($query); + if (!$last_result) { + $error = $active_db->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + // Indicate to drupal_error_handler that this is a database error. + ${DB_ERROR} = TRUE; + trigger_error(check_plain($error[2] ."\nquery: ". $query), E_USER_WARNING); + } + return FALSE; + } + + if (count($args)) { + for ($i = 0; $i < count($args); $i++) { + $last_result->bindValue($i + 1, $args[$i]); + } + } + + $result = $last_result->execute(); + if (!$result) { + $error = $last_result->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + // Indicate to drupal_error_handler that this is a database error. + ${DB_ERROR} = TRUE; + trigger_error(check_plain($error[2] ."\nquery: ". $query), E_USER_WARNING); + } + return FALSE; + } + + if (variable_get('dev_query', 0)) { + $query = $bt[2]['function'] ."\n". $query; + list($usec, $sec) = explode(' ', microtime()); + $stop = (float)$usec + (float)$sec; + $diff = $stop - $timer; + $queries[] = array($query, $diff); + } + + if ($debug) { + print '

query: '. $query .'
error:'. $error[2] .'

'; + } + + return $last_result; +} + +/** + * 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, or FALSE. The attributes + * of this object are the table fields selected by the query. + */ +function db_fetch_object($result) { + if ($result) { + $object = $result->fetch(PDO::FETCH_OBJ); + return isset($object) ? $object : FALSE; + } +} + +/** + * 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, or FALSE. + * 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) { + if ($result) { + $array = $result->fetch(PDO::FETCH_ASSOC); + return isset($array) ? $array : FALSE; + } +} + +/** + * 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(). + * @return + * The resulting field or FALSE. + */ +function db_result($result) { + if ($result) { + $array = $result->fetch(PDO::FETCH_NUM); + return $array[0]; + } + return FALSE; +} + +/** + * Determine whether the previous query caused an error. + */ +function db_error() { + global $last_result; + $error = $last_result->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + return $error[2]; + } +} + +/** + * Determine the number of rows changed by the preceding query. + */ +function db_affected_rows() { + global $last_result; + return $last_result->rowCount(); +} + +/** + * Returns text from a Binary Large Object value. + * + * @param $data + * Data to decode. + * @return + * Decoded data. + */ +function db_decode_blob($data) { + return $data; +} + +/** + * Returns text from a Character Large Object value. + * + * @param $data + * Data to decode. + * @return + * Decoded data. + */ +function db_decode_clob($data) { + return $data; +} + +/** + * @} End of "ingroup database". + */ Index: includes/database.pdo_oci.inc =================================================================== RCS file: includes/database.pdo_oci.inc diff -N includes/database.pdo_oci.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/database.pdo_oci.inc 16 Jan 2008 15:38:11 -0000 @@ -0,0 +1,456 @@ +
");
+  print_r($msg);
+  print("
"); +} + +function _debug_query($query) { + //_print($query); + + if (preg_match('/[^\[\'{a-z0-9_:]([a-z0-9_{}]{3,})[^\]\'}a-z0-9_]/Ds', $query, $matches) && !preg_match('/[0-9]/', $matches[1])) { + _print("NO []: ". $query); + _print($matches); + } + if (preg_match("/'%s'/", $query)) { + _print("OLD '%s': ". $query); + } + if (preg_match("/[ ,]''[ ,]/", $query)) { + _print("EMPTY STRING '': ". $query); + } +} + +/** + * @file + * Database interface code for Oracle database servers. + */ + +/** + * @ingroup database + * @{ + */ + +// Include functions shared between oci8 and pdo_oci. +require_once './includes/common.oracle.inc'; + +// Include schema API shared between oci8 and pdo_oci. +require_once './includes/schema.oracle.inc'; + +/** + * Initialize a database connection. + */ +function db_connect($url) { + // Check if PDO PostgreSQL support is present in PHP. + if (!(class_exists('PDO') && extension_loaded('pdo_oci'))) { + _db_error_page('Unable to use the Oracle database because the pdo_oci extension for PHP is not installed. Check your php.ini to see how you can enable it.'); + } + + $url = parse_url($url); + + // Decode url-encoded information in the db connection string. + if (isset($url['user'])) { + $username = urldecode($url['user']); + } + if (isset($url['pass'])) { + $password = urldecode($url['pass']); + } + + // Connect with Oracle Instant Client partten. + $url['host'] = urldecode($url['host']); + $url['path'] = urldecode($url['path']); + // Build oci8 connection string and allow for non-standard Oracle port. + $dsn = 'oci:dbname=//'. $url['host'] . (isset($url['port']) ? ':'. $url['port'] : '') .'/'. substr($url['path'], 1); + + try { + $connection = new PDO($dsn, $username, $password); + } + catch(PDOExecption $e) { + _db_error_page($e->getMessage()); + } + + // Force Oracle driver NOT use the auto commit mode. + $connection->setAttribute(PDO::ATTR_AUTOCOMMIT, false); + + return $connection; +} + +/** + * Runs a basic query in the active database. + * + * 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. Instead of a variable number of query arguments, + * you may also pass a single array containing the query arguments. + * + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: use NULL as arguments substitution for %b and %c. This will be + * replaced as corresponding empty LOB value placeholder, based on the + * database specific representation. + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query($query) { + $args = func_get_args(); + array_shift($args); + _debug_query($query); + $query = db_prefix_tables($query); + $query = db_escape_quote($query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + _db_query_callback(array('query' => $query, 'args' => $args), TRUE); + $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); + $args = _db_query_callback(NULL, TRUE); + return _db_query(array('query' => $query, 'args' => $args)); +} + +/** + * Helper function for db_query(). + */ +function _db_query($query, $debug = 0) { + global $active_db, $last_result, $queries; + static $last_stmts; + + // Expand $query if it is in array format. + $args = array(); + if (is_array($query)) { + $args = $query['args']; + $query = $query['query']; + + // Check if locator exists in query, or else unset it. + foreach ($args as $key => $value) { + if (!is_array($args[$key]) || !isset($args[$key]['locator']) || !strstr($query, $args[$key]['locator'])) { + unset($args[$key]); + } + } + } + + if (variable_get('dev_query', 0)) { + list($usec, $sec) = explode(' ', microtime()); + $timer = (float)$usec + (float)$sec; + // If devel.module query logging is enabled, prepend a comment with the username and calling function + // to the SQL string. This is useful when running mysql's SHOW PROCESSLIST to learn what exact + // code is issueing the slow query. + $bt = debug_backtrace(); + // t() may not be available yet so we don't wrap 'Anonymous' + $name = $user->uid ? $user->name : variable_get('anonymous', 'Anonymous'); + // str_replace() to prevent SQL injection via username or anonymous name. + $name = str_replace(array('*', '/'), '', $name); + $query = '/* '. $name .' : '. $bt[2]['function'] .' */ '. $query; + } + + // Oracle need to preform INSERT/UPDATE under a transcation, otherwise the + // newly inserted LOB will be committed with a zero-length. + // Check http://php.net/pdo#pdo.lobs for more information. + try { + $active_db->beginTransaction(); + } + catch(PDOExecption $e) { + // TODO: No operation. + } + + $last_stmts = array_filter((array) $last_stmts); + $ident = md5($query); + if (isset($last_stmts[$ident])) { + // We parse this query once before, just reuse it. + $stmt = $last_stmts[$ident]; + unset($last_stmts[$ident]); + } + else { + // Perform actual query and return the result set. + $stmt = $active_db->prepare($query); + } + + // Try to free resources associated with Oracle's cursor or statement, + // or else our conection pool may busted. + array_push($last_stmts, array($ident => $stmt)); + while (count($last_stmts) >= ORACLE_MAX_CACHE_STMT) { + @array_shift($last_stmts)->closeCursor(); + } + + if (!$stmt) { + $error = $active_db->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + // Indicate to drupal_error_handler that this is a database error. + ${DB_ERROR} = TRUE; + trigger_error(check_plain($error[2] ."\nquery: ". $query), E_USER_WARNING); + } + return FALSE; + } + + if (count($args)) { + foreach ($args as $key => $value) { + if (isset($args[$key]['type'])) { + $stmt->bindValue($args[$key]['locator'], $args[$key]['data'], $args[$key]['type']); + } + else { + $stmt->bindValue($args[$key]['locator'], $args[$key]['data']); + } + } + } + + $result = $stmt->execute(); + if (!$result) { + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + // Indicate to drupal_error_handler that this is a database error. + ${DB_ERROR} = TRUE; + trigger_error(check_plain($error[2] ."\nquery: ". $query), E_USER_WARNING); + } + $active_db->rollBack(); + return FALSE; + } + $active_db->commit(); + + if (variable_get('dev_query', 0)) { + $query = $bt[2]['function'] ."\n". $query; + list($usec, $sec) = explode(' ', microtime()); + $stop = (float)$usec + (float)$sec; + $diff = $stop - $timer; + $queries[] = array($query, $diff); + } + + if ($debug) { + print '

query: '. $query .'
error:'. $error[2] .'

'; + } + + $last_result = $stmt; + return $last_result; +} + +/** + * 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, or FALSE. The attributes + * of this object are the table fields selected by the query. + */ +function db_fetch_object($result) { + if ($result) { + if ($object = $result->fetch(PDO::FETCH_OBJ)) { + $ret = new stdClass(); + foreach ((array) $object as $key => $value) { + $column = $key; + // Preform short-to-long mapping if required. + $column = variable_get('oracle_'. $column, $column); + // Replace empty string placeholder. + $ret->$column = $value != ORACLE_EMPTY_STRING_PLACEHOLDER ? $value : ''; + } + return $ret; + } + } + return FALSE; +} + +/** + * 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, or FALSE. + * 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) { + if ($result) { + if ($array = $result->fetch(PDO::FETCH_ASSOC)) { + $ret = array(); + foreach ((array) $array as $key => $value) { + $column = $key; + // Preform short-to-long mapping if required. + $column = variable_get('oracle_'. $column, $column); + // Replace empty string placeholder. + $ret[$column] = $value != ORACLE_EMPTY_STRING_PLACEHOLDER ? $value : ''; + } + return $ret; + } + } + return FALSE; +} + +/** + * 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(). + * @return + * The resulting field or FALSE. + */ +function db_result($result) { + if ($result) { + if ($array = $result->fetch(PDO::FETCH_NUM)) { + // Replace empty string placeholder. + $ret = $array[0] != ORACLE_EMPTY_STRING_PLACEHOLDER ? $array[0] : ''; + return $ret; + } + } + return FALSE; +} + +/** + * Determine whether the previous query caused an error. + */ +function db_error() { + global $last_result; + $error = $last_result->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + return $error[2]; + } +} + +/** + * Determine the number of rows changed by the preceding query. + */ +function db_affected_rows() { + global $last_result; + return $last_result->rowCount(); +} + +/* + * Prepare user input for use in a database query, preventing SQL injection attacks. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_escape_decimal(&$data, $locator) { + $data = array( + 'locator' => $locator, + 'data' => (int) $data, + ); + return $locator; +} + +/** + * Prepare user input for use in a database query, preventing SQL injection attacks. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_escape_float(&$data, $locator) { + $data = array( + 'locator' => $locator, + 'data' => (float) $data, + ); + return $locator; +} + +/** + * Prepare user input for use in a database query, preventing SQL injection attacks. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_escape_string(&$data, $locator) { + // Replace empty string placeholder. + $data = $data != '' ? $data : ORACLE_EMPTY_STRING_PLACEHOLDER; + // Trim first 4000 characters, based on Oracle VARCHAR2(4000) limitation. + $data = preg_replace('/(.{0,4000})(.*)/', '\1', $data); + + $data = array( + 'locator' => $locator, + 'data' => $data, + 'type' => PDO::PARAM_STR, + ); + return $locator; +} + +/** + * Returns a properly formatted Binary Large OBject value. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_encode_blob(&$data, $locator) { + $data = array( + 'locator' => $locator, + 'data' => $data, + 'type' => PDO::PARAM_LOB, + ); + return $locator; +} + +/** + * Returns text from a Binary Large OBject value. + * In case of Oracle LOBs are read via LOB->load(). + * + * @param $data + * Data to decode. + * @return + * Decoded data. + */ +function db_decode_blob($data) { + return stream_get_contents($data); +} + +/** + * Returns a properly formatted Character Large OBject value. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_encode_clob(&$data, $locator) { + $data = array( + 'locator' => $locator, + 'data' => $data, + 'type' => PDO::PARAM_LOB, + ); + return $locator; +} + +/** + * Returns text from a Character Large OBject value. + * In case of Oracle LOBs are read via LOB->load(). + * + * @param $data + * Data to decode. + * @return + * Decoded data. + */ +function db_decode_clob($data) { + return stream_get_contents($data); +} + +/** + * @} End of "ingroup database". + */ Index: includes/database.pdo_pgsql.inc =================================================================== RCS file: includes/database.pdo_pgsql.inc diff -N includes/database.pdo_pgsql.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/database.pdo_pgsql.inc 16 Jan 2008 15:38:11 -0000 @@ -0,0 +1,386 @@ +getMessage()); + } + + return $connection; +} + +/** + * Runs a basic query in the active database. + * + * 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. Instead of a variable number of query arguments, + * you may also pass a single array containing the query arguments. + * + * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose + * in '') and %c (character large object). + * + * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, + * and TRUE values to decimal 1. + * + * @return + * A database query result resource, or FALSE if the query was not + * executed correctly. + */ +function db_query($query) { + $args = func_get_args(); + array_shift($args); + $query = db_prefix_tables($query); + $query = db_escape_quote($query); + if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax + $args = $args[0]; + } + _db_query_callback(array('query' => $query, 'args' => $args), TRUE); + $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); + $args = _db_query_callback(NULL, TRUE); + return _db_query(array('query' => $query, 'args' => $args)); +} + +/** + * Helper function for db_query(). + */ +function _db_query($query, $debug = 0) { + global $active_db, $last_result, $queries, $user; + static $last_stmts; + + // Expand $query if it is in array format. + $args = array(); + if (is_array($query)) { + $args = $query['args']; + $query = $query['query']; + + // Check if locator exists in query, or else unset it. + foreach ($args as $key => $value) { + if (!is_array($args[$key]) || !isset($args[$key]['locator']) || !strstr($query, $args[$key]['locator'])) { + unset($args[$key]); + } + } + } + + if (variable_get('dev_query', 0)) { + list($usec, $sec) = explode(' ', microtime()); + $timer = (float)$usec + (float)$sec; + // If devel.module query logging is enabled, prepend a comment with the username and calling function + // to the SQL string. This is useful when running mysql's SHOW PROCESSLIST to learn what exact + // code is issueing the slow query. + $bt = debug_backtrace(); + // t() may not be available yet so we don't wrap 'Anonymous' + $name = $user->uid ? $user->name : variable_get('anonymous', 'Anonymous'); + // str_replace() to prevent SQL injection via username or anonymous name. + $name = str_replace(array('*', '/'), '', $name); + $query = '/* '. $name .' : '. $bt[2]['function'] .' */ '. $query; + } + + $ident = md5($query); + if (isset($last_stmts[$ident])) { + // We parse this query once before, just reuse it. + $stmt = $last_stmts[$ident]; + } + else { + // Perform actual query and return the result set. + $stmt = $active_db->prepare($query); + $last_stmts[$ident] = $stmt; + } + + if (!$stmt) { + $error = $active_db->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + // Indicate to drupal_error_handler that this is a database error. + ${DB_ERROR} = TRUE; + trigger_error(check_plain($error[2] ."\nquery: ". $query), E_USER_WARNING); + } + return FALSE; + } + + if (count($args)) { + foreach ($args as $key => $value) { + if (isset($args[$key]['type'])) { + $stmt->bindValue($args[$key]['locator'], $args[$key]['data'], $args[$key]['type']); + } + else { + $stmt->bindValue($args[$key]['locator'], $args[$key]['data']); + } + } + } + + $result = $stmt->execute(); + if (!$result) { + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + // Indicate to drupal_error_handler that this is a database error. + ${DB_ERROR} = TRUE; + trigger_error(check_plain($error[2] ."\nquery: ". $query), E_USER_WARNING); + } + return FALSE; + } + + if (variable_get('dev_query', 0)) { + $query = $bt[2]['function'] ."\n". $query; + list($usec, $sec) = explode(' ', microtime()); + $stop = (float)$usec + (float)$sec; + $diff = $stop - $timer; + $queries[] = array($query, $diff); + } + + if ($debug) { + print '

query: '. $query .'
error:'. $error[2] .'

'; + } + + $last_result = $stmt; + return $last_result; +} + +/** + * 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, or FALSE. The attributes + * of this object are the table fields selected by the query. + */ +function db_fetch_object($result) { + if ($result) { + $object = $result->fetch(PDO::FETCH_OBJ); + return isset($object) ? $object : FALSE; + } +} + +/** + * 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, or FALSE. + * 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) { + if ($result) { + $array = $result->fetch(PDO::FETCH_ASSOC); + return isset($array) ? $array : FALSE; + } +} + +/** + * 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(). + * @return + * The resulting field or FALSE. + */ +function db_result($result) { + if ($result) { + $array = $result->fetch(PDO::FETCH_NUM); + return $array[0]; + } + return FALSE; +} + +/** + * Determine whether the previous query caused an error. + */ +function db_error() { + global $last_result; + $error = $last_result->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + return $error[2]; + } +} + +/** + * Determine the number of rows changed by the preceding query. + */ +function db_affected_rows() { + global $last_result; + return $last_result->rowCount(); +} + +/* + * Prepare user input for use in a database query, preventing SQL injection attacks. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_escape_decimal(&$data, $locator) { + $data = array( + 'locator' => $locator, + 'data' => (int) $data, + ); + return $locator; +} + +/** + * Prepare user input for use in a database query, preventing SQL injection attacks. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_escape_float(&$data, $locator) { + $data = array( + 'locator' => $locator, + 'data' => (float) $data, + ); + return $locator; +} + +/** + * Prepare user input for use in a database query, preventing SQL injection attacks. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_escape_string(&$data, $locator) { + $data = array( + 'locator' => $locator, + 'data' => $data, + 'type' => PDO::PARAM_STR, + ); + return $locator; +} + +/** + * Returns a properly formatted Binary Large OBject value. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_encode_blob(&$data, $locator) { + // LOB for PgSQL must define by PDO::PARAM_LOB, or else will case error + // during INSER/UPDATE. So we need to use Oracle style locator-data-type + // variable binding for pdo_pgsql. + $data = array( + 'locator' => $locator, + 'data' => $data, + 'type' => PDO::PARAM_LOB, + ); + return $locator; +} + +/** + * Returns text from a Binary Large OBject value. + * + * @param $data + * Data to decode. + * @return + * Decoded data. + */ +function db_decode_blob($data) { + // pdo_pgsql return bytea as stream, so we just need to use Streams API. + // Check http://bugs.php.net/bug.php?id=37124 for more information. + return stream_get_contents($data); +} + +/** + * Returns a properly formatted Character Large OBject value. + * + * @param $data + * Data to encode. Return with processed array pattern for variable binding. + * @param #locator + * Locator for variable binding. + * @return + * Locator for variable binding. + */ +function db_encode_clob(&$data, $locator) { + $data = array( + 'locator' => $locator, + 'data' => $data, + 'type' => PDO::PARAM_STR, + ); + return $locator; +} + +/** + * Returns text from a Character Large OBject value. + * + * @param $data + * Data to decode. + * @return + * Decoded data. + */ +function db_decode_clob($data) { + return $data; +} + +/** + * @} End of "ingroup database". + */ Index: includes/database.pgsql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database.pgsql.inc,v retrieving revision 1.68 diff -u -p -r1.68 database.pgsql.inc --- includes/database.pgsql.inc 4 Jan 2008 09:31:48 -0000 1.68 +++ includes/database.pgsql.inc 16 Jan 2008 15:38:11 -0000 @@ -11,43 +11,19 @@ * @{ */ -/** - * Report database status. - */ -function db_status_report() { - $t = get_t(); - - $version = db_version(); - - $form['pgsql'] = array( - 'title' => $t('PostgreSQL database'), - 'value' => $version, - ); - - if (version_compare($version, DRUPAL_MINIMUM_PGSQL) < 0) { - $form['pgsql']['severity'] = REQUIREMENT_ERROR; - $form['pgsql']['description'] = $t('Your PostgreSQL Server is too old. Drupal requires at least PostgreSQL %version.', array('%version' => DRUPAL_MINIMUM_PGSQL)); - } - - return $form; -} +// Include functions shared between pgsql and pdo_pgsql. +require_once './includes/common.postgresql.inc'; -/** - * Returns the version of the database server currently in use. - * - * @return Database server version - */ -function db_version() { - return db_result(db_query("SHOW SERVER_VERSION")); -} +// Include schema API shared between pgsql and pdo_pgsql. +require_once './includes/schema.postgresql.inc'; /** * Initialize a database connection. */ function db_connect($url) { // Check if PostgreSQL support is present in PHP - if (!function_exists('pg_connect')) { - _db_error_page('Unable to use the PostgreSQL database because the PostgreSQL extension for PHP is not installed. Check your php.ini to see how you can enable it.'); + if (!(function_exists('pg_connect') && extension_loaded('pgsql'))) { + _db_error_page('Unable to use the PostgreSQL database because the pgsql extension for PHP is not installed. Check your php.ini to see how you can enable it.'); } $url = parse_url($url); @@ -103,7 +79,7 @@ function db_connect($url) { * you may also pass a single array containing the query arguments. * * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose - * in '') and %%. + * in '') and %c (character large object). * * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, * and TRUE values to decimal 1. @@ -116,10 +92,11 @@ function db_query($query) { $args = func_get_args(); array_shift($args); $query = db_prefix_tables($query); + $query = db_escape_quote($query); if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax $args = $args[0]; } - _db_query_callback($args, TRUE); + _db_query_callback(array('query' => $query, 'args' => $args), TRUE); $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); return _db_query($query); } @@ -138,12 +115,17 @@ function _db_query($query, $debug = 0) { $last_result = pg_query($active_db, $query); if (variable_get('dev_query', 0)) { - $bt = debug_backtrace(); - $query = $bt[2]['function'] ."\n". $query; list($usec, $sec) = explode(' ', microtime()); - $stop = (float)$usec + (float)$sec; - $diff = $stop - $timer; - $queries[] = array($query, $diff); + $timer = (float)$usec + (float)$sec; + // If devel.module query logging is enabled, prepend a comment with the username and calling function + // to the SQL string. This is useful when running mysql's SHOW PROCESSLIST to learn what exact + // code is issueing the slow query. + $bt = debug_backtrace(); + // t() may not be available yet so we don't wrap 'Anonymous' + $name = $user->uid ? $user->name : variable_get('anonymous', 'Anonymous'); + // str_replace() to prevent SQL injection via username or anonymous name. + $name = str_replace(array('*', '/'), '', $name); + $query = '/* '. $name .' : '. $bt[2]['function'] .' */ '. $query; } if ($debug) { @@ -220,18 +202,6 @@ function db_error() { } /** - * Returns the last insert id. This function is thread safe. - * - * @param $table - * The name of the table you inserted into. - * @param $field - * The name of the autoincrement field. - */ -function db_last_insert_id($table, $field) { - return db_result(db_query("SELECT CURRVAL('{". db_escape_table($table) ."}_". db_escape_table($field) ."_seq')")); -} - -/** * Determine the number of rows changed by the preceding query. */ function db_affected_rows() { @@ -239,95 +209,26 @@ function db_affected_rows() { return empty($last_result) ? 0 : pg_affected_rows($last_result); } -/** - * 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. Instead of a variable number of query arguments, - * you may also pass a single array containing the query arguments. - * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose - * in '') and %%. - * - * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, - * and TRUE values to decimal 1. - * - * @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. +/* + * Prepare user input for use in a database query, preventing SQL injection attacks. */ -function db_query_range($query) { - $args = func_get_args(); - $count = array_pop($args); - $from = array_pop($args); - array_shift($args); - - $query = db_prefix_tables($query); - if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax - $args = $args[0]; - } - _db_query_callback($args, TRUE); - $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); - $query .= ' LIMIT '. (int)$count .' OFFSET '. (int)$from; - return _db_query($query); +function db_escape_decimal($data) { + return (int) $data; } /** - * Runs a SELECT query and stores its results in a temporary table. - * - * Use this as a substitute for db_query() when the results need to stored - * in a temporary table. Temporary tables exist for the duration of the page - * request. - * 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. - * - * Note that if you need to know how many results were returned, you should do - * a SELECT COUNT(*) on the temporary table afterwards. db_affected_rows() does - * not give consistent result across different database types in this case. - * - * @param $query - * A string containing a normal SELECT SQL query. - * @param ... - * A variable number of arguments which are substituted into the query - * using printf() syntax. The query arguments can be enclosed in one - * array instead. - * Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose - * in '') and %%. - * - * NOTE: using this syntax will cast NULL and FALSE values to decimal 0, - * and TRUE values to decimal 1. - * - * @param $table - * The name of the temporary table to select into. This name will not be - * prefixed as there is no risk of collision. - * @return - * A database query result resource, or FALSE if the query was not executed - * correctly. + * Prepare user input for use in a database query, preventing SQL injection attacks. */ -function db_query_temporary($query) { - $args = func_get_args(); - $tablename = array_pop($args); - array_shift($args); +function db_escape_float($data) { + return (float) $data; +} - $query = preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE '. $tablename .' AS SELECT', db_prefix_tables($query)); - if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax - $args = $args[0]; - } - _db_query_callback($args, TRUE); - $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query); - return _db_query($query); +/** + * 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($data) { + return "'". pg_escape_string($data) ."'"; } /** @@ -337,7 +238,7 @@ function db_query_temporary($query) { * @param $data * Data to encode. * @return - * Encoded data. + * Encoded data. */ function db_encode_blob($data) { return "'". pg_escape_bytea($data) ."'"; @@ -350,577 +251,39 @@ function db_encode_blob($data) { * @param $data * Data to decode. * @return - * Decoded data. + * Decoded data. */ function db_decode_blob($data) { return pg_unescape_bytea($data); } /** - * 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) { - return pg_escape_string($text); -} - -/** - * Lock a table. - * This function automatically starts a transaction. - */ -function db_lock_table($table) { - db_query('BEGIN; LOCK TABLE {'. db_escape_table($table) .'} IN EXCLUSIVE MODE'); -} - -/** - * Unlock all locked tables. - * This function automatically commits a transaction. - */ -function db_unlock_tables() { - db_query('COMMIT'); -} - -/** - * Check if a table exists. - */ -function db_table_exists($table) { - return (bool) db_result(db_query("SELECT COUNT(*) FROM pg_class WHERE relname = '{". db_escape_table($table) ."}'")); -} - -/** - * Check if a column exists in the given table. - */ -function db_column_exists($table, $column) { - return (bool) db_result(db_query("SELECT COUNT(pg_attribute.attname) FROM pg_class, pg_attribute WHERE pg_attribute.attrelid = pg_class.oid AND pg_class.relname = '{". db_escape_table($table) ."}' AND attname = '". db_escape_table($column) ."'")); -} - -/** - * Verify if the database is set up correctly. - */ -function db_check_setup() { - $t = get_t(); - - $encoding = db_result(db_query('SHOW server_encoding')); - if (!in_array(strtolower($encoding), array('unicode', 'utf8'))) { - drupal_set_message($t('Your PostgreSQL database is set up with the wrong character encoding (%encoding). It is possible it will not work as expected. It is advised to recreate it with UTF-8/Unicode encoding. More information can be found in the PostgreSQL documentation.', array('%encoding' => $encoding, '@url' => 'http://www.postgresql.org/docs/7.4/interactive/multibyte.html')), 'status'); - } -} - -/** - * Wraps the given table.field entry with a DISTINCT(). The wrapper is added to - * the SELECT list entry of the given query and the resulting query is returned. - * This function only applies the wrapper if a DISTINCT doesn't already exist in - * the query. - * - * @param $table Table containing the field to set as DISTINCT - * @param $field Field to set as DISTINCT - * @param $query Query to apply the wrapper to - * @return SQL query with the DISTINCT wrapper surrounding the given table.field. - */ -function db_distinct_field($table, $field, $query) { - $field_to_select = 'DISTINCT ON ('. $table .'.'. $field .") $table.$field"; - // (? 'varchar', - 'char:normal' => 'character', - - 'text:tiny' => 'text', - 'text:small' => 'text', - 'text:medium' => 'text', - 'text:big' => 'text', - 'text:normal' => 'text', - - 'int:tiny' => 'smallint', - 'int:small' => 'smallint', - 'int:medium' => 'int', - 'int:big' => 'bigint', - 'int:normal' => 'int', - - 'float:tiny' => 'real', - 'float:small' => 'real', - 'float:medium' => 'real', - 'float:big' => 'double precision', - 'float:normal' => 'real', - - 'numeric:normal' => 'numeric', - - 'blob:big' => 'bytea', - 'blob:normal' => 'bytea', - - 'datetime:normal' => 'timestamp', - - 'serial:tiny' => 'serial', - 'serial:small' => 'serial', - 'serial:medium' => 'serial', - 'serial:big' => 'bigserial', - 'serial:normal' => 'serial', - ); - return $map; -} - -/** - * Generate SQL to create a new table from a Drupal schema definition. + * Returns a properly formatted Character Large OBject value. + * In case of PostgreSQL encodes data for insert or update into text field. * - * @param $name - * The name of the table to create. - * @param $table - * A Schema API table definition array. + * @param $data + * Data to encode. * @return - * An array of SQL statements to create the table. + * Encoded data. */ -function db_create_table_sql($name, $table) { - $sql_fields = array(); - foreach ($table['fields'] as $field_name => $field) { - $sql_fields[] = _db_create_field_sql($field_name, _db_process_field($field)); - } +function db_encode_clob($data) { + return "'". pg_escape_string($data) ."'"; - $sql_keys = array(); - if (isset($table['primary key']) && is_array($table['primary key'])) { - $sql_keys[] = 'PRIMARY KEY ('. implode(', ', $table['primary key']) .')'; - } - if (isset($table['unique keys']) && is_array($table['unique keys'])) { - foreach ($table['unique keys'] as $key_name => $key) { - $sql_keys[] = 'CONSTRAINT {'. $name .'}_'. $key_name .'_key UNIQUE ('. implode(', ', $key) .')'; - } - } - - $sql = "CREATE TABLE {". $name ."} (\n\t"; - $sql .= implode(",\n\t", $sql_fields); - if (count($sql_keys) > 0) { - $sql .= ",\n\t"; - } - $sql .= implode(",\n\t", $sql_keys); - $sql .= "\n)"; - $statements[] = $sql; - - if (isset($table['indexes']) && is_array($table['indexes'])) { - foreach ($table['indexes'] as $key_name => $key) { - $statements[] = _db_create_index_sql($name, $key_name, $key); - } - } - - return $statements; -} - -function _db_create_index_sql($table, $name, $fields) { - $query = 'CREATE INDEX {'. $table .'}_'. $name .'_idx ON {'. $table .'} ('; - $query .= _db_create_key_sql($fields) .')'; - return $query; -} - -function _db_create_key_sql($fields) { - $ret = array(); - foreach ($fields as $field) { - if (is_array($field)) { - $ret[] = 'substr('. $field[0] .', 1, '. $field[1] .')'; - } - else { - $ret[] = $field; - } - } - return implode(', ', $ret); -} - -function _db_create_keys(&$ret, $table, $new_keys) { - if (isset($new_keys['primary key'])) { - db_add_primary_key($ret, $table, $new_keys['primary key']); - } - if (isset($new_keys['unique keys'])) { - foreach ($new_keys['unique keys'] as $name => $fields) { - db_add_unique_key($ret, $table, $name, $fields); - } - } - if (isset($new_keys['indexes'])) { - foreach ($new_keys['indexes'] as $name => $fields) { - db_add_index($ret, $table, $name, $fields); - } - } -} - -/** - * Set database-engine specific properties for a field. - * - * @param $field - * A field description array, as specified in the schema documentation. - */ -function _db_process_field($field) { - if (!isset($field['size'])) { - $field['size'] = 'normal'; - } - // Set the correct database-engine specific datatype. - if (!isset($field['pgsql_type'])) { - $map = db_type_map(); - $field['pgsql_type'] = $map[$field['type'] .':'. $field['size']]; - } - if ($field['type'] == 'serial') { - unset($field['not null']); - } - return $field; -} - -/** - * Create an SQL string for a field to be used in table creation or alteration. - * - * Before passing a field out of a schema definition into this function it has - * to be processed by _db_process_field(). - * - * @param $name - * Name of the field. - * @param $spec - * The field specification, as per the schema data structure format. - */ -function _db_create_field_sql($name, $spec) { - $sql = $name .' '. $spec['pgsql_type']; - - if ($spec['type'] == 'serial') { - unset($spec['not null']); - } - if (!empty($spec['unsigned'])) { - if ($spec['type'] == 'serial') { - $sql .= " CHECK ($name >= 0)"; - } - else { - $sql .= '_unsigned'; - } - } - - if (!empty($spec['length'])) { - $sql .= '('. $spec['length'] .')'; - } - elseif (isset($spec['precision']) && isset($spec['scale'])) { - $sql .= '('. $spec['scale'] .', '. $spec['precision'] .')'; - } - - if (isset($spec['not null']) && $spec['not null']) { - $sql .= ' NOT NULL'; - } - if (isset($spec['default'])) { - $default = is_string($spec['default']) ? "'". $spec['default'] ."'" : $spec['default']; - $sql .= " default $default"; - } - - return $sql; -} - -/** - * Rename a table. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be renamed. - * @param $new_name - * The new name for the table. - */ -function db_rename_table(&$ret, $table, $new_name) { - $ret[] = update_sql('ALTER TABLE {'. $table .'} RENAME TO {'. $new_name .'}'); -} - -/** - * Drop a table. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be dropped. - */ -function db_drop_table(&$ret, $table) { - $ret[] = update_sql('DROP TABLE {'. $table .'}'); -} - -/** - * Add a new field to a table. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * Name of the table to be altered. - * @param $field - * Name of the field to be added. - * @param $spec - * The field specification array, as taken from a schema definition. - * The specification may also contain the key 'initial', the newly - * created field will be set to the value of the key in all rows. - * This is most useful for creating NOT NULL columns with no default - * value in existing tables. - * @param $keys_new - * Optional keys and indexes specification to be created on the - * table along with adding the field. The format is the same as a - * table specification but without the 'fields' element. If you are - * adding a type 'serial' field, you MUST specify at least one key - * or index including it in this array. @see db_change_field for more - * explanation why. - */ -function db_add_field(&$ret, $table, $field, $spec, $new_keys = array()) { - $fixnull = FALSE; - if (!empty($spec['not null']) && !isset($spec['default'])) { - $fixnull = TRUE; - $spec['not null'] = FALSE; - } - $query = 'ALTER TABLE {'. $table .'} ADD COLUMN '; - $query .= _db_create_field_sql($field, _db_process_field($spec)); - $ret[] = update_sql($query); - if (isset($spec['initial'])) { - // All this because update_sql does not support %-placeholders. - $sql = 'UPDATE {'. $table .'} SET '. $field .' = '. db_type_placeholder($spec['type']); - $result = db_query($sql, $spec['initial']); - $ret[] = array('success' => $result !== FALSE, 'query' => check_plain($sql .' ('. $spec['initial'] .')')); - } - if ($fixnull) { - $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $field SET NOT NULL"); - } - if (isset($new_keys)) { - _db_create_keys($ret, $table, $new_keys); - } -} - -/** - * Drop a field. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $field - * The field to be dropped. - */ -function db_drop_field(&$ret, $table, $field) { - $ret[] = update_sql('ALTER TABLE {'. $table .'} DROP COLUMN '. $field); } /** - * Set the default value for a field. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $field - * The field to be altered. - * @param $default - * Default value to be set. NULL for 'default NULL'. - */ -function db_field_set_default(&$ret, $table, $field, $default) { - if ($default == NULL) { - $default = 'NULL'; - } - else { - $default = is_string($default) ? "'$default'" : $default; - } - - $ret[] = update_sql('ALTER TABLE {'. $table .'} ALTER COLUMN '. $field .' SET DEFAULT '. $default); -} - -/** - * Set a field to have no default value. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $field - * The field to be altered. - */ -function db_field_set_no_default(&$ret, $table, $field) { - $ret[] = update_sql('ALTER TABLE {'. $table .'} ALTER COLUMN '. $field .' DROP DEFAULT'); -} - -/** - * Add a primary key. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $fields - * Fields for the primary key. - */ -function db_add_primary_key(&$ret, $table, $fields) { - $ret[] = update_sql('ALTER TABLE {'. $table .'} ADD PRIMARY KEY ('. - implode(',', $fields) .')'); -} - -/** - * Drop the primary key. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - */ -function db_drop_primary_key(&$ret, $table) { - $ret[] = update_sql('ALTER TABLE {'. $table .'} DROP CONSTRAINT {'. $table .'}_pkey'); -} - -/** - * Add a unique key. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $name - * The name of the key. - * @param $fields - * An array of field names. - */ -function db_add_unique_key(&$ret, $table, $name, $fields) { - $name = '{'. $table .'}_'. $name .'_key'; - $ret[] = update_sql('ALTER TABLE {'. $table .'} ADD CONSTRAINT '. - $name .' UNIQUE ('. implode(',', $fields) .')'); -} - -/** - * Drop a unique key. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $name - * The name of the key. - */ -function db_drop_unique_key(&$ret, $table, $name) { - $name = '{'. $table .'}_'. $name .'_key'; - $ret[] = update_sql('ALTER TABLE {'. $table .'} DROP CONSTRAINT '. $name); -} - -/** - * Add an index. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $name - * The name of the index. - * @param $fields - * An array of field names. - */ -function db_add_index(&$ret, $table, $name, $fields) { - $ret[] = update_sql(_db_create_index_sql($table, $name, $fields)); -} - -/** - * Drop an index. - * - * @param $ret - * Array to which query results will be added. - * @param $table - * The table to be altered. - * @param $name - * The name of the index. - */ -function db_drop_index(&$ret, $table, $name) { - $name = '{'. $table .'}_'. $name .'_idx'; - $ret[] = update_sql('DROP INDEX '. $name); -} - -/** - * Change a field definition. - * - * IMPORTANT NOTE: To maintain database portability, you have to explicitly - * recreate all indices and primary keys that are using the changed field. - * - * That means that you have to drop all affected keys and indexes with - * db_drop_{primary_key,unique_key,index}() before calling db_change_field(). - * To recreate the keys and indices, pass the key definitions as the - * optional $new_keys argument directly to db_change_field(). - * - * For example, suppose you have: - * @code - * $schema['foo'] = array( - * 'fields' => array( - * 'bar' => array('type' => 'int', 'not null' => TRUE) - * ), - * 'primary key' => array('bar') - * ); - * @endcode - * and you want to change foo.bar to be type serial, leaving it as the - * primary key. The correct sequence is: - * @code - * db_drop_primary_key($ret, 'foo'); - * db_change_field($ret, 'foo', 'bar', 'bar', - * array('type' => 'serial', 'not null' => TRUE), - * array('primary key' => array('bar'))); - * @endcode - * - * The reasons for this are due to the different database engines: - * - * On PostgreSQL, changing a field definition involves adding a new field - * and dropping an old one which* causes any indices, primary keys and - * sequences (from serial-type fields) that use the changed field to be dropped. - * - * On MySQL, all type 'serial' fields must be part of at least one key - * or index as soon as they are created. You cannot use - * db_add_{primary_key,unique_key,index}() for this purpose because - * the ALTER TABLE command will fail to add the column without a key - * or index specification. The solution is to use the optional - * $new_keys argument to create the key or index at the same time as - * field. - * - * You could use db_add_{primary_key,unique_key,index}() in all cases - * unless you are converting a field to be type serial. You can use - * the $new_keys argument in all cases. + * Returns text from a Character Large OBject value. + * In case of PostgreSQL decodes data after select from bytea field. * - * @param $ret - * Array to which query results will be added. - * @param $table - * Name of the table. - * @param $field - * Name of the field to change. - * @param $field_new - * New name for the field (set to the same as $field if you don't want to change the name). - * @param $spec - * The field specification for the new field. - * @param $new_keys - * Optional keys and indexes specification to be created on the - * table along with changing the field. The format is the same as a - * table specification but without the 'fields' element. + * @param $data + * Data to decode. + * @return + * Decoded data. */ -function db_change_field(&$ret, $table, $field, $field_new, $spec, $new_keys = array()) { - $ret[] = update_sql("ALTER TABLE {". $table ."} RENAME $field TO ". $field ."_old"); - $not_null = isset($spec['not null']) ? $spec['not null'] : FALSE; - unset($spec['not null']); - - db_add_field($ret, $table, "$field_new", $spec); - - $ret[] = update_sql("UPDATE {". $table ."} SET $field_new = ". $field ."_old"); - - if ($not_null) { - $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $field_new SET NOT NULL"); - } - - db_drop_field($ret, $table, $field .'_old'); - - if (isset($new_keys)) { - _db_create_keys($ret, $table, $new_keys); - } +function db_decode_clob($data) { + return $data; } /** - * @} End of "ingroup schemaapi". + * @} End of "ingroup database". */ - Index: includes/file.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/file.inc,v retrieving revision 1.118 diff -u -p -r1.118 file.inc --- includes/file.inc 9 Jan 2008 10:39:48 -0000 1.118 +++ includes/file.inc 16 Jan 2008 15:38:11 -0000 @@ -22,7 +22,7 @@ define('FILE_EXISTS_ERROR', 2); /** * A files status can be one of two values: temporary or permanent. The status - * for each file Drupal manages is stored in the {files} tables. If the status + * for each file Drupal manages is stored in the [{files}] tables. If the status * is temporary Drupal's file garbage collection will delete the file and * remove it from the files table after a set period of time. * @@ -445,9 +445,9 @@ function file_delete($path) { */ function file_space_used($uid = NULL) { if (is_null($uid)) { - return db_result(db_query('SELECT SUM(filesize) FROM {files} WHERE uid = %d', $uid)); + return db_result(db_query('SELECT SUM([filesize]) FROM [{files}] WHERE [uid] = %d', $uid)); } - return db_result(db_query('SELECT SUM(filesize) FROM {files}')); + return db_result(db_query('SELECT SUM([filesize]) FROM [{files}]')); } /** @@ -777,7 +777,7 @@ function file_save_data($data, $dest, $r * status. */ function file_set_status(&$file, $status) { - if (db_query('UPDATE {files} SET status = %d WHERE fid = %d', $status, $file->fid)) { + if (db_query('UPDATE [{files}] SET [status] = %d WHERE [fid] = %d', $status, $file->fid)) { $file->status = $status; return TRUE; } Index: includes/form.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/form.inc,v retrieving revision 1.258 diff -u -p -r1.258 form.inc --- includes/form.inc 2 Jan 2008 15:18:15 -0000 1.258 +++ includes/form.inc 16 Jan 2008 15:38:11 -0000 @@ -2265,10 +2265,10 @@ function form_clean_id($id = NULL, $flus * if (empty($context['sandbox'])) { * $context['sandbox']['progress'] = 0; * $context['sandbox']['current_node'] = 0; - * $context['sandbox']['max'] = db_result(db_query('SELECT COUNT(DISTINCT nid) FROM {node}')); + * $context['sandbox']['max'] = db_result(db_query('SELECT COUNT(DISTINCT [nid]) FROM [{node}]')); * } * $limit = 5; - * $result = db_query_range("SELECT nid FROM {node} WHERE nid > %d ORDER BY nid ASC", $context['sandbox']['current_node'], 0, $limit); + * $result = db_query_range("SELECT [nid] FROM [{node}] WHERE [nid] > %d ORDER BY [nid] ASC", $context['sandbox']['current_node'], 0, $limit); * while ($row = db_fetch_array($result)) { * $node = node_load($row['nid'], NULL, TRUE); * $context['results'][] = $node->nid .' : '. $node->title; @@ -2432,7 +2432,7 @@ function batch_process($redirect = NULL, // Initiate db storage in order to get a batch id. We have to provide // at least an empty string for the (not null) 'token' column. - db_query("INSERT INTO {batch} (token, timestamp) VALUES ('', %d)", time()); + db_query("INSERT INTO [{batch}] ([token], [timestamp]) VALUES (%s, %d)", '', time()); $batch['id'] = db_last_insert_id('batch', 'bid'); // Now that we have a batch id, we can generate the redirection link in @@ -2441,7 +2441,7 @@ function batch_process($redirect = NULL, $batch['error_message'] = $t('Please continue to the error page', array('@error_url' => url($url, array('query' => array('id' => $batch['id'], 'op' => 'finished'))))); // Actually store the batch data and the token generated form the batch id. - db_query("UPDATE {batch} SET token = '%s', batch = '%s' WHERE bid = %d", drupal_get_token($batch['id']), serialize($batch), $batch['id']); + db_query("UPDATE [{batch}] SET [token] = %s, [batch] = %s WHERE [bid] = %d", drupal_get_token($batch['id']), serialize($batch), $batch['id']); drupal_goto($batch['url'], 'op=start&id='. $batch['id']); } Index: includes/install.ibm_db2.inc =================================================================== RCS file: includes/install.ibm_db2.inc diff -N includes/install.ibm_db2.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/install.ibm_db2.inc 16 Jan 2008 15:38:11 -0000 @@ -0,0 +1,161 @@ + DB2_AUTOCOMMIT_ON, + // Specifies that column names are returned in natural case. + 'DB2_ATTR_CASE' => DB2_CASE_NATURAL, + // Specifies a forward-only cursor for a statement resource. + 'CURSOR' => DB2_FORWARD_ONLY + ); + + // Test connecting to the database. + $connection = @db2_connect($conn_string, '', '', $conn_options); + if (!$connection && $error = db2_conn_errormsg()) { + drupal_set_message(st('Failure to connect to your DB2 database server. DB2 reports the following message: %error.For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => $error)), 'error'); + return FALSE; + } + + $success = array('CONNECT'); + + // Test CREATE. + $query = 'CREATE TABLE drupal_install_test (id integer NOT NULL)'; + $stmt = db2_prepare($connection, $query); + if (!$stmt && $error = db2_stmt_errormsg($stmt)) { + drupal_set_message(st('We were unable to create a test table on your DB2 database server with the command %query. DB2 reports the following message: %error.For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%query' => $query, '%error' => $error)), 'error'); + return FALSE; + } + $result = @db2_execute($stmt); + $err = FALSE; + $success[] = 'SELECT'; + $success[] = 'CREATE'; + + // Test INSERT. + $query = 'INSERT INTO drupal_install_test (id) VALUES (1)'; + $stmt = db2_prepare($connection, $query); + $result = @db2_execute($stmt); + if (!$result && $error = db2_stmt_errormsg($stmt)) { + drupal_set_message(st('We were unable to insert a value into a test table on your DB2 database server. We tried inserting a value with the command %query and DB2 reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error'); + $err = TRUE; + } + else { + $success[] = 'INSERT'; + } + + // Test UPDATE. + $query = 'UPDATE drupal_install_test SET id = 2'; + $stmt = db2_prepare($connection, $query); + $result = @db2_execute($stmt); + if (!$result && $error = db2_stmt_errormsg($stmt)) { + drupal_set_message(st('We were unable to update a value in a test table on your DB2 database server. We tried updating a value with the command %query and DB2 reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error'); + $err = TRUE; + } + else { + $success[] = 'UPDATE'; + } + + // Test LOCK. + $query = 'LOCK TABLE drupal_install_test IN EXCLUSIVE MODE'; + $stmt = db2_prepare($connection, $query); + $result = @db2_execute($stmt); + if (!$result && $error = db2_stmt_errormsg($stmt)) { + drupal_set_message(st('We were unable to lock a test table on your DB2 database server. We tried locking a table with the command %query and DB2 reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error'); + $err = TRUE; + } + else { + $success[] = 'LOCK'; + } + + // Test UNLOCK, which is done automatically upon transaction end in DB2 + $query = 'COMMIT'; + $stmt = db2_prepare($connection, $query); + $result = @db2_execute($stmt); + if (!$result && $error = db2_stmt_errormsg($stmt)) { + drupal_set_message(st('We were unable to unlock a test table on your DB2 database server. We tried unlocking a table with the command %query and DB2 reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error'); + $err = TRUE; + } + else { + $success[] = 'UNLOCK'; + } + + // Test DELETE. + $query = 'DELETE FROM drupal_install_test'; + $stmt = db2_prepare($connection, $query); + $result = @db2_execute($stmt); + if (!$result && $error = db2_stmt_errormsg($stmt)) { + drupal_set_message(st('We were unable to delete a value from a test table on your DB2 database server. We tried deleting a value with the command %query and DB2 reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error'); + $err = TRUE; + } + else { + $success[] = 'DELETE'; + } + + // Test DROP. + $query = 'DROP TABLE drupal_install_test'; + $stmt = db2_prepare($connection, $query); + $result = @db2_execute($stmt); + if (!$result && $error = db2_stmt_errormsg($stmt)) { + drupal_set_message(st('We were unable to drop a test table from your DB2 database server. We tried dropping a table with the command %query and DB2 reported the following error %error.', array('%query' => $query, '%error' => $error)), 'error'); + $err = TRUE; + } + else { + $success[] = 'DROP'; + } + + if ($err) { + return FALSE; + } + + db2_close($connection); + return TRUE; +} Index: includes/install.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/install.inc,v retrieving revision 1.56 diff -u -p -r1.56 install.inc --- includes/install.inc 19 Dec 2007 11:15:18 -0000 1.56 +++ includes/install.inc 16 Jan 2008 15:38:11 -0000 @@ -77,7 +77,7 @@ function drupal_get_installed_schema_ver if (!$versions) { $versions = array(); - $result = db_query("SELECT name, schema_version FROM {system} WHERE type = '%s'", 'module'); + $result = db_query("SELECT [name], [schema_version] FROM [{system}] WHERE [type] = %s", 'module'); while ($row = db_fetch_object($result)) { $versions[$row->name] = $row->schema_version; } @@ -95,7 +95,7 @@ function drupal_get_installed_schema_ver * The new schema version. */ function drupal_set_installed_schema_version($module, $version) { - db_query("UPDATE {system} SET schema_version = %d WHERE name = '%s'", $version, $module); + db_query("UPDATE [{system}] SET [schema_version] = %d WHERE [name] = %s", $version, $module); } /** @@ -151,7 +151,7 @@ function drupal_detect_baseurl($file = ' function drupal_detect_database_types() { $databases = array(); - foreach (array('mysql', 'mysqli', 'pgsql') as $type) { + foreach (array('mysql', 'mysqli', 'pdo_mysql', 'pgsql', 'pdo_pgsql', 'oci8') as $type) { if (file_exists('./includes/install.'. $type .'.inc')) { include_once './includes/install.'. $type .'.inc'; $function = $type .'_is_available'; @@ -359,7 +359,7 @@ function drupal_install_system() { module_invoke('system', 'install'); $system_versions = drupal_get_schema_versions('system'); $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED; - db_query("INSERT INTO {system} (filename, name, type, owner, status, throttle, bootstrap, schema_version) VALUES('%s', '%s', '%s', '%s', %d, %d, %d, %d)", $system_path .'/system.module', 'system', 'module', '', 1, 0, 0, $system_version); + db_query("INSERT INTO [{system}] ([filename], [name], [type], [owner], [status], [throttle], [bootstrap], [schema_version]) VALUES(%s, %s, %s, %s, %d, %d, %d, %d)", $system_path .'/system.module', 'system', 'module', '', 1, 0, 0, $system_version); // Now that we've installed things properly, bootstrap the full Drupal environment drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); module_rebuild_cache(); @@ -391,9 +391,9 @@ function drupal_uninstall_module($module } $paths[$index] = implode('/', $parts); } - $placeholders = implode(', ', array_fill(0, count($paths), "'%s'")); + $placeholders = implode(', ', array_fill(0, count($paths), "%s")); - $result = db_query('SELECT * FROM {menu_links} WHERE router_path IN ('. $placeholders .') AND external = 0 ORDER BY depth DESC', $paths); + $result = db_query('SELECT * FROM [{menu_links}] WHERE [router_path] IN ('. $placeholders .') AND [external] = 0 ORDER BY [depth] DESC', $paths); // Remove all such items. Starting from those with the greatest depth will // minimize the amount of re-parenting done by menu_link_delete(). while ($item = db_fetch_array($result)) { Index: includes/install.mysql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/install.mysql.inc,v retrieving revision 1.8 diff -u -p -r1.8 install.mysql.inc --- includes/install.mysql.inc 8 Dec 2007 14:06:20 -0000 1.8 +++ includes/install.mysql.inc 16 Jan 2008 15:38:11 -0000 @@ -10,7 +10,7 @@ * TRUE/FALSE */ function mysql_is_available() { - return function_exists('mysql_connect'); + return function_exists('mysql_connect') && extension_loaded('mysql'); } /** @@ -21,7 +21,7 @@ function mysql_is_available() { */ function drupal_test_mysql($url, &$success) { if (!mysql_is_available()) { - drupal_set_message(st('PHP MySQL support not enabled.'), 'error'); + drupal_set_message(st('PHP mysql support not enabled.'), 'error'); return FALSE; } Index: includes/install.mysqli.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/install.mysqli.inc,v retrieving revision 1.11 diff -u -p -r1.11 install.mysqli.inc --- includes/install.mysqli.inc 19 Dec 2007 11:25:47 -0000 1.11 +++ includes/install.mysqli.inc 16 Jan 2008 15:38:11 -0000 @@ -10,7 +10,7 @@ * TRUE/FALSE */ function mysqli_is_available() { - return function_exists('mysqli_connect'); + return function_exists('mysqli_init') && extension_loaded('mysqli'); } /** @@ -21,7 +21,7 @@ function mysqli_is_available() { */ function drupal_test_mysqli($url, &$success) { if (!mysqli_is_available()) { - drupal_set_message(st('PHP MySQLi support not enabled.'), 'error'); + drupal_set_message(st('PHP mysqli support not enabled.'), 'error'); return FALSE; } Index: includes/install.oci8.inc =================================================================== RCS file: includes/install.oci8.inc diff -N includes/install.oci8.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/install.oci8.inc 16 Jan 2008 15:38:11 -0000 @@ -0,0 +1,142 @@ +
  • Are you sure you have the correct username and password?
  • Are you sure that you have typed the correct database hostname?
  • Are you sure that the database server is running?
  • Are you sure you typed the correct database name?
  • For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.
    Error: '. $error, array('%error' => 'Connection failed. See log file for failure reason')), 'error'); + return FALSE; + } + + $success = array('CONNECT'); + + // Test CREATE. + $query = 'CREATE TABLE drupal_install_test (id integer NOT NULL)'; + $stmt = @oci_parse($connection, $query); + if (!$stmt && ($error = oci_error($connection))) { + drupal_set_message(st('We were unable to create a test table on your Oracle database server with the command %query. Oracle reports the following message: %error.For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%query' => $query, '%error' => $error)), 'error'); + return FALSE; + } + $result = @oci_execute($stmt); + $err = FALSE; + $success[] = 'SELECT'; + $success[] = 'CREATE'; + + // Test INSERT. + $query = 'INSERT INTO drupal_install_test (id) VALUES (1)'; + $stmt = @oci_parse($connection, $query); + $result = @oci_execute($stmt); + if ($error = oci_error($stmt)) { + drupal_set_message(st('We were unable to insert a value into a test table on your Oracle database server. We tried inserting a value with the command %query and Oracle reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error'); + $err = TRUE; + } + else { + $success[] = 'INSERT'; + } + + // Test UPDATE. + $query = 'UPDATE drupal_install_test SET id = 2'; + $stmt = @oci_parse($connection, $query); + $result = @oci_execute($stmt); + if ($error = oci_error($stmt)) { + drupal_set_message(st('We were unable to update a value in a test table on your Oracle database server. We tried updating a value with the command %query and Oracle reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error'); + $err = TRUE; + } + else { + $success[] = 'UPDATE'; + } + + // Test LOCK. + $query = 'LOCK TABLE drupal_install_test IN EXCLUSIVE MODE'; + $stmt = @oci_parse($connection, $query); + $result = @oci_execute($stmt); + if ($error = oci_error($stmt)) { + drupal_set_message(st('We were unable to lock a test table on your Oracle database server. We tried locking a table with the command %query and Oracle reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error'); + $err = TRUE; + } + else { + $success[] = 'LOCK'; + } + + // Test UNLOCK, which is done automatically upon transaction end in Oracle + $query = 'COMMIT'; + $stmt = @oci_parse($connection, $query); + $result = @oci_execute($stmt); + if ($error = oci_error($stmt)) { + drupal_set_message(st('We were unable to unlock a test table on your Oracle database server. We tried unlocking a table with the command %query and Oracle reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error'); + $err = TRUE; + } + else { + $success[] = 'UNLOCK'; + } + + // Test DELETE. + $query = 'DELETE FROM drupal_install_test'; + $stmt = @oci_parse($connection, $query); + $result = @oci_execute($stmt); + if ($error = oci_error($stmt)) { + drupal_set_message(st('We were unable to delete a value from a test table on your Oracle database server. We tried deleting a value with the command %query and Oracle reported the following error: %error.', array('%query' => $query, '%error' => $error)), 'error'); + $err = TRUE; + } + else { + $success[] = 'DELETE'; + } + + // Test DROP. + $query = 'DROP TABLE drupal_install_test'; + $stmt = @oci_parse($connection, $query); + $result = @oci_execute($stmt); + if ($error = oci_error($stmt)) { + drupal_set_message(st('We were unable to drop a test table from your Oracle database server. We tried dropping a table with the command %query and Oracle reported the following error %error.', array('%query' => $query, '%error' => $error)), 'error'); + $err = TRUE; + } + else { + $success[] = 'DROP'; + } + + if ($err) { + return FALSE; + } + + oci_close($connection); + return TRUE; +} Index: includes/install.pdo_mysql.inc =================================================================== RCS file: includes/install.pdo_mysql.inc diff -N includes/install.pdo_mysql.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/install.pdo_mysql.inc 16 Jan 2008 15:38:11 -0000 @@ -0,0 +1,155 @@ +
  • Are you sure you have the correct username and password?
  • Are you sure that you have typed the correct database hostname?
  • Are you sure that the database server is running?
  • For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => $e->getMessage())), 'error'); + return FALSE; + } + + $success = array('CONNECT'); + + // Test CREATE. + $query = 'CREATE TABLE drupal_install_test (id int NULL)'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('Failed to create a test table on your MySQL database server with the command %query. MySQL reports the following message: %error.For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%query' => $query, '%error' => $error[2])), 'error'); + return FALSE; + } + $err = FALSE; + $success[] = 'SELECT'; + $success[] = 'CREATE'; + + // Test INSERT. + $query = 'INSERT INTO drupal_install_test (id) VALUES (1)'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('Failed to insert a value into a test table on your MySQL database server. We tried inserting a value with the command %query and MySQL reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'INSERT'; + } + + // Test UPDATE. + $query = 'UPDATE drupal_install_test SET id = 2'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('Failed to update a value in a test table on your MySQL database server. We tried updating a value with the command %query and MySQL reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'UPDATE'; + } + + // Test LOCK. + $query = 'LOCK TABLES drupal_install_test WRITE'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('Failed to lock a test table on your MySQL database server. We tried locking a table with the command %query and MySQL reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'LOCK'; + } + + // Test UNLOCK. + $query = 'UNLOCK TABLES'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('Failed to unlock a test table on your MySQL database server. We tried unlocking a table with the command %query and MySQL reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'UNLOCK'; + } + + // Test DELETE. + $query = 'DELETE FROM drupal_install_test'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('Failed to delete a value from a test table on your MySQL database server. We tried deleting a value with the command %query and MySQL reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'DELETE'; + } + + // Test DROP. + $query = 'DROP TABLE drupal_install_test'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('Failed to drop a test table from your MySQL database server. We tried dropping a table with the command %query and MySQL reported the following error %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'DROP'; + } + + if ($err) { + return FALSE; + } + + $connection = NULL; + return TRUE; +} Index: includes/install.pdo_oci.inc =================================================================== RCS file: includes/install.pdo_oci.inc diff -N includes/install.pdo_oci.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/install.pdo_oci.inc 16 Jan 2008 15:38:11 -0000 @@ -0,0 +1,155 @@ +
  • Are you sure you have the correct username and password?
  • Are you sure that you have typed the correct database hostname?
  • Are you sure that the database server is running?
  • Are you sure you typed the correct database name?
  • For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.
    Error: '. $error, array('%error' => 'Connection failed. See log file for failure reason')), 'error'); + return FALSE; + } + + $success = array('CONNECT'); + + // Test CREATE. + $query = 'CREATE TABLE drupal_install_test (id integer NOT NULL)'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('We were unable to create a test table on your Oracle database server with the command %query. Oracle reports the following message: %error.For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%query' => $query, '%error' => $error[2])), 'error'); + return FALSE; + } + $err = FALSE; + $success[] = 'SELECT'; + $success[] = 'CREATE'; + + // Test INSERT. + $query = 'INSERT INTO drupal_install_test (id) VALUES (1)'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('We were unable to insert a value into a test table on your Oracle database server. We tried inserting a value with the command %query and Oracle reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'INSERT'; + } + + // Test UPDATE. + $query = 'UPDATE drupal_install_test SET id = 2'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('We were unable to update a value in a test table on your Oracle database server. We tried updating a value with the command %query and Oracle reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'UPDATE'; + } + + // Test LOCK. + $query = 'LOCK TABLE drupal_install_test IN EXCLUSIVE MODE'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('We were unable to lock a test table on your Oracle database server. We tried locking a table with the command %query and Oracle reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'LOCK'; + } + + // Test UNLOCK, which is done automatically upon transaction end in Oracle + $query = 'COMMIT'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('We were unable to unlock a test table on your Oracle database server. We tried unlocking a table with the command %query and Oracle reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'UNLOCK'; + } + + // Test DELETE. + $query = 'DELETE FROM drupal_install_test'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('We were unable to delete a value from a test table on your Oracle database server. We tried deleting a value with the command %query and Oracle reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'DELETE'; + } + + // Test DROP. + $query = 'DROP TABLE drupal_install_test'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('We were unable to drop a test table from your Oracle database server. We tried dropping a table with the command %query and Oracle reported the following error %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'DROP'; + } + + if ($err) { + return FALSE; + } + + $connection = NULL; + return TRUE; +} Index: includes/install.pdo_pgsql.inc =================================================================== RCS file: includes/install.pdo_pgsql.inc diff -N includes/install.pdo_pgsql.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/install.pdo_pgsql.inc 16 Jan 2008 15:38:11 -0000 @@ -0,0 +1,155 @@ +
  • Are you sure you have the correct username and password?
  • Are you sure that you have typed the correct database hostname?
  • Are you sure that the database server is running?
  • Are you sure you typed the correct database name?
  • For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => $e->getMessage())), 'error'); + return FALSE; + } + + $success = array('CONNECT'); + + // Test CREATE. + $query = 'CREATE TABLE drupal_install_test (id integer NOT NULL)'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('Failed to create a test table on your PostgreSQL database server with the command %query. PostgreSQL reports the following message: %error.For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%query' => $query, '%error' => $error[2])), 'error'); + return FALSE; + } + $err = FALSE; + $success[] = 'SELECT'; + $success[] = 'CREATE'; + + // Test INSERT. + $query = 'INSERT INTO drupal_install_test (id) VALUES (1)'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('Failed to insert a value into a test table on your PostgreSQL database server. We tried inserting a value with the command %query and PostgreSQL reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'INSERT'; + } + + // Test UPDATE. + $query = 'UPDATE drupal_install_test SET id = 2'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('Failed to update a value in a test table on your PostgreSQL database server. We tried updating a value with the command %query and PostgreSQL reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'UPDATE'; + } + + // Test LOCK. + $query = 'LOCK drupal_install_test IN SHARE ROW EXCLUSIVE MODE'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('Failed to lock a test table on your PostgreSQL database server. We tried locking a table with the command %query and PostgreSQL reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'LOCK'; + } + + // Test UNLOCK, which is done automatically upon transaction end in PostgreSQL + $query = 'COMMIT'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('Failed to unlock a test table on your PostgreSQL database server. We tried unlocking a table with the command %query and PostgreSQL reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'UNLOCK'; + } + + // Test DELETE. + $query = 'DELETE FROM drupal_install_test'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('Failed to delete a value from a test table on your PostgreSQL database server. We tried deleting a value with the command %query and PostgreSQL reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'DELETE'; + } + + // Test DROP. + $query = 'DROP TABLE drupal_install_test'; + $stmt = $connection->prepare($query); + $stmt->execute(); + $error = $stmt->errorInfo(); + if (is_array($error) && (int) $error[0] && isset($error[2])) { + drupal_set_message(st('Failed to drop a test table from your PostgreSQL database server. We tried dropping a table with the command %query and PostgreSQL reported the following error %error.', array('%query' => $query, '%error' => $error[2])), 'error'); + $err = TRUE; + } + else { + $success[] = 'DROP'; + } + + if ($err) { + return FALSE; + } + + $connection = NULL; + return TRUE; +} Index: includes/install.pgsql.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/install.pgsql.inc,v retrieving revision 1.6 diff -u -p -r1.6 install.pgsql.inc --- includes/install.pgsql.inc 22 Oct 2007 15:22:39 -0000 1.6 +++ includes/install.pgsql.inc 16 Jan 2008 15:38:11 -0000 @@ -10,7 +10,7 @@ * TRUE/FALSE */ function pgsql_is_available() { - return function_exists('pg_connect'); + return function_exists('pg_connect') && extension_loaded('pgsql'); } /** @@ -21,7 +21,7 @@ function pgsql_is_available() { */ function drupal_test_pgsql($url, &$success) { if (!pgsql_is_available()) { - drupal_set_message(st('PHP PostgreSQL support not enabled.'), 'error'); + drupal_set_message(st('PHP pgsql support not enabled.'), 'error'); return FALSE; } @@ -137,4 +137,4 @@ function drupal_test_pgsql($url, &$succe pg_close($connection); return TRUE; -} \ No newline at end of file +} Index: includes/locale.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/locale.inc,v retrieving revision 1.174 diff -u -p -r1.174 locale.inc --- includes/locale.inc 9 Jan 2008 21:36:13 -0000 1.174 +++ includes/locale.inc 16 Jan 2008 15:38:11 -0000 @@ -116,7 +116,7 @@ function locale_languages_overview_form_ $language->enabled = 0; } $language->weight = $form_state['values']['weight'][$langcode]; - db_query("UPDATE {languages} SET enabled = %d, weight = %d WHERE language = '%s'", $language->enabled, $language->weight, $langcode); + db_query("UPDATE [{languages}] SET [enabled] = %d, [weight] = %d WHERE [language] = %s", $language->enabled, $language->weight, $langcode); $languages[$langcode] = $language; } drupal_set_message(t('Configuration saved.')); @@ -195,7 +195,7 @@ function locale_languages_custom_form() * Language code of the language to edit. */ function locale_languages_edit_form(&$form_state, $langcode) { - if ($language = db_fetch_object(db_query("SELECT * FROM {languages} WHERE language = '%s'", $langcode))) { + if ($language = db_fetch_object(db_query("SELECT * FROM [{languages}] WHERE [language] = %s", $langcode))) { $form = array(); _locale_languages_common_controls($form, $language); $form['submit'] = array( @@ -287,7 +287,7 @@ function _locale_languages_common_contro function locale_languages_predefined_form_validate($form, &$form_state) { $langcode = $form_state['values']['langcode']; - if ($duplicate = db_result(db_query("SELECT COUNT(*) FROM {languages} WHERE language = '%s'", $langcode)) != 0) { + if ($duplicate = db_result(db_query("SELECT COUNT(*) FROM [{languages}] WHERE [language] = %s", $langcode)) != 0) { form_set_error('langcode', t('The language %language (%code) already exists.', array('%language' => $form_state['values']['name'], '%code' => $langcode))); } @@ -338,13 +338,13 @@ function locale_languages_edit_form_vali if (!empty($form_state['values']['domain']) && !empty($form_state['values']['prefix'])) { form_set_error('prefix', t('Domain and path prefix values should not be set at the same time.')); } - if (!empty($form_state['values']['domain']) && $duplicate = db_fetch_object(db_query("SELECT language FROM {languages} WHERE domain = '%s' AND language != '%s'", $form_state['values']['domain'], $form_state['values']['langcode']))) { + if (!empty($form_state['values']['domain']) && $duplicate = db_fetch_object(db_query("SELECT [language] FROM [{languages}] WHERE [domain] = %s AND [language] != %s", $form_state['values']['domain'], $form_state['values']['langcode']))) { form_set_error('domain', t('The domain (%domain) is already tied to a language (%language).', array('%domain' => $form_state['values']['domain'], '%language' => $duplicate->language))); } if (empty($form_state['values']['prefix']) && language_default('language') != $form_state['values']['langcode'] && empty($form_state['values']['domain'])) { form_set_error('prefix', t('Only the default language can have both the domain and prefix empty.')); } - if (!empty($form_state['values']['prefix']) && $duplicate = db_fetch_object(db_query("SELECT language FROM {languages} WHERE prefix = '%s' AND language != '%s'", $form_state['values']['prefix'], $form_state['values']['langcode']))) { + if (!empty($form_state['values']['prefix']) && $duplicate = db_fetch_object(db_query("SELECT language FROM [{languages}] WHERE [prefix] = %s AND [language] != %s", $form_state['values']['prefix'], $form_state['values']['langcode']))) { form_set_error('prefix', t('The prefix (%prefix) is already tied to a language (%language).', array('%prefix' => $form_state['values']['prefix'], '%language' => $duplicate->language))); } } @@ -353,7 +353,7 @@ function locale_languages_edit_form_vali * Process the language editing form submission. */ function locale_languages_edit_form_submit($form, &$form_state) { - db_query("UPDATE {languages} SET name = '%s', native = '%s', domain = '%s', prefix = '%s', direction = %d WHERE language = '%s'", $form_state['values']['name'], $form_state['values']['native'], $form_state['values']['domain'], $form_state['values']['prefix'], $form_state['values']['direction'], $form_state['values']['langcode']); + db_query("UPDATE [{languages}] SET [name] = %s, [native] = %s, [domain] = %s, [prefix] = %s, [direction] = %d WHERE [language] = %s", $form_state['values']['name'], $form_state['values']['native'], $form_state['values']['domain'], $form_state['values']['prefix'], $form_state['values']['direction'], $form_state['values']['langcode']); $default = language_default(); if ($default->language == $form_state['values']['langcode']) { $properties = array('name', 'native', 'direction', 'enabled', 'plurals', 'formula', 'domain', 'prefix', 'weight'); @@ -411,13 +411,13 @@ function locale_languages_delete_form_su $languages = language_list(); if (isset($languages[$form_state['values']['langcode']])) { // Remove translations first. - db_query("DELETE FROM {locales_target} WHERE language = '%s'", $form_state['values']['langcode']); + db_query("DELETE FROM [{locales_target}] WHERE [language] = %s", $form_state['values']['langcode']); cache_clear_all('locale:'. $form_state['values']['langcode'], 'cache'); // With no translations, this removes existing JavaScript translations file. _locale_rebuild_js($form_state['values']['langcode']); // Remove the language. - db_query("DELETE FROM {languages} WHERE language = '%s'", $form_state['values']['langcode']); - db_query("UPDATE {node} SET language = '' WHERE language = '%s'", $form_state['values']['langcode']); + db_query("DELETE FROM [{languages}] WHERE [language] = %s", $form_state['values']['langcode']); + db_query("UPDATE [{node}] SET [language] = %s WHERE [language] = %s", '', $form_state['values']['langcode']); $variables = array('%locale' => $languages[$form_state['values']['langcode']]->name); drupal_set_message(t('The language %locale has been removed.', $variables)); watchdog('locale', 'The language %locale has been removed.', $variables); @@ -489,7 +489,7 @@ function locale_translate_overview_scree $headers = array_merge(array(t('Language')), array_values($groups)); // Collect summaries of all source strings in all groups. - $sums = db_query("SELECT COUNT(*) AS strings, textgroup FROM {locales_source} GROUP BY textgroup"); + $sums = db_query("SELECT COUNT(*) AS [strings], [textgroup] FROM [{locales_source}] GROUP BY [textgroup]"); $groupsums = array(); while ($group = db_fetch_object($sums)) { $groupsums[$group->textgroup] = $group->strings; @@ -505,7 +505,7 @@ function locale_translate_overview_scree } // Languages with at least one record in the locale table. - $translations = db_query("SELECT COUNT(*) AS translation, t.language, s.textgroup FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid GROUP BY textgroup, language"); + $translations = db_query("SELECT COUNT(*) AS [translation], t.[language], s.[textgroup] FROM [{locales_source}] s INNER JOIN [{locales_target}] t ON s.[lid] = t.[lid] GROUP BY [textgroup], [language]"); while ($data = db_fetch_object($translations)) { $ratio = (!empty($groupsums[$data->textgroup]) && $data->translation > 0) ? round(($data->translation/$groupsums[$data->textgroup])*100., 2) : 0; $rows[$data->language][$data->textgroup] = $data->translation .'/'. $groupsums[$data->textgroup] ." ($ratio%)"; @@ -768,7 +768,7 @@ function locale_translate_export_po_form */ function locale_translate_edit_form(&$form_state, $lid) { // Fetch source string, if possible. - $source = db_fetch_object(db_query('SELECT source, textgroup, location FROM {locales_source} WHERE lid = %d', $lid)); + $source = db_fetch_object(db_query('SELECT [source], [textgroup], [location] FROM [{locales_source}] WHERE [lid] = %d', $lid)); if (!$source) { drupal_set_message(t('String not found.'), 'error'); drupal_goto('admin/build/translate/search'); @@ -815,7 +815,7 @@ function locale_translate_edit_form(&$fo } // Fetch translations and fill in default values in the form. - $result = db_query("SELECT DISTINCT translation, language FROM {locales_target} WHERE lid = %d AND language != '%s'", $lid, $omit); + $result = db_query("SELECT DISTINCT [translation], [language] FROM [{locales_target}] WHERE [lid] = %d AND [language] != %s", $lid, $omit); while ($translation = db_fetch_object($result)) { $form['translations'][$translation->language]['#default_value'] = $translation->translation; } @@ -831,19 +831,19 @@ function locale_translate_edit_form(&$fo function locale_translate_edit_form_submit($form, &$form_state) { $lid = $form_state['values']['lid']; foreach ($form_state['values']['translations'] as $key => $value) { - $translation = db_result(db_query("SELECT translation FROM {locales_target} WHERE lid = %d AND language = '%s'", $lid, $key)); + $translation = db_result(db_query("SELECT [translation] FROM [{locales_target}] WHERE [lid] = %d AND [language] = %s", $lid, $key)); if (!empty($value)) { // Only update or insert if we have a value to use. if (!empty($translation)) { - db_query("UPDATE {locales_target} SET translation = '%s' WHERE lid = %d AND language = '%s'", $value, $lid, $key); + db_query("UPDATE [{locales_target}] SET [translation] = %s WHERE [lid] = %d AND [language] = %s", $value, $lid, $key); } else { - db_query("INSERT INTO {locales_target} (lid, translation, language) VALUES (%d, '%s', '%s')", $lid, $value, $key); + db_query("INSERT INTO [{locales_target}] ([lid], [translation], [language]) VALUES (%d, %s, %s)", $lid, $value, $key); } } elseif (!empty($translation)) { // Empty translation entered: remove existing entry from database. - db_query("DELETE FROM {locales_target} WHERE lid = %d AND language = '%s'", $lid, $key); + db_query("DELETE FROM [{locales_target}] WHERE [lid] = %d AND [language] = %s", $lid, $key); } // Force JavaScript translation file recreation for this language. @@ -871,8 +871,8 @@ function locale_translate_edit_form_subm * Delete a language string. */ function locale_translate_delete($lid) { - db_query('DELETE FROM {locales_source} WHERE lid = %d', $lid); - db_query('DELETE FROM {locales_target} WHERE lid = %d', $lid); + db_query('DELETE FROM [{locales_source}] WHERE lid = %d', $lid); + db_query('DELETE FROM [{locales_target}] WHERE lid = %d', $lid); // Force JavaScript translation file recreation for all languages. _locale_invalidate_js(); cache_clear_all('locale:', 'cache', TRUE); @@ -924,7 +924,7 @@ function locale_add_language($langcode, $direction = isset($predefined[$langcode][2]) ? $predefined[$langcode][2] : LANGUAGE_LTR; } - db_query("INSERT INTO {languages} (language, name, native, direction, domain, prefix, enabled) VALUES ('%s', '%s', '%s', %d, '%s', '%s', %d)", $langcode, $name, $native, $direction, $domain, $prefix, $enabled); + db_query("INSERT INTO [{languages}] ([language], [name], [native], [direction], [domain], [prefix], [enabled]) VALUES (%s, %s, %s, %d, %s, %s, %d)", $langcode, $name, $native, $direction, $domain, $prefix, $enabled); // Only set it as default if enabled. if ($enabled && $default) { @@ -969,7 +969,7 @@ function _locale_import_po($file, $langc } // Check if we have the language already in the database. - if (!db_fetch_object(db_query("SELECT language FROM {languages} WHERE language = '%s'", $langcode))) { + if (!db_fetch_object(db_query("SELECT [language] FROM [{languages}] WHERE [language] = %s", $langcode))) { drupal_set_message(t('The language selected for import is not supported.'), 'error'); return FALSE; } @@ -1213,10 +1213,10 @@ function _locale_import_one_string($op, // Get the plural formula and update in database. if (isset($header["Plural-Forms"]) && $p = _locale_import_parse_plural_forms($header["Plural-Forms"], $file->filename)) { list($nplurals, $plural) = $p; - db_query("UPDATE {languages} SET plurals = %d, formula = '%s' WHERE language = '%s'", $nplurals, $plural, $lang); + db_query("UPDATE [{languages}] SET [plurals] = %d, [formula] = %s WHERE [language] = %s", $nplurals, $plural, $lang); } else { - db_query("UPDATE {languages} SET plurals = %d, formula = '%s' WHERE language = '%s'", 0, '', $lang); + db_query("UPDATE [{languages}] SET [plurals] = %d, [formula] = %s WHERE [language] = %s", 0, '', $lang); } $headerdone = TRUE; } @@ -1278,35 +1278,35 @@ function _locale_import_one_string($op, * The string ID of the existing string modified or the new string added. */ function _locale_import_one_string_db(&$report, $langcode, $source, $translation, $textgroup, $location, $mode, $plid = NULL, $plural = NULL) { - $lid = db_result(db_query("SELECT lid FROM {locales_source} WHERE source = '%s' AND textgroup = '%s'", $source, $textgroup)); + $lid = db_result(db_query("SELECT [lid] FROM [{locales_source}] WHERE [source] = %s AND [textgroup] = %s", $source, $textgroup)); if (!empty($translation)) { if ($lid) { // We have this source string saved already. - db_query("UPDATE {locales_source} SET location = '%s' WHERE lid = %d", $location, $lid); - $exists = (bool) db_result(db_query("SELECT lid FROM {locales_target} WHERE lid = %d AND language = '%s'", $lid, $langcode)); + db_query("UPDATE [{locales_source}] SET [location] = %s WHERE [lid] = %d", $location, $lid); + $exists = (bool) db_result(db_query("SELECT [lid] FROM [{locales_target}] WHERE [lid] = %d AND [language] = %s", $lid, $langcode)); if (!$exists) { // No translation in this language. - db_query("INSERT INTO {locales_target} (lid, language, translation, plid, plural) VALUES (%d, '%s', '%s', %d, %d)", $lid, $langcode, $translation, $plid, $plural); + db_query("INSERT INTO [{locales_target}] ([lid], [language], [translation], [plid], [plural]) VALUES (%d, %s, %s, %d, %d)", $lid, $langcode, $translation, $plid, $plural); $report[0]++; } else if ($mode == LOCALE_IMPORT_OVERWRITE) { // Translation exists, only overwrite if instructed. - db_query("UPDATE {locales_target} SET translation = '%s', plid = %d, plural = %d WHERE language = '%s' AND lid = %d", $translation, $plid, $plural, $langcode, $lid); + db_query("UPDATE [{locales_target}] SET [translation] = %s, [plid] = %d, [plural] = %d WHERE [language] = %s AND [lid] = %d", $translation, $plid, $plural, $langcode, $lid); $report[1]++; } } else { // No such source string in the database yet. - db_query("INSERT INTO {locales_source} (location, source, textgroup) VALUES ('%s', '%s', '%s')", $location, $source, $textgroup); - $lid = db_result(db_query("SELECT lid FROM {locales_source} WHERE source = '%s' AND textgroup = '%s'", $source, $textgroup)); - db_query("INSERT INTO {locales_target} (lid, language, translation, plid, plural) VALUES (%d, '%s', '%s', %d, %d)", $lid, $langcode, $translation, $plid, $plural); + db_query("INSERT INTO [{locales_source}] ([location], [source], [textgroup]) VALUES (%s, %s, %s)", $location, $source, $textgroup); + $lid = db_result(db_query("SELECT [lid] FROM [{locales_source}] WHERE [source] = %s AND [textgroup] = %s", $source, $textgroup)); + db_query("INSERT INTO [{locales_target}] ([lid], [language], [translation], [plid], [plural]) VALUES (%d, %s, %s, %d, %d)", $lid, $langcode, $translation, $plid, $plural); $report[0]++; } } elseif ($mode == LOCALE_IMPORT_OVERWRITE) { // Empty translation, remove existing if instructed. - db_query("DELETE FROM {locales_target} WHERE language = '%s' AND lid = %d AND plid = %d AND plural = %d", $translation, $langcode, $lid, $plid, $plural); + db_query("DELETE FROM [{locales_target}] WHERE [language] = %s AND [lid] = %d AND [plid] = %d AND [plural] = %d", $translation, $langcode, $lid, $plid, $plural); $report[2]++; } @@ -1642,7 +1642,7 @@ function _locale_parse_js_file($filepath // Remove the quotes and string concatenations from the string. $string = implode('', preg_split('~(?lid); + db_query("UPDATE [{locales_source}] SET [location] = %s WHERE [lid] = %d", $locations, $source->lid); } } else { // We don't have the source string yet, thus we insert it into the database. - db_query("INSERT INTO {locales_source} (location, source, textgroup) VALUES ('%s', '%s', 'default')", $filepath, $string); + db_query("INSERT INTO [{locales_source}] ([location], [source], [textgroup]) VALUES (%s, %s, 'default')", $filepath, $string); } } } @@ -1682,10 +1682,10 @@ function _locale_parse_js_file($filepath */ function _locale_export_get_strings($language = NULL, $group = 'default') { if (isset($language)) { - $result = db_query("SELECT s.lid, s.source, s.location, t.translation, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = '%s' WHERE s.textgroup = '%s' ORDER BY t.plid, t.plural", $language->language, $group); + $result = db_query("SELECT s.[lid], s.[source], s.[location], t.[translation], t.[plid], t.[plural] FROM [{locales_source}] s LEFT JOIN [{locales_target}] t ON s.[lid] = t.[lid] AND t.[language] = %s WHERE s.[textgroup] = %s ORDER BY t.[plid], t.[plural]", $language->language, $group); } else { - $result = db_query("SELECT s.lid, s.source, s.location, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE s.textgroup = '%s' ORDER BY t.plid, t.plural", $group); + $result = db_query("SELECT s.[lid], s.[source], s.[location], t.[plid], t.[plural] FROM [{locales_source}] s LEFT JOIN [{locales_target}] t ON s.[lid] = t.[lid] WHERE s.[textgroup] = %s ORDER BY t.[plid], t.[plural]", $group); } $strings = array(); while ($child = db_fetch_object($result)) { @@ -1913,41 +1913,41 @@ function _locale_translate_seek() { // We have at least one criterion to match if ($query = _locale_translate_seek_query()) { - $join = "SELECT s.source, s.location, s.lid, s.textgroup, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid "; + $join = "SELECT s.[source], s.[location], s.[lid], s.[textgroup], t.[translation], t.[language] FROM [{locales_source}] s LEFT JOIN [{locales_target}] t ON s.[lid] = t.[lid] "; $arguments = array(); $limit_language = FALSE; // Compute LIKE section switch ($query['translation']) { case 'translated': - $where = "WHERE (t.translation LIKE '%%%s%%')"; - $orderby = "ORDER BY t.translation"; - $arguments[] = $query['string']; + $where = "WHERE (t.[translation] LIKE %s)"; + $orderby = "ORDER BY t.[translation]"; + $arguments[] = "%". $query['string'] ."%"; break; case 'untranslated': - $where = "WHERE (s.source LIKE '%%%s%%' AND t.translation IS NULL)"; - $orderby = "ORDER BY s.source"; - $arguments[] = $query['string']; + $where = "WHERE (s.[source] LIKE %s AND t.[translation] IS NULL)"; + $orderby = "ORDER BY s.[source]"; + $arguments[] = "%". $query['string'] ."%"; break; case 'all' : default: - $where = "WHERE (s.source LIKE '%%%s%%' OR t.translation LIKE '%%%s%%')"; + $where = "WHERE (s.[source] LIKE %s OR t.[translation] LIKE %s)"; $orderby = ''; - $arguments[] = $query['string']; - $arguments[] = $query['string']; + $arguments[] = "%". $query['string'] ."%"; + $arguments[] = "%". $query['string'] ."%"; break; } $grouplimit = ''; if (!empty($query['group']) && $query['group'] != 'all') { - $grouplimit = " AND s.textgroup = '%s'"; + $grouplimit = " AND s.[textgroup] = %s"; $arguments[] = $query['group']; } switch ($query['language']) { // Force search in source strings case "en": - $sql = $join ." WHERE s.source LIKE '%%%s%%' $grouplimit ORDER BY s.source"; - $arguments = array($query['string']); // $where is not used, discard its arguments + $sql = $join ." WHERE s.[source] LIKE %s $grouplimit ORDER BY s.[source]"; + $arguments = array("%". $query['string'] ."%"); // $where is not used, discard its arguments if (!empty($grouplimit)) { $arguments[] = $query['group']; } @@ -1958,7 +1958,7 @@ function _locale_translate_seek() { break; // Some different language default: - $sql = "$join AND t.language = '%s' $where $grouplimit $orderby"; + $sql = "$join AND t.[language] = %s $where $grouplimit $orderby"; array_unshift($arguments, $query['language']); // Don't show translation flags for other languages, we can't see them with this search. $limit_language = $query['language']; @@ -2068,7 +2068,7 @@ function _locale_rebuild_js($langcode = // Construct the array for JavaScript translations. // We sort on plural so that we have all plural forms before singular forms. - $result = db_query("SELECT s.lid, s.source, t.plid, t.plural, t.translation FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = '%s' WHERE s.location LIKE '%%.js%%' AND s.textgroup = 'default' ORDER BY t.plural DESC", $language->language); + $result = db_query("SELECT s.[lid], s.[source], t.[plid], t.[plural], t.[translation] FROM [{locales_source}] s LEFT JOIN [{locales_target}] t ON s.[lid] = t.[lid] AND t.[language] = %s WHERE s.[location] LIKE %s AND s.[textgroup] = 'default' ORDER BY t.[plural] DESC", $language->language, '%.js%'); $translations = $plurals = array(); while ($data = db_fetch_object($result)) { @@ -2143,14 +2143,14 @@ function _locale_rebuild_js($langcode = // Save the new JavaScript hash (or an empty value if the file // just got deleted). Act only if some operation was executed. if ($status) { - db_query("UPDATE {languages} SET javascript = '%s' WHERE language = '%s'", $language->javascript, $language->language); + db_query("UPDATE [{languages}] SET [javascript] = %s WHERE [language] = %s", $language->javascript, $language->language); // Update the default language variable if the default language has been altered. // This is necessary to keep the variable consistent with the database // version of the language and to prevent checking against an outdated hash. $default_langcode = language_default('language'); if ($default_langcode == $language->language) { - $default = db_fetch_object(db_query("SELECT * FROM {languages} WHERE language = '%s'", $default_langcode)); + $default = db_fetch_object(db_query("SELECT * FROM [{languages}] WHERE [language] = %s", $default_langcode)); variable_set('language_default', $default); } } @@ -2440,7 +2440,7 @@ function locale_batch_by_language($langc // Collect all files to import for all enabled modules and themes. $files = array(); $components = array(); - $query = "SELECT name, filename FROM {system} WHERE status = 1"; + $query = "SELECT [name], [filename] FROM [{system}] WHERE [status] = 1"; if (count($skip)) { $query .= " AND name NOT IN (". db_placeholders($skip, 'varchar') .")"; } @@ -2475,7 +2475,7 @@ function locale_batch_by_component($comp if (count($languages[1])) { $language_list = join('|', array_keys($languages[1])); // Collect all files to import for all $components. - $result = db_query("SELECT name, filename FROM {system} WHERE status = 1"); + $result = db_query("SELECT [name], [filename] FROM [{system}] WHERE [status] = 1"); while ($component = db_fetch_object($result)) { if (in_array($component->name, $components)) { // Collect all files for this component in all enabled languages, named @@ -2536,7 +2536,7 @@ function _locale_batch_build($files, $fi * Contains a list of files imported. */ function _locale_batch_import($filepath, &$context) { - // The filename is either {langcode}.po or {prefix}.{langcode}.po, so + // The filename is either [{langcode}].po or [{prefix}].[{langcode}].po, so // we can extract the language code to use for the import from the end. if (preg_match('!(/|\.)([^\./]+)\.po$!', $filepath, $langcode)) { $file = (object) array('filename' => basename($filepath), 'filepath' => $filepath); Index: includes/menu.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/menu.inc,v retrieving revision 1.246 diff -u -p -r1.246 menu.inc --- includes/menu.inc 10 Jan 2008 20:16:50 -0000 1.246 +++ includes/menu.inc 16 Jan 2008 15:38:11 -0000 @@ -197,7 +197,7 @@ define('MENU_MAX_DEPTH', 9); * array('node', '12345', 'edit'). * @return * An array which contains the ancestors and placeholders. Placeholders - * simply contain as many '%s' as the ancestors. + * simply contain as many %s as the ancestors. */ function menu_get_ancestors($parts) { $number_parts = count($parts); @@ -228,7 +228,7 @@ function menu_get_ancestors($parts) { $current .= '/'; } } - $placeholders[] = "'%s'"; + $placeholders[] = "%s"; $ancestors[] = $current; } return array($ancestors, $placeholders); @@ -313,7 +313,7 @@ function menu_get_item($path = NULL, $ro $parts = array_slice($original_map, 0, MENU_MAX_PARTS); list($ancestors, $placeholders) = menu_get_ancestors($parts); - if ($router_item = db_fetch_array(db_query_range('SELECT * FROM {menu_router} WHERE path IN ('. implode (',', $placeholders) .') ORDER BY fit DESC', $ancestors, 0, 1))) { + if ($router_item = db_fetch_array(db_query_range('SELECT * FROM [{menu_router}] WHERE [path] IN ('. implode (',', $placeholders) .') ORDER BY [fit] DESC', $ancestors, 0, 1))) { $map = _menu_translate($router_item, $original_map); if ($map === FALSE) { $router_items[$path] = FALSE; @@ -750,7 +750,7 @@ function menu_tree_all_data($menu_name = $cid = 'links:'. $menu_name .':all:'. $mlid; if (!isset($tree[$cid])) { - // If the static variable doesn't have the data, check {cache_menu}. + // If the static variable doesn't have the data, check [{cache_menu}]. $cache = cache_get($cid, 'cache_menu'); if ($cache && isset($cache->data)) { $data = $cache->data; @@ -766,7 +766,7 @@ function menu_tree_all_data($menu_name = } $args = array_unique($args); $placeholders = implode(', ', array_fill(0, count($args), '%d')); - $where = ' AND ml.plid IN ('. $placeholders .')'; + $where = ' AND ml.[plid] IN ('. $placeholders .')'; $parents = $args; $parents[] = $item['mlid']; } @@ -778,13 +778,13 @@ function menu_tree_all_data($menu_name = } array_unshift($args, $menu_name); // Select the links from the table, and recursively build the tree. We - // LEFT JOIN since there is no match in {menu_router} for an external + // LEFT JOIN since there is no match in [{menu_router}] for an external // link. $data['tree'] = menu_tree_data(db_query(" - SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, m.description, ml.* - FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path - WHERE ml.menu_name = '%s'". $where ." - ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC", $args), $parents); + SELECT m.[load_functions], m.[to_arg_functions], m.[access_callback], m.[access_arguments], m.[page_callback], m.[page_arguments], m.[title], m.[title_callback], m.[title_arguments], m.[type], m.[description], ml.* + FROM [{menu_links}] ml LEFT JOIN [{menu_router}] m ON m.[path] = ml.[router_path] + WHERE ml.[menu_name] = %s". $where ." + ORDER BY [p1] ASC, [p2] ASC, [p3] ASC, [p4] ASC, [p5] ASC, [p6] ASC, [p7] ASC, [p8] ASC, [p9] ASC", $args), $parents); $data['node_links'] = array(); menu_tree_collect_node_links($data['tree'], $data['node_links']); // Cache the data. @@ -822,7 +822,7 @@ function menu_tree_page_data($menu_name $cid = 'links:'. $menu_name .':page:'. $item['href'] .':'. (int)$item['access']; if (!isset($tree[$cid])) { - // If the static variable doesn't have the data, check {cache_menu}. + // If the static variable doesn't have the data, check [{cache_menu}]. $cache = cache_get($cid, 'cache_menu'); if ($cache && isset($cache->data)) { $data = $cache->data; @@ -831,12 +831,12 @@ function menu_tree_page_data($menu_name // Build and run the query, and build the tree. if ($item['access']) { // Check whether a menu link exists that corresponds to the current path. - $parents = db_fetch_array(db_query("SELECT p1, p2, p3, p4, p5, p6, p7, p8 FROM {menu_links} WHERE menu_name = '%s' AND link_path = '%s'", $menu_name, $item['href'])); + $parents = db_fetch_array(db_query("SELECT [p1], [p2], [p3], [p4], [p5], [p6], [p7], [p8] FROM [{menu_links}] WHERE [menu_name] = %s AND [link_path] = %s", $menu_name, $item['href'])); if (empty($parents)) { // If no link exists, we may be on a local task that's not in the links. // TODO: Handle the case like a local task on a specific node in the menu. - $parents = db_fetch_array(db_query("SELECT p1, p2, p3, p4, p5, p6, p7, p8 FROM {menu_links} WHERE menu_name = '%s' AND link_path = '%s'", $menu_name, $item['tab_root'])); + $parents = db_fetch_array(db_query("SELECT [p1], [p2], [p3], [p4], [p5], [p6], [p7], [p8] FROM [{menu_links}] WHERE [menu_name] = %s AND [link_path] = %s", $menu_name, $item['tab_root'])); } // We always want all the top-level links with plid == 0. $parents[] = '0'; @@ -850,7 +850,7 @@ function menu_tree_page_data($menu_name // Collect all the links set to be expanded, and then add all of // their children to the list as well. do { - $result = db_query("SELECT mlid FROM {menu_links} WHERE menu_name = '%s' AND expanded = 1 AND has_children = 1 AND plid IN (". $placeholders .') AND mlid NOT IN ('. $placeholders .')', array_merge(array($menu_name), $args, $args)); + $result = db_query("SELECT [mlid] FROM [{menu_links}] WHERE [menu_name] = %s AND [expanded] = 1 AND [has_children] = 1 AND [plid] IN (". $placeholders .') AND [mlid] NOT IN ('. $placeholders .')', array_merge(array($menu_name), $args, $args)); $num_rows = FALSE; while ($item = db_fetch_array($result)) { $args[] = $item['mlid']; @@ -868,13 +868,13 @@ function menu_tree_page_data($menu_name $parents = array(); } // Select the links from the table, and recursively build the tree. We - // LEFT JOIN since there is no match in {menu_router} for an external + // LEFT JOIN since there is no match in [{menu_router}] for an external // link. $data['tree'] = menu_tree_data(db_query(" - SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, m.description, ml.* - FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path - WHERE ml.menu_name = '%s' AND ml.plid IN (". $placeholders .") - ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC", $args), $parents); + SELECT m.[load_functions], m.[to_arg_functions], m.[access_callback], m.[access_arguments], m.[page_callback], m.[page_arguments], m.[title], m.[title_callback], m.[title_arguments], m.[type], m.[description], ml.* + FROM [{menu_links}] ml LEFT JOIN [{menu_router}] m ON m.[path] = ml.[router_path] + WHERE ml.[menu_name] = %s AND ml.[plid] IN (". $placeholders .") + ORDER BY [p1] ASC, [p2] ASC, [p3] ASC, [p4] ASC, [p5] ASC, [p6] ASC, [p7] ASC, [p8] ASC, [p9] ASC", $args), $parents); $data['node_links'] = array(); menu_tree_collect_node_links($data['tree'], $data['node_links']); // Cache the data. @@ -917,7 +917,7 @@ function menu_tree_check_access(&$tree, // Use db_rewrite_sql to evaluate view access without loading each full node. $nids = array_keys($node_links); $placeholders = '%d'. str_repeat(', %d', count($nids) - 1); - $result = db_query(db_rewrite_sql("SELECT n.nid FROM {node} n WHERE n.nid IN (". $placeholders .")"), $nids); + $result = db_query(db_rewrite_sql("SELECT n.[nid] FROM [{node}] n WHERE n.[nid] IN (". $placeholders .")"), $nids); while ($node = db_fetch_array($result)) { $nid = $node['nid']; foreach ($node_links[$nid] as $mlid => $link) { @@ -1121,7 +1121,7 @@ function menu_get_names($reset = FALSE) if ($reset || empty($names)) { $names = array(); - $result = db_query("SELECT DISTINCT(menu_name) FROM {menu_links} ORDER BY menu_name"); + $result = db_query("SELECT DISTINCT([menu_name]) FROM [{menu_links}] ORDER BY [menu_name]"); while ($name = db_fetch_array($result)) { $names[] = $name['menu_name']; } @@ -1227,7 +1227,7 @@ function menu_local_tasks($level = 0, $r return ''; } // Get all tabs and the root page. - $result = db_query("SELECT * FROM {menu_router} WHERE tab_root = '%s' ORDER BY weight, title", $router_item['tab_root']); + $result = db_query("SELECT * FROM [{menu_router}] WHERE [tab_root] = %s ORDER BY [weight], [title]", $router_item['tab_root']); $map = arg(); $children = array(); $tasks = array(); @@ -1527,7 +1527,7 @@ function menu_get_active_title() { * rendering. */ function menu_link_load($mlid) { - if (is_numeric($mlid) && $item = db_fetch_array(db_query("SELECT m.*, ml.* FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path WHERE ml.mlid = %d", $mlid))) { + if (is_numeric($mlid) && $item = db_fetch_array(db_query("SELECT m.*, ml.* FROM [{menu_links}] ml LEFT JOIN [{menu_router}] m ON m.[path] = ml.[router_path] WHERE ml.[mlid] = %d", $mlid))) { _menu_link_translate($item); return $item; } @@ -1591,7 +1591,7 @@ function menu_router_build($reset = FALS $menu = $cache->data; } else { - db_query('DELETE FROM {menu_router}'); + db_query('DELETE FROM [{menu_router}]'); // We need to manually call each module so that we can know which module // a given item came from. $callbacks = array(); @@ -1624,7 +1624,7 @@ function _menu_link_build($item) { $item['hidden'] = 1; } // Note, we set this as 'system', so that we can be sure to distinguish all - // the menu links generated automatically from entries in {menu_router}. + // the menu links generated automatically from entries in [{menu_router}]. $item['module'] = 'system'; $item += array( 'menu_name' => 'navigation', @@ -1654,7 +1654,7 @@ function _menu_navigation_links_rebuild( array_multisort($sort, SORT_NUMERIC, $menu_links); foreach ($menu_links as $item) { - $existing_item = db_fetch_array(db_query("SELECT mlid, menu_name, plid, customized FROM {menu_links} WHERE link_path = '%s' AND module = '%s'", $item['link_path'], 'system')); + $existing_item = db_fetch_array(db_query("SELECT [mlid], [menu_name], [plid], [customized] FROM [{menu_links}] WHERE [link_path] = %s AND [module] = %s", $item['link_path'], 'system')); if ($existing_item) { $item['mlid'] = $existing_item['mlid']; $item['menu_name'] = $existing_item['menu_name']; @@ -1665,13 +1665,13 @@ function _menu_navigation_links_rebuild( } } } - $result = db_query("SELECT ml.link_path, ml.mlid, ml.router_path, ml.updated FROM {menu_links} ml WHERE ml.updated = 1"); + $result = db_query("SELECT ml.[link_path], ml.[mlid], ml.[router_path], ml.[updated] FROM [{menu_links}] ml WHERE ml.[updated] = 1"); while ($item = db_fetch_array($result)) { $router_path = _menu_find_router_path($menu, $item['link_path']); if (!empty($router_path) && ($router_path != $item['router_path'] || $item['updated'])) { // If the router path and the link path matches, it's surely a working // item, so we clear the updated flag. - db_query("UPDATE {menu_links} SET router_path = '%s', updated = %d WHERE mlid = %d", $router_path, $router_path != $item['link_path'], $item['mlid']); + db_query("UPDATE [{menu_links}] SET [router_path] = %s, [updated] = %d WHERE [mlid] = %d", $router_path, $router_path != $item['link_path'], $item['mlid']); } } } @@ -1686,10 +1686,10 @@ function _menu_navigation_links_rebuild( */ function menu_link_delete($mlid, $path = NULL) { if (isset($mlid)) { - _menu_delete_item(db_fetch_array(db_query("SELECT * FROM {menu_links} WHERE mlid = %d", $mlid))); + _menu_delete_item(db_fetch_array(db_query("SELECT * FROM [{menu_links}] WHERE [mlid] = %d", $mlid))); } else { - $result = db_query("SELECT * FROM {menu_links} WHERE link_path = '%s'", $path); + $result = db_query("SELECT * FROM [{menu_links}] WHERE [link_path] = %s", $path); while ($link = db_fetch_array($result)) { _menu_delete_item($link); } @@ -1705,14 +1705,14 @@ function _menu_delete_item($item) { if ($item && ($item['module'] != 'system' || $item['updated'])) { // Children get re-attached to the item's parent. if ($item['has_children']) { - $result = db_query("SELECT mlid FROM {menu_links} WHERE plid = %d", $item['mlid']); + $result = db_query("SELECT [mlid] FROM [{menu_links}] WHERE [plid] = %d", $item['mlid']); while ($m = db_fetch_array($result)) { $child = menu_link_load($m['mlid']); $child['plid'] = $item['plid']; menu_link_save($child); } } - db_query('DELETE FROM {menu_links} WHERE mlid = %d', $item['mlid']); + db_query('DELETE FROM [{menu_links}] WHERE [mlid] = %d', $item['mlid']); // Update the has_children status of the parent. _menu_update_parental_status($item); @@ -1759,18 +1759,18 @@ function menu_link_save(&$item) { $menu_name = $item['menu_name']; $existing_item = FALSE; if (isset($item['mlid'])) { - $existing_item = db_fetch_array(db_query("SELECT * FROM {menu_links} WHERE mlid = %d", $item['mlid'])); + $existing_item = db_fetch_array(db_query("SELECT * FROM [{menu_links}] WHERE [mlid] = %d", $item['mlid'])); } // Find the parent - it must be in the same menu. if (isset($item['plid'])) { - $parent = db_fetch_array(db_query("SELECT * FROM {menu_links} WHERE menu_name = '%s' AND mlid = %d", $menu_name, $item['plid'])); + $parent = db_fetch_array(db_query("SELECT * FROM [{menu_links}] WHERE [menu_name] = %s AND [mlid] = %d", $menu_name, $item['plid'])); } else { $parent_path = $item['link_path']; do { $parent_path = substr($parent_path, 0, strrpos($parent_path, '/')); - $parent = db_fetch_array(db_query("SELECT * FROM {menu_links} WHERE menu_name = '%s' AND link_path = '%s'", $menu_name, $parent_path)); + $parent = db_fetch_array(db_query("SELECT * FROM [{menu_links}] WHERE [menu_name] = %s AND [link_path] = %s", $menu_name, $parent_path)); } while ($parent === FALSE && $parent_path); } // Menu callbacks need to be in the links table for breadcrumbs, but can't @@ -1783,21 +1783,10 @@ function menu_link_save(&$item) { } if (!$existing_item) { - db_query("INSERT INTO {menu_links} ( - menu_name, plid, link_path, - hidden, external, has_children, - expanded, weight, - module, link_title, options, - customized, updated) VALUES ( - '%s', %d, '%s', - %d, %d, %d, - %d, %d, - '%s', '%s', '%s', %d, %d)", - $item['menu_name'], $item['plid'], $item['link_path'], - $item['hidden'], $item['_external'], $item['has_children'], - $item['expanded'], $item['weight'], - $item['module'], $item['link_title'], serialize($item['options']), - $item['customized'], $item['updated']); + $values = $item; + $values['external'] = $item['_external']; + $values['options'] = serialize($item['options']); + drupal_write_record('menu_links', $values); $item['mlid'] = db_last_insert_id('menu_links', 'mlid'); } @@ -1838,16 +1827,10 @@ function menu_link_save(&$item) { $item['router_path'] = _menu_find_router_path($menu, $item['link_path']); } } - db_query("UPDATE {menu_links} SET menu_name = '%s', plid = %d, link_path = '%s', - router_path = '%s', hidden = %d, external = %d, has_children = %d, - expanded = %d, weight = %d, depth = %d, - p1 = %d, p2 = %d, p3 = %d, p4 = %d, p5 = %d, p6 = %d, p7 = %d, p8 = %d, p9 = %d, - module = '%s', link_title = '%s', options = '%s', customized = %d WHERE mlid = %d", - $item['menu_name'], $item['plid'], $item['link_path'], - $item['router_path'], $item['hidden'], $item['_external'], $item['has_children'], - $item['expanded'], $item['weight'], $item['depth'], - $item['p1'], $item['p2'], $item['p3'], $item['p4'], $item['p5'], $item['p6'], $item['p7'], $item['p8'], $item['p9'], - $item['module'], $item['link_title'], serialize($item['options']), $item['customized'], $item['mlid']); + $values = $item; + $values['external'] = $item['_external']; + $values['options'] = serialize($item['options']); + drupal_write_record('menu_links', $values, 'mlid'); // Check the has_children status of the parent. _menu_update_parental_status($item); menu_cache_clear($menu_name); @@ -1886,7 +1869,7 @@ function _menu_clear_page_cache() { */ function _menu_set_expanded_menus() { $names = array(); - $result = db_query("SELECT menu_name FROM {menu_links} WHERE expanded != 0 GROUP BY menu_name"); + $result = db_query("SELECT [menu_name] FROM [{menu_links}] WHERE [expanded] != 0 GROUP BY [menu_name]"); while ($n = db_fetch_array($result)) { $names[] = $n['menu_name']; } @@ -1945,7 +1928,7 @@ function menu_link_maintain($module, $op return menu_link_save($menu_link); break; case 'update': - db_query("UPDATE {menu_links} SET link_title = '%s' WHERE link_path = '%s' AND customized = 0 AND module = '%s'", $link_title, $link_path, $module); + db_query("UPDATE [{menu_links}] SET [link_title] = %s WHERE [link_path] = %s AND [customized] = 0 AND [module] = %s", $link_title, $link_path, $module); menu_cache_clear(); break; case 'delete': @@ -1972,12 +1955,12 @@ function menu_link_children_relative_dep $args[] = $item['menu_name']; $p = 'p1'; while ($i <= MENU_MAX_DEPTH && $item[$p]) { - $match .= " AND $p = %d"; + $match .= " AND [$p] = %d"; $args[] = $item[$p]; $p = 'p'. ++$i; } - $max_depth = db_result(db_query_range("SELECT depth FROM {menu_links} WHERE menu_name = '%s'". $match ." ORDER BY depth DESC", $args, 0, 1)); + $max_depth = db_result(db_query_range("SELECT [depth] FROM [{menu_links}] WHERE [menu_name] = %s". $match ." ORDER BY [depth] DESC", $args, 0, 1)); return ($max_depth > $item['depth']) ? $max_depth - $item['depth'] : 0; } @@ -1991,26 +1974,26 @@ function menu_link_children_relative_dep function _menu_link_move_children($item, $existing_item) { $args[] = $item['menu_name']; - $set[] = "menu_name = '%s'"; + $set[] = "[menu_name] = %s"; $i = 1; while ($i <= $item['depth']) { $p = 'p'. $i++; - $set[] = "$p = %d"; + $set[] = "[$p] = %d"; $args[] = $item[$p]; } $j = $existing_item['depth'] + 1; while ($i <= MENU_MAX_DEPTH && $j <= MENU_MAX_DEPTH) { - $set[] = 'p'. $i++ .' = p'. $j++; + $set[] = '[p'. $i++ .'] = [p'. $j++ .']'; } while ($i <= MENU_MAX_DEPTH) { - $set[] = 'p'. $i++ .' = 0'; + $set[] = '[p'. $i++ .'] = 0'; } $shift = $item['depth'] - $existing_item['depth']; if ($shift < 0) { $args[] = -$shift; - $set[] = 'depth = depth - %d'; + $set[] = '[depth] = [depth] - %d'; } elseif ($shift > 0) { // The order of $set must be reversed so the new values don't overwrite the @@ -2021,17 +2004,17 @@ function _menu_link_move_children($item, $args = array_reverse($args); $args[] = $shift; - $set[] = 'depth = depth + %d'; + $set[] = '[depth] = [depth] + %d'; } - $where[] = "menu_name = '%s'"; + $where[] = "[menu_name] = %s"; $args[] = $existing_item['menu_name']; $p = 'p1'; for ($i = 1; $i <= MENU_MAX_DEPTH && $existing_item[$p]; $p = 'p'. ++$i) { - $where[] = "$p = %d"; + $where[] = "[$p] = %d"; $args[] = $existing_item[$p]; } - db_query("UPDATE {menu_links} SET ". implode(', ', $set) ." WHERE ". implode(' AND ', $where), $args); + db_query("UPDATE [{menu_links}] SET ". implode(', ', $set) ." WHERE ". implode(' AND ', $where), $args); // Check the has_children status of the parent, while excluding this item. _menu_update_parental_status($existing_item, TRUE); } @@ -2043,10 +2026,10 @@ function _menu_update_parental_status($i // If plid == 0, there is nothing to update. if ($item['plid']) { // We may want to exclude the passed link as a possible child. - $where = $exclude ? " AND mlid != %d" : ''; + $where = $exclude ? " AND [mlid] != %d" : ''; // Check if at least one visible child exists in the table. - $parent_has_children = (bool)db_result(db_query_range("SELECT mlid FROM {menu_links} WHERE menu_name = '%s' AND plid = %d AND hidden = 0". $where, $item['menu_name'], $item['plid'], $item['mlid'], 0, 1)); - db_query("UPDATE {menu_links} SET has_children = %d WHERE mlid = %d", $parent_has_children, $item['plid']); + $parent_has_children = (bool)db_result(db_query_range("SELECT [mlid] FROM [{menu_links}] WHERE [menu_name] = %s AND [plid] = %d AND [hidden] = 0". $where, $item['menu_name'], $item['plid'], $item['mlid'], 0, 1)); + db_query("UPDATE [{menu_links}] SET [has_children] = %d WHERE [mlid] = %d", $parent_has_children, $item['plid']); } } @@ -2230,23 +2213,19 @@ function _menu_router_build($callbacks) $item['include file'] = $file_path .'/'. $item['file']; } - $title_arguments = $item['title arguments'] ? serialize($item['title arguments']) : ''; - db_query("INSERT INTO {menu_router} - (path, load_functions, to_arg_functions, access_callback, - access_arguments, page_callback, page_arguments, fit, - number_parts, tab_parent, tab_root, - title, title_callback, title_arguments, - type, block_callback, description, position, weight, file) - VALUES ('%s', '%s', '%s', '%s', - '%s', '%s', '%s', %d, - %d, '%s', '%s', - '%s', '%s', '%s', - %d, '%s', '%s', '%s', %d, '%s')", - $path, $item['load_functions'], $item['to_arg_functions'], $item['access callback'], - serialize($item['access arguments']), $item['page callback'], serialize($item['page arguments']), $item['_fit'], - $item['_number_parts'], $item['tab_parent'], $item['tab_root'], - $item['title'], $item['title callback'], $title_arguments, - $item['type'], $item['block callback'], $item['description'], $item['position'], $item['weight'], $item['include file']); + $values = $item; + $values['path'] = $path; + $values['access_callback'] = $item['access callback']; + $values['access_arguments'] = serialize($item['access arguments']); + $values['page_callback'] = $item['page callback']; + $values['page_arguments'] = serialize($item['page arguments']); + $values['fit'] = $item['_fit']; + $values['number_parts'] = $item['_number_parts']; + $values['title_callback'] = $item['title callback']; + $values['title_arguments'] = $item['title arguments'] ? serialize($item['title arguments']) : ''; + $values['block_callback'] = $item['block callback']; + $values['file'] = $item['include file']; + drupal_write_record('menu_router', $values); } // Sort the masks so they are in order of descending fit, and store them. $masks = array_keys($masks); @@ -2314,7 +2293,7 @@ function menu_valid_path($form_item) { } elseif (preg_match('/\/\%/', $path)) { // Path is dynamic (ie 'user/%'), so check directly against menu_router table. - if ($item = db_fetch_array(db_query("SELECT * FROM {menu_router} where path = '%s' ", $path))) { + if ($item = db_fetch_array(db_query("SELECT * FROM [{menu_router}] where path = %s ", $path))) { $item['link_path'] = $form_item['link_path']; $item['link_title'] = $form_item['link_title']; $item['external'] = FALSE; Index: includes/module.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/module.inc,v retrieving revision 1.115 diff -u -p -r1.115 module.inc --- includes/module.inc 27 Dec 2007 12:31:05 -0000 1.115 +++ includes/module.inc 16 Jan 2008 15:38:11 -0000 @@ -58,10 +58,10 @@ function module_list($refresh = FALSE, $ } else { if ($bootstrap) { - $result = db_query("SELECT name, filename, throttle FROM {system} WHERE type = 'module' AND status = 1 AND bootstrap = 1 ORDER BY weight ASC, filename ASC"); + $result = db_query("SELECT [name], [filename], [throttle] FROM [{system}] WHERE [type] = 'module' AND [status] = 1 AND [bootstrap] = 1 ORDER BY [weight] ASC, [filename] ASC"); } else { - $result = db_query("SELECT name, filename, throttle FROM {system} WHERE type = 'module' AND status = 1 ORDER BY weight ASC, filename ASC"); + $result = db_query("SELECT [name], [filename], [throttle] FROM [{system}] WHERE [type] = 'module' AND [status] = 1 ORDER BY [weight] ASC, [filename] ASC"); } while ($module = db_fetch_object($result)) { if (file_exists($module->filename)) { @@ -138,13 +138,13 @@ function module_rebuild_cache() { // Update the contents of the system table: if (isset($file->status) || (isset($file->old_filename) && $file->old_filename != $file->filename)) { - db_query("UPDATE {system} SET info = '%s', name = '%s', filename = '%s', bootstrap = %d WHERE filename = '%s'", serialize($files[$filename]->info), $file->name, $file->filename, $bootstrap, $file->old_filename); + db_query("UPDATE [{system}] SET [info] = %s, [name] = %s, [filename] = %s, [bootstrap] = %d WHERE [filename] = %s", serialize($files[$filename]->info), $file->name, $file->filename, $bootstrap, $file->old_filename); } else { // This is a new module. $files[$filename]->status = 0; $files[$filename]->throttle = 0; - db_query("INSERT INTO {system} (name, info, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $file->name, serialize($files[$filename]->info), 'module', $file->filename, 0, 0, $bootstrap); + db_query("INSERT INTO [{system}] ([name], [info], [type], [filename], [status], [throttle], [bootstrap]) VALUES (%s, %s, %s, %s, %d, %d, %d)", $file->name, serialize($files[$filename]->info), 'module', $file->filename, 0, 0, $bootstrap); } } $files = _module_build_dependencies($files); @@ -286,10 +286,10 @@ function module_load_all_includes($type, function module_enable($module_list) { $invoke_modules = array(); foreach ($module_list as $module) { - $existing = db_fetch_object(db_query("SELECT status FROM {system} WHERE type = '%s' AND name = '%s'", 'module', $module)); + $existing = db_fetch_object(db_query("SELECT [status] FROM [{system}] WHERE [type] = %s AND [name] = %s", 'module', $module)); if ($existing->status == 0) { module_load_install($module); - db_query("UPDATE {system} SET status = %d, throttle = %d WHERE type = '%s' AND name = '%s'", 1, 0, 'module', $module); + db_query("UPDATE [{system}] SET [status] = %d, [throttle] = %d WHERE [type] = %s AND [name] = %s", 1, 0, 'module', $module); drupal_load('module', $module); $invoke_modules[] = $module; } @@ -331,7 +331,7 @@ function module_disable($module_list) { module_load_install($module); module_invoke($module, 'disable'); - db_query("UPDATE {system} SET status = %d, throttle = %d WHERE type = '%s' AND name = '%s'", 0, 0, 'module', $module); + db_query("UPDATE [{system}] SET [status] = %d, [throttle] = %d WHERE [type] = %s AND [name] = %s", 0, 0, 'module', $module); $invoke_modules[] = $module; } } Index: includes/path.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/path.inc,v retrieving revision 1.19 diff -u -p -r1.19 path.inc --- includes/path.inc 4 Nov 2007 16:42:45 -0000 1.19 +++ includes/path.inc 16 Jan 2008 15:38:11 -0000 @@ -52,7 +52,7 @@ function drupal_lookup_path($action, $pa // Use $count to avoid looking up paths in subsequent calls if there simply are no aliases if (!isset($count)) { - $count = db_result(db_query('SELECT COUNT(pid) FROM {url_alias}')); + $count = db_result(db_query('SELECT COUNT([pid]) FROM [{url_alias}]')); } if ($action == 'wipe') { @@ -65,7 +65,7 @@ function drupal_lookup_path($action, $pa return $map[$path_language][$path]; } // Get the most fitting result falling back with alias without language - $alias = db_result(db_query("SELECT dst FROM {url_alias} WHERE src = '%s' AND language IN('%s', '') ORDER BY language DESC", $path, $path_language)); + $alias = db_result(db_query("SELECT [dst] FROM [{url_alias}] WHERE [src] = %s AND [language] IN (%s, %s) ORDER BY [language] DESC", $path, $path_language, '')); $map[$path_language][$path] = $alias; return $alias; } @@ -76,7 +76,7 @@ function drupal_lookup_path($action, $pa $src = ''; if (!isset($map[$path_language]) || !($src = array_search($path, $map[$path_language]))) { // Get the most fitting result falling back with alias without language - if ($src = db_result(db_query("SELECT src FROM {url_alias} WHERE dst = '%s' AND language IN('%s', '') ORDER BY language DESC", $path, $path_language))) { + if ($src = db_result(db_query("SELECT [src] FROM [{url_alias}] WHERE [dst] = %s AND [language] IN (%s, %s) ORDER BY [language] DESC", $path, $path_language, ''))) { $map[$path_language][$src] = $path; } else { Index: includes/schema.db2.inc =================================================================== RCS file: includes/schema.db2.inc diff -N includes/schema.db2.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/schema.db2.inc 16 Jan 2008 15:38:11 -0000 @@ -0,0 +1,411 @@ + 'VARCHAR', + 'char:normal' => 'CHAR', + + 'text:tiny' => 'VARCHAR(4000)', + 'text:small' => 'VARCHAR(4000)', + 'text:medium' => 'VARCHAR(4000)', + 'text:big' => 'VARCHAR(4000)', + 'text:normal' => 'VARCHAR(4000)', + + 'serial:tiny' => 'INTEGER', + 'serial:small' => 'INTEGER', + 'serial:medium' => 'INTEGER', + 'serial:big' => 'BIGINT', + 'serial:normal' => 'INTEGER', + + 'int:tiny' => 'SMALLINT', + 'int:small' => 'SMALLINT', + 'int:medium' => 'INTEGER', + 'int:big' => 'BIGINT', + 'int:normal' => 'INTEGER', + + 'float:tiny' => 'REAL', + 'float:small' => 'REAL', + 'float:medium' => 'REAL', + 'float:big' => 'DOUBLE', + 'float:normal' => 'REAL', + + 'numeric:normal' => 'NUMERIC', + + 'blob:big' => 'BLOB(2G)', + 'blob:normal' => 'BLOB(2G)', + + 'clob:big' => 'CLOB(2G)', + 'clob:normal' => 'CLOB(2G)', + + 'datetime:normal' => 'TIMESTAMP', + ); + return $map; +} + +/** + * Generate SQL to create a new table from a Drupal schema definition. + * + * @param $name + * The name of the table to create. + * @param $table + * A Schema API table definition array. + * @return + * An array of SQL statements to create the table. + */ +function db_create_table_sql($name, $table) { + $sql_keys = array(); + if (isset($table['primary key']) && is_array($table['primary key'])) { + $sql_keys[] = 'CONSTRAINT [pk_{' . $name . '}] PRIMARY KEY (['. implode('], [', $table['primary key']) .'])'; + } + if (isset($table['unique keys']) && is_array($table['unique keys'])) { + foreach ($table['unique keys'] as $key => $value) { + $sql_keys[] = 'CONSTRAINT [ix_{'. $name .'}_'. $key .'] UNIQUE (['. implode('], [', $value) .'])'; + } + } + + $sql_fields = array(); + foreach ($table['fields'] as $field_name => $field) { + $sql_fields[] = _db_create_field_sql($field_name, _db_process_field($field)); + } + + $sql = 'CREATE TABLE [{'. $name .'}] (' . "\n\t"; + $sql .= implode(",\n\t", $sql_fields); + if (count($sql_keys) > 0) { + $sql .= ",\n\t"; + } + $sql .= implode(",\n\t", $sql_keys); + $sql .= "\n)"; + $statements[] = $sql; + + if (isset($table['indexes']) && is_array($table['indexes'])) { + foreach ($table['indexes'] as $key => $value) { + $statements[] = _db_create_index_sql($name, $key, $value); + } + } + + return $statements; +} + +function _db_create_index_sql($table, $name, $fields) { + $ix = 'ix_{'. $table .'}_'. $name; + return 'CREATE INDEX ['. $ix .'] ON [{'. $table .'}] ('. _db_create_key_sql($fields) .')'; +} + +function _db_create_key_sql($fields) { + $ret = array(); + foreach ($fields as $field) { + $ret[] = is_array($field) ? '['. $field[0] .']' : '['. $field .']'; + } + return implode(', ', $ret); +} + +/** + * Set database-engine specific properties for a field. + * + * @param $field + * A field description array, as specified in the schema documentation. + */ +function _db_process_field($field) { + if (!isset($field['size'])) { + $field['size'] = 'normal'; + } + // Set the correct database-engine specific datatype. + if (!isset($field['db2_type'])) { + $map = db_type_map(); + $field['db2_type'] = $map[$field['type'] .':'. $field['size']]; + } + if ($field['type'] == 'serial') { + unset($field['not null']); + } + return $field; +} + +/** + * Create an SQL string for a field to be used in table creation or alteration. + * + * Before passing a field out of a schema definition into this function it has + * to be processed by _db_process_field(). + * + * @param $name + * Name of the field. + * @param $spec + * The field specification, as per the schema data structure format. + */ +function _db_create_field_sql($name, $spec) { + $sql = '['. $name .'] '. $spec['db2_type']; + + if (($spec['type'] == 'blob') || ($spec['type'] == 'clob')) { + $sql .= " NOT LOGGED NOT COMPACT"; + unset($spec['not null']); + } + + if (!empty($spec['length'])) { + $sql .= '('. $spec['length'] .')'; + } + elseif (isset($spec['precision']) && isset($spec['scale'])) { + $sql .= '('. $spec['scale'] .', '. $spec['precision'] .')'; + } + + if (isset($spec['not null']) && $spec['not null']) { + $sql .= ' NOT NULL'; + } + + if (isset($spec['default'])) { + $default = is_string($spec['default']) ? "'". $spec['default'] ."'" : $spec['default']; + $sql .= " DEFAULT $default"; + } + + if (!empty($spec['unsigned'])) { + $sql .= ' CHECK (' . $name . ' >= 0)'; + } + + if ($spec['type'] == 'serial') { + $sql .= ' GENERATED ALWAYS AS IDENTITY (START WITH +1 INCREMENT BY +1 NO CYCLE NO CACHE ORDER)'; + } + + return $sql; +} + +/** + * Rename a table. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be renamed. + * @param $new_name + * The new name for the table. + */ +function db_rename_table(&$ret, $table, $new_name) { + $ret[] = update_sql('RENAME TABLE [{'. $table .'}] TO [{'. $new_name .'}]'); +} + +/** + * Drop a table. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be dropped. + */ +function db_drop_table(&$ret, $table) { + $ret[] = update_sql('DROP TABLE [{'. $table .'}]'); +} + +/** + * Add a new field to a table. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * Name of the table to be altered. + * @param $field + * Name of the field to be added. + * @param $spec + * The field specification array, as taken from a schema definition + */ +function db_add_field(&$ret, $table, $field, $spec) { + $query = 'ALTER TABLE [{'. $table .'}] ADD '; + $query .= _db_create_field_sql($field, _db_process_field($spec)); + $ret[] = update_sql($query); +} + +/** + * Drop a field. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $field + * The field to be dropped. + */ +function db_drop_field(&$ret, $table, $field) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] DROP ['. $field .']'); +} + +/** + * Set the default value for a field. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $field + * The field to be altered. + * @param $default + * Default value to be set. NULL for 'default NULL'. + */ +function db_field_set_default(&$ret, $table, $field, $default) { + if ($default == NULL) { + $default = 'NULL'; + } + else { + $default = is_string($default) ? "'$default'" : $default; + } + + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] ALTER ['. $field .'] SET DEFAULT '. $default); +} + +/** + * Set a field to have no default value. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $field + * The field to be altered. + */ +function db_field_set_no_default(&$ret, $table, $field) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] ALTER ['. $field .'] DROP DEFAULT'); +} + +/** + * Add a primary key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $fields + * Fields for the primary key. + */ +function db_add_primary_key(&$ret, $table, $fields) { + $pk = 'pk_{' . $table . '}'; + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] ADD CONSTRAINT ['. $pk .'] PRIMARY KEY ([' . implode('], [', $fields) . '])'); +} + +/** + * Drop the primary key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + */ +function db_drop_primary_key(&$ret, $table) { + $pk = 'pk_{' . $table . '}'; + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] DROP CONSTRAINT ['. $pk .']'); +} + +/** + * Add a unique key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the key. + * @param $fields + * An array of field names. + */ +function db_add_unique_key(&$ret, $table, $name, $fields) { + $ix = 'ix_{'. $table .'}_'. $name; + $ret[] = update_sql('ALTER TABLE [{' . $table . '}] ADD CONSTRAINT ['. $ix .'] UNIQUE ([' . implode('], [', $fields) . '])'); +} + +/** + * Drop a unique key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the key. + */ +function db_drop_unique_key(&$ret, $table, $name) { + $ix = 'ix_{'. $table .'}_'. $name; + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] DROP CONSTRAINT ['. $ix .']'); +} + +/** + * Add an index. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the index. + * @param $fields + * An array of field names. + */ +function db_add_index(&$ret, $table, $name, $fields) { + $ret[] = update_sql(_db_create_index_sql($table, $name, $fields)); +} + +/** + * Drop an index. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the index. + */ +function db_drop_index(&$ret, $table, $name) { + $name = 'ix_{'. $table .'}_'. $name; + $ret[] = update_sql('DROP INDEX ['. $name .']'); +} + +/** + * Change a field definition. + * + * Remember that changing a field definition involves adding a new field + * and dropping an old one. This means that any indices, primary keys and + * sequences from serial-type fields are dropped and might need to be + * recreated. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * Name of the table. + * @param $field + * Name of the field to change. + * @param $field_new + * New name for the field (set to the same as $field if you don't want to change the name). + * @param $spec + * The field specification for the new field. + */ +function db_change_field(&$ret, $table, $field, $field_new, $spec) { + // NOTE: DB2 don't support column rename query (known issue), so first of + // all we need to copy old column data to temp column, drop old column, and + // copy it back to new column. + db_add_field($ret, $table, "new_" . $field_new, $spec); + $ret[] = update_sql('UPDATE [{'. $table .'}] SET [new_'. $field_new ."] = [". $field .']'); + db_drop_field($ret, $table, $field); + db_add_field($ret, $table, "$field_new", $spec); + $ret[] = update_sql('UPDATE [{'. $table .'}] SET ['. $field_new ."] = [new_". $field .']'); + $not_null = isset($spec['not null']) ? $spec['not null'] : FALSE; + unset($spec['not null']); + if ($not_null) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] ALTER ['. $field_new ."] SET NOT NULL"); + } + db_drop_field($ret, $table, "new_" . $field); +} + +/** + * @} End of "ingroup schemaapi". + */ Index: includes/schema.mysql.inc =================================================================== RCS file: includes/schema.mysql.inc diff -N includes/schema.mysql.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/schema.mysql.inc 16 Jan 2008 15:38:11 -0000 @@ -0,0 +1,494 @@ + 'VARCHAR', + 'char:normal' => 'CHAR', + + 'text:tiny' => 'SMALLTEXT', + 'text:small' => 'SMALLTEXT', + 'text:medium' => 'MEDIUMTEXT', + 'text:big' => 'LONGTEXT', + 'text:normal' => 'TEXT', + + 'serial:tiny' => 'TINYINT', + 'serial:small' => 'SMALLINT', + 'serial:medium' => 'MEDIUMINT', + 'serial:big' => 'BIGINT', + 'serial:normal' => 'INT', + + 'int:tiny' => 'TINYINT', + 'int:small' => 'SMALLINT', + 'int:medium' => 'MEDIUMINT', + 'int:big' => 'BIGINT', + 'int:normal' => 'INT', + + 'float:tiny' => 'FLOAT', + 'float:small' => 'FLOAT', + 'float:medium' => 'FLOAT', + 'float:big' => 'DOUBLE', + 'float:normal' => 'FLOAT', + + 'numeric:normal' => 'DECIMAL', + + 'blob:big' => 'LONGBLOB', + 'blob:normal' => 'BLOB', + + 'clob:big' => 'LONGTEXT', + 'clob:normal' => 'TEXT', + + 'datetime:normal' => 'DATETIME', + ); + return $map; +} + +/** + * Generate SQL to create a new table from a Drupal schema definition. + * + * @param $name + * The name of the table to create. + * @param $table + * A Schema API table definition array. + * @return + * An array of SQL statements to create the table. + */ +function db_create_table_sql($name, $table) { + + if (empty($table['mysql_suffix'])) { + $table['mysql_suffix'] = "/*!40100 DEFAULT CHARACTER SET UTF8 */"; + } + + $sql = "CREATE TABLE [{". $name ."}] (\n"; + + // Add the SQL statement for each field. + foreach ($table['fields'] as $field_name => $field) { + $sql .= _db_create_field_sql($field_name, _db_process_field($field)) .", \n"; + } + + // Process keys & indexes. + $keys = _db_create_keys($table); + if (count($keys)) { + $sql .= implode(", \n", $keys) .", \n"; + } + + // Remove the last comma and space. + $sql = substr($sql, 0, -3) ."\n) "; + + $sql .= $table['mysql_suffix']; + + return array($sql); +} + +function _db_create_key_sql($fields) { + $ret = array(); + foreach ($fields as $field) { + if (is_array($field)) { + $ret[] = $field[0] .'('. $field[1] .')'; + } + else { + $ret[] = '['. $field .']'; + } + } + return implode(', ', $ret); +} + +function _db_create_keys($spec) { + $keys = array(); + + if (!empty($spec['primary key'])) { + $keys[] = 'PRIMARY KEY ('. _db_create_key_sql($spec['primary key']) .')'; + } + if (!empty($spec['unique keys'])) { + foreach ($spec['unique keys'] as $key => $fields) { + $keys[] = 'UNIQUE KEY ['. $key .'] ('. _db_create_key_sql($fields) .')'; + } + } + if (!empty($spec['indexes'])) { + foreach ($spec['indexes'] as $index => $fields) { + $keys[] = 'INDEX ['. $index .'] ('. _db_create_key_sql($fields) .')'; + } + } + + return $keys; +} + +/** + * Set database-engine specific properties for a field. + * + * @param $field + * A field description array, as specified in the schema documentation. + */ +function _db_process_field($field) { + + if (!isset($field['size'])) { + $field['size'] = 'normal'; + } + + // Set the correct database-engine specific datatype. + if (!isset($field['mysql_type'])) { + $map = db_type_map(); + $field['mysql_type'] = $map[$field['type'] .':'. $field['size']]; + } + + if ($field['type'] == 'serial') { + $field['auto_increment'] = TRUE; + } + + return $field; +} + +/** + * Create an SQL string for a field to be used in table creation or alteration. + * + * Before passing a field out of a schema definition into this function it has + * to be processed by _db_process_field(). + * + * @param $name + * Name of the field. + * @param $spec + * The field specification, as per the schema data structure format. + */ +function _db_create_field_sql($name, $spec) { + $sql = "[". $name ."] ". $spec['mysql_type']; + + if (($spec['type'] == 'text') || ($spec['type'] == 'blob')) { + unset($spec['default']); + } + + if (isset($spec['length'])) { + $sql .= '('. $spec['length'] .')'; + } + elseif (isset($spec['precision']) && isset($spec['scale'])) { + $sql .= '('. $spec['scale'] .', '. $spec['precision'] .')'; + } + + if (!empty($spec['unsigned'])) { + $sql .= ' UNSIGNED'; + } + + if (!empty($spec['not null'])) { + $sql .= ' NOT NULL'; + } + + if (!empty($spec['auto_increment'])) { + $sql .= ' AUTO_INCREMENT'; + } + + if (isset($spec['default'])) { + if (is_string($spec['default'])) { + $spec['default'] = "'". $spec['default'] ."'"; + } + $sql .= ' DEFAULT '. $spec['default']; + } + + if (empty($spec['not null']) && !isset($spec['default'])) { + $sql .= ' DEFAULT NULL'; + } + + return $sql; +} + +/** + * Rename a table. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be renamed. + * @param $new_name + * The new name for the table. + */ +function db_rename_table(&$ret, $table, $new_name) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] RENAME TO [{'. $new_name .'}]'); +} + +/** + * Drop a table. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be dropped. + */ +function db_drop_table(&$ret, $table) { + $ret[] = update_sql('DROP TABLE [{'. $table .'}]'); +} + +/** + * Add a new field to a table. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * Name of the table to be altered. + * @param $field + * Name of the field to be added. + * @param $spec + * The field specification array, as taken from a schema definition. + * The specification may also contain the key 'initial', the newly + * created field will be set to the value of the key in all rows. + * This is most useful for creating NOT NULL columns with no default + * value in existing tables. + * @param $keys_new + * Optional keys and indexes specification to be created on the + * table along with adding the field. The format is the same as a + * table specification but without the 'fields' element. If you are + * adding a type 'serial' field, you MUST specify at least one key + * or index including it in this array. @see db_change_field for more + * explanation why. + */ +function db_add_field(&$ret, $table, $field, $spec, $keys_new = array()) { + $fixnull = FALSE; + if (!empty($spec['not null']) && !isset($spec['default'])) { + $fixnull = TRUE; + $spec['not null'] = FALSE; + } + $query = 'ALTER TABLE [{'. $table .'}] ADD '; + $query .= _db_create_field_sql($field, _db_process_field($spec)); + if (count($keys_new)) { + $query .= ', ADD '. implode(', ADD ', _db_create_keys($keys_new)); + } + $ret[] = update_sql($query); + if (isset($spec['initial'])) { + // All this because update_sql does not support %-placeholders. + $sql = 'UPDATE [{'. $table .'}] SET ['. $field .'] = '. db_type_placeholder($spec['type']); + $result = db_query($sql, $spec['initial']); + $ret[] = array('success' => $result !== FALSE, 'query' => check_plain($sql .' ('. $spec['initial'] .')')); + } + if ($fixnull) { + $spec['not null'] = TRUE; + db_change_field($ret, $table, $field, $field, $spec); + } +} + +/** + * Drop a field. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $field + * The field to be dropped. + */ +function db_drop_field(&$ret, $table, $field) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] DROP '. $field); +} + +/** + * Set the default value for a field. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $field + * The field to be altered. + * @param $default + * Default value to be set. NULL for 'default NULL'. + */ +function db_field_set_default(&$ret, $table, $field, $default) { + if ($default == NULL) { + $default = 'NULL'; + } + else { + $default = is_string($default) ? "'$default'" : $default; + } + + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] ALTER COLUMN ['. $field .'] SET DEFAULT '. $default); +} + +/** + * Set a field to have no default value. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $field + * The field to be altered. + */ +function db_field_set_no_default(&$ret, $table, $field) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] ALTER COLUMN ['. $field .'] DROP DEFAULT'); +} + +/** + * Add a primary key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $fields + * Fields for the primary key. + */ +function db_add_primary_key(&$ret, $table, $fields) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] ADD PRIMARY KEY ('. _db_create_key_sql($fields) .')'); +} + +/** + * Drop the primary key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + */ +function db_drop_primary_key(&$ret, $table) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] DROP PRIMARY KEY'); +} + +/** + * Add a unique key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the key. + * @param $fields + * An array of field names. + */ +function db_add_unique_key(&$ret, $table, $name, $fields) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] ADD UNIQUE KEY '. $name .' ('. _db_create_key_sql($fields) .')'); +} + +/** + * Drop a unique key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the key. + */ +function db_drop_unique_key(&$ret, $table, $name) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] DROP KEY '. $name); +} + +/** + * Add an index. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the index. + * @param $fields + * An array of field names. + */ +function db_add_index(&$ret, $table, $name, $fields) { + $query = 'ALTER TABLE [{'. $table .'}] ADD INDEX ['. $name .'] ('. _db_create_key_sql($fields) .')'; + $ret[] = update_sql($query); +} + +/** + * Drop an index. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the index. + */ +function db_drop_index(&$ret, $table, $name) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] DROP INDEX '. $name); +} + +/** + * Change a field definition. + * + * IMPORTANT NOTE: To maintain database portability, you have to explicitly + * recreate all indices and primary keys that are using the changed field. + * + * That means that you have to drop all affected keys and indexes with + * db_drop_{primary_key,unique_key,index}() before calling db_change_field(). + * To recreate the keys and indices, pass the key definitions as the + * optional $keys_new argument directly to db_change_field(). + * + * For example, suppose you have: + * @code + * $schema['foo'] = array( + * 'fields' => array( + * 'bar' => array('type' => 'int', 'not null' => TRUE) + * ), + * 'primary key' => array('bar') + * ); + * @endcode + * and you want to change foo.bar to be type serial, leaving it as the + * primary key. The correct sequence is: + * @code + * db_drop_primary_key($ret, 'foo'); + * db_change_field($ret, 'foo', 'bar', 'bar', + * array('type' => 'serial', 'not null' => TRUE), + * array('primary key' => array('bar'))); + * @endcode + * + * The reasons for this are due to the different database engines: + * + * On PostgreSQL, changing a field definition involves adding a new field + * and dropping an old one which* causes any indices, primary keys and + * sequences (from serial-type fields) that use the changed field to be dropped. + * + * On MySQL, all type 'serial' fields must be part of at least one key + * or index as soon as they are created. You cannot use + * db_add_{primary_key,unique_key,index}() for this purpose because + * the ALTER TABLE command will fail to add the column without a key + * or index specification. The solution is to use the optional + * $keys_new argument to create the key or index at the same time as + * field. + * + * You could use db_add_{primary_key,unique_key,index}() in all cases + * unless you are converting a field to be type serial. You can use + * the $keys_new argument in all cases. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * Name of the table. + * @param $field + * Name of the field to change. + * @param $field_new + * New name for the field (set to the same as $field if you don't want to change the name). + * @param $spec + * The field specification for the new field. + * @param $keys_new + * Optional keys and indexes specification to be created on the + * table along with changing the field. The format is the same as a + * table specification but without the 'fields' element. + */ + +function db_change_field(&$ret, $table, $field, $field_new, $spec, $keys_new = array()) { + $sql = 'ALTER TABLE [{'. $table .'}] CHANGE '. $field .' '. + _db_create_field_sql($field_new, _db_process_field($spec)); + if (count($keys_new)) { + $sql .= ', ADD '. implode(', ADD ', _db_create_keys($keys_new)); + } + $ret[] = update_sql($sql); +} + +/** + * @} End of "ingroup schemaapi". + */ Index: includes/schema.oracle.inc =================================================================== RCS file: includes/schema.oracle.inc diff -N includes/schema.oracle.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/schema.oracle.inc 16 Jan 2008 15:38:11 -0000 @@ -0,0 +1,551 @@ + 'VARCHAR2', + 'char:normal' => 'CHAR', + + 'text:tiny' => 'VARCHAR2(4000)', + 'text:small' => 'VARCHAR2(4000)', + 'text:medium' => 'VARCHAR2(4000)', + 'text:big' => 'VARCHAR2(4000)', + 'text:normal' => 'VARCHAR2(4000)', + + 'serial:tiny' => 'NUMBER(38)', + 'serial:small' => 'NUMBER(38)', + 'serial:medium' => 'NUMBER(38)', + 'serial:big' => 'NUMBER(38)', + 'serial:normal' => 'NUMBER(38)', + + 'int:tiny' => 'NUMBER(38)', + 'int:small' => 'NUMBER(38)', + 'int:medium' => 'NUMBER(38)', + 'int:big' => 'NUMBER(38)', + 'int:normal' => 'NUMBER(38)', + + 'float:tiny' => 'FLOAT(126)', + 'float:small' => 'FLOAT(126)', + 'float:medium' => 'FLOAT(126)', + 'float:big' => 'FLOAT(126)', + 'float:normal' => 'FLOAT(126)', + + 'numeric:normal' => 'NUMBER', + + 'blob:big' => 'BLOB', + 'blob:normal' => 'BLOB', + + 'clob:big' => 'CLOB', + 'clob:normal' => 'CLOB', + + 'datetime:normal' => 'TIMESTAMP', + ); + return $map; +} + +/** + * Generate SQL to create a new table from a Drupal schema definition. + * + * @param $name + * The name of the table to create. + * @param $table + * A Schema API table definition array. + * @return + * An array of SQL statements to create the table. + */ +function db_create_table_sql($name, $table) { + $sql_fields = array(); + foreach ($table['fields'] as $field_name => $field) { + $spec = _db_process_field($field); + $sql_fields[] = _db_create_field_sql($field_name, $spec); + if ($spec['type'] == 'serial') { + $table['serials'][] = $field_name; + } + } + + $sql_keys = array(); + if (isset($table['primary key']) && is_array($table['primary key'])) { + $sql_keys[] = 'CONSTRAINT [pk_{'. $name .'}] PRIMARY KEY (['. implode('], [', $table['primary key']) .'])'; + } + if (isset($table['unique keys']) && is_array($table['unique keys'])) { + foreach ($table['unique keys'] as $key => $value) { + $sql_keys[] = 'CONSTRAINT [ix_{'. $name .'}_'. $key .'] UNIQUE (['. implode('], [', $value) .'])'; + } + } + + $sql = "CREATE TABLE [{". $name ."}] (\n\t"; + $sql .= implode(",\n\t", $sql_fields); + if (count($sql_keys) > 0) { + $sql .= ",\n\t"; + } + $sql .= implode(",\n\t", $sql_keys); + $sql .= "\n)"; + $statements[] = $sql; + + if (isset($table['indexes']) && is_array($table['indexes'])) { + foreach ($table['indexes'] as $key => $value) { + $statements[] = _db_create_index_sql($name, $key, $value); + } + } + + if (isset($table['serials']) && is_array($table['serials'])) { + foreach ($table['serials'] as $key => $value) { + $statements[] = _db_create_sequence_sql($name, $value); + $statements[] = _db_create_trigger_sql($name, $value); + } + } + + return $statements; +} + +function _db_create_sequence_sql($table, $field) { + $seq = 'seq_{'. $table .'}_'. $field; + return "CREATE SEQUENCE [". $seq ."] MINVALUE 1 INCREMENT BY 1 START WITH 1 NOCACHE NOORDER NOCYCLE"; +} + +function _db_create_trigger_sql($table, $field) { + $tgr = 'tgr_{'. $table .'}_'. $field; + $seq = 'seq_{'. $table .'}_'. $field; + $query = "CREATE OR REPLACE TRIGGER [". $tgr ."]\n"; + $query .= "BEFORE INSERT ON [{". $table ."}]\n"; + $query .= "FOR EACH ROW\n"; + $query .= "BEGIN\n"; + $query .= "\tIF :NEW.[". $field ."] IS NULL THEN\n"; + $query .= "\t\tSELECT [". $seq ."].NEXTVAL\n"; + $query .= "\t\tINTO :NEW.[". $field ."]\n"; + $query .= "\t\tFROM DUAL;\n"; + $query .= "\tEND IF;\n"; + $query .= "END;"; + return $query; +} + +function _db_create_index_sql($table, $name, $fields) { + $ix = 'ix_{'. $table .'}_'. $name; + return 'CREATE INDEX ['. $ix .'] ON [{'. $table .'}] ('. _db_create_key_sql($fields) .')'; +} + +function _db_create_key_sql($fields) { + $ret = array(); + foreach ($fields as $field) { + if (is_array($field)) { + $ret[] = DB_SUBSTR .'(['. $field[0] .'], 1, '. $field[1] .')'; + } + else { + $ret[] = '['. $field .']'; + } + } + return implode(', ', $ret); +} + +function _db_create_keys(&$ret, $table, $key_news) { + if (isset($key_news['primary key'])) { + db_add_primary_key($ret, $table, $key_news['primary key']); + } + if (isset($key_news['unique keys'])) { + foreach ($key_news['unique keys'] as $name => $fields) { + db_add_unique_key($ret, $table, $name, $fields); + } + } + if (isset($key_news['indexes'])) { + foreach ($key_news['indexes'] as $name => $fields) { + db_add_index($ret, $table, $name, $fields); + } + } +} + +/** + * Set database-engine specific properties for a field. + * + * @param $field + * A field description array, as specified in the schema documentation. + */ +function _db_process_field($field) { + if (!isset($field['size'])) { + $field['size'] = 'normal'; + } + + // Set the correct database-engine specific datatype. + if (!isset($field['oracle_type'])) { + $map = db_type_map(); + $field['oracle_type'] = $map[$field['type'] .':'. $field['size']]; + } + + if ($field['type'] == 'serial') { + unset($field['not null']); + } + + return $field; +} + +/** + * Create an SQL string for a field to be used in table creation or alteration. + * + * Before passing a field out of a schema definition into this function it has + * to be processed by _db_process_field(). + * + * @param $name + * Name of the field. + * @param $spec + * The field specification, as per the schema data structure format. + * @param $table + * Name of the table. Useful if required to create sequence and trigger. + * @param $extra_sql + * Array of extra queries. Useful if required to create sequence and trigger. + */ +function _db_create_field_sql($name, $spec) { + $sql = '['. $name .'] '. $spec['oracle_type']; + + if (!empty($spec['length'])) { + $sql .= '('. $spec['length'] .')'; + } + elseif (isset($spec['precision']) && isset($spec['scale'])) { + $sql .= '('. $spec['scale'] .', '. $spec['precision'] .')'; + } + + if (($spec['type'] == 'text') || ($spec['type'] == 'varchar')) { + if (isset($spec['not null']) && (!isset($spec['default']) || $spec['default'] == '')) { + $spec['default'] = ORACLE_EMPTY_STRING_PLACEHOLDER; + } + } + if (isset($spec['default'])) { + switch ($spec['type']) { + case 'blob': + $default = 'EMPTY_BLOB()'; + break; + case 'clob': + $default = 'EMPTY_CLOB()'; + break; + case 'text': + case 'varchar': + $default = "'". $spec['default'] ."'"; + break; + default: + $default = is_string($spec['default']) ? "'". $spec['default'] ."'" : $spec['default']; + } + $sql .= " DEFAULT $default"; + } + + if (isset($spec['not null']) && $spec['not null']) { + $sql .= ' NOT NULL'; + } + + if (!empty($spec['unsigned'])) { + $sql .= ' CHECK (['. $name .'] >= 0)'; + } + + return $sql; +} + +/** + * Rename a table. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be renamed. + * @param $new_name + * The new name for the table. + */ +function db_rename_table(&$ret, $table, $new_name) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] RENAME TO [{'. $new_name .'}]'); +} + +/** + * Drop a table. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be dropped. + */ +function db_drop_table(&$ret, $table) { + $ret[] = update_sql('DROP TABLE [{'. $table .'}] CASCADE CONSTRAINTS'); +} + +/** + * Add a new field to a table. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * Name of the table to be altered. + * @param $field + * Name of the field to be added. + * @param $spec + * The field specification array, as taken from a schema definition. + * The specification may also contain the key 'initial', the newly + * created field will be set to the value of the key in all rows. + * This is most useful for creating NOT NULL columns with no default + * value in existing tables. + * @param $keys_new + * Optional keys and indexes specification to be created on the + * table along with adding the field. The format is the same as a + * table specification but without the 'fields' element. If you are + * adding a type 'serial' field, you MUST specify at least one key + * or index including it in this array. @see db_change_field for more + * explanation why. + */ +function db_add_field(&$ret, $table, $field, $spec, $keys_new = array()) { + $spec = _db_process_field($field); + $queries[] = 'ALTER TABLE [{'. $table .'}] ADD '. _db_create_field_sql($field, $spec); + if ($spec['type'] == 'serial') { + $queries[] = _db_create_sequence_sql($table, $field); + $queries[] = _db_create_trigger_sql($table, $field); + } + foreach ($queries as $query) { + $ret[] = update_sql($query); + } + if (isset($keys_new)) { + _db_create_keys($ret, $table, $keys_new); + } +} + +/** + * Drop a field. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $field + * The field to be dropped. + */ +function db_drop_field(&$ret, $table, $field) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] DROP COLUMN ['. $field .']'); +} + +/** + * Set the default value for a field. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $field + * The field to be altered. + * @param $default + * Default value to be set. NULL for 'default NULL'. + */ +function db_field_set_default(&$ret, $table, $field, $default) { + if ($default == NULL) { + $default = 'NULL'; + } + else { + $default = is_string($default) ? "'$default'" : $default; + } + + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] MODIFY (['. $field .'] DEFAULT '. $default .')'); +} + +/** + * Set a field to have no default value. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $field + * The field to be altered. + */ +function db_field_set_no_default(&$ret, $table, $field) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] MODIFY (['. $field .'] DEFAULT NULL)'); +} + +/** + * Add a primary key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $fields + * Fields for the primary key. + */ +function db_add_primary_key(&$ret, $table, $fields) { + $pk = 'pk_{'. $table .'}'; + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] ADD CONSTRAINT ['. $pk .'] PRIMARY KEY (['. implode('], [', $fields) .'])'); +} + +/** + * Drop the primary key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + */ +function db_drop_primary_key(&$ret, $table) { + $pk = 'pk_{'. $table .'}'; + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] DROP CONSTRAINT ['. $pk .']'); +} + +/** + * Add a unique key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the key. + * @param $fields + * An array of field names. + */ +function db_add_unique_key(&$ret, $table, $name, $fields) { + $ix = 'ix_{'. $table .'}_'. $name; + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] ADD CONSTRAINT ['. $ix .'] UNIQUE (['. implode('], [', $fields) .'])'); +} + +/** + * Drop a unique key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the key. + */ +function db_drop_unique_key(&$ret, $table, $name) { + $ix = 'ix_{'. $table .'}_'. $name; + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] DROP CONSTRAINT ['. $ix .']'); +} + +/** + * Add an index. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the index. + * @param $fields + * An array of field names. + * + * NOTE: Need to do some checking before add index, since + * Oracle don't allow create index on promary key. + */ +function db_add_index(&$ret, $table, $name, $fields) { + if (db_constraint_exists($table, $fields)) { + $ret[] = update_sql(_db_create_index_sql($table, $name, $fields)); + } +} + +/** + * Drop an index. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the index. + */ +function db_drop_index(&$ret, $table, $name) { + $ix = 'ix_{'. $table .'}_'. $name; + $ret[] = update_sql('DROP INDEX ['. $ix .']'); +} + +/** + * Change a field definition. + * + * IMPORTANT NOTE: To maintain database portability, you have to explicitly + * recreate all indices and primary keys that are using the changed field. + * + * That means that you have to drop all affected keys and indexes with + * db_drop_{primary_key,unique_key,index}() before calling db_change_field(). + * To recreate the keys and indices, pass the key definitions as the + * optional $keys_new argument directly to db_change_field(). + * + * For example, suppose you have: + * @code + * $schema['foo'] = array( + * 'fields' => array( + * 'bar' => array('type' => 'int', 'not null' => TRUE) + * ), + * 'primary key' => array('bar') + * ); + * @endcode + * and you want to change foo.bar to be type serial, leaving it as the + * primary key. The correct sequence is: + * @code + * db_drop_primary_key($ret, 'foo'); + * db_change_field($ret, 'foo', 'bar', 'bar', + * array('type' => 'serial', 'not null' => TRUE), + * array('primary key' => array('bar'))); + * @endcode + * + * The reasons for this are due to the different database engines: + * + * On PostgreSQL, changing a field definition involves adding a new field + * and dropping an old one which* causes any indices, primary keys and + * sequences (from serial-type fields) that use the changed field to be dropped. + * + * On MySQL, all type 'serial' fields must be part of at least one key + * or index as soon as they are created. You cannot use + * db_add_{primary_key,unique_key,index}() for this purpose because + * the ALTER TABLE command will fail to add the column without a key + * or index specification. The solution is to use the optional + * $keys_new argument to create the key or index at the same time as + * field. + * + * You could use db_add_{primary_key,unique_key,index}() in all cases + * unless you are converting a field to be type serial. You can use + * the $keys_new argument in all cases. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * Name of the table. + * @param $field + * Name of the field to change. + * @param $field_new + * New name for the field (set to the same as $field if you don't want to change the name). + * @param $spec + * The field specification for the new field. + * @param $key_news + * Optional keys and indexes specification to be created on the + * table along with changing the field. The format is the same as a + * table specification but without the 'fields' element. + */ +function db_change_field(&$ret, $table, $field, $field_new, $spec, $key_news = array()) { + $ret[] = update_sql("ALTER TABLE [{". $table ."}] RENAME $field TO [old_". $field .']'); + $not_null = isset($spec['not null']) ? $spec['not null'] : FALSE; + unset($spec['not null']); + + db_add_field($ret, $table, "$field_new", $spec); + + $ret[] = update_sql("UPDATE [{". $table ."}] SET [$field_new] = [old_". $field .']'); + + if ($not_null) { + $ret[] = update_sql("ALTER TABLE [{". $table ."}] ALTER [$field_new] SET NOT NULL"); + } + + db_drop_field($ret, $table, 'old_'. $field); + + if (isset($key_news)) { + _db_create_keys($ret, $table, $key_news); + } +} + +/** + * @} End of "ingroup schemaapi". + */ Index: includes/schema.postgresql.inc =================================================================== RCS file: includes/schema.postgresql.inc diff -N includes/schema.postgresql.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ includes/schema.postgresql.inc 16 Jan 2008 15:38:11 -0000 @@ -0,0 +1,498 @@ + 'VARCHAR', + 'char:normal' => 'CHARACTER', + + 'text:tiny' => 'TEXT', + 'text:small' => 'TEXT', + 'text:medium' => 'TEXT', + 'text:big' => 'TEXT', + 'text:normal' => 'TEXT', + + 'serial:tiny' => 'SERIAL', + 'serial:small' => 'SERIAL', + 'serial:medium' => 'SERIAL', + 'serial:big' => 'BIGSERIAL', + 'serial:normal' => 'SERIAL', + + 'int:tiny' => 'SMALLINT', + 'int:small' => 'SMALLINT', + 'int:medium' => 'INT', + 'int:big' => 'BIGINT', + 'int:normal' => 'INT', + + 'float:tiny' => 'REAL', + 'float:small' => 'REAL', + 'float:medium' => 'REAL', + 'float:big' => 'DOUBLE PRECISION', + 'float:normal' => 'REAL', + + 'numeric:normal' => 'NUMERIC', + + 'blob:big' => 'BYTEA', + 'blob:normal' => 'BYTEA', + + 'clob:big' => 'TEXT', + 'clob:normal' => 'TEXT', + + 'datetime:normal' => 'TIMESTAMP', + ); + return $map; +} + +/** + * Generate SQL to create a new table from a Drupal schema definition. + * + * @param $name + * The name of the table to create. + * @param $table + * A Schema API table definition array. + * @return + * An array of SQL statements to create the table. + */ +function db_create_table_sql($name, $table) { + $sql_fields = array(); + foreach ($table['fields'] as $field_name => $field) { + $sql_fields[] = _db_create_field_sql($field_name, _db_process_field($field)); + } + + $sql_keys = array(); + if (isset($table['primary key']) && is_array($table['primary key'])) { + $sql_keys[] = 'PRIMARY KEY (['. implode('], [', $table['primary key']) .'])'; + } + if (isset($table['unique keys']) && is_array($table['unique keys'])) { + foreach ($table['unique keys'] as $key_name => $key) { + $sql_keys[] = 'CONSTRAINT [{'. $name .'}_'. $key_name .'_key] UNIQUE (['. implode('], [', $key) .'])'; + } + } + + $sql = "CREATE TABLE [{". $name ."}] (\n\t"; + $sql .= implode(",\n\t", $sql_fields); + if (count($sql_keys) > 0) { + $sql .= ",\n\t"; + } + $sql .= implode(",\n\t", $sql_keys); + $sql .= "\n)"; + $statements[] = $sql; + + if (isset($table['indexes']) && is_array($table['indexes'])) { + foreach ($table['indexes'] as $key_name => $key) { + $statements[] = _db_create_index_sql($name, $key_name, $key); + } + } + + return $statements; +} + +function _db_create_index_sql($table, $name, $fields) { + return 'CREATE INDEX [{'. $table .'}_'. $name .'_idx] ON [{'. $table .'}] ('. _db_create_key_sql($fields) .')'; +} + +function _db_create_key_sql($fields) { + $ret = array(); + foreach ($fields as $field) { + if (is_array($field)) { + $ret[] = DB_SUBSTR .'(['. $field[0] .'], 1, '. $field[1] .')'; + } + else { + $ret[] = '['. $field .']'; + } + } + return implode(', ', $ret); +} + +function _db_create_keys(&$ret, $table, $keys_new) { + if (isset($keys_new['primary key'])) { + db_add_primary_key($ret, $table, $keys_new['primary key']); + } + if (isset($keys_new['unique keys'])) { + foreach ($keys_new['unique keys'] as $name => $fields) { + db_add_unique_key($ret, $table, $name, $fields); + } + } + if (isset($keys_new['indexes'])) { + foreach ($keys_new['indexes'] as $name => $fields) { + db_add_index($ret, $table, $name, $fields); + } + } +} + +/** + * Set database-engine specific properties for a field. + * + * @param $field + * A field description array, as specified in the schema documentation. + */ +function _db_process_field($field) { + if (!isset($field['size'])) { + $field['size'] = 'normal'; + } + // Set the correct database-engine specific datatype. + if (!isset($field['postgresql_type'])) { + $map = db_type_map(); + $field['postgresql_type'] = $map[$field['type'] .':'. $field['size']]; + } + if ($field['type'] == 'serial') { + unset($field['not null']); + } + return $field; +} + +/** + * Create an SQL string for a field to be used in table creation or alteration. + * + * Before passing a field out of a schema definition into this function it has + * to be processed by _db_process_field(). + * + * @param $name + * Name of the field. + * @param $spec + * The field specification, as per the schema data structure format. + */ +function _db_create_field_sql($name, $spec) { + $sql = '['. $name .'] '. $spec['postgresql_type']; + + if ($spec['type'] == 'serial') { + unset($spec['not null']); + } + + if (!empty($spec['unsigned'])) { + $sql .= " CHECK ([$name] >= 0)"; + } + + if (!empty($spec['length'])) { + $sql .= '('. $spec['length'] .')'; + } + elseif (isset($spec['precision']) && isset($spec['scale'])) { + $sql .= '('. $spec['scale'] .', '. $spec['precision'] .')'; + } + + if (isset($spec['not null']) && $spec['not null']) { + $sql .= ' NOT NULL'; + } + + if (isset($spec['default'])) { + $default = is_string($spec['default']) ? "'". $spec['default'] ."'" : $spec['default']; + $sql .= " DEFAULT $default"; + } + + return $sql; +} + +/** + * Rename a table. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be renamed. + * @param $new_name + * The new name for the table. + */ +function db_rename_table(&$ret, $table, $new_name) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] RENAME TO [{'. $new_name .'}]'); +} + +/** + * Drop a table. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be dropped. + */ +function db_drop_table(&$ret, $table) { + $ret[] = update_sql('DROP TABLE [{'. $table .'}]'); +} + +/** + * Add a new field to a table. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * Name of the table to be altered. + * @param $field + * Name of the field to be added. + * @param $spec + * The field specification array, as taken from a schema definition. + * The specification may also contain the key 'initial', the newly + * created field will be set to the value of the key in all rows. + * This is most useful for creating NOT NULL columns with no default + * value in existing tables. + * @param $keys_new + * Optional keys and indexes specification to be created on the + * table along with adding the field. The format is the same as a + * table specification but without the 'fields' element. If you are + * adding a type 'serial' field, you MUST specify at least one key + * or index including it in this array. @see db_change_field for more + * explanation why. + */ +function db_add_field(&$ret, $table, $field, $spec, $keys_new = array()) { + $fixnull = FALSE; + if (!empty($spec['not null']) && !isset($spec['default'])) { + $fixnull = TRUE; + $spec['not null'] = FALSE; + } + $query = 'ALTER TABLE [{'. $table .'}] ADD COLUMN '; + $query .= _db_create_field_sql($field, _db_process_field($spec)); + $ret[] = update_sql($query); + if (isset($spec['initial'])) { + // All this because update_sql does not support %-placeholders. + $sql = 'UPDATE [{'. $table .'}] SET '. $field .' = '. db_type_placeholder($spec['type']); + $result = db_query($sql, $spec['initial']); + $ret[] = array('success' => $result !== FALSE, 'query' => check_plain($sql .' ('. $spec['initial'] .')')); + } + if ($fixnull) { + $ret[] = update_sql("ALTER TABLE [{". $table ."}] ALTER $field SET NOT NULL"); + } + if (isset($keys_new)) { + _db_create_keys($ret, $table, $keys_new); + } +} + +/** + * Drop a field. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $field + * The field to be dropped. + */ +function db_drop_field(&$ret, $table, $field) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] DROP COLUMN ['. $field .']'); +} + +/** + * Set the default value for a field. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $field + * The field to be altered. + * @param $default + * Default value to be set. NULL for 'default NULL'. + */ +function db_field_set_default(&$ret, $table, $field, $default) { + if ($default == NULL) { + $default = 'NULL'; + } + else { + $default = is_string($default) ? "'$default'" : $default; + } + + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] ALTER COLUMN ['. $field .'] SET DEFAULT '. $default); +} + +/** + * Set a field to have no default value. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $field + * The field to be altered. + */ +function db_field_set_no_default(&$ret, $table, $field) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] ALTER COLUMN ['. $field .'] DROP DEFAULT'); +} + +/** + * Add a primary key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $fields + * Fields for the primary key. + */ +function db_add_primary_key(&$ret, $table, $fields) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] ADD PRIMARY KEY (['. implode('], [', $fields) .'])'); +} + +/** + * Drop the primary key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + */ +function db_drop_primary_key(&$ret, $table) { + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] DROP CONSTRAINT [{'. $table .'}_pkey]'); +} + +/** + * Add a unique key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the key. + * @param $fields + * An array of field names. + */ +function db_add_unique_key(&$ret, $table, $name, $fields) { + $name = '{'. $table .'}_'. $name .'_key'; + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] ADD CONSTRAINT ['. $name .'] UNIQUE (['. implode('], [', $fields) .'])'); +} + +/** + * Drop a unique key. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the key. + */ +function db_drop_unique_key(&$ret, $table, $name) { + $name = '{'. $table .'}_'. $name .'_key'; + $ret[] = update_sql('ALTER TABLE [{'. $table .'}] DROP CONSTRAINT ['. $name .']'); +} + +/** + * Add an index. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the index. + * @param $fields + * An array of field names. + */ +function db_add_index(&$ret, $table, $name, $fields) { + $ret[] = update_sql(_db_create_index_sql($table, $name, $fields)); +} + +/** + * Drop an index. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * The table to be altered. + * @param $name + * The name of the index. + */ +function db_drop_index(&$ret, $table, $name) { + $name = '{'. $table .'}_'. $name .'_idx'; + $ret[] = update_sql('DROP INDEX ['. $name .']'); +} + +/** + * Change a field definition. + * + * IMPORTANT NOTE: To maintain database portability, you have to explicitly + * recreate all indices and primary keys that are using the changed field. + * + * That means that you have to drop all affected keys and indexes with + * db_drop_{primary_key,unique_key,index}() before calling db_change_field(). + * To recreate the keys and indices, pass the key definitions as the + * optional $keys_new argument directly to db_change_field(). + * + * For example, suppose you have: + * @code + * $schema['foo'] = array( + * 'fields' => array( + * 'bar' => array('type' => 'int', 'not null' => TRUE) + * ), + * 'primary key' => array('bar') + * ); + * @endcode + * and you want to change foo.bar to be type serial, leaving it as the + * primary key. The correct sequence is: + * @code + * db_drop_primary_key($ret, 'foo'); + * db_change_field($ret, 'foo', 'bar', 'bar', + * array('type' => 'serial', 'not null' => TRUE), + * array('primary key' => array('bar'))); + * @endcode + * + * The reasons for this are due to the different database engines: + * + * On PostgreSQL, changing a field definition involves adding a new field + * and dropping an old one which* causes any indices, primary keys and + * sequences (from serial-type fields) that use the changed field to be dropped. + * + * On MySQL, all type 'serial' fields must be part of at least one key + * or index as soon as they are created. You cannot use + * db_add_{primary_key,unique_key,index}() for this purpose because + * the ALTER TABLE command will fail to add the column without a key + * or index specification. The solution is to use the optional + * $keys_new argument to create the key or index at the same time as + * field. + * + * You could use db_add_{primary_key,unique_key,index}() in all cases + * unless you are converting a field to be type serial. You can use + * the $keys_new argument in all cases. + * + * @param $ret + * Array to which query results will be added. + * @param $table + * Name of the table. + * @param $field + * Name of the field to change. + * @param $field_new + * New name for the field (set to the same as $field if you don't want to change the name). + * @param $spec + * The field specification for the new field. + * @param $keys_new + * Optional keys and indexes specification to be created on the + * table along with changing the field. The format is the same as a + * table specification but without the 'fields' element. + */ +function db_change_field(&$ret, $table, $field, $field_new, $spec, $keys_new = array()) { + $ret[] = update_sql("ALTER TABLE [{". $table ."}] RENAME [$field] TO [". $field ."_old]"); + $not_null = isset($spec['not null']) ? $spec['not null'] : FALSE; + unset($spec['not null']); + + db_add_field($ret, $table, "$field_new", $spec); + + $ret[] = update_sql("UPDATE [{". $table ."}] SET [$field_new] = [". $field ."_old]"); + + if ($not_null) { + $ret[] = update_sql("ALTER TABLE [{". $table ."}] ALTER [$field_new] SET NOT NULL"); + } + + db_drop_field($ret, $table, $field .'_old'); + + if (isset($keys_new)) { + _db_create_keys($ret, $table, $keys_new); + } +} + +/** + * @} End of "ingroup schemaapi". + */ Index: includes/session.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/session.inc,v retrieving revision 1.44 diff -u -p -r1.44 session.inc --- includes/session.inc 22 Dec 2007 23:24:24 -0000 1.44 +++ includes/session.inc 16 Jan 2008 15:38:11 -0000 @@ -29,7 +29,7 @@ function sess_read($key) { } // Otherwise, if the session is still active, we have a record of the client's session in the database. - $user = db_fetch_object(db_query("SELECT u.*, s.* FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.sid = '%s'", $key)); + $user = db_fetch_object(db_query("SELECT u.*, s.* FROM [{users}] u INNER JOIN [{sessions}] s ON u.[uid] = s.[uid] WHERE s.[sid] = %s", $key)); // We found the client's session record and they are an authenticated user if ($user && $user->uid > 0) { @@ -39,7 +39,7 @@ function sess_read($key) { // Add roles element to $user $user->roles = array(); $user->roles[DRUPAL_AUTHENTICATED_RID] = 'authenticated user'; - $result = db_query("SELECT r.rid, r.name FROM {role} r INNER JOIN {users_roles} ur ON ur.rid = r.rid WHERE ur.uid = %d", $user->uid); + $result = db_query("SELECT r.[rid], r.[name] FROM [{role}] r INNER JOIN [{users_roles}] ur ON ur.[rid] = r.[rid] WHERE ur.[uid] = %d", $user->uid); while ($role = db_fetch_object($result)) { $user->roles[$role->rid] = $role->name; } @@ -62,7 +62,7 @@ function sess_write($key, $value) { return TRUE; } - $result = db_result(db_query("SELECT COUNT(*) FROM {sessions} WHERE sid = '%s'", $key)); + $result = db_result(db_query("SELECT COUNT(*) FROM [{sessions}] WHERE [sid] = %s", $key)); if (!$result) { // Only save session data when when the browser sends a cookie. This keeps @@ -70,16 +70,16 @@ function sess_write($key, $value) { // and gives more useful statistics. We can't eliminate anonymous session // table rows without breaking throttle module and "Who's Online" block. if ($user->uid || $value || count($_COOKIE)) { - db_query("INSERT INTO {sessions} (sid, uid, cache, hostname, session, timestamp) VALUES ('%s', %d, %d, '%s', '%s', %d)", $key, $user->uid, isset($user->cache) ? $user->cache : '', ip_address(), $value, time()); + db_query("INSERT INTO [{sessions}] ([sid], [uid], [cache], [hostname], [session], [timestamp]) VALUES (%s, %d, %d, %s, %s, %d)", $key, $user->uid, isset($user->cache) ? $user->cache : '', ip_address(), $value, time()); } } else { - db_query("UPDATE {sessions} SET uid = %d, cache = %d, hostname = '%s', session = '%s', timestamp = %d WHERE sid = '%s'", $user->uid, isset($user->cache) ? $user->cache : '', ip_address(), $value, time(), $key); + db_query("UPDATE [{sessions}] SET [uid] = %d, [cache] = %d, [hostname] = %s, [session] = %s, [timestamp] = %d WHERE [sid] = %s", $user->uid, isset($user->cache) ? $user->cache : '', ip_address(), $value, time(), $key); // Last access time is updated no more frequently than once every 180 seconds. // This reduces contention in the users table. if ($user->uid && time() - $user->access > variable_get('session_write_interval', 180)) { - db_query("UPDATE {users} SET access = %d WHERE uid = %d", time(), $user->uid); + db_query("UPDATE [{users}] SET [access] = %d WHERE [uid] = %d", time(), $user->uid); } } @@ -103,7 +103,7 @@ function sess_regenerate() { session_regenerate_id(); - db_query("UPDATE {sessions} SET sid = '%s' WHERE sid = '%s'", session_id(), $old_session_id); + db_query("UPDATE [{sessions}] SET [sid] = %s WHERE [sid] = %s", session_id(), $old_session_id); } /** @@ -120,8 +120,8 @@ function sess_regenerate() { * The number of users with sessions. */ function sess_count($timestamp = 0, $anonymous = true) { - $query = $anonymous ? ' AND uid = 0' : ' AND uid > 0'; - return db_result(db_query('SELECT COUNT(sid) AS count FROM {sessions} WHERE timestamp >= %d'. $query, $timestamp)); + $query = $anonymous ? ' AND [uid] = 0' : ' AND [uid] > 0'; + return db_result(db_query('SELECT COUNT([sid]) AS [count] FROM [{sessions}] WHERE [timestamp] >= %d'. $query, $timestamp)); } /** @@ -131,7 +131,7 @@ function sess_count($timestamp = 0, $ano * the session id */ function sess_destroy_sid($sid) { - db_query("DELETE FROM {sessions} WHERE sid = '%s'", $sid); + db_query("DELETE FROM [{sessions}] WHERE [sid] = %s", $sid); } /** @@ -141,7 +141,7 @@ function sess_destroy_sid($sid) { * the user id */ function sess_destroy_uid($uid) { - db_query('DELETE FROM {sessions} WHERE uid = %d', $uid); + db_query('DELETE FROM [{sessions}] WHERE [uid] = %d', $uid); } function sess_gc($lifetime) { @@ -150,7 +150,7 @@ function sess_gc($lifetime) { // for three weeks before deleting them, you need to set gc_maxlifetime // to '1814400'. At that value, only after a user doesn't log in after // three weeks (1814400 seconds) will his/her session be removed. - db_query("DELETE FROM {sessions} WHERE timestamp < %d", time() - $lifetime); + db_query("DELETE FROM [{sessions}] WHERE [timestamp] < %d", time() - $lifetime); return TRUE; } Index: includes/tablesort.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/tablesort.inc,v retrieving revision 1.47 diff -u -p -r1.47 tablesort.inc --- includes/tablesort.inc 4 Jan 2008 09:31:48 -0000 1.47 +++ includes/tablesort.inc 16 Jan 2008 15:38:11 -0000 @@ -40,7 +40,7 @@ function tablesort_sql($header, $before $ts = tablesort_init($header); if ($ts['sql']) { // Based on code from db_escape_table(), but this can also contain a dot. - $field = preg_replace('/[^A-Za-z0-9_.]+/', '', $ts['sql']); + $field = preg_replace('/[^A-Za-z0-9_.\[\]]+/', '', $ts['sql']); // Sort order can only be ASC or DESC. $sort = drupal_strtoupper($ts['sort']); Index: includes/theme.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/theme.inc,v retrieving revision 1.409 diff -u -p -r1.409 theme.inc --- includes/theme.inc 9 Jan 2008 22:01:29 -0000 1.409 +++ includes/theme.inc 16 Jan 2008 15:38:11 -0000 @@ -418,7 +418,7 @@ function list_themes($refresh = FALSE) { // Extract from the database only when it is available. // Also check that the site is not in the middle of an install or update. if (db_is_active() && !defined('MAINTENANCE_MODE')) { - $result = db_query("SELECT * FROM {system} WHERE type = '%s'", 'theme'); + $result = db_query("SELECT * FROM [{system}] WHERE [type] = %s", 'theme'); while ($theme = db_fetch_object($result)) { if (file_exists($theme->filename)) { $theme->info = unserialize($theme->info); Index: modules/aggregator/aggregator.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.admin.inc,v retrieving revision 1.7 diff -u -p -r1.7 aggregator.admin.inc --- modules/aggregator/aggregator.admin.inc 10 Jan 2008 22:47:17 -0000 1.7 +++ modules/aggregator/aggregator.admin.inc 16 Jan 2008 15:38:11 -0000 @@ -20,7 +20,7 @@ function aggregator_admin_overview() { * The page HTML. */ function aggregator_view() { - $result = db_query('SELECT f.*, COUNT(i.iid) AS items FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.fid = i.fid GROUP BY f.fid, f.title, f.url, f.refresh, f.checked, f.link, f.description, f.etag, f.modified, f.image, f.block ORDER BY f.title'); + $result = db_query('SELECT f.*, COUNT(i.[iid]) AS [items] FROM [{aggregator_feed}] f LEFT JOIN [{aggregator_item}] i ON f.[fid] = i.[fid] GROUP BY f.[fid], f.[title], f.[url], f.[refresh], f.[checked], f.[link], f.[description], f.[etag], f.[modified], f.[image], f.[block] ORDER BY f.[title]'); $output = '

    '. t('Feed overview') .'

    '; @@ -31,7 +31,7 @@ function aggregator_view() { } $output .= theme('table', $header, $rows); - $result = db_query('SELECT c.cid, c.title, count(ci.iid) as items FROM {aggregator_category} c LEFT JOIN {aggregator_category_item} ci ON c.cid = ci.cid GROUP BY c.cid, c.title ORDER BY title'); + $result = db_query('SELECT c.[cid], c.[title], COUNT(ci.[iid]) AS [items] FROM [{aggregator_category}] c LEFT JOIN [{aggregator_category_item}] ci ON c.[cid] = ci.[cid] GROUP BY c.[cid], c.[title] ORDER BY [title]'); $output .= '

    '. t('Category overview') .'

    '; @@ -83,7 +83,7 @@ function aggregator_form_feed(&$form_sta // Handling of categories: $options = array(); $values = array(); - $categories = db_query('SELECT c.cid, c.title, f.fid FROM {aggregator_category} c LEFT JOIN {aggregator_category_feed} f ON c.cid = f.cid AND f.fid = %d ORDER BY title', $edit['fid']); + $categories = db_query('SELECT c.[cid], c.[title], f.[fid] FROM [{aggregator_category}] c LEFT JOIN [{aggregator_category_feed}] f ON c.[cid] = f.[cid] AND f.[fid] = %d ORDER BY [title]', $edit['fid']); while ($category = db_fetch_object($categories)) { $options[$category->cid] = check_plain($category->title); if ($category->fid) $values[] = $category->cid; @@ -117,10 +117,10 @@ function aggregator_form_feed_validate($ } // Check for duplicate titles. if (isset($form_state['values']['fid'])) { - $result = db_query("SELECT title, url FROM {aggregator_feed} WHERE (title = '%s' OR url='%s') AND fid != %d", $form_state['values']['title'], $form_state['values']['url'], $form_state['values']['fid']); + $result = db_query("SELECT [title], [url] FROM [{aggregator_feed}] WHERE ([title] = %s OR [url] = %s) AND [fid] != %d", $form_state['values']['title'], $form_state['values']['url'], $form_state['values']['fid']); } else { - $result = db_query("SELECT title, url FROM {aggregator_feed} WHERE title = '%s' OR url='%s'", $form_state['values']['title'], $form_state['values']['url']); + $result = db_query("SELECT [title], [url] FROM [{aggregator_feed}] WHERE [title] = %s OR [url] = %s", $form_state['values']['title'], $form_state['values']['url']); } while ($feed = db_fetch_object($result)) { if (strcasecmp($feed->title, $form_state['values']['title']) == 0) { @@ -286,10 +286,10 @@ function aggregator_form_category_valida if ($form_state['values']['op'] == t('Save')) { // Check for duplicate titles if (isset($form_state['values']['cid'])) { - $category = db_fetch_object(db_query("SELECT cid FROM {aggregator_category} WHERE title = '%s' AND cid != %d", $form_state['values']['title'], $form_state['values']['cid'])); + $category = db_fetch_object(db_query("SELECT [cid] FROM [{aggregator_category}] WHERE [title] = %s AND [cid] != %d", $form_state['values']['title'], $form_state['values']['cid'])); } else { - $category = db_fetch_object(db_query("SELECT cid FROM {aggregator_category} WHERE title = '%s'", $form_state['values']['title'])); + $category = db_fetch_object(db_query("SELECT [cid] FROM [{aggregator_category}] WHERE [title] = %s", $form_state['values']['title'])); } if ($category) { form_set_error('title', t('A category named %category already exists. Please enter a unique title.', array('%category' => $form_state['values']['title']))); Index: modules/aggregator/aggregator.install =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.install,v retrieving revision 1.14 diff -u -p -r1.14 aggregator.install --- modules/aggregator/aggregator.install 18 Dec 2007 12:59:20 -0000 1.14 +++ modules/aggregator/aggregator.install 16 Jan 2008 15:38:11 -0000 @@ -44,6 +44,7 @@ function aggregator_schema() { 'description' => array( 'type' => 'text', 'not null' => TRUE, + 'default' => '', 'size' => 'big', 'description' => t('Description of the category'), ), @@ -143,12 +144,14 @@ function aggregator_schema() { 'description' => array( 'type' => 'text', 'not null' => TRUE, + 'default' => '', 'size' => 'big', 'description' => t("The parent website's description; comes from the element in the feed."), ), 'image' => array( 'type' => 'text', 'not null' => TRUE, + 'default' => '', 'size' => 'big', 'description' => t('An image representing the feed.'), ), @@ -216,8 +219,9 @@ function aggregator_schema() { 'description' => t('Author of the feed item.'), ), 'description' => array( - 'type' => 'text', + 'type' => 'clob', 'not null' => TRUE, + 'default' => '', 'size' => 'big', 'description' => t('Body of the feed item.'), ), Index: modules/aggregator/aggregator.module =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v retrieving revision 1.373 diff -u -p -r1.373 aggregator.module --- modules/aggregator/aggregator.module 10 Jan 2008 22:47:17 -0000 1.373 +++ modules/aggregator/aggregator.module 16 Jan 2008 15:38:11 -0000 @@ -270,7 +270,7 @@ function aggregator_init() { * TRUE if there is at least one category and the user has access to them, FALSE otherwise. */ function _aggregator_has_categories() { - return user_access('access news feeds') && db_result(db_query('SELECT COUNT(*) FROM {aggregator_category}')); + return user_access('access news feeds') && db_result(db_query('SELECT COUNT(*) FROM [{aggregator_category}]')); } /** @@ -286,7 +286,7 @@ function aggregator_perm() { * Checks news feeds for updates once their refresh interval has elapsed. */ function aggregator_cron() { - $result = db_query('SELECT * FROM {aggregator_feed} WHERE checked + refresh < %d', time()); + $result = db_query('SELECT * FROM [{aggregator_feed}] WHERE [checked] + [refresh] < %d', time()); while ($feed = db_fetch_array($result)) { aggregator_refresh($feed); } @@ -300,11 +300,11 @@ function aggregator_cron() { function aggregator_block($op = 'list', $delta = 0, $edit = array()) { if (user_access('access news feeds')) { if ($op == 'list') { - $result = db_query('SELECT cid, title FROM {aggregator_category} ORDER BY title'); + $result = db_query('SELECT [cid], [title] FROM [{aggregator_category}] ORDER BY [title]'); while ($category = db_fetch_object($result)) { $block['category-'. $category->cid]['info'] = t('!title category latest items', array('!title' => $category->title)); } - $result = db_query('SELECT fid, title FROM {aggregator_feed} ORDER BY fid'); + $result = db_query('SELECT [fid], [title] FROM [{aggregator_feed}] ORDER BY [fid]'); while ($feed = db_fetch_object($result)) { $block['feed-'. $feed->fid]['info'] = t('!title feed latest items', array('!title' => $feed->title)); } @@ -312,10 +312,10 @@ function aggregator_block($op = 'list', else if ($op == 'configure') { list($type, $id) = explode('-', $delta); if ($type == 'category') { - $value = db_result(db_query('SELECT block FROM {aggregator_category} WHERE cid = %d', $id)); + $value = db_result(db_query('SELECT [block] FROM [{aggregator_category}] WHERE [cid] = %d', $id)); } else { - $value = db_result(db_query('SELECT block FROM {aggregator_feed} WHERE fid = %d', $id)); + $value = db_result(db_query('SELECT [block] FROM [{aggregator_feed}] WHERE [fid] = %d', $id)); } $form['block'] = array('#type' => 'select', '#title' => t('Number of news items in block'), '#default_value' => $value, '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20))); return $form; @@ -323,27 +323,27 @@ function aggregator_block($op = 'list', else if ($op == 'save') { list($type, $id) = explode('-', $delta); if ($type == 'category') { - $value = db_query('UPDATE {aggregator_category} SET block = %d WHERE cid = %d', $edit['block'], $id); + $value = db_query('UPDATE [{aggregator_category}] SET [block] = %d WHERE [cid] = %d', $edit['block'], $id); } else { - $value = db_query('UPDATE {aggregator_feed} SET block = %d WHERE fid = %d', $edit['block'], $id); + $value = db_query('UPDATE [{aggregator_feed}] SET [block] = %d WHERE [fid] = %d', $edit['block'], $id); } } else if ($op == 'view') { list($type, $id) = explode('-', $delta); switch ($type) { case 'feed': - if ($feed = db_fetch_object(db_query('SELECT fid, title, block FROM {aggregator_feed} WHERE fid = %d', $id))) { + if ($feed = db_fetch_object(db_query('SELECT [fid], [title], [block] FROM [{aggregator_feed}] WHERE [fid] = %d', $id))) { $block['subject'] = check_plain($feed->title); - $result = db_query_range('SELECT * FROM {aggregator_item} WHERE fid = %d ORDER BY timestamp DESC, iid DESC', $feed->fid, 0, $feed->block); + $result = db_query_range('SELECT * FROM [{aggregator_item}] WHERE [fid] = %d ORDER BY [timestamp] DESC, [iid] DESC', $feed->fid, 0, $feed->block); $read_more = theme('more_link', url('aggregator/sources/'. $feed->fid), t("View this feed's recent news.")); } break; case 'category': - if ($category = db_fetch_object(db_query('SELECT cid, title, block FROM {aggregator_category} WHERE cid = %d', $id))) { + if ($category = db_fetch_object(db_query('SELECT [cid], [title], [block] FROM [{aggregator_category}] WHERE [cid] = %d', $id))) { $block['subject'] = check_plain($category->title); - $result = db_query_range('SELECT i.* FROM {aggregator_category_item} ci LEFT JOIN {aggregator_item} i ON ci.iid = i.iid WHERE ci.cid = %d ORDER BY i.timestamp DESC, i.iid DESC', $category->cid, 0, $category->block); + $result = db_query_range('SELECT i.* FROM [{aggregator_category_item}] ci LEFT JOIN [{aggregator_item}] i ON ci.[iid] = i.[iid] WHERE ci.[cid] = %d ORDER BY i.[timestamp] DESC, i.[iid] DESC', $category->cid, 0, $category->block); $read_more = theme('more_link', url('aggregator/categories/'. $category->cid), t("View this category's recent news.")); } break; @@ -375,18 +375,18 @@ function aggregator_save_category($edit) if (!empty($edit['cid'])) { $link_path .= $edit['cid']; if (!empty($edit['title'])) { - db_query("UPDATE {aggregator_category} SET title = '%s', description = '%s' WHERE cid = %d", $edit['title'], $edit['description'], $edit['cid']); + db_query("UPDATE [{aggregator_category}] SET [title] = %s, [description] = %s WHERE [cid] = %d", $edit['title'], $edit['description'], $edit['cid']); $op = 'update'; } else { - db_query('DELETE FROM {aggregator_category} WHERE cid = %d', $edit['cid']); + db_query('DELETE FROM [{aggregator_category}] WHERE [cid] = %d', $edit['cid']); $edit['title'] = ''; $op = 'delete'; } } else if (!empty($edit['title'])) { // A single unique id for bundles and feeds, to use in blocks - db_query("INSERT INTO {aggregator_category} (title, description, block) VALUES ('%s', '%s', 5)", $edit['title'], $edit['description']); + db_query("INSERT INTO [{aggregator_category}] ([title], [description], [block]) VALUES (%s, %s, %d)", $edit['title'], $edit['description'], 5); $link_path .= db_last_insert_id('aggregator', 'cid'); $op = 'insert'; } @@ -404,25 +404,25 @@ function aggregator_save_category($edit) function aggregator_save_feed($edit) { if (!empty($edit['fid'])) { // An existing feed is being modified, delete the category listings. - db_query('DELETE FROM {aggregator_category_feed} WHERE fid = %d', $edit['fid']); + db_query('DELETE FROM [{aggregator_category_feed}] WHERE [fid] = %d', $edit['fid']); } if (!empty($edit['fid']) && !empty($edit['title'])) { - db_query("UPDATE {aggregator_feed} SET title = '%s', url = '%s', refresh = %d WHERE fid = %d", $edit['title'], $edit['url'], $edit['refresh'], $edit['fid']); + db_query("UPDATE [{aggregator_feed}] SET [title] = %s, [url] = %s, [refresh] = %d WHERE [fid] = %d", $edit['title'], $edit['url'], $edit['refresh'], $edit['fid']); } else if (!empty($edit['fid'])) { $items = array(); - $result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = %d', $edit['fid']); + $result = db_query('SELECT [iid] FROM [{aggregator_item}] WHERE [fid] = %d', $edit['fid']); while ($item = db_fetch_object($result)) { - $items[] = "iid = $item->iid"; + $items[] = "[iid] = $item->iid"; } if (!empty($items)) { - db_query('DELETE FROM {aggregator_category_item} WHERE '. implode(' OR ', $items)); + db_query('DELETE FROM [{aggregator_category_item}] WHERE '. implode(' OR ', $items)); } - db_query('DELETE FROM {aggregator_feed} WHERE fid = %d', $edit['fid']); - db_query('DELETE FROM {aggregator_item} WHERE fid = %d', $edit['fid']); + db_query('DELETE FROM [{aggregator_feed}] WHERE [fid] = %d', $edit['fid']); + db_query('DELETE FROM [{aggregator_item}] WHERE [fid] = %d', $edit['fid']); } else if (!empty($edit['title'])) { - db_query("INSERT INTO {aggregator_feed} (title, url, refresh, block, description, image) VALUES ('%s', '%s', %d, 5, '', '')", $edit['title'], $edit['url'], $edit['refresh']); + db_query("INSERT INTO [{aggregator_feed}] ([title], [url], [refresh], [block], [description], [image]) VALUES (%s, %s, %d, %d, %s, %s)", $edit['title'], $edit['url'], $edit['refresh'], 5, '', ''); // A single unique id for bundles and feeds, to use in blocks. $edit['fid'] = db_last_insert_id('aggregator_feed', 'fid'); } @@ -431,7 +431,7 @@ function aggregator_save_feed($edit) { if (!empty($edit['category'])) { foreach ($edit['category'] as $cid => $value) { if ($value) { - db_query('INSERT INTO {aggregator_category_feed} (fid, cid) VALUES (%d, %d)', $edit['fid'], $cid); + db_query('INSERT INTO [{aggregator_category_feed}] ([fid], [cid]) VALUES (%d, %d)', $edit['fid'], $cid); } } } @@ -445,15 +445,15 @@ function aggregator_save_feed($edit) { * An associative array describing the feed to be cleared. */ function aggregator_remove($feed) { - $result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = %d', $feed['fid']); + $result = db_query('SELECT [iid] FROM [{aggregator_item}] WHERE [fid] = %d', $feed['fid']); while ($item = db_fetch_object($result)) { - $items[] = "iid = $item->iid"; + $items[] = "[iid] = $item->iid"; } if (!empty($items)) { - db_query('DELETE FROM {aggregator_category_item} WHERE '. implode(' OR ', $items)); + db_query('DELETE FROM [{aggregator_category_item}] WHERE '. implode(' OR ', $items)); } - db_query('DELETE FROM {aggregator_item} WHERE fid = %d', $feed['fid']); - db_query("UPDATE {aggregator_feed} SET checked = 0, etag = '', modified = 0 WHERE fid = %d", $feed['fid']); + db_query('DELETE FROM [{aggregator_item}] WHERE [fid] = %d', $feed['fid']); + db_query("UPDATE [{aggregator_feed}] SET [checked] = %d, [etag] = %s, [modified] = %d WHERE [fid] = %d", 0, '', 0, $feed['fid']); drupal_set_message(t('The news items from %site have been removed.', array('%site' => $feed['title']))); } @@ -594,7 +594,7 @@ function aggregator_refresh($feed) { // Process HTTP response code. switch ($result->code) { case 304: - db_query('UPDATE {aggregator_feed} SET checked = %d WHERE fid = %d', time(), $feed['fid']); + db_query('UPDATE [{aggregator_feed}] SET [checked] = %d WHERE [fid] = %d', time(), $feed['fid']); drupal_set_message(t('There is no new syndicated content from %site.', array('%site' => $feed['title']))); break; case 301: @@ -628,7 +628,7 @@ function aggregator_refresh($feed) { $etag = empty($result->headers['ETag']) ? '' : $result->headers['ETag']; // Update the feed data. - db_query("UPDATE {aggregator_feed} SET url = '%s', checked = %d, link = '%s', description = '%s', image = '%s', etag = '%s', modified = %d WHERE fid = %d", $feed['url'], time(), $channel['LINK'], $channel['DESCRIPTION'], $image, $etag, $modified, $feed['fid']); + db_query("UPDATE [{aggregator_feed}] SET [url] = %s, [checked] = %d, [link] = %s, [description] = %s, [image] = %s, [etag] = %s, [modified] = %d WHERE [fid] = %d", $feed['url'], time(), $channel['LINK'], $channel['DESCRIPTION'], $image, $etag, $modified, $feed['fid']); // Clear the cache. cache_clear_all(); @@ -785,13 +785,13 @@ function aggregator_parse_feed(&$data, $ // we find a duplicate entry, we resolve it and pass along its ID is such // that we can update it if needed. if (!empty($guid)) { - $entry = db_fetch_object(db_query("SELECT iid FROM {aggregator_item} WHERE fid = %d AND guid = '%s'", $feed['fid'], $guid)); + $entry = db_fetch_object(db_query("SELECT [iid] FROM [{aggregator_item}] WHERE [fid] = %d AND [guid] = %s", $feed['fid'], $guid)); } else if ($link && $link != $feed['link'] && $link != $feed['url']) { - $entry = db_fetch_object(db_query("SELECT iid FROM {aggregator_item} WHERE fid = %d AND link = '%s'", $feed['fid'], $link)); + $entry = db_fetch_object(db_query("SELECT [iid] FROM [{aggregator_item}] WHERE [fid] = %d AND [link] = %s", $feed['fid'], $link)); } else { - $entry = db_fetch_object(db_query("SELECT iid FROM {aggregator_item} WHERE fid = %d AND title = '%s'", $feed['fid'], $title)); + $entry = db_fetch_object(db_query("SELECT [iid] FROM [{aggregator_item}] WHERE [fid] = %d AND [title] = %s", $feed['fid'], $title)); } $item += array('AUTHOR' => '', 'DESCRIPTION' => ''); aggregator_save_item(array('iid' => (isset($entry->iid) ? $entry->iid: ''), 'fid' => $feed['fid'], 'timestamp' => $timestamp, 'title' => $title, 'link' => $link, 'author' => $item['AUTHOR'], 'description' => $item['DESCRIPTION'], 'guid' => $guid)); @@ -799,7 +799,7 @@ function aggregator_parse_feed(&$data, $ // Remove all items that are older than flush item timer. $age = time() - variable_get('aggregator_clear', 9676800); - $result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = %d AND timestamp < %d', $feed['fid'], $age); + $result = db_query('SELECT [iid] FROM [{aggregator_item}] WHERE [fid] = %d AND [timestamp] < %d', $feed['fid'], $age); $items = array(); $num_rows = FALSE; @@ -808,8 +808,8 @@ function aggregator_parse_feed(&$data, $ $num_rows = TRUE; } if ($num_rows) { - db_query('DELETE FROM {aggregator_category_item} WHERE iid IN ('. implode(', ', $items) .')'); - db_query('DELETE FROM {aggregator_item} WHERE fid = %d AND timestamp < %d', $feed['fid'], $age); + db_query('DELETE FROM [{aggregator_category_item}] WHERE [iid] IN ('. implode(', ', $items) .')'); + db_query('DELETE FROM [{aggregator_item}] WHERE [fid] = %d AND [timestamp] < %d', $feed['fid'], $age); } return 1; @@ -823,19 +823,18 @@ function aggregator_parse_feed(&$data, $ */ function aggregator_save_item($edit) { if ($edit['iid'] && $edit['title']) { - db_query("UPDATE {aggregator_item} SET title = '%s', link = '%s', author = '%s', description = '%s', guid = '%s', timestamp = %d WHERE iid = %d", $edit['title'], $edit['link'], $edit['author'], $edit['description'], $edit['guid'], $edit['timestamp'], $edit['iid']); + drupal_write_record("aggregator_item", $edit, 'iid'); } else if ($edit['iid']) { - db_query('DELETE FROM {aggregator_item} WHERE iid = %d', $edit['iid']); - db_query('DELETE FROM {aggregator_category_item} WHERE iid = %d', $edit['iid']); + db_query('DELETE FROM [{aggregator_item}] WHERE [iid] = %d', $edit['iid']); + db_query('DELETE FROM [{aggregator_category_item}] WHERE [iid] = %d', $edit['iid']); } else if ($edit['title'] && $edit['link']) { - db_query("INSERT INTO {aggregator_item} (fid, title, link, author, description, timestamp, guid) VALUES (%d, '%s', '%s', '%s', '%s', %d, '%s')", $edit['fid'], $edit['title'], $edit['link'], $edit['author'], $edit['description'], $edit['timestamp'], $edit['guid']); - $edit['iid'] = db_last_insert_id('aggregator_item', 'iid'); + drupal_write_record("aggregator_item", $edit); // file the items in the categories indicated by the feed - $categories = db_query('SELECT cid FROM {aggregator_category_feed} WHERE fid = %d', $edit['fid']); + $categories = db_query('SELECT [cid] FROM [{aggregator_category_feed}] WHERE [fid] = %d', $edit['fid']); while ($category = db_fetch_object($categories)) { - db_query('INSERT INTO {aggregator_category_item} (cid, iid) VALUES (%d, %d)', $category->cid, $edit['iid']); + db_query('INSERT INTO [{aggregator_category_item}] ([cid], [iid]) VALUES (%d, %d)', $category->cid, $edit['iid']); } } } @@ -851,7 +850,7 @@ function aggregator_save_item($edit) { function aggregator_feed_load($fid) { static $feeds; if (!isset($feeds[$fid])) { - $feeds[$fid] = db_fetch_array(db_query('SELECT * FROM {aggregator_feed} WHERE fid = %d', $fid)); + $feeds[$fid] = db_fetch_array(db_query('SELECT * FROM [{aggregator_feed}] WHERE [fid] = %d', $fid)); } return $feeds[$fid]; } @@ -867,7 +866,7 @@ function aggregator_feed_load($fid) { function aggregator_category_load($cid) { static $categories; if (!isset($categories[$cid])) { - $categories[$cid] = db_fetch_array(db_query('SELECT * FROM {aggregator_category} WHERE cid = %d', $cid)); + $categories[$cid] = db_fetch_array(db_query('SELECT * FROM [{aggregator_category}] WHERE [cid] = %d', $cid)); } return $categories[$cid]; } Index: modules/aggregator/aggregator.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.pages.inc,v retrieving revision 1.12 diff -u -p -r1.12 aggregator.pages.inc --- modules/aggregator/aggregator.pages.inc 8 Jan 2008 10:35:40 -0000 1.12 +++ modules/aggregator/aggregator.pages.inc 16 Jan 2008 15:38:11 -0000 @@ -15,7 +15,7 @@ function aggregator_page_last() { drupal_add_feed(url('aggregator/rss'), variable_get('site_name', 'Drupal') .' '. t('aggregator')); - $items = aggregator_feed_items_load('SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_item} i INNER JOIN {aggregator_feed} f ON i.fid = f.fid ORDER BY i.timestamp DESC, i.iid DESC'); + $items = aggregator_feed_items_load('SELECT i.*, f.[title] AS [ftitle], f.[link] AS [flink] FROM [{aggregator_item}] i INNER JOIN [{aggregator_feed}] f ON i.[fid] = f.[fid] ORDER BY i.[timestamp] DESC, i.[iid] DESC'); return _aggregator_page_list($items, arg(1)); } @@ -42,7 +42,7 @@ function aggregator_page_source($arg1, $ // It is safe to include the fid in the query because it's loaded from the // database by aggregator_feed_load. - $items = aggregator_feed_items_load('SELECT * FROM {aggregator_item} WHERE fid = '. $feed->fid .' ORDER BY timestamp DESC, iid DESC'); + $items = aggregator_feed_items_load('SELECT * FROM [{aggregator_item}] WHERE [fid] = '. $feed->fid .' ORDER BY [timestamp] DESC, [iid] DESC'); return _aggregator_page_list($items, arg(3), $feed_source); } @@ -69,7 +69,7 @@ function aggregator_page_category($arg1, // It is safe to include the cid in the query because it's loaded from the // database by aggregator_category_load. - $items = aggregator_feed_items_load('SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_category_item} c LEFT JOIN {aggregator_item} i ON c.iid = i.iid LEFT JOIN {aggregator_feed} f ON i.fid = f.fid WHERE cid = '. $category['cid'] .' ORDER BY timestamp DESC, i.iid DESC'); + $items = aggregator_feed_items_load('SELECT i.*, f.[title] AS [ftitle], f.[link] AS [flink] FROM [{aggregator_category_item}] c LEFT JOIN [{aggregator_item}] i ON c.[iid] = i.[iid] LEFT JOIN [{aggregator_feed}] f ON i.[fid] = f.[fid] WHERE [cid] = '. $category['cid'] .' ORDER BY [timestamp] DESC, i.[iid] DESC'); return _aggregator_page_list($items, arg(3)); } @@ -87,7 +87,7 @@ function aggregator_feed_items_load($sql if (isset($sql)) { $result = pager_query($sql, 20); while ($item = db_fetch_object($result)) { - $result_category = db_query('SELECT c.title, c.cid FROM {aggregator_category_item} ci LEFT JOIN {aggregator_category} c ON ci.cid = c.cid WHERE ci.iid = %d ORDER BY c.title', $item->iid); + $result_category = db_query('SELECT c.[title], c.[cid] FROM [{aggregator_category_item}] ci LEFT JOIN [{aggregator_category}] c ON ci.[cid] = c.[cid] WHERE ci.[iid] = %d ORDER BY c.[title]', $item->iid); $item->categories = array(); while ($item_categories = db_fetch_object($result_category)) { $item->categories[] = $item_categories; @@ -153,7 +153,7 @@ function aggregator_categorize_items($it foreach ($items as $item) { $form['items'][$item->iid] = array('#value' => theme('aggregator_item', $item)); $form['categories'][$item->iid] = array(); - $categories_result = db_query('SELECT c.cid, c.title, ci.iid FROM {aggregator_category} c LEFT JOIN {aggregator_category_item} ci ON c.cid = ci.cid AND ci.iid = %d', $item->iid); + $categories_result = db_query('SELECT c.[cid], c.[title], ci.[iid] FROM [{aggregator_category}] c LEFT JOIN [{aggregator_category_item}] ci ON c.[cid] = ci.[cid] AND ci.[iid] = %d', $item->iid); $selected = array(); while ($category = db_fetch_object($categories_result)) { if (!$done) { @@ -192,10 +192,10 @@ function aggregator_categorize_items_val function aggregator_categorize_items_submit($form, &$form_state) { if (!empty($form_state['values']['categories'])) { foreach ($form_state['values']['categories'] as $iid => $selection) { - db_query('DELETE FROM {aggregator_category_item} WHERE iid = %d', $iid); + db_query('DELETE FROM [{aggregator_category_item}] WHERE [iid] = %d', $iid); foreach ($selection as $cid) { if ($cid) { - db_query('INSERT INTO {aggregator_category_item} (cid, iid) VALUES (%d, %d)', $cid, $iid); + db_query('INSERT INTO [{aggregator_category_item}] ([cid], [iid]) VALUES (%d, %d)', $cid, $iid); } } } @@ -250,7 +250,7 @@ function template_preprocess_aggregator_ $variables['feed_url'] = check_url($item->link); $variables['feed_title'] = check_plain($item->title); - $variables['content'] = aggregator_filter_xss($item->description); + $variables['content'] = aggregator_filter_xss(db_decode_clob($item->description)); $variables['source_url'] = ''; $variables['source_title'] = ''; @@ -275,14 +275,14 @@ function template_preprocess_aggregator_ * Menu callback; displays all the feeds used by the aggregator. */ function aggregator_page_sources() { - $result = db_query('SELECT f.fid, f.title, f.description, f.image, MAX(i.timestamp) AS last FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.fid = i.fid GROUP BY f.fid, f.title, f.description, f.image ORDER BY last DESC, f.title'); + $result = db_query('SELECT f.[fid], f.[title], f.[description], f.[image], MAX(i.[timestamp]) AS [last] FROM [{aggregator_feed}] f LEFT JOIN [{aggregator_item}] i ON f.[fid] = i.[fid] GROUP BY f.[fid], f.[title], f.[description], f.[image] ORDER BY [last] DESC, f.[title]'); $output = ''; while ($feed = db_fetch_object($result)) { // Most recent items: $summary_items = array(); if (variable_get('aggregator_summary_items', 3)) { - $items = db_query_range('SELECT i.title, i.timestamp, i.link FROM {aggregator_item} i WHERE i.fid = %d ORDER BY i.timestamp DESC', $feed->fid, 0, variable_get('aggregator_summary_items', 3)); + $items = db_query_range('SELECT i.[title], i.[timestamp], i.[link] FROM [{aggregator_item}] i WHERE i.[fid] = %d ORDER BY i.[timestamp] DESC', $feed->fid, 0, variable_get('aggregator_summary_items', 3)); while ($item = db_fetch_object($items)) { $summary_items[] = theme('aggregator_summary_item', $item); } @@ -299,13 +299,13 @@ function aggregator_page_sources() { * Menu callback; displays all the categories used by the aggregator. */ function aggregator_page_categories() { - $result = db_query('SELECT c.cid, c.title, c.description FROM {aggregator_category} c LEFT JOIN {aggregator_category_item} ci ON c.cid = ci.cid LEFT JOIN {aggregator_item} i ON ci.iid = i.iid GROUP BY c.cid, c.title, c.description'); + $result = db_query('SELECT c.[cid], c.[title], c.[description] FROM [{aggregator_category}] c LEFT JOIN [{aggregator_category_item}] ci ON c.[cid] = ci.[cid] LEFT JOIN [{aggregator_item}] i ON ci.[iid] = i.[iid] GROUP BY c.[cid], c.[title], c.[description]'); $output = ''; while ($category = db_fetch_object($result)) { if (variable_get('aggregator_summary_items', 3)) { $summary_items = array(); - $items = db_query_range('SELECT i.title, i.timestamp, i.link, f.title as feed_title, f.link as feed_link FROM {aggregator_category_item} ci LEFT JOIN {aggregator_item} i ON i.iid = ci.iid LEFT JOIN {aggregator_feed} f ON i.fid = f.fid WHERE ci.cid = %d ORDER BY i.timestamp DESC', $category->cid, 0, variable_get('aggregator_summary_items', 3)); + $items = db_query_range('SELECT i.[title], i.[timestamp], i.[link], f.[title] AS [feed_title], f.[link] AS [feed_link] FROM [{aggregator_category_item}] ci LEFT JOIN [{aggregator_item}] i ON i.[iid] = ci.[iid] LEFT JOIN [{aggregator_feed}] f ON i.[fid] = f.[fid] WHERE ci.[cid] = %d ORDER BY i.[timestamp] DESC', $category->cid, 0, variable_get('aggregator_summary_items', 3)); while ($item = db_fetch_object($items)) { $summary_items[] = theme('aggregator_summary_item', $item); } @@ -324,14 +324,14 @@ function aggregator_page_rss() { $result = NULL; // arg(2) is the passed cid, only select for that category if (arg(2)) { - $category = db_fetch_object(db_query('SELECT cid, title FROM {aggregator_category} WHERE cid = %d', arg(2))); - $sql = 'SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_category_item} c LEFT JOIN {aggregator_item} i ON c.iid = i.iid LEFT JOIN {aggregator_feed} f ON i.fid = f.fid WHERE cid = %d ORDER BY timestamp DESC, i.iid DESC'; + $category = db_fetch_object(db_query('SELECT [cid], [title] FROM [{aggregator_category}] WHERE [cid] = %d', arg(2))); + $sql = 'SELECT i.*, f.[title] AS [ftitle], f.[link] AS [flink] FROM [{aggregator_category_item}] c LEFT JOIN [{aggregator_item}] i ON c.[iid] = i.[iid] LEFT JOIN [{aggregator_feed}] f ON i.[fid] = f.[fid] WHERE [cid] = %d ORDER BY [timestamp] DESC, i.[iid] DESC'; $result = db_query_range($sql, $category->cid, 0, variable_get('feed_default_items', 10)); } // or, get the default aggregator items else { $category = NULL; - $sql = 'SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_item} i INNER JOIN {aggregator_feed} f ON i.fid = f.fid ORDER BY i.timestamp DESC, i.iid DESC'; + $sql = 'SELECT i.*, f.[title] AS [ftitle], f.[link] AS [flink] FROM [{aggregator_item}] i INNER JOIN [{aggregator_feed}] f ON i.[fid] = f.[fid] ORDER BY i.[timestamp] DESC, i.[iid] DESC'; $result = db_query_range($sql, 0, variable_get('feed_default_items', 10)); } @@ -357,6 +357,7 @@ function theme_aggregator_page_rss($feed $items = ''; $feed_length = variable_get('feed_item_length', 'teaser'); foreach ($feeds as $feed) { + $feed->description = db_decode_clob($feed->description); switch ($feed_length) { case 'teaser': $teaser = node_teaser($feed->description); @@ -394,10 +395,10 @@ function theme_aggregator_page_rss($feed */ function aggregator_page_opml($cid = NULL) { if ($cid) { - $result = db_query('SELECT f.title, f.url FROM {aggregator_feed} f LEFT JOIN {aggregator_category_feed} c on f.fid = c.fid WHERE c.cid = %d ORDER BY title', $cid); + $result = db_query('SELECT f.[title], f.[url] FROM [{aggregator_feed}] f LEFT JOIN [{aggregator_category_feed}] c on f.[fid] = c.[fid] WHERE c.[cid] = %d ORDER BY [title]', $cid); } else { - $result = db_query('SELECT * FROM {aggregator_feed} ORDER BY title'); + $result = db_query('SELECT * FROM [{aggregator_feed}] ORDER BY [title]'); } $feeds = array(); Index: modules/block/block.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.admin.inc,v retrieving revision 1.14 diff -u -p -r1.14 block.admin.inc --- modules/block/block.admin.inc 22 Dec 2007 23:24:24 -0000 1.14 +++ modules/block/block.admin.inc 16 Jan 2008 15:38:11 -0000 @@ -95,7 +95,7 @@ function block_admin_display_form_submit foreach ($form_state['values'] as $block) { $block['status'] = $block['region'] != BLOCK_REGION_NONE; $block['region'] = $block['status'] ? $block['region'] : ''; - db_query("UPDATE {blocks} SET status = %d, weight = %d, region = '%s', throttle = %d WHERE module = '%s' AND delta = '%s' AND theme = '%s'", $block['status'], $block['weight'], $block['region'], isset($block['throttle']) ? $block['throttle'] : 0, $block['module'], $block['delta'], $block['theme']); + db_query("UPDATE [{blocks}] SET [status] = %d, [weight] = %d, [region] = %s, [throttle] = %d WHERE [module] = %s AND [delta] = %s AND [theme] = %s", $block['status'], $block['weight'], $block['region'], isset($block['throttle']) ? $block['throttle'] : 0, $block['module'], $block['delta'], $block['theme']); } drupal_set_message(t('The block settings have been updated.')); cache_clear_all(); @@ -144,7 +144,7 @@ function block_admin_configure(&$form_st $form['module'] = array('#type' => 'value', '#value' => $module); $form['delta'] = array('#type' => 'value', '#value' => $delta); - $edit = db_fetch_array(db_query("SELECT pages, visibility, custom, title FROM {blocks} WHERE module = '%s' AND delta = '%s'", $module, $delta)); + $edit = db_fetch_array(db_query("SELECT [pages], [visibility], [custom], [title] FROM [{blocks}] WHERE [module] = %s AND [delta] = %s", $module, $delta)); $form['block_settings'] = array( '#type' => 'fieldset', @@ -194,11 +194,11 @@ function block_admin_configure(&$form_st // Role-based visibility settings $default_role_options = array(); - $result = db_query("SELECT rid FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $module, $delta); + $result = db_query("SELECT [rid] FROM [{blocks_roles}] WHERE [module] = %s AND [delta] = %s", $module, $delta); while ($role = db_fetch_object($result)) { $default_role_options[] = $role->rid; } - $result = db_query('SELECT rid, name FROM {role} ORDER BY name'); + $result = db_query('SELECT [rid], [name] FROM [{role}] ORDER BY [name]'); $role_options = array(); while ($role = db_fetch_object($result)) { $role_options[$role->rid] = $role->name; @@ -260,7 +260,7 @@ function block_admin_configure(&$form_st function block_admin_configure_validate($form, &$form_state) { if ($form_state['values']['module'] == 'block') { - if (empty($form_state['values']['info']) || db_result(db_query("SELECT COUNT(*) FROM {boxes} WHERE bid != %d AND info = '%s'", $form_state['values']['delta'], $form_state['values']['info']))) { + if (empty($form_state['values']['info']) || db_result(db_query("SELECT COUNT(*) FROM [{boxes}] WHERE [bid] != %d AND [info] = %s", $form_state['values']['delta'], $form_state['values']['info']))) { form_set_error('info', t('Please ensure that each block description is unique.')); } } @@ -268,10 +268,10 @@ function block_admin_configure_validate( function block_admin_configure_submit($form, &$form_state) { if (!form_get_errors()) { - db_query("UPDATE {blocks} SET visibility = %d, pages = '%s', custom = %d, title = '%s' WHERE module = '%s' AND delta = '%s'", $form_state['values']['visibility'], trim($form_state['values']['pages']), $form_state['values']['custom'], $form_state['values']['title'], $form_state['values']['module'], $form_state['values']['delta']); - db_query("DELETE FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $form_state['values']['module'], $form_state['values']['delta']); + db_query("UPDATE [{blocks}] SET [visibility] = %d, [pages] = %s, [custom] = %d, [title] = %s WHERE [module] = %s AND [delta] = %s", $form_state['values']['visibility'], trim($form_state['values']['pages']), $form_state['values']['custom'], $form_state['values']['title'], $form_state['values']['module'], $form_state['values']['delta']); + db_query("DELETE FROM [{blocks_roles}] WHERE [module] = %s AND [delta] = %s", $form_state['values']['module'], $form_state['values']['delta']); foreach (array_filter($form_state['values']['roles']) as $rid) { - db_query("INSERT INTO {blocks_roles} (rid, module, delta) VALUES (%d, '%s', '%s')", $rid, $form_state['values']['module'], $form_state['values']['delta']); + db_query("INSERT INTO [{blocks_roles}] ([rid], [module], [delta]) VALUES (%d, %s, %s)", $rid, $form_state['values']['module'], $form_state['values']['delta']); } module_invoke($form_state['values']['module'], 'block', 'save', $form_state['values']['delta'], $form_state['values']); drupal_set_message(t('The block configuration has been saved.')); @@ -289,7 +289,7 @@ function block_add_block_form(&$form_sta } function block_add_block_form_validate($form, &$form_state) { - if (empty($form_state['values']['info']) || db_result(db_query("SELECT COUNT(*) FROM {boxes} WHERE info = '%s'", $form_state['values']['info']))) { + if (empty($form_state['values']['info']) || db_result(db_query("SELECT COUNT(*) FROM [{boxes}] WHERE [info] = %s", $form_state['values']['info']))) { form_set_error('info', t('Please ensure that each block description is unique.')); } } @@ -298,17 +298,17 @@ function block_add_block_form_validate($ * Save the new custom block. */ function block_add_block_form_submit($form, &$form_state) { - db_query("INSERT INTO {boxes} (body, info, format) VALUES ('%s', '%s', %d)", $form_state['values']['body'], $form_state['values']['info'], $form_state['values']['format']); - $delta = db_last_insert_id('boxes', 'bid'); + drupal_write_record('boxes', $form_state['values']); + $delta = $form_state['values']['bid']; foreach (list_themes() as $key => $theme) { if ($theme->status) { - db_query("INSERT INTO {blocks} (visibility, pages, custom, title, module, theme, status, weight, delta, cache) VALUES(%d, '%s', %d, '%s', '%s', '%s', %d, %d, %d, %d)", $form_state['values']['visibility'], trim($form_state['values']['pages']), $form_state['values']['custom'], $form_state['values']['title'], $form_state['values']['module'], $theme->name, 0, 0, $delta, BLOCK_NO_CACHE); + db_query("INSERT INTO [{blocks}] ([visibility], [pages], [custom], [title], [module], [theme], [status], [weight], [delta], [cache]) VALUES(%d, %s, %d, %s, %s, %s, %d, %d, %d, %d)", $form_state['values']['visibility'], trim($form_state['values']['pages']), $form_state['values']['custom'], $form_state['values']['title'], $form_state['values']['module'], $theme->name, 0, 0, $delta, BLOCK_NO_CACHE); } } foreach (array_filter($form_state['values']['roles']) as $rid) { - db_query("INSERT INTO {blocks_roles} (rid, module, delta) VALUES (%d, '%s', '%s')", $rid, $form_state['values']['module'], $delta); + db_query("INSERT INTO [{blocks_roles}] ([rid], [module], [delta]) VALUES (%d, %s, %s)", $rid, $form_state['values']['module'], $delta); } drupal_set_message(t('The block has been created.')); @@ -333,8 +333,8 @@ function block_box_delete(&$form_state, * Deletion of custom blocks. */ function block_box_delete_submit($form, &$form_state) { - db_query('DELETE FROM {boxes} WHERE bid = %d', $form_state['values']['bid']); - db_query("DELETE FROM {blocks} WHERE module = 'block' AND delta = %d", $form_state['values']['bid']); + db_query('DELETE FROM [{boxes}] WHERE [bid] = %d', $form_state['values']['bid']); + db_query("DELETE FROM [{blocks}] WHERE [module] = 'block' AND [delta] = %d", $form_state['values']['bid']); drupal_set_message(t('The block %name has been removed.', array('%name' => $form_state['values']['info']))); cache_clear_all(); $form_state['redirect'] = 'admin/build/block'; Index: modules/block/block.install =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.install,v retrieving revision 1.8 diff -u -p -r1.8 block.install --- modules/block/block.install 18 Dec 2007 12:59:20 -0000 1.8 +++ modules/block/block.install 16 Jan 2008 15:38:11 -0000 @@ -79,6 +79,7 @@ function block_schema() { 'pages' => array( 'type' => 'text', 'not null' => TRUE, + 'default' => '', 'description' => t('Contents of the "Pages" block; contains either a list of paths on which to include/exclude the block or PHP code, depending on "visibility" setting.'), ), 'title' => array( @@ -112,18 +113,21 @@ function block_schema() { 'type' => 'varchar', 'length' => 64, 'not null' => TRUE, + 'default' => '', 'description' => t("The block's origin module, from {blocks}.module."), ), 'delta' => array( 'type' => 'varchar', 'length' => 32, 'not null' => TRUE, + 'default' => '', 'description' => t("The block's unique delta within module, from {blocks}.delta."), ), 'rid' => array( 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, + 'default' => 0, 'description' => t("The user's role ID from {users_roles}.rid."), ), ), @@ -147,7 +151,7 @@ function block_schema() { 'description' => t("The block's {blocks}.bid."), ), 'body' => array( - 'type' => 'text', + 'type' => 'clob', 'not null' => FALSE, 'size' => 'big', 'description' => t('Block contents.'), Index: modules/block/block.module =================================================================== RCS file: /cvs/drupal/drupal/modules/block/block.module,v retrieving revision 1.297 diff -u -p -r1.297 block.module --- modules/block/block.module 24 Dec 2007 10:33:39 -0000 1.297 +++ modules/block/block.module 16 Jan 2008 15:38:12 -0000 @@ -188,7 +188,7 @@ function block_block($op = 'list', $delt case 'list': $blocks = array(); - $result = db_query('SELECT bid, info FROM {boxes} ORDER BY info'); + $result = db_query('SELECT [bid], [info] FROM [{boxes}] ORDER BY [info]'); while ($block = db_fetch_object($result)) { $blocks[$block->bid]['info'] = $block->info; // Not worth caching. @@ -211,8 +211,8 @@ function block_block($op = 'list', $delt break; case 'view': - $block = db_fetch_object(db_query('SELECT body, format FROM {boxes} WHERE bid = %d', $delta)); - $data['content'] = check_markup($block->body, $block->format, FALSE); + $block = db_fetch_object(db_query('SELECT [body], [format] FROM [{boxes}] WHERE [bid] = %d', $delta)); + $data['content'] = check_markup(db_decode_clob($block->body), $block->format, FALSE); return $data; } } @@ -228,7 +228,7 @@ function _block_rehash() { init_theme(); - $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s'", $theme_key); + $result = db_query("SELECT * FROM [{blocks}] WHERE [theme] = %s", $theme_key); $old_blocks = array(); while ($old_block = db_fetch_array($result)) { $old_blocks[$old_block['module']][$old_block['delta']] = $old_block; @@ -246,7 +246,7 @@ function _block_rehash() { $block['delta'] = $delta; $block['theme'] = $theme_key; if (!isset($block['pages'])) { - // {block}.pages is type 'text', so it cannot have a + // [{block}].[pages] is type 'text', so it cannot have a // default value, and not null, so we need to provide // value if the module did not. $block['pages'] = ''; @@ -279,14 +279,14 @@ function _block_rehash() { // Remove blocks that are no longer defined by the code from the database. foreach ($old_blocks as $module => $old_module_blocks) { foreach ($old_module_blocks as $delta => $block) { - db_query("DELETE FROM {blocks} WHERE module = '%s' AND delta = '%s' AND theme = '%s'", $module, $delta, $theme_key); + db_query("DELETE FROM [{blocks}] WHERE [module] = %s AND [delta] = %s AND [theme] = %s", $module, $delta, $theme_key); } } return $blocks; } function block_box_get($bid) { - return db_fetch_array(db_query("SELECT bx.*, bl.title FROM {boxes} bx INNER JOIN {blocks} bl ON bx.bid = bl.delta WHERE bl.module = 'block' AND bx.bid = %d", $bid)); + return db_fetch_array(db_query("SELECT bx.*, bl.[title] FROM [{boxes}] bx INNER JOIN [{blocks}] bl ON bx.[bid] = bl.[delta] WHERE bl.[module] = 'block' AND bx.[bid] = %d", $bid)); } /** @@ -328,7 +328,8 @@ function block_box_save($edit, $delta) { $edit['format'] = FILTER_FORMAT_DEFAULT; } - db_query("UPDATE {boxes} SET body = '%s', info = '%s', format = %d WHERE bid = %d", $edit['body'], $edit['info'], $edit['format'], $delta); + $edit['bid'] = $delta; + drupal_write_record('boxes', $edit, 'bid'); return TRUE; } @@ -345,7 +346,7 @@ function block_user($type, $edit, &$user case 'form': if ($category == 'account') { $rids = array_keys($user->roles); - $result = db_query("SELECT DISTINCT b.* FROM {blocks} b LEFT JOIN {blocks_roles} r ON b.module = r.module AND b.delta = r.delta WHERE b.status = 1 AND b.custom != 0 AND (r.rid IN (". db_placeholders($rids) .") OR r.rid IS NULL) ORDER BY b.weight, b.module", $rids); + $result = db_query("SELECT DISTINCT b.* FROM [{blocks}] b LEFT JOIN [{blocks_roles}] r ON b.[module] = r.[module] AND b.[delta] = r.[delta] WHERE b.[status] = 1 AND b.[custom] != 0 AND (r.[rid] IN (". db_placeholders($rids) .") OR r.[rid] IS NULL) ORDER BY b.[weight], b.[module]", $rids); $form['block'] = array('#type' => 'fieldset', '#title' => t('Block configuration'), '#weight' => 3, '#collapsible' => TRUE, '#tree' => TRUE); while ($block = db_fetch_object($result)) { $data = module_invoke($block->module, 'block', 'list'); @@ -392,7 +393,7 @@ function block_list($region) { if (!count($blocks)) { $rids = array_keys($user->roles); - $result = db_query(db_rewrite_sql("SELECT DISTINCT b.* FROM {blocks} b LEFT JOIN {blocks_roles} r ON b.module = r.module AND b.delta = r.delta WHERE b.theme = '%s' AND b.status = 1 AND (r.rid IN (". db_placeholders($rids) .") OR r.rid IS NULL) ORDER BY b.region, b.weight, b.module", 'b', 'bid'), array_merge(array($theme_key), $rids)); + $result = db_query(db_rewrite_sql("SELECT DISTINCT b.* FROM [{blocks}] b LEFT JOIN [{blocks_roles}] r ON b.[module] = r.[module] AND b.[delta] = r.[delta] WHERE b.[theme] = %s AND b.[status] = 1 AND (r.[rid] IN (". db_placeholders($rids) .") OR r.[rid] IS NULL) ORDER BY b.[region], b.[weight], b.[module]", 'b', 'bid'), array_merge(array($theme_key), $rids)); while ($block = db_fetch_object($result)) { if (!isset($blocks[$block->region])) { $blocks[$block->region] = array(); Index: modules/blog/blog.module =================================================================== RCS file: /cvs/drupal/drupal/modules/blog/blog.module,v retrieving revision 1.297 diff -u -p -r1.297 blog.module --- modules/blog/blog.module 9 Jan 2008 09:51:34 -0000 1.297 +++ modules/blog/blog.module 16 Jan 2008 15:38:12 -0000 @@ -86,7 +86,7 @@ function blog_form(&$node) { $node->body = ''. $blog->body .' ['. l($blog->name, "node/$nid") .']'; } - if ($iid && $item = db_fetch_object(db_query('SELECT i.*, f.title as ftitle, f.link as flink FROM {aggregator_item} i, {aggregator_feed} f WHERE i.iid = %d AND i.fid = f.fid', $iid))) { + if ($iid && $item = db_fetch_object(db_query('SELECT i.*, f.[title] AS [ftitle], f.[link] AS [flink] FROM [{aggregator_item}] i, [{aggregator_feed}] f WHERE i.[iid] = %d AND i.[fid] = f.[fid]', $iid))) { $node->title = $item->title; // Note: $item->description has been validated on aggregation. $node->body = ''. check_plain($item->title) .' - '. $item->description .' ['. check_plain($item->ftitle) ."]\n"; @@ -180,7 +180,7 @@ function blog_block($op = 'list', $delta } else if ($op == 'view') { if (user_access('access content')) { - $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.title, n.created FROM {node} n WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.created DESC"), 0, 10); + $result = db_query_range(db_rewrite_sql("SELECT n.[nid], n.[title], n.[created] FROM [{node}] n WHERE n.[type] = 'blog' AND n.[status] = 1 ORDER BY n.[created] DESC"), 0, 10); if ($node_title_list = node_title_list($result)) { $block['content'] = $node_title_list; $block['content'] .= theme('more_link', url('blog'), t('Read the latest blog entries.')); Index: modules/blog/blog.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/blog/blog.pages.inc,v retrieving revision 1.5 diff -u -p -r1.5 blog.pages.inc --- modules/blog/blog.pages.inc 9 Jan 2008 09:51:34 -0000 1.5 +++ modules/blog/blog.pages.inc 16 Jan 2008 15:38:12 -0000 @@ -25,7 +25,7 @@ function blog_page_user($account) { $output = theme('item_list', $items); - $result = pager_query(db_rewrite_sql("SELECT n.nid, n.sticky, n.created FROM {node} n WHERE n.type = 'blog' AND n.uid = %d AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC"), variable_get('default_nodes_main', 10), 0, NULL, $account->uid); + $result = pager_query(db_rewrite_sql("SELECT n.[nid], n.[sticky], n.[created] FROM [{node}] n WHERE n.[type] = 'blog' AND n.[uid] = %d AND n.[status] = 1 ORDER BY n.[sticky] DESC, n.[created] DESC"), variable_get('default_nodes_main', 10), 0, NULL, $account->uid); while ($node = db_fetch_object($result)) { $output .= node_view(node_load($node->nid), 1); } @@ -43,7 +43,7 @@ function blog_page_last() { $output = ''; - $result = pager_query(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC"), variable_get('default_nodes_main', 10)); + $result = pager_query(db_rewrite_sql("SELECT n.[nid], n.[created] FROM [{node}] n WHERE n.[type] = 'blog' AND n.[status] = 1 ORDER BY n.[sticky] DESC, n.[created] DESC"), variable_get('default_nodes_main', 10)); while ($node = db_fetch_object($result)) { $output .= node_view(node_load($node->nid), 1); @@ -58,7 +58,7 @@ function blog_page_last() { * Menu callback; displays an RSS feed containing recent blog entries of a given user. */ function blog_feed_user($account) { - $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n WHERE n.type = 'blog' AND n.uid = %d AND n.status = 1 ORDER BY n.created DESC"), $account->uid, 0, variable_get('feed_default_items', 10)); + $result = db_query_range(db_rewrite_sql("SELECT n.[nid], n.[created] FROM [{node}] n WHERE n.[type] = 'blog' AND n.[uid] = %d AND n.[status] = 1 ORDER BY n.[created] DESC"), $account->uid, 0, variable_get('feed_default_items', 10)); $channel['title'] = $account->name ."'s blog"; $channel['link'] = url('blog/'. $account->uid, array('absolute' => TRUE)); @@ -73,7 +73,7 @@ function blog_feed_user($account) { * Menu callback; displays an RSS feed containing recent blog entries of all users. */ function blog_feed_last() { - $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.created FROM {node} n WHERE n.type = 'blog' AND n.status = 1 ORDER BY n.created DESC"), 0, variable_get('feed_default_items', 10)); + $result = db_query_range(db_rewrite_sql("SELECT n.[nid], n.[created] FROM [{node}] n WHERE n.[type] = 'blog' AND n.[status] = 1 ORDER BY n.[created] DESC"), 0, variable_get('feed_default_items', 10)); $channel['title'] = variable_get('site_name', 'Drupal') .' blogs'; $channel['link'] = url('blog', array('absolute' => TRUE)); Index: modules/blogapi/blogapi.module =================================================================== RCS file: /cvs/drupal/drupal/modules/blogapi/blogapi.module,v retrieving revision 1.114 diff -u -p -r1.114 blogapi.module --- modules/blogapi/blogapi.module 9 Jan 2008 09:51:34 -0000 1.114 +++ modules/blogapi/blogapi.module 16 Jan 2008 15:38:12 -0000 @@ -329,10 +329,10 @@ function blogapi_blogger_get_recent_post $type = _blogapi_blogid($blogid); if ($bodies) { - $result = db_query_range("SELECT n.nid, n.title, r.body, r.format, n.comment, n.created, u.name FROM {node} n, {node_revisions} r, {users} u WHERE n.uid = u.uid AND n.vid = r.vid AND n.type = '%s' AND n.uid = %d ORDER BY n.created DESC", $type, $user->uid, 0, $number_of_posts); + $result = db_query_range("SELECT n.[nid], n.[title], r.[body], r.[format], n.[comment], n.[created], u.[name] FROM [{node}] n, [{node_revisions}] r, [{users}] u WHERE n.[uid] = u.[uid] AND n.[vid] = r.[vid] AND n.[type] = %s AND n.[uid] = %d ORDER BY n.[created] DESC", $type, $user->uid, 0, $number_of_posts); } else { - $result = db_query_range("SELECT n.nid, n.title, n.created, u.name FROM {node} n, {users} u WHERE n.uid = u.uid AND n.type = '%s' AND n.uid = %d ORDER BY n.created DESC", $type, $user->uid, 0, $number_of_posts); + $result = db_query_range("SELECT n.[nid], n.[title], n.[created], u.[name] FROM [{node}] n, [{users}] u WHERE n.[uid] = u.[uid] AND n.[type] = %s AND n.[uid] = %d ORDER BY n.[created] DESC", $type, $user->uid, 0, $number_of_posts); } $blogs = array(); while ($blog = db_fetch_object($result)) { Index: modules/book/book.install =================================================================== RCS file: /cvs/drupal/drupal/modules/book/book.install,v retrieving revision 1.20 diff -u -p -r1.20 book.install --- modules/book/book.install 10 Jan 2008 18:13:42 -0000 1.20 +++ modules/book/book.install 16 Jan 2008 15:38:12 -0000 @@ -16,7 +16,7 @@ function book_install() { */ function book_uninstall() { // Delete menu links. - db_query("DELETE FROM {menu_links} WHERE module = 'book'"); + db_query("DELETE FROM [{menu_links}] WHERE [module] = 'book'"); menu_cache_clear_all(); // Remove tables. drupal_uninstall_schema('book'); Index: modules/book/book.module =================================================================== RCS file: /cvs/drupal/drupal/modules/book/book.module,v retrieving revision 1.454 diff -u -p -r1.454 book.module --- modules/book/book.module 8 Jan 2008 10:35:41 -0000 1.454 +++ modules/book/book.module 16 Jan 2008 15:38:12 -0000 @@ -207,7 +207,7 @@ function book_block($op = 'list', $delta } elseif ($current_bid) { // Only display this block when the user is browsing a book. - $title = db_result(db_query(db_rewrite_sql('SELECT n.title FROM {node} n WHERE n.nid = %d'), $node->book['bid'])); + $title = db_result(db_query(db_rewrite_sql('SELECT n.[title] FROM [{node}] n WHERE n.[nid] = %d'), $node->book['bid'])); // Only show the block if the user has view access for the top-level node. if ($title) { $tree = menu_tree_all_data($node->book['menu_name'], $node->book); @@ -258,13 +258,13 @@ function book_get_books() { if (!isset($all_books)) { $all_books = array(); - $result = db_query("SELECT DISTINCT(bid) FROM {book}"); + $result = db_query("SELECT DISTINCT([bid]) FROM [{book}]"); $nids = array(); while ($book = db_fetch_array($result)) { $nids[] = $book['bid']; } if ($nids) { - $result2 = db_query(db_rewrite_sql("SELECT n.type, n.title, b.*, ml.* FROM {book} b INNER JOIN {node} n on b.nid = n.nid INNER JOIN {menu_links} ml ON b.mlid = ml.mlid WHERE n.nid IN (". implode(',', $nids) .") AND n.status = 1 ORDER BY ml.weight, ml.link_title")); + $result2 = db_query(db_rewrite_sql("SELECT n.[type], n.[title], b.*, ml.* FROM [{book}] b INNER JOIN [{node}] n on b.[nid] = n.[nid] INNER JOIN [{menu_links}] ml ON b.[mlid] = ml.[mlid] WHERE n.[nid] IN (". implode(',', $nids) .") AND n.[status] = 1 ORDER BY ml.[weight], ml.[link_title]")); while ($link = db_fetch_array($result2)) { $link['href'] = $link['link_path']; $link['options'] = unserialize($link['options']); @@ -453,20 +453,20 @@ function _book_update_outline(&$node) { else { // Check in case the parent is not is this book; the book takes precedence. if (!empty($node->book['plid'])) { - $parent = db_fetch_array(db_query("SELECT * FROM {book} WHERE mlid = %d", $node->book['plid'])); + $parent = db_fetch_array(db_query("SELECT * FROM [{book}] WHERE [mlid] = %d", $node->book['plid'])); } if (empty($node->book['plid']) || !$parent || $parent['bid'] != $node->book['bid']) { - $node->book['plid'] = db_result(db_query("SELECT mlid FROM {book} WHERE nid = %d", $node->book['bid'])); + $node->book['plid'] = db_result(db_query("SELECT [mlid] FROM [{book}] WHERE [nid] = %d", $node->book['bid'])); $node->book['parent_mismatch'] = TRUE; // Likely when JS is disabled. } } if (menu_link_save($node->book)) { if ($new) { // Insert new. - db_query("INSERT INTO {book} (nid, mlid, bid) VALUES (%d, %d, %d)", $node->nid, $node->book['mlid'], $node->book['bid']); + db_query("INSERT INTO [{book}] ([nid], [mlid], [bid]) VALUES (%d, %d, %d)", $node->nid, $node->book['mlid'], $node->book['bid']); } else { - if ($node->book['bid'] != db_result(db_query("SELECT bid FROM {book} WHERE nid = %d", $node->nid))) { + if ($node->book['bid'] != db_result(db_query("SELECT [bid] FROM [{book}] WHERE [nid] = %d", $node->nid))) { // Update the bid for this page and all children. book_update_bid($node->book); } @@ -486,17 +486,17 @@ function _book_update_outline(&$node) { function book_update_bid($book_link) { for ($i = 1; $i <= MENU_MAX_DEPTH && $book_link["p$i"]; $i++) { - $match[] = "p$i = %d"; + $match[] = "[p$i] = %d"; $args[] = $book_link["p$i"]; } - $result = db_query("SELECT mlid FROM {menu_links} WHERE ". implode(' AND ', $match), $args); + $result = db_query("SELECT [mlid] FROM [{menu_links}] WHERE ". implode(' AND ', $match), $args); $mlids = array(); while ($a = db_fetch_array($result)) { $mlids[] = $a['mlid']; } if ($mlids) { - db_query("UPDATE {book} SET bid = %d WHERE mlid IN (". implode(',', $mlids) .")", $book_link['bid']); + db_query("UPDATE [{book}] SET [bid] = %d WHERE [mlid] IN (". implode(',', $mlids) .")", $book_link['bid']); } } @@ -654,7 +654,7 @@ function book_nodeapi(&$node, $op, $teas switch ($op) { case 'load': // Note - we cannot use book_link_load() because it will call node_load() - $info['book'] = db_fetch_array(db_query('SELECT * FROM {book} b INNER JOIN {menu_links} ml ON b.mlid = ml.mlid WHERE b.nid = %d', $node->nid)); + $info['book'] = db_fetch_array(db_query('SELECT * FROM [{book}] b INNER JOIN [{menu_links}] ml ON b.[mlid] = ml.[mlid] WHERE b.[nid] = %d', $node->nid)); if ($info['book']) { $info['book']['href'] = $info['book']['link_path']; $info['book']['title'] = $info['book']['link_title']; @@ -700,7 +700,7 @@ function book_nodeapi(&$node, $op, $teas if (!empty($node->book['bid'])) { if ($node->nid == $node->book['bid']) { // Handle deletion of a top-level post. - $result = db_query("SELECT b.nid FROM {menu_links} ml INNER JOIN {book} b on b.mlid = ml.mlid WHERE ml.plid = %d", $node->book['mlid']); + $result = db_query("SELECT b.[nid] FROM [{menu_links}] ml INNER JOIN [{book}] b on b.[mlid] = ml.[mlid] WHERE ml.[plid] = %d", $node->book['mlid']); while ($child = db_fetch_array($result)) { $child_node = node_load($child['nid']); $child_node->book['bid'] = $child_node->nid; @@ -708,7 +708,7 @@ function book_nodeapi(&$node, $op, $teas } } menu_link_delete($node->book['mlid']); - db_query('DELETE FROM {book} WHERE mlid = %d', $node->book['mlid']); + db_query('DELETE FROM [{book}] WHERE [mlid] = %d', $node->book['mlid']); } break; case 'prepare': @@ -1014,12 +1014,12 @@ function book_help($path, $arg) { } /** - * Like menu_link_load(), but adds additional data from the {book} table. + * Like menu_link_load(), but adds additional data from the [{book}] table. * * Do not call when loading a node, since this function may call node_load(). */ function book_link_load($mlid) { - if ($item = db_fetch_array(db_query("SELECT * FROM {menu_links} ml INNER JOIN {book} b ON b.mlid = ml.mlid LEFT JOIN {menu_router} m ON m.path = ml.router_path WHERE ml.mlid = %d", $mlid))) { + if ($item = db_fetch_array(db_query("SELECT * FROM [{menu_links}] ml INNER JOIN [{book}] b ON b.[mlid] = ml.[mlid] LEFT JOIN [{menu_router}] m ON m.[path] = ml.[router_path] WHERE ml.[mlid] = %d", $mlid))) { _menu_link_translate($item); return $item; } @@ -1048,20 +1048,20 @@ function book_menu_subtree_data($item) { $data = $cache->data; } else { - $match = array("menu_name = '%s'"); + $match = array("[menu_name] = %s"); $args = array($item['menu_name']); $i = 1; while ($i <= MENU_MAX_DEPTH && $item["p$i"]) { - $match[] = "p$i = %d"; + $match[] = "[p$i] = %d"; $args[] = $item["p$i"]; $i++; } $sql = " - SELECT b.*, m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, ml.* - FROM {menu_links} ml INNER JOIN {menu_router} m ON m.path = ml.router_path - INNER JOIN {book} b ON ml.mlid = b.mlid + SELECT b.*, m.[load_functions], m.[to_arg_functions], m.[access_callback], m.[access_arguments], m.[page_callback], m.[page_arguments], m.[title], m.[title_callback], m.[title_arguments], m.[type], ml.* + FROM [{menu_links}] ml INNER JOIN [{menu_router}] m ON m.[path] = ml.[router_path] + INNER JOIN [{book}] b ON ml.[mlid] = b.[mlid] WHERE ". implode(' AND ', $match) ." - ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC"; + ORDER BY [p1] ASC, [p2] ASC, [p3] ASC, [p4] ASC, [p5] ASC, [p6] ASC, [p7] ASC, [p8] ASC, [p9] ASC"; $data['tree'] = menu_tree_data(db_query($sql, $args), array(), $item['depth']); $data['node_links'] = array(); Index: modules/book/book.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/book/book.pages.inc,v retrieving revision 1.5 diff -u -p -r1.5 book.pages.inc --- modules/book/book.pages.inc 22 Dec 2007 23:24:24 -0000 1.5 +++ modules/book/book.pages.inc 16 Jan 2008 15:38:12 -0000 @@ -209,7 +209,7 @@ function book_remove_form_submit($form, if ($node->nid != $node->book['bid']) { // Only allowed when this is not a book (top-level page). menu_link_delete($node->book['mlid']); - db_query('DELETE FROM {book} WHERE nid = %d', $node->nid); + db_query('DELETE FROM [{book}] WHERE [nid] = %d', $node->nid); drupal_set_message(t('The post has been removed from the book.')); } $form_state['redirect'] = 'node/'. $node->nid; Index: modules/comment/comment.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.admin.inc,v retrieving revision 1.4 diff -u -p -r1.4 comment.admin.inc --- modules/comment/comment.admin.inc 8 Jan 2008 10:35:41 -0000 1.4 +++ modules/comment/comment.admin.inc 16 Jan 2008 15:38:12 -0000 @@ -51,20 +51,20 @@ function comment_admin_overview($type = $status = ($arg == 'approval') ? COMMENT_NOT_PUBLISHED : COMMENT_PUBLISHED; $form['header'] = array('#type' => 'value', '#value' => array( theme('table_select_header_cell'), - array('data' => t('Subject'), 'field' => 'subject'), - array('data' => t('Author'), 'field' => 'name'), - array('data' => t('Posted in'), 'field' => 'node_title'), - array('data' => t('Time'), 'field' => 'timestamp', 'sort' => 'desc'), + array('data' => t('Subject'), 'field' => '[subject]'), + array('data' => t('Author'), 'field' => '[name]'), + array('data' => t('Posted in'), 'field' => '[node_title]'), + array('data' => t('Time'), 'field' => '[timestamp]', 'sort' => 'desc'), array('data' => t('Operations')) )); - $result = pager_query('SELECT c.subject, c.nid, c.cid, c.comment, c.timestamp, c.status, c.name, c.homepage, u.name AS registered_name, u.uid, n.title as node_title FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid INNER JOIN {node} n ON n.nid = c.nid WHERE c.status = %d'. tablesort_sql($form['header']['#value']), 50, 0, NULL, $status); + $result = pager_query('SELECT c.[subject], c.[nid], c.[cid], c.[comment], c.[timestamp], c.[status], c.[name], c.[homepage], u.[name] AS [registered_name], u.[uid], n.[title] as [node_title] FROM [{comments}] c INNER JOIN [{users}] u ON u.[uid] = c.[uid] INNER JOIN [{node}] n ON n.[nid] = c.[nid] WHERE c.[status] = %d'. tablesort_sql($form['header']['#value']), 50, 0, NULL, $status); // build a table listing the appropriate comments $destination = drupal_get_destination(); while ($comment = db_fetch_object($result)) { $comments[$comment->cid] = ''; $comment->name = $comment->uid ? $comment->registered_name : $comment->name; - $form['subject'][$comment->cid] = array('#value' => l($comment->subject, 'node/'. $comment->nid, array('title' => truncate_utf8($comment->comment, 128), 'fragment' => 'comment-'. $comment->cid))); + $form['subject'][$comment->cid] = array('#value' => l($comment->subject, 'node/'. $comment->nid, array('title' => truncate_utf8(db_decode_clob($comment->comment), 128), 'fragment' => 'comment-'. $comment->cid))); $form['username'][$comment->cid] = array('#value' => theme('username', $comment)); $form['node_title'][$comment->cid] = array('#value' => l($comment->node_title, 'node/'. $comment->nid)); $form['timestamp'][$comment->cid] = array('#value' => format_date($comment->timestamp, 'small')); @@ -172,7 +172,7 @@ function comment_multiple_delete_confirm foreach (array_filter($edit['comments']) as $cid => $value) { $comment = _comment_load($cid); if (is_object($comment) && is_numeric($comment->cid)) { - $subject = db_result(db_query('SELECT subject FROM {comments} WHERE cid = %d', $cid)); + $subject = db_result(db_query('SELECT [subject] FROM [{comments}] WHERE [cid] = %d', $cid)); $form['comments'][$cid] = array('#type' => 'hidden', '#value' => $cid, '#prefix' => '
  • ', '#suffix' => check_plain($subject) .'
  • '); $comment_counter++; } @@ -216,7 +216,7 @@ function comment_multiple_delete_confirm * The comment do be deleted. */ function comment_delete($cid = NULL) { - $comment = db_fetch_object(db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = %d', $cid)); + $comment = db_fetch_object(db_query('SELECT c.*, u.[name] AS [registered_name], u.[uid] FROM [{comments}] c INNER JOIN [{users}] u ON u.[uid] = c.[uid] WHERE c.[cid] = %d', $cid)); $comment->name = $comment->uid ? $comment->registered_name : $comment->name; $output = ''; @@ -282,13 +282,13 @@ function _comment_delete_thread($comment } // Delete the comment: - db_query('DELETE FROM {comments} WHERE cid = %d', $comment->cid); + db_query('DELETE FROM [{comments}] WHERE [cid] = %d', $comment->cid); watchdog('content', 'Comment: deleted %subject.', array('%subject' => $comment->subject)); comment_invoke_comment($comment, 'delete'); // Delete the comment's replies - $result = db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE pid = %d', $comment->cid); + $result = db_query('SELECT c.*, u.[name] AS [registered_name], u.[uid] FROM [{comments}] c INNER JOIN [{users}] u ON u.[uid] = c.[uid] WHERE [pid] = %d', $comment->cid); while ($comment = db_fetch_object($result)) { $comment->name = $comment->uid ? $comment->registered_name : $comment->name; _comment_delete_thread($comment); Index: modules/comment/comment.install =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.install,v retrieving revision 1.18 diff -u -p -r1.18 comment.install --- modules/comment/comment.install 5 Jan 2008 22:45:40 -0000 1.18 +++ modules/comment/comment.install 16 Jan 2008 15:38:12 -0000 @@ -6,7 +6,7 @@ */ function comment_enable() { // Insert records into the node_comment_statistics for nodes that are missing. - db_query("INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count) SELECT n.nid, n.changed, NULL, n.uid, 0 FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE c.comment_count IS NULL"); + db_query("INSERT INTO [{node_comment_statistics}] ([nid], [last_comment_timestamp], [last_comment_name], [last_comment_uid], [comment_count]) SELECT n.[nid], n.[changed], NULL, n.[uid], 0 FROM [{node}] n LEFT JOIN [{node_comment_statistics}] c ON n.[nid] = c.[nid] WHERE c.[comment_count] IS NULL"); } /** @@ -14,7 +14,7 @@ function comment_enable() { */ function comment_update_1() { // Change any future last comment timestamps to now. - db_query('UPDATE {node_comment_statistics} SET last_comment_timestamp = %d WHERE last_comment_timestamp > %d', time(), time()); + db_query('UPDATE [{node_comment_statistics}] SET [last_comment_timestamp] = %d WHERE [last_comment_timestamp] > %d', time(), time()); // Unstuck node indexing timestamp if needed. if (($last = variable_get('node_cron_last', FALSE)) !== FALSE) { @@ -24,8 +24,8 @@ function comment_update_1() { } function comment_update_6001() { - $ret[] = update_sql("ALTER TABLE {comments} DROP score"); - $ret[] = update_sql("ALTER TABLE {comments} DROP users"); + $ret[] = update_sql("ALTER TABLE [{comments}] DROP [score]"); + $ret[] = update_sql("ALTER TABLE [{comments}] DROP [users]"); return $ret; } @@ -62,7 +62,7 @@ function comment_update_6002() { * Add index to parent ID field. */ function comment_update_6003() { - $ret[] = update_sql("ALTER TABLE {comments} ADD KEY pid (pid)"); + $ret[] = update_sql("ALTER TABLE [{comments}] ADD KEY [pid] ([pid])"); return $ret; } @@ -105,8 +105,9 @@ function comment_schema() { 'description' => t('The comment title.'), ), 'comment' => array( - 'type' => 'text', + 'type' => 'clob', 'not null' => TRUE, + 'default' => '', 'size' => 'big', 'description' => t('The comment body.'), ), @@ -142,6 +143,7 @@ function comment_schema() { 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, + 'default' => '', 'description' => t("The vancode representation of the comment's place in a thread."), ), 'name' => array( Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.616 diff -u -p -r1.616 comment.module --- modules/comment/comment.module 10 Jan 2008 15:03:53 -0000 1.616 +++ modules/comment/comment.module 16 Jan 2008 15:38:12 -0000 @@ -310,7 +310,7 @@ function comment_get_recent($number = 10 // Select the $number nodes (visible to the current user) with the most // recent comments. This is efficient due to the index on // last_comment_timestamp. - $result = db_query_range(db_rewrite_sql("SELECT nc.nid FROM {node_comment_statistics} nc WHERE nc.comment_count > 0 ORDER BY nc.last_comment_timestamp DESC", 'nc'), 0, $number); + $result = db_query_range(db_rewrite_sql("SELECT nc.[nid] FROM [{node_comment_statistics}] nc WHERE nc.[comment_count] > 0 ORDER BY nc.[last_comment_timestamp] DESC", 'nc'), 0, $number); $nids = array(); while ($row = db_fetch_object($result)) { @@ -321,7 +321,7 @@ function comment_get_recent($number = 10 if (!empty($nids)) { // From among the comments on the nodes selected in the first query, // find the $number most recent comments. - $result = db_query_range('SELECT c.nid, c.subject, c.cid, c.timestamp FROM {comments} c INNER JOIN {node} n ON n.nid = c.nid WHERE c.nid IN ('. implode(',', $nids) .') AND n.status = 1 AND c.status = %d ORDER BY c.cid DESC', COMMENT_PUBLISHED, 0, $number); + $result = db_query_range('SELECT c.[nid], c.[subject], c.[cid], c.[timestamp] FROM [{comments}] c INNER JOIN [{node}] n ON n.[nid] = c.[nid] WHERE c.[nid] IN ('. implode(',', $nids) .') AND n.[status] = 1 AND c.[status] = %d ORDER BY c.[cid] DESC', COMMENT_PUBLISHED, 0, $number); while ($comment = db_fetch_object($result)) { $comments[] = $comment; } @@ -362,15 +362,15 @@ function comment_new_page_count($num_com // Threaded comments. See the documentation for comment_render(). if ($order == COMMENT_ORDER_NEWEST_FIRST) { // Newest first: find the last thread with new comment - $result = db_query('(SELECT thread FROM {comments} WHERE nid = %d AND status = 0 ORDER BY timestamp DESC LIMIT %d) ORDER BY thread DESC LIMIT 1', $node->nid, $new_replies); + $result = db_query('(SELECT [thread] FROM [{comments}] WHERE [nid] = %d AND [status] = 0 ORDER BY [timestamp] DESC LIMIT %d) ORDER BY [thread] DESC LIMIT 1', $node->nid, $new_replies); $thread = db_result($result); - $result_count = db_query("SELECT COUNT(*) FROM {comments} WHERE nid = %d AND status = 0 AND thread > '". $thread ."'", $node->nid); + $result_count = db_query("SELECT COUNT(*) FROM [{comments}] WHERE [nid] = %d AND [status] = 0 AND [thread] > '". $thread ."'", $node->nid); } else { // Oldest first: find the first thread with new comment - $result = db_query('(SELECT thread FROM {comments} WHERE nid = %d AND status = 0 ORDER BY timestamp DESC LIMIT %d) ORDER BY SUBSTRING(thread, 1, (LENGTH(thread) - 1)) LIMIT 1', $node->nid, $new_replies); + $result = db_query('(SELECT [thread] FROM [{comments}] WHERE [nid] = %d AND [status] = 0 ORDER BY [timestamp] DESC LIMIT %d) ORDER BY '. DB_SUBSTR .'([thread], 1, ('. DB_STRLEN .'([thread]) - 1)) LIMIT 1', $node->nid, $new_replies); $thread = substr(db_result($result), 0, -1); - $result_count = db_query("SELECT COUNT(*) FROM {comments} WHERE nid = %d AND status = 0 AND SUBSTRING(thread, 1, (LENGTH(thread) - 1)) < '". $thread ."'", $node->nid); + $result_count = db_query("SELECT COUNT(*) FROM [{comments}] WHERE [nid] = %d AND [status] = 0 AND ". DB_SUBSTR ."([thread], 1, (". DB_STRLEN ."([thread]) - 1)) < '". $thread ."'", $node->nid); } $count = db_result($result_count); } @@ -593,7 +593,7 @@ function comment_form_alter(&$form, $for function comment_nodeapi(&$node, $op, $arg = 0) { switch ($op) { case 'load': - return db_fetch_array(db_query("SELECT last_comment_timestamp, last_comment_name, comment_count FROM {node_comment_statistics} WHERE nid = %d", $node->nid)); + return db_fetch_array(db_query("SELECT [last_comment_timestamp], [last_comment_name], [comment_count] FROM [{node_comment_statistics}] WHERE [nid] = %d", $node->nid)); break; case 'prepare': @@ -603,24 +603,24 @@ function comment_nodeapi(&$node, $op, $a break; case 'insert': - db_query('INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count) VALUES (%d, %d, NULL, %d, 0)', $node->nid, $node->changed, $node->uid); + db_query('INSERT INTO [{node_comment_statistics}] ([nid], [last_comment_timestamp], [last_comment_name], [last_comment_uid], [comment_count]) VALUES (%d, %d, NULL, %d, 0)', $node->nid, $node->changed, $node->uid); break; case 'delete': - db_query('DELETE FROM {comments} WHERE nid = %d', $node->nid); - db_query('DELETE FROM {node_comment_statistics} WHERE nid = %d', $node->nid); + db_query('DELETE FROM [{comments}] WHERE [nid] = %d', $node->nid); + db_query('DELETE FROM [{node_comment_statistics}] WHERE [nid] = %d', $node->nid); break; case 'update index': $text = ''; - $comments = db_query('SELECT subject, comment, format FROM {comments} WHERE nid = %d AND status = %d', $node->nid, COMMENT_PUBLISHED); + $comments = db_query('SELECT [subject], [comment], [format] FROM [{comments}] WHERE [nid] = %d AND [status] = %d', $node->nid, COMMENT_PUBLISHED); while ($comment = db_fetch_object($comments)) { - $text .= '

    '. check_plain($comment->subject) .'

    '. check_markup($comment->comment, $comment->format, FALSE); + $text .= '

    '. check_plain($comment->subject) .'

    '. check_markup(db_decode_clob($comment->comment), $comment->format, FALSE); } return $text; case 'search result': - $comments = db_result(db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = %d', $node->nid)); + $comments = db_result(db_query('SELECT [comment_count] FROM [{node_comment_statistics}] WHERE [nid] = %d', $node->nid)); return format_plural($comments, '1 comment', '@count comments'); case 'rss item': @@ -638,8 +638,8 @@ function comment_nodeapi(&$node, $op, $a */ function comment_user($type, $edit, &$user, $category = NULL) { if ($type == 'delete') { - db_query('UPDATE {comments} SET uid = 0 WHERE uid = %d', $user->uid); - db_query('UPDATE {node_comment_statistics} SET last_comment_uid = 0 WHERE last_comment_uid = %d', $user->uid); + db_query('UPDATE [{comments}] SET [uid] = 0 WHERE [uid] = %d', $user->uid); + db_query('UPDATE [{node_comment_statistics}] SET [last_comment_uid] = 0 WHERE [last_comment_uid] = %d', $user->uid); } } @@ -698,7 +698,7 @@ function comment_save($edit) { ); if ($edit['cid']) { // Update the comment in the database. - db_query("UPDATE {comments} SET status = %d, timestamp = %d, subject = '%s', comment = '%s', format = %d, uid = %d, name = '%s', mail = '%s', homepage = '%s' WHERE cid = %d", $edit['status'], $edit['timestamp'], $edit['subject'], $edit['comment'], $edit['format'], $edit['uid'], $edit['name'], $edit['mail'], $edit['homepage'], $edit['cid']); + drupal_write_record('comments', $edit, 'cid'); // Allow modules to respond to the updating of a comment. comment_invoke_comment($edit, 'update'); @@ -713,7 +713,7 @@ function comment_save($edit) { if ($edit['pid'] == 0) { // This is a comment with no parent comment (depth 0): we start // by retrieving the maximum thread level. - $max = db_result(db_query('SELECT MAX(thread) FROM {comments} WHERE nid = %d', $edit['nid'])); + $max = db_result(db_query('SELECT MAX([thread]) FROM [{comments}] WHERE [nid] = %d', $edit['nid'])); // Strip the "/" from the end of the thread. $max = rtrim($max, '/'); @@ -732,7 +732,7 @@ function comment_save($edit) { $parent->thread = (string) rtrim((string) $parent->thread, '/'); // Get the max value in _this_ thread. - $max = db_result(db_query("SELECT MAX(thread) FROM {comments} WHERE thread LIKE '%s.%%' AND nid = %d", $parent->thread, $edit['nid'])); + $max = db_result(db_query("SELECT MAX([thread]) FROM [{comments}] WHERE [thread] LIKE %s AND [nid] = %d", $parent->thread .".%", $edit['nid'])); if ($max == '') { // First child of this parent. @@ -758,8 +758,9 @@ function comment_save($edit) { $edit['name'] = $user->name; } - db_query("INSERT INTO {comments} (nid, pid, uid, subject, comment, format, hostname, timestamp, status, thread, name, mail, homepage) VALUES (%d, %d, %d, '%s', '%s', %d, '%s', %d, %d, '%s', '%s', '%s', '%s')", $edit['nid'], $edit['pid'], $edit['uid'], $edit['subject'], $edit['comment'], $edit['format'], ip_address(), $edit['timestamp'], $edit['status'], $thread, $edit['name'], $edit['mail'], $edit['homepage']); - $edit['cid'] = db_last_insert_id('comments', 'cid'); + $edit['hostname'] = ip_address(); + $edit['thread'] = $thread; + drupal_write_record('comments', $edit); // Tell the other modules a new comment has been submitted. comment_invoke_comment($edit, 'insert'); @@ -933,10 +934,10 @@ function comment_render($node, $cid = 0) if ($cid && is_numeric($cid)) { // Single comment view. - $query = 'SELECT c.cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.signature, u.picture, u.data, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d'; + $query = 'SELECT c.[cid], c.[pid], c.[nid], c.[subject], c.[comment], c.[format], c.[timestamp], c.[name], c.[mail], c.[homepage], u.[uid], u.[name] AS [registered_name], u.[signature], u.[picture], u.[data], c.[status] FROM [{comments}] c INNER JOIN [{users}] u ON c.[uid] = u.[uid] WHERE c.[cid] = %d'; $query_args = array($cid); if (!user_access('administer comments')) { - $query .= ' AND c.status = %d'; + $query .= ' AND c.[status] = %d'; $query_args[] = COMMENT_PUBLISHED; } @@ -953,33 +954,33 @@ function comment_render($node, $cid = 0) } else { // Multiple comment view - $query_count = 'SELECT COUNT(*) FROM {comments} WHERE nid = %d'; - $query = 'SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.signature, u.picture, u.data, c.thread, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.nid = %d'; + $query_count = 'SELECT COUNT(*) FROM [{comments}] WHERE [nid] = %d'; + $query = 'SELECT c.[cid] as [cid], c.[pid], c.[nid], c.[subject], c.[comment], c.[format], c.[timestamp], c.[name], c.[mail], c.[homepage], u.[uid], u.[name] AS [registered_name], u.[signature], u.[picture], u.[data], c.[thread], c.[status] FROM [{comments}] c INNER JOIN [{users}] u ON c.[uid] = u.[uid] WHERE c.[nid] = %d'; $query_args = array($nid); if (!user_access('administer comments')) { - $query .= ' AND c.status = %d'; - $query_count .= ' AND status = %d'; + $query .= ' AND c.[status] = %d'; + $query_count .= ' AND [status] = %d'; $query_args[] = COMMENT_PUBLISHED; } if ($order == COMMENT_ORDER_NEWEST_FIRST) { if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) { - $query .= ' ORDER BY c.cid DESC'; + $query .= ' ORDER BY c.[cid] DESC'; } else { - $query .= ' ORDER BY c.thread DESC'; + $query .= ' ORDER BY c.[thread] DESC'; } } else if ($order == COMMENT_ORDER_OLDEST_FIRST) { if ($mode == COMMENT_MODE_FLAT_COLLAPSED || $mode == COMMENT_MODE_FLAT_EXPANDED) { - $query .= ' ORDER BY c.cid'; + $query .= ' ORDER BY c.[cid]'; } else { // See comment above. Analysis reveals that this doesn't cost too // much. It scales much much better than having the whole comment // structure. - $query .= ' ORDER BY SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))'; + $query .= ' ORDER BY '. DB_SUBSTR .'(c.[thread], 1, ('. DB_STRLEN .'(c.[thread]) - 1))'; } } $query = db_rewrite_sql($query, 'c', 'cid'); @@ -1066,20 +1067,20 @@ function comment_render($node, $cid = 0) function comment_operations($action = NULL) { if ($action == 'publish') { $operations = array( - 'publish' => array(t('Publish the selected comments'), 'UPDATE {comments} SET status = '. COMMENT_PUBLISHED .' WHERE cid = %d'), + 'publish' => array(t('Publish the selected comments'), 'UPDATE [{comments}] SET [status] = '. COMMENT_PUBLISHED .' WHERE [cid] = %d'), 'delete' => array(t('Delete the selected comments'), '') ); } else if ($action == 'unpublish') { $operations = array( - 'unpublish' => array(t('Unpublish the selected comments'), 'UPDATE {comments} SET status = '. COMMENT_NOT_PUBLISHED .' WHERE cid = %d'), + 'unpublish' => array(t('Unpublish the selected comments'), 'UPDATE [{comments}] SET [status] = '. COMMENT_NOT_PUBLISHED .' WHERE [cid] = %d'), 'delete' => array(t('Delete the selected comments'), '') ); } else { $operations = array( - 'publish' => array(t('Publish the selected comments'), 'UPDATE {comments} SET status = '. COMMENT_PUBLISHED .' WHERE cid = %d'), - 'unpublish' => array(t('Unpublish the selected comments'), 'UPDATE {comments} SET status = '. COMMENT_NOT_PUBLISHED .' WHERE cid = %d'), + 'publish' => array(t('Publish the selected comments'), 'UPDATE [{comments}] SET [status] = '. COMMENT_PUBLISHED .' WHERE [cid] = %d'), + 'unpublish' => array(t('Unpublish the selected comments'), 'UPDATE [{comments}] SET [status] = '. COMMENT_NOT_PUBLISHED .' WHERE [cid] = %d'), 'delete' => array(t('Delete the selected comments'), '') ); } @@ -1099,7 +1100,7 @@ function comment_operations($action = NU * The comment object. */ function _comment_load($cid) { - return db_fetch_object(db_query('SELECT * FROM {comments} WHERE cid = %d', $cid)); + return db_fetch_object(db_query('SELECT * FROM [{comments}] WHERE [cid] = %d', $cid)); } /** @@ -1114,7 +1115,7 @@ function comment_num_all($nid) { static $cache; if (!isset($cache[$nid])) { - $cache[$nid] = db_result(db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = %d', $nid)); + $cache[$nid] = db_result(db_query('SELECT [comment_count] FROM [{node_comment_statistics}] WHERE [nid] = %d', $nid)); } return $cache[$nid]; } @@ -1131,7 +1132,7 @@ function comment_num_replies($pid) { static $cache; if (!isset($cache[$pid])) { - $cache[$pid] = db_result(db_query('SELECT COUNT(cid) FROM {comments} WHERE pid = %d AND status = %d', $pid, COMMENT_PUBLISHED)); + $cache[$pid] = db_result(db_query('SELECT COUNT([cid]) FROM [{comments}] WHERE [pid] = %d AND [status] = %d', $pid, COMMENT_PUBLISHED)); } return $cache[$pid]; @@ -1158,7 +1159,7 @@ function comment_num_new($nid, $timestam $timestamp = ($timestamp > NODE_NEW_LIMIT ? $timestamp : NODE_NEW_LIMIT); // Use the timestamp to retrieve the number of new comments. - $result = db_result(db_query('SELECT COUNT(c.cid) FROM {node} n INNER JOIN {comments} c ON n.nid = c.nid WHERE n.nid = %d AND timestamp > %d AND c.status = %d', $nid, $timestamp, COMMENT_PUBLISHED)); + $result = db_result(db_query('SELECT COUNT(c.[cid]) FROM [{node}] n INNER JOIN [{comments}] c ON n.[nid] = c.[nid] WHERE n.[nid] = %d AND [timestamp] > %d AND c.[status] = %d', $nid, $timestamp, COMMENT_PUBLISHED)); return $result; } @@ -1197,7 +1198,7 @@ function comment_validate($edit) { $node = node_load($edit['nid']); if (variable_get('comment_anonymous_'. $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) > COMMENT_ANONYMOUS_MAYNOT_CONTACT) { if ($edit['name']) { - $taken = db_result(db_query("SELECT COUNT(uid) FROM {users} WHERE LOWER(name) = '%s'", $edit['name'])); + $taken = db_result(db_query("SELECT COUNT([uid]) FROM [{users}] WHERE LOWER([name]) = %s", $edit['name'])); if ($taken != 0) { form_set_error('name', t('The name you used belongs to a registered user.')); @@ -1463,7 +1464,7 @@ function comment_form_add_preview($form, $output = ''; if ($edit['pid']) { - $comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = %d', $edit['pid'], COMMENT_PUBLISHED)); + $comment = db_fetch_object(db_query('SELECT c.*, u.[uid], u.[name] AS [registered_name], u.[signature], u.[picture], u.[data] FROM [{comments}] c INNER JOIN [{users}] u ON c.[uid] = u.[uid] WHERE c.[cid] = %d AND c.[status] = %d', $edit['pid'], COMMENT_PUBLISHED)); $comment = drupal_unpack($comment); $comment->name = $comment->uid ? $comment->registered_name : $comment->name; $output .= theme('comment_view', $comment, $node); @@ -1571,7 +1572,7 @@ function theme_comment_view($comment, $n // Switch to folded/unfolded view of the comment if ($visible) { - $comment->comment = check_markup($comment->comment, $comment->format, FALSE); + $comment->comment = check_markup(db_decode_clob($comment->comment), $comment->format, FALSE); // Comment API hook comment_invoke_comment($comment, 'view'); @@ -1923,18 +1924,18 @@ function _comment_get_display_setting($s * - comment_count: the total number of approved/published comments on this node. */ function _comment_update_node_statistics($nid) { - $count = db_result(db_query('SELECT COUNT(cid) FROM {comments} WHERE nid = %d AND status = %d', $nid, COMMENT_PUBLISHED)); + $count = db_result(db_query('SELECT COUNT([cid]) FROM [{comments}] WHERE [nid] = %d AND [status] = %d', $nid, COMMENT_PUBLISHED)); // comments exist if ($count > 0) { - $last_reply = db_fetch_object(db_query_range('SELECT cid, name, timestamp, uid FROM {comments} WHERE nid = %d AND status = %d ORDER BY cid DESC', $nid, COMMENT_PUBLISHED, 0, 1)); - db_query("UPDATE {node_comment_statistics} SET comment_count = %d, last_comment_timestamp = %d, last_comment_name = '%s', last_comment_uid = %d WHERE nid = %d", $count, $last_reply->timestamp, $last_reply->uid ? '' : $last_reply->name, $last_reply->uid, $nid); + $last_reply = db_fetch_object(db_query_range('SELECT [cid], [name], [timestamp], [uid] FROM [{comments}] WHERE [nid] = %d AND [status] = %d ORDER BY [cid] DESC', $nid, COMMENT_PUBLISHED, 0, 1)); + db_query("UPDATE [{node_comment_statistics}] SET [comment_count] = %d, [last_comment_timestamp] = %d, [last_comment_name] = %s, [last_comment_uid] = %d WHERE [nid] = %d", $count, $last_reply->timestamp, $last_reply->uid ? '' : $last_reply->name, $last_reply->uid, $nid); } // no comments else { - $node = db_fetch_object(db_query("SELECT uid, created FROM {node} WHERE nid = %d", $nid)); - db_query("UPDATE {node_comment_statistics} SET comment_count = 0, last_comment_timestamp = %d, last_comment_name = '', last_comment_uid = %d WHERE nid = %d", $node->created, $node->uid, $nid); + $node = db_fetch_object(db_query("SELECT [uid], [created] FROM [{node}] WHERE [nid] = %d", $nid)); + db_query("UPDATE [{node_comment_statistics}] SET [comment_count] = %d, [last_comment_timestamp] = %d, [last_comment_name] = %s, [last_comment_uid] = %d WHERE [nid] = %d", 0, $node->created, '', $node->uid, $nid); } } @@ -2052,9 +2053,9 @@ function comment_unpublish_action($comme } else { $cid = $context['cid']; - $subject = db_result(db_query("SELECT subject FROM {comments} WHERE cid = %d", $cid)); + $subject = db_result(db_query("SELECT [subject] FROM [{comments}] WHERE [cid] = %d", $cid)); } - db_query('UPDATE {comments} SET status = %d WHERE cid = %d', COMMENT_NOT_PUBLISHED, $cid); + db_query('UPDATE [{comments}] SET [status] = %d WHERE [cid] = %d', COMMENT_NOT_PUBLISHED, $cid); watchdog('action', 'Unpublished comment %subject.', array('%subject' => $subject)); } @@ -2093,8 +2094,8 @@ function comment_unpublish_by_keyword_ac */ function comment_unpublish_by_keyword_action($comment, $context) { foreach ($context['keywords'] as $keyword) { - if (strstr($comment->comment, $keyword) || strstr($comment->subject, $keyword)) { - db_query('UPDATE {comments} SET status = %d WHERE cid = %d', COMMENT_NOT_PUBLISHED, $comment->cid); + if (strstr(db_decode_clob($comment->comment), $keyword) || strstr($comment->subject, $keyword)) { + db_query('UPDATE [{comments}] SET [status] = %d WHERE [cid] = %d', COMMENT_NOT_PUBLISHED, $comment->cid); watchdog('action', 'Unpublished comment %subject.', array('%subject' => $comment->subject)); break; } Index: modules/comment/comment.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.pages.inc,v retrieving revision 1.2 diff -u -p -r1.2 comment.pages.inc --- modules/comment/comment.pages.inc 16 Dec 2007 21:01:44 -0000 1.2 +++ modules/comment/comment.pages.inc 16 Jan 2008 15:38:12 -0000 @@ -16,7 +16,7 @@ function comment_edit($cid) { global $user; - $comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d', $cid)); + $comment = db_fetch_object(db_query('SELECT c.*, u.[uid], u.[name] AS [registered_name], u.[data] FROM [{comments}] c INNER JOIN [{users}] u ON c.[uid] = u.[uid] WHERE c.[cid] = %d', $cid)); $comment = drupal_unpack($comment); $comment->name = $comment->uid ? $comment->registered_name : $comment->name; if (comment_access('edit', $comment)) { @@ -70,7 +70,7 @@ function comment_reply($node, $pid = NUL // $pid indicates that this is a reply to a comment. if ($pid) { // load the comment whose cid = $pid - if ($comment = db_fetch_object(db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = %d', $pid, COMMENT_PUBLISHED))) { + if ($comment = db_fetch_object(db_query('SELECT c.*, u.[uid], u.[name] AS [registered_name], u.[signature], u.[picture], u.[data] FROM [{comments}] c INNER JOIN [{users}] u ON c.[uid] = u.[uid] WHERE c.[cid] = %d AND c.[status] = %d', $pid, COMMENT_PUBLISHED))) { // If that comment exists, make sure that the current comment and the parent comment both // belong to the same parent node. if ($comment->nid != $node->nid) { Index: modules/contact/contact.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/contact/contact.admin.inc,v retrieving revision 1.3 diff -u -p -r1.3 contact.admin.inc --- modules/contact/contact.admin.inc 9 Nov 2007 07:55:13 -0000 1.3 +++ modules/contact/contact.admin.inc 16 Jan 2008 15:38:12 -0000 @@ -10,7 +10,7 @@ * Categories/list tab. */ function contact_admin_categories() { - $result = db_query('SELECT cid, category, recipients, selected FROM {contact} ORDER BY weight, category'); + $result = db_query('SELECT [cid], [category], [recipients], [selected] FROM [{contact}] ORDER BY [weight], [category]'); $rows = array(); while ($category = db_fetch_object($result)) { $rows[] = array($category->category, $category->recipients, ($category->selected ? t('Yes') : t('No')), l(t('edit'), 'admin/build/contact/edit/'. $category->cid), l(t('delete'), 'admin/build/contact/delete/'. $category->cid)); @@ -101,7 +101,7 @@ function contact_admin_edit_validate($fo function contact_admin_edit_submit($form, &$form_state) { if ($form_state['values']['selected']) { // Unselect all other contact categories. - db_query('UPDATE {contact} SET selected = 0'); + db_query('UPDATE [{contact}] SET [selected] = 0'); } $recipients = explode(',', $form_state['values']['recipients']); foreach ($recipients as $key => $recipient) { @@ -143,7 +143,7 @@ function contact_admin_delete(&$form_sta */ function contact_admin_delete_submit($form, &$form_state) { $contact = $form_state['values']['contact']; - db_query("DELETE FROM {contact} WHERE cid = %d", $contact['cid']); + db_query("DELETE FROM [{contact}] WHERE [cid] = %d", $contact['cid']); drupal_set_message(t('Category %category has been deleted.', array('%category' => $contact['category']))); watchdog('mail', 'Contact form: category %category deleted.', array('%category' => $contact['category']), WATCHDOG_NOTICE); Index: modules/contact/contact.install =================================================================== RCS file: /cvs/drupal/drupal/modules/contact/contact.install,v retrieving revision 1.10 diff -u -p -r1.10 contact.install --- modules/contact/contact.install 18 Dec 2007 12:59:21 -0000 1.10 +++ modules/contact/contact.install 16 Jan 2008 15:38:12 -0000 @@ -44,12 +44,14 @@ function contact_schema() { 'recipients' => array( 'type' => 'text', 'not null' => TRUE, + 'default' => '', 'size' => 'big', 'description' => t('Comma-separated list of recipient e-mail addresses.'), ), 'reply' => array( - 'type' => 'text', + 'type' => 'clob', 'not null' => TRUE, + 'default' => '', 'size' => 'big', 'description' => t('Text of the auto-reply message.'), ), Index: modules/contact/contact.module =================================================================== RCS file: /cvs/drupal/drupal/modules/contact/contact.module,v retrieving revision 1.102 diff -u -p -r1.102 contact.module --- modules/contact/contact.module 19 Dec 2007 17:42:13 -0000 1.102 +++ modules/contact/contact.module 16 Jan 2008 15:38:12 -0000 @@ -125,7 +125,7 @@ function _contact_user_tab_access($accou * Load the data for a single contact category. */ function contact_load($cid) { - $contact = db_fetch_array(db_query("SELECT * FROM {contact} WHERE cid = %d", $cid)); + $contact = db_fetch_array(db_query("SELECT * FROM [{contact}] WHERE [cid] = %d", $cid)); return empty($contact) ? FALSE : $contact; } @@ -172,7 +172,7 @@ function contact_mail($key, &$message, $ case 'page_autoreply': $contact = $params['contact']; $message['subject'] .= t('[!category] !subject', array('!category' => $contact['category'], '!subject' => $params['subject']), $language->language); - $message['body'][] = $contact['reply']; + $message['body'][] = db_decode_clob($contact['reply']); break; case 'user_mail': case 'user_copy': Index: modules/contact/contact.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/contact/contact.pages.inc,v retrieving revision 1.5 diff -u -p -r1.5 contact.pages.inc --- modules/contact/contact.pages.inc 10 Dec 2007 10:38:00 -0000 1.5 +++ modules/contact/contact.pages.inc 16 Jan 2008 15:38:12 -0000 @@ -28,7 +28,7 @@ function contact_mail_page() { $form = $categories = array(); - $result = db_query('SELECT cid, category, selected FROM {contact} ORDER BY weight, category'); + $result = db_query('SELECT [cid], [category], [selected] FROM [{contact}] ORDER BY [weight], [category]'); while ($category = db_fetch_object($result)) { $categories[$category->cid] = $category->category; if ($category->selected) { @@ -135,7 +135,7 @@ function contact_mail_page_submit($form, } // Send an auto-reply if necessary using the current language. - if ($contact['reply']) { + if (db_decode_clob($contact['reply'])) { drupal_mail('contact', 'page_autoreply', $from, $language, $values, $contact['recipients']); } Index: modules/dblog/dblog.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/dblog/dblog.admin.inc,v retrieving revision 1.6 diff -u -p -r1.6 dblog.admin.inc --- modules/dblog/dblog.admin.inc 8 Jan 2008 10:35:41 -0000 1.6 +++ modules/dblog/dblog.admin.inc 16 Jan 2008 15:38:12 -0000 @@ -45,14 +45,14 @@ function dblog_overview() { $header = array( ' ', - array('data' => t('Type'), 'field' => 'w.type'), - array('data' => t('Date'), 'field' => 'w.wid', 'sort' => 'desc'), + array('data' => t('Type'), 'field' => 'w.[type]'), + array('data' => t('Date'), 'field' => 'w.[wid]', 'sort' => 'desc'), t('Message'), - array('data' => t('User'), 'field' => 'u.name'), + array('data' => t('User'), 'field' => 'u.[name]'), array('data' => t('Operations')), ); - $sql = "SELECT w.wid, w.uid, w.severity, w.type, w.timestamp, w.message, w.variables, w.link, u.name FROM {watchdog} w INNER JOIN {users} u ON w.uid = u.uid"; + $sql = "SELECT w.[wid], w.[uid], w.[severity], w.[type], w.[timestamp], w.[message], w.[variables], w.[link], u.[name] FROM [{watchdog}] w INNER JOIN [{users}] u ON w.[uid] = u.[uid]"; $tablesort = tablesort_sql($header); if (!empty($filter['where'])) { $result = pager_query($sql ." WHERE ". $filter['where'] . $tablesort, 50, 0, NULL, $filter['args']); @@ -94,11 +94,11 @@ function dblog_overview() { function dblog_top($type) { $header = array( - array('data' => t('Count'), 'field' => 'count', 'sort' => 'desc'), - array('data' => t('Message'), 'field' => 'message') + array('data' => t('Count'), 'field' => '[count]', 'sort' => 'desc'), + array('data' => t('Message'), 'field' => '[message]') ); - $result = pager_query("SELECT COUNT(wid) AS count, message, variables FROM {watchdog} WHERE type = '%s' GROUP BY message, variables ". tablesort_sql($header), 30, 0, "SELECT COUNT(DISTINCT(message)) FROM {watchdog} WHERE type = '%s'", $type); + $result = pager_query("SELECT COUNT([wid]) AS [count], [message], [variables] FROM [{watchdog}] WHERE [type] = %s GROUP BY [message], [variables] ". tablesort_sql($header), 30, 0, "SELECT COUNT(DISTINCT([message])) FROM [{watchdog}] WHERE [type] = %s", $type); $rows = array(); while ($dblog = db_fetch_object($result)) { @@ -121,7 +121,7 @@ function dblog_top($type) { function dblog_event($id) { $severity = watchdog_severity_levels(); $output = ''; - $result = db_query('SELECT w.*, u.name, u.uid FROM {watchdog} w INNER JOIN {users} u ON w.uid = u.uid WHERE w.wid = %d', $id); + $result = db_query('SELECT w.*, u.[name], u.[uid] FROM [{watchdog}] w INNER JOIN [{users}] u ON w.[uid] = u.[uid] WHERE w.[wid] = %d', $id); if ($dblog = db_fetch_object($result)) { $rows = array( array( @@ -211,7 +211,7 @@ function dblog_filters() { if (!empty($types)) { $filters['type'] = array( 'title' => t('Type'), - 'where' => "w.type = '%s'", + 'where' => "w.type = %s", 'options' => $types, ); } Index: modules/dblog/dblog.install =================================================================== RCS file: /cvs/drupal/drupal/modules/dblog/dblog.install,v retrieving revision 1.6 diff -u -p -r1.6 dblog.install --- modules/dblog/dblog.install 4 Nov 2007 14:33:06 -0000 1.6 +++ modules/dblog/dblog.install 16 Jan 2008 15:38:12 -0000 @@ -45,12 +45,14 @@ function dblog_schema() { 'message' => array( 'type' => 'text', 'not null' => TRUE, + 'default' => '', 'size' => 'big', 'description' => t('Text of log message to be passed into the t() function.'), ), 'variables' => array( 'type' => 'text', 'not null' => TRUE, + 'default' => '', 'size' => 'big', 'description' => t('Serialized array of variables that match the message string and that is passed into the t() function.'), ), @@ -72,6 +74,7 @@ function dblog_schema() { 'location' => array( 'type' => 'text', 'not null' => TRUE, + 'default' => '', 'description' => t('URL of the origin of the event.'), ), 'referer' => array( Index: modules/dblog/dblog.module =================================================================== RCS file: /cvs/drupal/drupal/modules/dblog/dblog.module,v retrieving revision 1.21 diff -u -p -r1.21 dblog.module --- modules/dblog/dblog.module 8 Jan 2008 10:35:41 -0000 1.21 +++ modules/dblog/dblog.module 16 Jan 2008 15:38:12 -0000 @@ -97,8 +97,8 @@ function dblog_init() { */ function dblog_cron() { // Cleanup the watchdog table - $max = db_result(db_query('SELECT MAX(wid) FROM {watchdog}')); - db_query('DELETE FROM {watchdog} WHERE wid < %d', $max - variable_get('dblog_row_limit', 1000)); + $max = db_result(db_query('SELECT MAX([wid]) FROM [{watchdog}]')); + db_query('DELETE FROM [{watchdog}] WHERE [wid] < %d', $max - variable_get('dblog_row_limit', 1000)); } /** @@ -106,14 +106,14 @@ function dblog_cron() { */ function dblog_user($op, &$edit, &$user) { if ($op == 'delete') { - db_query('UPDATE {watchdog} SET uid = 0 WHERE uid = %d', $user->uid); + db_query('UPDATE [{watchdog}] SET [uid] = 0 WHERE [uid] = %d', $user->uid); } } function _dblog_get_message_types() { $types = array(); - $result = db_query('SELECT DISTINCT(type) FROM {watchdog} ORDER BY type'); + $result = db_query('SELECT DISTINCT([type]) FROM [{watchdog}] ORDER BY [type]'); while ($object = db_fetch_object($result)) { $types[] = $object->type; } @@ -123,20 +123,11 @@ function _dblog_get_message_types() { function dblog_watchdog($log = array()) { $current_db = db_set_active(); - db_query("INSERT INTO {watchdog} - (uid, type, message, variables, severity, link, location, referer, hostname, timestamp) - VALUES - (%d, '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', %d)", - $log['user']->uid, - $log['type'], - $log['message'], - serialize($log['variables']), - $log['severity'], - $log['link'], - $log['request_uri'], - $log['referer'], - $log['ip'], - $log['timestamp']); + $log['uid'] = $log['user']->uid; + $log['variables'] = serialize($log['variables']); + $log['location'] = $log['request_uri']; + $log['hostname'] = $log['ip']; + drupal_write_record('watchdog', $log); if ($current_db) { db_set_active($current_db); Index: modules/filter/filter.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/filter/filter.admin.inc,v retrieving revision 1.8 diff -u -p -r1.8 filter.admin.inc --- modules/filter/filter.admin.inc 8 Jan 2008 10:35:41 -0000 1.8 +++ modules/filter/filter.admin.inc 16 Jan 2008 15:38:12 -0000 @@ -163,7 +163,7 @@ function filter_admin_format_form(&$form function filter_admin_format_form_validate($form, &$form_state) { if (!isset($form_state['values']['format'])) { $name = trim($form_state['values']['name']); - $result = db_fetch_object(db_query("SELECT format FROM {filter_formats} WHERE name='%s'", $name)); + $result = db_fetch_object(db_query("SELECT [format] FROM [{filter_formats}] WHERE [name] = %s", $name)); if ($result) { form_set_error('name', t('Filter format names need to be unique. A format named %name already exists.', array('%name' => $name))); } @@ -182,21 +182,21 @@ function filter_admin_format_form_submit // Add a new filter format. if (!$format) { $new = TRUE; - db_query("INSERT INTO {filter_formats} (name) VALUES ('%s')", $name); - $format = db_result(db_query("SELECT MAX(format) AS format FROM {filter_formats}")); + db_query("INSERT INTO [{filter_formats}] ([name]) VALUES (%s)", $name); + $format = db_result(db_query("SELECT MAX([format]) AS [format] FROM [{filter_formats}]")); drupal_set_message(t('Added input format %format.', array('%format' => $name))); } else { drupal_set_message(t('The input format settings have been updated.')); } - db_query("DELETE FROM {filters} WHERE format = %d", $format); + db_query("DELETE FROM [{filters}] WHERE [format] = %d", $format); foreach ($form_state['values']['filters'] as $id => $checked) { if ($checked) { list($module, $delta) = explode('/', $id); // Add new filters to the bottom. $weight = isset($current[$id]->weight) ? $current[$id]->weight : 10; - db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES (%d, '%s', %d, %d)", $format, $module, $delta, $weight); + db_query("INSERT INTO [{filters}] ([format], [module], [delta], [weight]) VALUES (%d, %s, %d, %d)", $format, $module, $delta, $weight); // Check if there are any 'no cache' filters. $cache &= !module_invoke($module, 'filter', 'no cache', $delta); @@ -221,7 +221,7 @@ function filter_admin_format_form_submit $roles = ','. implode(',', $roles) .','; } - db_query("UPDATE {filter_formats} SET cache = %d, name='%s', roles = '%s' WHERE format = %d", $cache, $name, $roles, $format); + db_query("UPDATE [{filter_formats}] SET [cache] = %d, [name] = %s, [roles] = %s WHERE [format] = %d", $cache, $name, $roles, $format); cache_clear_all($format .':', 'cache_filter', TRUE); @@ -242,7 +242,7 @@ function filter_admin_format_form_submit */ function filter_admin_delete() { $format = arg(4); - $format = db_fetch_object(db_query('SELECT * FROM {filter_formats} WHERE format = %d', $format)); + $format = db_fetch_object(db_query('SELECT * FROM [{filter_formats}] WHERE [format] = %d', $format)); if ($format) { if ($format->format != variable_get('filter_default_format', 1)) { @@ -265,14 +265,14 @@ function filter_admin_delete() { * Process filter delete form submission. */ function filter_admin_delete_submit($form, &$form_state) { - db_query("DELETE FROM {filter_formats} WHERE format = %d", $form_state['values']['format']); - db_query("DELETE FROM {filters} WHERE format = %d", $form_state['values']['format']); + db_query("DELETE FROM [{filter_formats}] WHERE [format] = %d", $form_state['values']['format']); + db_query("DELETE FROM [{filters}] WHERE [format] = %d", $form_state['values']['format']); $default = variable_get('filter_default_format', 1); // Replace existing instances of the deleted format with the default format. - db_query("UPDATE {node_revisions} SET format = %d WHERE format = %d", $default, $form_state['values']['format']); - db_query("UPDATE {comments} SET format = %d WHERE format = %d", $default, $form_state['values']['format']); - db_query("UPDATE {boxes} SET format = %d WHERE format = %d", $default, $form_state['values']['format']); + db_query("UPDATE [{node_revisions}] SET [format] = %d WHERE [format] = %d", $default, $form_state['values']['format']); + db_query("UPDATE [{comments}] SET [format] = %d WHERE [format] = %d", $default, $form_state['values']['format']); + db_query("UPDATE [{boxes}] SET [format] = %d WHERE [format] = %d", $default, $form_state['values']['format']); cache_clear_all($form_state['values']['format'] .':', 'cache_filter', TRUE); drupal_set_message(t('Deleted input format %format.', array('%format' => $form_state['values']['name']))); @@ -386,7 +386,7 @@ function theme_filter_admin_order($form) function filter_admin_order_submit($form, &$form_state) { foreach ($form_state['values']['weights'] as $id => $weight) { list($module, $delta) = explode('/', $id); - db_query("UPDATE {filters} SET weight = %d WHERE format = %d AND module = '%s' AND delta = %d", $weight, $form_state['values']['format'], $module, $delta); + db_query("UPDATE [{filters}] SET [weight] = %d WHERE [format] = %d AND [module] = %s AND [delta] = %d", $weight, $form_state['values']['format'], $module, $delta); } drupal_set_message(t('The filter ordering has been saved.')); Index: modules/filter/filter.module =================================================================== RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v retrieving revision 1.202 diff -u -p -r1.202 filter.module --- modules/filter/filter.module 10 Jan 2008 22:47:17 -0000 1.202 +++ modules/filter/filter.module 16 Jan 2008 15:38:12 -0000 @@ -294,17 +294,17 @@ function filter_formats($index = NULL) { if (!isset($formats)) { $formats = array(); - $query = 'SELECT * FROM {filter_formats}'; + $query = 'SELECT * FROM [{filter_formats}]'; // Build query for selecting the format(s) based on the user's roles. $args = array(); if (!$all) { $where = array(); foreach ($user->roles as $rid => $role) { - $where[] = "roles LIKE '%%,%d,%%'"; - $args[] = $rid; + $where[] = "[roles] LIKE %s"; + $args[] = '%,'. (int) $rid .',%'; } - $query .= ' WHERE '. implode(' OR ', $where) .' OR format = %d'; + $query .= ' WHERE '. implode(' OR ', $where) .' OR [format] = %d'; $args[] = variable_get('filter_default_format', 1); } @@ -359,7 +359,7 @@ function filter_format_allowcache($forma static $cache = array(); $format = filter_resolve_format($format); if (!isset($cache[$format])) { - $cache[$format] = db_result(db_query('SELECT cache FROM {filter_formats} WHERE format = %d', $format)); + $cache[$format] = db_result(db_query('SELECT [cache] FROM [{filter_formats}] WHERE [format] = %d', $format)); } return $cache[$format]; } @@ -372,7 +372,7 @@ function filter_list_format($format) { if (!isset($filters[$format])) { $filters[$format] = array(); - $result = db_query("SELECT * FROM {filters} WHERE format = %d ORDER BY weight, module, delta", $format); + $result = db_query("SELECT * FROM [{filters}] WHERE [format] = %d ORDER BY [weight], [module], [delta]", $format); while ($filter = db_fetch_object($result)) { $list = module_invoke($filter->module, 'filter', 'list'); if (isset($list) && is_array($list) && isset($list[$filter->delta])) { @@ -554,7 +554,7 @@ function _filter_tips($format, $long = F $formats = filter_formats(); } else { - $formats = array(db_fetch_object(db_query("SELECT * FROM {filter_formats} WHERE format = %d", $format))); + $formats = array(db_fetch_object(db_query("SELECT * FROM [{filter_formats}] WHERE [format] = %d", $format))); } $tips = array(); Index: modules/forum/forum.install =================================================================== RCS file: /cvs/drupal/drupal/modules/forum/forum.install,v retrieving revision 1.16 diff -u -p -r1.16 forum.install --- modules/forum/forum.install 31 Dec 2007 16:58:34 -0000 1.16 +++ modules/forum/forum.install 16 Jan 2008 15:38:12 -0000 @@ -50,8 +50,8 @@ function forum_uninstall() { $vid = variable_get('forum_nav_vocabulary', ''); taxonomy_del_vocabulary($vid); - db_query("DELETE FROM {node} WHERE type = 'forum'"); - db_query('DROP TABLE {forum}'); + db_query("DELETE FROM [{node}] WHERE [type] = 'forum'"); + db_query('DROP TABLE [{forum}]'); variable_del('forum_containers'); variable_del('forum_nav_vocabulary'); variable_del('forum_hot_topic'); Index: modules/forum/forum.module =================================================================== RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v retrieving revision 1.445 diff -u -p -r1.445 forum.module --- modules/forum/forum.module 9 Jan 2008 21:38:57 -0000 1.445 +++ modules/forum/forum.module 16 Jan 2008 15:38:12 -0000 @@ -74,7 +74,7 @@ function forum_theme() { * An associative array containing the term data or FALSE if the term cannot be loaded, or is not part of the forum vocabulary. */ function forum_term_load($tid) { - $result = db_query(db_rewrite_sql('SELECT t.tid, t.vid, t.name, t.description, t.weight FROM {term_data} t WHERE t.tid = %d AND t.vid = %d', 't', 'tid'), $tid, variable_get('forum_nav_vocabulary', '')); + $result = db_query(db_rewrite_sql('SELECT t.[tid], t.[vid], t.[name], t.[description], t.[weight] FROM [{term_data}] t WHERE t.[tid] = %d AND t.[vid] = %d', 't', 'tid'), $tid, variable_get('forum_nav_vocabulary', '')); return db_fetch_array($result); } @@ -224,7 +224,7 @@ function forum_nodeapi(&$node, $op, $tea $vocabulary = $vid; $containers = variable_get('forum_containers', array()); foreach ($node->taxonomy as $term) { - if (db_result(db_query('SELECT COUNT(*) FROM {term_data} WHERE tid = %d AND vid = %d', $term, $vocabulary))) { + if (db_result(db_query('SELECT COUNT(*) FROM [{term_data}] WHERE [tid] = %d AND [vid] = %d', $term, $vocabulary))) { if (in_array($term, $containers)) { $term = taxonomy_get_term($term); form_set_error('taxonomy', t('The item %forum is only a container for forums. Please select one of the forums below it.', array('%forum' => $term->name))); @@ -249,7 +249,7 @@ function forum_nodeapi(&$node, $op, $tea $node->tid = $term_id; } } - $old_tid = db_result(db_query_range("SELECT t.tid FROM {term_node} t INNER JOIN {node} n ON t.vid = n.vid WHERE n.nid = %d ORDER BY t.vid DESC", $node->nid, 0, 1)); + $old_tid = db_result(db_query_range("SELECT t.[tid] FROM [{term_node}] t INNER JOIN [{node}] n ON t.[vid] = n.[vid] WHERE n.[nid] = %d ORDER BY t.[vid] DESC", $node->nid, 0, 1)); if ($old_tid && isset($node->tid) && ($node->tid != $old_tid) && !empty($node->shadow)) { // A shadow copy needs to be created. Retain new term and add old term. $node->taxonomy[] = $old_tid; @@ -258,13 +258,13 @@ function forum_nodeapi(&$node, $op, $tea break; case 'update': - if (empty($node->revision) && db_result(db_query('SELECT tid FROM {forum} WHERE nid=%d', $node->nid))) { + if (empty($node->revision) && db_result(db_query('SELECT [tid] FROM [{forum}] WHERE [nid] = %d', $node->nid))) { if (!empty($node->tid)) { - db_query('UPDATE {forum} SET tid = %d WHERE vid = %d', $node->tid, $node->vid); + db_query('UPDATE [{forum}] SET [tid] = %d WHERE [vid] = %d', $node->tid, $node->vid); } // The node is removed from the forum. else { - db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid); + db_query('DELETE FROM [{forum}] WHERE [nid] = %d', $node->nid); } break; } @@ -272,16 +272,16 @@ function forum_nodeapi(&$node, $op, $tea case 'insert': if (!empty($node->tid)) { - db_query('INSERT INTO {forum} (tid, vid, nid) VALUES (%d, %d, %d)', $node->tid, $node->vid, $node->nid); + db_query('INSERT INTO [{forum}] ([tid], [vid], [nid]) VALUES (%d, %d, %d)', $node->tid, $node->vid, $node->nid); } break; case 'delete': - db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid); + db_query('DELETE FROM [{forum}] WHERE [nid] = %d', $node->nid); break; case 'load': - return db_fetch_array(db_query('SELECT tid AS forum_tid FROM {forum} WHERE vid = %d', $node->vid)); + return db_fetch_array(db_query('SELECT [tid] AS [forum_tid] FROM [{forum}] WHERE [vid] = %d', $node->vid)); } return; @@ -329,7 +329,7 @@ function forum_taxonomy($op, $type, $ter if ($op == 'delete' && $term['vid'] == variable_get('forum_nav_vocabulary', '')) { switch ($type) { case 'term': - $results = db_query('SELECT tn.nid FROM {term_node} tn WHERE tn.tid = %d', $term['tid']); + $results = db_query('SELECT tn.[nid] FROM [{term_node}] tn WHERE tn.[tid] = %d', $term['tid']); while ($node = db_fetch_object($results)) { // node_delete will also remove any association with non-forum vocabularies. node_delete($node->nid); @@ -386,7 +386,7 @@ function forum_form_alter(&$form, $form_ * Implementation of hook_load(). */ function forum_load($node) { - $forum = db_fetch_object(db_query('SELECT * FROM {term_node} WHERE vid = %d', $node->vid)); + $forum = db_fetch_object(db_query('SELECT * FROM [{term_node}] WHERE [vid] = %d', $node->vid)); return $forum; } @@ -417,14 +417,14 @@ function forum_block($op = 'list', $delt switch ($delta) { case 0: $title = t('Active forum topics'); - $sql = db_rewrite_sql("SELECT n.nid, n.title, l.comment_count, l.last_comment_timestamp FROM {node} n INNER JOIN {term_node} tn ON tn.nid = n.nid INNER JOIN {term_data} td ON td.tid = tn.tid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 AND td.vid = %d ORDER BY l.last_comment_timestamp DESC"); + $sql = db_rewrite_sql("SELECT n.[nid], n.[title], l.[comment_count], l.[last_comment_timestamp] FROM [{node}] n INNER JOIN [{term_node}] tn ON tn.[nid] = n.[nid] INNER JOIN [{term_data}] td ON td.[tid] = tn.[tid] INNER JOIN [{node_comment_statistics}] l ON n.[nid] = l.[nid] WHERE n.[status] = 1 AND td.[vid] = %d ORDER BY l.[last_comment_timestamp] DESC"); $result = db_query_range($sql, variable_get('forum_nav_vocabulary', ''), 0, variable_get('forum_block_num_0', '5')); $content = node_title_list($result); break; case 1: $title = t('New forum topics'); - $sql = db_rewrite_sql("SELECT n.nid, n.title, l.comment_count FROM {node} n INNER JOIN {term_node} tn ON tn.nid = n.nid INNER JOIN {term_data} td ON td.tid = tn.tid INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.status = 1 AND td.vid = %d ORDER BY n.nid DESC"); + $sql = db_rewrite_sql("SELECT n.[nid], n.[title], l.[comment_count] FROM [{node}] n INNER JOIN [{term_node}] tn ON tn.[nid] = n.[nid] INNER JOIN [{term_data}] td ON td.[tid] = tn.[tid] INNER JOIN [{node_comment_statistics}] l ON n.[nid] = l.[nid] WHERE n.[status] = 1 AND td.[vid] = %d ORDER BY n.[nid] DESC"); $result = db_query_range($sql, variable_get('forum_nav_vocabulary', ''), 0, variable_get('forum_block_num_1', '5')); $content = node_title_list($result); break; @@ -500,7 +500,7 @@ function forum_get_forums($tid = 0) { $counts = array(); - $sql = "SELECT r.tid, COUNT(n.nid) AS topic_count, SUM(l.comment_count) AS comment_count FROM {node} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid INNER JOIN {term_node} r ON n.nid = r.nid WHERE n.status = 1 GROUP BY r.tid"; + $sql = "SELECT r.[tid], COUNT(n.[nid]) AS [topic_count], SUM(l.[comment_count]) AS [comment_count] FROM [{node}] n INNER JOIN [{node_comment_statistics}] l ON n.[nid] = l.[nid] INNER JOIN [{term_node}] r ON n.[nid] = r.[nid] WHERE n.[status] = 1 GROUP BY r.[tid]"; $sql = db_rewrite_sql($sql); $_counts = db_query($sql); while ($count = db_fetch_object($_counts)) { @@ -525,7 +525,7 @@ function forum_get_forums($tid = 0) { // This query does not use full ANSI syntax since MySQL 3.x does not support // table1 INNER JOIN table2 INNER JOIN table3 ON table2_criteria ON table3_criteria // used to join node_comment_statistics to users. - $sql = "SELECT ncs.last_comment_timestamp, IF (ncs.last_comment_uid != 0, u2.name, ncs.last_comment_name) AS last_comment_name, ncs.last_comment_uid FROM {node} n INNER JOIN {users} u1 ON n.uid = u1.uid INNER JOIN {term_node} tn ON n.vid = tn.vid INNER JOIN {node_comment_statistics} ncs ON n.nid = ncs.nid INNER JOIN {users} u2 ON ncs.last_comment_uid=u2.uid WHERE n.status = 1 AND tn.tid = %d ORDER BY ncs.last_comment_timestamp DESC"; + $sql = "SELECT ncs.[last_comment_timestamp], IF (ncs.[last_comment_uid] != 0, u2.[name], ncs.[last_comment_name]) AS [last_comment_name], ncs.[last_comment_uid] FROM [{node}] n INNER JOIN [{users}] u1 ON n.[uid] = u1.[uid] INNER JOIN [{term_node}] tn ON n.[vid] = tn.[vid] INNER JOIN [{node_comment_statistics}] ncs ON n.[nid] = ncs.[nid] INNER JOIN [{users}] u2 ON ncs.[last_comment_uid] = u2.[uid] WHERE n.[status] = 1 AND tn.[tid] = %d ORDER BY ncs.[last_comment_timestamp] DESC"; $sql = db_rewrite_sql($sql); $topic = db_fetch_object(db_query_range($sql, $forum->tid, 0, 1)); @@ -548,7 +548,7 @@ function forum_get_forums($tid = 0) { * than NODE_NEW_LIMIT. */ function _forum_topics_unread($term, $uid) { - $sql = "SELECT COUNT(n.nid) FROM {node} n INNER JOIN {term_node} tn ON n.vid = tn.vid AND tn.tid = %d LEFT JOIN {history} h ON n.nid = h.nid AND h.uid = %d WHERE n.status = 1 AND n.created > %d AND h.nid IS NULL"; + $sql = "SELECT COUNT(n.[nid]) FROM [{node}] n INNER JOIN [{term_node}] tn ON n.[vid] = tn.[vid] AND tn.[tid] = %d LEFT JOIN [{history}] h ON n.[nid] = h.[nid] AND h.[uid] = %d WHERE n.[status] = 1 AND n.[created] > %d AND h.[nid] IS NULL"; $sql = db_rewrite_sql($sql); return db_result(db_query($sql, $term, $uid, NODE_NEW_LIMIT)); } @@ -558,10 +558,10 @@ function forum_get_topics($tid, $sortby, $forum_topic_list_header = array( array('data' => ' ', 'field' => NULL), - array('data' => t('Topic'), 'field' => 'n.title'), - array('data' => t('Replies'), 'field' => 'l.comment_count'), - array('data' => t('Created'), 'field' => 'n.created'), - array('data' => t('Last reply'), 'field' => 'l.last_comment_timestamp'), + array('data' => t('Topic'), 'field' => 'n.[title]'), + array('data' => t('Replies'), 'field' => 'l.[comment_count]'), + array('data' => t('Created'), 'field' => 'n.[created]'), + array('data' => t('Last reply'), 'field' => 'l.[last_comment_timestamp]'), ); $order = _forum_get_topic_order($sortby); @@ -573,11 +573,11 @@ function forum_get_topics($tid, $sortby, $term = taxonomy_get_term($tid); - $sql = db_rewrite_sql("SELECT n.nid, r.tid, n.title, n.sticky, u.name, u.uid, n.created AS timestamp, n.comment AS comment_mode, l.last_comment_timestamp, IF(l.last_comment_uid != 0, cu.name, l.last_comment_name) AS last_comment_name, l.last_comment_uid, l.comment_count AS num_comments, f.tid AS forum_tid FROM {node_comment_statistics} l INNER JOIN {node} n ON n.nid = l.nid INNER JOIN {users} cu ON l.last_comment_uid = cu.uid INNER JOIN {term_node} r ON n.vid = r.vid INNER JOIN {users} u ON n.uid = u.uid INNER JOIN {forum} f ON n.vid = f.vid WHERE n.status = 1 AND r.tid = %d"); - $sql .= tablesort_sql($forum_topic_list_header, 'n.sticky DESC,'); - $sql .= ', n.created DESC'; // Always add a secondary sort order so that the news forum topics are on top. + $sql = db_rewrite_sql("SELECT n.[nid], r.[tid], n.[title], n.[sticky], u.[name], u.[uid], n.[created] AS [timestamp], n.[comment] AS [comment_mode], l.[last_comment_timestamp], IF(l.[last_comment_uid] != 0, cu.[name], l.[last_comment_name]) AS [last_comment_name], l.[last_comment_uid], l.[comment_count] AS [num_comments], f.[tid] AS [forum_tid] FROM [{node_comment_statistics}] l INNER JOIN [{node}] n ON n.[nid] = l.[nid] INNER JOIN [{users}] cu ON l.[last_comment_uid] = cu.[uid] INNER JOIN [{term_node}] r ON n.[vid] = r.[vid] INNER JOIN [{users}] u ON n.[uid] = u.[uid] INNER JOIN [{forum}] f ON n.[vid] = f.[vid] WHERE n.[status] = 1 AND r.[tid] = %d"); + $sql .= tablesort_sql($forum_topic_list_header, 'n.[sticky] DESC,'); + $sql .= ', n.[created] DESC'; // Always add a secondary sort order so that the news forum topics are on top. - $sql_count = db_rewrite_sql("SELECT COUNT(n.nid) FROM {node} n INNER JOIN {term_node} r ON n.nid = r.nid AND r.tid = %d WHERE n.status = 1"); + $sql_count = db_rewrite_sql("SELECT COUNT(n.[nid]) FROM [{node}] n INNER JOIN [{term_node}] r ON n.[nid] = r.[nid] AND r.[tid] = %d WHERE n.[status] = 1"); $result = pager_query($sql, $forum_per_page, 0, $sql_count, $tid); $topics = array(); @@ -618,7 +618,7 @@ function forum_get_topics($tid, $sortby, function _forum_new($tid) { global $user; - $sql = "SELECT n.nid FROM {node} n LEFT JOIN {history} h ON n.nid = h.nid AND h.uid = %d INNER JOIN {term_node} r ON n.nid = r.nid AND r.tid = %d WHERE n.status = 1 AND h.nid IS NULL AND n.created > %d ORDER BY created"; + $sql = "SELECT n.[nid] FROM [{node}] n LEFT JOIN [{history}] h ON n.[nid] = h.[nid] AND h.[uid] = %d INNER JOIN [{term_node}] r ON n.[nid] = r.[nid] AND r.[tid] = %d WHERE n.[status] = 1 AND h.[nid] IS NULL AND n.[created] > %d ORDER BY [created]"; $sql = db_rewrite_sql($sql); $nid = db_result(db_query_range($sql, $user->uid, $tid, NODE_NEW_LIMIT, 0, 1)); @@ -881,7 +881,7 @@ function template_preprocess_forum_topic $output = ''; // get previous and next topic - $sql = "SELECT n.nid, n.title, n.sticky, l.comment_count, l.last_comment_timestamp FROM {node} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid INNER JOIN {term_node} r ON n.nid = r.nid AND r.tid = %d WHERE n.status = 1 ORDER BY n.sticky DESC, ". _forum_get_topic_order_sql(variable_get('forum_order', 1)); + $sql = "SELECT n.[nid], n.[title], n.[sticky], l.[comment_count], l.[last_comment_timestamp] FROM [{node}] n INNER JOIN [{node_comment_statistics}] l ON n.[nid] = l.[nid] INNER JOIN [{term_node}] r ON n.[nid] = r.[nid] AND r.[tid] = %d WHERE n.[status] = 1 ORDER BY n.[sticky] DESC, ". _forum_get_topic_order_sql(variable_get('forum_order', 1)); $result = db_query(db_rewrite_sql($sql), isset($variables['node']->tid) ? $variables['node']->tid : 0); $stop = $variables['prev'] = $variables['next'] = 0; @@ -922,7 +922,7 @@ function _forum_user_last_visit($nid) { static $history = array(); if (empty($history)) { - $result = db_query('SELECT nid, timestamp FROM {history} WHERE uid = %d', $user->uid); + $result = db_query('SELECT [nid], [timestamp] FROM [{history}] WHERE [uid] = %d', $user->uid); while ($t = db_fetch_object($result)) { $history[$t->nid] = $t->timestamp > NODE_NEW_LIMIT ? $t->timestamp : NODE_NEW_LIMIT; } @@ -933,16 +933,16 @@ function _forum_user_last_visit($nid) { function _forum_get_topic_order($sortby) { switch ($sortby) { case 1: - return array('field' => 'l.last_comment_timestamp', 'sort' => 'desc'); + return array('field' => 'l.[last_comment_timestamp]', 'sort' => 'desc'); break; case 2: - return array('field' => 'l.last_comment_timestamp', 'sort' => 'asc'); + return array('field' => 'l.[last_comment_timestamp]', 'sort' => 'asc'); break; case 3: - return array('field' => 'l.comment_count', 'sort' => 'desc'); + return array('field' => 'l.[comment_count]', 'sort' => 'desc'); break; case 4: - return array('field' => 'l.comment_count', 'sort' => 'asc'); + return array('field' => 'l.[comment_count]', 'sort' => 'asc'); break; } } Index: modules/locale/locale.install =================================================================== RCS file: /cvs/drupal/drupal/modules/locale/locale.install,v retrieving revision 1.27 diff -u -p -r1.27 locale.install --- modules/locale/locale.install 10 Jan 2008 14:35:24 -0000 1.27 +++ modules/locale/locale.install 16 Jan 2008 15:38:12 -0000 @@ -12,7 +12,7 @@ function locale_install() { // Create tables. drupal_install_schema('locale'); - db_query("INSERT INTO {languages} (language, name, native, direction, enabled, weight, javascript) VALUES ('en', 'English', 'English', '0', '1', '0', '')"); + db_query("INSERT INTO [{languages}] ([language], [name], [native], [direction], [enabled], [weight], [javascript]) VALUES (%s, %s, %s, %d, %d, %d, %s)", 'en', 'English', 'English', 0, 1, 0, ''); } /** @@ -100,17 +100,17 @@ function locale_update_6000() { db_create_table($ret, 'languages', $schema['languages']); // Save the languages - $ret[] = update_sql("INSERT INTO {languages} (language, name, native, direction, enabled, plurals, formula, domain, prefix, weight) SELECT locale, name, name, 0, enabled, plurals, formula, '', locale, 0 FROM {locales_meta}"); + $ret[] = update_sql("INSERT INTO [{languages}] ([language], [name], [native], [direction], [enabled], [plurals], [formula], [domain], [prefix], [weight]) SELECT [locale], [name], [name], 0, [enabled], [plurals], [formula], '', [locale], 0 FROM [{locales_meta}]"); // Save the language count in the variable table - $count = db_result(db_query('SELECT COUNT(*) FROM {languages} WHERE enabled = 1')); + $count = db_result(db_query('SELECT COUNT(*) FROM [{languages}] WHERE [enabled] = 1')); variable_set('language_count', $count); // Save the default language in the variable table - $default = db_fetch_object(db_query('SELECT * FROM {locales_meta} WHERE isdefault = 1')); + $default = db_fetch_object(db_query('SELECT * FROM [{locales_meta}] WHERE [isdefault] = 1')); variable_set('language_default', (object) array('language' => $default->locale, 'name' => $default->name, 'native' => '', 'direction' => 0, 'enabled' => 1, 'plurals' => $default->plurals, 'formula' => $default->formula, 'domain' => '', 'prefix' => $default->locale, 'weight' => 0)); - $ret[] = update_sql("DROP TABLE {locales_meta}"); + $ret[] = update_sql("DROP TABLE [{locales_meta}]"); return $ret; } @@ -122,7 +122,7 @@ function locale_update_6000() { */ function locale_update_6001() { $ret = array(); - $ret[] = update_sql('UPDATE {locales_target} SET language = locale'); + $ret[] = update_sql('UPDATE [{locales_target}] SET [language] = locale'); db_drop_field($ret, 'locales_target', 'locale'); return $ret; } @@ -132,7 +132,7 @@ function locale_update_6001() { */ function locale_update_6002() { $ret = array(); - $ret[] = update_sql("DELETE FROM {locales_target} WHERE translation = ''"); + $ret[] = update_sql("DELETE FROM [{locales_target}] WHERE [translation] = ''"); return $ret; } @@ -141,7 +141,7 @@ function locale_update_6002() { */ function locale_update_6003() { $ret = array(); - $ret[] = update_sql("DELETE FROM {locales_source} WHERE lid NOT IN (SELECT lid FROM {locales_target})"); + $ret[] = update_sql("DELETE FROM [{locales_source}] WHERE [lid] NOT IN (SELECT [lid] FROM [{locales_target}])"); return $ret; } @@ -196,7 +196,7 @@ function locale_update_6005() { } } // Update language count variable that might be overwritten. - $count = db_result(db_query('SELECT COUNT(*) FROM {languages} WHERE enabled = 1')); + $count = db_result(db_query('SELECT COUNT(*) FROM [{languages}] WHERE [enabled] = 1')); variable_set('language_count', $count); return array(); } @@ -210,7 +210,7 @@ function locale_update_6005() { */ function locale_uninstall() { // Delete all JavaScript translation files - $files = db_query('SELECT javascript FROM {languages}'); + $files = db_query('SELECT [javascript] FROM [{languages}]'); while ($file = db_fetch_object($files)) { if (!empty($file)) { file_delete(file_create_path($file->javascript)); @@ -334,6 +334,7 @@ function locale_schema() { 'type' => 'text', 'mysql_type' => 'blob', 'not null' => TRUE, + 'default' => '', 'description' => t('The original string in English.'), ), 'version' => array( @@ -363,6 +364,7 @@ function locale_schema() { 'type' => 'text', 'mysql_type' => 'blob', 'not null' => TRUE, + 'default' => '', 'description' => t('Translation string value in this language.'), ), 'language' => array( Index: modules/locale/locale.module =================================================================== RCS file: /cvs/drupal/drupal/modules/locale/locale.module,v retrieving revision 1.211 diff -u -p -r1.211 locale.module --- modules/locale/locale.module 9 Jan 2008 11:51:54 -0000 1.211 +++ modules/locale/locale.module 16 Jan 2008 15:38:12 -0000 @@ -351,7 +351,7 @@ function locale($string = NULL, $langcod // Refresh database stored cache of translations for given language. // We only store short strings used in current version, to improve // performance and consume less memory. - $result = db_query("SELECT s.source, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = '%s' WHERE s.textgroup = 'default' AND s.version = '%s' AND LENGTH(s.source) < 75", $langcode, VERSION); + $result = db_query("SELECT s.[source], t.[translation], t.[language] FROM [{locales_source}] s LEFT JOIN [{locales_target}] t ON s.[lid] = t.[lid] AND t.[language] = %s WHERE s.[textgroup] = 'default' AND s.[version] = %s AND ". DB_STRLEN ."(s.[source]) < 75", $langcode, VERSION); while ($data = db_fetch_object($result)) { $locale_t[$langcode][$data->source] = (empty($data->translation) ? TRUE : $data->translation); } @@ -364,7 +364,7 @@