summaryrefslogtreecommitdiff
path: root/includes/database
diff options
context:
space:
mode:
Diffstat (limited to 'includes/database')
-rw-r--r--includes/database/database.inc53
1 files changed, 51 insertions, 2 deletions
diff --git a/includes/database/database.inc b/includes/database/database.inc
index 411d2cfd7..900a518c7 100644
--- a/includes/database/database.inc
+++ b/includes/database/database.inc
@@ -349,10 +349,14 @@ abstract class DatabaseConnection extends PDO {
* @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 @@ abstract class DatabaseConnection extends PDO {
$stmt->execute(NULL, $options);
}
else {
- $stmt = $this->prepareQuery($query);
+ $modified = $this->expandArguments($query, $args);
+ $stmt = $this->prepareQuery($query, !$modified);
$stmt->execute($args, $options);
}
@@ -508,6 +513,50 @@ abstract class DatabaseConnection extends PDO {
}
/**
+ * 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.
*
* @see SelectQuery