? files
? sites/default/files
Index: CHANGELOG.txt
===================================================================
RCS file: /cvs/drupal/drupal/CHANGELOG.txt,v
retrieving revision 1.253.2.9
diff -u -p -r1.253.2.9 CHANGELOG.txt
--- CHANGELOG.txt	9 Jul 2008 21:48:27 -0000	1.253.2.9
+++ CHANGELOG.txt	9 Aug 2008 06:00:34 -0000
@@ -9,8 +9,12 @@ Drupal 6.3, 2008-07-09
 - performance improvements to search, menu handling and form API caches
 - fixed Views compatibility issues (Views for Drupal 6 requires Drupal 6.3+)
 - fixed a variety of small bugs.
+- Siren: update PDO ATTR_ERRMODE as ERRMODE_EXCEPTION.
+- Siren: update {batch}.batch as blob.
+- Siren: update {watchdog}.variables as blob.
+- Siren: pdo_oci is now able to work for production.
 
-Drupal 6.2, 2008-04-09 
+Drupal 6.2, 2008-04-09
 ----------------------
 - fixed a variety of small bugs
 - fixed a security issue (Access bypasses), see SA-2008-026
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	9 Aug 2008 06:00:34 -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	9 Aug 2008 06:00:34 -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.txt
===================================================================
RCS file: /cvs/drupal/drupal/MAINTAINERS.txt,v
retrieving revision 1.19.2.1
diff -u -p -r1.19.2.1 MAINTAINERS.txt
--- MAINTAINERS.txt	15 May 2008 22:13:42 -0000	1.19.2.1
+++ MAINTAINERS.txt	9 Aug 2008 06:00:34 -0000
@@ -83,5 +83,9 @@ TRANSLATIONS COORDINATOR
 M: Gerhard Killesreiter <gerhard@killesreiter.de>
 S: maintained
 
+SIREN MULTIPLCATE DATABASE HACK
+M: Edison Wong <hswong3i@gmail.com>
+S: maintained
+
 THE REST:
 M: Dries <dries@drupal.org>
Index: SIREN.txt
===================================================================
RCS file: SIREN.txt
diff -N SIREN.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SIREN.txt	9 Aug 2008 06:00:34 -0000
@@ -0,0 +1,84 @@
+// $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.
+
+6. ALWAYS USE BLOB IF POSSIBLE
+
+   Most Database have size limitation in VARCHAR, e.g. Oralce only allow for
+   maximum 4000 characters in VARCHAR2, where DB2 only have a good support of
+   VARCHAR update to maximum 4000 characters, too.
+
+   Therefore always try to use BLOB if possible, combine with
+   drupal_write_record() and db_decode_blob() function, as most database
+   support GB-scale BLOB field without any problem.
+
+
+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.113.2.3
diff -u -p -r1.113.2.3 install.php
--- install.php	9 Jul 2008 19:15:59 -0000	1.113.2.3
+++ install.php	9 Aug 2008 06:00:34 -0000
@@ -143,7 +143,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_table_exists('variable') ? db_query("SELECT [value] FROM [{variable}] WHERE [name] = %s", 'install_task') : FALSE;
   if ($result) {
     return unserialize(db_result($result));
   }
@@ -160,16 +160,16 @@ function install_verify_settings() {
     // We need this because we want to run form_get_errors.
     include_once './includes/form.inc';
 
-    $url = parse_url(is_array($db_url) ? $db_url['default'] : $db_url);
-    $db_user = urldecode($url['user']);
-    $db_pass = isset($url['pass']) ? urldecode($url['pass']) : NULL;
-    $db_host = urldecode($url['host']);
-    $db_port = isset($url['port']) ? urldecode($url['port']) : '';
-    $db_path = ltrim(urldecode($url['path']), '/');
+    $url = isset($db_url['default']) ? $db_url['default'] : $db_url;
+    $db_user = $url['db_user'];
+    $db_pass = isset($url['db_pass']) ? $url['db_pass'] : NULL;
+    $db_host = $url['db_host'];
+    $db_port = isset($url['db_port']) ? $url['db_port'] : '';
+    $db_name = $url['db_name'];
     $settings_file = './'. conf_path(FALSE, TRUE) .'/settings.php';
 
     $form_state = array();
-    _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_path, $settings_file, $form_state);
+    _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_name, $settings_file, $form_state);
     if (!form_get_errors()) {
       return TRUE;
     }
@@ -183,12 +183,12 @@ function install_verify_settings() {
 function install_change_settings($profile = 'default', $install_locale = '') {
   global $db_url, $db_type, $db_prefix;
 
-  $url = parse_url(is_array($db_url) ? $db_url['default'] : $db_url);
-  $db_user = isset($url['user']) ? urldecode($url['user']) : '';
-  $db_pass = isset($url['pass']) ? urldecode($url['pass']) : '';
-  $db_host = isset($url['host']) ? urldecode($url['host']) : '';
-  $db_port = isset($url['port']) ? urldecode($url['port']) : '';
-  $db_path = ltrim(urldecode($url['path']), '/');
+  $url = isset($db_url['default']) ? $db_url['default'] : $db_url;
+  $db_user = isset($url['db_user']) ? $url['db_user'] : '';
+  $db_pass = isset($url['db_pass']) ? $url['db_pass'] : '';
+  $db_host = isset($url['db_host']) ? $url['db_host'] : '';
+  $db_port = isset($url['db_port']) ? $url['db_port'] : '';
+  $db_name = isset($url['db_name']) ? $url['db_name'] : '';
   $conf_path = './'. conf_path(FALSE, TRUE);
   $settings_file = $conf_path .'/settings.php';
 
@@ -196,7 +196,7 @@ function install_change_settings($profil
   include_once './includes/form.inc';
   install_task_list('database');
 
-  $output = drupal_get_form('install_settings_form', $profile, $install_locale, $settings_file, $db_url, $db_type, $db_prefix, $db_user, $db_pass, $db_host, $db_port, $db_path);
+  $output = drupal_get_form('install_settings_form', $profile, $install_locale, $settings_file, $db_url, $db_type, $db_prefix, $db_user, $db_pass, $db_host, $db_port, $db_name);
   drupal_set_title(st('Database configuration'));
   print theme('install_page', $output);
   exit;
@@ -206,7 +206,7 @@ function install_change_settings($profil
 /**
  * Form API array definition for install_settings.
  */
-function install_settings_form(&$form_state, $profile, $install_locale, $settings_file, $db_url, $db_type, $db_prefix, $db_user, $db_pass, $db_host, $db_port, $db_path) {
+function install_settings_form(&$form_state, $profile, $install_locale, $settings_file, $db_url, $db_type, $db_prefix, $db_user, $db_pass, $db_host, $db_port, $db_name) {
   if (empty($db_host)) {
     $db_host = 'localhost';
   }
@@ -216,6 +216,20 @@ 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 both 'oci8' and 'pdo_oci' are available, we disable 'oci8':
+  if (isset($db_types['pdo_oci'])) {
+    unset($db_types['oci8']);
+  }
 
   if (count($db_types) == 0) {
     $form['no_db_types'] = array(
@@ -238,7 +252,7 @@ function install_settings_form(&$form_st
         '#default_value' => ($db_type ? $db_type : current($db_types)),
         '#description' => st('The type of database your @drupal data will be stored in.', array('@drupal' => drupal_install_profile_name())),
       );
-      $db_path_description = st('The name of the database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('@drupal' => drupal_install_profile_name()));
+      $db_name_description = st('The name of the database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('@drupal' => drupal_install_profile_name()));
     }
     else {
       if (count($db_types) == 1) {
@@ -247,19 +261,19 @@ function install_settings_form(&$form_st
           '#type' => 'hidden',
           '#value' => $db_types[0],
         );
-        $db_path_description = st('The name of the %db_type database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('%db_type' => $db_types[0], '@drupal' => drupal_install_profile_name()));
+        $db_name_description = st('The name of the %db_type database your @drupal data will be stored in. It must exist on your server before @drupal can be installed.', array('%db_type' => $db_types[0], '@drupal' => drupal_install_profile_name()));
       }
     }
 
     // Database name
-    $form['basic_options']['db_path'] = array(
+    $form['basic_options']['db_name'] = array(
       '#type' => 'textfield',
       '#title' => st('Database name'),
-      '#default_value' => $db_path,
+      '#default_value' => $db_name,
       '#size' => 45,
       '#maxlength' => 45,
       '#required' => TRUE,
-      '#description' => $db_path_description
+      '#description' => $db_name_description
     );
 
     // Database username
@@ -340,13 +354,13 @@ function install_settings_form(&$form_st
  */
 function install_settings_form_validate($form, &$form_state) {
   global $db_url;
-  _install_settings_form_validate($form_state['values']['db_prefix'], $form_state['values']['db_type'], $form_state['values']['db_user'], $form_state['values']['db_pass'], $form_state['values']['db_host'], $form_state['values']['db_port'], $form_state['values']['db_path'], $form_state['values']['settings_file'], $form_state, $form);
+  _install_settings_form_validate($form_state['values']['db_prefix'], $form_state['values']['db_type'], $form_state['values']['db_user'], $form_state['values']['db_pass'], $form_state['values']['db_host'], $form_state['values']['db_port'], $form_state['values']['db_name'], $form_state['values']['settings_file'], $form_state, $form);
 }
 
 /**
  * Helper function for install_settings_validate.
  */
-function _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_path, $settings_file, &$form_state, $form = NULL) {
+function _install_settings_form_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_port, $db_name, $settings_file, &$form_state, $form = NULL) {
   global $db_url;
 
   // Verify the table prefix
@@ -360,8 +374,7 @@ 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_type = $db_url['db_type'];
   }
   $databases = drupal_detect_database_types();
   if (!in_array($db_type, $databases)) {
@@ -369,9 +382,17 @@ 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 = array(
+      'db_host' => $db_host ? $db_host : NULL,
+      'db_port' => $db_port ? $db_port : NULL,
+      'db_name' => $db_name ? $db_name : NULL,
+      'db_user' => $db_user ? $db_user : NULL,
+      'db_pass' => $db_pass ? $db_pass : NULL,
+      'db_type' => $db_type ? $db_type : NULL,
+      'db_prefix' => $db_prefix ? $db_prefix : NULL,
+    );
     if (isset($form)) {
-      form_set_value($form['_db_url'], $db_url, $form_state);
+      form_set_value($form['_db_url'], array_filter($db_url), $form_state);
     }
     $success = array();
 
@@ -398,10 +419,6 @@ function install_settings_form_submit($f
     'value'    => $form_state['values']['_db_url'],
     'required' => TRUE,
   );
-  $settings['db_prefix'] = array(
-    'value'    => $form_state['values']['db_prefix'],
-    'required' => TRUE,
-  );
   drupal_rewrite_settings($settings);
 
   // Continue to install profile step
@@ -915,7 +932,7 @@ function install_check_requirements($pro
         drupal_set_message($message, 'warning');
       }
     }
-  } 
+  }
 }
 
 /**
Index: update.php
===================================================================
RCS file: /cvs/drupal/drupal/update.php,v
retrieving revision 1.252
diff -u -p -r1.252 update.php
--- update.php	3 Feb 2008 18:41:16 -0000	1.252
+++ update.php	9 Aug 2008 06:00:34 -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]");
 }
 
 /**
@@ -428,14 +428,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.2.1
diff -u -p -r1.8.2.1 actions.inc
--- includes/actions.inc	23 Apr 2008 18:06:36 -0000	1.8.2.1
+++ includes/actions.inc	9 Aug 2008 06:00:34 -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	9 Aug 2008 06:00:34 -0000
@@ -12,8 +12,8 @@ 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'])))) {
-    $batch = unserialize($data);
+  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(db_decode_blob($data));
   }
   else {
     return FALSE;
@@ -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,9 @@ function _batch_finished() {
  */
 function _batch_shutdown() {
   if ($batch = batch_get()) {
-    db_query("UPDATE {batch} SET batch = '%s' WHERE bid = %d", serialize($batch), $batch['id']);
+    $values = array(
+      array('field' => 'batch', 'placeholder' => '%b', 'data' => serialize($batch)),
+    );
+    db_query_update('batch', $values, '[bid] = %d', $batch['id']);
   }
 }
Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.206.2.3
diff -u -p -r1.206.2.3 bootstrap.inc
--- includes/bootstrap.inc	9 Jul 2008 19:15:59 -0000	1.206.2.3
+++ includes/bootstrap.inc	9 Aug 2008 06:00:34 -0000
@@ -281,11 +281,6 @@ function conf_init() {
     include_once './'. conf_path() .'/settings.php';
   }
 
-  // Ignore the placeholder url from default.settings.php.
-  if (isset($db_url) && $db_url == 'mysql://username:password@localhost/databasename') {
-    $db_url = '';
-  }
-
   if (isset($base_url)) {
     // Parse fixed base URL from settings.php.
     $parts = parse_url($base_url);
@@ -389,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 {
@@ -425,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);
     }
@@ -468,9 +463,11 @@ function variable_set($name, $value) {
   global $conf;
 
   $serialized_value = serialize($value);
-  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);
+  if (db_result(db_query("SELECT COUNT(*) FROM [{variable}] WHERE [name] = %s", $name))) {
+    db_query("UPDATE [{variable}] SET [value] = %s WHERE [name] = %s", $serialized_value, $name);
+  }
+  else {
+    db_query("INSERT INTO [{variable}] ([name], [value]) VALUES (%s, %s)", $name, $serialized_value);
   }
 
   cache_clear_all('variables', 'cache');
@@ -487,7 +484,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]);
@@ -879,13 +876,19 @@ function drupal_get_messages($type = NUL
  *   TRUE if access is denied, FALSE if access is allowed.
  */
 function drupal_is_denied($type, $mask) {
-  // Because this function is called for every page request, both cached
-  // and non-cached pages, we tried to optimize it as much as possible.
-  // 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";
-  return db_result(db_query_range($sql, $type, $mask, 0, 0, 1)) && !db_result(db_query_range($sql, $type, $mask, 1, 0, 1));
+  switch ($GLOBALS['db_type']) {
+    case 'ibm_db2':
+    case 'pdo_ibm':
+      return FALSE;
+    default:
+      // Because this function is called for every page request, both cached
+      // and non-cached pages, we tried to optimize it as much as possible.
+      // 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";
+      return db_result(db_query_range($sql, $type, $mask, 0, 0, 1)) && !db_result(db_query_range($sql, $type, $mask, 1, 0, 1));
+  }
 }
 
 /**
@@ -1083,7 +1086,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.17
diff -u -p -r1.17 cache.inc
--- includes/cache.inc	29 Jan 2008 11:36:06 -0000	1.17
+++ includes/cache.inc	9 Aug 2008 06:00:34 -0000
@@ -20,10 +20,10 @@ function cache_get($cid, $table = 'cache
     // Reset the variable immediately to prevent a meltdown in heavy load situations.
     variable_set('cache_flush', 0);
     // 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);
   }
 
-  $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.
@@ -106,9 +106,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);
   }
 }
 
@@ -157,26 +165,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	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,397 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Functions shared between ibm_db2 and pdo_ibm database engines.
+ */
+
+/**
+ * @ingroup database
+ * @{
+ */
+
+/**
+ * Indicates the string to use to quote identifiers and names.
+ */
+define('DB_QUOTE_OPERATOR', '"');
+
+/**
+ * Indicates the concatenation operator.
+ */
+define('DB_CONCAT_OPERATOR', '||');
+
+/**
+ * Indicates the name of the SQL strtoupper function.
+ */
+define('DB_UPPER', 'UPPER');
+
+/**
+ * Indicates the SQL to generate a random number between 0.00 and 1.00.
+ */
+define('DB_RAND', 'RAND()');
+
+/**
+ * Indicates the name of the SQL strlen function.
+ */
+define('DB_STRLEN', 'LENGTH');
+
+/**
+ * Indicates the name of the SQL substr function.
+ */
+define('DB_SUBSTR', 'SUBSTR');
+
+/**
+ * Replace all escape characters in a query, based on the database specific
+ * implementation.
+ *
+ * Queries sent to Drupal should wrap all identifiers and names in square
+ * brackets. This function will search for this syntax and replace it as
+ * corresponding escape characters, based on the database specific
+ * requirement.
+ */
+function db_escape_quote($sql) {
+  return preg_replace('/\[([A-Za-z0-9_]+)\]/', DB_QUOTE_OPERATOR .'\1'. DB_QUOTE_OPERATOR, $sql);
+}
+
+/**
+ * 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 " CASE WHEN $expr1 IS NULL THEN $expr2 ELSE $expr1 END ";
+}
+
+/**
+ * Report database status.
+ */
+function db_status_report($phase) {
+  $t = get_t();
+
+  $version = db_version();
+
+  $form['db2'] = array(
+    'title' => $t('DB2 database'),
+    'value' => $version,
+  );
+
+  if (version_compare($version, DRUPAL_MINIMUM_DB2) < 0) {
+    $form['db2']['severity'] = REQUIREMENT_ERROR;
+    $form['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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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 .'])';
+  // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
+  $query = preg_replace('/(SELECT.*)(?:\['. $table .'\]\.|\s)(?<!DISTINCT\()(?<!DISTINCT\(\['. $table .'\]\.)\['. $field .'\](.*FROM )/AUsi', '\1 '. $field_to_select .'\2', $query);
+  $query = preg_replace('/(ORDER BY )(?!\['. $table .'\]\.\['. $field .'\])/', '\1'."[$table].[$field], ", $query);
+  return $query;
+}
+
+/**
+ * @} End of "ingroup database".
+ */
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.756.2.20
diff -u -p -r1.756.2.20 common.inc
--- includes/common.inc	9 Jul 2008 21:48:27 -0000	1.756.2.20
+++ includes/common.inc	9 Aug 2008 06:00:35 -0000
@@ -577,7 +577,7 @@ function drupal_error_handler($errno, $m
     return;
   }
 
-  if ($errno & (E_ALL ^ E_NOTICE)) {
+  if ($errno & (E_ALL)) {
     $types = array(1 => 'error', 2 => 'warning', 4 => 'parse error', 8 => 'notice', 16 => 'core error', 32 => 'core warning', 64 => 'compile error', 128 => 'compile warning', 256 => 'user error', 512 => 'user warning', 1024 => 'user notice', 2048 => 'strict warning', 4096 => 'recoverable fatal error');
 
     // For database errors, we want the line number/file name of the place that
@@ -856,7 +856,7 @@ function valid_url($url, $absolute = FAL
  *   The name of an event.
  */
 function flood_register_event($name) {
-  db_query("INSERT INTO {flood} (event, hostname, timestamp) VALUES ('%s', '%s', %d)", $name, ip_address(), time());
+  db_query("INSERT INTO [{flood}] ([event], [hostname], [timestamp]) VALUES (%s, %s, %d)", $name, ip_address(), time());
 }
 
 /**
@@ -873,7 +873,7 @@ function flood_register_event($name) {
  *   True if the user did not exceed the hourly threshold. False otherwise.
  */
 function flood_is_allowed($name, $threshold) {
-  $number = db_result(db_query("SELECT COUNT(*) FROM {flood} WHERE event = '%s' AND hostname = '%s' AND timestamp > %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);
 }
 
@@ -3188,7 +3188,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) {
@@ -3213,7 +3215,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.
@@ -3224,17 +3226,17 @@ 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);
   }
 
   $schema = drupal_get_schema($table);
   if (empty($schema)) {
     return FALSE;
   }
-  
+
   // Convert to an object if needed.
   if (is_array($object)) {
     $object = (object) $object;
@@ -3244,18 +3246,19 @@ function drupal_write_record($table, &$o
     $array = FALSE;
   }
 
-  $fields = $defs = $values = $serials = $placeholders = 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'];
     }
 
@@ -3268,44 +3271,52 @@ 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;
+      }
+      elseif (!empty($object->$field)) {
+        $value['data'] = serialize($object->$field);
       }
       else {
-        $values[] = serialize($object->$field);
+        $value['data'] = '';
       }
+
+      $values[] = $value;
     }
   }
 
-  // Build the SQL.
-  $query = '';
-  if (!count($update)) {
-    $query = "INSERT INTO {". $table ."} (". implode(', ', $fields) .') VALUES ('. implode(', ', $placeholders) .')';
+  if (empty($values)) {
+    // No changes requested.
+    // If we began with an array, convert back so we don't surprise the caller.
+    if ($array) {
+      $object = (array) $object;
+    }
+    return;
+  }
+
+  // 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];
+      $conditions[] = "[$key] = ". db_type_placeholder($schema['fields'][$key]['type']);
+      $args[] = $value;
     }
-
-    foreach ($update as $key){
-      $conditions[] = "$key = ". db_type_placeholder($schema['fields'][$key]['type']);
-      $values[] = $object->$key;
-    }
-
-    $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) {
@@ -3326,6 +3337,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	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,385 @@
+<?php
+// $Id: common.mysql.inc,v 1.2 2007/12/11 07:21:32 hswong3i Exp $
+
+/**
+ * @file
+ * Functions shared between mysql, mysqli and pdo_mysql database engines.
+ */
+
+/**
+ * @ingroup database
+ * @{
+ */
+
+/**
+ * Indicates the string to use to quote identifiers and names.
+ */
+define('DB_QUOTE_OPERATOR', '`');
+
+/**
+ * Indicates the concatenation operator.
+ */
+define('DB_CONCAT_OPERATOR', '+');
+
+/**
+ * Indicates the name of the SQL strtoupper function.
+ */
+define('DB_UPPER', 'UPPER');
+
+/**
+ * Indicates the SQL to generate a random number between 0.00 and 1.00.
+ */
+define('DB_RAND', 'RAND()');
+
+/**
+ * Indicates the name of the SQL strlen function.
+ */
+define('DB_STRLEN', 'LENGTH');
+
+/**
+ * Indicates the name of the SQL substring function.
+ */
+define('DB_SUBSTR', 'SUBSTRING');
+
+/**
+ * Replace all escape characters in a query, based on the database specific
+ * implementation.
+ *
+ * Queries sent to Drupal should wrap all identifiers and names in square
+ * brackets. This function will search for this syntax and replace it as
+ * corresponding escape characters, based on the database specific
+ * requirement.
+ */
+function db_escape_quote($sql) {
+  return preg_replace('/\[([A-Za-z0-9_]+)\]/', DB_QUOTE_OPERATOR .'\1'. DB_QUOTE_OPERATOR, $sql);
+}
+
+/**
+ * Portable SQL generating function.
+ *
+ * @param ...
+ *   Variable number of string parameters.
+ * @return
+ *   Portably concatenate strings.
+ */
+function db_concat() {
+  $args = func_get_args();
+  $return = implode(', ', $args);
+  return (strlen($return) > 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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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 .'])';
+  // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
+  return preg_replace('/(SELECT.*)(?:\['. $table .'\]\.|\s)(?<!DISTINCT\()(?<!DISTINCT\(\['. $table .'\]\.)\['. $field .'\](.*FROM )/AUsi', '\1 '. $field_to_select .'\2', $query);
+}
+
+/**
+ * @} End of "ingroup database".
+ */
Index: includes/common.oracle.inc
===================================================================
RCS file: includes/common.oracle.inc
diff -N includes/common.oracle.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/common.oracle.inc	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,476 @@
+<?php
+// $Id: common.oracle.inc,v 1.2 2007/12/11 07:21:32 hswong3i Exp $
+
+/**
+ * @file
+ * Functions shared between oci8 and pdo_oci database engines.
+ */
+
+/**
+ * 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('ORACLE_MAX_CACHE_STMT', 256);
+
+/**
+ * Indicates the empty string placeholder.
+ */
+define('ORACLE_EMPTY_STRING_PLACEHOLDER', "\x01");
+
+/**
+ * @ingroup database
+ * @{
+ */
+
+/**
+ * Indicates the string to use to quote identifiers and names.
+ */
+define('DB_QUOTE_OPERATOR', '"');
+
+/**
+ * Indicates the concatenation operator.
+ */
+define('DB_CONCAT_OPERATOR', '||');
+
+/**
+ * Indicates the name of the SQL strtoupper function.
+ */
+define('DB_UPPER', 'UPPER');
+
+/**
+ * Indicates the SQL to generate a random number between 0.00 and 1.00.
+ */
+define('DB_RAND', 'ABS(MOD(DBMS_RANDOM.RANDOM,10000001)/10000000)');
+
+/**
+ * Indicates the name of the SQL strlen function.
+ */
+define('DB_STRLEN', 'LENGTH');
+
+/**
+ * Indicates the name of the SQL substr function.
+ */
+define('DB_SUBSTR', 'SUBSTR');
+
+/**
+ * Replace all escape characters in a query, based on the database specific
+ * implementation.
+ *
+ * Queries sent to Drupal should wrap all identifiers and names in square
+ * brackets. This function will search for this syntax and replace it as
+ * corresponding escape characters, based on the database specific
+ * requirement.
+ */
+function db_escape_quote($sql) {
+  return preg_replace_callback('/\[([A-Za-z0-9_]+)\]/', '_db_escape_quote_callback', $sql);
+}
+
+/**
+ * Helper function for db_escape_quote().
+ */
+function _db_escape_quote_callback($matches) {
+  $match = $matches[1];
+  if (strlen($match) > 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['oracle'] = array(
+    'title' => $t('Oracle database'),
+    'value' => $version,
+  );
+
+  if (version_compare($version, DRUPAL_MINIMUM_ORACLE) < 0) {
+    $form['oracle']['severity'] = REQUIREMENT_ERROR;
+    $form['oracle']['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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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 .'])';
+  // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
+  $query = preg_replace('/(SELECT.*)(?:\['. $table .'\]\.|\s)(?<!DISTINCT\()(?<!DISTINCT\(\['. $table .'\]\.)\['. $field .'\](.*FROM )/AUsi', '\1 '. $field_to_select .'\2', $query);
+  $query = preg_replace('/(ORDER BY )(?!\['. $table .'\]\.\['. $field .'\])/', '\1'."[$table].[$field], ", $query);
+  return $query;
+}
+
+/**
+ * @} End of "ingroup database".
+ */
Index: includes/common.postgresql.inc
===================================================================
RCS file: includes/common.postgresql.inc
diff -N includes/common.postgresql.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/common.postgresql.inc	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,402 @@
+<?php
+// $Id: common.postgresql.inc,v 1.2 2007/12/11 07:21:32 hswong3i Exp $
+
+/**
+ * @file
+ * Functions shared between pgsql and pdo_pgsql database engines.
+ */
+
+/**
+ * @ingroup database
+ * @{
+ */
+
+/**
+ * Indicates the string to use to quote identifiers and names.
+ */
+define('DB_QUOTE_OPERATOR', '"');
+
+/**
+ * Indicates the concatenation operator.
+ */
+define('DB_CONCAT_OPERATOR', '||');
+
+/**
+ * Indicates the name of the SQL strtoupper function.
+ */
+define('DB_UPPER', 'UPPER');
+
+/**
+ * Indicates the SQL to generate a random number between 0.00 and 1.00.
+ */
+define('DB_RAND', 'RANDOM()');
+
+/**
+ * Indicates the name of the SQL strlen function.
+ */
+define('DB_STRLEN', 'LENGTH');
+
+/**
+ * Indicates the name of the SQL substr function.
+ */
+define('DB_SUBSTR', 'SUBSTRING');
+
+/**
+ * Replace all escape characters in a query, based on the database specific
+ * implementation.
+ *
+ * Queries sent to Drupal should wrap all identifiers and names in square
+ * brackets. This function will search for this syntax and replace it as
+ * corresponding escape characters, based on the database specific
+ * requirement.
+ */
+function db_escape_quote($sql) {
+  return preg_replace('/\[([A-Za-z0-9_]+)\]/', DB_QUOTE_OPERATOR .'\1'. DB_QUOTE_OPERATOR, $sql);
+}
+
+/**
+ * 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 " COALESCE($expr1, $expr2) ";
+}
+
+/**
+ * Report database status.
+ */
+function db_status_report() {
+  $t = get_t();
+
+  $version = db_version();
+
+  $form['postgresql'] = array(
+    'title' => $t('PostgreSQL database'),
+    'value' => $version,
+  );
+
+  if (version_compare($version, DRUPAL_MINIMUM_POSTGRESQL) < 0) {
+    $form['postgresql']['severity'] = REQUIREMENT_ERROR;
+    $form['postgresql']['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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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) {
+  if (!preg_match('/FROM\s+\S+\s+AS/si', $query)
+  && !preg_match('/DISTINCT\s+ON\s*\(\s*(' . $table . '\s*\.\s*)?' . $field . '\s*\)/si', $query)
+  && !preg_match('/DISTINCT[ (]' . $field . '/si', $query)
+  && preg_match('/(.*FROM\s+)(.*?\s)(\s*(WHERE|GROUP|HAVING|ORDER|LIMIT|FOR).*)/Asi', $query, $m)) {
+    $query = $m[1];
+    $query .= preg_replace('/([\{\w+\}]+)\s+(\[' . $table . '\])\s/Usi', '(SELECT DISTINCT ON (\[' . $field . '\]) * FROM \1) \2 ', $m[2]);
+    $query .= $m[3];
+  }
+}
+
+/**
+ * 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 <a href="@url">PostgreSQL documentation</a>.', array('%encoding' => $encoding, '@url' => 'http://www.postgresql.org/docs/7.4/interactive/multibyte.html')), 'status');
+  }
+}
+
+/**
+ * @} End of "ingroup database".
+ */
Index: includes/common.sqlite.inc
===================================================================
RCS file: includes/common.sqlite.inc
diff -N includes/common.sqlite.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/common.sqlite.inc	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,393 @@
+<?php
+// $Id: common.sqlite.inc,v 1.1 2008/02/03 10:08:54 hswong3i Exp $
+
+/**
+ * @file
+ * Functions shared between sqlite and pdo_sqlite database engines.
+ */
+
+/**
+ * @ingroup database
+ * @{
+ */
+
+/**
+ * Indicates the string to use to quote identifiers and names.
+ */
+define('DB_QUOTE_OPERATOR', '"');
+
+/**
+ * Indicates the concatenation operator.
+ */
+define('DB_CONCAT_OPERATOR', '||');
+
+/**
+ * Indicates the name of the SQL strtoupper function.
+ */
+define('DB_UPPER', 'UPPER');
+
+/**
+ * Indicates the SQL to generate a random number between 0.00 and 1.00.
+ */
+define('DB_RAND', 'ABS(RANDOM()%10000001.0/10000000.0)');
+
+/**
+ * Indicates the name of the SQL strlen function.
+ */
+define('DB_STRLEN', 'LENGTH');
+
+/**
+ * Indicates the name of the SQL substr function.
+ */
+define('DB_SUBSTR', 'SUBSTR');
+
+/**
+ * Replace all escape characters in a query, based on the database specific
+ * implementation.
+ *
+ * Queries sent to Drupal should wrap all identifiers and names in square
+ * brackets. This function will search for this syntax and replace it as
+ * corresponding escape characters, based on the database specific
+ * requirement.
+ */
+function db_escape_quote($sql) {
+  return preg_replace('/\[([A-Za-z0-9_]+)\]/', DB_QUOTE_OPERATOR .'\1'. DB_QUOTE_OPERATOR, $sql);
+}
+
+/**
+ * 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 " IFNULL($expr1, $expr2) ";
+}
+
+/**
+ * Report database status.
+ */
+function db_status_report() {
+  $t = get_t();
+
+  $version = db_version();
+
+  $form['sqlite'] = array(
+    'title' => $t('SQLite database'),
+    'value' => $version,
+  );
+
+  if (version_compare($version, DRUPAL_MINIMUM_SQLITE) < 0) {
+    $form['sqlite']['severity'] = REQUIREMENT_ERROR;
+    $form['sqlite']['description'] = $t('Your SQLite Server is too old. Drupal requires at least SQLite %version.', array('%version' => DRUPAL_MINIMUM_SQLITE));
+  }
+
+  return $form;
+}
+
+/**
+ * Returns the version of the database server currently in use.
+ *
+ * @return Database server version
+ */
+function db_version() {
+  return db_result(db_query("SELECT SQLITE_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 LAST_INSERT_ROWID()"));
+}
+
+/**
+ * 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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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('BEGIN');
+}
+
+/**
+ * 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 SQLITE_MASTER WHERE TBL_NAME LIKE '{". db_escape_table($table) ."}'"));
+}
+
+/**
+ * Check if a column exists in the given table.
+ */
+function db_column_exists($table, $column) {
+  $result = db_query("PRAGMA TABLE_INFO('{". db_escape_table($table) ."}')");
+  while ($column = db_fetch_array($result)) {
+    if ($column['name'] == $column) {
+      return TRUE;
+    }
+  }
+  return 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 ON (['. $table .'].['. $field ."]) [$table].[$field]";
+  // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
+  $query = preg_replace('/(SELECT.*)(?:\['. $table .'\]\.|\s)(?<!DISTINCT\()(?<!DISTINCT\(\['. $table .'\]\.)\['. $field .'\](.*FROM )/AUsi', '\1 '. $field_to_select .'\2', $query);
+  $query = preg_replace('/(ORDER BY )(?!\['. $table .'\]\.\['. $field .'\])/', '\1'."[$table].[$field], ", $query);
+  return $query;
+}
+
+/**
+ * @} End of "ingroup database".
+ */
Index: includes/database.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database.inc,v
retrieving revision 1.92.2.2
diff -u -p -r1.92.2.2 database.inc
--- includes/database.inc	9 Jul 2008 21:48:28 -0000	1.92.2.2
+++ includes/database.inc	9 Aug 2008 06:00:35 -0000
@@ -122,7 +122,7 @@ function db_prefix_tables($sql) {
  * @return the name of the previously active database or FALSE if non was found.
  */
 function db_set_active($name = 'default') {
-  global $db_url, $db_type, $active_db;
+  global $db_url, $db_prefix, $db_type, $active_db;
   static $db_conns, $active_name = FALSE;
 
   if (empty($db_url)) {
@@ -132,21 +132,25 @@ function db_set_active($name = 'default'
 
   if (!isset($db_conns[$name])) {
     // Initiate a new connection, using the named DB URL specified.
-    if (is_array($db_url)) {
-      $connect_url = array_key_exists($name, $db_url) ? $db_url[$name] : $db_url['default'];
+    if (array_key_exists($name, $db_url)) {
+      $connect_url = $db_url[$name];
+    }
+    elseif (array_key_exists('default', $db_url)) {
+      $connect_url = $db_url['default'];
     }
     else {
       $connect_url = $db_url;
     }
 
-    $db_type = substr($connect_url, 0, strpos($connect_url, '://'));
+    $db_type = $connect_url['db_type'];
+    $db_prefix = $connect_url['db_prefix'];
     $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' or 'pdo_oci' for Oracle databases; 'ibm_db2' or 'pdo_ibm' for IBM DB2 databases; 'pdo_sqlite' for SQLite databases.");
     }
 
     $db_conns[$name] = db_connect($connect_url);
@@ -199,28 +203,32 @@ 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 '%d':
+      return db_escape_decimal($args[$current], $locator);
+    case '%f':
+      return db_escape_float($args[$current], $locator);
     case '%n':
       // Numeric values have arbitrary precision, so can't be treated as float.
       // is_numeric() allows hex values (0xFF), but they are not valid.
-      $value = trim(array_shift($args));
-      return is_numeric($value) && !preg_match('/x/i', $value) ? $value : '0';
-    case '%%':
-      return '%';
-    case '%f':
-      return (float) array_shift($args);
-    case '%b': // binary data
-      return db_encode_blob(array_shift($args));
+      return db_escape_numeric($args[$current], $locator);
+    case '%s':
+      return db_escape_string($args[$current], $locator);
+    case '%b': // Binary Large OBject.
+      return db_encode_blob($args[$current], $locator);
   }
 }
 
@@ -243,7 +251,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|%n)/');
+define('DB_QUERY_REGEXP', '/(%d|%f|%n|%s|%b)/');
 
 /**
  * Helper function for db_rewrite_sql.
@@ -265,7 +273,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;
@@ -312,7 +320,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) {
@@ -368,7 +376,7 @@ function db_rewrite_sql($query, $primary
       $query .= " $join WHERE $where";
     }
     else {
-      $query = substr($query, 0, -$pos) . " $join WHERE $where " . substr($query, -$pos);
+      $query = substr($query, 0, -$pos) ." $join WHERE $where ". substr($query, -$pos);
     }
   }
 
@@ -556,7 +564,7 @@ function db_type_placeholder($type) {
     case 'char':
     case 'text':
     case 'datetime':
-      return "'%s'";
+      return '%s';
 
     case 'numeric':
       // Numeric values are arbitrary precision numbers.  Syntacically, numerics
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	7 Feb 2008 10:17:26 -0000	1.17.2.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,533 +0,0 @@
-<?php
-// $Id: database.mysql-common.inc,v 1.17.2.1 2008/02/07 10:17:26 goba Exp $
-
-/**
- * @file
- * Functions shared between mysql and mysqli database engines.
- */
-
-/**
- * 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 %%.
- *
- *   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);
-  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);
-}
-
-/**
- * @ingroup schemaapi
- * @{
- */
-
-/**
- * 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_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['precision'] .', '. $spec['scale'] .')';
-  }
-
-  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'       => 'TINYTEXT',
-    'text:small'      => 'TINYTEXT',
-    '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.89
diff -u -p -r1.89 database.mysql.inc
--- includes/database.mysql.inc	24 Jan 2008 10:46:54 -0000	1.89
+++ includes/database.mysql.inc	9 Aug 2008 06:00:35 -0000
@@ -11,61 +11,24 @@
  * @{
  */
 
-// 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 <code>php.ini</code> 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.');
   }
 
-  // Decode url-encoded information in the db connection string
-  $url['user'] = urldecode($url['user']);
-  // Test if database url has a password.
-  $url['pass'] = isset($url['pass']) ? urldecode($url['pass']) : '';
-  $url['host'] = urldecode($url['host']);
-  $url['path'] = urldecode($url['path']);
-
   // Allow for non-standard MySQL port.
-  if (isset($url['port'])) {
-    $url['host'] = $url['host'] .':'. $url['port'];
+  if (isset($url['db_port'])) {
+    $url['db_host'] = $url['db_host'] .':'. $url['db_port'];
   }
 
   // - TRUE makes mysql_connect() always open a new link, even if
@@ -74,22 +37,61 @@ function db_connect($url) {
   //   server.
   // - 2 means CLIENT_FOUND_ROWS: return the number of found
   //   (matched) rows, not the number of affected rows.
-  $connection = @mysql_connect($url['host'], $url['user'], $url['pass'], TRUE, 2);
-  if (!$connection || !mysql_select_db(substr($url['path'], 1))) {
+  $connection = @mysql_connect($url['db_host'], $url['db_user'], $url['db_pass'], TRUE, 2);
+  if (!$connection || !mysql_select_db($url['db_name'])) {
     // Show error screen otherwise
     _db_error_page(mysql_error());
   }
 
+  // Require ANSI mode to improve SQL portability.
+  mysql_query("SET SESSION SQL_MODE = 'ANSI'", $connection);
   // Force UTF-8.
-  mysql_query('SET NAMES "utf8"', $connection);
+  mysql_query('SET NAMES "UTF8"', $connection);
   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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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) {
-  global $active_db, $queries, $user;
+  global $active_db, $last_result, $queries, $user;
 
   if (variable_get('dev_query', 0)) {
     list($usec, $sec) = explode(' ', microtime());
@@ -105,7 +107,14 @@ function _db_query($query, $debug = 0) {
     $query = '/* '. $name .' : '. $bt[2]['function'] .' */ '. $query;
   }
 
-  $result = mysql_query($query, $active_db);
+  // Execute the statement.
+  $stmt = mysql_query($query, $active_db);
+  if (mysql_errno($active_db)) {
+    // Indicate to drupal_error_handler that this is a database error.
+    ${DB_ERROR} = TRUE;
+    trigger_error(check_plain(mysql_error($active_db) ."\nquery: ". $query), E_USER_WARNING);
+    return FALSE;
+  }
 
   if (variable_get('dev_query', 0)) {
     $query = $bt[2]['function'] ."\n". $query;
@@ -119,15 +128,8 @@ function _db_query($query, $debug = 0) {
     print '<p>query: '. $query .'<br />error:'. mysql_error($active_db) .'</p>';
   }
 
-  if (!mysql_errno($active_db)) {
-    return $result;
-  }
-  else {
-    // Indicate to drupal_error_handler that this is a database error.
-    ${DB_ERROR} = TRUE;
-    trigger_error(check_plain(mysql_error($active_db) ."\nquery: ". $query), E_USER_WARNING);
-    return FALSE;
-  }
+  $last_result = $stmt;
+  return $last_result;
 }
 
 /**
@@ -141,8 +143,10 @@ function _db_query($query, $debug = 0) {
  */
 function db_fetch_object($result) {
   if ($result) {
-    return mysql_fetch_object($result);
+    $object = mysql_fetch_object($result);
+    return isset($object) ? $object : FALSE;
   }
+  return FALSE;
 }
 
 /**
@@ -157,8 +161,10 @@ function db_fetch_object($result) {
  */
 function db_fetch_array($result) {
   if ($result) {
-    return mysql_fetch_array($result, MYSQL_ASSOC);
+    $array = mysql_fetch_array($result, MYSQL_ASSOC);
+    return isset($array) ? $array : FALSE;
   }
+  return FALSE;
 }
 
 /**
@@ -177,7 +183,7 @@ function db_result($result) {
     // The mysql_fetch_row function has an optional second parameter $row
     // but that can't be used for compatibility with Oracle, DB2, etc.
     $array = mysql_fetch_row($result);
-    return $array[0];
+    return isset($array[0]) ? $array[0] : FALSE;
   }
   return FALSE;
 }
@@ -198,172 +204,79 @@ 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.
+/*
+ * Prepare user input for use in a database query, preventing SQL injection attacks.
  *
- * @param $from
- *   The first result row to return.
- * @param $count
- *   The maximum number of result rows to return.
+ * @param $data
+ *   Data to encode.
  * @return
- *   A database query result resource, or FALSE if the query was not executed
- *   correctly.
+ *   Encoded data.
  */
-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.
+ * Prepare user input for use in a database query, preventing SQL injection attacks.
  *
- * @param $table
- *   The name of the temporary table to select into. This name will not be
- *   prefixed as there is no risk of collision.
+ * @param $data
+ *   Data to encode.
  * @return
- *   A database query result resource, or FALSE if the query was not executed
- *   correctly.
+ *   Encoded data.
  */
-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', 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);
+function db_escape_float($data) {
+  return (float) $data;
 }
 
 /**
- * Returns a properly formatted Binary Large OBject value.
+ * Prepare user input for use in a database query, preventing SQL injection attacks.
  *
  * @param $data
  *   Data to encode.
  * @return
- *  Encoded data.
+ *   Encoded data.
  */
-function db_encode_blob($data) {
-  global $active_db;
-  return "'". mysql_real_escape_string($data, $active_db) ."'";
+function db_escape_numeric($data) {
+  $data = trim($data);
+  return is_numeric($data) && !preg_match('/x/i', $data) ? $data : '0';
 }
 
 /**
- * Returns text from a Binary Large Object value.
+ * Prepare user input for use in a database query, preventing SQL injection attacks.
  *
  * @param $data
- *   Data to decode.
+ *   Data to encode.
  * @return
- *  Decoded data.
+ *   Encoded data.
  */
-function db_decode_blob($data) {
-  return $data;
-}
-
-/**
- * Prepare user input for use in a database query, preventing SQL injection attacks.
- */
-function db_escape_string($text) {
+function db_escape_string($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) ."}'"));
+  return "'". mysql_real_escape_string($data, $active_db) ."'";
 }
 
 /**
- * Check if a column exists in the given table.
+ * Returns a properly formatted Binary Large OBject value.
+ *
+ * @param $data
+ *   Data to encode.
+ * @return
+ *   Encoded data.
  */
-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) ."'"));
+function db_encode_blob($data) {
+  global $active_db;
+  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 Binary 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 .')';
-  // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
-  return preg_replace('/(SELECT.*)(?:'. $table .'\.|\s)(?<!DISTINCT\()(?<!DISTINCT\('. $table .'\.)'. $field .'(.*FROM )/AUsi', '\1 '. $field_to_select .'\2', $query);
+function db_decode_blob($data) {
+  return $data;
 }
 
 /**
Index: includes/database.mysqli.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database.mysqli.inc,v
retrieving revision 1.54
diff -u -p -r1.54 database.mysqli.inc
--- includes/database.mysqli.inc	23 Jan 2008 09:59:29 -0000	1.54
+++ includes/database.mysqli.inc	9 Aug 2008 06:00:35 -0000
@@ -3,93 +3,91 @@
 
 /**
  * @file
- * Database interface code for MySQL database servers using the mysqli client libraries. mysqli is included in PHP 5 by default and allows developers to use the advanced features of MySQL 4.1.x, 5.0.x and beyond.
+ * Database interface code for MySQL database servers using the mysqli client
+ * libraries. mysqli is included in PHP 5 by default and allows developers to
+ * use the advanced features of MySQL 4.1.x, 5.0.x and beyond.
+ * Check http://www.php.net/manual/en/ref.mysqli.php for more information.
  */
 
- // Maintainers of this file should consult:
- // http://www.php.net/manual/en/ref.mysqli.php
-
 /**
  * @ingroup database
  * @{
  */
 
-// Include functions shared between mysql and mysqli.
-require_once './includes/database.mysql-common.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;
-}
+// Include functions shared between mysql, mysqli and pdo_mysql.
+require_once './includes/common.mysql.inc';
 
-/**
- * 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.
+ * Initialize a database connection.
  *
  * Note that mysqli does not support persistent connections.
  */
 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 <code>php.ini</code> 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.
-  $url['pass'] = isset($url['pass']) ? urldecode($url['pass']) : '';
-  $url['host'] = urldecode($url['host']);
-  $url['path'] = urldecode($url['path']);
-  if (!isset($url['port'])) {
-    $url['port'] = NULL;
+  // Check if MySQL support is present in PHP
+  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.');
   }
 
   $connection = mysqli_init();
-  @mysqli_real_connect($connection, $url['host'], $url['user'], $url['pass'], substr($url['path'], 1), $url['port'], NULL, MYSQLI_CLIENT_FOUND_ROWS);
+  @mysqli_real_connect($connection, $url['db_host'], $url['db_user'], $url['db_pass'], $url['db_name'], $url['db_port'], NULL, MYSQLI_CLIENT_FOUND_ROWS);
 
   if (mysqli_connect_errno() > 0) {
     _db_error_page(mysqli_connect_error());
   }
 
+  // Require ANSI mode to improve SQL portability.
+  mysqli_query($connection, "SET SESSION SQL_MODE = 'ANSI'");
   // Force UTF-8.
-  mysqli_query($connection, 'SET NAMES "utf8"');
+  mysqli_query($connection, 'SET NAMES "UTF8"');
 
   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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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) {
-  global $active_db, $queries, $user;
+  global $active_db, $last_result, $queries, $user;
 
   if (variable_get('dev_query', 0)) {
     list($usec, $sec) = explode(' ', microtime());
@@ -98,14 +96,21 @@ function _db_query($query, $debug = 0) {
     // 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'
+    // 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;
   }
 
-  $result = mysqli_query($active_db, $query);
+  // Execute the statement.
+  $stmt = mysqli_query($active_db, $query);
+  if (mysqli_errno($active_db)) {
+    // Indicate to drupal_error_handler that this is a database error.
+    ${DB_ERROR} = TRUE;
+    trigger_error(check_plain(mysqli_error($active_db) ."\nquery: ". $query), E_USER_WARNING);
+    return FALSE;
+  }
 
   if (variable_get('dev_query', 0)) {
     $query = $bt[2]['function'] ."\n". $query;
@@ -119,15 +124,8 @@ function _db_query($query, $debug = 0) {
     print '<p>query: '. $query .'<br />error:'. mysqli_error($active_db) .'</p>';
   }
 
-  if (!mysqli_errno($active_db)) {
-    return $result;
-  }
-  else {
-    // Indicate to drupal_error_handler that this is a database error.
-    ${DB_ERROR} = TRUE;
-    trigger_error(check_plain(mysqli_error($active_db) ."\nquery: ". $query), E_USER_WARNING);
-    return FALSE;
-  }
+  $last_result = $stmt;
+  return $last_result;
 }
 
 /**
@@ -144,6 +142,7 @@ function db_fetch_object($result) {
     $object = mysqli_fetch_object($result);
     return isset($object) ? $object : FALSE;
   }
+  return FALSE;
 }
 
 /**
@@ -161,6 +160,7 @@ function db_fetch_array($result) {
     $array = mysqli_fetch_array($result, MYSQLI_ASSOC);
     return isset($array) ? $array : FALSE;
   }
+  return FALSE;
 }
 
 /**
@@ -179,7 +179,7 @@ function db_result($result) {
     // The mysqli_fetch_row function has an optional second parameter $row
     // but that can't be used for compatibility with Oracle, DB2, etc.
     $array = mysqli_fetch_row($result);
-    return $array[0];
+    return isset($array[0]) ? $array[0] : FALSE;
   }
   return FALSE;
 }
@@ -196,179 +196,85 @@ function db_error() {
  * Determine the number of rows changed by the preceding query.
  */
 function db_affected_rows() {
-  global $active_db; /* mysqli connection resource */
+  global $active_db;
   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.
+/*
+ * Prepare user input for use in a database query, preventing SQL injection attacks.
  *
- * @param $from
- *   The first result row to return.
- * @param $count
- *   The maximum number of result rows to return.
+ * @param $data
+ *   Data to encode.
  * @return
- *   A database query result resource, or FALSE if the query was not executed
- *   correctly.
+ *   Encoded data.
  */
-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.
+ * Prepare user input for use in a database query, preventing SQL injection attacks.
  *
- * @param $table
- *   The name of the temporary table to select into. This name will not be
- *   prefixed as there is no risk of collision.
+ * @param $data
+ *   Data to encode.
  * @return
- *   A database query result resource, or FALSE if the query was not executed
- *   correctly.
+ *   Encoded data.
  */
-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', 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);
+function db_escape_float($data) {
+  return (float) $data;
 }
 
 /**
- * Returns a properly formatted Binary Large Object value.
+ * Prepare user input for use in a database query, preventing SQL injection attacks.
  *
  * @param $data
  *   Data to encode.
  * @return
- *  Encoded data.
+ *   Encoded data.
  */
-function db_encode_blob($data) {
-  global $active_db;
-  return "'". mysqli_real_escape_string($active_db, $data) ."'";
+function db_escape_numeric($data) {
+  $data = trim($data);
+  return is_numeric($data) && !preg_match('/x/i', $data) ? $data : '0';
 }
 
 /**
- * Returns text from a Binary Large OBject value.
+ * Prepare user input for use in a database query, preventing SQL injection attacks.
  *
  * @param $data
- *   Data to decode.
+ *   Data to encode.
  * @return
- *  Decoded data.
+ *   Encoded data.
  */
-function db_decode_blob($data) {
-  return $data;
-}
-
-/**
- * Prepare user input for use in a database query, preventing SQL injection attacks.
- */
-function db_escape_string($text) {
+function db_escape_string($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) ."}'"));
+  return "'". mysqli_real_escape_string($active_db, $data) ."'";
 }
 
 /**
- * Check if a column exists in the given table.
+ * Returns a properly formatted Binary Large OBject value.
+ *
+ * @param $data
+ *   Data to encode.
+ * @return
+ *   Encoded data.
  */
-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) ."'"));
+function db_encode_blob($data) {
+  global $active_db;
+  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 Binary 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 .')';
-  // (?<!text) is a negative look-behind (no need to rewrite queries that already use DISTINCT).
-  return preg_replace('/(SELECT.*)(?:'. $table .'\.|\s)(?<!DISTINCT\()(?<!DISTINCT\('. $table .'\.)'. $field .'(.*FROM )/AUsi', '\1 '. $field_to_select .'\2', $query);
+function db_decode_blob($data) {
+  return $data;
 }
 
 /**
  * @} End of "ingroup database".
  */
-
Index: includes/database.oci8.inc
===================================================================
RCS file: includes/database.oci8.inc
diff -N includes/database.oci8.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/database.oci8.inc	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,406 @@
+<?php
+// $Id: database.oci8.inc,v 1.2 2007/12/11 07:21:32 hswong3i Exp $
+
+/**
+ * @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 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.');
+  }
+
+  // Build oci8 connection string and allow for non-standard Oracle port.
+  $conn_string = '//'. $url['db_host'] . (isset($url['db_port']) ? ':'. $url['db_port'] : '') .'/'. $url['db_name'];
+
+  // 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['db_user'], $url['db_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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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;
+
+  // 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;
+  }
+
+  $stmt = oci_parse($active_db, $query);
+  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]['type']) && $args[$key]['type'] == SQLT_BLOB) {
+        // Bind the returned Oracle LOB locator to the PHP LOB object.
+        $args[$key]['obj'] = oci_new_descriptor($active_db, OCI_D_LOB);
+        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']);
+      }
+    }
+  }
+
+  // Oracle need to preform INSERT/UPDATE under a transcation, otherwise the
+  // newly inserted LOB will be committed with a zero-length.
+  // 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;
+  }
+
+  // A LOB Locator tells Oracle where it stashed the actual LOB contents
+  // without making the table rows overly large, and allows some clever
+  // optimizations when manipulating LOBs. You can't just conjure up a LOB
+  // Locator though, so you need to insert a brand new empty LOB into a table
+  // and then fetch it's locator back out before you can start modifying it.
+  // Check http://netevil.org/uuid/4365876a-cee9-3009-7726-365876a51802 for more information.
+  if (count($args)) {
+    foreach ($args as $key => $value) {
+      if (isset($args[$key]['type']) && $args[$key]['type'] == SQLT_BLOB) {
+        // Flush existing data before action.
+        @$args[$key]['obj']->truncate();
+        // Save value into Oracle object.
+        @$args[$key]['obj']->save($args[$key]['data']);
+        // Free resources.
+        @$args[$key]['obj']->free();
+      }
+    }
+  }
+
+  // On success, commit the transaction.
+  oci_commit($active_db);
+
+  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) {
+    $error = oci_error($stmt);
+    print '<p>query: '. $query .'<br />error:'. $error['message'] .'</p>';
+  }
+
+  $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 != ORACLE_EMPTY_STRING_PLACEHOLDER ? $value : '';
+      }
+      return isset($return) ? $return : FALSE;
+    }
+  }
+  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 != ORACLE_EMPTY_STRING_PLACEHOLDER ? $value : '';
+      }
+      return isset($return) ? $return : FALSE;
+    }
+  }
+  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 != ORACLE_EMPTY_STRING_PLACEHOLDER ? $value : '';
+      return isset($return) ? $return : FALSE;
+    }
+  }
+  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,
+  );
+  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_numeric(&$data, $locator) {
+  $data = trim($data);
+  $data = is_numeric($data) && !preg_match('/x/i', $data) ? $data : '0';
+  $data = array(
+    'locator' => $locator,
+    'data' => $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 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})(.*)/u', '\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) {
+  // Replace as empty string placeholder, if not an empty string nor NULL.
+  $data = ($data !== '' && !is_null($data)) ? $data : ORACLE_EMPTY_STRING_PLACEHOLDER;
+
+  $data = array(
+    'locator' => $locator,
+    'data' => $data,
+    'type' => SQLT_BLOB,
+  );
+  return $locator;
+}
+
+/**
+ * Returns text from a Binary Large OBject value.
+ *
+ * @param $data
+ *   Data to decode.
+ * @return
+ *   Decoded data.
+ */
+function db_decode_blob($data) {
+  // In case of Oracle LOBs are read via LOB->load().
+  return $data->load();
+}
+
+/**
+ * @} End of "ingroup database".
+ */
Index: includes/database.pdo_ibm.inc
===================================================================
RCS file: includes/database.pdo_ibm.inc
diff -N includes/database.pdo_ibm.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/database.pdo_ibm.inc	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,364 @@
+<?php
+// $Id: database.pdo_ibm.inc,v 1.3 2007/12/11 07:21:32 hswong3i Exp $
+
+/**
+ * @file
+ * Database interface code for DB2 database servers.
+ */
+
+/**
+ * @ingroup database
+ * @{
+ */
+
+// Include functions shared between pgsql and pdo_ibm.
+require_once './includes/common.db2.inc';
+
+// Include schema API shared between pgsql and pdo_ibm.
+require_once './includes/schema.db2.inc';
+
+/**
+ * Initialize a database connection.
+ */
+function db_connect($url) {
+  // Check if PDO DB2 support is present in PHP.
+  if (!(class_exists('PDO') && extension_loaded('pdo_ibm'))) {
+    _db_error_page('Unable to use the DB2 database because the pdo_ibm extension for PHP is not installed. Check your php.ini to see how you can enable it.');
+  }
+
+  // Build pdo_ibm connection string and allow for non-standard DB2 port.
+  $dsn[] = 'PROTOCOL=TCPIP';
+  $dsn[] = isset($url['db_host']) ? 'HOSTNAME='. $url['db_host'] : NULL;
+  $dsn[] = isset($url['db_port']) ? 'PORT='. $url['db_port'] : 'PORT=50000';
+  $dsn[] = isset($url['db_name']) ? 'DATABASE='. $url['db_name'] : NULL;
+  $dsn = 'ibm:'. implode(';', $dsn);
+
+  $driver_options = array(
+    // Throw a PDOException and set its properties to reflect the error code
+    // and error information.
+    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+    //  Leave column names as returned by the database driver.
+    PDO::ATTR_CASE => PDO::CASE_NATURAL,
+  );
+
+  try {
+    $connection = new PDO($dsn, $url['db_user'], $url['db_pass'], $driver_options);
+  } catch (PDOExecption $e) {
+    _db_error_page($e->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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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;
+
+  // 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;
+  }
+
+  $stmt = $active_db->prepare($query);
+  if ($stmt === FALSE) {
+    $error = $active_db->errorInfo();
+    if (is_array($error) && $error[0] != 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']);
+      }
+    }
+  }
+
+  // Execute the statement.
+  $result = $stmt->execute();
+  if ($result === FALSE) {
+    $error = $stmt->errorInfo();
+    if (is_array($error) && $error[0] != 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) {
+    $error = $active_db->errorInfo();
+    print '<p>query: '. $query .'<br />error:'. $error[2] .'</p>';
+  }
+
+  $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;
+  }
+  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) {
+    $array = $result->fetch(PDO::FETCH_ASSOC);
+    return isset($array) ? $array : FALSE;
+  }
+  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) {
+    $array = $result->fetch(PDO::FETCH_NUM);
+    return isset($array[0]) ? $array[0] : FALSE;
+  }
+  return FALSE;
+}
+
+/**
+ * Determine whether the previous query caused an error.
+ */
+function db_error() {
+  global $last_result;
+  $error = $last_result->errorInfo();
+  if (is_array($error) && 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_numeric(&$data, $locator) {
+  $data = trim($data);
+  $data = is_numeric($data) && !preg_match('/x/i', $data) ? $data : '0';
+  $data = array(
+    'locator' => $locator,
+    'data' => $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, since functions in the SYSFUN schema taking
+  // a VARCHAR as an argument will not accept VARCHARs greater than 4000
+  // bytes long as an argument.
+  $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.
+ *
+ * @param $data
+ *   Data to decode.
+ * @return
+ *   Decoded data.
+ */
+function db_decode_blob($data) {
+  // pdo_ibm 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);
+}
+
+/**
+ * @} 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	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,366 @@
+<?php
+// $Id: database.pdo_mysql.inc,v 1.2 2007/12/11 07:21:32 hswong3i Exp $
+
+/**
+ * @file
+ * Database interface code for MySQL database servers.
+ */
+
+/**
+ * @ingroup database
+ * @{
+ */
+
+// Include functions shared between mysql, mysqli and pdo_mysql.
+require_once './includes/common.mysql.inc';
+
+// Include schema API shared between mysql, mysqli and pdo_mysql.
+require_once './includes/schema.mysql.inc';
+
+/**
+ * Initialize a database connection.
+ */
+function db_connect($url) {
+  // Check if PDO MySQL support is present in PHP.
+  if (!(class_exists('PDO') && extension_loaded('pdo_mysql'))) {
+    _db_error_page('Unable to use the MySQL database because the pdo_mysql extension for PHP is not installed. Check your php.ini to see how you can enable it.');
+  }
+
+  // Build pdo_mysql connection string and allow for non-standard MySQL port.
+  $dsn[] = isset($url['db_host']) ? 'host='. $url['db_host'] : NULL;
+  $dsn[] = isset($url['db_port']) ? 'port='. $url['db_port'] : 'port=3306';
+  $dsn[] = isset($url['db_name']) ? 'dbname='. $url['db_name'] : NULL;
+  $dsn = 'mysql:'. implode(';', $dsn);
+
+  $driver_options = array(
+    // Throw a PDOException and set its properties to reflect the error code
+    // and error information.
+    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+    //  Leave column names as returned by the database driver.
+    PDO::ATTR_CASE => PDO::CASE_NATURAL,
+    // Force MySQL driver will use the buffered versions of the MySQL API.
+    PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
+  );
+
+  try {
+    $connection = new PDO($dsn, $url['db_user'], $url['db_pass'], $driver_options);
+  } catch (PDOExecption $e) {
+    _db_error_page($e->getMessage());
+  }
+
+  // Require ANSI mode to improve SQL portability.
+  $stmt = $connection->exec("SET SESSION SQL_MODE = 'ANSI'");
+  // Force UTF-8
+  $stmt = $connection->exec('SET NAMES "UTF8"');
+
+  // 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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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;
+
+  // 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;
+  }
+
+  $stmt = $active_db->prepare($query);
+  if ($stmt === FALSE) {
+    $error = $active_db->errorInfo();
+    if (is_array($error) && $error[0] != 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']);
+      }
+    }
+  }
+
+  // Execute the statement.
+  $result = $stmt->execute();
+  if ($result === FALSE) {
+    $error = $stmt->errorInfo();
+    if (is_array($error) && $error[0] != 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) {
+    $error = $active_db->errorInfo();
+    print '<p>query: '. $query .'<br />error:'. $error[2] .'</p>';
+  }
+
+  $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;
+  }
+  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) {
+    $array = $result->fetch(PDO::FETCH_ASSOC);
+    return isset($array) ? $array : FALSE;
+  }
+  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) {
+    $array = $result->fetch(PDO::FETCH_NUM);
+    return isset($array[0]) ? $array[0] : FALSE;
+  }
+  return FALSE;
+}
+
+/**
+ * Determine whether the previous query caused an error.
+ */
+function db_error() {
+  global $last_result;
+  $error = $last_result->errorInfo();
+  if (is_array($error) && 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_numeric(&$data, $locator) {
+  $data = trim($data);
+  $data = is_numeric($data) && !preg_match('/x/i', $data) ? $data : '0';
+  $data = array(
+    'locator' => $locator,
+    'data' => $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) {
+  $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) {
+  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	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,420 @@
+<?php
+// $Id: database.pdo_oci.inc,v 1.1 2007/12/11 07:21:32 hswong3i Exp $
+
+/**
+ * @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 Oracle 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.');
+  }
+
+  // Build pdo_oci connection string and allow for non-standard Oracle port.
+  // Connect with Oracle Instant Client partten.
+  $dsn = 'oci://'. $url['db_host'] . (isset($url['db_port']) ? ':'. $url['db_port'] : ':1521') .'/'. $url['db_name'];
+
+  $driver_options = array(
+    // Throw a PDOException and set its properties to reflect the error code
+    // and error information.
+    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+    //  Leave column names as returned by the database driver.
+    PDO::ATTR_CASE => PDO::CASE_NATURAL,
+    // Disable autocommit so that the connection begins a transaction.
+    PDO::ATTR_AUTOCOMMIT => FALSE,
+  );
+
+  try {
+    $connection = new PDO($dsn, $url['db_user'], $url['db_pass'], $driver_options);
+  } catch (PDOExecption $e) {
+    _db_error_page($e->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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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;
+
+  // 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;
+  }
+
+  $stmt = $active_db->prepare($query);
+  if ($stmt === FALSE) {
+    $error = $active_db->errorInfo();
+    if (is_array($error) && $error[0] != 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;
+  }
+
+  if (count($args)) {
+    foreach ($args as $key => $value) {
+      if (isset($args[$key]['type']) && $args[$key]['type'] == PDO::PARAM_LOB) {
+        // Bind the returned Oracle LOB locator to the PHP file handler.
+        // Use PDOStatement->bindParam() here for stream I/O handling.
+        $stmt->bindParam($args[$key]['locator'], $args[$key]['obj'], $args[$key]['type']);
+        $args[$key]['obj'] = NULL;
+      }
+      else 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']);
+      }
+    }
+  }
+
+  // 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.
+  $active_db->beginTransaction();
+
+  try {
+    // Execute the statement.
+    $result = $stmt->execute();
+
+    // A LOB Locator tells Oracle where it stashed the actual LOB contents
+    // without making the table rows overly large, and allows some clever
+    // optimizations when manipulating LOBs. You can't just conjure up a LOB
+    // Locator though, so you need to insert a brand new empty LOB into a table
+    // and then fetch it's locator back out before you can start modifying it.
+    // Check http://netevil.org/uuid/4365876a-cee9-3009-7726-365876a51802 for more information.
+    if (count($args)) {
+      foreach ($args as $key => $value) {
+        if (isset($args[$key]['type']) && $args[$key]['type'] == PDO::PARAM_LOB) {
+          // Flush existing data before action.
+          fflush($args[$key]['obj']);
+          // Save value into INPUT/OUTPUT BLOB handler.
+          fwrite($args[$key]['obj'], $args[$key]['data']);
+          // Free resources.
+          fclose($args[$key]['obj']);
+        }
+      }
+    }
+
+    // On success, commit the transaction.
+    $active_db->commit();
+  }
+  catch (Exception $e) {
+    // Indicate to drupal_error_handler that this is a database error.
+    ${DB_ERROR} = TRUE;
+    trigger_error(check_plain($e->getMessage() ."\nquery: ". $query), E_USER_WARNING);
+    $active_db->rollBack();
+  }
+
+  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) {
+    $error = $active_db->errorInfo();
+    print '<p>query: '. $query .'<br />error:'. $error[2] .'</p>';
+  }
+
+  $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)) {
+      $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 != ORACLE_EMPTY_STRING_PLACEHOLDER ? $value : '';
+      }
+      return isset($return) ? $return : FALSE;
+    }
+  }
+  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)) {
+      $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 != ORACLE_EMPTY_STRING_PLACEHOLDER ? $value : '';
+      }
+      return isset($return) ? $return : FALSE;
+    }
+  }
+  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.
+      $return = $array[0] != ORACLE_EMPTY_STRING_PLACEHOLDER ? $array[0] : '';
+      return isset($return) ? $return : FALSE;
+    }
+  }
+  return FALSE;
+}
+
+/**
+ * Determine whether the previous query caused an error.
+ */
+function db_error() {
+  global $last_result;
+  $error = $last_result->errorInfo();
+  if (is_array($error) && 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_numeric(&$data, $locator) {
+  $data = trim($data);
+  $data = is_numeric($data) && !preg_match('/x/i', $data) ? $data : '0';
+  $data = array(
+    'locator' => $locator,
+    'data' => $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 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})(.*)/u', '\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) {
+  // Replace as empty string placeholder, if not an empty string nor NULL.
+  $data = ($data !== '' && !is_null($data)) ? $data : ORACLE_EMPTY_STRING_PLACEHOLDER;
+
+  $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_oci 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);
+}
+
+/**
+ * @} 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	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,361 @@
+<?php
+// $Id: database.pdo_pgsql.inc,v 1.3 2007/12/11 07:21:32 hswong3i Exp $
+
+/**
+ * @file
+ * Database interface code for PostgreSQL database servers.
+ */
+
+/**
+ * @ingroup database
+ * @{
+ */
+
+// Include functions shared between pgsql and pdo_pgsql.
+require_once './includes/common.postgresql.inc';
+
+// 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 PDO PostgreSQL support is present in PHP.
+  if (!(class_exists('PDO') && extension_loaded('pdo_pgsql'))) {
+    _db_error_page('Unable to use the PostgreSQL database because the pdo_pgsql extension for PHP is not installed. Check your php.ini to see how you can enable it.');
+  }
+
+  // Build pdo_pgsql connection string and allow for non-standard PostgreSQL port.
+  $dsn[] = isset($url['db_host']) ? 'host='. $url['db_host'] : NULL;
+  $dsn[] = isset($url['db_port']) ? 'port='. $url['db_port'] : 'port=5432';
+  $dsn[] = isset($url['db_name']) ? 'dbname='. $url['db_name'] : NULL;
+  $dsn = 'pgsql:'. implode(' ', $dsn);
+
+  $driver_options = array(
+    // Throw a PDOException and set its properties to reflect the error code
+    // and error information.
+    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+    //  Leave column names as returned by the database driver.
+    PDO::ATTR_CASE => PDO::CASE_NATURAL,
+  );
+
+  try {
+    $connection = new PDO($dsn, $url['db_user'], $url['db_pass'], $driver_options);
+  } catch (PDOExecption $e) {
+    _db_error_page($e->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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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;
+
+  // 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;
+  }
+
+  $stmt = $active_db->prepare($query);
+  if ($stmt === FALSE) {
+    $error = $active_db->errorInfo();
+    if (is_array($error) && $error[0] != 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']);
+      }
+    }
+  }
+
+  // Execute the statement.
+  $result = $stmt->execute();
+  if ($result === FALSE) {
+    $error = $stmt->errorInfo();
+    if (is_array($error) && $error[0] != 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) {
+    $error = $active_db->errorInfo();
+    print '<p>query: '. $query .'<br />error:'. $error[2] .'</p>';
+  }
+
+  $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;
+  }
+  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) {
+    $array = $result->fetch(PDO::FETCH_ASSOC);
+    return isset($array) ? $array : FALSE;
+  }
+  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) {
+    $array = $result->fetch(PDO::FETCH_NUM);
+    return isset($array[0]) ? $array[0] : FALSE;
+  }
+  return FALSE;
+}
+
+/**
+ * Determine whether the previous query caused an error.
+ */
+function db_error() {
+  global $last_result;
+  $error = $last_result->errorInfo();
+  if (is_array($error) && 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_numeric(&$data, $locator) {
+  $data = trim($data);
+  $data = is_numeric($data) && !preg_match('/x/i', $data) ? $data : '0';
+  $data = array(
+    'locator' => $locator,
+    'data' => $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);
+}
+
+/**
+ * @} End of "ingroup database".
+ */
Index: includes/database.pdo_sqlite.inc
===================================================================
RCS file: includes/database.pdo_sqlite.inc
diff -N includes/database.pdo_sqlite.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/database.pdo_sqlite.inc	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,362 @@
+<?php
+// $Id: database.pdo_sqlite.inc,v 1.1 2008/02/03 10:08:54 hswong3i Exp $
+
+/**
+ * @file
+ * Database interface code for SQLite database servers.
+ */
+
+/**
+ * @ingroup database
+ * @{
+ */
+
+// Include functions shared between sqlite and pdo_sqlite.
+require_once './includes/common.sqlite.inc';
+
+// Include schema API shared between sqlite and pdo_sqlite.
+require_once './includes/schema.sqlite.inc';
+
+/**
+ * Initialize a database connection.
+ */
+function db_connect($url) {
+  // Check if PDO SQLite support is present in PHP.
+  if (!(class_exists('PDO') && extension_loaded('pdo_sqlite'))) {
+    _db_error_page('Unable to use the SQLite database because the pdo_sqlite extension for PHP is not installed. Check your php.ini to see how you can enable it.');
+  }
+
+  // Build pdo_sqlite connection string.
+  $dsn = 'sqlite:'. isset($url['db_name']) ? $url['db_name'] : ':memory';
+
+  $driver_options = array(
+    // Throw a PDOException and set its properties to reflect the error code
+    // and error information.
+    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+    //  Leave column names as returned by the database driver.
+    PDO::ATTR_CASE => PDO::CASE_NATURAL,
+  );
+
+  try {
+    $connection = new PDO($dsn, $username, $password, $driver_options);
+  } catch (PDOExecption $e) {
+    _db_error_page($e->getMessage());
+  }
+
+  // Modify the operation of the SQLite library
+  $connection->exec('PRAGMA SYNCHRONOUS = OFF');
+  $connection->exec('PRAGMA SHORT_COLUMN_NAMES = 1');
+  $connection->exec('PRAGMA TEMP_STORE = MEMORY');
+  $connection->exec('PRAGMA CACHE_SIZE = 5120');
+  $connection->exec('PRAGMA COUNT_CHANGES = OFF');
+  $connection->exec('PRAGMA ENCODING = "UTF-8"');
+
+  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 and %b (binary data, do not enclose
+ *   in '').
+ *
+ *   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, $user;
+
+  // 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;
+  }
+
+  $stmt = $active_db->prepare($query);
+  if ($stmt === FALSE) {
+    $error = $active_db->errorInfo();
+    if (is_array($error) && $error[0] != 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']);
+      }
+    }
+  }
+
+  // Execute the statement.
+  $result = $stmt->execute();
+  if ($result === FALSE) {
+    $error = $stmt->errorInfo();
+    if (is_array($error) && $error[0] != 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) {
+    $error = $active_db->errorInfo();
+    print '<p>query: '. $query .'<br />error:'. $error[2] .'</p>';
+  }
+
+  $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;
+  }
+  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) {
+    $array = $result->fetch(PDO::FETCH_ASSOC);
+    return isset($array) ? $array : FALSE;
+  }
+  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) {
+    $array = $result->fetch(PDO::FETCH_NUM);
+    return isset($array[0]) ? $array[0] : FALSE;
+  }
+  return FALSE;
+}
+
+/**
+ * Determine whether the previous query caused an error.
+ */
+function db_error() {
+  global $last_result;
+  $error = $last_result->errorInfo();
+  if (is_array($error) && 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_numeric(&$data, $locator) {
+  $data = trim($data);
+  $data = is_numeric($data) && !preg_match('/x/i', $data) ? $data : '0';
+  $data = array(
+    'locator' => $locator,
+    'data' => $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) {
+  $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) {
+  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.2.2
diff -u -p -r1.68.2.2 database.pgsql.inc
--- includes/database.pgsql.inc	8 Jul 2008 09:50:03 -0000	1.68.2.2
+++ includes/database.pgsql.inc	9 Aug 2008 06:00:35 -0000
@@ -11,64 +11,29 @@
  * @{
  */
 
-/**
- * Report database status.
- */
-function db_status_report() {
-  $t = get_t();
-
-  $version = db_version();
+// Include functions shared between pgsql and pdo_pgsql.
+require_once './includes/common.postgresql.inc';
 
-  $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;
-}
-
-/**
- * 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 <code>php.ini</code> 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);
-  $conn_string = '';
-
   // Decode url-encoded information in the db connection string
-  if (isset($url['user'])) {
-    $conn_string .= ' user='. urldecode($url['user']);
-  }
-  if (isset($url['pass'])) {
-    $conn_string .= ' password='. urldecode($url['pass']);
-  }
-  if (isset($url['host'])) {
-    $conn_string .= ' host='. urldecode($url['host']);
-  }
-  if (isset($url['path'])) {
-    $conn_string .= ' dbname='. substr(urldecode($url['path']), 1);
-  }
-  if (isset($url['port'])) {
-    $conn_string .= ' port='. urldecode($url['port']);
-  }
+  $conn_string[] = isset($url['db_host']) ? 'host='. $url['db_host'] : NULL;
+  $conn_string[] = isset($url['db_port']) ? 'port='. $url['db_port'] : NULL;
+  $conn_string[] = isset($url['db_name']) ? 'dbname='. $url['db_name'] : NULL;
+  $conn_string[] = isset($url['db_user']) ? 'user='. $url['db_user'] : NULL;
+  $conn_string[] = isset($url['db_pass']) ? 'password='. $url['db_pass'] : NULL;
+
+  $conn_string = implode(' ', array_filter($conn_string));
 
   // pg_last_error() does not return a useful error message for database
   // connection errors. We must turn on error tracking to get at a good error
@@ -102,8 +67,8 @@ function db_connect($url) {
  *   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 %%.
+ *   Valid %-modifiers are: %s, %d, %f and %b (binary data, do not enclose
+ *   in '').
  *
  *   NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
  *   and TRUE values to decimal 1.
@@ -116,10 +81,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);
 }
@@ -128,17 +94,31 @@ function db_query($query) {
  * Helper function for db_query().
  */
 function _db_query($query, $debug = 0) {
-  global $active_db, $last_result, $queries;
+  global $active_db, $last_result, $queries, $user;
 
   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 = pg_query($active_db, $query);
+  $stmt = pg_query($active_db, $query);
+  if ($stmt === FALSE) {
+    // Indicate to drupal_error_handler that this is a database error.
+    ${DB_ERROR} = TRUE;
+    trigger_error(check_plain(pg_last_error($active_db) ."\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;
@@ -150,15 +130,8 @@ function _db_query($query, $debug = 0) {
     print '<p>query: '. $query .'<br />error:'. pg_last_error($active_db) .'</p>';
   }
 
-  if ($last_result !== FALSE) {
-    return $last_result;
-  }
-  else {
-    // Indicate to drupal_error_handler that this is a database error.
-    ${DB_ERROR} = TRUE;
-    trigger_error(check_plain(pg_last_error($active_db) ."\nquery: ". $query), E_USER_WARNING);
-    return FALSE;
-  }
+  $last_result = $stmt;
+  return $last_result;
 }
 
 /**
@@ -172,8 +145,10 @@ function _db_query($query, $debug = 0) {
  */
 function db_fetch_object($result) {
   if ($result) {
-    return pg_fetch_object($result);
+    $object = pg_fetch_object($result);
+    return isset($object) ? $object : FALSE;
   }
+  return FALSE;
 }
 
 /**
@@ -188,8 +163,10 @@ function db_fetch_object($result) {
  */
 function db_fetch_array($result) {
   if ($result) {
-    return pg_fetch_assoc($result);
+    $array = pg_fetch_assoc($result);
+    return isset($array) ? $array : FALSE;
   }
+  return FALSE;
 }
 
 /**
@@ -206,7 +183,7 @@ function db_fetch_array($result) {
 function db_result($result) {
   if ($result && pg_num_rows($result) > 0) {
     $array = pg_fetch_row($result);
-    return $array[0];
+    return isset($array[0]) ? $array[0] : FALSE;
   }
   return FALSE;
 }
@@ -220,711 +197,88 @@ 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() {
   global $last_result;
-  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.
- */
-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);
+  return pg_affected_rows($last_result);
 }
 
-/**
- * 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.
+/*
+ * Prepare user input for use in a database query, preventing SQL injection attacks.
  *
- * @param $table
- *   The name of the temporary table to select into. This name will not be
- *   prefixed as there is no risk of collision.
+ * @param $data
+ *   Data to encode.
  * @return
- *   A database query result resource, or FALSE if the query was not executed
- *   correctly.
+ *   Encoded data.
  */
-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', 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);
+function db_escape_decimal($data) {
+  return (int) $data;
 }
 
 /**
- * Returns a properly formatted Binary Large OBject value.
- * In case of PostgreSQL encodes data for insert into bytea field.
+ * Prepare user input for use in a database query, preventing SQL injection attacks.
  *
  * @param $data
  *   Data to encode.
  * @return
- *  Encoded data.
+ *   Encoded data.
  */
-function db_encode_blob($data) {
-  return "'". pg_escape_bytea($data) ."'";
+function db_escape_float($data) {
+  return (float) $data;
 }
 
 /**
- * Returns text from a Binary Large OBject value.
- * In case of PostgreSQL decodes data after select from bytea field.
+ * Prepare user input for use in a database query, preventing SQL injection attacks.
  *
  * @param $data
- *   Data to decode.
+ *   Data to encode.
  * @return
- *  Decoded data.
+ *   Encoded data.
  */
-function db_decode_blob($data) {
-  return pg_unescape_bytea($data);
+function db_escape_numeric($data) {
+  $data = trim($data);
+  return is_numeric($data) && !preg_match('/x/i', $data) ? $data : '0';
 }
 
 /**
  * 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 <a href="@url">PostgreSQL documentation</a>.', 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) {
-  if (!preg_match('/FROM\s+\S+\s+AS/si', $query)
-  && !preg_match('/DISTINCT\s+ON\s*\(\s*(' . $table . '\s*\.\s*)?' . $field . '\s*\)/si', $query)
-  && !preg_match('/DISTINCT[ (]' . $field . '/si', $query)
-  && preg_match('/(.*FROM\s+)(.*?\s)(\s*(WHERE|GROUP|HAVING|ORDER|LIMIT|FOR).*)/Asi', $query, $m)) {
-    $query = $m[1];
-    $query .= preg_replace('/([\{\w+\}]+)\s+(' . $table . ')\s/Usi', '(SELECT DISTINCT ON (' . $field . ') * FROM \1) \2 ', $m[2]);
-    $query .= $m[3];
-  }
-  return $query;
-}
-
-/**
- * @} End of "ingroup database".
- */
-
-/**
- * @ingroup schemaapi
- * @{
- */
-
-/**
- * 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' => '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.
  *
- * @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));
-  }
-
-  $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['precision'] .', '. $spec['scale'] .')';
-  }
-
-  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);
-  }
+function db_escape_string($data) {
+  return "'". pg_escape_string($data) ."'";
 }
 
 /**
- * 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.
+ * Returns a properly formatted Binary Large OBject value.
  *
- * @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 $data
+ *   Data to encode.
+ * @return
+ *   Encoded data.
  */
-function db_drop_index(&$ret, $table, $name) {
-  $name = '{'. $table .'}_'. $name .'_idx';
-  $ret[] = update_sql('DROP INDEX '. $name);
+function db_encode_blob($data) {
+  // In case of PostgreSQL encodes data for INSERT into bytea field.
+  return "'". pg_escape_bytea($data) ."'";
 }
 
 /**
- * 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 Binary Large OBject value.
  *
- * @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_blob($data) {
+  // In case of PostgreSQL decodes data after select from bytea field.
+  return pg_unescape_bytea($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.121.2.2
diff -u -p -r1.121.2.2 file.inc
--- includes/file.inc	23 Apr 2008 18:18:09 -0000	1.121.2.2
+++ includes/file.inc	9 Aug 2008 06:00:35 -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 (isset($uid)) {
-    return (int) db_result(db_query('SELECT SUM(filesize) FROM {files} WHERE uid = %d', $uid));
+    return (int) db_result(db_query('SELECT SUM([filesize]) FROM [{files}] WHERE [uid] = %d', $uid));
   }
-  return (int) db_result(db_query('SELECT SUM(filesize) FROM {files}'));
+  return (int) 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.265.2.7
diff -u -p -r1.265.2.7 form.inc
--- includes/form.inc	25 Jun 2008 09:58:09 -0000	1.265.2.7
+++ includes/form.inc	9 Aug 2008 06:00:35 -0000
@@ -2317,10 +2317,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;
@@ -2484,7 +2484,11 @@ 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());
+      $values = array(
+        array('field' => 'token', 'placeholder' => '%s', 'data' => ''),
+        array('field' => 'timestamp', 'placeholder' => '%d', 'data' => time()),
+      );
+      db_query_insert('batch', $values);
       $batch['id'] = db_last_insert_id('batch', 'bid');
 
       // Now that we have a batch id, we can generate the redirection link in
@@ -2493,7 +2497,11 @@ function batch_process($redirect = NULL,
       $batch['error_message'] = $t('Please continue to <a href="@error_url">the error page</a>', 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']);
+      $values = array(
+        array('field' => 'token', 'placeholder' => '%s', 'data' => drupal_get_token($batch['id'])),
+        array('field' => 'batch', 'placeholder' => '%b', 'data' => serialize($batch)),
+      );
+      db_query_update('batch', $values, '[bid] = %d', $batch['id']);
 
       drupal_goto($batch['url'], 'op=start&id='. $batch['id']);
     }
Index: includes/image.gd.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/Attic/image.gd.inc,v
retrieving revision 1.4
diff -u -p -r1.4 image.gd.inc
--- includes/image.gd.inc	15 Jan 2008 10:17:42 -0000	1.4
+++ includes/image.gd.inc	9 Aug 2008 06:00:35 -0000
@@ -38,7 +38,7 @@ function image_gd_settings() {
       '#field_suffix' => t('%'),
     );
     $form['#element_validate'] = array('image_gd_settings_validate');
-    
+
     return $form;
   }
   else {
Index: includes/install.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/install.inc,v
retrieving revision 1.56.2.2
diff -u -p -r1.56.2.2 install.inc
--- includes/install.inc	11 Feb 2008 15:10:26 -0000	1.56.2.2
+++ includes/install.inc	9 Aug 2008 06:00:35 -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,12 +151,13 @@ function drupal_detect_baseurl($file = '
 function drupal_detect_database_types() {
   $databases = array();
 
-  foreach (array('mysql', 'mysqli', 'pgsql') as $type) {
-    if (file_exists('./includes/install.'. $type .'.inc')) {
-      include_once './includes/install.'. $type .'.inc';
-      $function = $type .'_is_available';
+  foreach (glob('./includes/database.*.inc') as $driver_file) {
+    list(, $driver) = explode('.', basename($driver_file));
+    if (file_exists('./includes/database.'. $driver .'.inc') && file_exists('./includes/install.'. $driver .'.inc')) {
+      include_once './includes/install.'. $driver .'.inc';
+      $function = $driver .'_is_available';
       if ($function()) {
-        $databases[$type] = $type;
+        $databases[$driver] = $driver;
       }
     }
   }
@@ -212,7 +213,7 @@ function drupal_rewrite_settings($settin
           // Write new value to settings.php in the following format:
           //    $'setting' = 'value'; // 'comment'
           $setting = $settings[$variable[1]];
-          $buffer .= '$'. $variable[1] ." = '". $setting['value'] ."';". (!empty($setting['comment']) ? ' // '. $setting['comment'] ."\n" : "\n");
+          $buffer .= '$'. $variable[1] ." = ". var_export($setting['value'], TRUE) .";". (!empty($setting['comment']) ? ' // '. $setting['comment'] ."\n" : "\n");
           unset($settings[$variable[1]]);
         }
         else {
@@ -228,7 +229,7 @@ function drupal_rewrite_settings($settin
     // Add required settings that were missing from settings.php.
     foreach ($settings as $setting => $data) {
       if ($data['required']) {
-        $buffer .= "\$$setting = '". $data['value'] ."';\n";
+        $buffer .= "\$$setting = ". var_export($data['value'], TRUE) .";\n";
       }
     }
 
@@ -359,7 +360,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();
@@ -394,9 +395,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.9
diff -u -p -r1.9 install.mysql.inc
--- includes/install.mysql.inc	23 Jan 2008 09:59:29 -0000	1.9
+++ includes/install.mysql.inc	9 Aug 2008 06:00:35 -0000
@@ -1,16 +1,16 @@
 <?php
 // $Id: install.mysql.inc,v 1.9 2008/01/23 09:59:29 goba Exp $
 
-// MySQL specific install functions
+// mysql specific install functions.
 
 /**
- * Check if MySQL is available.
+ * Check if mysql is available.
  *
  * @return
  *  TRUE/FALSE
  */
 function mysql_is_available() {
-  return function_exists('mysql_connect');
+  return function_exists('mysql_connect') && extension_loaded('mysql');
 }
 
 /**
@@ -21,32 +21,24 @@ 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;
   }
 
-  $url = parse_url($url);
-
-  // Decode url-encoded information in the db connection string.
-  $url['user'] = urldecode($url['user']);
-  $url['pass'] = isset($url['pass']) ? urldecode($url['pass']) : '';
-  $url['host'] = urldecode($url['host']);
-  $url['path'] = urldecode($url['path']);
-
   // Allow for non-standard MySQL port.
-  if (isset($url['port'])) {
-    $url['host'] = $url['host'] .':'. $url['port'];
+  if (isset($url['db_port'])) {
+    $url['db_host'] = $url['db_host'] .':'. $url['db_port'];
   }
 
   // Test connecting to the database.
-  $connection = @mysql_connect($url['host'], $url['user'], $url['pass'], TRUE, 2);
+  $connection = @mysql_connect($url['db_host'], $url['db_user'], $url['db_pass'], TRUE, 2);
   if (!$connection) {
     drupal_set_message(st('Failed to connect to your MySQL database server. MySQL reports the following message: %error.<ul><li>Are you sure you have the correct username and password?</li><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => mysql_error())), 'error');
     return FALSE;
   }
 
   // Test selecting the database.
-  if (!mysql_select_db(substr($url['path'], 1))) {
+  if (!mysql_select_db($url['db_name'])) {
     drupal_set_message(st('Failed to select your database on your MySQL database server, which means the connection username and password are valid, but there is a problem accessing your data. MySQL reports the following message: %error.<ul><li>Are you sure you have the correct database name?</li><li>Are you sure the database exists?</li><li>Are you sure the username has permission to access the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => mysql_error())), 'error');
     return FALSE;
   }
@@ -54,7 +46,7 @@ function drupal_test_mysql($url, &$succe
   $success = array('CONNECT');
 
   // Test CREATE.
-  $query = 'CREATE TABLE drupal_install_test (id int NULL)';
+  $query = 'CREATE TABLE `drupal_install_test` (`id` INT NULL)';
   $result = mysql_query($query);
   if ($error = mysql_error()) {
     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.<ul><li>Are you sure the configured username has the necessary MySQL permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%query' => $query, '%error' => $error)), 'error');
@@ -65,7 +57,7 @@ function drupal_test_mysql($url, &$succe
   $success[] = 'CREATE';
 
   // Test INSERT.
-  $query = 'INSERT INTO drupal_install_test (id) VALUES (1)';
+  $query = 'INSERT INTO `drupal_install_test` (`id`) VALUES (1)';
   $result = mysql_query($query);
   if ($error = mysql_error()) {
     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)), 'error');
@@ -76,7 +68,7 @@ function drupal_test_mysql($url, &$succe
   }
 
   // Test UPDATE.
-  $query = 'UPDATE drupal_install_test SET id = 2';
+  $query = 'UPDATE `drupal_install_test` SET `id` = 2';
   $result = mysql_query($query);
   if ($error = mysql_error()) {
     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)), 'error');
@@ -87,7 +79,7 @@ function drupal_test_mysql($url, &$succe
   }
 
   // Test DELETE.
-  $query = 'DELETE FROM drupal_install_test';
+  $query = 'DELETE FROM `drupal_install_test`';
   $result = mysql_query($query);
   if ($error = mysql_error()) {
     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)), 'error');
@@ -98,7 +90,7 @@ function drupal_test_mysql($url, &$succe
   }
 
   // Test DROP.
-  $query = 'DROP TABLE drupal_install_test';
+  $query = 'DROP TABLE `drupal_install_test`';
   $result = mysql_query($query);
   if ($error = mysql_error()) {
     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)), 'error');
Index: includes/install.mysqli.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/install.mysqli.inc,v
retrieving revision 1.12
diff -u -p -r1.12 install.mysqli.inc
--- includes/install.mysqli.inc	23 Jan 2008 09:59:29 -0000	1.12
+++ includes/install.mysqli.inc	9 Aug 2008 06:00:35 -0000
@@ -1,16 +1,16 @@
 <?php
 // $Id: install.mysqli.inc,v 1.12 2008/01/23 09:59:29 goba Exp $
 
-// MySQLi specific install functions
+// mysqli specific install functions.
 
 /**
- * Check if MySQLi is available.
+ * Check if mysqli is available.
  *
  * @return
  *  TRUE/FALSE
  */
 function mysqli_is_available() {
-  return function_exists('mysqli_connect');
+  return function_exists('mysqli_init') && extension_loaded('mysqli');
 }
 
 /**
@@ -21,20 +21,12 @@ 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;
   }
 
-  $url = parse_url($url);
-
-  // Decode url-encoded information in the db connection string.
-  $url['user'] = urldecode($url['user']);
-  $url['pass'] = isset($url['pass']) ? urldecode($url['pass']) : '';
-  $url['host'] = urldecode($url['host']);
-  $url['path'] = urldecode($url['path']);
-
   $connection = mysqli_init();
-  @mysqli_real_connect($connection, $url['host'], $url['user'], $url['pass'], substr($url['path'], 1), $url['port'], NULL, MYSQLI_CLIENT_FOUND_ROWS);
+  @mysqli_real_connect($connection, $url['db_host'], $url['db_user'], $url['db_pass'], $url['db_name'], $url['db_port'], NULL, MYSQLI_CLIENT_FOUND_ROWS);
   if (mysqli_connect_errno() >= 2000 || mysqli_connect_errno() == 1045) {
     drupal_set_message(st('Failed to connect to your MySQL database server. MySQL reports the following message: %error.<ul><li>Are you sure you have the correct username and password?</li><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => mysqli_connect_error())), 'error');
     return FALSE;
@@ -49,7 +41,7 @@ function drupal_test_mysqli($url, &$succ
   $success = array('CONNECT');
 
   // Test CREATE.
-  $query = 'CREATE TABLE drupal_install_test (id int NULL)';
+  $query = 'CREATE TABLE `drupal_install_test` (`id` INT NULL)';
   $result = mysqli_query($connection, $query);
   if ($error = mysqli_error($connection)) {
     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.<ul><li>Are you sure the configured username has the necessary MySQL permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%query' => $query, '%error' => $error)), 'error');
@@ -60,7 +52,7 @@ function drupal_test_mysqli($url, &$succ
   $success[] = 'CREATE';
 
   // Test INSERT.
-  $query = 'INSERT INTO drupal_install_test (id) VALUES (1)';
+  $query = 'INSERT INTO `drupal_install_test` (`id`) VALUES (1)';
   $result = mysqli_query($connection, $query);
   if ($error = mysqli_error($connection)) {
     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)), 'error');
@@ -71,7 +63,7 @@ function drupal_test_mysqli($url, &$succ
   }
 
   // Test UPDATE.
-  $query = 'UPDATE drupal_install_test SET id = 2';
+  $query = 'UPDATE `drupal_install_test` SET `id` = 2';
   $result = mysqli_query($connection, $query);
   if ($error = mysqli_error($connection)) {
     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)), 'error');
@@ -82,7 +74,7 @@ function drupal_test_mysqli($url, &$succ
   }
 
   // Test DELETE.
-  $query = 'DELETE FROM drupal_install_test';
+  $query = 'DELETE FROM `drupal_install_test`';
   $result = mysqli_query($connection, $query);
   if ($error = mysqli_error($connection)) {
     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)), 'error');
@@ -93,7 +85,7 @@ function drupal_test_mysqli($url, &$succ
   }
 
   // Test DROP.
-  $query = 'DROP TABLE drupal_install_test';
+  $query = 'DROP TABLE `drupal_install_test`';
   $result = mysqli_query($connection, $query);
   if ($error = mysqli_error($connection)) {
     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)), 'error');
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	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,134 @@
+<?php
+// $Id: install.oci8.inc,v 1.2 2007/12/11 07:21:32 hswong3i Exp $
+
+// oci8 specific install functions.
+
+/**
+ * Check if oci8 is available.
+ *
+ * @return
+ *  TRUE/FALSE
+ */
+function oci8_is_available() {
+  return function_exists('oci_connect') && extension_loaded('oci8');
+}
+
+/**
+ * Check if we can connect to Oracle.
+ *
+ * @return
+ *  TRUE/FALSE
+ */
+function drupal_test_oci8($url, &$success) {
+  if (!oci8_is_available()) {
+    drupal_set_message(st('PHP oci8 support not enabled.'), 'error');
+    return FALSE;
+  }
+
+  // Build oci8 connection string and allow for non-standard Oracle port.
+  $conn_string = '//'. $url['db_host'] . (isset($url['db_port']) ? ':'. $url['db_port'] : '') .'/'. $url['db_name'];
+
+  // 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['db_user'], $url['db_pass'], $conn_string);
+
+  // Test connecting to the database.
+  if (!$connection && ($error = oci_error())) {
+    drupal_set_message(st('Failure to connect to your Oracle database server. Oracle reports the following message: %error.<ul><li>Are you sure you have the correct username and password?</li><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li><li>Are you sure you typed the correct database name?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.<br />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" NUMBER(38) 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.<ul><li>Are you sure the configured username has the necessary Oracle permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. 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.
+  $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_ibm.inc
===================================================================
RCS file: includes/install.pdo_ibm.inc
diff -N includes/install.pdo_ibm.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/install.pdo_ibm.inc	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,149 @@
+<?php
+// $Id$
+
+// pdo_ibm specific install functions.
+
+/**
+ * Check if PDO DB2 is available.
+ *
+ * @return
+ *  TRUE/FALSE
+ */
+function pdo_ibm_is_available() {
+  return class_exists('PDO') && extension_loaded('pdo_ibm');
+}
+
+/**
+ * Check if we can connect to DB2.
+ *
+ * @return
+ *  TRUE/FALSE
+ */
+function drupal_test_pdo_ibm($url, &$success) {
+  if (!pdo_ibm_is_available()) {
+    drupal_set_message(st('PHP pdo_ibm support not enabled.'), 'error');
+    return FALSE;
+  }
+
+  // Build pdo_ibm connection string and allow for non-standard DB2 port.
+  $dsn[] = 'PROTOCOL=TCPIP';
+  $dsn[] = isset($url['db_host']) ? 'HOSTNAME='. $url['db_host'] : NULL;
+  $dsn[] = isset($url['db_port']) ? 'PORT='. $url['db_port'] : 'PORT=50000';
+  $dsn[] = isset($url['db_name']) ? 'DATABASE='. $url['db_name'] : NULL;
+  $dsn = 'ibm:'. implode(';', $dsn);
+
+  $driver_options = array(
+    // Throw a PDOException and set its properties to reflect the error code
+    // and error information.
+    PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING,
+    //  Leave column names as returned by the database driver.
+    PDO::ATTR_CASE => PDO::CASE_NATURAL,
+  );
+
+  try {
+    $connection = new PDO($dsn, $url['db_user'], $url['db_pass'], $driver_options);
+  } catch (PDOExecption $e) {
+    drupal_set_message(st('Failed to connect to your DB2 database server. DB2 reports the following message: %error.<ul><li>Are you sure you have the correct username and password?</li><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li><li>Are you sure you typed the correct database name?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. 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) && $error[0] != 0 && isset($error[2])) {
+    drupal_set_message(st('Failed to create a test table on your DB2 database server with the command %query. DB2 reports the following message: %error.<ul><li>Are you sure the configured username has the necessary DB2 permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. 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) && $error[0] != 0 && isset($error[2])) {
+    drupal_set_message(st('Failed 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[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) && $error[0] != 0 && isset($error[2])) {
+    drupal_set_message(st('Failed 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[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) && $error[0] != 0 && isset($error[2])) {
+    drupal_set_message(st('Failed 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[2])), 'error');
+    $err = TRUE;
+  }
+  else {
+    $success[] = 'LOCK';
+  }
+
+  // Test UNLOCK.
+  $query = 'COMMIT';
+  $stmt = $connection->prepare($query);
+  $stmt->execute();
+  $error = $stmt->errorInfo();
+  if (is_array($error) && $error[0] != 0 && isset($error[2])) {
+    drupal_set_message(st('Failed 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[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) && $error[0] != 0 && isset($error[2])) {
+    drupal_set_message(st('Failed 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[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) && $error[0] != 0 && isset($error[2])) {
+    drupal_set_message(st('Failed 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[2])), 'error');
+    $err = TRUE;
+  }
+  else {
+    $success[] = 'DROP';
+  }
+
+  if ($err) {
+    return FALSE;
+  }
+
+  $connection = NULL;
+  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	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,155 @@
+<?php
+// $Id: install.pdo_mysql.inc,v 1.2 2007/12/11 07:21:32 hswong3i Exp $
+
+// pdo_mysql specific install functions.
+
+/**
+ * Check if pdo_mysql is available.
+ *
+ * @return
+ *  TRUE/FALSE
+ */
+function pdo_mysql_is_available() {
+  return class_exists('PDO') && extension_loaded('pdo_mysql');
+}
+
+/**
+ * Check if we can connect to MySQL.
+ *
+ * @return
+ *  TRUE/FALSE
+ */
+function drupal_test_pdo_mysql($url, &$success) {
+  if (!pdo_mysql_is_available()) {
+    drupal_set_message(st('PHP pdo_mysql support not enabled.'), 'error');
+    return FALSE;
+  }
+
+  // Build pdo_mysql connection string and allow for non-standard MySQL port.
+  $dsn[] = isset($url['db_host']) ? 'host='. $url['db_host'] : NULL;
+  $dsn[] = isset($url['db_port']) ? 'port='. $url['db_port'] : 'port=3306';
+  $dsn[] = isset($url['db_name']) ? 'dbname='. $url['db_name'] : NULL;
+  $dsn = 'mysql:'. implode(';', $dsn);
+
+  $driver_options = array(
+    // Throw a PDOException and set its properties to reflect the error code
+    // and error information.
+    PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING,
+    //  Leave column names as returned by the database driver.
+    PDO::ATTR_CASE => PDO::CASE_NATURAL,
+    // Force MySQL driver will use the buffered versions of the MySQL API.
+    PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
+  );
+
+  try {
+    $connection = new PDO($dsn, $url['db_user'], $url['db_pass'], $driver_options);
+  } catch (PDOExecption $e) {
+    drupal_set_message(st('Failed to connect to your MySQL database server. MySQL reports the following message: %error.<ul><li>Are you sure you have the correct username and password?</li><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => $e->getMessage())), 'error');
+    return FALSE;
+  }
+
+  // Require ANSI mode to improve SQL portability.
+  $stmt = $connection->exec("SET SESSION SQL_MODE = 'ANSI'");
+  // Force UTF-8
+  $stmt = $connection->exec('SET NAMES "UTF8"');
+
+  $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) && $error[0] != 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.<ul><li>Are you sure the configured username has the necessary MySQL permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. 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) && $error[0] != 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) && $error[0] != 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) && $error[0] != 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) && $error[0] != 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) && $error[0] != 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) && $error[0] != 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	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,148 @@
+<?php
+// $Id: install.pdo_oci.inc,v 1.1 2007/12/11 07:21:32 hswong3i Exp $
+
+// pdo_oci specific install functions.
+
+/**
+ * Check if pdo_oci is available.
+ *
+ * @return
+ *  TRUE/FALSE
+ */
+function pdo_oci_is_available() {
+  return class_exists('PDO') && extension_loaded('pdo_oci');
+}
+
+/**
+ * Check if we can connect to Oracle.
+ *
+ * @return
+ *  TRUE/FALSE
+ */
+function drupal_test_pdo_oci($url, &$success) {
+  if (!pdo_oci_is_available()) {
+    drupal_set_message(st('PHP pdo_oci support not enabled.'), 'error');
+    return FALSE;
+  }
+
+  // Build pdo_oci connection string and allow for non-standard Oracle port.
+  // Connect with Oracle Instant Client partten.
+  $dsn = 'oci://'. $url['db_host'] . (isset($url['db_port']) ? ':'. $url['db_port'] : ':1521') .'/'. $url['db_name'];
+
+  $driver_options = array(
+    // Throw a PDOException and set its properties to reflect the error code
+    // and error information.
+    PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING,
+    //  Leave column names as returned by the database driver.
+    PDO::ATTR_CASE => PDO::CASE_NATURAL,
+    // Disable autocommit so that the connection begins a transaction.
+    PDO::ATTR_AUTOCOMMIT => FALSE,
+  );
+
+  try {
+    $connection = new PDO($dsn, $url['db_user'], $url['db_pass'], $driver_options);
+  } catch (PDOExecption $e) {
+    drupal_set_message(st('Failure to connect to your Oracle database server. Oracle reports the following message: %error.<ul><li>Are you sure you have the correct username and password?</li><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li><li>Are you sure you typed the correct database name?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. 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" NUMBER(38) NOT NULL)';
+  $stmt = $connection->prepare($query);
+  $stmt->execute();
+  $error = $stmt->errorInfo();
+  if (is_array($error) && $error[0] != 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.<ul><li>Are you sure the configured username has the necessary Oracle permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. 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) && $error[0] != 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) && $error[0] != 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) && $error[0] != 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
+  $query = 'COMMIT';
+  $stmt = $connection->prepare($query);
+  $stmt->execute();
+  $error = $stmt->errorInfo();
+  if (is_array($error) && $error[0] != 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) && $error[0] != 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) && $error[0] != 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	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,148 @@
+<?php
+// $Id: install.pdo_pgsql.inc,v 1.2 2007/12/11 07:21:32 hswong3i Exp $
+
+// pdo_pgsql specific install functions.
+
+/**
+ * Check if pdo_pgsql is available.
+ *
+ * @return
+ *  TRUE/FALSE
+ */
+function pdo_pgsql_is_available() {
+  return class_exists('PDO') && extension_loaded('pdo_pgsql');
+}
+
+/**
+ * Check if we can connect to PostgreSQL.
+ *
+ * @return
+ *  TRUE/FALSE
+ */
+function drupal_test_pdo_pgsql($url, &$success) {
+  if (!pdo_pgsql_is_available()) {
+    drupal_set_message(st('PHP pdo_pgsql support not enabled.'), 'error');
+    return FALSE;
+  }
+
+  // Build pdo_pgsql connection string and allow for non-standard PostgreSQL port.
+  $dsn[] = isset($url['db_host']) ? 'host='. $url['db_host'] : NULL;
+  $dsn[] = isset($url['db_port']) ? 'port='. $url['db_port'] : 'port=5432';
+  $dsn[] = isset($url['db_name']) ? 'dbname='. $url['db_name'] : NULL;
+  $dsn = 'pgsql:'. implode(' ', $dsn);
+
+  $driver_options = array(
+    // Throw a PDOException and set its properties to reflect the error code
+    // and error information.
+    PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING,
+    //  Leave column names as returned by the database driver.
+    PDO::ATTR_CASE => PDO::CASE_NATURAL,
+  );
+
+  try {
+    $connection = new PDO($dsn, $url['db_user'], $url['db_pass'], $driver_options);
+  } catch (PDOExecption $e) {
+    drupal_set_message(st('Failed to connect to your PostgreSQL database server. PostgreSQL reports the following message: %error.<ul><li>Are you sure you have the correct username and password?</li><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li><li>Are you sure you typed the correct database name?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. 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 NOT NULL)';
+  $stmt = $connection->prepare($query);
+  $stmt->execute();
+  $error = $stmt->errorInfo();
+  if (is_array($error) && $error[0] != 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.<ul><li>Are you sure the configured username has the necessary PostgreSQL permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. 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) && $error[0] != 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) && $error[0] != 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) && $error[0] != 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.
+  $query = 'COMMIT';
+  $stmt = $connection->prepare($query);
+  $stmt->execute();
+  $error = $stmt->errorInfo();
+  if (is_array($error) && $error[0] != 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) && $error[0] != 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) && $error[0] != 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.pdo_sqlite.inc
===================================================================
RCS file: includes/install.pdo_sqlite.inc
diff -N includes/install.pdo_sqlite.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/install.pdo_sqlite.inc	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,153 @@
+<?php
+// $Id: install.pdo_sqlite.inc,v 1.1 2008/02/03 10:08:54 hswong3i Exp $
+
+// pdo_sqlite specific install functions.
+
+/**
+ * Check if PDO SQLite is available.
+ *
+ * @return
+ *  TRUE/FALSE
+ */
+function pdo_sqlite_is_available() {
+  return class_exists('PDO') && extension_loaded('pdo_sqlite');
+}
+
+/**
+ * Check if we can connect to SQLite.
+ *
+ * @return
+ *  TRUE/FALSE
+ */
+function drupal_test_pdo_sqlite($url, &$success) {
+  if (!pdo_sqlite_is_available()) {
+    drupal_set_message(st('PHP pdo_sqlite support not enabled.'), 'error');
+    return FALSE;
+  }
+
+  // Build pdo_sqlite connection string.
+  $dsn = 'sqlite:'. isset($url['db_name']) ? $url['db_name'] : ':memory';
+
+  $driver_options = array(
+    // Throw a PDOException and set its properties to reflect the error code
+    // and error information.
+    PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING,
+    //  Leave column names as returned by the database driver.
+    PDO::ATTR_CASE => PDO::CASE_NATURAL,
+  );
+
+  try {
+    $connection = new PDO($dsn, $username, $password, $driver_options);
+  } catch (PDOExecption $e) {
+    drupal_set_message(st('Failed to connect to your SQLite database server. SQLite reports the following message: %error.<ul><li>Are you sure you have the correct username and password?</li><li>Are you sure that you have typed the correct database hostname?</li><li>Are you sure that the database server is running?</li><li>Are you sure you typed the correct database name?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%error' => $e->getMessage())), 'error');
+    return FALSE;
+  }
+
+  // Modify the operation of the SQLite library
+  $connection->exec('PRAGMA SYNCHRONOUS = OFF');
+  $connection->exec('PRAGMA SHORT_COLUMN_NAMES = 1');
+  $connection->exec('PRAGMA TEMP_STORE = MEMORY');
+  $connection->exec('PRAGMA CACHE_SIZE = 5120');
+  $connection->exec('PRAGMA COUNT_CHANGES = OFF');
+  $connection->exec('PRAGMA ENCODING = "UTF-8"');
+
+  $success = array('CONNECT');
+
+  // Test CREATE.
+  $query = 'CREATE TABLE "drupal_install_test" ("id" INTEGER)';
+  $stmt = $connection->prepare($query);
+  $stmt->execute();
+  $error = $stmt->errorInfo();
+  if (is_array($error) && $error[0] != 0 && isset($error[2])) {
+    drupal_set_message(st('Failed to create a test table on your SQLite database server with the command %query. SQLite reports the following message: %error.<ul><li>Are you sure the configured username has the necessary SQLite permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. 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) && $error[0] != 0 && isset($error[2])) {
+    drupal_set_message(st('Failed to insert a value into a test table on your SQLite database server. We tried inserting a value with the command %query and SQLite 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) && $error[0] != 0 && isset($error[2])) {
+    drupal_set_message(st('Failed to update a value in a test table on your SQLite database server. We tried updating a value with the command %query and SQLite reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error');
+    $err = TRUE;
+  }
+  else {
+    $success[] = 'UPDATE';
+  }
+
+  // Test LOCK.
+  $query = 'BEGIN';
+  $stmt = $connection->prepare($query);
+  $stmt->execute();
+  $error = $stmt->errorInfo();
+  if (is_array($error) && $error[0] != 0 && isset($error[2])) {
+    drupal_set_message(st('Failed to lock a test table on your SQLite database server. We tried locking a table with the command %query and SQLite reported the following error: %error.', array('%query' => $query, '%error' => $error[2])), 'error');
+    $err = TRUE;
+  }
+  else {
+    $success[] = 'LOCK';
+  }
+
+  // Test UNLOCK.
+  $query = 'COMMIT';
+  $stmt = $connection->prepare($query);
+  $stmt->execute();
+  $error = $stmt->errorInfo();
+  if (is_array($error) && $error[0] != 0 && isset($error[2])) {
+    drupal_set_message(st('Failed to unlock a test table on your SQLite database server. We tried unlocking a table with the command %query and SQLite 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) && $error[0] != 0 && isset($error[2])) {
+    drupal_set_message(st('Failed to delete a value from a test table on your SQLite database server. We tried deleting a value with the command %query and SQLite 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) && $error[0] != 0 && isset($error[2])) {
+    drupal_set_message(st('Failed to drop a test table from your SQLite database server. We tried dropping a table with the command %query and SQLite 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	9 Aug 2008 06:00:35 -0000
@@ -1,16 +1,16 @@
 <?php
 // $Id: install.pgsql.inc,v 1.6 2007/10/22 15:22:39 dries Exp $
 
-// PostgreSQL specific install functions
+// pgsql specific install functions.
 
 /**
- * Check if PostgreSQL is available.
+ * Check if pgsql is available.
  *
  * @return
  *  TRUE/FALSE
  */
 function pgsql_is_available() {
-  return function_exists('pg_connect');
+  return function_exists('pg_connect') && extension_loaded('pgsql');
 }
 
 /**
@@ -21,29 +21,18 @@ 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;
   }
 
-  $url = parse_url($url);
-  $conn_string = '';
-
   // Decode url-encoded information in the db connection string
-  if (isset($url['user'])) {
-    $conn_string .= ' user='. urldecode($url['user']);
-  }
-  if (isset($url['pass'])) {
-    $conn_string .= ' password='. urldecode($url['pass']);
-  }
-  if (isset($url['host'])) {
-    $conn_string .= ' host='. urldecode($url['host']);
-  }
-  if (isset($url['path'])) {
-    $conn_string .= ' dbname='. substr(urldecode($url['path']), 1);
-  }
-  if (isset($url['port'])) {
-    $conn_string .= ' port='. urldecode($url['port']);
-  }
+  $conn_string[] = isset($url['db_host']) ? 'host='. $url['db_host'] : NULL;
+  $conn_string[] = isset($url['db_port']) ? 'port='. $url['db_port'] : NULL;
+  $conn_string[] = isset($url['db_name']) ? 'dbname='. $url['db_name'] : NULL;
+  $conn_string[] = isset($url['db_user']) ? 'user='. $url['db_user'] : NULL;
+  $conn_string[] = isset($url['db_pass']) ? 'password='. $url['db_pass'] : NULL;
+
+  $conn_string = implode(' ', array_filter($conn_string));
 
   // Test connecting to the database.
   $connection = @pg_connect($conn_string);
@@ -55,7 +44,7 @@ function drupal_test_pgsql($url, &$succe
   $success = array('CONNECT');
 
   // Test CREATE.
-  $query = 'CREATE TABLE drupal_install_test (id integer NOT NULL)';
+  $query = 'CREATE TABLE "drupal_install_test" ("id" INT NOT NULL)';
   $result = pg_query($connection, $query);
   if ($error = pg_result_error($result)) {
     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.<ul><li>Are you sure the configured username has the necessary PostgreSQL permissions to create tables in the database?</li></ul>For more help, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.', array('%query' => $query, '%error' => $error)), 'error');
@@ -66,7 +55,7 @@ function drupal_test_pgsql($url, &$succe
   $success[] = 'CREATE';
 
   // Test INSERT.
-  $query = 'INSERT INTO drupal_install_test (id) VALUES (1)';
+  $query = 'INSERT INTO "drupal_install_test" ("id") VALUES (1)';
   $result = pg_query($connection, $query);
   if ($error = pg_result_error($result)) {
     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)), 'error');
@@ -77,7 +66,7 @@ function drupal_test_pgsql($url, &$succe
   }
 
   // Test UPDATE.
-  $query = 'UPDATE drupal_install_test SET id = 2';
+  $query = 'UPDATE "drupal_install_test" SET "id" = 2';
   $result = pg_query($connection, $query);
   if ($error = pg_result_error($result)) {
     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)), 'error');
@@ -88,7 +77,7 @@ function drupal_test_pgsql($url, &$succe
   }
 
   // Test LOCK.
-  $query = 'BEGIN; LOCK drupal_install_test IN SHARE ROW EXCLUSIVE MODE';
+  $query = 'LOCK "drupal_install_test" IN SHARE ROW EXCLUSIVE MODE';
   $result = pg_query($connection, $query);
   if ($error = pg_result_error($result)) {
     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)), 'error');
@@ -98,7 +87,7 @@ function drupal_test_pgsql($url, &$succe
     $success[] = 'LOCK';
   }
 
-  // Test UNLOCK, which is done automatically upon transaction end in PostgreSQL
+  // Test UNLOCK.
   $query = 'COMMIT';
   $result = pg_query($connection, $query);
   if ($error = pg_result_error()) {
@@ -110,7 +99,7 @@ function drupal_test_pgsql($url, &$succe
   }
 
   // Test DELETE.
-  $query = 'DELETE FROM drupal_install_test';
+  $query = 'DELETE FROM "drupal_install_test"';
   $result = pg_query($connection, $query);
   if ($error = pg_result_error()) {
     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)), 'error');
@@ -121,7 +110,7 @@ function drupal_test_pgsql($url, &$succe
   }
 
   // Test DROP.
-  $query = 'DROP TABLE drupal_install_test';
+  $query = 'DROP TABLE "drupal_install_test"';
   $result = pg_query($connection, $query);
   if ($error = pg_result_error()) {
     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)), 'error');
@@ -137,4 +126,4 @@ function drupal_test_pgsql($url, &$succe
 
   pg_close($connection);
   return TRUE;
-}
\ No newline at end of file
+}
Index: includes/language.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/language.inc,v
retrieving revision 1.14
diff -u -p -r1.14 language.inc
--- includes/language.inc	6 Jan 2008 16:46:02 -0000	1.14
+++ includes/language.inc	9 Aug 2008 06:00:35 -0000
@@ -17,7 +17,7 @@ function language_initialize() {
   // Get a list of enabled languages.
   $languages = language_list('enabled');
   $languages = $languages[1];
-  
+
   switch ($mode) {
     case LANGUAGE_NEGOTIATION_NONE:
       return language_default();
Index: includes/locale.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/locale.inc,v
retrieving revision 1.174.2.1
diff -u -p -r1.174.2.1 locale.inc
--- includes/locale.inc	9 Jul 2008 21:48:28 -0000	1.174.2.1
+++ includes/locale.inc	9 Aug 2008 06:00:35 -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,7 +871,7 @@ function locale_translate_edit_form_subm
  * String deletion confirmation page.
  */
 function locale_translate_delete_page($lid) {
-  if ($source = db_fetch_object(db_query('SELECT * FROM {locales_source} WHERE lid = %d', $lid))) {
+  if ($source = db_fetch_object(db_query('SELECT * FROM [{locales_source}] WHERE [lid] = %d', $lid))) {
     return drupal_get_form('locale_translate_delete_form', $source);
   }
   else {
@@ -891,8 +891,8 @@ function locale_translate_delete_form(&$
  * Process string deletion submissions.
  */
 function locale_translate_delete_form_submit($form, &$form_state) {
-  db_query('DELETE FROM {locales_source} WHERE lid = %d', $form_state['values']['lid']);
-  db_query('DELETE FROM {locales_target} WHERE lid = %d', $form_state['values']['lid']);
+  db_query('DELETE FROM [{locales_source}] WHERE [lid] = %d', $form_state['values']['lid']);
+  db_query('DELETE FROM [{locales_target}] WHERE [lid] = %d', $form_state['values']['lid']);
   // Force JavaScript translation file recreation for all languages.
   _locale_invalidate_js();
   cache_clear_all('locale:', 'cache', TRUE);
@@ -944,7 +944,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) {
@@ -989,7 +989,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;
   }
@@ -1233,10 +1233,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;
       }
@@ -1298,35 +1298,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]++;
   }
 
@@ -1662,7 +1662,7 @@ function _locale_parse_js_file($filepath
       // Remove the quotes and string concatenations from the string.
       $string = implode('', preg_split('~(?<!\\\\)[\'"]\s*\+\s*[\'"]~s', substr($string, 1, -1)));
 
-      $result = db_query("SELECT lid, location FROM {locales_source} WHERE source = '%s' AND textgroup = 'default'", $string);
+      $result = db_query("SELECT [lid], [location] FROM [{locales_source}] WHERE [source] = %s AND [textgroup] = 'default'", $string);
       if ($source = db_fetch_object($result)) {
         // We already have this source string and now have to add the location
         // to the location column, if this file is not yet present in there.
@@ -1673,12 +1673,12 @@ function _locale_parse_js_file($filepath
           $locations = implode('; ', $locations);
 
           // Save the new locations string to the database.
-          db_query("UPDATE {locales_source} SET location = '%s' WHERE lid = %d", $locations, $source->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);
       }
     }
   }
@@ -1702,10 +1702,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)) {
@@ -1933,41 +1933,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'];
         }
@@ -1978,7 +1978,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'];
@@ -2088,7 +2088,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)) {
@@ -2163,14 +2163,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);
     }
   }
@@ -2460,7 +2460,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') .")";
   }
@@ -2495,7 +2495,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
@@ -2556,7 +2556,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/mail.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/mail.inc,v
retrieving revision 1.8.2.3
diff -u -p -r1.8.2.3 mail.inc
--- includes/mail.inc	19 May 2008 08:19:00 -0000	1.8.2.3
+++ includes/mail.inc	9 Aug 2008 06:00:35 -0000
@@ -435,7 +435,7 @@ function _drupal_wrap_mail_line(&$line, 
 function _drupal_html_to_mail_urls($match = NULL, $reset = FALSE) {
   global $base_url, $base_path;
   static $urls = array(), $regexp;
-  
+
   if ($reset) {
     // Reset internal URL list.
     $urls = array();
Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.255.2.17
diff -u -p -r1.255.2.17 menu.inc
--- includes/menu.inc	9 Jul 2008 15:23:50 -0000	1.255.2.17
+++ includes/menu.inc	9 Aug 2008 06:00:35 -0000
@@ -196,7 +196,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);
@@ -227,7 +227,7 @@ function menu_get_ancestors($parts) {
         $current .= '/';
       }
     }
-    $placeholders[] = "'%s'";
+    $placeholders[] = "%s";
     $ancestors[] = $current;
   }
   return array($ancestors, $placeholders);
@@ -312,7 +312,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;
@@ -362,7 +362,7 @@ function menu_execute_active_handler($pa
  * @return
  *   Returns TRUE for success, FALSE if an object cannot be loaded.
  *   Names of object loading functions are placed in $item['load_functions'].
- *   Loaded objects are placed in $map[]; keys are the same as keys in the 
+ *   Loaded objects are placed in $map[]; keys are the same as keys in the
  *   $item['load_functions'] array.
  *   $item['access'] is set to FALSE if an object cannot be loaded.
  */
@@ -471,10 +471,10 @@ function _menu_check_access(&$item, $map
  * @return
  *   No return value.
  *   $item['title'] is localized according to $item['title_callback'].
- *   If an item's callback is check_plain(), $item['options']['html'] becomes 
+ *   If an item's callback is check_plain(), $item['options']['html'] becomes
  *   TRUE.
  *   $item['description'] is translated using t().
- *   When doing link translation and the $item['options']['attributes']['title'] 
+ *   When doing link translation and the $item['options']['attributes']['title']
  *   (link title attribute) matches the description, it is translated as well.
  */
 function _menu_item_localize(&$item, $map, $link_translate = FALSE) {
@@ -570,7 +570,7 @@ function _menu_translate(&$router_item, 
   $router_item['href'] = implode('/', $link_map);
   $router_item['options'] = array();
   _menu_check_access($router_item, $map);
-  
+
   // For performance, don't localize an item the user can't access.
   if ($router_item['access']) {
     _menu_item_localize($router_item, $map);
@@ -657,14 +657,14 @@ function _menu_link_translate(&$item) {
       _menu_item_localize($item, $map, TRUE);
     }
   }
-  
+
   // Allow other customizations - e.g. adding a page-specific query string to the
   // options array. For performance reasons we only invoke this hook if the link
   // has the 'alter' flag set in the options array.
   if (!empty($item['options']['alter'])) {
     drupal_alter('translated_menu_link', $item, $map);
   }
-  
+
   return $map;
 }
 
@@ -781,7 +781,7 @@ function menu_tree_all_data($menu_name =
   $cid = 'links:'. $menu_name .':all-cid:'. $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)) {
       // If the cache entry exists, it will just be the cid for the actual data.
@@ -803,7 +803,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'];
       }
@@ -815,13 +815,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, if it is not already in the cache.
@@ -864,7 +864,7 @@ function menu_tree_page_data($menu_name 
     $cid = 'links:'. $menu_name .':page-cid:'. $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)) {
         // If the cache entry exists, it will just be the cid for the actual data.
@@ -880,17 +880,17 @@ function menu_tree_page_data($menu_name 
         if ($item['access']) {
           // Check whether a menu link exists that corresponds to the current path.
           $args = array($menu_name, $item['href']);
-          $placeholders = "'%s'";
+          $placeholders = "%s";
           if (drupal_is_front_page()) {
             $args[] = '<front>';
-            $placeholders .= ", '%s'";
+            $placeholders .= ", %s";
           }
-          $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 IN (". $placeholders .")", $args));
+          $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] IN (". $placeholders .")", $args));
 
           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';
@@ -904,7 +904,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'];
@@ -922,13 +922,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, if it is not already in the cache.
@@ -983,7 +983,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.status = 1 AND n.nid IN (". $placeholders .")"), $nids);
+    $result = db_query(db_rewrite_sql("SELECT n.[nid] FROM [{node}] n WHERE n.[status] = 1 AND n.[nid] IN (". $placeholders .")"), $nids);
     while ($node = db_fetch_array($result)) {
       $nid = $node['nid'];
       foreach ($node_links[$nid] as $mlid => $link) {
@@ -1187,7 +1187,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'];
     }
@@ -1267,7 +1267,7 @@ function menu_navigation_links($menu_nam
           $l['attributes']['class'] = 'active-trail';
         }
         else {
-          $l['attributes']['class'] .= ' active-trail'; 
+          $l['attributes']['class'] .= ' active-trail';
         }
       }
       // Keyed with unique menu id to generate classes from theme_links().
@@ -1301,7 +1301,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();
@@ -1557,7 +1557,7 @@ function menu_get_active_trail() {
  */
 function menu_get_active_breadcrumb() {
   $breadcrumb = array();
-  
+
   // No breadcrumb for the front page.
   if (drupal_is_front_page()) {
     return $breadcrumb;
@@ -1607,7 +1607,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;
   }
@@ -1702,7 +1702,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',
@@ -1732,7 +1732,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, has_children, updated 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], [has_children], [updated] 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'];
@@ -1748,18 +1748,18 @@ function _menu_navigation_links_rebuild(
   $placeholders = db_placeholders($menu, 'varchar');
   $paths = array_keys($menu);
   // Updated and customized items whose router paths are gone need new ones.
-  $result = db_query("SELECT ml.link_path, ml.mlid, ml.router_path, ml.updated FROM {menu_links} ml WHERE ml.updated = 1 OR (router_path NOT IN ($placeholders) AND external = 0 AND customized = 1)", $paths);
+  $result = db_query("SELECT ml.[link_path], ml.[mlid], ml.[router_path], ml.[updated] FROM [{menu_links}] ml WHERE ml.[updated] = 1 OR ([router_path] NOT IN ($placeholders) AND [external] = 0 AND [customized] = 1)", $paths);
   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.
       $updated = $item['updated'] && $router_path != $item['link_path'];
-      db_query("UPDATE {menu_links} SET router_path = '%s', updated = %d WHERE mlid = %d", $router_path, $updated, $item['mlid']);
+      db_query("UPDATE [{menu_links}] SET [router_path] = %s, [updated] = %d WHERE [mlid] = %d", $router_path, $updated, $item['mlid']);
     }
   }
   // Find any item whose router path does not exist any more.
-  $result = db_query("SELECT * FROM {menu_links} WHERE router_path NOT IN ($placeholders) AND external = 0 AND updated = 0 AND customized = 0 ORDER BY depth DESC", $paths);
+  $result = db_query("SELECT * FROM [{menu_links}] WHERE [router_path] NOT IN ($placeholders) AND [external] = 0 AND [updated] = 0 AND [customized] = 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)) {
@@ -1777,10 +1777,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);
     }
@@ -1799,14 +1799,14 @@ function _menu_delete_item($item, $force
   if ($item && ($item['module'] != 'system' || $item['updated'] || $force)) {
     // 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);
@@ -1852,34 +1852,34 @@ function menu_link_save(&$item) {
   );
   $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']));
   }
 
   if (isset($item['plid'])) {
-    $parent = db_fetch_array(db_query("SELECT * FROM {menu_links} WHERE mlid = %d", $item['plid']));
+    $parent = db_fetch_array(db_query("SELECT * FROM [{menu_links}] WHERE [mlid] = %d", $item['plid']));
   }
   else {
     // Find the parent - it must be unique.
     $parent_path = $item['link_path'];
-    $where = "WHERE link_path = '%s'";
+    $where = "WHERE [link_path] = %s";
     // Only links derived from router items should have module == 'system', and
     // we want to find the parent even if it's in a different menu.
     if ($item['module'] == 'system') {
-      $where .= " AND module = '%s'";
+      $where .= " AND [module] = %s";
       $arg2 = 'system';
     }
     else {
       // If not derived from a router item, we respect the specified menu name.
-      $where .= " AND menu_name = '%s'";
+      $where .= " AND [menu_name] = %s";
       $arg2 = $item['menu_name'];
     }
     do {
       $parent = FALSE;
       $parent_path = substr($parent_path, 0, strrpos($parent_path, '/'));
-      $result = db_query("SELECT COUNT(*) FROM {menu_links} ". $where, $parent_path, $arg2);
+      $result = db_query("SELECT COUNT(*) FROM [{menu_links}] ". $where, $parent_path, $arg2);
       // Only valid if we get a unique result.
       if (db_result($result) == 1) {
-        $parent = db_fetch_array(db_query("SELECT * FROM {menu_links} ". $where, $parent_path, $arg2));
+        $parent = db_fetch_array(db_query("SELECT * FROM [{menu_links}] ". $where, $parent_path, $arg2));
       }
     } while ($parent === FALSE && $parent_path);
   }
@@ -1897,21 +1897,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');
   }
 
@@ -1952,16 +1941,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);
@@ -2000,7 +1983,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'];
   }
@@ -2059,7 +2042,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':
@@ -2086,12 +2069,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;
 }
@@ -2105,26 +2088,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
@@ -2135,17 +2118,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);
 }
@@ -2157,10 +2140,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']);
   }
 }
 
@@ -2271,7 +2254,7 @@ function _menu_router_build($callbacks) 
     return array();
   }
   // Delete the existing router since we have some data to replace it.
-  db_query('DELETE FROM {menu_router}');
+  db_query('DELETE FROM [{menu_router}]');
   // Apply inheritance rules.
   foreach ($menu as $path => $v) {
     $item = &$menu[$path];
@@ -2352,23 +2335,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);
@@ -2440,7 +2419,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	9 Aug 2008 06:00:35 -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	9 Aug 2008 06:00:35 -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	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,413 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Schema API shared between ibm_db2 and pdo_ibm database engines.
+ */
+
+/**
+ * @ingroup schemaapi
+ * @{
+ */
+
+/**
+ * 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'       => '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)',
+
+    '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') {
+    $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['precision'] .', '. $spec['scale'] .')';
+  }
+
+  if (isset($spec['not null']) && $spec['not null']) {
+    $sql .= ' NOT NULL';
+  }
+
+  if (isset($spec['default'])) {
+    if (($spec['type'] == 'blob') && ($spec['default'] == '')) {
+      $sql .= " DEFAULT EMPTY_BLOB()";
+    }
+    else {
+      $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 BY DEFAULT 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	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,491 @@
+<?php
+// $Id: schema.mysql.inc,v 1.3 2007/12/11 07:21:32 hswong3i Exp $
+
+/**
+ * @file
+ * Schema API shared between mysql, mysqli and pdo_mysql database engines.
+ */
+
+/**
+ * @ingroup schemaapi
+ * @{
+ */
+
+/**
+ * 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'       => 'TINYTEXT',
+    'text:small'      => 'TINYTEXT',
+    '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;
+}
+
+/**
+ * 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['precision'] .', '. $spec['scale'] .')';
+  }
+
+  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	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,545 @@
+<?php
+// $Id: schema.oracle.inc,v 1.3 2007/12/11 07:21:32 hswong3i Exp $
+
+/**
+ * @file
+ * Schema API shared between oci8 and pdo_oci database engines.
+ */
+
+/**
+ * @ingroup schemaapi
+ * @{
+ */
+
+/**
+ * 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'  => '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',
+
+    '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['precision'] .', '. $spec['scale'] .')';
+  }
+
+  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 '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	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,495 @@
+<?php
+// $Id: schema.postgresql.inc,v 1.1 2007/12/09 17:46:01 hswong3i Exp $
+
+/**
+ * @file
+ * Schema API shared between pgsql and pdo_pgsql database engines.
+ */
+
+/**
+ * @ingroup schemaapi
+ * @{
+ */
+
+/**
+ * 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'     => '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',
+
+    '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['precision'] .', '. $spec['scale'] .')';
+  }
+
+  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/schema.sqlite.inc
===================================================================
RCS file: includes/schema.sqlite.inc
diff -N includes/schema.sqlite.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/schema.sqlite.inc	9 Aug 2008 06:00:35 -0000
@@ -0,0 +1,511 @@
+<?php
+// $Id: schema.sqlite.inc,v 1.1 2008/02/03 10:08:54 hswong3i Exp $
+
+/**
+ * @file
+ * Schema API shared between sqlite and pdo_sqlite database engines.
+ */
+
+/**
+ * @ingroup schemaapi
+ * @{
+ */
+
+/**
+ * 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'  => 'TEXT',
+    'char:normal'     => 'TEXT',
+
+    'text:tiny'       => 'TEXT',
+    'text:small'      => 'TEXT',
+    'text:medium'     => 'TEXT',
+    'text:big'        => 'TEXT',
+    'text:normal'     => 'TEXT',
+
+    'serial:tiny'     => 'INTEGER',
+    'serial:small'    => 'INTEGER',
+    'serial:medium'   => 'INTEGER',
+    'serial:big'      => 'INTEGER',
+    'serial:normal'   => 'INTEGER',
+
+    'int:tiny'        => 'INTEGER',
+    'int:small'       => 'INTEGER',
+    'int:medium'      => 'INTEGER',
+    'int:big'         => 'INTEGER',
+    'int:normal'      => 'INTEGER',
+
+    'float:tiny'      => 'REAL',
+    'float:small'     => 'REAL',
+    'float:medium'    => 'REAL',
+    'float:big'       => 'REAL',
+    'float:normal'    => 'REAL',
+
+    'numeric:normal'  => 'NUMERIC',
+
+    'blob:big'        => 'BLOB',
+    'blob:normal'     => 'BLOB',
+
+    'datetime:normal' => 'TEXT',
+  );
+  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) {
+    if ($field['type'] == 'serial' && isset($table['primary key']) && in_array($field_name, $table['primary key'])) {
+      unset($table['primary key']);
+    }
+    $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[] = '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);
+    }
+  }
+
+  // In case of SQLite, use transection to ensure atomic CREATE TABLE.
+  return array_merge(
+    array('BEGIN'),
+    $statements,
+    array('COMMIT')
+  );
+}
+
+function _db_create_index_sql($table, $name, $fields) {
+  return 'CREATE INDEX [ix_{'. $table .'}_'. $name .'] ON [{'. $table .'}] ('. _db_create_key_sql($fields) .')';
+}
+
+function _db_create_key_sql($fields) {
+  $ret = array();
+  foreach ($fields as $field) {
+    if (is_array($field)) {
+      $ret[] = '['. $field[0] .']';
+    }
+    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['sqlite_type'])) {
+    $map = db_type_map();
+    $field['sqlite_type'] = $map[$field['type'] .':'. $field['size']];
+  }
+
+  if ($field['type'] == 'serial') {
+    $field['auto_increment'] = TRUE;
+  }
+
+  if ($field['type'] == 'varchar' || $field['type'] == 'char') {
+    unset($field['length']);
+  }
+
+  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['sqlite_type'];
+
+  if (!empty($spec['auto_increment'])) {
+    $sql .= ' PRIMARY KEY AUTOINCREMENT';
+    return $sql;
+  }
+
+  if (!empty($spec['unsigned'])) {
+    $sql .= " CHECK ([$name] >= 0)";
+  }
+
+  if (!empty($spec['length'])) {
+    $sql .= '('. $spec['length'] .')';
+  }
+  elseif (isset($spec['precision']) && isset($spec['scale'])) {
+    $sql .= '('. $spec['precision'] .', '. $spec['scale'] .')';
+  }
+
+  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.2.1
diff -u -p -r1.44.2.1 session.inc
--- includes/session.inc	7 Feb 2008 11:58:40 -0000	1.44.2.1
+++ includes/session.inc	9 Aug 2008 06:00:35 -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	9 Aug 2008 06:00:35 -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.415.2.9
diff -u -p -r1.415.2.9 theme.inc
--- includes/theme.inc	9 Jul 2008 21:48:28 -0000	1.415.2.9
+++ includes/theme.inc	9 Aug 2008 06:00:35 -0000
@@ -426,7 +426,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: includes/theme.maintenance.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.maintenance.inc,v
retrieving revision 1.10
diff -u -p -r1.10 theme.maintenance.inc
--- includes/theme.maintenance.inc	24 Jan 2008 09:42:50 -0000	1.10
+++ includes/theme.maintenance.inc	9 Aug 2008 06:00:35 -0000
@@ -124,7 +124,7 @@ function theme_install_page($content) {
     $variables['messages'] .= theme('status_messages', 'error');
     $variables['content'] .= '<p>'. st('Please check the error messages and <a href="!url">try again</a>.', array('!url' => request_uri())) .'</p>';
   }
-  
+
   // Special handling of warning messages
   if (isset($messages['warning'])) {
     $title = count($messages['warning']) > 1 ? st('The following installation warnings should be carefully reviewed') : st('The following installation warning should be carefully reviewed');
Index: misc/jquery.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/jquery.js,v
retrieving revision 1.12.2.3
diff -u -p -r1.12.2.3 jquery.js
--- misc/jquery.js	25 Jun 2008 09:38:39 -0000	1.12.2.3
+++ misc/jquery.js	9 Aug 2008 06:00:36 -0000
@@ -1,4 +1,4 @@
-// $Id: jquery.js,v 1.12.2.3 2008/06/25 09:38:39 goba Exp $ 
+// $Id: jquery.js,v 1.12.2.3 2008/06/25 09:38:39 goba Exp $
 
 /*
  * jQuery 1.2.6 - New Wave Javascript
Index: misc/tabledrag.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/tabledrag.js,v
retrieving revision 1.13.2.3
diff -u -p -r1.13.2.3 tabledrag.js
--- misc/tabledrag.js	12 Jun 2008 19:13:25 -0000	1.13.2.3
+++ misc/tabledrag.js	9 Aug 2008 06:00:36 -0000
@@ -699,7 +699,7 @@ Drupal.tableDrag.prototype.updateField =
           var maxVal = values[values.length - 1];
           // Populate the values in the siblings.
           $(targetClass, siblings).each(function() {
-            // If there are more items than possible values, assign the maximum value to the row. 
+            // If there are more items than possible values, assign the maximum value to the row.
             if (values.length > 0) {
               this.value = values.shift();
             }
Index: misc/textarea.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/textarea.js,v
retrieving revision 1.22
diff -u -p -r1.22 textarea.js
--- misc/textarea.js	17 Jan 2008 19:31:56 -0000	1.22
+++ misc/textarea.js	9 Aug 2008 06:00:36 -0000
@@ -4,7 +4,7 @@ Drupal.behaviors.textarea = function(con
   $('textarea.resizable:not(.textarea-processed)', context).each(function() {
     // Avoid non-processed teasers.
     if ($(this).is(('textarea.teaser:not(.teaser-processed)'))) {
-      return false;  
+      return false;
     }
     var textarea = $(this).addClass('textarea-processed'), staticOffset = null;
 
Index: misc/farbtastic/farbtastic.js
===================================================================
RCS file: /cvs/drupal/drupal/misc/farbtastic/farbtastic.js,v
retrieving revision 1.4.2.1
diff -u -p -r1.4.2.1 farbtastic.js
--- misc/farbtastic/farbtastic.js	25 Jun 2008 09:34:17 -0000	1.4.2.1
+++ misc/farbtastic/farbtastic.js	9 Aug 2008 06:00:36 -0000
@@ -104,14 +104,14 @@ jQuery._farbtastic = function (container
     var x, y;
     var el = event.target || event.srcElement;
     var reference = fb.wheel;
-    
+
     // If the offset from the relative element is undefined calculate it.
     if ( typeof event.offsetX == 'undefined' && typeof event.offsetY == 'undefined' ) {
       var offset = $(event.target).offset(false);
       event.offsetX = event.pageX - offset.left;
       event.offsetY = event.pageY - offset.top;
     }
-    
+
     // Use offset coordinates and find common offsetParent
     var pos = { x: event.offsetX, y: event.offsetY };
 
Index: modules/aggregator/aggregator.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.admin.inc,v
retrieving revision 1.7.2.1
diff -u -p -r1.7.2.1 aggregator.admin.inc
--- modules/aggregator/aggregator.admin.inc	25 Apr 2008 21:11:57 -0000	1.7.2.1
+++ modules/aggregator/aggregator.admin.inc	9 Aug 2008 06:00:36 -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 = '<h3>'. t('Feed overview') .'</h3>';
 
@@ -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 .= '<h3>'. t('Category overview') .'</h3>';
 
@@ -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	9 Aug 2008 06:00:36 -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 <description> 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' => 'blob',
         '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.374.2.2
diff -u -p -r1.374.2.2 aggregator.module
--- modules/aggregator/aggregator.module	5 Jul 2008 05:57:33 -0000	1.374.2.2
+++ modules/aggregator/aggregator.module	9 Aug 2008 06:00:36 -0000
@@ -271,7 +271,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}]'));
 }
 
 /**
@@ -287,7 +287,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);
   }
@@ -301,11 +301,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));
       }
@@ -313,10 +313,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;
@@ -324,27 +324,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;
@@ -376,18 +376,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';
   }
@@ -405,25 +405,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');
   }
@@ -432,7 +432,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);
         }
       }
     }
@@ -446,15 +446,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'])));
 }
 
@@ -595,7 +595,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:
@@ -629,7 +629,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();
@@ -786,13 +786,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));
@@ -800,7 +800,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;
@@ -809,8 +809,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;
@@ -824,19 +824,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']);
     }
   }
 }
@@ -852,7 +851,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];
 }
@@ -868,7 +867,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	9 Aug 2008 06:00:36 -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_blob($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_blob($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.2.2
diff -u -p -r1.14.2.2 block.admin.inc
--- modules/block/block.admin.inc	24 Jun 2008 14:40:08 -0000	1.14.2.2
+++ modules/block/block.admin.inc	9 Aug 2008 06:00:36 -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();
@@ -143,7 +143,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',
@@ -193,11 +193,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;
@@ -259,7 +259,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.'));
     }
   }
@@ -267,10 +267,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.'));
@@ -288,7 +288,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.'));
   }
 }
@@ -297,17 +297,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_