From bd087e6716f8b48d48386c3d42e529849d7b68cd Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Sun, 7 Oct 2007 22:01:59 +0000 Subject: Use fast date/time parsing by default. Closes #9811. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@7780 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- activerecord/CHANGELOG | 2 +- .../abstract/schema_definitions.rb | 38 +++++++++++++++++++--- .../connection_adapters/mysql_adapter.rb | 29 ----------------- 3 files changed, 34 insertions(+), 35 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 96c434ce9e..028029fc05 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -2,7 +2,7 @@ * Raise ProtectedAttributeAssignmentError in development and test environments when mass-assigning to an attr_protected attribute. #9802 [Henrik N] -* MySQL: speedup date/time parsing. [Jeremy Kemper] +* Speedup database date/time parsing. [Jeremy Kemper, Tarmo Tänav] * Fix calling .clear on a has_many :dependent=>:delete_all association. [tarmo] diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index 507ddd2499..0325bdbbd8 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -6,6 +6,11 @@ module ActiveRecord module ConnectionAdapters #:nodoc: # An abstract definition of a column in a table. class Column + module Format + ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/ + ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/ + end + attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale attr_accessor :primary @@ -109,18 +114,16 @@ module ActiveRecord def string_to_date(string) return string unless string.is_a?(String) + return nil if string.empty? - new_date *ParseDate.parsedate(string)[0..2] + fast_string_to_date(string) || fallback_string_to_date(string) end def string_to_time(string) return string unless string.is_a?(String) return nil if string.empty? - time_hash = Date._parse(string) - time_hash[:sec_fraction] = microseconds(time_hash) - - new_time *time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction) + fast_string_to_time(string) || fallback_string_to_time(string) end def string_to_dummy_time(string) @@ -174,6 +177,31 @@ module ActiveRecord # Append zero calendar reform start to account for dates skipped by calendar reform DateTime.new(year, mon, mday, hour, min, sec, zone_offset, 0) rescue nil end + + def fast_string_to_date(string) + if string =~ Format::ISO_DATE + new_date $1.to_i, $2.to_i, $3.to_i + end + end + + # Doesn't handle time zones. + def fast_string_to_time(string) + if string =~ Format::ISO_DATETIME + microsec = ($7.to_f * 10e6).to_i + new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec + end + end + + def fallback_string_to_date(string) + new_date *ParseDate.parsedate(string)[0..2] + end + + def fallback_string_to_time(string) + time_hash = Date._parse(string) + time_hash[:sec_fraction] = microseconds(time_hash) + + new_time *time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction) + end end private diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index b385af7321..f0d6e443a7 100755 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -91,11 +91,6 @@ module ActiveRecord module ConnectionAdapters class MysqlColumn < Column #:nodoc: - module Format - DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/ - DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(?:\.(\d{6}))?\z/ - end - def extract_default(default) if type == :binary || type == :text if default.blank? @@ -110,30 +105,6 @@ module ActiveRecord end end - class << self - def string_to_date(string) - return string unless string.is_a?(String) - return nil if string.empty? - - if string =~ Format::DATE - new_date $1.to_i, $2.to_i, $3.to_i - else - super - end - end - - def string_to_time(string) - return string unless string.is_a?(String) - return nil if string.empty? - - if string =~ Format::DATETIME - new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, $7.to_i - else - super - end - end - end - private def simplified_type(field_type) return :boolean if MysqlAdapter.emulate_booleans && field_type.downcase.index("tinyint(1)") -- cgit v1.2.3