From notifications_event_tracker() in notifications.cron.inc:
385 case 'update':
386 foreach ($events as $eid => $count) {
387 db_query('UPDATE {notifications_event} SET counter = counter - %d WHERE eid = %d', $count, $eid);
388 }
I encountered this by chance and have yet to be able to reproduce the conditions that caused it (I'll update this if I do). At some point on my site, this update statement tried to set the counter to a value below zero, which is a problem since counter is unsigned. As of MySQL 5.5.5, this will generate the error "BIGINT UNSIGNED value is out of range in ..." (see bottom of http://dev.mysql.com/doc/refman/5.5/en/out-of-range-and-overflow.html)
Regardless of how this error might have happened, there should be protection in place to prevent a value less than zero from being assigned to counter. Maybe something along the lines of
db_query('UPDATE {notifications_event} SET counter = GREATEST(counter - %d, 0) WHERE eid = %d', $count, $eid);
Comment | File | Size | Author |
---|---|---|---|
#2 | notifications-add_Mysql_int_mask-1272292-2.patch | 634 bytes | christianchristensen |
Comments
Comment #1
nnewton CreditAttribution: nnewton commentedI hit this recently with a 5.5 update, definitely a problem. I think this: "GREATEST(counter - %d, 0)" needs a CAST though, because MySQL 5.5 will make the result of a subtraction unsigned if any element of the subtraction is unsigned (so the actual expression eval will likely throw an error). You can disabled this in 5.5 by setting the SQL mode to NO_UNSIGNED_SUBTRACTION, but the correct way is with a cast I believe.
-N
Comment #2
christianchristensen CreditAttribution: christianchristensen commentedPlease find an attached patch that follows this idea of
GREATEST(CAST AS INTEGER
Comment #3
greggles