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
Comment #1
jhodgdonWow, 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():
b) The query is altered for tag node_access in _node_query_node_access_alter() as follows:
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.
Comment #3
roderik