? .completion.db
? .git
? drushrc.php
? mw.patch
? tmp.patch
? modules/aggregator/aggregator.fetcher.inc
? modules/aggregator/aggregator.parser.inc
? modules/aggregator/aggregator.processor.inc
? modules/menu/menu.js
? modules/node/node.diff.inc
? modules/node/node.js
? modules/node/node.pages-diff.inc
? modules/path/path.js
? modules/simpletest/tests/hook_url_rewrite.info
? modules/simpletest/tests/hook_url_rewrite.module
? modules/simpletest/tests/path.test
? modules/upload/upload.js
Index: includes/database/select.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/select.inc,v
retrieving revision 1.12
diff -u -F^f -p -r1.12 select.inc
--- includes/database/select.inc	30 Dec 2008 16:43:14 -0000	1.12
+++ includes/database/select.inc	31 Dec 2008 03:40:43 -0000
@@ -291,7 +291,13 @@ class SelectQuery extends Query implemen
   }
 
   public function execute() {
+    // Modules may alter all queries or only those having a particular tag.
     drupal_alter('query', $this);
+    if (isset($this->alterTags)) {
+      foreach ($this->alterTags as $tag => $value) {
+        drupal_alter("query_$tag", $this);
+      }
+    }
 
     $args = $this->getArguments();
 
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1007
diff -u -F^f -p -r1.1007 node.module
--- modules/node/node.module	30 Dec 2008 16:43:18 -0000	1.1007
+++ modules/node/node.module	31 Dec 2008 03:40:44 -0000
@@ -2342,10 +2342,10 @@ function node_db_rewrite_sql($query, $pr
 }
 
 /**
- * Implementation of hook_query_alter().
+ * Implementation of hook_query_TAG_alter().
  */
-function node_query_alter(QueryAlterableInterface $query) {
-  if ($query->hasTag('node_access') && !node_access_view_all_nodes()) {
+function node_query_node_access_alter(QueryAlterableInterface $query) {
+  if (!node_access_view_all_nodes()) {
     $query->distinct();
     if (!$op = $query->getMetaData('op')) {
       $op = 'view';
Index: modules/simpletest/tests/database_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/database_test.module,v
retrieving revision 1.4
diff -u -F^f -p -r1.4 database_test.module
--- modules/simpletest/tests/database_test.module	12 Dec 2008 16:21:58 -0000	1.4
+++ modules/simpletest/tests/database_test.module	31 Dec 2008 03:40:44 -0000
@@ -4,16 +4,12 @@
 /**
  * Implementation of hook_query_alter().
  */
-function database_test_query_alter(SelectQuery $query) {
+function database_test_query_alter(QueryAlterableInterface $query) {
 
   if ($query->hasTag('database_test_alter_add_range')) {
     $query->range(0, 2);
   }
 
-  if ($query->hasTag('database_test_alter_remove_range')) {
-    $query->range();
-  }
-
   if ($query->hasTag('database_test_alter_add_join')) {
     $people_alias = $query->join('test', 'people', "test_task.pid=people.id");
     $name_field = $query->addField('people', 'name', 'name');
@@ -36,6 +32,14 @@ function database_test_query_alter(Selec
   }
 }
 
+
+/**
+ * Implementation of hook_query_TAG_alter(). Called by DatabaseTestCase::testAlterRemoveRange.
+ */
+function database_test_query_database_test_alter_remove_range_alter(QueryAlterableInterface $query) {
+  $query->range();
+}
+
 /**
  * Implementation of hook_menu().
  */
Index: modules/simpletest/tests/database_test.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/database_test.test,v
retrieving revision 1.33
diff -u -F^f -p -r1.33 database_test.test
--- modules/simpletest/tests/database_test.test	30 Dec 2008 16:43:18 -0000	1.33
+++ modules/simpletest/tests/database_test.test	31 Dec 2008 03:40:44 -0000
@@ -1695,7 +1695,7 @@ class DatabaseAlter2TestCase extends Dat
   }
 
   /**
-   * Test that we can remove a range() value from a query.
+   * Test that we can remove a range() value from a query. This also tests hook_query_TAG_alter().
    */
   function testAlterRemoveRange() {
     $query = db_select('test');
Index: modules/system/system.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.api.php,v
retrieving revision 1.7
diff -u -F^f -p -r1.7 system.api.php
--- modules/system/system.api.php	30 Dec 2008 16:43:19 -0000	1.7
+++ modules/system/system.api.php	31 Dec 2008 03:40:44 -0000
@@ -1374,6 +1374,62 @@ function hook_schema_alter(&$schema) {
 }
 
 /**
+ * Perform alterations to a structured query.
+ *
+ * Structured (aka dynamic) queries that have tags associated may be altered by any module
+ * before the query is executed.
+ *
+ * @see hook_query_TAG_alter()
+ * @see node_query_node_access_alter()
+ * 
+ * @param $query
+ *   A Query object describing the composite parts of a SQL query.
+ * @return
+ *   None.
+ */
+function hook_query_alter(QueryAlterableInterface $query) {
+  
+}
+
+/**
+ * Perform alterations to a structured query for a given tag.
+ *
+ * @see hook_query_alter()
+ * @see node_query_node_access_alter()
+ * 
+ * @param $query
+ *   An Query object describing the composite parts of a SQL query.
+ * @return
+ *   None.
+ */
+function hook_query_TAG_alter(QueryAlterableInterface $query) {
+  if (!node_access_view_all_nodes()) {
+    $query->distinct();
+    if (!$op = $query->getMetaData('op')) {
+      $op = 'view';
+    }
+    if (!user_access('bypass node access')) {
+      $access_alias = $query->join('node_access', 'na', 'na.nid = n.nid');
+      $or = db_or();
+      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)
+          );
+        }
+      }
+
+      if (count($or->conditions())) {
+        $query->condition($or);
+      }
+      
+      $query->condition("{$access_alias}.grant_$op", 1, '>=');
+    }
+  }
+}
+
+/**
  * Install the current version of the database schema, and any other setup tasks.
  *
  * The hook will be called the first time a module is installed, and the
