Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1225
diff -u -r1.1225 node.module
--- modules/node/node.module	30 Jan 2010 02:52:08 -0000	1.1225
+++ modules/node/node.module	5 Feb 2010 20:19:24 -0000
@@ -2918,25 +2918,33 @@
     }
     // Skip the extra joins and conditions for node admins.
     if (!user_access('bypass node access')) {
-      // The node_access table has the access grants for any given node.
-      $access_alias = $query->join('node_access', 'na', 'na.nid = n.nid');
-      $or = db_or();
-      // If any grant exists for the specified user, then user has access to the
-      // node for the specified operation.
-      foreach (node_access_grants($op, $query->getMetaData('account')) as $realm => $gids) {
-        foreach ($gids as $gid) {
-          $or->condition(db_and()
-            ->condition("{$access_alias}.gid", $gid)
-            ->condition("{$access_alias}.realm", $realm)
-          );
-        }
-      }
+      // Find all instances of the {node} table being joined.
+      $tables = $query->getTables();
+      $grants = node_access_grants($op, $query->getMetaData('account'));
+      foreach ($tables as $nalias => $tableinfo) {
+        $table = $tableinfo['table'];
+        if (!$table instanceof SelectQueryInterface && $table == 'node') {
+          // The node_access table has the access grants for any given node.
+          $access_alias = $query->join('node_access', 'na', "na.nid = {$nalias}.nid");
+          $or = db_or();
+          // If any grant exists for the specified user, then user has access
+          // to the node for the specified operation.
+          foreach ($grants as $realm => $gids) {
+            foreach ($gids as $gid) {
+              $or->condition(db_and()
+                ->condition("{$access_alias}.gid", $gid)
+                ->condition("{$access_alias}.realm", $realm)
+              );
+            }
+          }
+
+          if (count($or->conditions())) {
+            $query->condition($or);
+          }
 
-      if (count($or->conditions())) {
-        $query->condition($or);
+          $query->condition("{$access_alias}.grant_$op", 1, '>=');
+        }
       }
-
-      $query->condition("{$access_alias}.grant_$op", 1, '>=');
     }
   }
 }
Index: modules/node/node.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.test,v
retrieving revision 1.73
diff -u -r1.73 node.test
--- modules/node/node.test	1 Feb 2010 06:46:26 -0000	1.73
+++ modules/node/node.test	5 Feb 2010 20:19:24 -0000
@@ -1438,3 +1438,65 @@
     $this->assertFalse(isset($content['test_content_property']), t('Node content was emptied prior to being built.'));
   }
 }
+
+/**
+ * Tests node_query_node_access_alter().
+ */
+class NodeQueryAlter extends DrupalWebTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Node query alter',
+      'description' => 'Test that node access queries are properly altered by the node module.',
+      'group' => 'Node',
+    );
+  }
+
+  /**
+   * User with permission to view content.
+   */
+  protected $accessUser;
+
+  /**
+   * User without permission to view content.
+   */
+  protected $noAccessUser;
+
+  function setUp() {
+    parent::setUp('node_access_test');
+    node_access_rebuild();
+
+    // Create some content.
+    $this->drupalCreateNode();
+    $this->drupalCreateNode();
+    $this->drupalCreateNode();
+    $this->drupalCreateNode();
+
+    // Create user with simple node access permission.
+    $this->accessUser = $this->drupalCreateUser(array('access content', 'node test view'));
+    $this->noAccessUser = $this->drupalCreateUser(array('access content'));
+    $g1 = node_access_grants('view', $this->accessUser);
+    $g2 = node_access_grants('view', $this->noAccessUser);
+  }
+
+  /**
+   * Test that a query tagged with 'node_access' is altered by the node module.
+   *
+   * Verifies that a non-standard table alias can be used.
+   */
+  function testNodeQueryAlter() {
+    // Verify that a user with access permission can see at least one node.
+
+    $this->drupalLogin($this->accessUser);
+    $this->drupalGet('node_access_test_page');
+    $this->assertText('Yes nodes', "Nodes were found for access user");
+    $this->assertNoText('Exception', "No database exception");
+
+    // Verify that a user with no access permission cannot see nodes.
+
+    $this->drupalLogin($this->noAccessUser);
+    $this->drupalGet('node_access_test_page');
+    $this->assertText('No nodes', "No nodes were found for no access user");
+    $this->assertNoText('Exception', "No database exception");
+  }
+}
Index: modules/node/tests/node_access_test.module
===================================================================
RCS file: modules/node/tests/node_access_test.module
diff -N modules/node/tests/node_access_test.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/node/tests/node_access_test.module	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,101 @@
+<?php
+// $Id: node_test.module,v 1.9 2009/12/26 16:50:09 dries Exp $
+
+/**
+ * @file
+ * Dummy module implementing node access related hooks to test API interaction
+ * with the Node module. This module restricts view permission to those with
+ * a special 'node test view' permission.
+ */
+
+/**
+ * Implements hook_node_grants().
+ */
+function node_access_test_node_grants($account, $op) {
+  $grants = array();
+  if ($op == 'view' && user_access('node test view', $account)) {
+    $grants['node_access_test'] = array(888);
+  }
+  return $grants;
+}
+
+/**
+ * Implements hook_node_access_records().
+ */
+function node_access_test_node_access_records($node) {
+  $grants = array();
+  $grants[] = array(
+    'realm' => 'node_access_test',
+    'gid' => 888,
+    'grant_view' => 1,
+    'grant_update' => 0,
+    'grant_delete' => 0,
+    'priority' => 999,
+    );
+
+  return $grants;
+}
+
+/**
+ * Implements hook_permission().
+ *
+ * Sets up permissions for this module.
+ */
+function node_access_test_permission() {
+  return array('node test view' => array('title' => 'View content'));
+}
+
+/**
+ * Implements hook_menu().
+ *
+ * Sets up a page that lists nodes.
+ */
+function node_access_test_menu() {
+  $items = array();
+  $items['node_access_test_page'] = array(
+    'title' => 'Node access test',
+    'page callback' => 'node_access_test_page',
+    'access arguments' => array('access content'),
+    'type' => MENU_SUGGESTED_ITEM,
+  );
+  return $items;
+}
+
+/**
+ * Page callback for node access test page.
+ *
+ * Page should say "No nodes" if there are no nodes, and "Yes nodes" if there
+ * were nodes the user could access. Also, the database query is shown, and
+ * a list of the node IDs, for debugging purposes. And if there is a query
+ * exception, the page says "Exception" and gives the error.
+ */
+function node_access_test_page() {
+  $output = '';
+
+  try {
+    $query = db_select('node', 'mytab')
+      ->fields('mytab');
+    $query->addTag('node_access');
+    $result = $query->execute()->fetchAll();
+
+    if (count($result)) {
+      $output .= '<p>Yes nodes</p>';
+      $output .= '<ul>';
+      foreach ($result as $item) {
+        $output .= '<li>' . $item->nid . '</li>';
+      }
+      $output .= '</ul>';
+    }
+    else {
+      $output .= '<p>No nodes</p>';
+    }
+
+    $output .= '<p>' . ((string) $query ) . '</p>';
+  }
+  catch (Exception $e) {
+    $output = '<p>Exception</p>';
+    $output .= '<p>' . $e->getMessage() . '</p>';
+  }
+
+  return $output;
+}
Index: modules/node/tests/node_access_test.info
===================================================================
RCS file: modules/node/tests/node_access_test.info
diff -N modules/node/tests/node_access_test.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/node/tests/node_access_test.info	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,8 @@
+; $Id: node_test.info,v 1.1 2009/04/02 20:47:54 dries Exp $
+name = "Node module access tests"
+description = "Support module for node permission testing."
+package = Testing
+version = VERSION
+core = 7.x
+files[] = node_access_test.module
+hidden = TRUE
