Index: modules/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.1330 diff -u -p -r1.1330 node.module --- modules/node/node.module 2 Dec 2010 23:58:21 -0000 1.1330 +++ modules/node/node.module 16 Dec 2010 20:20:34 -0000 @@ -3161,29 +3161,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 @@ -3193,17 +3190,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 @@ -3211,29 +3200,35 @@ 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) ); } } + // Attach conditions to the subquery for nodes. $count = count($grant_conditions->conditions()); if ($type == 'node') { if ($count) { - $query->condition($grant_conditions); + $subquery->condition($grant_conditions); } - $query->condition($access_alias . '.grant_' . $op, 1, '>='); + $subquery->condition('na.grant_' . $op, 1, '>='); + $query->condition($nalias . '.nid', $subquery, 'IN'); } + // Now handle entities. else { + // Set a common alias for entities. + $base_alias = $nalias; if ($count) { - $entity_conditions->condition($grant_conditions); + $subquery->condition($grant_conditions); } - $entity_conditions->condition($access_alias . '.grant_' . $op, 1, '>='); + $subquery->condition('na.grant_' . $op, 1, '>='); + $query->condition($nalias . '.entity_id', $subquery, 'IN'); } } } - 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. $etid = variable_get('field_sql_storage_node_etid'); @@ -3246,6 +3241,7 @@ function _node_query_node_access_alter($ // Add the compiled set of rules to the query. $query->condition($or); } + } /**