Skip to content

Commit

Permalink
MySQL 5.6 and later supports microsecond precision in datetime.
Browse files Browse the repository at this point in the history
You might want to branch it to include this only for 5.6, but
passing these values to < 5.6 doesn't cause issues either.
  • Loading branch information
miyagawa authored and arthurnn committed Mar 12, 2014
1 parent 7e21be3 commit df5a38f
Showing 1 changed file with 8 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ def quote_string(string)
@connection.escape(string)
end

def quoted_date(value)
if value.acts_like?(:time) && value.respond_to?(:usec)
"#{super}.#{sprintf("%06d", value.usec)}"
else
super
end
end

# CONNECTION MANAGEMENT ====================================

def active?
Expand Down

1 comment on commit df5a38f

@dre-hh
Copy link

@dre-hh dre-hh commented on df5a38f Mar 5, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

passing these values to < 5.6 doesn't cause issues either.

Unfortunately it does. Let's consider following usecase. you insert some records, which recieve a created at.

 INSERT INTO `recent_contact_requests` (`requester_id`, `requestee_id`, `created_at`, `updated_at`) VALUES (2, 3, '2014-11-23 13:41:38.394797', '2014-11-22 13:41:38.394797')
INSERT INTO `recent_contact_requests` (`requester_id`, `requestee_id`, `created_at`, `updated_at`) VALUES (1, 3, '2014-11-24 13:41:38.394797', '2014-11-23 13:41:38.394797')
INSERT INTO `recent_contact_requests` (`requester_id`, `requestee_id`, `created_at`, `updated_at`) VALUES (1, 2, '2014-11-22 13:41:38.394797', '2014-11-24 13:41:38.394797')
RecentContactRequest.where('created_at < ?', 100.days.ago)

which will generate the query

SELECT `recent_contact_requests`.* FROM `recent_contact_requests` WHERE (created_at < '2014-11-24 13:41:38.394797')

So you would expect it to return the first 2 records but not the last one, because the it's created is exactly2014-11-24 13:41:38.39479 but not less than it.

However this is not what will happen on mysql below 5.6. Below 5.6 all the records will be stored without the microsecond timestamp. So the last record will be stored with created_at: "2014-11-22 13:41:38".

And for the comparison of dates mysql, will just do a lexical comparison. So 2014-11-22 13:41:38 is actually less than 2014-11-24 13:41:38.394797 and the query will return the last record also.

You might want to branch it to include this only for 5.6

I.d.k why, but we experience this behavior on 5.6 either. The timestamps have been truncated on insert.

This implementation of microseconds also ignores the fact, that a a precision was set manually.

You can define the precision of timestamps for db queries by setting Time::DATE_FORMATS[:db]. If you then pass a datetime like object to an AR query it will automatically respect this setting.

So

# set date format to have 3 places for microseconds
Time::DATE_FORMATS[:db] = '%Y-%m-%d %H:%M:%S.%3N'
#fire up a query
RecentContactRequest.where('created_at < ?', 100.days.ago)

will result in

SELECT `recent_contact_requests`.* FROM `recent_contact_requests` WHERE (created_at < '2014-11-24 13:41:38.394.394797')

See issue #19223

Please sign in to comment.