sequel 4.21.0 → 4.22.0

Sign up to get free protection for your applications and to get access to all the features.
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