Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 7769

Show
Ignore:
Timestamp:
10/07/07 05:29:37 (1 year ago)
Author:
bitsweat
Message:

MySQL: speedup date/time parsing.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/CHANGELOG

    r7767 r7769  
    11*SVN* 
     2 
     3* MySQL: speedup date/time parsing.  [Jeremy Kemper] 
    24 
    35* Fix calling .clear on a has_many :dependent=>:delete_all association. [tarmo] 
  • trunk/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb

    r7220 r7769  
    9393      end 
    9494 
    95       # Used to convert from Strings to BLOBs 
    96       def self.string_to_binary(value) 
    97         value 
    98       end 
    99  
    100       # Used to convert from BLOBs to Strings 
    101       def self.binary_to_string(value) 
    102         value 
    103       end 
    104  
    105       def self.string_to_date(string) 
    106         return string unless string.is_a?(String) 
    107         date_array = ParseDate.parsedate(string) 
    108         # treat 0000-00-00 as nil 
    109         Date.new(date_array[0], date_array[1], date_array[2]) rescue nil 
    110       end 
    111  
    112       def self.string_to_time(string) 
    113         return string unless string.is_a?(String) 
    114         time_hash = Date._parse(string) 
    115         time_hash[:sec_fraction] = microseconds(time_hash) 
    116         time_array = time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction) 
    117         # treat 0000-00-00 00:00:00 as nil 
    118         begin 
    119           Time.send(Base.default_timezone, *time_array) 
    120         rescue 
    121           zone_offset = if Base.default_timezone == :local then DateTime.now.offset else 0 end 
    122           # Append zero calendar reform start to account for dates skipped by calendar reform 
    123           DateTime.new(*time_array[0..5] << zone_offset << 0) rescue nil 
    124         end 
    125       end 
    126  
    127       def self.string_to_dummy_time(string) 
    128         return string unless string.is_a?(String) 
    129         return nil if string.empty? 
    130         time_hash = Date._parse(string) 
    131         time_hash[:sec_fraction] = microseconds(time_hash) 
    132         # pad the resulting array with dummy date information 
    133         time_array = [2000, 1, 1] 
    134         time_array += time_hash.values_at(:hour, :min, :sec, :sec_fraction) 
    135         Time.send(Base.default_timezone, *time_array) rescue nil 
    136       end 
    137  
    138       # convert something to a boolean 
    139       def self.value_to_boolean(value) 
    140         if value == true || value == false 
     95      class << self 
     96        # Used to convert from Strings to BLOBs 
     97        def string_to_binary(value) 
    14198          value 
    142         else 
    143           %w(true t 1).include?(value.to_s.downcase) 
    144         end 
    145       end 
    146  
    147       # convert something to a BigDecimal 
    148       def self.value_to_decimal(value) 
    149         if value.is_a?(BigDecimal) 
     99        end 
     100 
     101        # Used to convert from BLOBs to Strings 
     102        def binary_to_string(value) 
    150103          value 
    151         elsif value.respond_to?(:to_d) 
    152           value.to_d 
    153         else 
    154           value.to_s.to_d 
    155         end 
     104        end 
     105 
     106        def string_to_date(string) 
     107          return string unless string.is_a?(String) 
     108          new_date *ParseDate.parsedate(string)[0..2] 
     109        end 
     110 
     111        def string_to_time(string) 
     112          return string unless string.is_a?(String) 
     113          return nil if string.empty? 
     114          time_hash = Date._parse(string) 
     115          time_hash[:sec_fraction] = microseconds(time_hash) 
     116          new_time *time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction) 
     117        end 
     118 
     119        def string_to_dummy_time(string) 
     120          return string unless string.is_a?(String) 
     121          return nil if string.empty? 
     122 
     123          string_to_time "2000-01-01 #{string}" 
     124        end 
     125 
     126        # convert something to a boolean 
     127        def value_to_boolean(value) 
     128          if value == true || value == false 
     129            value 
     130          else 
     131            %w(true t 1).include?(value.to_s.downcase) 
     132          end 
     133        end 
     134 
     135        # convert something to a BigDecimal 
     136        def value_to_decimal(value) 
     137          if value.is_a?(BigDecimal) 
     138            value 
     139          elsif value.respond_to?(:to_d) 
     140            value.to_d 
     141          else 
     142            value.to_s.to_d 
     143          end 
     144        end 
     145 
     146        protected 
     147          # '0.123456' -> 123456 
     148          # '1.123456' -> 123456 
     149          def microseconds(time) 
     150            ((time[:sec_fraction].to_f % 1) * 1_000_000).to_i 
     151          end 
     152 
     153          def new_date(year, mon, mday) 
     154            Date.new(year, mon, mday) unless year == 0 
     155          end 
     156 
     157          def new_time(year, mon, mday, hour, min, sec, microsec) 
     158            # Treat 0000-00-00 00:00:00 as nil. 
     159            return nil if year == 0 
     160 
     161            Time.send(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) 
     162          # Over/underflow to DateTime 
     163          rescue ArgumentError, TypeError 
     164            zone_offset = if Base.default_timezone == :local then DateTime.now.offset else 0 end 
     165            # Append zero calendar reform start to account for dates skipped by calendar reform 
     166            DateTime.new(year, mon, mday, hour, min, sec, zone_offset, 0) 
     167          end 
    156168      end 
    157169 
    158170      private 
    159         # '0.123456' -> 123456 
    160         # '1.123456' -> 123456 
    161         def self.microseconds(time) 
    162           ((time[:sec_fraction].to_f % 1) * 1_000_000).to_i 
    163         end 
    164  
    165171        def extract_limit(sql_type) 
    166172          $1.to_i if sql_type =~ /\((.*)\)/ 
  • trunk/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb

    r7688 r7769  
    9595      TYPES_ALLOWING_EMPTY_STRING_DEFAULT = Set.new([:string]) 
    9696 
     97      module Format 
     98        DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/ 
     99        DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(?:\.(\d{6}))?\z/ 
     100      end 
     101 
    97102      def initialize(name, default, sql_type = nil, null = true) 
    98103        @original_default = default 
     
    100105        @default = nil if no_default_allowed? || missing_default_forged_as_empty_string? 
    101106        @default = '' if @original_default == '' && no_default_allowed? 
     107      end 
     108 
     109      class << self 
     110        def string_to_date(string) 
     111          return string unless string.is_a?(String) 
     112          return nil if string.empty? 
     113 
     114          if string =~ Format::DATE 
     115            new_date $1.to_i, $2.to_i, $3.to_i 
     116          else 
     117            new_date *ParseDate.parsedate(string)[0..2] 
     118          end 
     119        end 
     120 
     121        def string_to_time(string) 
     122          return string unless string.is_a?(String) 
     123          return nil if string.empty? 
     124 
     125          if string =~ Format::DATETIME 
     126            new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, $7.to_i 
     127          else 
     128            time_hash = Date._parse(string) 
     129            new_time *(time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec) << microseconds(time_hash)) 
     130          end 
     131        end 
    102132      end 
    103133