Scenario
One hierarchical vocabulary called Countries with 300 taxonomy terms, one for each country, indenting like:
- America (level 1)
- Anguila (level 2)
- Antigua y barbuda (level 2)
- ... (level 2)
- Europe (level 1)
- Austria (level 2)
- Armenia (level 2)
- ... (level 2)
One content type called Office, then you add a field called Country, and its type is taxonomy reference, related to you recent created vocabulary called Countries.
- After that, you create a few nodes: the first is called 'My secret office', checking Afghanistan in its country field. The second node is called 'My beautiful office', checking Albania.
Now you think it should be interesting if you could have a page where you can see a list of all your offices. The finest way to achieve this is by creating a view. To do so, you create a view page with this configuration:
- Filter criteria: Content: Content type (= Office)
- Page settings: Path: /offices
Then you visit your new page /offices and you can see 2 offices: My secret office and My beautiful office. Everything works as expected.
Then you add a country filter in you page. Going back to views configuration:
- Filter criteria: Content: Has taxonomy term (exposed, Show as hierarchical) related to Countries.
You return to visit your page, and you can see a filter listing 300 countries and your 2 offices. You are on fire, so you decide to test your brand new filter:
- You check Afghanistan option, and click Search; then you only see My secret office. Great.
- You check Albania option, and click Search; then you only see My beautiful office. Awesome.
- You now check Afghanistan, Albania, Algeria, Andorra, Angola and so on until you have checked all your 300 countries. The correct output should be your 2 offices, since you have no more; so you click search and BAAAM: White Screen of Death. But you are smart, and you have allowed PHP yo show the error log. You see that MySQL had a failure:
SQLSTATE[HY000]: General error: 1116 Too many tables; MySQL can only use 61 tables in a join
It follows the entire query Drupal is trying to execute. You notice everything is fine EXCEPT for this:
LEFT JOIN {taxonomy_index} taxonomy_index_value_0 ON node_field_data.nid = taxonomy_index_value_0.nid AND taxonomy_index_value_0.tid = :views_join_condition_1
LEFT JOIN {taxonomy_index} taxonomy_index_value_1 ON node_field_data.nid = taxonomy_index_value_0.nid AND taxonomy_index_value_1.tid = :views_join_condition_2
LEFT JOIN {taxonomy_index} taxonomy_index_value_2 ON node_field_data.nid = taxonomy_index_value_0.nid AND taxonomy_index_value_2.tid = :views_join_condition_3
LEFT JOIN {taxonomy_index} taxonomy_index_value_3 ON node_field_data.nid = taxonomy_index_value_0.nid AND taxonomy_index_value_4.tid = :views_join_condition_4
and so on. Drupal is using the left join technique to access the database. The problem is that Drupal is using one left join for each taxonomy termed checked, meaning the first one is related to Afghanistan, the second one to Albania, the third is for Algeria, and so on.
¿How can I make a search using more than 61 options?
I think it is not a crazy thing that an user could search for offices in America and Europe, resulting this in more than 100 countries being checked. While looking for a solution, I have wrote a litle Javascript code that prevents the user from marking more than 50 countries so he doesn't face the WSoD.
Setup:
- Drupal 8.8.1 (core and all its modules updated)
- I'm not using any contributed module related to taxonomy or views
- PHP 7.1
- MySQL 5.5