I fear that this is not a bug or that it has already been reported, but I can't find anything like in the issues. I have OG 7.x-2.5 on Drupal 7.26 and am using og_access as the only node access module. For now all the group content is public, so it is visible to anyone, even anonymous users. I am just using the core search and the permissions are set so anyone can use search.

When anyone other than user 1 searches, no results are returned. I verified, using devel node access, that the content I am searching for is viewable by all. I used dpq() to print the search queries in node.module node_search_execute() like this:

dsm('node 1');
dpq($query);
// Only continue if the first pass query matches.
if (!$query->executeFirstPass()) {
  return array();
}
dsm('node 2');
dpq($query);

and in search.extender.inc executeFirstPass() like this:

if (!empty($this->words)) {
  dsm('fpq 1');  
  dpq($this);
  $or = db_or();
  foreach ($this->words as $word) {
    $or->condition('i.word', $word);
  }
  $this->condition($or);
  dsm('fpq 2');  
  dpq($this);
}

The results are below, but in summary, the search terms are getting injected into the node access part of the query. I'm not sure how to debug deeper.

SELECT
FROM
{search_index} i
INNER JOIN {node} n ON n.nid = i.sid AND EXISTS(SELECT na.nid AS nid
FROM
{node_access} na
WHERE (( (na.gid = '0') AND (na.realm = 'all') ))AND (na.grant_view >= '1') AND (n.nid = na.nid) )
WHERE (n.status = '1')

fpq 1

SELECT
FROM
{search_index} i
INNER JOIN {node} n ON n.nid = i.sid AND EXISTS(SELECT na.nid AS nid
FROM
{node_access} na
WHERE (( (na.gid = '0') AND (na.realm = 'all') ))AND (na.grant_view >= '1') AND (n.nid = na.nid) )
WHERE (n.status = '1')

fpq 2

SELECT
FROM
{search_index} i
INNER JOIN {node} n ON n.nid = i.sid AND EXISTS(SELECT na.nid AS nid
FROM
{node_access} na
WHERE (( (na.gid = '1') AND (na.realm = 'school') ))AND (na.grant_view >= '1') AND (n.nid = na.nid) )
WHERE (n.status = '1') AND( (i.word = 'school') )

node 2

SELECT
FROM
{search_index} i
INNER JOIN {node} n ON n.nid = i.sid AND EXISTS(SELECT na.nid AS nid
FROM
{node_access} na
WHERE (( (na.gid = '0') AND (na.realm = 'school') ))AND (na.grant_view >= '1') AND (n.nid = na.nid) )
INNER JOIN {search_total} t ON i.word = t.word
WHERE (n.status = '1') AND( (i.word = 'school') )AND (i.type = 'node')
GROUP BY i.type, i.sid
HAVING (COUNT(*) >= '1')

So if I use a search term of "all", I do get results, ha ha.

If I have two words as the search term, then the second one ends up also in the node access part of the query, e.g., na.grant_view >= 'student'.

Comments

jhodgdon’s picture

Title: No search results for non-admin user » Search query getting confused about which values go with which conditions
Component: search.module » database system
Related issues: +#2142107: Complex cloned query dependent on __toString() call

Wow, that is a strange bug! Thanks for your detailed report.

I actually think this is a symptom of an underlying problem in the Drupal database code, and not a problem in the Search module itself, or in the function _node_query_node_access_alter() that is adding the node access conditions to the query.

The problem is that the query condition builder is getting confused about which values go with which condition, when $query->condition() is called, and then when it constructs the SQL query string, it is putting the wrong values with those conditions.

For reference, for database system maintainers who want to look into this:

a) The Search query is set up in node_search_execute():

 $query = db_select('search_index', 'i', array('target' => 'slave'))->extend('SearchQuery')->extend('PagerDefault');
  $query->join('node', 'n', 'n.nid = i.sid');
  $query->condition('n.status', 1)->addTag('node_access')->searchExpression($keys, 'node');

b) The query is altered for tag node_access in _node_query_node_access_alter() as follows:

...
  $grants = node_access_grants($op, $account);
...
     foreach ($grants as $realm => $gids) {
        foreach ($gids as $gid) {
          $grant_conditions->condition(db_and()->condition('na.gid', $gid)->condition('na.realm', $realm));
        }
      }

c) SearchQuery::executeFirstPass() adds conditions for the keywords, and the query is fine until the db_or() it generates is added to the query, as evidenced by this issue's output.

This is probably due to #2142107: Complex cloned query dependent on __toString() call, because executeFirstPass() does do a clone just before this problem occurs, but I'm not sure, so I haven't marked it as a duplicate.

Version: 7.26 » 7.x-dev

Core issues are now filed against the dev versions where changes will be made. Document the specific release you are using in your issue comment. More information about choosing a version.

roderik’s picture