diff --git a/includes/database.inc b/includes/database.inc
index 683ae69..5c9cdf0 100644
--- a/includes/database.inc
+++ b/includes/database.inc
@@ -53,15 +53,28 @@ define('DB_ERROR', 'a515ac9c2796ca0e23adbe92c68fc9fc');
  * Perform an SQL query and return success or failure.
  *
  * @param $sql
- *   A string containing a complete SQL query.  %-substitution
- *   parameters are not supported.
+ *   A string containing an SQL query.
+ * @param ...
+ *   A variable number of arguments which are substituted into the query
+ *   using printf() syntax. Instead of a variable number of query arguments,
+ *   you may also pass a single array containing the query arguments.
+ *
+ *   Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
+ *   in '') and %%.
+ *
+ *   NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
+ *   and TRUE values to decimal 1.
+ *
  * @return
  *   An array containing the keys:
  *      success: a boolean indicating whether the query succeeded
  *      query: the SQL query executed, passed through check_plain()
  */
 function update_sql($sql) {
-  $result = db_query($sql, true);
+  $args = func_get_args();
+  array_shift($args);
+  $result = db_query($sql, $args);
+  $sql = db_query_get_string($sql, $args);
   return array('success' => $result !== FALSE, 'query' => check_plain($sql));
 }
 
diff --git a/includes/database.mysql-common.inc b/includes/database.mysql-common.inc
index e3e0d85..ad2682c 100644
--- a/includes/database.mysql-common.inc
+++ b/includes/database.mysql-common.inc
@@ -42,6 +42,41 @@ function db_query($query) {
 }
 
 /**
+ * Builds a query, returns string.
+ *
+ * User-supplied arguments to the query should be passed in as separate
+ * parameters so that they can be properly escaped to avoid SQL injection
+ * attacks.
+ *
+ * @param $query
+ *   A string containing an SQL query.
+ * @param ...
+ *   A variable number of arguments which are substituted into the query
+ *   using printf() syntax. Instead of a variable number of query arguments,
+ *   you may also pass a single array containing the query arguments.
+ *
+ *   Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
+ *   in '') and %%.
+ *
+ *   NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
+ *   and TRUE values to decimal 1.
+ *
+ * @return
+ *   String of the query fully escaped and ready to run.
+ */
+function db_query_get_string($query) {
+  $args = func_get_args();
+  array_shift($args);
+  $query = db_prefix_tables($query);
+  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
+    $args = $args[0];
+  }
+  _db_query_callback($args, TRUE);
+  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
+  return $query;
+}
+
+/**
  * @ingroup schemaapi
  * @{
  */
diff --git a/includes/database.pgsql.inc b/includes/database.pgsql.inc
index 5fb0ccc..6cc7b8a 100644
--- a/includes/database.pgsql.inc
+++ b/includes/database.pgsql.inc
@@ -125,6 +125,41 @@ function db_query($query) {
 }
 
 /**
+ * Builds a query, returns string.
+ *
+ * User-supplied arguments to the query should be passed in as separate
+ * parameters so that they can be properly escaped to avoid SQL injection
+ * attacks.
+ *
+ * @param $query
+ *   A string containing an SQL query.
+ * @param ...
+ *   A variable number of arguments which are substituted into the query
+ *   using printf() syntax. Instead of a variable number of query arguments,
+ *   you may also pass a single array containing the query arguments.
+ *
+ *   Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
+ *   in '') and %%.
+ *
+ *   NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
+ *   and TRUE values to decimal 1.
+ *
+ * @return
+ *   String of the query fully escaped and ready to run.
+ */
+function db_query_get_string($query) {
+  $args = func_get_args();
+  array_shift($args);
+  $query = db_prefix_tables($query);
+  if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
+    $args = $args[0];
+  }
+  _db_query_callback($args, TRUE);
+  $query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
+  return $query;
+}
+
+/**
  * Helper function for db_query().
  */
 function _db_query($query, $debug = 0) {
