? .DS_Store ? .cache ? .git ? .project ? .settings ? INSTALL.sqlite.txt ? logs ? placeholder_array_0.patch ? includes/database/.database.inc.swp ? sites/.DS_Store ? sites/all/modules ? sites/default/.DS_Store ? sites/default/files ? sites/default/settings.php ? sites/default/test Index: includes/database/database.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database/database.inc,v retrieving revision 1.36 diff -u -p -r1.36 database.inc --- includes/database/database.inc 24 Dec 2008 09:53:40 -0000 1.36 +++ includes/database/database.inc 25 Dec 2008 09:37:14 -0000 @@ -349,7 +349,7 @@ abstract class DatabaseConnection extend * @param $query * The query string as SQL, with curly-braces surrounding the * table names. - * @param $query + * @param $cache * Whether or not to cache the prepared statement for later reuse in this * same request. Usually we want to, but queries that require preprocessing * cannot be safely cached. @@ -529,21 +529,21 @@ abstract class DatabaseConnection extend $modified = FALSE; foreach ($args as $key => $data) { - // is_array() is slower than checking a string value, so do that first. + // If the placeholder value to insert is an array, assume that we need + // to expand it out into a comma-delimited set of placeholders. if (is_array($data)) { $new_keys = array(); - $base = $key; - $base[0] = ':'; foreach ($data as $i => $value) { - $candidate_placeholder = $base . '_' . $i; - while (isset($args[$candidate_placeholder])) { - $candidate_placeholder .= mt_rand(); - } - $new_keys[$candidate_placeholder] = $value; + // This assumes that there are no other placeholders that use the same + // name. For example, if the array placeholder is defined as :example + // and there is already an :example_2 placeholder, this will generate + // a duplicate key. We do not account for that as the calling code + // is already broken if that happens. + $new_keys[$key . '_' . $i] = $value; } // Update the query with the new placeholders. - $query = str_replace($key, implode(', ', $new_keys), $query); + $query = str_replace($key, implode(', ', array_keys($new_keys)), $query); // Update the args array with the new placeholders. unset($args[$key]); Index: includes/database/pgsql/database.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database/pgsql/database.inc,v retrieving revision 1.14 diff -u -p -r1.14 database.inc --- includes/database/pgsql/database.inc 20 Dec 2008 18:24:34 -0000 1.14 +++ includes/database/pgsql/database.inc 25 Dec 2008 09:37:14 -0000 @@ -41,7 +41,8 @@ class DatabaseConnection_pgsql extends D $stmt->execute(NULL, $options); } else { - $stmt = $this->prepareQuery($query); + $modified = $this->expandArguments($query, $args); + $stmt = $this->prepareQuery($query, !$modified); $stmt->execute($args, $options); } Index: modules/simpletest/tests/database_test.test =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/database_test.test,v retrieving revision 1.30 diff -u -p -r1.30 database_test.test --- modules/simpletest/tests/database_test.test 24 Dec 2008 10:21:32 -0000 1.30 +++ modules/simpletest/tests/database_test.test 25 Dec 2008 09:37:16 -0000 @@ -2085,10 +2085,10 @@ class DatabaseQueryTestCase extends Data } /** - * Confirm that temporary tables work and are limited to one request. + * Test that we can specify an array of values in the query by simply passing in an array. */ function testArraySubstitution() { - $names = db_query("SELECT name FROM {test} WHERE age IN (@ages) ORDER BY age", array('@ages' => array(25, 26, 27)))->fetchAll(); + $names = db_query("SELECT name FROM {test} WHERE age IN (:ages) ORDER BY age", array(':ages' => array(25, 26, 27)))->fetchAll(); $this->assertEqual(count($names), 3, t('Correct number of names returned')); }