This is an issue that manifests a problem in Signup module. Signup provides the ability to set a reminder for an event a variable number of days before it, and the date on the event can be configurable. When using a date cck field the math of checking if the current date is within the range that a reminder should go out is incorrect, and the reminder is sent before the correct point. Much more information is at #856140: Reminder E-mails Sent as Soon as Cron Runs
The problem has been narrowed down to date module's sql_field handler, specifically STR_TO_DATE. When STR_TO_DATE is used on a Date field and then used within a conditional after DATE_SUB it is incorrect, it is expected to evaluate false and it instead evaluates true.
This is the query that Signup module generates: Assume there is an event
node with Date field field_dates
with start value ' 2011-11-30T00:00:00' and that we have the Signup 'send_reminder' set to 2.
SELECT n.title, n.nid, n.type, s.reminder_email, s.forwarding_email, field_dates_value FROM node n INNER JOIN signup s ON s.nid = n.nid INNER JOIN content_type_event ON content_type_event.vid = n.vid WHERE (s.send_reminder = 1) AND (n.type = 'event') AND ('2011-04-25 21:11:34' >= DATE_SUB(STR_TO_DATE(field_dates_value, '%Y-%m-%dT%T'), INTERVAL s.reminder_days_before DAY)) AND ('2011-04-25 21:11:34' <= DATE_ADD( STR_TO_DATE(field_dates_value, '%Y-%m-%dT%T'), INTERVAL 1 HOUR));
The above query should not return a result, but it does.
Steps to replicate:
1. Install Date 2.7, CCK, Signup 6.x-1.0
2. Enable Signup
3. Create signup-enabled node type with date field (Date type)
4. Create Signup node, set date many months in the future, enable reminder for 2 days before the event
5. Signup for the event
6. Hit cron, see email reminder
While looking into STR_TO_TIME I came across http://lists.mysql.com/mysql/204350 which says to use DATE_FORMAT
I propose altering
$field = "STR_TO_DATE($field, '%Y-%m-%%dT%T')";
to be
$field = "DATE_FORMAT(STR_TO_DATE($field, '%Y-%m-%%dT%T'), '%Y-%m-%%dT%T')";
which fixes the Signup bug. I will make a patch and test out other Date functionality with it.
Comment | File | Size | Author |
---|---|---|---|
#20 | date_sql_handler-1138210-20.patch | 658 bytes | djdevin |
Comments
Comment #1
coltraneProposed one change patch.
Comment #2
scottrigby@coltrane from #856140: Reminder E-mails Sent as Soon as Cron Runs I was seeing the same issues, and this patch seems to do the trick. I haven't tested it out exhaustively, but so far so good. Not sure that qualifies for RTBC, but +1 from me.
Comment #3
gjerdery CreditAttribution: gjerdery commentedThis change causes all events to disappear from my calendar view.
Comment #4
echoz CreditAttribution: echoz commentedsubscribe
Comment #5
gjerdery CreditAttribution: gjerdery commentedWhen the date patch suggested above encounters a view which is set to filter a date by a granularity of less than a day - this causes the view to return nothing. Specifically, it appears the ADDTIME function doesn't cope well with being passed the results of a DATE_FORMAT call. Here's the where clause of my view which doesn't work.
Comment #6
gjerdery CreditAttribution: gjerdery commentedAm I correct that STR_TO_DATE takes in a string and returns a DATETIME value, while DATE_FORMAT takes in a DATETIME value and returns a string? If so, in the code listed by the OP, are we comparing a string with a DATETIME value, whereas after the patch we are comparing string to string?
Comment #7
gjerdery CreditAttribution: gjerdery commentedI finally got all my views to show using the recent dev version of date and the patch. I had to change the granularity of the date filter from minute to day. This doesn't yet appear to cause any adverse effects.
Comment #8
gjerdery CreditAttribution: gjerdery commentedAn update - while for those views that you can change to a granularity of Day - this solution above works. However, if you need hour, minute or second granularity for a view, this change to the Date module gives incorrect results.
Comment #9
djdevinI found this in the MySQL manual, for DATE_ADD():
I think it's possible for DATE_ADD() to be returning a type/value that isn't comparable to Signup's input. Based on MySQL's recommendations I added a CAST() to DATETIME in the DATE_ADD() and DATE_SUB() calls in Date module. This fixed it for us without having to change signup or our other modules that use different intervals.
The only thing I'm unsure about is whether or not there is a use case for working with DATE, sans time.
Comment #10
protitude CreditAttribution: protitude commentedTested and seems to fix the issue on the Signup module.
Comment #11
KarenS CreditAttribution: KarenS commentedEarlier in the code, in sql_offset(), we switched to using ADDTIME instead of DATE_ADD for later versions of MYSQL. I wonder if we need the same change here. The sql_date_math() function is not used much so may need to be updated.
Comment #12
JvE CreditAttribution: JvE commentedNo, ADDTIME() takes a TIME or DATETIME, adds a TIME and returns a TIME or DATETIME.
It does not support INTERVAL and so cannot deal with the $granularity needed by sql_date_math().
In fact, I can see no reason why ADDTIME() is used in sql_offset() except that maybe it is slightly faster due to being simpler.
Patch from #9 looks simple and clean and solves our problems.
Comment #13
RobLoachStill applies too.
Comment #14
cafuego CreditAttribution: cafuego commentedApplied to 6.x-2.x-dev.
Comment #16
kyoder CreditAttribution: kyoder commentedThe patch in this ticket needs to be ported to the D7 version.
Comment #17
kyoder CreditAttribution: kyoder commentedHere's an updated version of the patch for 7.x-2.9-beta2
Comment #18
kyoder CreditAttribution: kyoder commentedComment #19
cafuego CreditAttribution: cafuego as a volunteer commentedCan you ensure that patch applies against HEAD please, 7.x-2.x?
Comment #20
djdevinRe-rolled.
Comment #21
Nique CreditAttribution: Nique commentedI need some help understanding the status of this issue.
On 2013-Oct-10, in comment #14, cafuego said that the patch was applied to "Applied to 6.x-2.x-dev" and changed the status to "Fixed" which I believe refers to the patch by djdevin in comment #9.) I am using Date 6.x-2.10 which is dated 2014-Mar-31. I assumed that the bug fixes made to Date 6.x-2.x-dev prior to 2014-Mar-31 would be included in that release. (Date 6.x-2.x-dev is currently dated 2015-May-09.)
Is that wrong?
I ask because I am using Date 6.x-2.10 and Signup 6.x-1.x-dev, and I am still having the problem of reminder e-mails being sent as soon as Cron runs. I don't know if I need to upgrade to or if I need to pursue another avenue for fixing this problem.
Comment #22
Chris Matthews CreditAttribution: Chris Matthews as a volunteer commentedThe 3 year old patch in #20 to date_api_sql.inc still applies cleanly to the latest 7.x-2.x-dev. Would anyone be able/willing to review/test this patch?
Comment #23
JvE CreditAttribution: JvE at One Shoe commentedI reviewed and tested the original D6 patch and have used the D7 patch for many years without issue.
Comment #27
DamienMcKennaComment #29
DamienMcKennaCommitted. Thanks.