sequel 4.21.0 → 4.22.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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +32 -0
  3. data/README.rdoc +3 -4
  4. data/doc/opening_databases.rdoc +10 -75
  5. data/doc/release_notes/4.22.0.txt +72 -0
  6. data/lib/sequel/adapters/ado/access.rb +1 -1
  7. data/lib/sequel/adapters/cubrid.rb +3 -3
  8. data/lib/sequel/adapters/db2.rb +1 -0
  9. data/lib/sequel/adapters/dbi.rb +1 -0
  10. data/lib/sequel/adapters/fdbsql.rb +3 -2
  11. data/lib/sequel/adapters/firebird.rb +1 -0
  12. data/lib/sequel/adapters/ibmdb.rb +1 -21
  13. data/lib/sequel/adapters/informix.rb +1 -0
  14. data/lib/sequel/adapters/jdbc.rb +37 -49
  15. data/lib/sequel/adapters/jdbc/fdbsql.rb +1 -0
  16. data/lib/sequel/adapters/mysql.rb +5 -3
  17. data/lib/sequel/adapters/mysql2.rb +5 -2
  18. data/lib/sequel/adapters/odbc.rb +8 -4
  19. data/lib/sequel/adapters/openbase.rb +1 -0
  20. data/lib/sequel/adapters/oracle.rb +3 -46
  21. data/lib/sequel/adapters/postgres.rb +3 -36
  22. data/lib/sequel/adapters/shared/access.rb +1 -1
  23. data/lib/sequel/adapters/shared/fdbsql.rb +3 -3
  24. data/lib/sequel/adapters/shared/mssql.rb +1 -1
  25. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +12 -44
  26. data/lib/sequel/adapters/shared/oracle.rb +6 -2
  27. data/lib/sequel/adapters/shared/postgres.rb +6 -6
  28. data/lib/sequel/adapters/shared/sqlite.rb +1 -1
  29. data/lib/sequel/adapters/sqlite.rb +3 -46
  30. data/lib/sequel/adapters/tinytds.rb +12 -28
  31. data/lib/sequel/adapters/utils/pg_types.rb +1 -1
  32. data/lib/sequel/connection_pool/sharded_threaded.rb +63 -16
  33. data/lib/sequel/connection_pool/threaded.rb +72 -18
  34. data/lib/sequel/core.rb +1 -1
  35. data/lib/sequel/database/connecting.rb +2 -2
  36. data/lib/sequel/database/misc.rb +5 -5
  37. data/lib/sequel/database/query.rb +3 -2
  38. data/lib/sequel/database/schema_generator.rb +19 -19
  39. data/lib/sequel/database/schema_methods.rb +2 -2
  40. data/lib/sequel/database/transactions.rb +3 -3
  41. data/lib/sequel/dataset/actions.rb +18 -8
  42. data/lib/sequel/dataset/graph.rb +2 -2
  43. data/lib/sequel/dataset/prepared_statements.rb +28 -1
  44. data/lib/sequel/dataset/query.rb +7 -7
  45. data/lib/sequel/exceptions.rb +27 -24
  46. data/lib/sequel/extensions/_pretty_table.rb +1 -1
  47. data/lib/sequel/extensions/constraint_validations.rb +2 -2
  48. data/lib/sequel/extensions/date_arithmetic.rb +2 -2
  49. data/lib/sequel/extensions/pg_array.rb +10 -1
  50. data/lib/sequel/extensions/pg_row.rb +1 -1
  51. data/lib/sequel/extensions/pg_static_cache_updater.rb +1 -1
  52. data/lib/sequel/extensions/schema_dumper.rb +8 -8
  53. data/lib/sequel/extensions/split_array_nil.rb +1 -1
  54. data/lib/sequel/model.rb +1 -1
  55. data/lib/sequel/model/associations.rb +18 -11
  56. data/lib/sequel/model/base.rb +15 -15
  57. data/lib/sequel/model/exceptions.rb +11 -2
  58. data/lib/sequel/plugins/accessed_columns.rb +1 -1
  59. data/lib/sequel/plugins/auto_validations.rb +1 -1
  60. data/lib/sequel/plugins/boolean_readers.rb +1 -1
  61. data/lib/sequel/plugins/class_table_inheritance.rb +4 -7
  62. data/lib/sequel/plugins/composition.rb +1 -1
  63. data/lib/sequel/plugins/constraint_validations.rb +2 -2
  64. data/lib/sequel/plugins/csv_serializer.rb +171 -0
  65. data/lib/sequel/plugins/dirty.rb +2 -2
  66. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  67. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  68. data/lib/sequel/plugins/many_through_many.rb +1 -1
  69. data/lib/sequel/plugins/nested_attributes.rb +5 -5
  70. data/lib/sequel/plugins/pg_array_associations.rb +4 -4
  71. data/lib/sequel/plugins/prepared_statements.rb +2 -2
  72. data/lib/sequel/plugins/prepared_statements_safe.rb +1 -1
  73. data/lib/sequel/plugins/serialization.rb +6 -6
  74. data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
  75. data/lib/sequel/plugins/sharding.rb +3 -1
  76. data/lib/sequel/plugins/single_table_inheritance.rb +5 -13
  77. data/lib/sequel/plugins/static_cache.rb +2 -2
  78. data/lib/sequel/plugins/tactical_eager_loading.rb +1 -1
  79. data/lib/sequel/plugins/tree.rb +1 -1
  80. data/lib/sequel/plugins/validation_class_methods.rb +2 -2
  81. data/lib/sequel/plugins/validation_helpers.rb +4 -4
  82. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  83. data/lib/sequel/sql.rb +1 -1
  84. data/lib/sequel/version.rb +1 -1
  85. data/spec/adapters/postgres_spec.rb +17 -0
  86. data/spec/core/connection_pool_spec.rb +1 -1
  87. data/spec/core/dataset_spec.rb +22 -0
  88. data/spec/extensions/auto_validations_spec.rb +1 -1
  89. data/spec/extensions/blacklist_security_spec.rb +2 -2
  90. data/spec/extensions/csv_serializer_spec.rb +173 -0
  91. data/spec/extensions/json_serializer_spec.rb +2 -2
  92. data/spec/extensions/nested_attributes_spec.rb +9 -9
  93. data/spec/extensions/pg_array_spec.rb +5 -0
  94. data/spec/extensions/single_table_inheritance_spec.rb +21 -0
  95. data/spec/extensions/touch_spec.rb +1 -1
  96. data/spec/extensions/tree_spec.rb +4 -0
  97. data/spec/extensions/xml_serializer_spec.rb +3 -3
  98. data/spec/integration/prepared_statement_test.rb +1 -1
  99. data/spec/integration/schema_test.rb +7 -0
  100. data/spec/integration/type_test.rb +2 -2
  101. data/spec/model/associations_spec.rb +108 -14
  102. data/spec/model/base_spec.rb +8 -8
  103. data/spec/model/record_spec.rb +7 -7
  104. metadata +6 -2
@@ -201,9 +201,9 @@ module Sequel
201
201
  # Duplicate internal data structures
202
202
  def initialize_copy(other)
203
203
  super
204
- @initial_values = other.initial_values.dup
204
+ @initial_values = Hash[other.initial_values]
205
205
  @missing_initial_values = other.send(:missing_initial_values).dup
206
- @previous_changes = other.previous_changes.dup if other.previous_changes
206
+ @previous_changes = Hash[other.previous_changes] if other.previous_changes
207
207
  self
208
208
  end
209
209
 
@@ -63,7 +63,7 @@ module Sequel
63
63
  #
64
64
  # class MyModel
65
65
  # add_hook_type :before_move_to
66
- # before_move_to(:check_move_allowed){|o| o.allow_move?}
66
+ # before_move_to(:check_move_allowed, &:allow_move?)
67
67
  # def move_to(there)
68
68
  # return if before_move_to == false
69
69
  # # move MyModel object to there
@@ -82,7 +82,7 @@ module Sequel
82
82
 
83
83
  # Run all hook blocks of the given hook type.
84
84
  def run_after_instance_hooks(hook)
85
- instance_hooks(hook).each{|b| b.call}
85
+ instance_hooks(hook).each(&:call)
86
86
  end
87
87
 
88
88
  # Run all hook blocks of the given hook type. If a hook block returns false,
@@ -263,7 +263,7 @@ module Sequel
263
263
  select_all(egds.first_source).
264
264
  select_append(*associated_key_array)
265
265
  egds = opts.apply_eager_graph_limit_strategy(egls, egds)
266
- ds.graph(egds, associated_key_array.map{|v| v.alias}.zip(Array(lpkcs)) + conditions, :qualify=>:deep, :table_alias=>eo[:table_alias], :implicit_qualifier=>iq, :join_type=>eo[:join_type]||join_type, :join_only=>eo[:join_only], :from_self_alias=>eo[:from_self_alias], :select=>select||orig_egds.columns, &graph_block)
266
+ ds.graph(egds, associated_key_array.map(&:alias).zip(Array(lpkcs)) + conditions, :qualify=>:deep, :table_alias=>eo[:table_alias], :implicit_qualifier=>iq, :join_type=>eo[:join_type]||join_type, :join_only=>eo[:join_only], :from_self_alias=>eo[:from_self_alias], :select=>select||orig_egds.columns, &graph_block)
267
267
  else
268
268
  opts.edges.each do |t|
269
269
  ds = ds.graph(t[:table], t.fetch(:only_conditions, (Array(t[:right]).zip(Array(t[:left])) + t[:conditions])), :select=>false, :table_alias=>ds.unused_table_alias(t[:table]), :join_type=>eo[:join_type]||t[:join_type], :join_only=>eo[:join_only], :qualify=>:deep, :implicit_qualifier=>iq, :from_self_alias=>eo[:from_self_alias], &t[:block])
@@ -137,7 +137,7 @@ module Sequel
137
137
  def set_nested_attributes(assoc, obj, opts=OPTS)
138
138
  raise(Error, "no association named #{assoc} for #{model.inspect}") unless ref = model.association_reflection(assoc)
139
139
  raise(Error, "nested attributes are not enabled for association #{assoc} for #{model.inspect}") unless meta = ref[:nested_attributes]
140
- meta = meta.merge(opts)
140
+ meta = Hash[meta].merge!(opts)
141
141
  meta[:reflection] = ref
142
142
  if ref.returns_array?
143
143
  nested_attributes_list_setter(meta, obj)
@@ -195,7 +195,7 @@ module Sequel
195
195
  # If there is a limit on the nested attributes for this association,
196
196
  # make sure the length of the attributes_list is not greater than the limit.
197
197
  def nested_attributes_list_setter(meta, attributes_list)
198
- attributes_list = attributes_list.sort_by{|x| x.to_s}.map{|k,v| v} if attributes_list.is_a?(Hash)
198
+ attributes_list = attributes_list.sort_by(&:to_s).map{|k,v| v} if attributes_list.is_a?(Hash)
199
199
  if (limit = meta[:limit]) && attributes_list.length > limit
200
200
  raise(Error, "number of nested attributes (#{attributes_list.length}) exceeds the limit (#{limit})")
201
201
  end
@@ -254,10 +254,10 @@ module Sequel
254
254
  reflection = meta[:reflection]
255
255
  klass = reflection.associated_class
256
256
  sym_keys = Array(klass.primary_key)
257
- str_keys = sym_keys.map{|k| k.to_s}
257
+ str_keys = sym_keys.map(&:to_s)
258
258
  if (pk = attributes.values_at(*sym_keys)).all? || (pk = attributes.values_at(*str_keys)).all?
259
- pk = pk.map{|k| k.to_s}
260
- obj = Array(send(reflection[:name])).find{|x| Array(x.pk).map{|k| k.to_s} == pk}
259
+ pk = pk.map(&:to_s)
260
+ obj = Array(send(reflection[:name])).find{|x| Array(x.pk).map(&:to_s) == pk}
261
261
  end
262
262
  if obj
263
263
  attributes = attributes.dup.delete_if{|k,v| str_keys.include? k.to_s}
@@ -312,7 +312,7 @@ module Sequel
312
312
  opts[:eager_loader] ||= proc do |eo|
313
313
  id_map = eo[:id_map]
314
314
 
315
- eager_load_results(opts, eo.merge(:loader=>false)) do |assoc_record|
315
+ eager_load_results(opts, Hash[eo].merge!(:loader=>false)) do |assoc_record|
316
316
  if pks ||= assoc_record.get_column_value(key)
317
317
  pks.each do |pkv|
318
318
  next unless objects = id_map[pkv]
@@ -348,7 +348,7 @@ module Sequel
348
348
 
349
349
  opts[:eager_grapher] ||= proc do |eo|
350
350
  ds = eo[:self]
351
- ds = ds.graph(eager_graph_dataset(opts, eo), conditions, eo.merge(:select=>select, :join_type=>eo[:join_type]||join_type, :qualify=>:deep, :from_self_alias=>eo[:from_self_alias]), &graph_block)
351
+ ds = ds.graph(eager_graph_dataset(opts, eo), conditions, Hash[eo].merge!(:select=>select, :join_type=>eo[:join_type]||join_type, :qualify=>:deep, :from_self_alias=>eo[:from_self_alias]), &graph_block)
352
352
  ds
353
353
  end
354
354
 
@@ -402,7 +402,7 @@ module Sequel
402
402
  end
403
403
  end
404
404
 
405
- eager_load_results(opts, eo.merge(:id_map=>id_map)) do |assoc_record|
405
+ eager_load_results(opts, Hash[eo].merge!(:id_map=>id_map)) do |assoc_record|
406
406
  if objects = id_map[assoc_record.get_column_value(pkm)]
407
407
  objects.each do |object|
408
408
  object.associations[name].push(assoc_record)
@@ -435,7 +435,7 @@ module Sequel
435
435
 
436
436
  opts[:eager_grapher] ||= proc do |eo|
437
437
  ds = eo[:self]
438
- ds = ds.graph(eager_graph_dataset(opts, eo), conditions, eo.merge(:select=>select, :join_type=>eo[:join_type]||join_type, :qualify=>:deep, :from_self_alias=>eo[:from_self_alias]), &graph_block)
438
+ ds = ds.graph(eager_graph_dataset(opts, eo), conditions, Hash[eo].merge!(:select=>select, :join_type=>eo[:join_type]||join_type, :qualify=>:deep, :from_self_alias=>eo[:from_self_alias]), &graph_block)
439
439
  ds
440
440
  end
441
441
 
@@ -72,7 +72,7 @@ module Sequel
72
72
 
73
73
  # Return a sorted array of columns for use as a hash key.
74
74
  def prepared_columns(cols)
75
- RUBY_VERSION >= '1.9' ? cols.sort : cols.sort_by{|c| c.to_s}
75
+ RUBY_VERSION >= '1.9' ? cols.sort : cols.sort_by(&:to_s)
76
76
  end
77
77
 
78
78
  # Return a prepared statement that can be used to delete a row from this model's dataset.
@@ -194,7 +194,7 @@ module Sequel
194
194
  # Use a prepared statement to update this model's columns in the database.
195
195
  def _update_without_checking(columns)
196
196
  if use_prepared_statements_for?(:update)
197
- model.send(:prepared_update, columns.keys).call(columns.merge(pk_hash))
197
+ model.send(:prepared_update, columns.keys).call(Hash[columns].merge!(pk_hash))
198
198
  else
199
199
  super
200
200
  end
@@ -57,7 +57,7 @@ module Sequel
57
57
  # of free columns.
58
58
  def before_create
59
59
  if v = model.prepared_statements_column_defaults
60
- @values = v.merge(values)
60
+ @values = Hash[v].merge!(values)
61
61
  end
62
62
  super
63
63
  end
@@ -36,8 +36,8 @@ module Sequel
36
36
  # # Register custom serializer/deserializer pair, if desired
37
37
  # require 'sequel/plugins/serialization'
38
38
  # Sequel::Plugins::Serialization.register_format(:reverse,
39
- # lambda{|v| v.reverse},
40
- # lambda{|v| v.reverse})
39
+ # lambda(&:reverse),
40
+ # lambda(&:reverse))
41
41
  #
42
42
  # class User < Sequel::Model
43
43
  # # Built-in format support when loading the plugin
@@ -51,7 +51,7 @@ module Sequel
51
51
  # serialize_attributes :reverse, :password
52
52
  #
53
53
  # # Use a custom serializer/deserializer pair without registering
54
- # serialize_attributes [lambda{|v| v.reverse}, lambda{|v| v.reverse}], :password
54
+ # serialize_attributes [lambda(&:reverse), lambda(&:reverse)], :password
55
55
  # end
56
56
  # user = User.create
57
57
  # user.permissions = { :global => 'read-only' }
@@ -106,7 +106,7 @@ module Sequel
106
106
  end
107
107
  end
108
108
  end)
109
- register_format(:yaml, lambda{|v| v.to_yaml}, lambda{|v| YAML.load(v)})
109
+ register_format(:yaml, lambda(&:to_yaml), lambda{|v| YAML.load(v)})
110
110
  register_format(:json, lambda{|v| Sequel.object_to_json(v)}, lambda{|v| Sequel.parse_json(v)})
111
111
 
112
112
  module ClassMethods
@@ -129,7 +129,7 @@ module Sequel
129
129
  def serialize_attributes(format, *columns)
130
130
  if format.is_a?(Symbol)
131
131
  unless format = REGISTERED_FORMATS[format]
132
- raise(Error, "Unsupported serialization format: #{format} (valid formats: #{REGISTERED_FORMATS.keys.map{|k| k.inspect}.join})")
132
+ raise(Error, "Unsupported serialization format: #{format} (valid formats: #{REGISTERED_FORMATS.keys.map(&:inspect).join})")
133
133
  end
134
134
  end
135
135
  serializer, deserializer = format
@@ -212,7 +212,7 @@ module Sequel
212
212
  # Dup the deserialized values when duping model instance.
213
213
  def initialize_copy(other)
214
214
  super
215
- @deserialized_values = other.deserialized_values.dup
215
+ @deserialized_values = Hash[other.deserialized_values]
216
216
  self
217
217
  end
218
218
 
@@ -58,7 +58,7 @@ module Sequel
58
58
  def initialize_copy(other)
59
59
  super
60
60
  if o = other.instance_variable_get(:@original_deserialized_values)
61
- @original_deserialized_values = o.dup
61
+ @original_deserialized_values = Hash[o]
62
62
  end
63
63
  self
64
64
  end
@@ -33,7 +33,9 @@ module Sequel
33
33
  ds = ds.server?(server)
34
34
  ds
35
35
  end
36
- eo = eo.merge(:eager_block=>set_server)
36
+ eo = Hash[eo]
37
+ eo[:eager_block] = set_server
38
+ eo
37
39
  end
38
40
 
39
41
  super
@@ -59,7 +59,7 @@ module Sequel
59
59
  # # and :key_map taking a class object and returning the column
60
60
  # # value to use
61
61
  # Employee.plugin :single_table_inheritance, :type,
62
- # :model_map=>proc{|v| v.reverse},
62
+ # :model_map=>proc(&:reverse),
63
63
  # :key_map=>proc{|klass| klass.name.reverse}
64
64
  #
65
65
  # # You can use the same class for multiple values.
@@ -147,27 +147,19 @@ module Sequel
147
147
  # This defaults to a lookup in the key map.
148
148
  attr_reader :sti_key_chooser
149
149
 
150
+ Plugins.inherited_instance_variables(self, :@sti_dataset=>nil, :@sti_key=>nil, :@sti_key_map=>nil, :@sti_model_map=>nil, :@sti_key_chooser=>nil)
151
+
150
152
  # Copy the necessary attributes to the subclasses, and filter the
151
153
  # subclass's dataset based on the sti_kep_map entry for the class.
152
154
  def inherited(subclass)
153
155
  super
154
- sk = sti_key
155
- sd = sti_dataset
156
- skm = sti_key_map
157
- smm = sti_model_map
158
- skc = sti_key_chooser
159
- key = Array(skm[subclass]).dup
156
+ key = Array(sti_key_map[subclass]).dup
160
157
  sti_subclass_added(key)
161
158
  rp = dataset.row_proc
162
- subclass.set_dataset(sd.filter(SQL::QualifiedIdentifier.new(table_name, sk)=>key), :inherited=>true)
159
+ subclass.set_dataset(sti_dataset.filter(SQL::QualifiedIdentifier.new(sti_dataset.first_source_alias, sti_key)=>key), :inherited=>true)
163
160
  subclass.instance_eval do
164
161
  dataset.row_proc = rp
165
- @sti_key = sk
166
162
  @sti_key_array = key
167
- @sti_dataset = sd
168
- @sti_key_map = skm
169
- @sti_model_map = smm
170
- @sti_key_chooser = skc
171
163
  self.simple_table = nil
172
164
  end
173
165
  end
@@ -111,7 +111,7 @@ module Sequel
111
111
  def to_hash(key_column = nil, value_column = nil)
112
112
  if key_column.nil? && value_column.nil?
113
113
  if @static_cache_frozen
114
- return cache.dup
114
+ return Hash[cache]
115
115
  else
116
116
  key_column = primary_key
117
117
  end
@@ -198,7 +198,7 @@ module Sequel
198
198
  if @static_cache_frozen
199
199
  o
200
200
  elsif o
201
- call(o.values.dup)
201
+ call(Hash[o.values])
202
202
  end
203
203
  end
204
204
  end
@@ -53,7 +53,7 @@ module Sequel
53
53
  name = opts[:name]
54
54
  if !associations.include?(name) && retrieved_by && !frozen?
55
55
  begin
56
- retrieved_by.send(:eager_load, retrieved_with.reject{|o| o.frozen?}, name=>{})
56
+ retrieved_by.send(:eager_load, retrieved_with.reject(&:frozen?), name=>{})
57
57
  rescue Sequel::UndefinedAssociation
58
58
  # This can happen if class table inheritance is used and the association
59
59
  # is only defined in a subclass. This particular instance can use the
@@ -43,7 +43,7 @@ module Sequel
43
43
  children = chi.fetch(:name, :children)
44
44
 
45
45
  par[:reciprocal] = children
46
- chi[:recripocal] = parent
46
+ chi[:reciprocal] = parent
47
47
 
48
48
  model.many_to_one parent, par
49
49
  model.one_to_many children, chi
@@ -182,8 +182,8 @@ module Sequel
182
182
  blk = if (i = opts[:if]) || (am = opts[:allow_missing]) || (an = opts[:allow_nil]) || (ab = opts[:allow_blank])
183
183
  proc do |o,a,v|
184
184
  next if i && !validation_if_proc(o, i)
185
- next if an && Array(v).all?{|x| x.nil?}
186
- next if ab && Array(v).all?{|x| x.blank?}
185
+ next if an && Array(v).all?(&:nil?)
186
+ next if ab && Array(v).all?(&:blank?)
187
187
  next if am && Array(a).all?{|x| !o.values.has_key?(x)}
188
188
  block.call(o,a,v)
189
189
  end
@@ -156,7 +156,7 @@ module Sequel
156
156
  def validates_schema_types(atts=keys, opts=OPTS)
157
157
  Array(atts).each do |k|
158
158
  if type = schema_type_class(k)
159
- validates_type(type, k, {:allow_nil=>true}.merge(opts))
159
+ validates_type(type, k, {:allow_nil=>true}.merge!(opts))
160
160
  end
161
161
  end
162
162
  end
@@ -224,7 +224,7 @@ module Sequel
224
224
  def validates_unique(*atts)
225
225
  opts = default_validation_helpers_options(:unique)
226
226
  if atts.last.is_a?(Hash)
227
- opts = opts.merge(atts.pop)
227
+ opts = Hash[opts].merge!(atts.pop)
228
228
  end
229
229
  message = validation_error_message(opts[:message])
230
230
  where = opts[:where]
@@ -237,7 +237,7 @@ module Sequel
237
237
  where.call(ds, self, arr)
238
238
  else
239
239
  vals = arr.map{|x| get_column_value(x)}
240
- next if vals.any?{|v| v.nil?}
240
+ next if vals.any?(&:nil?)
241
241
  ds.where(arr.zip(vals))
242
242
  end
243
243
  ds = yield(ds) if block_given?
@@ -279,7 +279,7 @@ module Sequel
279
279
  # Merge the given options with the default options for the given type
280
280
  # and call validatable_attributes with the merged options.
281
281
  def validatable_attributes_for_type(type, atts, opts, &block)
282
- validatable_attributes(atts, default_validation_helpers_options(type).merge(opts), &block)
282
+ validatable_attributes(atts, Hash[default_validation_helpers_options(type)].merge!(opts), &block)
283
283
  end
284
284
 
285
285
  # The validation error message to use, as a string. If message
@@ -113,17 +113,17 @@ module Sequel
113
113
  module XmlSerializer
114
114
  module ClassMethods
115
115
  # Proc that camelizes the input string, used for the :camelize option
116
- CAMELIZE = proc{|s| s.camelize}
116
+ CAMELIZE = proc(&:camelize)
117
117
 
118
118
  # Proc that dasherizes the input string, used for the :dasherize option
119
- DASHERIZE = proc{|s| s.dasherize}
119
+ DASHERIZE = proc(&:dasherize)
120
120
 
121
121
  # Proc that returns the input string as is, used if
122
122
  # no :name_proc, :dasherize, or :camelize option is used.
123
123
  IDENTITY = proc{|s| s}
124
124
 
125
125
  # Proc that underscores the input string, used for the :underscore option
126
- UNDERSCORE = proc{|s| s.underscore}
126
+ UNDERSCORE = proc(&:underscore)
127
127
 
128
128
  # Return an array of instances of this class based on
129
129
  # the provided XML.
data/lib/sequel/sql.rb CHANGED
@@ -1378,7 +1378,7 @@ module Sequel
1378
1378
 
1379
1379
  # Return a new function call with the given opts merged into the current opts.
1380
1380
  def with_opts(opts)
1381
- self.class.new!(name, args, @opts.merge(opts))
1381
+ self.class.new!(name, args, Hash[@opts].merge!(opts))
1382
1382
  end
1383
1383
  end
1384
1384
 
@@ -3,7 +3,7 @@ module Sequel
3
3
  MAJOR = 4
4
4
  # The minor version of Sequel. Bumped for every non-patch level
5
5
  # release, generally around once a month.
6
- MINOR = 21
6
+ MINOR = 22
7
7
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
8
8
  # releases that fix regressions from previous versions.
9
9
  TINY = 0
@@ -2162,6 +2162,23 @@ describe 'PostgreSQL array handling' do
2162
2162
  end
2163
2163
  end
2164
2164
 
2165
+ specify 'convert ruby array :default values' do
2166
+ @db.create_table!(:items) do
2167
+ column :n, 'integer[]', :default=>[]
2168
+ end
2169
+ @ds.insert
2170
+ @ds.count.should == 1
2171
+ if @native
2172
+ rs = @ds.all
2173
+ rs.should == [{:n=>[]}]
2174
+ rs.first.values.each{|v| v.should_not be_a_kind_of(Array)}
2175
+ rs.first.values.each{|v| v.to_a.should be_a_kind_of(Array)}
2176
+ @ds.delete
2177
+ @ds.insert(rs.first)
2178
+ @ds.all.should == rs
2179
+ end
2180
+ end
2181
+
2165
2182
  specify 'insert and retrieve custom array types' do
2166
2183
  int2vector = Class.new do
2167
2184
  attr_reader :array
@@ -33,7 +33,7 @@ describe "ConnectionPool options" do
33
33
  cpool = Sequel::ConnectionPool.get_pool(mock_db.call, {:max_connections=>'5', :pool_timeout=>'3', :pool_sleep_time=>'0.01'})
34
34
  cpool.max_size.should == 5
35
35
  cpool.instance_variable_get(:@timeout).should == 3
36
- cpool.instance_variable_get(:@sleep_time).should == 0.01
36
+ cpool.instance_variable_get(:@sleep_time).should == 0.01 unless cpool.class::USE_WAITER
37
37
  end
38
38
 
39
39
  specify "should raise an error unless size is positive" do
@@ -1758,6 +1758,17 @@ describe "Dataset#to_hash" do
1758
1758
  @d.to_hash(:b).should == {4 => {:a => 2, :b => 4}, 8 => {:a => 6, :b => 8}, 12 => {:a => 10, :b => 12}}
1759
1759
  @d.to_hash([:a, :b]).should == {[2, 4] => {:a => 2, :b => 4}, [6, 8] => {:a => 6, :b => 8}, [10, 12] => {:a => 10, :b => 12}}
1760
1760
  end
1761
+
1762
+ specify "should handle a single composite key when using a row_proc" do
1763
+ c = @d.row_proc = Class.new do
1764
+ def self.call(h); new(h); end
1765
+ def initialize(h); @h = h; end
1766
+ def [](k) @h[k]; end
1767
+ def h; @h; end
1768
+ def ==(o) @h == o.h; end
1769
+ end
1770
+ @d.to_hash([:a, :b]).should == {[1, 2] => c.call(:a => 1, :b => 2), [3, 4] => c.call(:a => 3, :b => 4), [5, 6] => c.call(:a => 5, :b => 6)}
1771
+ end
1761
1772
  end
1762
1773
 
1763
1774
  describe "Dataset#to_hash_groups" do
@@ -1797,6 +1808,17 @@ describe "Dataset#to_hash_groups" do
1797
1808
  @d.to_hash_groups(:b).should == {4 => [{:a => 2, :b => 4}], 8 => [{:a => 6, :b => 8}, {:a => 14, :b => 8}], 12 => [{:a => 2, :b => 12}]}
1798
1809
  @d.to_hash_groups([:a, :b]).should == {[2, 4] => [{:a => 2, :b => 4}], [6, 8] => [{:a => 6, :b => 8}], [2, 12] => [{:a => 2, :b => 12}], [14, 8] => [{:a => 14, :b => 8}]}
1799
1810
  end
1811
+
1812
+ specify "should handle a single composite key when using a row_proc" do
1813
+ c = @d.row_proc = Class.new do
1814
+ def self.call(h); new(h); end
1815
+ def initialize(h); @h = h; end
1816
+ def [](k) @h[k]; end
1817
+ def h; @h; end
1818
+ def ==(o) @h == o.h; end
1819
+ end
1820
+ @d.to_hash_groups([:a, :b]).should == {[1, 2] => [c.call(:a => 1, :b => 2)], [3, 4] => [c.call(:a => 3, :b => 4)], [1, 6] => [c.call(:a => 1, :b => 6)], [7, 4] => [c.call(:a => 7, :b => 4)]}
1821
+ end
1800
1822
  end
1801
1823
 
1802
1824
  describe "Dataset#distinct" do