sequel 3.21.0 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. data/CHANGELOG +413 -3
  2. data/README.rdoc +20 -6
  3. data/Rakefile +23 -16
  4. data/bin/sequel +1 -5
  5. data/doc/association_basics.rdoc +210 -43
  6. data/doc/dataset_basics.rdoc +4 -4
  7. data/doc/mass_assignment.rdoc +54 -0
  8. data/doc/migration.rdoc +15 -538
  9. data/doc/model_hooks.rdoc +72 -27
  10. data/doc/opening_databases.rdoc +86 -50
  11. data/doc/prepared_statements.rdoc +40 -13
  12. data/doc/reflection.rdoc +8 -2
  13. data/doc/release_notes/3.22.0.txt +39 -0
  14. data/doc/release_notes/3.23.0.txt +172 -0
  15. data/doc/release_notes/3.24.0.txt +420 -0
  16. data/doc/release_notes/3.25.0.txt +88 -0
  17. data/doc/release_notes/3.26.0.txt +88 -0
  18. data/doc/release_notes/3.27.0.txt +82 -0
  19. data/doc/release_notes/3.28.0.txt +304 -0
  20. data/doc/release_notes/3.29.0.txt +459 -0
  21. data/doc/schema_modification.rdoc +547 -0
  22. data/doc/sharding.rdoc +7 -1
  23. data/doc/testing.rdoc +115 -0
  24. data/doc/transactions.rdoc +137 -0
  25. data/doc/virtual_rows.rdoc +2 -2
  26. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  27. data/lib/sequel/adapters/ado.rb +40 -18
  28. data/lib/sequel/adapters/amalgalite.rb +15 -7
  29. data/lib/sequel/adapters/db2.rb +175 -86
  30. data/lib/sequel/adapters/dbi.rb +15 -15
  31. data/lib/sequel/adapters/do/mysql.rb +0 -5
  32. data/lib/sequel/adapters/do/postgres.rb +0 -5
  33. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  34. data/lib/sequel/adapters/do.rb +17 -36
  35. data/lib/sequel/adapters/firebird.rb +27 -208
  36. data/lib/sequel/adapters/ibmdb.rb +448 -0
  37. data/lib/sequel/adapters/informix.rb +6 -23
  38. data/lib/sequel/adapters/jdbc/as400.rb +5 -31
  39. data/lib/sequel/adapters/jdbc/db2.rb +44 -0
  40. data/lib/sequel/adapters/jdbc/derby.rb +217 -0
  41. data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
  42. data/lib/sequel/adapters/jdbc/h2.rb +26 -17
  43. data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
  44. data/lib/sequel/adapters/jdbc/informix.rb +26 -0
  45. data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
  46. data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
  47. data/lib/sequel/adapters/jdbc/mysql.rb +9 -10
  48. data/lib/sequel/adapters/jdbc/oracle.rb +67 -25
  49. data/lib/sequel/adapters/jdbc/postgresql.rb +6 -11
  50. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
  51. data/lib/sequel/adapters/jdbc/sqlserver.rb +41 -0
  52. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  53. data/lib/sequel/adapters/jdbc.rb +107 -38
  54. data/lib/sequel/adapters/mock.rb +315 -0
  55. data/lib/sequel/adapters/mysql.rb +78 -182
  56. data/lib/sequel/adapters/mysql2.rb +24 -23
  57. data/lib/sequel/adapters/odbc/db2.rb +17 -0
  58. data/lib/sequel/adapters/odbc/mssql.rb +0 -5
  59. data/lib/sequel/adapters/odbc.rb +28 -9
  60. data/lib/sequel/adapters/openbase.rb +2 -4
  61. data/lib/sequel/adapters/oracle.rb +349 -51
  62. data/lib/sequel/adapters/postgres.rb +169 -21
  63. data/lib/sequel/adapters/shared/access.rb +21 -6
  64. data/lib/sequel/adapters/shared/db2.rb +288 -0
  65. data/lib/sequel/adapters/shared/firebird.rb +214 -0
  66. data/lib/sequel/adapters/shared/informix.rb +45 -0
  67. data/lib/sequel/adapters/shared/mssql.rb +108 -65
  68. data/lib/sequel/adapters/shared/mysql.rb +56 -13
  69. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
  70. data/lib/sequel/adapters/shared/oracle.rb +185 -34
  71. data/lib/sequel/adapters/shared/postgres.rb +107 -58
  72. data/lib/sequel/adapters/shared/progress.rb +0 -6
  73. data/lib/sequel/adapters/shared/sqlite.rb +168 -41
  74. data/lib/sequel/adapters/sqlite.rb +27 -18
  75. data/lib/sequel/adapters/swift/mysql.rb +9 -5
  76. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  77. data/lib/sequel/adapters/swift/sqlite.rb +6 -4
  78. data/lib/sequel/adapters/swift.rb +5 -5
  79. data/lib/sequel/adapters/tinytds.rb +152 -17
  80. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +63 -0
  81. data/lib/sequel/ast_transformer.rb +190 -0
  82. data/lib/sequel/connection_pool/threaded.rb +3 -2
  83. data/lib/sequel/connection_pool.rb +1 -1
  84. data/lib/sequel/core.rb +46 -5
  85. data/lib/sequel/database/connecting.rb +5 -6
  86. data/lib/sequel/database/dataset.rb +4 -4
  87. data/lib/sequel/database/dataset_defaults.rb +59 -1
  88. data/lib/sequel/database/logging.rb +1 -1
  89. data/lib/sequel/database/misc.rb +100 -19
  90. data/lib/sequel/database/query.rb +153 -58
  91. data/lib/sequel/database/schema_generator.rb +8 -5
  92. data/lib/sequel/database/schema_methods.rb +59 -29
  93. data/lib/sequel/dataset/actions.rb +194 -57
  94. data/lib/sequel/dataset/features.rb +81 -8
  95. data/lib/sequel/dataset/graph.rb +8 -7
  96. data/lib/sequel/dataset/misc.rb +50 -23
  97. data/lib/sequel/dataset/mutation.rb +5 -6
  98. data/lib/sequel/dataset/prepared_statements.rb +32 -15
  99. data/lib/sequel/dataset/query.rb +223 -42
  100. data/lib/sequel/dataset/sql.rb +58 -61
  101. data/lib/sequel/dataset.rb +8 -0
  102. data/lib/sequel/exceptions.rb +4 -0
  103. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  104. data/lib/sequel/extensions/migration.rb +6 -4
  105. data/lib/sequel/extensions/named_timezones.rb +5 -0
  106. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  107. data/lib/sequel/extensions/to_dot.rb +95 -83
  108. data/lib/sequel/model/associations.rb +997 -331
  109. data/lib/sequel/model/base.rb +386 -129
  110. data/lib/sequel/model/errors.rb +1 -1
  111. data/lib/sequel/model/exceptions.rb +5 -1
  112. data/lib/sequel/model.rb +15 -8
  113. data/lib/sequel/plugins/association_pks.rb +22 -4
  114. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  115. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  116. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  117. data/lib/sequel/plugins/force_encoding.rb +6 -6
  118. data/lib/sequel/plugins/identity_map.rb +114 -7
  119. data/lib/sequel/plugins/many_through_many.rb +65 -7
  120. data/lib/sequel/plugins/prepared_statements.rb +151 -0
  121. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  122. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  123. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  124. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  125. data/lib/sequel/plugins/serialization.rb +6 -1
  126. data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
  127. data/lib/sequel/plugins/sharding.rb +12 -25
  128. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  129. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  130. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  131. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  132. data/lib/sequel/sql.rb +107 -51
  133. data/lib/sequel/timezones.rb +44 -35
  134. data/lib/sequel/version.rb +1 -1
  135. data/spec/adapters/db2_spec.rb +146 -0
  136. data/spec/adapters/mssql_spec.rb +65 -29
  137. data/spec/adapters/mysql_spec.rb +122 -123
  138. data/spec/adapters/oracle_spec.rb +48 -76
  139. data/spec/adapters/postgres_spec.rb +213 -61
  140. data/spec/adapters/spec_helper.rb +6 -5
  141. data/spec/adapters/sqlite_spec.rb +35 -21
  142. data/spec/core/connection_pool_spec.rb +71 -92
  143. data/spec/core/core_sql_spec.rb +20 -31
  144. data/spec/core/database_spec.rb +729 -508
  145. data/spec/core/dataset_spec.rb +980 -1044
  146. data/spec/core/expression_filters_spec.rb +159 -42
  147. data/spec/core/mock_adapter_spec.rb +378 -0
  148. data/spec/core/object_graph_spec.rb +48 -114
  149. data/spec/core/schema_generator_spec.rb +3 -3
  150. data/spec/core/schema_spec.rb +298 -38
  151. data/spec/core/spec_helper.rb +6 -48
  152. data/spec/extensions/association_pks_spec.rb +38 -0
  153. data/spec/extensions/class_table_inheritance_spec.rb +1 -1
  154. data/spec/extensions/columns_introspection_spec.rb +91 -0
  155. data/spec/extensions/dataset_associations_spec.rb +199 -0
  156. data/spec/extensions/defaults_setter_spec.rb +64 -0
  157. data/spec/extensions/identity_map_spec.rb +162 -0
  158. data/spec/extensions/instance_hooks_spec.rb +71 -0
  159. data/spec/extensions/many_through_many_spec.rb +195 -20
  160. data/spec/extensions/migration_spec.rb +17 -17
  161. data/spec/extensions/named_timezones_spec.rb +22 -2
  162. data/spec/extensions/nested_attributes_spec.rb +4 -0
  163. data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
  164. data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
  165. data/spec/extensions/prepared_statements_spec.rb +72 -0
  166. data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
  167. data/spec/extensions/schema_dumper_spec.rb +2 -2
  168. data/spec/extensions/schema_spec.rb +13 -21
  169. data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
  170. data/spec/extensions/serialization_spec.rb +5 -8
  171. data/spec/extensions/single_table_inheritance_spec.rb +11 -0
  172. data/spec/extensions/spec_helper.rb +7 -1
  173. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  174. data/spec/extensions/to_dot_spec.rb +3 -5
  175. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  176. data/spec/extensions/xml_serializer_spec.rb +16 -4
  177. data/spec/integration/associations_test.rb +522 -21
  178. data/spec/integration/database_test.rb +4 -2
  179. data/spec/integration/dataset_test.rb +375 -62
  180. data/spec/integration/eager_loader_test.rb +19 -21
  181. data/spec/integration/model_test.rb +80 -1
  182. data/spec/integration/plugin_test.rb +304 -116
  183. data/spec/integration/prepared_statement_test.rb +200 -120
  184. data/spec/integration/schema_test.rb +161 -30
  185. data/spec/integration/spec_helper.rb +39 -30
  186. data/spec/integration/timezone_test.rb +38 -12
  187. data/spec/integration/transaction_test.rb +172 -5
  188. data/spec/integration/type_test.rb +17 -3
  189. data/spec/model/association_reflection_spec.rb +174 -7
  190. data/spec/model/associations_spec.rb +849 -661
  191. data/spec/model/base_spec.rb +255 -95
  192. data/spec/model/dataset_methods_spec.rb +7 -27
  193. data/spec/model/eager_loading_spec.rb +640 -676
  194. data/spec/model/hooks_spec.rb +309 -67
  195. data/spec/model/model_spec.rb +207 -167
  196. data/spec/model/plugins_spec.rb +24 -13
  197. data/spec/model/record_spec.rb +321 -218
  198. data/spec/model/spec_helper.rb +13 -71
  199. data/spec/model/validations_spec.rb +11 -0
  200. metadata +95 -38
@@ -1,10 +1,13 @@
1
1
  module Sequel
2
2
  class Database
3
3
  # ---------------------
4
- # :section: Methods that set defaults for created datasets
4
+ # :section: 5 - Methods that set defaults for created datasets
5
5
  # This methods change the default behavior of this database's datasets.
6
6
  # ---------------------
7
7
 
8
+ # The default class to use for datasets
9
+ DatasetClass = Sequel::Dataset
10
+
8
11
  # The identifier input method to use by default
9
12
  @@identifier_input_method = nil
10
13
 
@@ -42,9 +45,59 @@ module Sequel
42
45
  @@quote_identifiers = value
43
46
  end
44
47
 
48
+ # The class to use for creating datasets. Should respond to
49
+ # new with the Database argument as the first argument, and
50
+ # an optional options hash.
51
+ attr_reader :dataset_class
52
+
45
53
  # The default schema to use, generally should be nil.
46
54
  attr_accessor :default_schema
47
55
 
56
+ # If the database has any dataset modules associated with it,
57
+ # use a subclass of the given class that includes the modules
58
+ # as the dataset class.
59
+ def dataset_class=(c)
60
+ unless @dataset_modules.empty?
61
+ c = Class.new(c)
62
+ @dataset_modules.each{|m| c.send(:include, m)}
63
+ end
64
+ @dataset_class = c
65
+ end
66
+
67
+ # Equivalent to extending all datasets produced by the database with a
68
+ # module. What it actually does is use a subclass of the current dataset_class
69
+ # as the new dataset_class, and include the module in the subclass.
70
+ # Instead of a module, you can provide a block that is used to create an
71
+ # anonymous module.
72
+ #
73
+ # This allows you to override any of the dataset methods even if they are
74
+ # defined directly on the dataset class that this Database object uses.
75
+ #
76
+ # Examples:
77
+ #
78
+ # # Introspec columns for all of DB's datasets
79
+ # DB.extend_datasets(Sequel::ColumnsIntrospection)
80
+ #
81
+ # # Trace all SELECT queries by printing the SQL and the full backtrace
82
+ # DB.extend_datasets do
83
+ # def fetch_rows(sql)
84
+ # puts sql
85
+ # puts caller
86
+ # super
87
+ # end
88
+ # end
89
+ def extend_datasets(mod=nil, &block)
90
+ raise(Error, "must provide either mod or block, not both") if mod && block
91
+ mod = Module.new(&block) if block
92
+ if @dataset_modules.empty?
93
+ @dataset_modules = [mod]
94
+ @dataset_class = Class.new(@dataset_class)
95
+ else
96
+ @dataset_modules << mod
97
+ end
98
+ @dataset_class.send(:include, mod)
99
+ end
100
+
48
101
  # The method to call on identifiers going into the database
49
102
  def identifier_input_method
50
103
  case @identifier_input_method
@@ -109,6 +162,11 @@ module Sequel
109
162
 
110
163
  private
111
164
 
165
+ # The default dataset class to use for the database
166
+ def dataset_class_default
167
+ self.class.const_get(:DatasetClass)
168
+ end
169
+
112
170
  # The default value for default_schema.
113
171
  def default_schema_default
114
172
  nil
@@ -1,7 +1,7 @@
1
1
  module Sequel
2
2
  class Database
3
3
  # ---------------------
4
- # :section: Methods relating to logging
4
+ # :section: 6 - Methods relating to logging
5
5
  # This methods affect relating to the logging of executed SQL.
6
6
  # ---------------------
7
7
 
@@ -1,13 +1,13 @@
1
1
  module Sequel
2
2
  class Database
3
3
  # ---------------------
4
- # :section: Miscellaneous methods
4
+ # :section: 7 - Miscellaneous methods
5
5
  # These methods don't fit neatly into another category.
6
6
  # ---------------------
7
7
 
8
8
  # Converts a uri to an options hash. These options are then passed
9
9
  # to a newly created database object.
10
- def self.uri_to_options(uri) # :nodoc:
10
+ def self.uri_to_options(uri)
11
11
  { :user => uri.user,
12
12
  :password => uri.password,
13
13
  :host => uri.host,
@@ -19,6 +19,9 @@ module Sequel
19
19
  # The options hash for this database
20
20
  attr_reader :opts
21
21
 
22
+ # Set the timezone to use for this database, overridding <tt>Sequel.database_timezone</tt>.
23
+ attr_writer :timezone
24
+
22
25
  # Constructs a new instance of a database connection with the specified
23
26
  # options hash.
24
27
  #
@@ -50,15 +53,46 @@ module Sequel
50
53
  @schemas = {}
51
54
  @default_schema = @opts.fetch(:default_schema, default_schema_default)
52
55
  @prepared_statements = {}
53
- @transactions = []
56
+ @transactions = {}
54
57
  @identifier_input_method = nil
55
58
  @identifier_output_method = nil
56
59
  @quote_identifiers = nil
60
+ @timezone = nil
61
+ @dataset_class = dataset_class_default
62
+ @dataset_modules = []
57
63
  self.sql_log_level = @opts[:sql_log_level] ? @opts[:sql_log_level].to_sym : :info
58
64
  @pool = ConnectionPool.get_pool(@opts, &block)
59
65
 
60
66
  ::Sequel::DATABASES.push(self)
61
67
  end
68
+
69
+ # If a transaction is not currently in process, yield to the block immediately.
70
+ # Otherwise, add the block to the list of blocks to call after the currently
71
+ # in progress transaction commits (and only if it commits).
72
+ def after_commit(opts={}, &block)
73
+ raise Error, "must provide block to after_commit" unless block
74
+ synchronize(opts) do |conn|
75
+ if h = @transactions[conn]
76
+ raise Error, "cannot call after_commit in a prepared transaction" if h[:prepare]
77
+ (h[:after_commit] ||= []) << block
78
+ else
79
+ yield
80
+ end
81
+ end
82
+ end
83
+
84
+ # If a transaction is not currently in progress, ignore the block.
85
+ # Otherwise, add the block to the list of the blocks to call after the currently
86
+ # in progress transaction rolls back (and only if it rolls back).
87
+ def after_rollback(opts={}, &block)
88
+ raise Error, "must provide block to after_rollback" unless block
89
+ synchronize(opts) do |conn|
90
+ if h = @transactions[conn]
91
+ raise Error, "cannot call after_rollback in a prepared transaction" if h[:prepare]
92
+ (h[:after_rollback] ||= []) << block
93
+ end
94
+ end
95
+ end
62
96
 
63
97
  # Cast the given type to a literal type
64
98
  #
@@ -68,6 +102,20 @@ module Sequel
68
102
  type_literal(:type=>type)
69
103
  end
70
104
 
105
+ # Convert the given timestamp from the application's timezone,
106
+ # to the databases's timezone or the default database timezone if
107
+ # the database does not have a timezone.
108
+ def from_application_timestamp(v)
109
+ Sequel.convert_output_timestamp(v, timezone)
110
+ end
111
+
112
+ # Return true if already in a transaction given the options,
113
+ # false otherwise. Respects the :server option for selecting
114
+ # a shard.
115
+ def in_transaction?(opts={})
116
+ synchronize(opts[:server]){|conn| !!@transactions[conn]}
117
+ end
118
+
71
119
  # Returns a string representation of the database object including the
72
120
  # class name and the connection URI (or the opts if the URI
73
121
  # cannot be constructed).
@@ -90,6 +138,12 @@ module Sequel
90
138
  {:primary_key => true, :type => Integer, :auto_increment => true}
91
139
  end
92
140
 
141
+ # Whether the database supports CREATE TABLE IF NOT EXISTS syntax,
142
+ # false by default.
143
+ def supports_create_table_if_not_exists?
144
+ false
145
+ end
146
+
93
147
  # Whether the database and adapter support prepared transactions
94
148
  # (two-phase commit), false by default.
95
149
  def supports_prepared_transactions?
@@ -106,6 +160,18 @@ module Sequel
106
160
  false
107
161
  end
108
162
 
163
+ # The timezone to use for this database, defaulting to <tt>Sequel.database_timezone</tt>.
164
+ def timezone
165
+ @timezone || Sequel.database_timezone
166
+ end
167
+
168
+ # Convert the given timestamp to the application's timezone,
169
+ # from the databases's timezone or the default database timezone if
170
+ # the database does not have a timezone.
171
+ def to_application_timestamp(v)
172
+ Sequel.convert_timestamp(v, timezone)
173
+ end
174
+
109
175
  # Typecast the value to the given column_type. Calls
110
176
  # typecast_value_#{column_type} if the method exists,
111
177
  # otherwise returns the value.
@@ -175,12 +241,17 @@ module Sequel
175
241
  def database_error_classes
176
242
  []
177
243
  end
244
+
245
+ # Return true if exception represents a disconnect error, false otherwise.
246
+ def disconnect_error?(exception, opts)
247
+ opts[:disconnect]
248
+ end
178
249
 
179
250
  # Convert the given exception to a DatabaseError, keeping message
180
251
  # and traceback.
181
252
  def raise_error(exception, opts={})
182
253
  if !opts[:classes] || Array(opts[:classes]).any?{|c| exception.is_a?(c)}
183
- raise Sequel.convert_exception_class(exception, opts[:disconnect] ? DatabaseDisconnectError : DatabaseError)
254
+ raise Sequel.convert_exception_class(exception, disconnect_error?(exception, opts) ? DatabaseDisconnectError : DatabaseError)
184
255
  else
185
256
  raise exception
186
257
  end
@@ -194,7 +265,7 @@ module Sequel
194
265
  # Typecast the value to true, false, or nil
195
266
  def typecast_value_boolean(value)
196
267
  case value
197
- when false, 0, "0", /\Af(alse)?\z/i
268
+ when false, 0, "0", /\Af(alse)?\z/i, /\Ano?\z/i
198
269
  false
199
270
  else
200
271
  blank_object?(value) ? nil : true
@@ -204,10 +275,10 @@ module Sequel
204
275
  # Typecast the value to a Date
205
276
  def typecast_value_date(value)
206
277
  case value
207
- when Date
208
- value
209
278
  when DateTime, Time
210
279
  Date.new(value.year, value.month, value.day)
280
+ when Date
281
+ value
211
282
  when String
212
283
  Sequel.string_to_date(value)
213
284
  when Hash
@@ -219,12 +290,7 @@ module Sequel
219
290
 
220
291
  # Typecast the value to a DateTime or Time depending on Sequel.datetime_class
221
292
  def typecast_value_datetime(value)
222
- klass = Sequel.datetime_class
223
- if value.is_a?(Hash)
224
- klass.send(klass == Time ? :mktime : :new, *[:year, :month, :day, :hour, :minute, :second].map{|x| (value[x] || value[x.to_s]).to_i})
225
- else
226
- Sequel.typecast_to_application_timestamp(value)
227
- end
293
+ Sequel.typecast_to_application_timestamp(value)
228
294
  end
229
295
 
230
296
  # Typecast the value to a BigDecimal
@@ -244,9 +310,21 @@ module Sequel
244
310
  Float(value)
245
311
  end
246
312
 
247
- # Typecast the value to an Integer
248
- def typecast_value_integer(value)
249
- Integer(value)
313
+ # Used for checking/removing leading zeroes from strings so they don't get
314
+ # interpreted as octal.
315
+ LEADING_ZERO_RE = /\A0+(\d)/.freeze
316
+ if RUBY_VERSION >= '1.9'
317
+ # Typecast the value to an Integer
318
+ def typecast_value_integer(value)
319
+ (value.is_a?(String) && value =~ LEADING_ZERO_RE) ? Integer(value, 10) : Integer(value)
320
+ end
321
+ else
322
+ # Replacement string when replacing leading zeroes.
323
+ LEADING_ZERO_REP = "\\1".freeze
324
+ # Typecast the value to an Integer
325
+ def typecast_value_integer(value)
326
+ Integer(value.is_a?(String) ? value.sub(LEADING_ZERO_RE, LEADING_ZERO_REP) : value)
327
+ end
250
328
  end
251
329
 
252
330
  # Typecast the value to a String
@@ -258,12 +336,15 @@ module Sequel
258
336
  def typecast_value_time(value)
259
337
  case value
260
338
  when Time
261
- value
339
+ if value.is_a?(SQLTime)
340
+ value
341
+ else
342
+ SQLTime.create(value.hour, value.min, value.sec, value.respond_to?(:nsec) ? value.nsec/1000.0 : value.usec)
343
+ end
262
344
  when String
263
345
  Sequel.string_to_time(value)
264
346
  when Hash
265
- t = Time.now
266
- Time.mktime(t.year, t.month, t.day, *[:hour, :minute, :second].map{|x| (value[x] || value[x.to_s]).to_i})
347
+ SQLTime.create(*[:hour, :minute, :second].map{|x| (value[x] || value[x.to_s]).to_i})
267
348
  else
268
349
  raise Sequel::InvalidValue, "invalid value for Time: #{value.inspect}"
269
350
  end