Index: includes/database/query.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database/query.inc,v retrieving revision 1.59 diff -u -p -r1.59 query.inc --- includes/database/query.inc 15 Dec 2010 06:52:54 -0000 1.59 +++ includes/database/query.inc 17 Dec 2010 18:44:26 -0000 @@ -1756,6 +1756,7 @@ class DatabaseCondition implements Query 'BETWEEN' => array('delimiter' => ' AND '), 'IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'), 'NOT IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'), + 'EXISTS' => array('prefix' => ' (', 'postfix' => ')'), 'IS NULL' => array('use_value' => FALSE), 'IS NOT NULL' => array('use_value' => FALSE), // Use backslash for escaping wildcard characters. Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.1333 diff -u -p -r1.1333 node.module --- modules/node/node.module 15 Dec 2010 03:47:28 -0000 1.1333 +++ modules/node/node.module 17 Dec 2010 18:44:31 -0000 @@ -3162,29 +3162,26 @@ function _node_query_node_access_alter($ return; } - // Prevent duplicate records. - $query->distinct(); - - // Find all instances of the {node} table being joined -- could appear - // more than once in the query, and could be aliased. Join each one to - // the node_access table. + // Find all instances of the {node} table in the query -- could appear + // more than once in the query, and could be aliased. Add a subselect + // to each one to properly filter by node access rules. $tables = $query->getTables(); + $grants = node_access_grants($op, $account); if ($type == 'entity') { // The original query looked something like: // @code // SELECT nid FROM sometable s - // INNER JOIN node_access na ON na.nid = s.nid - // WHERE ($node_access_conditions) + // WHERE s.nid IN (SELECT nid FROM node_access na WHERE $node_access_conditions) // @endcode // // Our query will look like: // @code // SELECT entity_type, entity_id // FROM field_data_something s - // LEFT JOIN node_access na ON s.entity_id = na.nid - // WHERE (entity_type = 'node' AND $node_access_conditions) OR (entity_type <> 'node') + // WHERE (entity_type = 'node' AND entity_id IN (SELECT nid FROM node_access na WHERE + // $node_access_conditions)) OR (entity_type <> 'node') // @endcode // // So instead of directly adding to the query object, we need to collect @@ -3194,17 +3191,9 @@ function _node_query_node_access_alter($ foreach ($tables as $nalias => $tableinfo) { $table = $tableinfo['table']; if (!($table instanceof SelectQueryInterface) && $table == $base_table) { - - // The node_access table has the access grants for any given node so JOIN - // it to the table containing the nid which can be either the node - // table or a field value table. - if ($type == 'node') { - $access_alias = $query->join('node_access', 'na', '%alias.nid = ' . $nalias . '.nid'); - } - else { - $access_alias = $query->leftJoin('node_access', 'na', '%alias.nid = ' . $nalias . '.entity_id'); - $base_alias = $nalias; - } + // Set the subquery. + $subquery = db_select('node_access', 'na') + ->fields('na', array('nid')); $grant_conditions = db_or(); // If any grant exists for the specified user, then user has access @@ -3212,29 +3201,29 @@ function _node_query_node_access_alter($ foreach ($grants as $realm => $gids) { foreach ($gids as $gid) { $grant_conditions->condition(db_and() - ->condition($access_alias . '.gid', $gid) - ->condition($access_alias . '.realm', $realm) + ->condition('na.gid', $gid) + ->condition('na.realm', $realm) ); } } - $count = count($grant_conditions->conditions()); - if ($type == 'node') { - if ($count) { - $query->condition($grant_conditions); - } - $query->condition($access_alias . '.grant_' . $op, 1, '>='); + // Attach conditions to the subquery for nodes. + if (count($grant_conditions->conditions())) { + $subquery->condition($grant_conditions); } - else { - if ($count) { - $entity_conditions->condition($grant_conditions); - } - $entity_conditions->condition($access_alias . '.grant_' . $op, 1, '>='); + $subquery->condition('na.grant_' . $op, 1, '>='); + $field = 'nid'; + // Now handle entities. + if ($type == 'entity') { + // Set a common alias for entities. + $base_alias = $nalias; + $field = 'entity_id'; } + $query->condition('', $subquery, 'EXISTS'); } } - if ($type == 'entity' && count($entity_conditions->conditions())) { + if ($type == 'entity' && count($subquery->conditions())) { // All the node access conditions are only for field values belonging to // nodes. $entity_conditions->condition("$base_alias.entity_type", 'node'); @@ -3246,6 +3235,7 @@ function _node_query_node_access_alter($ // Add the compiled set of rules to the query. $query->condition($or); } + } /**