4.6.x database.inc db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $args = array())
4.7.x database.inc db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $args = array())
5.x database.inc db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $args = array())
6.x database.inc db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $args = array())

Rewrites node, taxonomy and comment queries. Use it for listing queries. Do not use FROM table1, table2 syntax, use JOIN instead.


$query: Query to be rewritten.

$primary_table: Name or alias of the table which has the primary key field for this query. Typical table names would be: {blocks}, {comments}, {forum}, {node}, {menu}, {term_data} or {vocabulary}. However, it is more common to use the the usual table aliases: b, c, f, n, m, t or v.

$primary_field: Name of the primary field.

$args: An array of arguments, passed to the implementations of hook_db_rewrite_sql.

Return value

The original query with JOIN and WHERE statements inserted from hook_db_rewrite_sql implementations. nid is rewritten if needed.

Related topics

38 calls to db_rewrite_sql()
block_list in modules/block/block.module
Return all blocks in the specified region for the current user.
blogapi_mt_validate_terms in modules/blogapi/blogapi.module
Blogging API helper - find allowed taxonomy terms for a node type.
blog_feed_last in modules/blog/blog.pages.inc
Menu callback; displays an RSS feed containing recent blog entries of all users.
blog_feed_user in modules/blog/blog.pages.inc
Menu callback; displays an RSS feed containing recent blog entries of a given user.
blog_page_last in modules/blog/blog.pages.inc
Menu callback; displays a Drupal page containing recent blog entries of all users.

... See full list

1 string reference to 'db_rewrite_sql'
_db_rewrite_sql in includes/database.inc
Helper function for db_rewrite_sql.


includes/database.inc, line 328
Wrapper for database interface code.


function db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid', $args = array()) {
  list($join, $where, $distinct) = _db_rewrite_sql($query, $primary_table, $primary_field, $args);
  if ($distinct) {
    $query = db_distinct_field($primary_table, $primary_field, $query);
  if (!empty($where) || !empty($join)) {
    $pattern = '{
      # Beginning of the string
        # Everything within this set of parentheses is named "anonymous view"
          [^()]++                   # anything not parentheses
          \\( (?P>anonymous_view) \\)          # an open parenthesis, more "anonymous view" and finally a close parenthesis.
    preg_match($pattern, $query, $matches);
    if (!$where) {
      $where = '1 = 1';
    if ($matches) {
      $n = strlen($matches[1]);
      $second_part = substr($query, $n);
      $first_part = substr($matches[1], 0, $n - 5) . " {$join} WHERE {$where} AND ( ";

      // PHP 4 does not support strrpos for strings. We emulate it.
      $haystack_reverse = strrev($second_part);
    else {
      $haystack_reverse = strrev($query);

    // No need to use strrev on the needle, we supply GROUP, ORDER, LIMIT
    // reversed.
    foreach (array(
    ) as $needle_reverse) {
      $pos = strpos($haystack_reverse, $needle_reverse);
      if ($pos !== FALSE) {

        // All needles are five characters long.
        $pos += 5;
    if ($matches) {
      if ($pos === FALSE) {
        $query = $first_part . $second_part . ')';
      else {
        $query = $first_part . substr($second_part, 0, -$pos) . ')' . substr($second_part, -$pos);
    elseif ($pos === FALSE) {
      $query .= " {$join} WHERE {$where}";
    else {
      $query = substr($query, 0, -$pos) . " {$join} WHERE {$where} " . substr($query, -$pos);
  return $query;


jcfiala’s picture

One subtle point to remember is that when you're using db_rewrite_sql, the WHERE in the original query must be capitalized, or you'll get errors if it's adding anything to the query.

bmarti44’s picture

using db_set_active before executing this function may cause errors. The node_access table is referenced by this function, and will not be available if you are temporarily using a different db.

ahtih’s picture

For new developers who have no idea what this function is about:

This function adds access control checks to SQL queries, so that the query returns only the rows the logged-in user is allowed to view. The actual checks necessary are determined by hook_db_rewrite_sql() and are thus extensible. For $primary_table='n', the core Node module implements hook_db_rewrite_sql() to tie into node access system ( hook_node_grants() etc).

manarth’s picture

db_rewrite_sql() is not available in Drupal 7.

Instead, DB queries can be tagged (with 'node_access'), which allows hook_query_alter to recognise queries which should have node-access controls added.

For example:

  $nids = db_select('node', 'n')
    ->fields('n', array('nid', 'created'))
    ->condition('type', 'blog')
    ->condition('status', 1)
    ->orderBy('created', 'DESC')
    ->range(0, variable_get('feed_default_items', 10))

The ->addTag('node_access') method marks the query for handling by the node access system.


bailey86’s picture

Even if you use the --user=1 option with Drush I'm getting no rows returned.

I don't appear to have any records in the {node_access} table - not sure what is going on here.

But - if I run the same function from the admin interface (logged in as admin) there do appear to be records returned.

If I get anything more definite I'll file a bug.

apotek’s picture

With node_access enabled...

> drush php-eval '
 $args = array(2, 4);
 echo db_rewrite_sql("SELECT n.* FROM {node} AS n INNER JOIN {%s} AS t ON n.vid = t.vid WHERE t.%s = %d", $args) . "\n";

SELECT n.* FROM {node} AS n INNER JOIN {%s} AS t ON n.vid = t.vid WHERE t.%s = %d

It looks to me like db_rewrite_sql() modifying the query at all when executed from drush.

Sudishth’s picture

$query = db_rewrite_sql("SELECT nid FROM {content_field_myfield} dmf WHERE field_myfield_nid = %d AND vid IN ( SELECT vid FROM {node} n where status = 1) order by nid");
  $result = db_query($query, $id);
  while ($row = db_fetch_object($result)) {
    if ($row->nid !== $id) {
      dpm($row->nid );