Commit e5ddb46d authored by Dries's avatar Dries
Browse files

- Patch #314464 by Crell, Dave Reid et al: convert db_placeholders() to the new DB layer.

parent dcf75020
......@@ -349,10 +349,14 @@ protected function prefixTables($sql) {
* @param $query
* The query string as SQL, with curly-braces surrounding the
* table names.
* @param $query
* 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.
* @return
* A PDO prepared statement ready for its execute() method.
*/
protected function prepareQuery($query) {
protected function prepareQuery($query, $cache = TRUE) {
$query = self::prefixTables($query);
if (empty($this->preparedStatements[$query])) {
// Call PDO::prepare.
......@@ -473,7 +477,8 @@ public function query($query, array $args = array(), $options = array()) {
$stmt->execute(NULL, $options);
}
else {
$stmt = $this->prepareQuery($query);
$modified = $this->expandArguments($query, $args);
$stmt = $this->prepareQuery($query, !$modified);
$stmt->execute($args, $options);
}
......@@ -507,6 +512,50 @@ public function query($query, array $args = array(), $options = array()) {
}
}
/**
* Expand out shorthand placeholders.
*
* Drupal supports an alternate syntax for doing arrays of values. We therefore
* need to expand them out into a full, executable query string.
*
* @param $query
* The query string to modify.
* @param $args
* The arguments for the query.
* @return
* TRUE if the query was modified, FALSE otherwise.
*/
protected function expandArguments(&$query, &$args) {
$modified = FALSE;
foreach ($args as $key => $data) {
// is_array() is slower than checking a string value, so do that first.
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;
}
// Update the query with the new placeholders.
$query = str_replace($key, implode(', ', $new_keys), $query);
// Update the args array with the new placeholders.
unset($args[$key]);
$args += $new_keys;
$modified = TRUE;
}
}
return $modified;
}
/**
* Prepare and return a SELECT query object with the specified ID.
*
......
......@@ -2067,3 +2067,29 @@ class DatabaseInvalidDataTestCase extends DatabaseTestCase {
}
}
}
/**
* Drupal-specific SQL syntax tests.
*/
class DatabaseQueryTestCase extends DatabaseTestCase {
function getInfo() {
return array(
'name' => t('Custom query syntax tests'),
'description' => t('Test Drupal\'s extended prepared statement syntax..'),
'group' => t('Database'),
);
}
function setUp() {
parent::setUp('database_test');
}
/**
* Confirm that temporary tables work and are limited to one request.
*/
function testArraySubstitution() {
$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'));
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment