Problem

I have a search page view (showing a search index). It has seven exposed filters and a facet to limit search results. When using multiple exposed filters to limit the search and after that using the facet to limit the search even more, the view shows zero results when there should be a result. See the attached screenshot.

Accidental fix

As I was debugging this issue I found, by accident, that putting the line:

$db_query->getArguments();

Into function:

public function search(QueryInterface $query)

Of file:

search_api_db/src/Plugin/search_api/backend/Database.php

 

Fixed the issue. As far as I can see only calling this method shouldn't do anything. Somewhere else something is wrong. When debugging the objects I found that query placeholders were being mixed up or even left out of the final query.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

MartijnB created an issue. See original summary.

MartijnB’s picture

Issue summary: View changes
MartijnB’s picture

Issue summary: View changes
drunken monkey’s picture

Status: Active » Postponed (maintainer needs more info)

Did you try with the latest dev release of this module (or Alpha 17)? Please note that you should uninstall it, then update and re-install, though, to make sure that no update-caused errors occur.
Then, can you provide a test case that's failing, or post the generated (Search API) query? (It would normally be visible in the Views preview, but of course you can't set facets there, so probably just add

    drupal_set_message(new \Drupal\Component\Render\FormattableMarkup('<pre>' . \Drupal\Component\Utility\Html::escape((string) $query) . '</pre>', []));

to the beginning of search(). (Man, this is significantly more complicated in D8 …)
Finally, which DBMS are you using? Postgres also had problems with complex arguments in D7 (which we ran into with the DB backend).

Edit: The empty strings in the above code are supposed to be opening and closing <pre> tags.

MartijnB’s picture

Sorry for my very very late response! I finally had time to update Facets and Search API. Facets to 8.x-1.0-alpha7 and Search API to 8.x-1.0-beta3. No dev versions because it has to go into production and because of the tedious job of uninstalling and installing and creating everything again. Not something I want to do another time!
Unfortunately the bug is still there. :(
But when I put the same line:

$db_query->getArguments();

into the search function everything works fine again.

I've outputted the query with your line of code. See the image attached.
I'm using MariaDB.

drunken monkey’s picture

As written:

Edit: The empty strings in the above code are supposed to be opening and closing <pre> tags.

That would make the output considerably more readable.

In any case, there doesn't seem to be anything obviously wrong with the search query, and a quick test shows me there also shouldn't be a problem in the select query generated by the DB backend. Still, could you maybe also find out and post the select query corresponding to the search?
Also, could you maybe check directly in the database whether there should be entities matching those search criteria? Maybe the counts displayed by Facets are just wrong.

MartijnB’s picture

So I used your drupal_set_message with pre tags this time. :) In the search I'm doing the facets counts are correct. I couldn't find any difference in the queries. But when I outputted $db_query at the end of the search function I got two different queries.

This one is wrong:

SELECT t.item_id AS item_id, t.score AS score, t_2.title AS title, CASE WHEN t.word LIKE :like_w0 THEN 1 ELSE 0 END AS w0
FROM 
{search_api_db_actor_text} t
LEFT OUTER JOIN {search_api_db_actor} t_2 ON t.item_id = t_2.item_id
LEFT OUTER JOIN {search_api_db_actor_field_added_legal_states} t_3 ON t.item_id = t_3.item_id
WHERE ( (t.word LIKE :db_condition_placeholder_0 ESCAPE '\\') )AND (field_name IN  (:db_condition_placeholder_1)) AND(( (t_2.field_search_exist_start_end >= :db_condition_placeholder_2) AND (t_2.field_search_exist_end_start <= :db_condition_placeholder_3) AND (t_2.name = :db_condition_placeholder_4) AND (t_3.value = :db_condition_placeholder_5) )AND(( (t.item_id IN  (SELECT t.item_id AS item_id
FROM 
(SELECT t.item_id AS item_id, t.score AS score, CASE WHEN t.word LIKE :like_w0 THEN 1 ELSE 0 END AS w0
FROM 
{search_api_db_actor_text} t
WHERE ( (t.word LIKE :db_condition_placeholder_6 ESCAPE '\\') )AND (field_name IN  (:db_condition_placeholder_7)) 
GROUP BY item_id, score, w0) t)) ))AND( (t_2.field_organization_type = :db_condition_placeholder_6) ))
GROUP BY item_id, score, w0, t_2.title
ORDER BY score DESC, t_2.title ASC
LIMIT 20 OFFSET 0



This one is correct:

SELECT t.item_id AS item_id, t.score AS score, t_2.title AS title, CASE WHEN t.word LIKE :like_w0 THEN 1 ELSE 0 END AS w0
FROM 
{search_api_db_actor_text} t
LEFT OUTER JOIN {search_api_db_actor} t_2 ON t.item_id = t_2.item_id
LEFT OUTER JOIN {search_api_db_actor_field_added_legal_states} t_3 ON t.item_id = t_3.item_id
WHERE ( (t.word LIKE :db_condition_placeholder_0 ESCAPE '\\') )AND (field_name IN  (:db_condition_placeholder_1)) AND(( (t_2.field_search_exist_start_end >= :db_condition_placeholder_2) AND (t_2.field_search_exist_end_start <= :db_condition_placeholder_3) AND (t_2.name = :db_condition_placeholder_4) AND (t_3.value = :db_condition_placeholder_5) )AND(( (t.item_id IN  (SELECT t.item_id AS item_id
FROM 
(SELECT t.item_id AS item_id, t.score AS score, CASE WHEN t.word LIKE :like_w0 THEN 1 ELSE 0 END AS w0
FROM 
{search_api_db_actor_text} t
WHERE ( (t.word LIKE :db_condition_placeholder_6 ESCAPE '\\') )AND (field_name IN  (:db_condition_placeholder_7)) 
GROUP BY item_id, score, w0) t)) ))AND( (t_2.field_organization_type = :db_condition_placeholder_8) ))
GROUP BY item_id, score, w0, t_2.title
ORDER BY score DESC, t_2.title ASC
LIMIT 20 OFFSET 0



Notice the line:
GROUP BY item_id, score, w0) t)) ))AND( (t_2.field_organization_type = :db_condition_placeholder_6) ))

Where db_placeholder_6 should be db_placeholder_8.

Funny thing: When I put the drupal_set_message, outputting $db_query, before the line:
$results = $query->getResults();

Things work ok again. That is also the spot where I put the line:
$db_query->getArguments();

Getting confused now! :-S

drunken monkey’s picture

Thanks for the detailed findings, very helpful!
This sounds like it could have to do with this Core bug: #2142107-44: Complex cloned query dependent on __toString() call. Could you give the patch in #44 there a try?

drunken monkey’s picture

Version: 8.x-1.0-alpha14 » 8.x-1.0-beta3
MartijnB’s picture

Yes! The patch works! :)
Any idea when this patch is going to be in core?

drunken monkey’s picture

Category: Bug report » Support request
Status: Postponed (maintainer needs more info) » Fixed

Good to hear, thanks for reporting back!

Any idea when this patch is going to be in core?

No, sorry. Getting bug fixes (or other patches) into Core requires a pretty large (mostly diplomatic) effort, so unless someone invests that, the patch might lie there for several more years. (As you can see, my first patch for the issue, for D7, is already two and a half years old.)

However, you should in any case report in the Core issue that the patch works for you. Maybe that will help at least a bit.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

jordan.jamous’s picture

Thanks @drunkin-monkey
patch in #44 [ref: https://www.drupal.org/comment/11885996#comment-11885996 Complex cloned query dependent on __toString() call] worked fine for me