1

The Search API has a Node Access Data Access Alteration which adds info into the index which can be used to implement 'normal' drupal node access restrictions to searches.

This was working fine until recently when a particular user was granted one too many Realm + grant Ids: now the Search API is throwing a hideous exception that's killing my site.

Basically Search API seems to create a JOIN for each realm:gid combo, and MySQL is limited to 64 JOINS.

Is there any way around this or is it a limitation of the Search API?

Would using Solr (never done it), for example, provide a solution?

0

My solution was to patch the search api db implementation.

This looks to see whether the field is a one-to-many relationship; if it is, then the table is added for each condition. I presume that this is so that these matches can then be counted and add towards the relevance score. However, for access restriction we're only interested in a single match, and (presumably) shouldn't add this to the score anyway. Therefore for this case there is no need to add a join for each possibility.

The patch below looks for this use case and ensures the user access table is only joined once.

--- a/sites/all/modules/search_api_db/service.inc
+++ b/sites/all/modules/search_api_db/service.inc
@@ -1028,7 +1028,12 @@ class SearchApiDbService extends SearchApiAbstractService {
           $cond->condition('t.item_id', $query, $f[2] == '<>' || $f[2] == '!=' ? 'NOT IN' : 'IN');
         }
         else {
-          $alias = $this->getTableAlias($fields[$f[0]], $db_query, search_api_is_list_type($fields[$f[0]]['type']));
+          // the user access node table only needs joining once; we're not interested in
+          // scoring based on access; access is a boolean, so we do not need muliple joins
+          // which can break the query if there are more of them than the SQL engine allows joins
+          // (e.g. MySQL is limited to 64 joins).
+          $rejoin = search_api_is_list_type($fields[$f[0]]['type']) && ($f[0] != 'search_api_access_node');
+          $alias = $this->getTableAlias($fields[$f[0]], $db_query, $rejoin);
           $cond->condition($alias . '.value', $f[1], $f[2]);
         }
       }

EDIT: LOL - or as they did it...

+          $new_join = search_api_is_list_type($field['type'])
+              && ($filter->getConjunction() == 'AND'
+                  || empty($first_join[$f[0]]));
+          if ($new_join || empty($tables[$f[0]])) {
+            $tables[$f[0]] = $this->getTableAlias($field, $db_query, $new_join);
+            $first_join[$f[0]] = TRUE;
+          }
+          $cond->condition($tables[$f[0]] . '.' . $field['column'], $f[1], $f[2]);

Answer is: upgrade module to v7.x-1.0!

0

May be you can check if node access is being indexed in filter options. Building a search View that respects access control

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.