This issue appears in d6 too: #1390098: multiple date filters adds up as OR instead of AND

Here is a simple setup that highlight the bug:
- two view filters on the date:
date.start OR date.end >= now
date.start OR date.end <= now
- the result query looks similar to this: WHERE (date.start OR date.end >= now) OR (date.start OR date.end <= now)
- it should be: - WHERE (date.start OR date.end >= now) AND (date.start OR date.end <= now)

The view filter operator is the default AND but the query doesn't respect that. Another issue is that moving one of the date filter in a filter group doesn't change the query.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

idflood’s picture

I've found that the date module use the "date_group" option to group the view filters. The problem is that there is no way to set this in the UI and it is the same across different filters. So here is two patches with different approaches.

The first use the filter id as a group name. The good thing is by default this will be "date", "date_1", ... So if there is only one filter it will be exactly the same as the default of "date_group" ("date").

The second one adds a form element to define this date_group option. The good thing with this approach is that it change less thing in the code and make use of a previously non-editable option. The catch is that the user has to manually enter a unique date_group for their date filters. The screenshot attached show this new option.

note: the validation part of the second patch isn't working right now but it gives an idea.

idflood’s picture

Status: Active » Needs review
idflood’s picture

here is a excerpt of the query after the patch #2 is applied and a unique group is set on the second filter:

WHERE (( (node.status = '1') AND (node.type IN  ('promo')) AND (1=1) AND (1=1) )AND( (DATE_FORMAT(field_data_field_date_promo.field_date_promo_value, '%Y-%m-%d') <= '2012-01-10') OR (DATE_FORMAT(field_data_field_date_promo2.field_date_promo_value2, '%Y-%m-%d') <= '2012-01-10') )AND( (DATE_FORMAT(field_data_field_date_promo3.field_date_promo_value, '%Y-%m-%d') >= '2012-01-10') OR (DATE_FORMAT(field_data_field_date_promo4.field_date_promo_value2, '%Y-%m-%d') >= '2012-01-10') ))

the same query, but with the same group defined in both filters:

WHERE (( (node.status = '1') AND (node.type IN  ('promo')) AND (1=1) AND (1=1) )AND( (DATE_FORMAT(field_data_field_date_promo.field_date_promo_value, '%Y-%m-%d') <= '2012-01-10') OR (DATE_FORMAT(field_data_field_date_promo2.field_date_promo_value2, '%Y-%m-%d') <= '2012-01-10') OR (DATE_FORMAT(field_data_field_date_promo3.field_date_promo_value, '%Y-%m-%d') >= '2012-01-10') OR (DATE_FORMAT(field_data_field_date_promo4.field_date_promo_value2, '%Y-%m-%d') >= '2012-01-10') ))
tim.plunkett’s picture

Status: Needs review » Postponed

This is related to #1367304: Using OR in filters breaks contextual filters.
I'm postponing until that's resolved.

idflood’s picture

Status: Postponed » Needs review
FileSize
2.71 KB

The views related issue has been fixed, that was fast : http://drupalcode.org/project/views.git/commit/e433b6519035357aab83a8d51...

I tried to reproduce the issue described here with a clean install and a git version of views and date module. Even with the latest version of views the issue is still there. I then tried both solutions provided by the patches in #1 and they still work.

One issue with both proposed patches and the current situation is that the date filter doesn't integrate with the view filter groups. So here is another patch, similar to the first one. This make the date filter use the views filter groups but has a big disadvantage. By default it will make all filters in the default group have an OR operator instead of the AND. Moving the two date filter in two new groups fix the issue described in #0.

vikramaditya234’s picture

any fixes for similar problem in D6?

tim.plunkett’s picture

Status: Needs review » Needs work

There are still stray references to date_group in some of the handlers, shouldn't those be replaced or removed?

KarenS’s picture

Of the two choices in #1, I prefer the one where you name the group. That is consistent with the way other things in Views work, like the naming of filter and pager keys.

The date filter was deliberately kept separate from the other filters so you could OR or AND the individual date fields without regard for the way the other filters were connected. I don't know that I understand why we would want to lose that, nor do I know any other way to accomplish that goal.

tim.plunkett’s picture

Title: d7: multiple date filters adds up as OR instead of AND » Using a custom filter group breaks the filter grouping UI
Assigned: Unassigned » KarenS
Priority: Normal » Major
Status: Needs work » Needs review
Issue tags: +D7 stable release blocker
FileSize
1.45 KB

I was able to solve the problem described in the original post by editing the setting for the date field, and changing the method. It's all the way at the bottom below the list of available date fields.

However, there is a bigger problem here. Views now has the ability to regroup filters, but specifying a group prevents the UI from working. AFAIK, there is no way for Views to avoid this, making it squarely Date's problem.

This approach just concatenates all of the appropriate conditions together and adds it back into whatever group is chosen with the UI.

Obviously it needs a better name than 'clean_up_query()' :)

Status: Needs review » Needs work
Issue tags: -D7 stable release blocker

The last submitted patch, date-1399744-9.patch, failed testing.

tim.plunkett’s picture

Status: Needs work » Needs review
Issue tags: +D7 stable release blocker

#9: date-1399744-9.patch queued for re-testing.

tim.plunkett’s picture

FileSize
5.32 KB

At first glance the difference between op_simple and op_between was not clear, until I realized they were identical except for the parent:: call.

So I consolidated into a helper function, documented it, and also was able to remove the 1=1 hack from #1096246: Filters not being applied correctly.

idflood’s picture

The patch in #12 is working perfectly in my tests. The date filters behave like other field now and result in a clean mysql query.

tim.plunkett’s picture

I'm generally against indirection, but this is very clear to me, since the code flow is identical for both ob_between and op_single.

I'm happy with this, idflood says it fixes his problem, any objections KarenS?

KarenS’s picture

Status: Needs review » Fixed

One thing that is left out of the new code is the elseif() clause from the following:

        if ($field['table_name'] != $this->table || !empty($this->relationship)) {
          $this->related_table_alias = $this->query->queue_table($field['table_name'], $this->relationship);
        }
        // $this->related_table_alias gets set when the first field is processed if otherwise empty.
        // For subsequent fields, we need to be sure it is emptied again.
        elseif (empty($this->relationship)) {
          $this->related_table_alias = NULL;
        }

This was only on the between op and unfortunately I didn't document it very well. I remember I had a problem with some combinations of dates that did and did not use relationships without that fix. But I can't replicate any problem now with the new code that is missing that clause. Basically I'm documenting here that we've lost that clause in case we find later that it is still needed.

Other than that this looks like a very elegant solution to the problem. Since I can't find a way to trigger a problem from the missing elseif() clause, I'm going to call this good.

Thanks!

http://drupalcode.org/project/date.git/commit/6a3828f

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