#783814: enforce that only simple SELECT queries are passed to db_query() and DatabaseConnection::query() to prevent module authors from writing non-portable queries unknowingly.

From: root <root@lab.local>


---
 actions.inc                                        |    4 +-
 database/database.inc                              |   33 ++++++++++++++++----
 database/mysql/database.inc                        |    9 +++--
 database/mysql/schema.inc                          |   32 ++++++++++---------
 database/pgsql/database.inc                        |    7 ++--
 database/pgsql/install.inc                         |   19 ++++--------
 database/pgsql/schema.inc                          |   28 ++++++++---------
 database/query.inc                                 |   20 ++++++++++++
 database/schema.inc                                |    8 ++---
 database/select.inc                                |    4 ++
 database/sqlite/database.inc                       |    9 ++---
 database/sqlite/schema.inc                         |   24 +++++++--------
 install.inc                                        |    2 +
 locale.inc                                         |    4 +-
 menu.inc                                           |    2 +
 module.inc                                         |    2 +
 path.inc                                           |    2 +
 registry.inc                                       |    2 +
 update.inc                                         |    4 +-
 block/block.install                                |    2 +
 block/block.test                                   |    8 ++---
 book/book.install                                  |    4 ++
 comment/comment.install                            |    5 ++-
 .../field_sql_storage/field_sql_storage.test       |    4 +-
 forum/forum.install                                |   13 +++++++-
 forum/forum.test                                   |    6 +++-
 help/help.test                                     |    2 +
 locale/locale.module                               |    5 ++-
 locale/locale.test                                 |    6 ++--
 menu/menu.admin.inc                                |    2 +
 menu/menu.module                                   |   10 ++++--
 menu/menu.test                                     |    2 +
 node/node.module                                   |    4 +-
 node/node.test                                     |    6 ++--
 openid/openid.pages.inc                            |    5 ++-
 search/search.api.php                              |    4 +-
 simpletest/drupal_web_test_case.php                |    4 +-
 simpletest/tests/actions.test                      |    2 +
 simpletest/tests/database_test.test                |    2 +
 simpletest/tests/menu.test                         |    6 +---
 simpletest/tests/path.test                         |    2 +
 system/system.admin.inc                            |   14 +++++---
 system/system.install                              |   17 +++++-----
 system/system.module                               |    7 +++-
 system/system.test                                 |    9 ++++-
 toolbar/toolbar.module                             |    6 +++-
 trigger/trigger.install                            |    2 +
 user/user.install                                  |    2 +
 48 files changed, 224 insertions(+), 152 deletions(-)

diff --git includes/actions.inc includes/actions.inc
index d7c625c..c15ee30 100644
--- includes/actions.inc
+++ includes/actions.inc
@@ -245,7 +245,7 @@ function actions_function_lookup($hash) {
   }
   $aid = FALSE;
   // Must be a configurable action; check database.
-  $result = db_query("SELECT aid FROM {actions} WHERE parameters <> ''")->fetchAll(PDO::FETCH_ASSOC);
+  $result = db_query("SELECT aid FROM {actions} WHERE parameters <> :parameters", array(':parameters' => ''))->fetchAll(PDO::FETCH_ASSOC);
   foreach ($result as $row) {
     if (drupal_hash_base64($row['aid']) == $hash) {
       $aid = $row['aid'];
@@ -270,7 +270,7 @@ function actions_function_lookup($hash) {
  */
 function actions_synchronize($delete_orphans = FALSE) {
   $actions_in_code = actions_list(TRUE);
-  $actions_in_db = db_query("SELECT aid, callback, label FROM {actions} WHERE parameters = ''")->fetchAllAssoc('callback', PDO::FETCH_ASSOC);
+  $actions_in_db = db_query("SELECT aid, callback, label FROM {actions} WHERE parameters = :parameters", array(':parameters' => ''))->fetchAllAssoc('callback', PDO::FETCH_ASSOC);
 
   // Go through all the actions provided by modules.
   foreach ($actions_in_code as $callback => $array) {
diff --git includes/database/database.inc includes/database/database.inc
index d772094..37beeed 100644
--- includes/database/database.inc
+++ includes/database/database.inc
@@ -313,6 +313,10 @@ abstract class DatabaseConnection extends PDO {
    *   further up the call chain can take an appropriate action. To suppress
    *   that behavior and simply return NULL on failure, set this option to
    *   FALSE.
+   * - relax_checks: By default, only simple SELECT queries will be accepted by
+   *   the db_query() call. You can set this flag to TRUE to pass other types
+   *   of query directly to the database engine. The behavior of the database
+   *   layer in that case is undefined.
    *
    * @return
    *   An array of default query options.
@@ -323,6 +327,7 @@ abstract class DatabaseConnection extends PDO {
       'fetch' => PDO::FETCH_OBJ,
       'return' => Database::RETURN_STATEMENT,
       'throw_exception' => TRUE,
+      'relax_checks' => FALSE,
     );
   }
 
@@ -534,6 +539,15 @@ abstract class DatabaseConnection extends PDO {
         $stmt->execute(NULL, $options);
       }
       else {
+        // Whitelist queries. Only simple SELECT queries should be passed to this
+        // function (and the db_query() wrapper). The queries should start with
+        // SELECT and should not contain any single or double quotes.
+        if (empty($options['relax_checks'])) {
+          if (!preg_match('/^\s*SELECT\s+[^\'"]+$/', $query)) {
+            throw new DatabaseInvalidQueryException('Unsafe query passed to db_query(): ' . $query);
+          }
+        }
+
         $this->expandArguments($query, $args);
         $stmt = $this->prepareQuery($query);
         $stmt->execute($args, $options);
@@ -879,7 +893,7 @@ abstract class DatabaseConnection extends PDO {
         if (empty($this->transactionLayers)) {
           break;
         }
-        $this->query('ROLLBACK TO SAVEPOINT ' . $savepoint);
+        $this->query('ROLLBACK TO SAVEPOINT ' . $savepoint, array(), array('relax_checks' => TRUE));
         return;
       }
     }
@@ -905,7 +919,7 @@ abstract class DatabaseConnection extends PDO {
     // If we're already in a transaction then we want to create a savepoint
     // rather than try to create another transaction.
     if ($this->inTransaction()) {
-      $this->query('SAVEPOINT ' . $name);
+      $this->query('SAVEPOINT ' . $name, array(), array('relax_checks' => TRUE));
     }
     else {
       parent::beginTransaction();
@@ -944,7 +958,7 @@ abstract class DatabaseConnection extends PDO {
         }
       }
       else {
-        $this->query('RELEASE SAVEPOINT ' . $name);
+        $this->query('RELEASE SAVEPOINT ' . $name, array(), array('relax_checks' => TRUE));
         break;
       }
     }
@@ -1467,6 +1481,11 @@ abstract class Database {
 }
 
 /**
+ * Exception thrown when an unsafe query is passed to DatabaseConnection::query().
+ */
+class DatabaseInvalidQueryException extends Exception { }
+
+/**
  * Exception for when popTransaction() is called with no active transaction.
  */
 class DatabaseTransactionNoActiveException extends Exception { }
@@ -2068,9 +2087,11 @@ function db_autoload($class) {
 /**
  * Executes an arbitrary query string against the active database.
  *
- * Do not use this function for INSERT, UPDATE, or DELETE queries. Those should
- * be handled via the appropriate query builder factory. Use this function for
- * SELECT queries that do not require a query builder.
+ * This function cannot be used for INSERT, UPDATE, or DELETE queries, unless
+ * the 'relax_checks' option is set. Those queries should be handled via the
+ * appropriate query builder factory. Use this function only for SELECT queries
+ * that do not require a query builder, and use the appropriate placeholders
+ * to pass string values.
  *
  * @param $query
  *   The prepared statement query to run. Although it will accept both named and
diff --git includes/database/mysql/database.inc includes/database/mysql/database.inc
index 448c325..3b11d75 100644
--- includes/database/mysql/database.inc
+++ includes/database/mysql/database.inc
@@ -64,6 +64,7 @@ class DatabaseConnection_mysql extends DatabaseConnection {
 
   public function queryTemporary($query, array $args = array(), array $options = array()) {
     $tablename = $this->generateTemporaryTableName();
+    $options['relax_checks'] = TRUE;
     $this->query(preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE {' . $tablename . '} Engine=MEMORY SELECT', $query), $args, $options);
     return $tablename;
   }
@@ -82,7 +83,7 @@ class DatabaseConnection_mysql extends DatabaseConnection {
   }
 
   public function nextId($existing_id = 0) {
-    $new_id = $this->query('INSERT INTO {sequences} () VALUES ()', array(), array('return' => Database::RETURN_INSERT_ID));
+    $new_id = $this->query('INSERT INTO {sequences} () VALUES ()', array(), array('relax_checks' => TRUE, 'return' => Database::RETURN_INSERT_ID));
     // This should only happen after an import or similar event.
     if ($existing_id >= $new_id) {
       // If we INSERT a value manually into the sequences table, on the next
@@ -92,8 +93,8 @@ class DatabaseConnection_mysql extends DatabaseConnection {
       // other than duplicate keys. Instead, we use INSERT ... ON DUPLICATE KEY
       // UPDATE in such a way that the UPDATE does not do anything. This way,
       // duplicate keys do not generate errors but everything else does.
-      $this->query('INSERT INTO {sequences} (value) VALUES (:value) ON DUPLICATE KEY UPDATE value = value', array(':value' => $existing_id));
-      $new_id = $this->query('INSERT INTO {sequences} () VALUES ()', array(), array('return' => Database::RETURN_INSERT_ID));
+      $this->query('INSERT INTO {sequences} (value) VALUES (:value) ON DUPLICATE KEY UPDATE value = value', array(':value' => $existing_id), array('relax_checks' => TRUE));
+      $new_id = $this->query('INSERT INTO {sequences} () VALUES ()', array(), array('relax_checks' => TRUE, 'return' => Database::RETURN_INSERT_ID));
     }
     if (!$this->shutdownRegistered) {
       register_shutdown_function(array($this, 'nextIdDelete'));
@@ -113,7 +114,7 @@ class DatabaseConnection_mysql extends DatabaseConnection {
     // counter.
     $max_id = $this->query('SELECT MAX(value) FROM {sequences}')->fetchField();
     // We know we are using MySQL here, so need for the slower db_delete().
-    $this->query('DELETE FROM {sequences} WHERE value < :value', array(':value' => $max_id));
+    $this->query('DELETE FROM {sequences} WHERE value < :value', array(':value' => $max_id), array('relax_checks' => TRUE));
   }
 }
 
diff --git includes/database/mysql/schema.inc includes/database/mysql/schema.inc
index 56fca57..dd714c9 100644
--- includes/database/mysql/schema.inc
+++ includes/database/mysql/schema.inc
@@ -289,7 +289,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
     }
 
     $info = $this->getPrefixInfo($new_name);
-    return $this->connection->query('ALTER TABLE {' . $table . '} RENAME TO `' . $info['table'] . '`');
+    return $this->connection->query('ALTER TABLE {' . $table . '} RENAME TO `' . $info['table'] . '`', array(), array('relax_checks' => TRUE));
   }
 
   public function dropTable($table) {
@@ -297,7 +297,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
       return FALSE;
     }
 
-    $this->connection->query('DROP TABLE {' . $table . '}');
+    $this->connection->query('DROP TABLE {' . $table . '}', array(), array('relax_checks' => TRUE));
     return TRUE;
   }
 
@@ -319,7 +319,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
     if (count($keys_new)) {
       $query .= ', ADD ' . implode(', ADD ', $this->createKeysSql($keys_new));
     }
-    $this->connection->query($query);
+    $this->connection->query($query, array(), array('relax_checks' => TRUE));
     if (isset($spec['initial'])) {
       $this->connection->update($table)
         ->fields(array($field, $spec['initial']))
@@ -336,7 +336,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
       return FALSE;
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} DROP `' . $field . '`');
+    $this->connection->query('ALTER TABLE {' . $table . '} DROP `' . $field . '`', array(), array('relax_checks' => TRUE));
     return TRUE;
   }
 
@@ -352,7 +352,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
       $default = is_string($default) ? "'$default'" : $default;
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN `' . $field . '` SET DEFAULT ' . $default);
+    $this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN `' . $field . '` SET DEFAULT ' . $default, array(), array('relax_checks' => TRUE));
   }
 
   public function fieldSetNoDefault($table, $field) {
@@ -360,13 +360,13 @@ class DatabaseSchema_mysql extends DatabaseSchema {
       throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot remove default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN `' . $field . '` DROP DEFAULT');
+    $this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN `' . $field . '` DROP DEFAULT', array(), array('relax_checks' => TRUE));
   }
 
   public function indexExists($table, $name) {
     // Returns one row for each column in the index. Result is string or FALSE.
     // Details at http://dev.mysql.com/doc/refman/5.0/en/show-index.html
-    $row = $this->connection->query('SHOW INDEX FROM {' . $table . "} WHERE key_name = '$name'")->fetchAssoc();
+    $row = $this->connection->query('SHOW INDEX FROM {' . $table . "} WHERE key_name = '$name'", array(), array('relax_checks' => TRUE))->fetchAssoc();
     return isset($row['key_name']);
   }
 
@@ -378,7 +378,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
       throw new DatabaseSchemaObjectExistsException(t("Cannot add primary key to table %table: primary key already exists.", array('%table' => $table)));
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} ADD PRIMARY KEY (' . $this->createKeySql($fields) . ')');
+    $this->connection->query('ALTER TABLE {' . $table . '} ADD PRIMARY KEY (' . $this->createKeySql($fields) . ')', array(), array('relax_checks' => TRUE));
   }
 
   public function dropPrimaryKey($table) {
@@ -386,7 +386,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
       return FALSE;
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} DROP PRIMARY KEY');
+    $this->connection->query('ALTER TABLE {' . $table . '} DROP PRIMARY KEY', array(), array('relax_checks' => TRUE));
     return TRUE;
   }
 
@@ -398,7 +398,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
       throw new DatabaseSchemaObjectExistsException(t("Cannot add unique key %name to table %table: unique key already exists.", array('%table' => $table, '%name' => $name)));
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} ADD UNIQUE KEY `' . $name . '` (' . $this->createKeySql($fields) . ')');
+    $this->connection->query('ALTER TABLE {' . $table . '} ADD UNIQUE KEY `' . $name . '` (' . $this->createKeySql($fields) . ')', array(), array('relax_checks' => TRUE));
   }
 
   public function dropUniqueKey($table, $name) {
@@ -406,7 +406,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
       return FALSE;
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} DROP KEY `' . $name . '`');
+    $this->connection->query('ALTER TABLE {' . $table . '} DROP KEY `' . $name . '`', array(), array('relax_checks' => TRUE));
     return TRUE;
   }
 
@@ -418,7 +418,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
       throw new DatabaseSchemaObjectExistsException(t("Cannot add index %name to table %table: index already exists.", array('%table' => $table, '%name' => $name)));
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} ADD INDEX `' . $name . '` (' . $this->createKeySql($fields) . ')');
+    $this->connection->query('ALTER TABLE {' . $table . '} ADD INDEX `' . $name . '` (' . $this->createKeySql($fields) . ')', array(), array('relax_checks' => TRUE));
   }
 
   public function dropIndex($table, $name) {
@@ -426,7 +426,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
       return FALSE;
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} DROP INDEX `' . $name . '`');
+    $this->connection->query('ALTER TABLE {' . $table . '} DROP INDEX `' . $name . '`', array(), array('relax_checks' => TRUE));
     return TRUE;
   }
 
@@ -442,7 +442,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
     if (count($keys_new)) {
       $sql .= ', ADD ' . implode(', ADD ', $this->createKeysSql($keys_new));
     }
-    $this->connection->query($sql);
+    $this->connection->query($sql, array(), array('relax_checks' => TRUE));
   }
 
   public function prepareComment($comment, $length = NULL) {
@@ -467,11 +467,11 @@ class DatabaseSchema_mysql extends DatabaseSchema {
       $condition->condition('column_name', $column);
       $condition->compile($this->connection, $this);
       // Don't use {} around information_schema.columns table.
-      return $this->connection->query("SELECT column_comment FROM information_schema.columns WHERE " . (string) $condition, $condition->arguments())->fetchField();
+      return $this->connection->query("SELECT column_comment FROM information_schema.columns WHERE " . (string) $condition, $condition->arguments(), array('relax_checks' => TRUE))->fetchField();
     }
     $condition->compile($this->connection, $this);
     // Don't use {} around information_schema.tables table.
-    $comment = $this->connection->query("SELECT table_comment FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments())->fetchField();
+    $comment = $this->connection->query("SELECT table_comment FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments(), array('relax_checks' => TRUE))->fetchField();
     // Work-around for MySQL 5.0 bug http://bugs.mysql.com/bug.php?id=11379
     return preg_replace('/; InnoDB free:.*$/', '', $comment);
   }
diff --git includes/database/pgsql/database.inc includes/database/pgsql/database.inc
index a4a2cc7..f97ef9a 100644
--- includes/database/pgsql/database.inc
+++ includes/database/pgsql/database.inc
@@ -111,6 +111,7 @@ class DatabaseConnection_pgsql extends DatabaseConnection {
 
   public function queryTemporary($query, array $args = array(), array $options = array()) {
     $tablename = $this->generateTemporaryTableName();
+    $options['relax_checks'] = TRUE;
     $this->query(preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE {' . $tablename . '} AS SELECT', $query), $args, $options);
     return $tablename;
   }
@@ -149,7 +150,7 @@ class DatabaseConnection_pgsql extends DatabaseConnection {
 
     // When PostgreSQL gets a value too small then it will lock the table,
     // retry the INSERT and if it's still too small then alter the sequence.
-    $id = $this->query("SELECT nextval('" . $sequence_name . "')")->fetchField();
+    $id = $this->query("SELECT nextval(:sequence)", array(':sequence' => $sequence_name))->fetchField();
     if ($id > $existing) {
       return $id;
     }
@@ -168,10 +169,10 @@ class DatabaseConnection_pgsql extends DatabaseConnection {
     }
 
     // Reset the sequence to a higher value than the existing id.
-    $this->query("ALTER SEQUENCE " . $sequence_name . " RESTART WITH " . ($existing + 1));
+    $this->query("ALTER SEQUENCE " . $sequence_name . " RESTART WITH " . ($existing + 1), array(), array('relax_checks' => TRUE));
 
     // Retrive the next id. We know this will be as high as we want it.
-    $id = $this->query("SELECT nextval('" . $sequence_name . "')")->fetchField();
+    $id = $this->query("SELECT nextval(:sequence)", array(':sequence' => $sequence_name))->fetchField();
 
     $this->query("SELECT pg_advisory_unlock(" . POSTGRESQL_NEXTID_LOCK . ")");
 
diff --git includes/database/pgsql/install.inc includes/database/pgsql/install.inc
index f3b47b7..dcf6771 100644
--- includes/database/pgsql/install.inc
+++ includes/database/pgsql/install.inc
@@ -63,32 +63,27 @@ class DatabaseTasks_pgsql extends DatabaseTasks {
       // Create functions.
       db_query('CREATE OR REPLACE FUNCTION "greatest"(numeric, numeric) RETURNS numeric AS
         \'SELECT CASE WHEN (($1 > $2) OR ($2 IS NULL)) THEN $1 ELSE $2 END;\'
-        LANGUAGE \'sql\''
-      );
+        LANGUAGE \'sql\'', array(), array('relax_checks' => TRUE));
       db_query('CREATE OR REPLACE FUNCTION "greatest"(numeric, numeric, numeric) RETURNS numeric AS
         \'SELECT greatest($1, greatest($2, $3));\'
-        LANGUAGE \'sql\''
-      );
+        LANGUAGE \'sql\'', array(), array('relax_checks' => TRUE));
       // Don't use {} around pg_proc table.
-      if (!db_query("SELECT COUNT(*) FROM pg_proc WHERE proname = 'rand'")->fetchField()) {
+      if (!db_query("SELECT COUNT(*) FROM pg_proc WHERE proname = 'rand'", array(), array('relax_checks' => TRUE))->fetchField()) {
         db_query('CREATE OR REPLACE FUNCTION "rand"() RETURNS float AS
           \'SELECT random();\'
-          LANGUAGE \'sql\''
-        );
+          LANGUAGE \'sql\'',  array(), array('relax_checks' => TRUE));
       }
 
       // Don't use {} around pg_proc table.
-      if (!db_query("SELECT COUNT(*) FROM pg_proc WHERE proname = 'concat'")->fetchField()) {
+      if (!db_query("SELECT COUNT(*) FROM pg_proc WHERE proname = 'concat'", array(), array('relax_checks' => TRUE))->fetchField()) {
         db_query('CREATE OR REPLACE FUNCTION "concat"(text, text) RETURNS text AS
           \'SELECT $1 || $2;\'
-          LANGUAGE \'sql\''
-        );
+          LANGUAGE \'sql\'', array(), array('relax_checks' => TRUE));
       }
 
       db_query('CREATE OR REPLACE FUNCTION "substring_index"(text, text, integer) RETURNS text AS
         \'SELECT array_to_string((string_to_array($1, $2)) [1:$3], $2);\'
-        LANGUAGE \'sql\''
-      );
+        LANGUAGE \'sql\'',  array(), array('relax_checks' => TRUE));
       $this->pass(st('PostgreSQL has initialized itself.'));
     }
     catch (Exception $e) {
diff --git includes/database/pgsql/schema.inc includes/database/pgsql/schema.inc
index 44dccdc..553099e 100644
--- includes/database/pgsql/schema.inc
+++ includes/database/pgsql/schema.inc
@@ -56,7 +56,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
         ':schema' => $schema,
         ':table' => $table_name,
         ':default' => '%nextval%',
-      ));
+      ), array('relax_checks' => TRUE));
       foreach ($result as $column) {
         if ($column->data_type == 'bytea') {
           $table_information->blob_fields[$column->column_name] = TRUE;
@@ -292,14 +292,14 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
     foreach ($indexes as $index) {
       if (preg_match('/^' . preg_quote($old_full_name) . '_(.*)_idx$/', $index->indexname, $matches)) {
         $index_name = $matches[1];
-        $this->connection->query('ALTER INDEX ' . $index->indexname . ' RENAME TO {' . $new_name . '}_' . $index_name . '_idx');
+        $this->connection->query('ALTER INDEX ' . $index->indexname . ' RENAME TO {' . $new_name . '}_' . $index_name . '_idx', array(), array('relax_checks' => TRUE));
       }
     }
 
     // Now rename the table.
     // Ensure the new table name does not include schema syntax.
     $prefixInfo = $this->getPrefixInfo($new_name);
-    $this->connection->query('ALTER TABLE {' . $table . '} RENAME TO ' . $prefixInfo['table']);
+    $this->connection->query('ALTER TABLE {' . $table . '} RENAME TO ' . $prefixInfo['table'], array(), array('relax_checks' => TRUE));
   }
 
   public function dropTable($table) {
@@ -307,7 +307,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
       return FALSE;
     }
 
-    $this->connection->query('DROP TABLE {' . $table . '}');
+    $this->connection->query('DROP TABLE {' . $table . '}', array(), array('relax_checks' => TRUE));
     return TRUE;
   }
 
@@ -340,7 +340,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
     }
     // Add column comment.
     if (!empty($spec['description'])) {
-      $this->connection->query('COMMENT ON COLUMN {' . $table . '}.' . $field . ' IS ' . $this->prepareComment($spec['description']));
+      $this->connection->query('COMMENT ON COLUMN {' . $table . '}.' . $field . ' IS ' . $this->prepareComment($spec['description']), array(), array('relax_checks' => TRUE));
     }
   }
 
@@ -349,7 +349,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
       return FALSE;
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} DROP COLUMN "' . $field . '"');
+    $this->connection->query('ALTER TABLE {' . $table . '} DROP COLUMN "' . $field . '"', array(), array('relax_checks' => TRUE));
     return TRUE;
   }
 
@@ -365,7 +365,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
       $default = is_string($default) ? "'$default'" : $default;
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN "' . $field . '" SET DEFAULT ' . $default);
+    $this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN "' . $field . '" SET DEFAULT ' . $default, array(), array('relax_checks' => TRUE));
   }
 
   public function fieldSetNoDefault($table, $field) {
@@ -373,7 +373,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
       throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot remove default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN "' . $field . '" DROP DEFAULT');
+    $this->connection->query('ALTER TABLE {' . $table . '} ALTER COLUMN "' . $field . '" DROP DEFAULT', array(), array('relax_checks' => TRUE));
   }
 
   public function indexExists($table, $name) {
@@ -403,7 +403,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
       throw new DatabaseSchemaObjectExistsException(t("Cannot add primary key to table %table: primary key already exists.", array('%table' => $table)));
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} ADD PRIMARY KEY (' . implode(',', $fields) . ')');
+    $this->connection->query('ALTER TABLE {' . $table . '} ADD PRIMARY KEY (' . implode(',', $fields) . ')', array(), array('relax_checks' => TRUE));
   }
 
   public function dropPrimaryKey($table) {
@@ -411,7 +411,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
       return FALSE;
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} DROP CONSTRAINT ' . $this->prefixNonTable($table, 'pkey'));
+    $this->connection->query('ALTER TABLE {' . $table . '} DROP CONSTRAINT ' . $this->prefixNonTable($table, 'pkey'), array(), array('relax_checks' => TRUE));
     return TRUE;
   }
 
@@ -423,7 +423,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
       throw new DatabaseSchemaObjectExistsException(t("Cannot add unique key %name to table %table: unique key already exists.", array('%table' => $table, '%name' => $name)));
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} ADD CONSTRAINT "' . $this->prefixNonTable($table, $name, 'key') . '" UNIQUE (' . implode(',', $fields) . ')');
+    $this->connection->query('ALTER TABLE {' . $table . '} ADD CONSTRAINT "' . $this->prefixNonTable($table, $name, 'key') . '" UNIQUE (' . implode(',', $fields) . ')', array(), array('relax_checks' => TRUE));
   }
 
   public function dropUniqueKey($table, $name) {
@@ -431,7 +431,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
       return FALSE;
     }
 
-    $this->connection->query('ALTER TABLE {' . $table . '} DROP CONSTRAINT "' . $this->prefixNonTable($table, $name, 'key') . '"');
+    $this->connection->query('ALTER TABLE {' . $table . '} DROP CONSTRAINT "' . $this->prefixNonTable($table, $name, 'key') . '"', array(), array('relax_checks' => TRUE));
     return TRUE;
   }
 
@@ -451,7 +451,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
       return FALSE;
     }
 
-    $this->connection->query('DROP INDEX ' . $this->prefixNonTable($table, $name, 'idx'));
+    $this->connection->query('DROP INDEX ' . $this->prefixNonTable($table, $name, 'idx'), array(), array('relax_checks' => TRUE));
     return TRUE;
   }
 
@@ -485,7 +485,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
 
     // Rename the column if necessary.
     if ($field != $field_new) {
-      $this->connection->query('ALTER TABLE {' . $table . '} RENAME "' . $field . '" TO "' . $field_new . '_old"');
+      $this->connection->query('ALTER TABLE {' . $table . '} RENAME "' . $field . '" TO "' . $field_new . '_old"', array(), array('relax_checks' => TRUE));
     }
 
     if (isset($new_keys)) {
diff --git includes/database/query.inc includes/database/query.inc
index f8e5fdd..9576e25 100644
--- includes/database/query.inc
+++ includes/database/query.inc
@@ -369,6 +369,10 @@ class InsertQuery extends Query {
       $options['return'] = Database::RETURN_INSERT_ID;
     }
     $options += array('delay' => FALSE);
+
+    // This query builder will emit DML queries. Relax the checks.
+    $options['relax_checks'] = TRUE;
+
     parent::__construct($connection, $options);
     $this->table = $table;
   }
@@ -635,6 +639,10 @@ class MergeQuery extends Query {
 
   public function __construct($connection, $table, array $options = array()) {
     $options['return'] = Database::RETURN_AFFECTED;
+
+    // This query builder will emit DML queries. Relax the checks.
+    $options['relax_checks'] = TRUE;
+
     parent::__construct($connection, $options);
     $this->table = $table;
   }
@@ -899,6 +907,10 @@ class DeleteQuery extends Query implements QueryConditionInterface {
 
   public function __construct(DatabaseConnection $connection, $table, array $options = array()) {
     $options['return'] = Database::RETURN_AFFECTED;
+
+    // This query builder will emit DML queries. Relax the checks.
+    $options['relax_checks'] = TRUE;
+
     parent::__construct($connection, $options);
     $this->table = $table;
 
@@ -979,6 +991,10 @@ class TruncateQuery extends Query {
 
   public function __construct(DatabaseConnection $connection, $table, array $options = array()) {
     $options['return'] = Database::RETURN_AFFECTED;
+
+    // This query builder will emit DML queries. Relax the checks.
+    $options['relax_checks'] = TRUE;
+
     parent::__construct($connection, $options);
     $this->table = $table;
   }
@@ -1048,6 +1064,10 @@ class UpdateQuery extends Query implements QueryConditionInterface {
 
   public function __construct(DatabaseConnection $connection, $table, array $options = array()) {
     $options['return'] = Database::RETURN_AFFECTED;
+
+    // This query builder will emit DML queries. Relax the checks.
+    $options['relax_checks'] = TRUE;
+
     parent::__construct($connection, $options);
     $this->table = $table;
 
diff --git includes/database/schema.inc includes/database/schema.inc
index 8f3b806..07d6a7e 100644
--- includes/database/schema.inc
+++ includes/database/schema.inc
@@ -264,7 +264,7 @@ abstract class DatabaseSchema implements QueryPlaceholderInterface {
     // couldn't use db_select() here because it would prefix
     // information_schema.tables and the query would fail.
     // Don't use {} around information_schema.tables table.
-    return (bool) $this->connection->query("SELECT 1 FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments())->fetchField();
+    return (bool) $this->connection->query("SELECT 1 FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments(), array('relax_checks' => TRUE))->fetchField();
   }
 
   /**
@@ -285,7 +285,7 @@ abstract class DatabaseSchema implements QueryPlaceholderInterface {
     // couldn't use db_select() here because it would prefix
     // information_schema.tables and the query would fail.
     // Don't use {} around information_schema.tables table.
-    return $this->connection->query("SELECT table_name FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments())->fetchAllKeyed(0, 0);
+    return $this->connection->query("SELECT table_name FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments(), array('relax_checks' => TRUE))->fetchAllKeyed(0, 0);
   }
 
   /**
@@ -308,7 +308,7 @@ abstract class DatabaseSchema implements QueryPlaceholderInterface {
     // couldn't use db_select() here because it would prefix
     // information_schema.tables and the query would fail.
     // Don't use {} around information_schema.columns table.
-    return (bool) $this->connection->query("SELECT 1 FROM information_schema.columns WHERE " . (string) $condition, $condition->arguments())->fetchField();
+    return (bool) $this->connection->query("SELECT 1 FROM information_schema.columns WHERE " . (string) $condition, $condition->arguments(), array('relax_checks' => TRUE))->fetchField();
   }
 
   /**
@@ -606,7 +606,7 @@ abstract class DatabaseSchema implements QueryPlaceholderInterface {
     }
     $statements = $this->createTableSql($name, $table);
     foreach ($statements as $statement) {
-      $this->connection->query($statement);
+      $this->connection->query($statement, array(), array('relax_checks' => TRUE));
     }
   }
 
diff --git includes/database/select.inc includes/database/select.inc
index 6e29541..b3c3ded 100644
--- includes/database/select.inc
+++ includes/database/select.inc
@@ -902,6 +902,10 @@ class SelectQuery extends Query implements SelectQueryInterface {
 
   public function __construct($table, $alias = NULL, DatabaseConnection $connection, $options = array()) {
     $options['return'] = Database::RETURN_STATEMENT;
+
+    // This query builder will emit complex queries. Relax the checks.
+    $options['relax_checks'] = TRUE;
+
     parent::__construct($connection, $options);
     $this->where = new DatabaseCondition('AND');
     $this->having = new DatabaseCondition('AND');
diff --git includes/database/sqlite/database.inc includes/database/sqlite/database.inc
index bc0b9c5..b4d3b8b 100644
--- includes/database/sqlite/database.inc
+++ includes/database/sqlite/database.inc
@@ -164,6 +164,7 @@ class DatabaseConnection_sqlite extends DatabaseConnection {
 
   public function queryTemporary($query, array $args = array(), array $options = array()) {
     $tablename = $this->generateTemporaryTableName();
+    $options['relax_checks'] = TRUE;
     $this->query(preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE {' . $tablename . '} AS SELECT', $query), $args, $options);
     return $tablename;
   }
@@ -197,13 +198,9 @@ class DatabaseConnection_sqlite extends DatabaseConnection {
     // and integers and no known databases require special handling for those
     // simple cases. If another transaction wants to write the same row, it will
     // wait until this transaction commits.
-    $stmt = $this->query('UPDATE {sequences} SET value = GREATEST(value, :existing_id) + 1', array(
-      ':existing_id' => $existing_id,
-    ));
+    $stmt = $this->query('UPDATE {sequences} SET value = GREATEST(value, :existing_id) + 1', array(':existing_id' => $existing_id), array('relax_checks' => TRUE));
     if (!$stmt->rowCount()) {
-      $this->query('INSERT INTO {sequences} (value) VALUES (:existing_id + 1)', array(
-        ':existing_id' => $existing_id,
-      ));
+      $this->query('INSERT INTO {sequences} (value) VALUES (:existing_id + 1)', array(':existing_id' => $existing_id), array('relax_checks' => TRUE));
     }
     // The transaction gets committed when the transaction object gets destroyed
     // because it gets out of scope.
diff --git includes/database/sqlite/schema.inc includes/database/sqlite/schema.inc
index 432ebd1..c7c9eb4 100644
--- includes/database/sqlite/schema.inc
+++ includes/database/sqlite/schema.inc
@@ -21,7 +21,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
 
   public function tableExists($table) {
     // Don't use {} around sqlite_master table.
-    return (bool) $this->connection->query("SELECT name FROM sqlite_master WHERE type = 'table' AND name LIKE '{" . $table . "}'", array(), array())->fetchField();
+    return (bool) $this->connection->query("SELECT name FROM sqlite_master WHERE type = 'table' AND name LIKE '{" . $table . "}'", array(), array('relax_checks' => TRUE))->fetchField();
   }
 
   public function fieldExists($table, $column) {
@@ -244,7 +244,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
     // the table with curly braces incase the db_prefix contains a reference
     // to a database outside of our existsing database.
     $info = $this->getPrefixInfo($new_name);
-    $this->connection->query('ALTER TABLE {' . $table . '} RENAME TO ' . $info['table']);
+    $this->connection->query('ALTER TABLE {' . $table . '} RENAME TO ' . $info['table'], array(), array('relax_checks' => TRUE));
 
     // Drop the indexes, there is no RENAME INDEX command in SQLite.
     if (!empty($schema['unique keys'])) {
@@ -270,7 +270,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
       return FALSE;
     }
 
-    $this->connection->query('DROP TABLE {' . $table . '}');
+    $this->connection->query('DROP TABLE {' . $table . '}', array(), array('relax_checks' => TRUE));
     return TRUE;
   }
 
@@ -285,7 +285,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
     // TODO: $keys_new is not supported yet.
     $query = 'ALTER TABLE {' . $table . '} ADD ';
     $query .= $this->createFieldSql($field, $this->processField($spec));
-    $this->connection->query($query);
+    $this->connection->query($query, array(), array('relax_checks' => TRUE));
   }
 
   /**
@@ -311,8 +311,8 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
     $this->connection->insert($new_table)
       ->from($select)
       ->execute();
-    $old_count = $this->connection->query('SELECT COUNT(*) FROM {' . $table . '}')->fetchField();
-    $new_count = $this->connection->query('SELECT COUNT(*) FROM {' . $new_table . '}')->fetchField();
+    $old_count = $this->connection->query('SELECT COUNT(*) FROM {' . $table . '}', array())->fetchField();
+    $new_count = $this->connection->query('SELECT COUNT(*) FROM {' . $new_table . '}', array())->fetchField();
     if ($old_count == $new_count) {
       do {
         $temp_table = $table . '_' . $i++;
@@ -339,7 +339,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
   protected function introspectSchema($table) {
     $mapped_fields = array_flip($this->getFieldTypeMap());
     $schema = array();
-    $result = $this->connection->query("PRAGMA table_info('{" . $table . "}')");
+    $result = $this->connection->query("PRAGMA table_info('{" . $table . "}')", array(), array('relax_checks' => TRUE));
     foreach ($result as $row) {
       if (preg_match('/^([^(]+)\((.*)\)$/', $row->type, $matches)) {
         $type = $matches[1];
@@ -369,7 +369,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
       }
     }
     $indexes = array();
-    $result = $this->connection->query("PRAGMA index_list('{" . $table . "}')");
+    $result = $this->connection->query("PRAGMA index_list('{" . $table . "}')", array(), array('relax_checks' => TRUE));
     foreach ($result as $row) {
       if (strpos($row->name, 'sqlite_autoindex_') !== 0) {
         $indexes[] = array(
@@ -384,7 +384,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
       $name = $index['name'];
       // Get index name without prefix.
       $index_name = substr($name, $n);
-      $result = $this->connection->query("PRAGMA index_info('$name')");
+      $result = $this->connection->query("PRAGMA index_info('$name')", array(), array('relax_checks' => TRUE));
       foreach ($result as $row) {
         $schema[$index['schema_key']][$index_name][] = $row->name;
       }
@@ -453,7 +453,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
   }
 
   public function indexExists($table, $name) {
-    return $this->connection->query('PRAGMA index_info({' . $table . '}_' . $name . ')')->fetchField() != '';
+    return $this->connection->query('PRAGMA index_info({' . $table . '}_' . $name . ')', array(), array('relax_checks' => TRUE))->fetchField() != '';
   }
 
   public function dropIndex($table, $name) {
@@ -461,7 +461,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
       return FALSE;
     }
 
-    $this->connection->query('DROP INDEX ' . $this->prefixNonTable($table, $name));
+    $this->connection->query('DROP INDEX ' . $this->prefixNonTable($table, $name), array(), array('relax_checks' => TRUE));
     return TRUE;
   }
 
@@ -485,7 +485,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
       return FALSE;
     }
 
-    $this->connection->query('DROP INDEX ' . $this->prefixNonTable($table, $name));
+    $this->connection->query('DROP INDEX ' . $this->prefixNonTable($table, $name), array(), array('relax_checks' => TRUE));
     return TRUE;
   }
 
diff --git includes/install.inc includes/install.inc
index 9095e8e..3184fef 100644
--- includes/install.inc
+++ includes/install.inc
@@ -395,7 +395,7 @@ abstract class DatabaseTasks {
    */
   protected function runTestQuery($query, $pass, $fail, $fatal = FALSE) {
     try {
-      db_query($query);
+      db_query($query, array(), array('relax_checks' => TRUE));
       $this->pass(st($pass));
     }
     catch (Exception $e) {
diff --git includes/locale.inc includes/locale.inc
index da747e7..022ac1f 100644
--- includes/locale.inc
+++ includes/locale.inc
@@ -1194,7 +1194,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)));
 
-      $source = db_query("SELECT lid, location FROM {locales_source} WHERE source = :source AND textgroup = 'default'", array(':source' => $string))->fetchObject();
+      $source = db_query("SELECT lid, location FROM {locales_source} WHERE source = :source AND textgroup = :textgroup", array(':source' => $string, ':textgroup' => 'default'))->fetchObject();
       if ($source) {
         // 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.
@@ -1638,7 +1638,7 @@ function _locale_rebuild_js($langcode = NULL) {
 
   // Construct the array for JavaScript translations.
   // Only add strings with a translation to the translations array.
-  $result = db_query("SELECT s.lid, s.source, t.translation FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.location LIKE '%.js%' AND s.textgroup = :textgroup AND t.translation IS NOT NULL", array(':language' => $language->language, ':textgroup' => 'default'));
+  $result = db_query("SELECT s.lid, s.source, t.translation FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.location LIKE :location AND s.textgroup = :textgroup AND t.translation IS NOT NULL", array(':language' => $language->language, ':location' => '%.js%', ':textgroup' => 'default'));
 
   $translations = array();
   foreach ($result as $data) {
diff --git includes/menu.inc includes/menu.inc
index 3a15631..39fbac1 100644
--- includes/menu.inc
+++ includes/menu.inc
@@ -3146,7 +3146,7 @@ function _menu_router_build($callbacks) {
           // previous iteration assigned one already), try to find the menu name
           // of the parent item in the currently stored menu links.
           if (!isset($parent['menu_name'])) {
-            $menu_name = db_query("SELECT menu_name FROM {menu_links} WHERE router_path = :router_path AND module = 'system'", array(':router_path' => $parent_path))->fetchField();
+            $menu_name = db_query("SELECT menu_name FROM {menu_links} WHERE router_path = :router_path AND module = :module", array(':router_path' => $parent_path, ':module' => 'system'))->fetchField();
             if ($menu_name) {
               $parent['menu_name'] = $menu_name;
             }
diff --git includes/module.inc includes/module.inc
index 380d4c8..c54b89f 100644
--- includes/module.inc
+++ includes/module.inc
@@ -112,7 +112,7 @@ function system_list($type) {
       $bootstrap_list = $cached->data;
     }
     else {
-      $bootstrap_list = db_query("SELECT name, filename FROM {system} WHERE status = 1 AND bootstrap = 1 AND type = 'module' ORDER BY weight ASC, name ASC")->fetchAllAssoc('name');
+      $bootstrap_list = db_query("SELECT name, filename FROM {system} WHERE status = 1 AND bootstrap = 1 AND type = :type ORDER BY weight ASC, name ASC", array(':type' => 'module'))->fetchAllAssoc('name');
       cache_set('bootstrap_modules', $bootstrap_list, 'cache_bootstrap');
     }
     // To avoid a separate database lookup for the filepath, prime the
diff --git includes/path.inc includes/path.inc
index 98a5962..598fe32 100644
--- includes/path.inc
+++ includes/path.inc
@@ -336,7 +336,7 @@ function drupal_path_alias_whitelist_rebuild($source = NULL) {
   // path it corresponds to. This is the portion of the path before the first
   // '/', if present, otherwise the whole path itself.
   $whitelist = array();
-  $result = db_query("SELECT SUBSTRING_INDEX(source, '/', 1) AS path FROM {url_alias} GROUP BY path");
+  $result = db_query("SELECT SUBSTRING_INDEX(source, :separator, 1) AS path FROM {url_alias} GROUP BY path", array(':separator' => '/'));
   foreach ($result as $row) {
     $whitelist[$row->path] = TRUE;
   }
diff --git includes/registry.inc includes/registry.inc
index 2d2ded4..c218dfe 100644
--- includes/registry.inc
+++ includes/registry.inc
@@ -35,7 +35,7 @@ function _registry_update() {
   require_once DRUPAL_ROOT . '/includes/database/' . $driver . '/query.inc';
 
   // Get current list of modules and their files.
-  $modules = db_query("SELECT * FROM {system} WHERE type = 'module'")->fetchAll();
+  $modules = db_query("SELECT * FROM {system} WHERE type = :type", array(':type' => 'module'))->fetchAll();
   // Get the list of files we are going to parse.
   $files = array();
   foreach ($modules as &$module) {
diff --git includes/update.inc includes/update.inc
index 74d439c..8740acf 100644
--- includes/update.inc
+++ includes/update.inc
@@ -14,7 +14,7 @@
  */
 function update_fix_compatibility() {
   $incompatible = array();
-  $result = db_query("SELECT name, type, status FROM {system} WHERE status = 1 AND type IN ('module','theme')");
+  $result = db_query("SELECT name, type, status FROM {system} WHERE status = 1 AND type IN (:types)", array(':types' => array('module','theme')));
   foreach ($result as $row) {
     if (update_check_incompatibility($row->name, $row->type)) {
       $incompatible[] = $row->name;
@@ -1188,7 +1188,7 @@ function update_retrieve_dependencies() {
   $return = array();
   // Get a list of installed modules, arranged so that we invoke their hooks in
   // the same order that module_invoke_all() does.
-  $modules = db_query("SELECT name FROM {system} WHERE type = 'module' AND schema_version != :schema ORDER BY weight ASC, name ASC", array(':schema' => SCHEMA_UNINSTALLED))->fetchCol();
+  $modules = db_query("SELECT name FROM {system} WHERE type = :type AND schema_version != :schema ORDER BY weight ASC, name ASC", array(':schema' => SCHEMA_UNINSTALLED, ':type' => 'module'))->fetchCol();
   foreach ($modules as $module) {
     $function = $module . '_update_dependencies';
     if (function_exists($function)) {
diff --git modules/block/block.install modules/block/block.install
index fafc39e..aa4acd2 100644
--- modules/block/block.install
+++ modules/block/block.install
@@ -235,7 +235,7 @@ function block_update_7003() {
 function block_update_7004() {
   // Collect a list of themes with blocks.
   $themes_with_blocks = array();
-  $result = db_query("SELECT s.name FROM {system} s INNER JOIN {block} b ON s.name = b.theme WHERE s.type = 'theme' GROUP by s.name");
+  $result = db_query("SELECT s.name FROM {system} s INNER JOIN {block} b ON s.name = b.theme WHERE s.type = :type GROUP by s.name", array(':type' => 'theme'));
 
   $insert = db_insert('block')->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'pages', 'cache'));
   foreach ($result as $theme) {
diff --git modules/block/block.test modules/block/block.test
index 595e6aa..3710e02 100644
--- modules/block/block.test
+++ modules/block/block.test
@@ -304,12 +304,12 @@ class NewDefaultThemeBlocks extends DrupalWebTestCase {
     $this->drupalLogin($admin_user);
 
     // Ensure no other theme's blocks are in the block table yet.
-    $count = db_query_range("SELECT 1 FROM {block} WHERE theme NOT IN ('garland', 'seven')", 0, 1)->fetchField();
+    $count = db_query_range("SELECT 1 FROM {block} WHERE theme NOT IN (:themes)", 0, 1, array(':themes' => array('garland', 'seven')))->fetchField();
     $this->assertFalse($count, t('Only Garland and Seven have blocks.'));
 
     // Populate list of all blocks for matching against new theme.
     $blocks = array();
-    $result = db_query("SELECT * FROM {block} WHERE theme = 'garland'");
+    $result = db_query("SELECT * FROM {block} WHERE theme = :theme", array(':theme' => 'garland'));
     foreach ($result as $block) {
       // $block->theme and $block->bid will not match, so remove them.
       unset($block->theme, $block->bid);
@@ -320,7 +320,7 @@ class NewDefaultThemeBlocks extends DrupalWebTestCase {
     // that Garland did.
     theme_enable(array('stark'));
     variable_set('theme_default', 'stark');
-    $result = db_query("SELECT * FROM {block} WHERE theme='stark'");
+    $result = db_query("SELECT * FROM {block} WHERE theme = :theme", array(':theme' => 'stark'));
     foreach ($result as $block) {
       unset($block->theme, $block->bid);
       $this->assertEqual($blocks[$block->module][$block->delta], $block, t('Block %name matched', array('%name' => $block->module . '-' . $block->delta)));
@@ -543,7 +543,7 @@ class BlockCacheTestCase extends DrupalWebTestCase {
       ->condition('module', 'block_test')
       ->execute();
 
-    $current_mode = db_query("SELECT cache FROM {block} WHERE module = 'block_test'")->fetchField();
+    $current_mode = db_query("SELECT cache FROM {block} WHERE module = :module", array(':module' => 'block_test'))->fetchField();
     if ($current_mode != $cache_mode) {
       $this->fail(t('Unable to set cache mode to %mode. Current mode: %current_mode', array('%mode' => $cache_mode, '%current_mode' => $current_mode)));
     }
diff --git modules/book/book.install modules/book/book.install
index 3f0a14e..238b787 100644
--- modules/book/book.install
+++ modules/book/book.install
@@ -19,7 +19,9 @@ function book_install() {
  */
 function book_uninstall() {
   // Delete menu links.
-  db_query("DELETE FROM {menu_links} WHERE module = 'book'");
+  db_delete('menu_links')
+    ->condition('module', 'book')
+    ->execute();
   menu_cache_clear_all();
 }
 
diff --git modules/comment/comment.install modules/comment/comment.install
index 29449e1..7a6194b 100644
--- modules/comment/comment.install
+++ modules/comment/comment.install
@@ -195,8 +195,9 @@ function comment_update_7007() {
   ));
 
   // Migrate the data.
-  // @todo db_update() should support this.
-  db_query('UPDATE {comment} SET created = changed');
+  db_update('comment')
+    ->expression('created', 'changed')
+    ->execute();
 
   // Recreate the indexes.
   // The 'comment_num_new' index is optimized for comment_num_new()
diff --git modules/field/modules/field_sql_storage/field_sql_storage.test modules/field/modules/field_sql_storage/field_sql_storage.test
index 552b958..a7eeb12 100644
--- modules/field/modules/field_sql_storage/field_sql_storage.test
+++ modules/field/modules/field_sql_storage/field_sql_storage.test
@@ -44,8 +44,8 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
     $this->assertEqual($t1+1, $t2, 'Entity type ids are sequential');
     $this->assertIdentical(variable_get('field_sql_storage_t1_etid', NULL), $t1, 'First entity type variable is correct');
     $this->assertIdentical(variable_get('field_sql_storage_t2_etid', NULL), $t2, 'Second entity type variable is correct');
-    $this->assertEqual(db_query("SELECT etid FROM {field_config_entity_type} WHERE type='t1'")->fetchField(), $t1, 'First entity type in database is correct');
-    $this->assertEqual(db_query("SELECT etid FROM {field_config_entity_type} WHERE type='t2'")->fetchField(), $t2, 'Second entity type in database is correct');
+    $this->assertEqual(db_query("SELECT etid FROM {field_config_entity_type} WHERE type = :type", array(':type' => 't1'))->fetchField(), $t1, 'First entity type in database is correct');
+    $this->assertEqual(db_query("SELECT etid FROM {field_config_entity_type} WHERE type = :type", array(':type' => 't2'))->fetchField(), $t2, 'Second entity type in database is correct');
     $this->assertEqual($t1, _field_sql_storage_etid('t1'), '_field_sql_storage_etid returns the same value for the first entity type');
     $this->assertEqual($t2, _field_sql_storage_etid('t2'), '_field_sql_storage_etid returns the same value for the second entity type');
   }
diff --git modules/forum/forum.install modules/forum/forum.install
index 79b062a..98467c4 100644
--- modules/forum/forum.install
+++ modules/forum/forum.install
@@ -291,5 +291,16 @@ function forum_update_7001() {
   );
   db_create_table('forum_index', $forum_index);
 
-  db_query('INSERT INTO {forum_index} (SELECT n.nid, n.title, f.tid, n.sticky, n.created, ncs.last_comment_timestamp, ncs.comment_count FROM {node} n INNER JOIN {forum} f on n.vid = f.vid INNER JOIN {node_comment_statistics} ncs ON n.nid = ncs.nid)');
+  // Migrate over the data from the {node_comment_statistics} table.
+  $source_data = db_select('node', 'n');
+  $source_data->innerJoin('forum', 'f', 'n.vid = f.vid');
+  $source_data->innerJoin('node_comment_statistics', 'ncs', 'n.nid = ncs.nid');
+  $source_data
+    ->fields('n', array('nid', 'title', 'created'))
+    ->fields('f', array('tid'))
+    ->fields('ncs', array('last_comment_timestamp', 'comment_count'));
+
+  db_insert('forum_index')
+    ->from($source_data)
+    ->execute();
 }
diff --git modules/forum/forum.test modules/forum/forum.test
index 7860937..f9eb5bc 100644
--- modules/forum/forum.test
+++ modules/forum/forum.test
@@ -141,7 +141,11 @@ class ForumTestCase extends DrupalWebTestCase {
     $this->assertText(t('The block settings have been updated.'), t('[New forum topics] Forum block was enabled'));
 
     // Retrieve forum menu id.
-    $mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = 'forum' AND menu_name = 'navigation' AND module = 'system' ORDER BY mlid ASC", 0, 1)->fetchField();
+    $mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :link_path AND menu_name = :menu_name AND module = :module ORDER BY mlid ASC", 0, 1, array(
+      ':link_path' => 'forum',
+      ':menu_name' => 'navigation',
+      ':module' => 'system',
+    ))->fetchField();
 
     // Add forum to navigation menu.
     $edit = array();
diff --git modules/help/help.test modules/help/help.test
index fc80ca5..cb2ce8d 100644
--- modules/help/help.test
+++ modules/help/help.test
@@ -79,7 +79,7 @@ class HelpTestCase extends DrupalWebTestCase {
    */
   protected function getModuleList() {
     $this->modules = array();
-    $result = db_query("SELECT name, filename, info FROM {system} WHERE type = 'module' AND status = 1 ORDER BY weight ASC, filename ASC");
+    $result = db_query("SELECT name, filename, info FROM {system} WHERE type = :type AND status = 1 ORDER BY weight ASC, filename ASC", array(':type' => 'module'));
     foreach ($result as $module) {
       if (file_exists($module->filename) && function_exists($module->name . '_help')) {
         $fullname = unserialize($module->info);
diff --git modules/locale/locale.module modules/locale/locale.module
index e396cef..d505eef 100644
--- modules/locale/locale.module
+++ modules/locale/locale.module
@@ -650,7 +650,7 @@ function locale($string = NULL, $context = NULL, $langcode = NULL) {
         // Refresh database stored cache of translations for given language.
         // We only store short strings used in current version, to improve
         // performance and consume less memory.
-        $result = db_query("SELECT s.source, s.context, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.textgroup = 'default' AND s.version = :version AND LENGTH(s.source) < 75", array(':language' => $langcode, ':version' => VERSION));
+        $result = db_query("SELECT s.source, s.context, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.textgroup = :textgroup AND s.version = :version AND LENGTH(s.source) < 75", array(':language' => $langcode, ':textgroup' => 'default', ':version' => VERSION));
         foreach ($result as $data) {
           $locale_t[$langcode][$data->context][$data->source] = (empty($data->translation) ? TRUE : $data->translation);
         }
@@ -664,10 +664,11 @@ function locale($string = NULL, $context = NULL, $langcode = NULL) {
   if (!isset($locale_t[$langcode][$context][$string])) {
 
     // We do not have this translation cached, so get it from the DB.
-    $translation = db_query("SELECT s.lid, t.translation, s.version FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.source = :source AND s.context = :context AND s.textgroup = 'default'", array(
+    $translation = db_query("SELECT s.lid, t.translation, s.version FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.source = :source AND s.context = :context AND s.textgroup = :textgroup", array(
       ':language' => $langcode,
       ':source' => $string,
       ':context' => (string) $context,
+      ':textgroup' => 'default',
     ))->fetchObject();
     if ($translation) {
       // We have the source string at least.
diff --git modules/locale/locale.test modules/locale/locale.test
index 6fa5c23..8349d7b 100644
--- modules/locale/locale.test
+++ modules/locale/locale.test
@@ -614,7 +614,7 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
     $this->assertRaw(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => 7, '%update' => 0, '%delete' => 0)), t('The translation file was successfully imported.'));
 
     // This import should have saved plural forms to have 2 variants.
-    $this->assert(db_query("SELECT plurals FROM {languages} WHERE language = 'fr'")->fetchField() == 2, t('Plural number initialized.'));
+    $this->assert(db_query("SELECT plurals FROM {languages} WHERE language = :language", array(':language' => 'fr'))->fetchField() == 2, t('Plural number initialized.'));
 
     // Ensure we were redirected correctly.
     $this->assertEqual($this->getUrl(), url('admin/config/regional/translate', array('absolute' => TRUE)), t('Correct page redirection.'));
@@ -672,7 +672,7 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
     $this->assertText(t('No strings available.'), t('String not overwritten by imported string.'));
 
     // This import should not have changed number of plural forms.
-    $this->assert(db_query("SELECT plurals FROM {languages} WHERE language = 'fr'")->fetchField() == 2, t('Plural numbers untouched.'));
+    $this->assert(db_query("SELECT plurals FROM {languages} WHERE language = :language", array(':language' => 'fr'))->fetchField() == 2, t('Plural numbers untouched.'));
 
     // Try importing a .po file with overriding strings, and ensure existing
     // strings are overwritten.
@@ -693,7 +693,7 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertNoText(t('No strings available.'), t('String overwritten by imported string.'));
     // This import should have changed number of plural forms.
-    $this->assert(db_query("SELECT plurals FROM {languages} WHERE language = 'fr'")->fetchField() == 3, t('Plural numbers changed.'));
+    $this->assert(db_query("SELECT plurals FROM {languages} WHERE language = :language", array(':language' => 'fr'))->fetchField() == 3, t('Plural numbers changed.'));
   }
 
   /**
diff --git modules/menu/menu.admin.inc modules/menu/menu.admin.inc
index 5e391ae..462f60f 100644
--- modules/menu/menu.admin.inc
+++ modules/menu/menu.admin.inc
@@ -536,7 +536,7 @@ function menu_delete_menu_confirm_submit($form, &$form_state) {
   }
 
   // Reset all the menu links defined by the system via hook_menu().
-  $result = db_query("SELECT * FROM {menu_links} ml INNER JOIN {menu_router} m ON ml.router_path = m.path WHERE ml.menu_name = :menu AND ml.module = 'system' ORDER BY m.number_parts ASC", array(':menu' => $menu['menu_name']), array('fetch' => PDO::FETCH_ASSOC));
+  $result = db_query("SELECT * FROM {menu_links} ml INNER JOIN {menu_router} m ON ml.router_path = m.path WHERE ml.menu_name = :menu AND ml.module = :module ORDER BY m.number_parts ASC", array(':menu' => $menu['menu_name'], ':module' => 'system'), array('fetch' => PDO::FETCH_ASSOC));
   foreach ($result as $link) {
     menu_reset_item($link);
   }
diff --git modules/menu/menu.module modules/menu/menu.module
index d72fbdd..7ef6c57 100644
--- modules/menu/menu.module
+++ modules/menu/menu.module
@@ -179,7 +179,7 @@ function menu_theme() {
  */
 function menu_enable() {
   menu_rebuild();
-  $base_link = db_query("SELECT mlid AS plid, menu_name FROM {menu_links} WHERE link_path = 'admin/structure/menu' AND module = 'system'")->fetchAssoc();
+  $base_link = db_query("SELECT mlid AS plid, menu_name FROM {menu_links} WHERE link_path = :link_path AND module = :module", array(':link_path' => 'admin/structure/menu', ':module' => 'system'))->fetchAssoc();
   $base_link['router_path'] = 'admin/structure/menu/manage/%';
   $base_link['module'] = 'menu';
   $result = db_query("SELECT * FROM {menu_custom}", array(), array('fetch' => PDO::FETCH_ASSOC));
@@ -524,7 +524,7 @@ function menu_node_save($node) {
  */
 function menu_node_delete($node) {
   // Delete all menu module links that point to this node.
-  $result = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :path AND module = 'menu'", array(':path' => 'node/' . $node->nid), array('fetch' => PDO::FETCH_ASSOC));
+  $result = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :path AND module = :module", array(':path' => 'node/' . $node->nid, ':module' => 'menu'), array('fetch' => PDO::FETCH_ASSOC));
   foreach ($result as $m) {
     menu_link_delete($m['mlid']);
   }
@@ -540,14 +540,16 @@ function menu_node_prepare($node) {
     $item = array();
     if (isset($node->nid)) {
       // Give priority to the default menu
-      $mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :path AND menu_name = :menu_name AND module = 'menu' ORDER BY mlid ASC", 0, 1, array(
+      $mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :path AND menu_name = :menu_name AND module = :module ORDER BY mlid ASC", 0, 1, array(
         ':path' => 'node/' . $node->nid,
         ':menu_name' => $menu_name,
+        ':module' => 'menu',
       ))->fetchField();
       // Check all menus if a link does not exist in the default menu.
       if (!$mlid) {
-        $mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :path AND module = 'menu' ORDER BY mlid ASC", 0, 1, array(
+        $mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :path AND module = :module ORDER BY mlid ASC", 0, 1, array(
           ':path' => 'node/' . $node->nid,
+          ':module' => 'menu',
         ))->fetchField();
       }
       if ($mlid) {
diff --git modules/menu/menu.test modules/menu/menu.test
index 36ba1ab..76a8eca 100644
--- modules/menu/menu.test
+++ modules/menu/menu.test
@@ -478,7 +478,7 @@ class MenuTestCase extends DrupalWebTestCase {
    */
   private function getStandardMenuLink() {
     // Retrieve menu link id of the Log out menu link, which will always be on the front page.
-    $mlid = db_query("SELECT mlid FROM {menu_links} WHERE module = 'system' AND router_path = 'user/logout'")->fetchField();
+    $mlid = db_query("SELECT mlid FROM {menu_links} WHERE module = :module AND router_path = :path", array(':module' => 'system', ':path' => 'user/logout'))->fetchField();
     $this->assertTrue($mlid > 0, 'Standard menu link id was found');
     // Load menu link.
     // Use api function so that link is translated for rendering.
diff --git modules/node/node.module modules/node/node.module
index 4fdff7f..7a26ec8 100644
--- modules/node/node.module
+++ modules/node/node.module
@@ -1501,7 +1501,7 @@ function node_search_reset() {
  */
 function node_search_status() {
   $total = db_query('SELECT COUNT(*) FROM {node}')->fetchField();
-  $remaining = db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE d.sid IS NULL OR d.reindex <> 0")->fetchField();
+  $remaining = db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = :type AND d.sid = n.nid WHERE d.sid IS NULL OR d.reindex <> 0", array(':type' => 'node'))->fetchField();
   return array('remaining' => $remaining, 'total' => $total);
 }
 
@@ -2517,7 +2517,7 @@ function node_page_view($node) {
 function node_update_index() {
   $limit = (int)variable_get('search_cron_limit', 100);
 
-  $result = db_query_range("SELECT n.nid FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE d.sid IS NULL OR d.reindex <> 0 ORDER BY d.reindex ASC, n.nid ASC", 0, $limit, array(), array('target' => 'slave'));
+  $result = db_query_range("SELECT n.nid FROM {node} n LEFT JOIN {search_dataset} d ON d.type = :type AND d.sid = n.nid WHERE d.sid IS NULL OR d.reindex <> 0 ORDER BY d.reindex ASC, n.nid ASC", 0, $limit, array(':type' => 'node'), array('target' => 'slave'));
 
   foreach ($result as $node) {
     _node_index_node($node);
diff --git modules/node/node.test modules/node/node.test
index 45728b9..cae31cb 100644
--- modules/node/node.test
+++ modules/node/node.test
@@ -485,12 +485,12 @@ class NodeCreationTestCase extends DrupalWebTestCase {
       $this->assertTrue($node, t('Transactions not supported, and node found in database.'));
 
       // Check that the failed rollback was logged.
-      $records = db_query("SELECT wid FROM {watchdog} WHERE message LIKE 'Explicit rollback failed%'")->fetchAll();
+      $records = db_query("SELECT wid FROM {watchdog} WHERE message LIKE :message", array(':message' => 'Explicit rollback failed%'))->fetchAll();
       $this->assertTrue(count($records) > 0, t('Transactions not supported, and rollback error logged to watchdog.'));
     }
 
     // Check that the rollback error was logged.
-    $records = db_query("SELECT wid FROM {watchdog} WHERE variables LIKE '%Test exception for rollback.%'")->fetchAll();
+    $records = db_query("SELECT wid FROM {watchdog} WHERE variables LIKE :message", array(':message' => '%Test exception for rollback.%'))->fetchAll();
     $this->assertTrue(count($records) > 0, t('Rollback explanatory error logged to watchdog.'));
   }
 }
@@ -1469,7 +1469,7 @@ class NodeBlockFunctionalTest extends DrupalWebTestCase {
 
     // Delete the created custom block & verify that it's been deleted.
     $this->drupalPost('admin/structure/block/manage/block/' . $bid . '/delete', array(), t('Delete'));
-    $bid = db_query("SELECT 1 FROM {block_node_type} WHERE module = 'block' AND delta = :delta", array(':delta' => $bid))->fetchField();
+    $bid = db_query("SELECT 1 FROM {block_node_type} WHERE module = :module AND delta = :delta", array(':module' => 'block', ':delta' => $bid))->fetchField();
     $this->assertFalse($bid, t('Custom block was deleted.'));
   }
 }
diff --git modules/openid/openid.pages.inc modules/openid/openid.pages.inc
index 06738a1..91f5fcc 100644
--- modules/openid/openid.pages.inc
+++ modules/openid/openid.pages.inc
@@ -48,7 +48,7 @@ function openid_user_identities($account) {
   $header = array(t('OpenID'), t('Operations'));
   $rows = array();
 
-  $result = db_query("SELECT * FROM {authmap} WHERE module='openid' AND uid=:uid", array(':uid' => $account->uid));
+  $result = db_query("SELECT * FROM {authmap} WHERE module = :module AND uid = :uid", array(':module' => 'openid', ':uid' => $account->uid));
   foreach ($result as $identity) {
     $rows[] = array(check_plain($identity->authname), l(t('Delete'), 'user/' . $account->uid . '/openid/delete/' . $identity->aid));
   }
@@ -95,9 +95,10 @@ function openid_user_add_submit($form, &$form_state) {
  * Menu callback; Delete the specified OpenID identity from the system.
  */
 function openid_user_delete_form($form, $form_state, $account, $aid = 0) {
-  $authname = db_query("SELECT authname FROM {authmap} WHERE uid = :uid AND aid = :aid AND module = 'openid'", array(
+  $authname = db_query("SELECT authname FROM {authmap} WHERE uid = :uid AND aid = :aid AND module = :module", array(
     ':uid' => $account->uid,
     ':aid' => $aid,
+    ':module' => 'openid',
   ))
   ->fetchField();
   return confirm_form(array(), t('Are you sure you want to delete the OpenID %authname for %user?', array('%authname' => $authname, '%user' => $account->name)), 'user/' . $account->uid . '/openid');
diff --git modules/search/search.api.php modules/search/search.api.php
index f366e64..ae0b253 100644
--- modules/search/search.api.php
+++ modules/search/search.api.php
@@ -82,7 +82,7 @@ function hook_search_reset() {
  */
 function hook_search_status() {
   $total = db_query('SELECT COUNT(*) FROM {node} WHERE status = 1')->fetchField();
-  $remaining = db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE n.status = 1 AND d.sid IS NULL OR d.reindex <> 0")->fetchField();
+  $remaining = db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = :type AND d.sid = n.nid WHERE n.status = 1 AND d.sid IS NULL OR d.reindex <> 0", array(':type' => 'node'))->fetchField();
   return array('remaining' => $remaining, 'total' => $total);
 }
 
@@ -294,7 +294,7 @@ function hook_search_preprocess($text) {
 function hook_update_index() {
   $limit = (int)variable_get('search_cron_limit', 100);
 
-  $result = db_query_range("SELECT n.nid FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE d.sid IS NULL OR d.reindex <> 0 ORDER BY d.reindex ASC, n.nid ASC", 0, $limit);
+  $result = db_query_range("SELECT n.nid FROM {node} n LEFT JOIN {search_dataset} d ON d.type = :type AND d.sid = n.nid WHERE d.sid IS NULL OR d.reindex <> 0 ORDER BY d.reindex ASC, n.nid ASC", 0, $limit, array(':type' => 'node'));
 
   foreach ($result as $node) {
     $node = node_load($node->nid);
diff --git modules/simpletest/drupal_web_test_case.php modules/simpletest/drupal_web_test_case.php
index 7f8e8eb..8457b8c 100644
--- modules/simpletest/drupal_web_test_case.php
+++ modules/simpletest/drupal_web_test_case.php
@@ -1230,8 +1230,8 @@ class DrupalWebTestCase extends DrupalTestCase {
    * setup a clean environment for the current test run.
    */
   protected function preloadRegistry() {
-    db_query('INSERT INTO {registry} SELECT * FROM ' . $this->originalPrefix . 'registry');
-    db_query('INSERT INTO {registry_file} SELECT * FROM ' . $this->originalPrefix . 'registry_file');
+    db_query('INSERT INTO {registry} SELECT * FROM ' . $this->originalPrefix . 'registry', array(), array('relax_checks' => TRUE));
+    db_query('INSERT INTO {registry_file} SELECT * FROM ' . $this->originalPrefix . 'registry_file', array(), array('relax_checks' => TRUE));
   }
 
   /**
diff --git modules/simpletest/tests/actions.test modules/simpletest/tests/actions.test
index 8e8f176..fdee36f 100644
--- modules/simpletest/tests/actions.test
+++ modules/simpletest/tests/actions.test
@@ -116,7 +116,7 @@ class ActionLoopTestCase extends DrupalWebTestCase {
     }
     $expected[] = 'Stack overflow: too many calls to actions_do(). Aborting to prevent infinite recursion.';
 
-    $result = db_query("SELECT message FROM {watchdog} WHERE type = 'actions_loop_test' OR type = 'actions' ORDER BY wid");
+    $result = db_query("SELECT message FROM {watchdog} WHERE type IN (:types) ORDER BY wid", array(':types' => array('actions', 'actions_loop_test')));
     $loop_started = FALSE;
     foreach ($result as $row) {
       $expected_message = array_shift($expected);
diff --git modules/simpletest/tests/database_test.test modules/simpletest/tests/database_test.test
index e97435b..e8b1813 100644
--- modules/simpletest/tests/database_test.test
+++ modules/simpletest/tests/database_test.test
@@ -984,7 +984,7 @@ class DatabaseDeleteTruncateTestCase extends DatabaseTestCase {
    */
   function testSubselectDelete() {
     $num_records_before = db_query('SELECT COUNT(*) FROM {test_task}')->fetchField();
-    $pid_to_delete = db_query("SELECT * FROM {test_task} WHERE task = 'sleep'")->fetchField();
+    $pid_to_delete = db_query("SELECT * FROM {test_task} WHERE task = :task", array(':task' => 'sleep'))->fetchField();
 
     $subquery = db_select('test', 't')
       ->fields('t', array('id'))
diff --git modules/simpletest/tests/menu.test modules/simpletest/tests/menu.test
index 0f29b0f..c09d1f0 100644
--- modules/simpletest/tests/menu.test
+++ modules/simpletest/tests/menu.test
@@ -225,8 +225,7 @@ class MenuRouterTestCase extends DrupalWebTestCase {
     $admin_user = $this->drupalCreateUser(array('administer site configuration'));
     $this->drupalLogin($admin_user);
 
-    $sql = "SELECT menu_name FROM {menu_links} WHERE router_path = 'menu_name_test'";
-    $name = db_query($sql)->fetchField();
+    $name = db_query('SELECT menu_name FROM {menu_links} WHERE router_path = :router_path', array(':router_path' => 'menu_name_test'))->fetchField();
     $this->assertEqual($name, 'original', t('Menu name is "original".'));
 
     // Change the menu_name parameter in menu_test.module, then force a menu
@@ -234,8 +233,7 @@ class MenuRouterTestCase extends DrupalWebTestCase {
     menu_test_menu_name('changed');
     menu_rebuild();
 
-    $sql = "SELECT menu_name FROM {menu_links} WHERE router_path = 'menu_name_test'";
-    $name = db_query($sql)->fetchField();
+    $name = db_query('SELECT menu_name FROM {menu_links} WHERE router_path = :router_path', array(':router_path' => 'menu_name_test'))->fetchField();
     $this->assertEqual($name, 'changed', t('Menu name was successfully changed after rebuild.'));
   }
 
diff --git modules/simpletest/tests/path.test modules/simpletest/tests/path.test
index 5fb8ced..e80c669 100644
--- modules/simpletest/tests/path.test
+++ modules/simpletest/tests/path.test
@@ -181,7 +181,7 @@ class UrlAlterFunctionalTest extends DrupalWebTestCase {
     // level and for a specific existing forum.
     $this->assertUrlInboundAlter('community', 'forum');
     $this->assertUrlOutboundAlter('forum', 'community');
-    $forum_vid = db_query("SELECT vid FROM {taxonomy_vocabulary} WHERE module = 'forum'")->fetchField();
+    $forum_vid = db_query("SELECT vid FROM {taxonomy_vocabulary} WHERE module = :module", array(':module' => 'forum'))->fetchField();
     $tid = db_insert('taxonomy_term_data')
       ->fields(array(
         'name' => $this->randomName(),
diff --git modules/system/system.admin.inc modules/system/system.admin.inc
index e612c02..8d77984 100644
--- modules/system/system.admin.inc
+++ modules/system/system.admin.inc
@@ -23,12 +23,13 @@ function system_main_admin_page($arg = NULL) {
     drupal_set_message(t('One or more problems were detected with your Drupal installation. Check the <a href="@status">status report</a> for more information.', array('@status' => url('admin/reports/status'))), 'error');
   }
   $blocks = array();
-  if ($admin = db_query("SELECT menu_name, mlid FROM {menu_links} WHERE link_path = 'admin' AND module = 'system'")->fetchAssoc()) {
+  if ($admin = db_query("SELECT menu_name, mlid FROM {menu_links} WHERE link_path = :path AND module = :module", array(':path' => 'admin', ':module' => 'system'))->fetchAssoc()) {
+    $admin[':help_path'] = 'admin/help';
     $result = db_query("
       SELECT m.*, ml.*
       FROM {menu_links} ml
       INNER JOIN {menu_router} m ON ml.router_path = m.path
-      WHERE ml.link_path != 'admin/help' AND menu_name = :menu_name AND ml.plid = :mlid AND hidden = 0", $admin, array('fetch' => PDO::FETCH_ASSOC));
+      WHERE ml.link_path != :help_path AND menu_name = :menu_name AND ml.plid = :mlid AND hidden = 0", $admin, array('fetch' => PDO::FETCH_ASSOC));
     foreach ($result as $item) {
       _menu_link_translate($item);
       if (!$item['access']) {
@@ -79,12 +80,13 @@ function system_admin_config_page() {
     drupal_set_message(t('One or more problems were detected with your Drupal installation. Check the <a href="@status">status report</a> for more information.', array('@status' => url('admin/reports/status'))), 'error');
   }
   $blocks = array();
-  if ($admin = db_query("SELECT menu_name, mlid FROM {menu_links} WHERE link_path = 'admin/config' AND module = 'system'")->fetchAssoc()) {
+  if ($admin = db_query("SELECT menu_name, mlid FROM {menu_links} WHERE link_path = :config_path AND module = :module", array(':config_path' => 'admin/config', ':module' => 'system'))->fetchAssoc()) {
+    $admin[':help_path'] = 'admin/help';
     $result = db_query("
       SELECT m.*, ml.*
       FROM {menu_links} ml
       INNER JOIN {menu_router} m ON ml.router_path = m.path
-      WHERE ml.link_path != 'admin/help' AND menu_name = :menu_name AND ml.plid = :mlid AND hidden = 0", $admin, array('fetch' => PDO::FETCH_ASSOC));
+      WHERE ml.link_path != :help_path AND menu_name = :menu_name AND ml.plid = :mlid AND hidden = 0", $admin, array('fetch' => PDO::FETCH_ASSOC));
     foreach ($result as $item) {
       _menu_link_translate($item);
       if (!$item['access']) {
@@ -1278,7 +1280,7 @@ function system_modules_uninstall($form, $form_state = NULL) {
   }
 
   // Pull all disabled modules from the system table.
-  $disabled_modules = db_query("SELECT name, filename, info FROM {system} WHERE type = 'module' AND status = 0 AND schema_version > :schema ORDER BY name", array(':schema' => SCHEMA_UNINSTALLED));
+  $disabled_modules = db_query("SELECT name, filename, info FROM {system} WHERE type = :type AND status = 0 AND schema_version > :schema ORDER BY name", array(':type' => 'module', ':schema' => SCHEMA_UNINSTALLED));
   foreach ($disabled_modules as $module) {
     // Grab the module info
     $info = unserialize($module->info);
@@ -2847,7 +2849,7 @@ function system_actions_manage() {
   }
 
   $row = array();
-  $instances_present = db_query("SELECT aid FROM {actions} WHERE parameters <> ''")->fetchField();
+  $instances_present = db_query("SELECT aid FROM {actions} WHERE parameters <> :parameters", array(':parameters' => ''))->fetchField();
   $header = array(
     array('data' => t('Action type'), 'field' => 'type'),
     array('data' => t('Label'), 'field' => 'label'),
diff --git modules/system/system.install modules/system/system.install
index 923be4e..bbd7945 100644
--- modules/system/system.install
+++ modules/system/system.install
@@ -1785,7 +1785,9 @@ function system_update_7008() {
     // Add chid column and convert existing votes.
     db_add_field('poll_votes', 'chid', array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0));
     db_add_index('poll_votes', 'chid', array('chid'));
-    db_query("UPDATE {poll_votes} SET chid = (SELECT chid FROM {poll_choices} c WHERE {poll_votes}.chorder = c.chorder AND {poll_votes}.nid = c.nid)");
+    db_update('poll_votes')
+      ->expression('chid', '(SELECT chid FROM {poll_choices} c WHERE {poll_votes}.chorder = c.chorder AND {poll_votes}.nid = c.nid)')
+      ->execute();
     // Remove old chorder column.
     db_drop_field('poll_votes', 'chorder');
   }
@@ -1919,12 +1921,12 @@ function system_update_7016() {
           $datatype = 'bigint';
           break;
       }
-      db_query('ALTER TABLE ' . $row->table . ' ALTER COLUMN ' . $row->field . ' TYPE ' . $datatype);
-      db_query('ALTER TABLE ' . $row->table . ' ADD CHECK (' . $row->field . ' >= 0)');
+      db_query('ALTER TABLE ' . $row->table . ' ALTER COLUMN ' . $row->field . ' TYPE ' . $datatype, array(), array('relax_checks' => TRUE));
+      db_query('ALTER TABLE ' . $row->table . ' ADD CHECK (' . $row->field . ' >= 0)', array(), array('relax_checks' => TRUE));
     }
-    db_query('DROP DOMAIN smallint_unsigned');
-    db_query('DROP DOMAIN int_unsigned');
-    db_query('DROP DOMAIN bigint_unsigned');
+    db_query('DROP DOMAIN smallint_unsigned', array(), array('relax_checks' => TRUE));
+    db_query('DROP DOMAIN int_unsigned', array(), array('relax_checks' => TRUE));
+    db_query('DROP DOMAIN bigint_unsigned', array(), array('relax_checks' => TRUE));
   }
 }
 
@@ -1990,8 +1992,7 @@ function system_update_7024() {
   if (db_driver() == 'pgsql') {
     db_query('CREATE OR REPLACE FUNCTION "substring_index"(text, text, integer) RETURNS text AS
       \'SELECT array_to_string((string_to_array($1, $2)) [1:$3], $2);\'
-      LANGUAGE \'sql\''
-    );
+      LANGUAGE \'sql\'', array(), array('relax_checks' => TRUE));
   }
 }
 
diff --git modules/system/system.module modules/system/system.module
index 0317810..5869c05 100644
--- modules/system/system.module
+++ modules/system/system.module
@@ -1982,7 +1982,7 @@ function system_block_view($delta = '') {
 function system_admin_menu_block($item) {
   $cache = &drupal_static(__FUNCTION__, array());
   if (!isset($item['mlid'])) {
-    $item += db_query("SELECT mlid, menu_name FROM {menu_links} ml WHERE ml.router_path = :path AND module = 'system'", array(':path' => $item['path']))->fetchAssoc();
+    $item += db_query("SELECT mlid, menu_name FROM {menu_links} ml WHERE ml.router_path = :path AND module = :module", array(':path' => $item['path'], ':module' => 'system'))->fetchAssoc();
   }
 
   if (isset($cache[$item['mlid']])) {
@@ -2761,7 +2761,10 @@ function system_get_module_admin_tasks($module) {
   if (empty($items)) {
     $result = db_query("
        SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.delivery_callback, m.title, m.title_callback, m.title_arguments, m.theme_callback, m.theme_arguments, m.type, ml.*
-       FROM {menu_links} ml INNER JOIN {menu_router} m ON ml.router_path = m.path WHERE ml.link_path LIKE 'admin/%' AND hidden >= 0 AND module = 'system' AND m.number_parts > 2", array(), array('fetch' => PDO::FETCH_ASSOC));
+       FROM {menu_links} ml INNER JOIN {menu_router} m ON ml.router_path = m.path WHERE ml.link_path LIKE :link_path AND hidden >= 0 AND module = :module AND m.number_parts > 2", array(
+        ':link_path' => 'admin/%',
+        ':module' => 'system',
+      ), array('fetch' => PDO::FETCH_ASSOC));
     foreach ($result as $item) {
       _menu_link_translate($item);
       if ($item['access']) {
diff --git modules/system/system.test modules/system/system.test
index 6c94b93..8bfce95 100644
--- modules/system/system.test
+++ modules/system/system.test
@@ -1733,7 +1733,10 @@ class UpdateScriptFunctionalTest extends DrupalWebTestCase {
     $user1->pass_raw = user_password();
     require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
     $user1->pass = user_hash_password(trim($user1->pass_raw));
-    db_query("UPDATE {users} SET pass = :pass WHERE uid = :uid", array(':pass' => $user1->pass, ':uid' => $user1->uid));
+    db_update('users')
+      ->fields(array('pass' => $user1->pass))
+      ->condition('uid', $user1->uid)
+      ->execute();
     $this->drupalLogin($user1);
     $this->drupalGet($this->update_url, array('external' => TRUE));
     $this->assertResponse(200);
@@ -1746,10 +1749,10 @@ class UpdateScriptFunctionalTest extends DrupalWebTestCase {
     // Since visiting update.php triggers a rebuild of the theme system from an
     // unusual maintenance mode environment, we check that this rebuild did not
     // put any incorrect information about the themes into the database.
-    $original_theme_data = db_query("SELECT * FROM {system} WHERE type = 'theme' ORDER BY name")->fetchAll();
+    $original_theme_data = db_query("SELECT * FROM {system} WHERE type = :type ORDER BY name", array(':type' => 'theme'))->fetchAll();
     $this->drupalLogin($this->update_user);
     $this->drupalGet($this->update_url, array('external' => TRUE));
-    $final_theme_data = db_query("SELECT * FROM {system} WHERE type = 'theme' ORDER BY name")->fetchAll();
+    $final_theme_data = db_query("SELECT * FROM {system} WHERE type = :type ORDER BY name", array(':type' => 'theme'))->fetchAll();
     $this->assertEqual($original_theme_data, $final_theme_data, t('Visiting update.php does not alter the information about themes stored in the database.'));
   }
 }
diff --git modules/toolbar/toolbar.module modules/toolbar/toolbar.module
index dba77dd..2ecd9d2 100644
--- modules/toolbar/toolbar.module
+++ modules/toolbar/toolbar.module
@@ -269,7 +269,11 @@ function toolbar_view() {
  */
 function toolbar_get_menu_tree() {
   $tree = array();
-  $admin_link = db_query("SELECT * FROM {menu_links} WHERE menu_name = 'management' AND module = 'system' AND link_path = 'admin'")->fetchAssoc();
+  $admin_link = db_query("SELECT * FROM {menu_links} WHERE menu_name = :menu_name AND module = :module AND link_path = :link_path", array(
+    ':menu_name' => 'management',
+    ':module' => 'system',
+    ':link_path' => 'admin',
+  ))->fetchAssoc();
   if ($admin_link) {
     // @todo Use a function like book_menu_subtree_data().
     $tree = menu_tree_all_data('management', $admin_link, $admin_link['depth'] + 1);
diff --git modules/trigger/trigger.install modules/trigger/trigger.install
index 14a30bf..428d6ef 100644
--- modules/trigger/trigger.install
+++ modules/trigger/trigger.install
@@ -54,7 +54,7 @@ function trigger_install() {
  * Adds operation names to the hook names and drops the "op" field.
  */
 function trigger_update_7000() {
-  $result = db_query("SELECT hook, op, aid FROM {trigger_assignments} WHERE op <> ''");
+  $result = db_query("SELECT hook, op, aid FROM {trigger_assignments} WHERE op <> :op", array(':op' => ''));
 
   foreach ($result as $record) {
     db_update('trigger_assignments')
diff --git modules/user/user.install modules/user/user.install
index 33c17b4..9f5dcb4 100644
--- modules/user/user.install
+++ modules/user/user.install
@@ -497,7 +497,7 @@ function user_update_7004(&$sandbox) {
     // Initialize batch update information.
     $sandbox['progress'] = 0;
     $sandbox['last_user_processed'] = -1;
-    $sandbox['max'] = db_query("SELECT COUNT(*) FROM {users} WHERE picture <> ''")->fetchField();
+    $sandbox['max'] = db_query("SELECT COUNT(*) FROM {users} WHERE picture <> :picture", array(':picture' => ''))->fetchField();
   }
 
   // As a batch operation move the photos into the {file_managed} table and
