? .project
Index: install.php
===================================================================
RCS file: /cvs/drupal/drupal/install.php,v
retrieving revision 1.41
diff -u -p -r1.41 install.php
--- install.php	13 Apr 2007 08:56:57 -0000	1.41
+++ install.php	27 Apr 2007 01:53:57 -0000
@@ -103,8 +103,11 @@ function install_main() {
  * Verify if Drupal is installed.
  */
 function install_verify_drupal() {
+  ini_set('display_errors', FALSE);
   $result = @db_query("SELECT name FROM {system} WHERE name = 'system'");
-  return $result && db_result($result) == 'system';
+  $return = $result && db_result($result) == 'system';
+  ini_set('display_errors', TRUE);
+  return $return;
 }
 
 /**
@@ -634,3 +637,4 @@ function install_task_list($active = NUL
 }
 
 install_main();
+
Index: includes/cache.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/cache.inc,v
retrieving revision 1.9
diff -u -p -r1.9 cache.inc
--- includes/cache.inc	25 Apr 2007 21:34:32 -0000	1.9
+++ includes/cache.inc	27 Apr 2007 01:53:58 -0000
@@ -105,8 +105,8 @@ function cache_set($cid, $data, $table =
     $serialized = 1;
   }
   db_lock_table($table);
-  db_query("UPDATE {$table} SET data = %b, created = %d, expire = %d, headers = '%s', serialized = %d WHERE cid = '%s'", $data, time(), $expire, $headers, $serialized, $cid);
-  if (!db_affected_rows()) {
+  $result = db_query("UPDATE {$table} SET data = %b, created = %d, expire = %d, headers = '%s', serialized = %d WHERE cid = '%s'", $data, time(), $expire, $headers, $serialized, $cid);
+  if (!db_affected_rows($result)) {
     @db_query("INSERT INTO {$table} (cid, data, created, expire, headers, serialized) VALUES ('%s', %b, %d, %d, '%s', %d)", $cid, $data, time(), $expire, $headers, $serialized);
   }
   db_unlock_tables();
Index: includes/database.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database.inc,v
retrieving revision 1.67
diff -u -p -r1.67 database.inc
--- includes/database.inc	13 Apr 2007 08:56:57 -0000	1.67
+++ includes/database.inc	27 Apr 2007 01:53:58 -0000
@@ -164,41 +164,7 @@ function _db_query_callback($match, $ini
  */
 define('DB_QUERY_REGEXP', '/(%d|%s|%%|%f|%b)/');
 
-/**
- * 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);
-}
+
 
 /**
  * Helper function for db_rewrite_sql.
@@ -311,4 +277,3 @@ function db_escape_table($string) {
 /**
  * @} End of "defgroup database".
  */
-
Index: includes/database.mysql.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database.mysql.inc,v
retrieving revision 1.70
diff -u -p -r1.70 database.mysql.inc
--- includes/database.mysql.inc	21 Apr 2007 18:08:41 -0000	1.70
+++ includes/database.mysql.inc	27 Apr 2007 01:53:58 -0000
@@ -140,6 +140,42 @@ function db_connect($url) {
 }
 
 /**
+ * Runs a basic query in the active database.
+ *
+ * User-supplied arguments to the query should be passed in as separate
+ * parameters so that they can be properly escaped to avoid SQL injection
+ * attacks.
+ *
+ * @param $query
+ *   A string containing an SQL query.
+ * @param ...
+ *   A variable number of arguments which are substituted into the query
+ *   using printf() syntax. Instead of a variable number of query arguments,
+ *   you may also pass a single array containing the query arguments.
+ *
+ *   Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
+ *   in '') and %%.
+ *
+ *   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);
+}
+
+/**
  * Helper function for db_query().
  */
 function _db_query($query, $debug = 0) {
Index: includes/database.pdo.inc
===================================================================
RCS file: includes/database.pdo.inc
diff -N includes/database.pdo.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/database.pdo.inc	27 Apr 2007 01:53:58 -0000
@@ -0,0 +1,200 @@
+<?php
+// $Id: $
+
+/**
+ * @file
+ * Database interface code for PDO-based database drivers
+ */
+
+/**
+ * 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];
+  }
+
+  $query = str_replace(array('%d', '$f', '%b', "'%s'", '%s'), '?', $query);
+
+  // NOT NULL DEFAULT 0 and similar techniques in MySQL don't work through PDO.  For now,
+  // fold NULL to 0.  Remove this eventually and make the caller send real data
+  foreach ($args as $key => $value) {
+    if (is_null($args[$key])) {
+      $args[$key] = 0;
+    }
+  }
+
+  return _db_query($query, $args);
+}
+
+/**
+ * Helper function for db_query().
+ */
+function _db_query($query, $args, $debug = 0) {
+  global $active_db, $queries;
+
+  static $prepared = array();
+
+  if (variable_get('dev_query', 0)) {
+    list($usec, $sec) = explode(' ', microtime());
+    $timer = (float)$usec + (float)$sec;
+  }
+
+  // Static-cache prepared statements for speed
+  if (!isset($prepared[$query])) {
+    $prepared[$query] = $active_db->prepare($query);
+  }
+  $result = $prepared[$query];
+if (function_exists('drupal_set_message')) drupal_set_message($result);
+  // Run the query.  ->execute() returns TRUE on success or FALSE on error.
+  // There seems to be a bug with the return value of the ->execute() statement,
+  // so we use exceptions instead, since they seem to work.
+  try {
+    $result->execute($args);
+
+    if (variable_get('dev_query', 0)) {
+      $bt = debug_backtrace();
+      $query = $bt[2]['function'] . "\n" . $query;
+      list($usec, $sec) = explode(' ', microtime());
+      $stop = (float)$usec + (float)$sec;
+      $diff = $stop - $timer;
+      $queries[] = array($query, $diff);
+    }
+
+    return $result;
+  }
+  catch (Exception $e) {
+    if (variable_get('dev_query', 0)) {
+      $bt = debug_backtrace();
+      $query = $bt[2]['function'] . "\n" . $query;
+      list($usec, $sec) = explode(' ', microtime());
+      $stop = (float)$usec + (float)$sec;
+      $diff = $stop - $timer;
+      $queries[] = array($query, $diff);
+    }
+
+    trigger_error(check_plain($e->getMessage() ."\nquery: ". $query), E_USER_WARNING);
+    return FALSE;
+  }
+
+  if ($debug) {
+    print '<p>query: '. $query .'<br />error:'. mysql_error($active_db) .'</p>';
+  }
+
+  return FALSE;
+
+}
+
+/**
+ * Fetch one result row from the previous query as an object.
+ *
+ * @param $result
+ *   A database query result resource, as returned from db_query().
+ * @return
+ *   An object representing the next row of the result. The attributes of this
+ *   object are the table fields selected by the query.
+ */
+function db_fetch_object(PDOStatement $result) {
+  if ($result) {
+    return $result->fetch(PDO::FETCH_OBJ);
+  }
+}
+
+/**
+ * Fetch one result row from the previous query as an array.
+ *
+ * @param $result
+ *   A database query result resource, as returned from db_query().
+ * @return
+ *   An associative array representing the next row of the result. The keys of
+ *   this object are the names of the table fields selected by the query, and
+ *   the values are the field values for this result row.
+ */
+function db_fetch_array(PDOStatement $result) {
+  if ($result) {
+    return $result->fetch(PDO::FETCH_ASSOC);
+  }
+}
+
+/**
+ * Determine how many result rows were found by the preceding query.
+ *
+ * @param $result
+ *   A database query result resource, as returned from db_query().
+ * @return
+ *   The number of result rows.
+ */
+ /*
+function db_num_rows(PDOStatement $result) {
+  if ($result) {
+    return $result->rowCount();
+  }
+}
+*/
+
+/**
+ * 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) {
+    return $result->fetchColumn();
+  }
+  return FALSE;
+}
+
+/**
+ * Determine whether the previous query caused an error.
+ */
+function db_error() {
+  global $active_db;
+  return $active_db->errorCode();
+}
+
+/**
+ * Prepare user input for use in a database query, preventing SQL injection attacks.
+ */
+function db_escape_string($text) {
+  global $active_db;
+  return $active_db->quote($text);
+}
+
+
+/**
+ * @} End of "ingroup database".
+ */
+
Index: includes/database.pdomysql.inc
===================================================================
RCS file: includes/database.pdomysql.inc
diff -N includes/database.pdomysql.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/database.pdomysql.inc	27 Apr 2007 01:53:58 -0000
@@ -0,0 +1,342 @@
+<?php
+// $Id: $
+
+/**
+ * @file
+ * Database interface code for MySQL database servers using the PDO API
+ */
+
+/**
+ * @ingroup database
+ * @{
+ */
+
+// Include the shared portions of the PDO driver
+require_once('includes/database.pdo.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/logs/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('-', db_result(db_query("SELECT version()")));
+  return $version;
+}
+
+/**
+ * Initialize a database connection.
+ *
+ * Note that you can change the mysql_connect() call to mysql_pconnect() if you
+ * want to use persistent connections. This is not recommended on shared hosts,
+ * and might require additional database/webserver tuning. It can increase
+ * performance, however, when the overhead to connect to your database is high
+ * (e.g. your database and web server live on different machines).
+ */
+function db_connect($url) {
+  $url = parse_url($url);
+
+  // Check if PDO support is present in PHP, and the MySQL driver
+  if (!class_exists('PDO') || !in_array('mysql', PDO::getAvailableDrivers())) {
+    // Redirect to installer if using default DB credentials
+    if ($url['user'] == 'username' && $url['pass'] == 'password') {
+      include_once 'includes/install.inc';
+      install_goto('install.php');
+    }
+    drupal_maintenance_theme();
+    drupal_set_title('PHP PDO-MySQL support not enabled');
+    print theme('maintenance_page', '<p>We were unable to use the MySQL database because the PDO extension for PHP is not installed. Check your <code>PHP.ini</code> to see how you can enable it.</p>
+<p>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.</p>');
+    exit;
+  }
+
+  // Decode url-encoded information in the db connection string
+  $url['user'] = urldecode($url['user']);
+  // Test if database url has a password.
+  if(isset($url['pass'])) {
+    $url['pass'] = urldecode($url['pass']);
+  }
+  else {
+    $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'];
+  }
+
+  try {
+    $connection = new PDO('mysql:host='. $url['host'] . ';dbname=' . substr($url['path'], 1), $url['user'], $url['pass'], array(
+      PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
+    ));
+    $connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
+    $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+  }
+  catch (PDOException $e) {
+     // Redirect to installer if using default DB credentials
+    if ($url['user'] == 'username' && $url['pass'] == 'password') {
+      include_once 'includes/install.inc';
+      install_goto('install.php');
+    }
+
+    // Show error screen otherwise
+    drupal_maintenance_theme();
+    drupal_set_header('HTTP/1.1 503 Service Unavailable');
+    drupal_set_title('Unable to connect to database server');
+    print theme('maintenance_page', '<p>If you still have to install Drupal, proceed to the <a href="'. base_path() .'install.php">installation page</a>.</p>
+  <p>If you have already finished installed Drupal, this either means that the username and password information in your <code>settings.php</code> file is incorrect or that we can\'t connect to the MySQL database server. This could mean your hosting provider\'s database server is down.</p>
+  <p>The MySQL error was: '. theme('placeholder', mysql_error()) .'.</p>
+  <p>Currently, the username is '. theme('placeholder', $url['user']) .' and the database server is '. theme('placeholder', $url['host']) .'.</p>
+  <ul>
+  <li>Are you sure you have the correct username and password?</li>
+  <li>Are you sure that you have typed the correct hostname?</li>
+  <li>Are you sure that the database server is running?</li>
+  </ul>
+  <p>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.</p>');
+    exit;
+  
+  /* Old code for separate handling of db failure rather than server failure
+  drupal_maintenance_theme();
+    drupal_set_title('Unable to select database');
+    print theme('maintenance_page', '<p>We were able to connect to the MySQL database server (which means your username and password are okay) but not able to select the database.</p>
+<p>The MySQL error was: '. theme('placeholder', mysql_error($connection)) .'.</p>
+<p>Currently, the database is '. theme('placeholder', substr($url['path'], 1)) .'. The username is '. theme('placeholder', $url['user']) .' and the database server is '. theme('placeholder', $url['host']) .'.</p>
+<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>
+<p>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.</p>');
+    exit;
+    */
+  
+  }
+
+  // Set the connection to UTF-8
+  $connection->exec('SET NAMES "utf8"');
+
+  return $connection;
+}
+
+
+/**
+ * Return a new unique ID in the given sequence.
+ *
+ * For compatibility reasons, Drupal does not use auto-numbered fields in its
+ * database tables. Instead, this function is used to return a new unique ID
+ * of the type requested. If necessary, a new sequence with the given name
+ * will be created.
+ *
+ * Note that the table name should be in curly brackets to preserve compatibility
+ * with table prefixes. For example, db_next_id('{node}_nid');
+ */
+function db_next_id($name) {
+  $name = db_prefix_tables($name);
+  db_query('LOCK TABLES {sequences} WRITE');
+  $id = db_result(db_query("SELECT id FROM {sequences} WHERE name = '%s'", $name)) + 1;
+  db_query("REPLACE INTO {sequences} VALUES ('%s', %d)", $name, $id);
+  db_query('UNLOCK TABLES');
+
+  return $id;
+}
+
+/**
+ * Determine the number of rows changed by the preceding query.
+ */
+function db_affected_rows(PDOStatement $statement) {
+  return $statement->rowCount();
+}
+
+
+/**
+ * Runs a limited-range query in the active database.
+ *
+ * Use this as a substitute for db_query() when a subset of the query is to be
+ * returned.
+ * User-supplied arguments to the query should be passed in as separate parameters
+ * so that they can be properly escaped to avoid SQL injection attacks.
+ *
+ * @param $query
+ *   A string containing an SQL query.
+ * @param ...
+ *   A variable number of arguments which are substituted into the query
+ *   using printf() syntax. The query arguments can be enclosed in one
+ *   array instead.
+ *   Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
+ *   in '') and %%.
+ *
+ *   NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
+ *   and TRUE values to decimal 1.
+ *
+ * @param $from
+ *   The first result row to return.
+ * @param $count
+ *   The maximum number of result rows to return.
+ * @return
+ *   A database query result resource, or FALSE if the query was not executed
+ *   correctly.
+ */
+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];
+  }
+  $query = str_replace(array('%d', '$f', '%b', "'%s'"), '?', $query);
+
+  $query .= ' LIMIT '. (int)$from .', '. (int)$count;
+
+  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_num_rows() and
+ * db_affected_rows() do not give consistent result across different database
+ * types in this case.
+ *
+ * @param $query
+ *   A string containing a normal SELECT SQL query.
+ * @param ...
+ *   A variable number of arguments which are substituted into the query
+ *   using printf() syntax. The query arguments can be enclosed in one
+ *   array instead.
+ *   Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
+ *   in '') and %%.
+ *
+ *   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', db_prefix_tables($query));
+  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
+    $args = $args[0];
+  }
+
+  $query = str_replace(array('%d', '$f', '%b', "'%s'", '%s'), '?', $query);
+
+  // NOT NULL DEFAULT 0 and similar techniques in MySQL don't work through PDO.  For now,
+  // fold NULL to 0.  Remove this eventually and make the caller send real data
+  foreach ($args as $key => $value) {
+    if (is_null($args[$key])) {
+      $args[$key] = 0;
+    }
+  }
+
+  return _db_query($query, $args);
+}
+
+/**
+ * Returns a properly formatted Binary Large OBject value.
+ *
+ * @param $data
+ *   Data to encode.
+ * @return
+ *  Encoded data.
+ */
+function db_encode_blob($data) {
+  global $active_db;
+  return "'" . mysql_real_escape_string($data, $active_db) . "'";
+}
+
+/**
+ * Returns text from a Binary Large Object value.
+ *
+ * @param $data
+ *   Data to decode.
+ * @return
+ *  Decoded data.
+ */
+function db_decode_blob($data) {
+  return $data;
+}
+
+/**
+ * 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 (boolean) db_result(db_query("SHOW TABLES LIKE '{" . db_escape_table($table) . "}'"));
+}
+
+/**
+ * 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/install.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/install.inc,v
retrieving revision 1.37
diff -u -p -r1.37 install.inc
--- includes/install.inc	17 Apr 2007 07:19:38 -0000	1.37
+++ includes/install.inc	27 Apr 2007 01:53:58 -0000
@@ -144,7 +144,7 @@ function drupal_detect_baseurl($file = '
 function drupal_detect_database_types() {
   $databases = array();
 
-  foreach (array('mysql', 'mysqli', 'pgsql') as $type) {
+  foreach (array('mysql', 'mysqli', 'pgsql', 'pdomysql') as $type) {
     if (file_exists('./includes/install.'. $type .'.inc')) {
       include_once './includes/install.'. $type .'.inc';
       $function = $type .'_is_available';
Index: includes/install.pdomysql.inc
===================================================================
RCS file: includes/install.pdomysql.inc
diff -N includes/install.pdomysql.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/install.pdomysql.inc	27 Apr 2007 01:53:58 -0000
@@ -0,0 +1,144 @@
+<?php
+// $Id: install.mysql.inc,v 1.4 2006/12/27 13:02:34 drumm Exp $
+
+// PDO-MySQL specific install functions
+
+/**
+ * Check if MySQL is available.
+ *
+ * @return
+ *  TRUE/FALSE
+ */
+function pdomysql_is_available() {
+  return (class_exists('PDO') && in_array('mysql', PDO::getAvailableDrivers()));
+}
+
+/**
+ * Check if we can connect to MySQL.
+ *
+ * @return
+ *  TRUE/FALSE
+ */
+function drupal_test_pdomysql($url, &$success) {
+  if (!pdomysql_is_available()) {
+    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'] = 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'];
+  }
+
+  // Test connecting to the database and selecting the database.  In PDO, that's a single operation.
+  try {
+    $connection = new PDO('mysql:host='. $url['host'] . ';dbname=' . substr($url['path'], 1), $url['user'], $url['pass'], array(
+      PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
+    ));
+    $connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
+    $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+  }
+  catch (PDOException $e) {
+    drupal_set_message(st('Failure to connect to your MySQL database server or to connect to the database. 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;
+  }
+
+  $success = array('CONNECT');
+
+  // Test CREATE.
+  try {
+    $query = 'CREATE TABLE drupal_install_test (id int NULL)';
+    $result = $connection->query($query);
+  }
+  catch (PDOException $e) {
+    drupal_set_message(st('We were unable 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' => $e->getMessage())), 'error');
+    return FALSE;
+  }
+
+  $err = FALSE;
+  $success[] = 'SELECT';
+  $success[] = 'CREATE';
+
+  // Test INSERT.
+  try {
+    $query = 'INSERT INTO drupal_install_test (id) VALUES (1)';
+    $result = $connection->query($query);
+    $success[] = 'INSERT';
+  }
+  catch (PDOException $e) {
+    drupal_set_message(st('We were unable 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' => $e->getMessage())), 'error');
+    $err = TRUE;
+  }
+
+  // Test UPDATE.
+  try {
+    $query = 'UPDATE drupal_install_test SET id = 2';
+    $result = $connection->query($query);
+    $success[] = 'UPDATE';
+  }
+  catch (PDOException $e) {
+    drupal_set_message(st('We were unable 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' => $e->getMessage())), 'error');
+    $err = TRUE;
+  }
+
+  // Test LOCK.
+  try {
+    $query = 'LOCK TABLES drupal_install_test WRITE';
+    $result = $connection->query($query);
+    $success[] = 'LOCK';
+  }
+  catch (PDOException $e) {
+    drupal_set_message(st('We were unable 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' => $e->getMessage())), 'error');
+    $err = TRUE;
+  }
+
+  // Test UNLOCK.
+  try {
+    $query = 'UNLOCK TABLES';
+    $result = $connection->query($query);
+    $success[] = 'UNLOCK';
+  }
+  catch (PDOException $e) {
+    drupal_set_message(st('We were unable 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' => $e->getMessage())), 'error');
+    $err = TRUE;
+  }
+
+  // Test DELETE.
+  try {
+    $query = 'DELETE FROM drupal_install_test';
+    $result = $connection->query($query);
+    $success[] = 'DELETE';
+  }
+  catch (PDOException $e) {
+    drupal_set_message(st('We were unable 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' => $e->getMessage())), 'error');
+    $err = TRUE;
+  }
+
+  // Test DROP.
+  try {
+    $query = 'DROP TABLE drupal_install_test';
+    $result = $connection->query($query);
+    $success[] = 'DROP';
+  }
+  catch (PDOException $e) {
+    drupal_set_message(st('We were unable 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' => $e->getMessage())), 'error');
+    $err = TRUE;
+  }
+
+  if ($err) {
+    return FALSE;
+  }
+
+  unset($connection);
+  return TRUE;
+}
Index: includes/path.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/path.inc,v
retrieving revision 1.15
diff -u -p -r1.15 path.inc
--- includes/path.inc	26 Mar 2007 01:32:22 -0000	1.15
+++ includes/path.inc	27 Apr 2007 01:53:58 -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(*) FROM {url_alias}'));
   }
 
   if ($action == 'wipe') {
Index: includes/session.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/session.inc,v
retrieving revision 1.38
diff -u -p -r1.38 session.inc
--- includes/session.inc	27 Mar 2007 05:13:53 -0000	1.38
+++ includes/session.inc	27 Apr 2007 01:53:58 -0000
@@ -61,9 +61,10 @@ function sess_write($key, $value) {
     return TRUE;
   }
 
-  $result = db_query("SELECT sid FROM {sessions} WHERE sid = '%s'", $key);
+  $result = db_query("SELECT COUNT(*) FROM {sessions} WHERE sid = '%s'", $key);
+  $is_existing_session = db_result($result);
 
-  if (!db_num_rows($result)) {
+  if (!$is_existing_session) {
     // Only save session data when when the browser sends a cookie. This keeps
     // crawlers out of session table. This improves speed up queries, reduces
     // memory, and gives more useful statistics. We can't eliminate anonymous
Index: modules/aggregator/aggregator.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.install,v
retrieving revision 1.8
diff -u -p -r1.8 aggregator.install
--- modules/aggregator/aggregator.install	26 Sep 2006 14:19:00 -0000	1.8
+++ modules/aggregator/aggregator.install	27 Apr 2007 01:53:58 -0000
@@ -8,6 +8,7 @@ function aggregator_install() {
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
+    case 'pdomysql':
       db_query("CREATE TABLE {aggregator_category} (
         cid int NOT NULL auto_increment,
         title varchar(255) NOT NULL default '',
Index: modules/aggregator/aggregator.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v
retrieving revision 1.337
diff -u -p -r1.337 aggregator.module
--- modules/aggregator/aggregator.module	24 Apr 2007 13:53:11 -0000	1.337
+++ modules/aggregator/aggregator.module	27 Apr 2007 01:53:58 -0000
@@ -956,11 +956,13 @@ function aggregator_parse_feed(&$data, $
   $age = time() - variable_get('aggregator_clear', 9676800);
   $result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = %d AND timestamp < %d', $feed['fid'], $age);
 
-  if (db_num_rows($result)) {
+  $items = array();
+  while ($item = db_fetch_object($result)) {
+    $items[] = $item->iid;
+  }
+
+  if (count($items)) {
     $items = array();
-    while ($item = db_fetch_object($result)) {
-      $items[] = $item->iid;
-    }
     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);
   }
Index: modules/book/book.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.install,v
retrieving revision 1.6
diff -u -p -r1.6 book.install
--- modules/book/book.install	1 Sep 2006 07:40:08 -0000	1.6
+++ modules/book/book.install	27 Apr 2007 01:53:58 -0000
@@ -8,6 +8,7 @@ function book_install() {
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
+    case 'pdomysql':
       db_query("CREATE TABLE {book} (
         vid int unsigned NOT NULL default '0',
         nid int unsigned NOT NULL default '0',
Index: modules/contact/contact.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/contact/contact.install,v
retrieving revision 1.6
diff -u -p -r1.6 contact.install
--- modules/contact/contact.install	2 Jan 2007 05:30:29 -0000	1.6
+++ modules/contact/contact.install	27 Apr 2007 01:53:58 -0000
@@ -8,6 +8,7 @@ function contact_install() {
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
+    case 'pdomysql':
       db_query("CREATE TABLE {contact} (
         cid int unsigned NOT NULL auto_increment,
         category varchar(255) NOT NULL default '',
Index: modules/dblog/dblog.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/dblog/dblog.install,v
retrieving revision 1.2
diff -u -p -r1.2 dblog.install
--- modules/dblog/dblog.install	24 Apr 2007 13:53:11 -0000	1.2
+++ modules/dblog/dblog.install	27 Apr 2007 01:53:58 -0000
@@ -8,6 +8,7 @@ function dblog_install() {
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
+    case 'pdomysql':
       db_query("CREATE TABLE {watchdog} (
         wid int NOT NULL auto_increment,
         uid int NOT NULL default '0',
Index: modules/drupal/drupal.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/drupal/drupal.install,v
retrieving revision 1.5
diff -u -p -r1.5 drupal.install
--- modules/drupal/drupal.install	1 Sep 2006 07:40:08 -0000	1.5
+++ modules/drupal/drupal.install	27 Apr 2007 01:53:58 -0000
@@ -8,6 +8,7 @@ function drupal_install() {
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
+    case 'pdomysql':
       db_query("CREATE TABLE {client} (
         cid int unsigned NOT NULL auto_increment,
         link varchar(255) NOT NULL default '',
Index: modules/forum/forum.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forum.install,v
retrieving revision 1.6
diff -u -p -r1.6 forum.install
--- modules/forum/forum.install	1 Sep 2006 07:40:08 -0000	1.6
+++ modules/forum/forum.install	27 Apr 2007 01:53:58 -0000
@@ -8,6 +8,7 @@ function forum_install() {
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
+    case 'pdomysql':
       db_query("CREATE TABLE {forum} (
         nid int unsigned NOT NULL default '0',
         vid int unsigned NOT NULL default '0',
Index: modules/locale/locale.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.install,v
retrieving revision 1.8
diff -u -p -r1.8 locale.install
--- modules/locale/locale.install	26 Mar 2007 01:32:22 -0000	1.8
+++ modules/locale/locale.install	27 Apr 2007 01:53:58 -0000
@@ -11,6 +11,7 @@ function locale_install() {
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
+    case 'pdomysql':
       db_query("CREATE TABLE {languages} (
         language varchar(12) NOT NULL default '',
         name varchar(64) NOT NULL default '',
Index: modules/menu/menu.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.install,v
retrieving revision 1.2
diff -u -p -r1.2 menu.install
--- modules/menu/menu.install	15 Apr 2007 14:38:16 -0000	1.2
+++ modules/menu/menu.install	27 Apr 2007 01:53:58 -0000
@@ -8,6 +8,7 @@ function menu_install() {
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
+    case 'pdomysql':
       db_query("CREATE TABLE {menu_custom} (
         path varchar(255) NOT NULL default '' ,
         disabled int NOT NULL default 0,
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.805
diff -u -p -r1.805 node.module
--- modules/node/node.module	25 Apr 2007 21:28:00 -0000	1.805
+++ modules/node/node.module	27 Apr 2007 01:53:59 -0000
@@ -343,7 +343,7 @@ function node_types_rebuild() {
 function node_type_save($info) {
   $is_existing = FALSE;
   $existing_type = !empty($info->old_type) ? $info->old_type : $info->type;
-  $is_existing = db_num_rows(db_query("SELECT * FROM {node_type} WHERE type = '%s'", $existing_type));
+  $is_existing = db_result(db_query("SELECT COUNT(*) FROM {node_type} WHERE type = '%s'", $existing_type));
   if (!isset($info->help)) {
     $info->help = '';
   }
@@ -2426,12 +2426,18 @@ function node_revisions() {
 function node_page_default() {
   $result = pager_query(db_rewrite_sql('SELECT n.nid, n.sticky, n.created FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC'), variable_get('default_nodes_main', 10));
 
-  if (db_num_rows($result)) {
+    // We don't have db_num_rows() anymore, so we have to pre-fetch the data to know if there is any
+    $records = array();
+    while ($record = db_fetch_object($result)) {
+      $records[] = $record;
+    }
+    if (count($records)) {
+
     $feed_url = url('rss.xml', array('absolute' => TRUE));
     drupal_add_feed($feed_url, variable_get('site_name', 'Drupal') .' '. t('RSS'));
 
     $output = '';
-    while ($node = db_fetch_object($result)) {
+    foreach ($records as $node) {
       $output .= node_view(node_load($node->nid), 1);
     }
     $output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
Index: modules/poll/poll.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll/poll.install,v
retrieving revision 1.7
diff -u -p -r1.7 poll.install
--- modules/poll/poll.install	1 Sep 2006 07:40:08 -0000	1.7
+++ modules/poll/poll.install	27 Apr 2007 01:53:59 -0000
@@ -8,6 +8,7 @@ function poll_install() {
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
+    case 'pdomysql':
       db_query("CREATE TABLE {poll} (
         nid int unsigned NOT NULL default '0',
         runtime int NOT NULL default '0',
Index: modules/profile/profile.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/profile/profile.install,v
retrieving revision 1.8
diff -u -p -r1.8 profile.install
--- modules/profile/profile.install	28 Nov 2006 14:37:44 -0000	1.8
+++ modules/profile/profile.install	27 Apr 2007 01:53:59 -0000
@@ -8,6 +8,7 @@ function profile_install() {
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
+    case 'pdomysql':
       db_query("CREATE TABLE {profile_fields} (
         fid int NOT NULL auto_increment,
         title varchar(255) default NULL,
Index: modules/search/search.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.install,v
retrieving revision 1.6
diff -u -p -r1.6 search.install
--- modules/search/search.install	1 Sep 2006 07:40:08 -0000	1.6
+++ modules/search/search.install	27 Apr 2007 01:53:59 -0000
@@ -8,6 +8,7 @@ function search_install() {
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
+    case 'pdomysql':
       db_query("CREATE TABLE {search_dataset} (
         sid int unsigned NOT NULL default '0',
         type varchar(16) default NULL,
Index: modules/statistics/statistics.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/statistics/statistics.install,v
retrieving revision 1.7
diff -u -p -r1.7 statistics.install
--- modules/statistics/statistics.install	7 Nov 2006 22:27:07 -0000	1.7
+++ modules/statistics/statistics.install	27 Apr 2007 01:53:59 -0000
@@ -8,6 +8,7 @@ function statistics_install() {
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
+    case 'pdomysql':
       db_query("CREATE TABLE {accesslog} (
         aid int NOT NULL auto_increment,
         sid varchar(64) NOT NULL default '',
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.99
diff -u -p -r1.99 system.install
--- modules/system/system.install	25 Apr 2007 21:34:32 -0000	1.99
+++ modules/system/system.install	27 Apr 2007 01:54:00 -0000
@@ -173,6 +173,7 @@ function system_install() {
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
+    case 'pdomysql':
       db_query("CREATE TABLE {access} (
         aid int NOT NULL auto_increment,
         mask varchar(255) NOT NULL default '',
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.775
diff -u -p -r1.775 user.module
--- modules/user/user.module	24 Apr 2007 13:53:15 -0000	1.775
+++ modules/user/user.module	27 Apr 2007 01:54:00 -0000
@@ -105,8 +105,9 @@ function user_load($array = array()) {
   }
   $result = db_query('SELECT * FROM {users} u WHERE '. implode(' AND ', $query), $params);
 
-  if (db_num_rows($result)) {
-    $user = db_fetch_object($result);
+  $user = db_fetch_object($result);
+
+  if ($user) {
     $user = drupal_unpack($user);
 
     $user->roles = array();
@@ -434,11 +435,10 @@ function user_fields() {
   static $fields;
 
   if (!$fields) {
-    $result = db_query('SELECT * FROM {users} WHERE uid = 1');
-    if (db_num_rows($result)) {
-      $fields = array_keys(db_fetch_array($result));
-    }
-    else {
+    // All records in the users table will have the same fields, so it doesn't matter which one 
+    // we get as long as there's always one user in the table.
+    $fields = array_keys(db_fetch_array(db_query_range('SELECT * FROM {users}', 0, 1)));
+    if (! count($fields)) {
       // Make sure we return the default fields at least
       $fields = array('uid', 'name', 'pass', 'mail', 'picture', 'mode', 'sort', 'threshold', 'theme', 'signature', 'created', 'access', 'login', 'status', 'timezone', 'language', 'init', 'data');
     }
@@ -1507,7 +1507,7 @@ function _user_edit_validate($uid, &$edi
     if ($error = user_validate_name($edit['name'])) {
       form_set_error('name', $error);
     }
-    else if (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != %d AND LOWER(name) = LOWER('%s')", $uid, $edit['name'])) > 0) {
+    else if (db_result(db_query("SELECT COUNT(*) FROM {users} WHERE uid != %d AND LOWER(name) = LOWER('%s')", $uid, $edit['name'])) > 0) {
       form_set_error('name', t('The name %name is already taken.', array('%name' => $edit['name'])));
     }
     else if (drupal_is_denied('user', $edit['name'])) {
@@ -1519,7 +1519,7 @@ function _user_edit_validate($uid, &$edi
   if ($error = user_validate_mail($edit['mail'])) {
     form_set_error('mail', $error);
   }
-  else if (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != %d AND LOWER(mail) = LOWER('%s')", $uid, $edit['mail'])) > 0) {
+  else if (db_result(db_query("SELECT COUNT(*) FROM {users} WHERE uid != %d AND LOWER(mail) = LOWER('%s')", $uid, $edit['mail'])) > 0) {
     form_set_error('mail', t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array('%email' => $edit['mail'], '@password' => url('user/password'))));
   }
   else if (drupal_is_denied('mail', $edit['mail'])) {
