sequel 4.47.0 → 4.48.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 (177) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +134 -0
  3. data/Rakefile +1 -1
  4. data/doc/release_notes/4.48.0.txt +293 -0
  5. data/lib/sequel/adapters/ado/access.rb +2 -1
  6. data/lib/sequel/adapters/do/postgres.rb +5 -2
  7. data/lib/sequel/adapters/ibmdb.rb +24 -7
  8. data/lib/sequel/adapters/jdbc.rb +36 -22
  9. data/lib/sequel/adapters/jdbc/db2.rb +12 -3
  10. data/lib/sequel/adapters/jdbc/derby.rb +4 -5
  11. data/lib/sequel/adapters/jdbc/oracle.rb +16 -2
  12. data/lib/sequel/adapters/jdbc/postgresql.rb +43 -18
  13. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +9 -7
  14. data/lib/sequel/adapters/jdbc/sqlserver.rb +11 -4
  15. data/lib/sequel/adapters/mock.rb +24 -19
  16. data/lib/sequel/adapters/mysql.rb +17 -16
  17. data/lib/sequel/adapters/mysql2.rb +4 -5
  18. data/lib/sequel/adapters/oracle.rb +5 -9
  19. data/lib/sequel/adapters/postgres.rb +89 -102
  20. data/lib/sequel/adapters/shared/db2.rb +22 -6
  21. data/lib/sequel/adapters/shared/mssql.rb +5 -4
  22. data/lib/sequel/adapters/shared/mysql.rb +75 -24
  23. data/lib/sequel/adapters/shared/postgres.rb +196 -94
  24. data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
  25. data/lib/sequel/adapters/shared/sqlite.rb +72 -82
  26. data/lib/sequel/adapters/sqlanywhere.rb +4 -1
  27. data/lib/sequel/adapters/sqlite.rb +5 -3
  28. data/lib/sequel/adapters/swift/postgres.rb +5 -2
  29. data/lib/sequel/adapters/tinytds.rb +0 -5
  30. data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
  31. data/lib/sequel/adapters/utils/pg_types.rb +2 -76
  32. data/lib/sequel/core.rb +2 -2
  33. data/lib/sequel/database/connecting.rb +5 -5
  34. data/lib/sequel/database/dataset.rb +6 -3
  35. data/lib/sequel/database/misc.rb +1 -1
  36. data/lib/sequel/database/query.rb +3 -0
  37. data/lib/sequel/database/schema_methods.rb +1 -1
  38. data/lib/sequel/dataset/actions.rb +18 -10
  39. data/lib/sequel/dataset/graph.rb +1 -1
  40. data/lib/sequel/dataset/misc.rb +1 -0
  41. data/lib/sequel/dataset/prepared_statements.rb +3 -3
  42. data/lib/sequel/dataset/query.rb +19 -8
  43. data/lib/sequel/extensions/core_extensions.rb +4 -1
  44. data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
  45. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -0
  46. data/lib/sequel/extensions/filter_having.rb +2 -0
  47. data/lib/sequel/extensions/freeze_datasets.rb +2 -0
  48. data/lib/sequel/extensions/from_block.rb +1 -1
  49. data/lib/sequel/extensions/graph_each.rb +2 -2
  50. data/lib/sequel/extensions/hash_aliases.rb +2 -0
  51. data/lib/sequel/extensions/identifier_mangling.rb +0 -7
  52. data/lib/sequel/extensions/meta_def.rb +2 -0
  53. data/lib/sequel/extensions/migration.rb +6 -6
  54. data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
  55. data/lib/sequel/extensions/pagination.rb +1 -1
  56. data/lib/sequel/extensions/pg_array.rb +207 -130
  57. data/lib/sequel/extensions/pg_hstore.rb +38 -20
  58. data/lib/sequel/extensions/pg_inet.rb +18 -6
  59. data/lib/sequel/extensions/pg_interval.rb +19 -12
  60. data/lib/sequel/extensions/pg_json.rb +25 -14
  61. data/lib/sequel/extensions/pg_json_ops.rb +2 -2
  62. data/lib/sequel/extensions/pg_range.rb +133 -100
  63. data/lib/sequel/extensions/pg_range_ops.rb +4 -3
  64. data/lib/sequel/extensions/pg_row.rb +68 -39
  65. data/lib/sequel/extensions/pg_row_ops.rb +11 -5
  66. data/lib/sequel/extensions/query_literals.rb +2 -0
  67. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +2 -0
  68. data/lib/sequel/extensions/s.rb +1 -1
  69. data/lib/sequel/extensions/schema_dumper.rb +24 -24
  70. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +3 -1
  71. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +83 -0
  72. data/lib/sequel/extensions/set_overrides.rb +2 -2
  73. data/lib/sequel/extensions/string_agg.rb +0 -1
  74. data/lib/sequel/extensions/symbol_aref.rb +0 -4
  75. data/lib/sequel/model.rb +25 -57
  76. data/lib/sequel/model/associations.rb +14 -5
  77. data/lib/sequel/model/base.rb +96 -32
  78. data/lib/sequel/plugins/association_pks.rb +73 -46
  79. data/lib/sequel/plugins/association_proxies.rb +1 -1
  80. data/lib/sequel/plugins/auto_validations.rb +6 -2
  81. data/lib/sequel/plugins/boolean_readers.rb +1 -1
  82. data/lib/sequel/plugins/caching.rb +19 -13
  83. data/lib/sequel/plugins/class_table_inheritance.rb +19 -10
  84. data/lib/sequel/plugins/column_conflicts.rb +7 -2
  85. data/lib/sequel/plugins/column_select.rb +1 -1
  86. data/lib/sequel/plugins/csv_serializer.rb +8 -8
  87. data/lib/sequel/plugins/defaults_setter.rb +10 -0
  88. data/lib/sequel/plugins/eager_each.rb +1 -1
  89. data/lib/sequel/plugins/force_encoding.rb +2 -2
  90. data/lib/sequel/plugins/hook_class_methods.rb +9 -12
  91. data/lib/sequel/plugins/identifier_columns.rb +2 -0
  92. data/lib/sequel/plugins/instance_filters.rb +3 -1
  93. data/lib/sequel/plugins/instance_hooks.rb +17 -9
  94. data/lib/sequel/plugins/json_serializer.rb +17 -10
  95. data/lib/sequel/plugins/lazy_attributes.rb +8 -7
  96. data/lib/sequel/plugins/modification_detection.rb +3 -0
  97. data/lib/sequel/plugins/nested_attributes.rb +5 -1
  98. data/lib/sequel/plugins/pg_array_associations.rb +5 -0
  99. data/lib/sequel/plugins/prepared_statements.rb +1 -0
  100. data/lib/sequel/plugins/rcte_tree.rb +4 -4
  101. data/lib/sequel/plugins/serialization.rb +3 -10
  102. data/lib/sequel/plugins/single_table_inheritance.rb +2 -2
  103. data/lib/sequel/plugins/split_values.rb +6 -5
  104. data/lib/sequel/plugins/static_cache.rb +31 -25
  105. data/lib/sequel/plugins/subset_conditions.rb +3 -1
  106. data/lib/sequel/plugins/table_select.rb +1 -1
  107. data/lib/sequel/plugins/touch.rb +2 -1
  108. data/lib/sequel/plugins/validation_class_methods.rb +5 -6
  109. data/lib/sequel/plugins/validation_helpers.rb +2 -4
  110. data/lib/sequel/plugins/xml_serializer.rb +4 -4
  111. data/lib/sequel/sql.rb +2 -2
  112. data/lib/sequel/version.rb +1 -1
  113. data/spec/adapters/db2_spec.rb +115 -14
  114. data/spec/adapters/mysql_spec.rb +78 -28
  115. data/spec/adapters/oracle_spec.rb +24 -24
  116. data/spec/adapters/postgres_spec.rb +38 -24
  117. data/spec/adapters/sqlanywhere_spec.rb +88 -86
  118. data/spec/adapters/sqlite_spec.rb +29 -24
  119. data/spec/core/connection_pool_spec.rb +17 -0
  120. data/spec/core/database_spec.rb +6 -0
  121. data/spec/core/dataset_spec.rb +46 -36
  122. data/spec/core/schema_spec.rb +16 -0
  123. data/spec/core/spec_helper.rb +1 -0
  124. data/spec/core_extensions_spec.rb +6 -2
  125. data/spec/extensions/active_model_spec.rb +1 -1
  126. data/spec/extensions/arbitrary_servers_spec.rb +1 -1
  127. data/spec/extensions/association_pks_spec.rb +34 -2
  128. data/spec/extensions/auto_literal_strings_spec.rb +5 -1
  129. data/spec/extensions/auto_validations_spec.rb +2 -0
  130. data/spec/extensions/boolean_readers_spec.rb +1 -1
  131. data/spec/extensions/boolean_subsets_spec.rb +1 -1
  132. data/spec/extensions/class_table_inheritance_spec.rb +48 -2
  133. data/spec/extensions/column_conflicts_spec.rb +11 -0
  134. data/spec/extensions/connection_validator_spec.rb +1 -1
  135. data/spec/extensions/dataset_associations_spec.rb +8 -8
  136. data/spec/extensions/defaults_setter_spec.rb +1 -1
  137. data/spec/extensions/filter_having_spec.rb +5 -3
  138. data/spec/extensions/hash_aliases_spec.rb +3 -1
  139. data/spec/extensions/identifier_columns_spec.rb +3 -1
  140. data/spec/extensions/implicit_subquery_spec.rb +4 -2
  141. data/spec/extensions/json_serializer_spec.rb +18 -0
  142. data/spec/extensions/lazy_attributes_spec.rb +3 -3
  143. data/spec/extensions/meta_def_spec.rb +9 -0
  144. data/spec/extensions/migration_spec.rb +3 -3
  145. data/spec/extensions/nested_attributes_spec.rb +14 -3
  146. data/spec/extensions/no_auto_literal_strings_spec.rb +8 -4
  147. data/spec/extensions/pg_array_associations_spec.rb +29 -18
  148. data/spec/extensions/pg_array_spec.rb +44 -25
  149. data/spec/extensions/pg_hstore_spec.rb +10 -0
  150. data/spec/extensions/pg_inet_spec.rb +26 -0
  151. data/spec/extensions/pg_interval_spec.rb +20 -0
  152. data/spec/extensions/pg_json_spec.rb +24 -0
  153. data/spec/extensions/pg_range_spec.rb +98 -14
  154. data/spec/extensions/pg_row_spec.rb +14 -4
  155. data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
  156. data/spec/extensions/query_literals_spec.rb +3 -1
  157. data/spec/extensions/schema_dumper_spec.rb +96 -98
  158. data/spec/extensions/sequel_3_dataset_methods_spec.rb +10 -6
  159. data/spec/extensions/sequel_4_dataset_methods_spec.rb +121 -0
  160. data/spec/extensions/single_table_inheritance_spec.rb +1 -1
  161. data/spec/extensions/spec_helper.rb +7 -1
  162. data/spec/extensions/static_cache_spec.rb +75 -24
  163. data/spec/extensions/string_agg_spec.rb +1 -1
  164. data/spec/extensions/touch_spec.rb +9 -0
  165. data/spec/extensions/validation_helpers_spec.rb +9 -3
  166. data/spec/extensions/whitelist_security_spec.rb +26 -0
  167. data/spec/integration/dataset_test.rb +45 -44
  168. data/spec/integration/plugin_test.rb +20 -0
  169. data/spec/integration/prepared_statement_test.rb +3 -0
  170. data/spec/integration/schema_test.rb +21 -1
  171. data/spec/integration/transaction_test.rb +40 -40
  172. data/spec/model/class_dataset_methods_spec.rb +14 -4
  173. data/spec/model/dataset_methods_spec.rb +12 -3
  174. data/spec/model/model_spec.rb +8 -0
  175. metadata +6 -4
  176. data/spec/adapters/firebird_spec.rb +0 -405
  177. data/spec/adapters/informix_spec.rb +0 -100
@@ -26,6 +26,7 @@ module Sequel
26
26
  # * Model.each
27
27
  # * Model.count (without an argument or block)
28
28
  # * Model.map
29
+ # * Model.as_hash
29
30
  # * Model.to_hash
30
31
  # * Model.to_hash_groups
31
32
  #
@@ -127,41 +128,46 @@ module Sequel
127
128
  Plugins.inherited_instance_variables(self, :@static_cache_frozen=>nil)
128
129
 
129
130
  # Use the cache instead of a query to get the results.
130
- def to_hash(key_column = nil, value_column = nil)
131
- if key_column.nil? && value_column.nil?
132
- if @static_cache_frozen
133
- return Hash[cache]
134
- else
135
- key_column = primary_key
131
+ def as_hash(key_column = nil, value_column = nil, opts = OPTS)
132
+ if key_column.nil? && value_column.nil?
133
+ if @static_cache_frozen && !opts[:hash]
134
+ return Hash[cache]
135
+ else
136
+ key_column = primary_key
137
+ end
136
138
  end
137
- end
138
139
 
139
- h = {}
140
- if value_column
141
- if value_column.is_a?(Array)
142
- if key_column.is_a?(Array)
143
- @all.each{|r| h[r.values.values_at(*key_column)] = r.values.values_at(*value_column)}
140
+ h = opts[:hash] || {}
141
+ if value_column
142
+ if value_column.is_a?(Array)
143
+ if key_column.is_a?(Array)
144
+ @all.each{|r| h[r.values.values_at(*key_column)] = r.values.values_at(*value_column)}
145
+ else
146
+ @all.each{|r| h[r[key_column]] = r.values.values_at(*value_column)}
147
+ end
144
148
  else
145
- @all.each{|r| h[r[key_column]] = r.values.values_at(*value_column)}
149
+ if key_column.is_a?(Array)
150
+ @all.each{|r| h[r.values.values_at(*key_column)] = r[value_column]}
151
+ else
152
+ @all.each{|r| h[r[key_column]] = r[value_column]}
153
+ end
146
154
  end
155
+ elsif key_column.is_a?(Array)
156
+ @all.each{|r| h[r.values.values_at(*key_column)] = static_cache_object(r)}
147
157
  else
148
- if key_column.is_a?(Array)
149
- @all.each{|r| h[r.values.values_at(*key_column)] = r[value_column]}
150
- else
151
- @all.each{|r| h[r[key_column]] = r[value_column]}
152
- end
158
+ @all.each{|r| h[r[key_column]] = static_cache_object(r)}
153
159
  end
154
- elsif key_column.is_a?(Array)
155
- @all.each{|r| h[r.values.values_at(*key_column)] = static_cache_object(r)}
156
- else
157
- @all.each{|r| h[r[key_column]] = static_cache_object(r)}
160
+ h
158
161
  end
159
- h
162
+
163
+ # Alias of as_hash for backwards compatibility.
164
+ def to_hash(*a)
165
+ as_hash(*a)
160
166
  end
161
167
 
162
168
  # Use the cache instead of a query to get the results
163
- def to_hash_groups(key_column, value_column = nil)
164
- h = {}
169
+ def to_hash_groups(key_column, value_column = nil, opts = OPTS)
170
+ h = opts[:hash] || {}
165
171
  if value_column
166
172
  if value_column.is_a?(Array)
167
173
  if key_column.is_a?(Array)
@@ -13,7 +13,9 @@ module Sequel
13
13
  # Album.plugin :subset_conditions
14
14
  #
15
15
  # # This will now create a published_conditions method
16
- # Album.subset :published, :published => true
16
+ # Album.dataset_module do
17
+ # subset :published, :published => true
18
+ # end
17
19
  #
18
20
  # Album.where(Album.published_conditions).sql
19
21
  # # SELECT * FROM albums WHERE (published IS TRUE)
@@ -32,7 +32,7 @@ module Sequel
32
32
  # has no explicit selection, select table.* from that table.
33
33
  def convert_input_dataset(ds)
34
34
  ds = super
35
- if !ds.opts[:select] && (from = ds.opts[:from]) && from.length == 1 && !ds.opts[:join]
35
+ if !ds.opts[:select] && (from = ds.opts[:from]) && from.length == 1 && !ds.opts[:join] # SEQUEL5: Only !ds.opts[:select]
36
36
  ds = ds.select_all(ds.first_source)
37
37
  end
38
38
  ds
@@ -136,10 +136,11 @@ module Sequel
136
136
  # Can't update all values at once, so update each instance individually.
137
137
  # Instead if doing a simple save, update via the instance's dataset,
138
138
  # to avoid going into an infinite loop in some cases.
139
- send(r[:name]).each{|x| x.this.update(column=>touch_association_value)}
139
+ send(assoc).each{|x| x.this.update(column=>touch_association_value)}
140
140
  else
141
141
  # Update all values at once for performance reasons.
142
142
  ds.update(column=>touch_association_value)
143
+ associations.delete(assoc)
143
144
  end
144
145
  end
145
146
  end
@@ -1,8 +1,6 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Sequel
4
- extension :blank
5
-
6
4
  module Plugins
7
5
  # Sequel's built-in validation_class_methods plugin adds backwards compatibility
8
6
  # for the legacy class-level validation methods (e.g. validates_presence_of :column).
@@ -11,7 +9,7 @@ module Sequel
11
9
  # as it is less complex and more flexible. However, this plugin provides reflection
12
10
  # support, since it is class-level, while the instance-level validation_helpers
13
11
  # plugin does not.
14
- #
12
+ #
15
13
  # Usage:
16
14
  #
17
15
  # # Add the validation class methods to all model subclasses (called before loading subclasses)
@@ -118,7 +116,7 @@ module Sequel
118
116
  validations.each do |att, procs|
119
117
  v = case att
120
118
  when Array
121
- att.collect{|a| o.get_column_value(a)}
119
+ att.map{|a| o.get_column_value(a)}
122
120
  else
123
121
  o.get_column_value(att)
124
122
  end
@@ -194,11 +192,12 @@ module Sequel
194
192
  # :tag :: The tag to use for this validation.
195
193
  def validates_each(*atts, &block)
196
194
  opts = extract_options!(atts)
195
+ blank_meth = db.method(:blank_object?).to_proc
197
196
  blk = if (i = opts[:if]) || (am = opts[:allow_missing]) || (an = opts[:allow_nil]) || (ab = opts[:allow_blank])
198
197
  proc do |o,a,v|
199
198
  next if i && !validation_if_proc(o, i)
200
199
  next if an && Array(v).all?(&:nil?)
201
- next if ab && Array(v).all?(&:blank?)
200
+ next if ab && Array(v).all?(&blank_meth)
202
201
  next if am && Array(a).all?{|x| !o.values.has_key?(x)}
203
202
  block.call(o,a,v)
204
203
  end
@@ -317,7 +316,7 @@ module Sequel
317
316
  reflect_validation(:presence, opts, atts)
318
317
  atts << opts
319
318
  validates_each(*atts) do |o, a, v|
320
- o.errors.add(a, opts[:message]) if v.blank? && v != false
319
+ o.errors.add(a, opts[:message]) if db.send(:blank_object?, v) && v != false
321
320
  end
322
321
  end
323
322
 
@@ -19,9 +19,7 @@ module Sequel
19
19
  # atts :: Single attribute symbol or an array of attribute symbols specifying the
20
20
  # attribute(s) to validate.
21
21
  # Options:
22
- # :allow_blank :: Whether to skip the validation if the value is blank. You should
23
- # make sure all objects respond to blank if you use this option, which you can do by:
24
- # Sequel.extension :blank
22
+ # :allow_blank :: Whether to skip the validation if the value is blank.
25
23
  # :allow_missing :: Whether to skip the validation if the attribute isn't a key in the
26
24
  # values hash. This is different from allow_nil, because Sequel only sends the attributes
27
25
  # in the values when doing an insert or update. If the attribute is not present, Sequel
@@ -284,7 +282,7 @@ module Sequel
284
282
  next if am && !values.has_key?(a)
285
283
  v = from_values ? values[a] : get_column_value(a)
286
284
  next if an && v.nil?
287
- next if ab && v.respond_to?(:blank?) && v.blank?
285
+ next if ab && model.db.send(:blank_object?, v)
288
286
  if message = yield(a, v, m)
289
287
  errors.add(a, message)
290
288
  end
@@ -158,7 +158,7 @@ module Sequel
158
158
  opts[:builder]
159
159
  else
160
160
  builder_opts = if opts[:builder_opts]
161
- opts[:builder_opts]
161
+ Hash[opts[:builder_opts]]
162
162
  else
163
163
  {}
164
164
  end
@@ -234,10 +234,10 @@ module Sequel
234
234
  if assocs = opts[:associations]
235
235
  assocs = case assocs
236
236
  when Symbol
237
- {assocs=>{}}
237
+ {assocs=>OPTS}
238
238
  when Array
239
239
  assocs_tmp = {}
240
- assocs.each{|v| assocs_tmp[v] = {}}
240
+ assocs.each{|v| assocs_tmp[v] = OPTS}
241
241
  assocs_tmp
242
242
  when Hash
243
243
  assocs
@@ -347,7 +347,7 @@ module Sequel
347
347
  cols.each do |c|
348
348
  attrs = {}
349
349
  if types
350
- attrs[:type] = db_schema.fetch(c, {})[:type]
350
+ attrs[:type] = db_schema.fetch(c, OPTS)[:type]
351
351
  end
352
352
  v = vals[c]
353
353
  if v.nil?
@@ -1150,7 +1150,7 @@ module Sequel
1150
1150
  when BooleanExpression
1151
1151
  case op = ce.op
1152
1152
  when :AND, :OR
1153
- BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.collect{|a| BooleanExpression.invert(a)})
1153
+ BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.map{|a| BooleanExpression.invert(a)})
1154
1154
  else
1155
1155
  BooleanExpression.new(OPERTATOR_INVERSIONS[op], *ce.args.dup)
1156
1156
  end
@@ -1764,7 +1764,7 @@ module Sequel
1764
1764
  def self.like(l, *ces)
1765
1765
  l, lre, lci = like_element(l)
1766
1766
  lci = (ces.last.is_a?(Hash) ? ces.pop : {})[:case_insensitive] ? true : lci
1767
- ces.collect! do |ce|
1767
+ ces.map! do |ce|
1768
1768
  r, rre, rci = like_element(ce)
1769
1769
  BooleanExpression.new(LIKE_MAP[[lre||rre, lci||rci]], l, r)
1770
1770
  end
@@ -5,7 +5,7 @@ module Sequel
5
5
  MAJOR = 4
6
6
  # The minor version of Sequel. Bumped for every non-patch level
7
7
  # release, generally around once a month.
8
- MINOR = 47
8
+ MINOR = 48
9
9
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
10
10
  # releases that fix regressions from previous versions.
11
11
  TINY = 0
@@ -28,9 +28,47 @@ describe Sequel::Database do
28
28
  end
29
29
  end
30
30
 
31
+ # SEQUEL5: Remove
31
32
  describe "Simple Dataset operations" do
32
33
  before(:all) do
33
- Sequel::DB2.use_clob_as_blob = true
34
+ deprecated do
35
+ Sequel::DB2.use_clob_as_blob = true
36
+ end
37
+ DB.send(:remove_instance_variable, :@use_clob_as_blob) if DB.send(:instance_variable_defined?, :@use_clob_as_blob)
38
+ DB.create_table!(:items) do
39
+ Integer :id, :primary_key => true
40
+ Integer :number
41
+ column :bin_string, 'varchar(20) for bit data'
42
+ column :bin_clob, 'clob'
43
+ end
44
+ @ds = DB[:items]
45
+ end
46
+ after(:each) do
47
+ @ds.delete
48
+ end
49
+ after(:all) do
50
+ deprecated do
51
+ Sequel::DB2.use_clob_as_blob = false
52
+ end
53
+ DB.send(:remove_instance_variable, :@use_clob_as_blob) if DB.send(:instance_variable_defined?, :@use_clob_as_blob)
54
+ DB.drop_table(:items)
55
+ end
56
+
57
+ it "should insert with a primary key specified" do
58
+ @ds.insert(:id => 1, :number => 10)
59
+ @ds.insert(:id => 100, :number => 20)
60
+ @ds.select_hash(:id, :number).must_equal(1 => 10, 100 => 20)
61
+ end
62
+
63
+ it "should insert into binary columns" do
64
+ @ds.insert(:id => 1, :bin_string => Sequel.blob("\1"), :bin_clob => Sequel.blob("\2"))
65
+ @ds.select(:bin_string, :bin_clob).first.must_equal(:bin_string => "\1", :bin_clob => "\2")
66
+ end
67
+ end
68
+
69
+ describe "Simple Dataset operations" do
70
+ before(:all) do
71
+ DB.use_clob_as_blob = true
34
72
  DB.create_table!(:items) do
35
73
  Integer :id, :primary_key => true
36
74
  Integer :number
@@ -43,7 +81,7 @@ describe "Simple Dataset operations" do
43
81
  @ds.delete
44
82
  end
45
83
  after(:all) do
46
- Sequel::DB2.use_clob_as_blob = false
84
+ DB.use_clob_as_blob = false
47
85
  DB.drop_table(:items)
48
86
  end
49
87
 
@@ -88,6 +126,7 @@ describe Sequel::Database do
88
126
  end
89
127
  end
90
128
 
129
+ # SEQUEL5: remove
91
130
  describe "Sequel::IBMDB.convert_smallint_to_bool" do
92
131
  before do
93
132
  @db = DB
@@ -95,55 +134,117 @@ describe "Sequel::IBMDB.convert_smallint_to_bool" do
95
134
  @ds = @db[:booltest]
96
135
  end
97
136
  after do
137
+ deprecated do
138
+ Sequel::IBMDB.convert_smallint_to_bool = true
139
+ end
140
+ @db.drop_table(:booltest)
141
+ end
142
+
143
+ deprecated "should consider smallint datatypes as boolean if set, but not larger smallints" do
144
+ @db.schema(:booltest, :reload=>true).first.last[:type].must_equal :boolean
145
+ @db.schema(:booltest, :reload=>true).first.last[:db_type].must_match /smallint/i
146
+ Sequel::IBMDB.convert_smallint_to_bool = false
147
+ @db.schema(:booltest, :reload=>true).first.last[:type].must_equal :integer
148
+ @db.schema(:booltest, :reload=>true).first.last[:db_type].must_match /smallint/i
149
+ end
150
+
151
+ deprecated "should return smallints as bools and integers as integers when set" do
98
152
  Sequel::IBMDB.convert_smallint_to_bool = true
153
+ @ds.delete
154
+ @ds.insert(:b=>true, :i=>10)
155
+ @ds.all.must_equal [{:b=>true, :i=>10}]
156
+ @ds.delete
157
+ @ds.insert(:b=>false, :i=>0)
158
+ @ds.all.must_equal [{:b=>false, :i=>0}]
159
+ @ds.delete
160
+ @ds.insert(:b=>true, :i=>1)
161
+ @ds.all.must_equal [{:b=>true, :i=>1}]
162
+
163
+ @ds = @ds.with_convert_smallint_to_bool(false)
164
+ @ds.delete
165
+ @ds.insert(:b=>true, :i=>10)
166
+ @ds.all.must_equal [{:b=>1, :i=>10}]
167
+ end
168
+
169
+ deprecated "should return all smallints as integers when unset" do
170
+ Sequel::IBMDB.convert_smallint_to_bool = false
171
+ @ds.delete
172
+ @ds.insert(:b=>true, :i=>10)
173
+ @ds.all.must_equal [{:b=>1, :i=>10}]
174
+ @ds.delete
175
+ @ds.insert(:b=>false, :i=>0)
176
+ @ds.all.must_equal [{:b=>0, :i=>0}]
177
+
178
+ @ds.delete
179
+ @ds.insert(:b=>1, :i=>10)
180
+ @ds.all.must_equal [{:b=>1, :i=>10}]
181
+ @ds.delete
182
+ @ds.insert(:b=>0, :i=>0)
183
+ @ds.all.must_equal [{:b=>0, :i=>0}]
184
+
185
+ @ds = @ds.with_convert_smallint_to_bool(true)
186
+ @ds.delete
187
+ @ds.insert(:b=>true, :i=>10)
188
+ @ds.all.must_equal [{:b=>true, :i=>10}]
189
+ end
190
+ end if DB.adapter_scheme == :ibmdb
191
+
192
+ describe "Sequel::IBMDB::Database#convert_smallint_to_bool" do
193
+ before do
194
+ @db = DB
195
+ @db.create_table!(:booltest){column :b, 'smallint'; column :i, 'integer'}
196
+ @ds = @db[:booltest]
197
+ end
198
+ after do
199
+ @db.convert_smallint_to_bool = nil # SEQUEL5: true
99
200
  @db.drop_table(:booltest)
100
201
  end
101
202
 
102
203
  it "should consider smallint datatypes as boolean if set, but not larger smallints" do
103
204
  @db.schema(:booltest, :reload=>true).first.last[:type].must_equal :boolean
104
205
  @db.schema(:booltest, :reload=>true).first.last[:db_type].must_match /smallint/i
105
- Sequel::IBMDB.convert_smallint_to_bool = false
206
+ @db.convert_smallint_to_bool = false
106
207
  @db.schema(:booltest, :reload=>true).first.last[:type].must_equal :integer
107
208
  @db.schema(:booltest, :reload=>true).first.last[:db_type].must_match /smallint/i
108
209
  end
109
210
 
110
211
  it "should return smallints as bools and integers as integers when set" do
111
- Sequel::IBMDB.convert_smallint_to_bool = true
212
+ @db.convert_smallint_to_bool = true
112
213
  @ds.delete
113
- @ds << {:b=>true, :i=>10}
214
+ @ds.insert(:b=>true, :i=>10)
114
215
  @ds.all.must_equal [{:b=>true, :i=>10}]
115
216
  @ds.delete
116
- @ds << {:b=>false, :i=>0}
217
+ @ds.insert(:b=>false, :i=>0)
117
218
  @ds.all.must_equal [{:b=>false, :i=>0}]
118
219
  @ds.delete
119
- @ds << {:b=>true, :i=>1}
220
+ @ds.insert(:b=>true, :i=>1)
120
221
  @ds.all.must_equal [{:b=>true, :i=>1}]
121
222
 
122
223
  @ds = @ds.with_convert_smallint_to_bool(false)
123
224
  @ds.delete
124
- @ds << {:b=>true, :i=>10}
225
+ @ds.insert(:b=>true, :i=>10)
125
226
  @ds.all.must_equal [{:b=>1, :i=>10}]
126
227
  end
127
228
 
128
229
  it "should return all smallints as integers when unset" do
129
- Sequel::IBMDB.convert_smallint_to_bool = false
230
+ @db.convert_smallint_to_bool = false
130
231
  @ds.delete
131
- @ds << {:b=>true, :i=>10}
232
+ @ds.insert(:b=>true, :i=>10)
132
233
  @ds.all.must_equal [{:b=>1, :i=>10}]
133
234
  @ds.delete
134
- @ds << {:b=>false, :i=>0}
235
+ @ds.insert(:b=>false, :i=>0)
135
236
  @ds.all.must_equal [{:b=>0, :i=>0}]
136
237
 
137
238
  @ds.delete
138
- @ds << {:b=>1, :i=>10}
239
+ @ds.insert(:b=>1, :i=>10)
139
240
  @ds.all.must_equal [{:b=>1, :i=>10}]
140
241
  @ds.delete
141
- @ds << {:b=>0, :i=>0}
242
+ @ds.insert(:b=>0, :i=>0)
142
243
  @ds.all.must_equal [{:b=>0, :i=>0}]
143
244
 
144
245
  @ds = @ds.with_convert_smallint_to_bool(true)
145
246
  @ds.delete
146
- @ds << {:b=>true, :i=>10}
247
+ @ds.insert(:b=>true, :i=>10)
147
248
  @ds.all.must_equal [{:b=>true, :i=>10}]
148
249
  end
149
250
  end if DB.adapter_scheme == :ibmdb
@@ -121,30 +121,30 @@ if [:mysql, :mysql2].include?(DB.adapter_scheme)
121
121
  it "should return tinyint(1)s as bools and tinyint(4)s as integers when set" do
122
122
  @db.convert_tinyint_to_bool = true
123
123
  @ds.delete
124
- @ds << {:b=>true, :i=>10}
124
+ @ds.insert(:b=>true, :i=>10)
125
125
  @ds.all.must_equal [{:b=>true, :i=>10}]
126
126
  @ds.delete
127
- @ds << {:b=>false, :i=>0}
127
+ @ds.insert(:b=>false, :i=>0)
128
128
  @ds.all.must_equal [{:b=>false, :i=>0}]
129
129
  @ds.delete
130
- @ds << {:b=>true, :i=>1}
130
+ @ds.insert(:b=>true, :i=>1)
131
131
  @ds.all.must_equal [{:b=>true, :i=>1}]
132
132
  end
133
133
 
134
134
  it "should return all tinyints as integers when unset" do
135
135
  @db.convert_tinyint_to_bool = false
136
136
  @ds.delete
137
- @ds << {:b=>true, :i=>10}
137
+ @ds.insert(:b=>true, :i=>10)
138
138
  @ds.all.must_equal [{:b=>1, :i=>10}]
139
139
  @ds.delete
140
- @ds << {:b=>false, :i=>0}
140
+ @ds.insert(:b=>false, :i=>0)
141
141
  @ds.all.must_equal [{:b=>0, :i=>0}]
142
142
 
143
143
  @ds.delete
144
- @ds << {:b=>1, :i=>10}
144
+ @ds.insert(:b=>1, :i=>10)
145
145
  @ds.all.must_equal [{:b=>1, :i=>10}]
146
146
  @ds.delete
147
- @ds << {:b=>0, :i=>0}
147
+ @ds.insert(:b=>0, :i=>0)
148
148
  @ds.all.must_equal [{:b=>0, :i=>0}]
149
149
  end
150
150
 
@@ -155,7 +155,7 @@ if [:mysql, :mysql2].include?(DB.adapter_scheme)
155
155
  def convert_tinyint_to_bool?() false end #mysql2
156
156
  end
157
157
  ds.delete
158
- ds << {:b=>true, :i=>10}
158
+ ds.insert(:b=>true, :i=>10)
159
159
  ds.all.must_equal [{:b=>1, :i=>10}]
160
160
  @ds.all.must_equal [{:b=>true, :i=>10}]
161
161
  end
@@ -220,8 +220,8 @@ describe "A MySQL dataset" do
220
220
  end if false # SEQUEL5
221
221
 
222
222
  it "should support regexps" do
223
- @d << {:name => 'abc', :value => 1}
224
- @d << {:name => 'bcd', :value => 2}
223
+ @d.insert(:name => 'abc', :value => 1)
224
+ @d.insert(:name => 'bcd', :value => 2)
225
225
  @d.filter(:name => /bc/).count.must_equal 2
226
226
  @d.filter(:name => /^bc/).count.must_equal 1
227
227
  end
@@ -234,7 +234,7 @@ describe "A MySQL dataset" do
234
234
 
235
235
  it "should correctly literalize strings with comment backslashes in them" do
236
236
  @d.delete
237
- @d << {:name => ':\\'}
237
+ @d.insert(:name => ':\\')
238
238
 
239
239
  @d.first[:name].must_equal ':\\'
240
240
  end
@@ -297,6 +297,9 @@ describe "MySQL join expressions" do
297
297
  it "should raise error for :full_outer join requests." do
298
298
  lambda{@ds.join_table(:full_outer, :nodes)}.must_raise(Sequel::Error)
299
299
  end
300
+ it "should raise error for :natural_full join requests." do
301
+ lambda{@ds.join_table(:natural_full, :nodes)}.must_raise(Sequel::Error)
302
+ end
300
303
  it "should support natural left joins" do
301
304
  @ds.join_table(:natural_left, :nodes).sql.must_equal 'SELECT * FROM `nodes` NATURAL LEFT JOIN `nodes`'
302
305
  end
@@ -309,7 +312,7 @@ describe "MySQL join expressions" do
309
312
  it "should support natural right outer joins" do
310
313
  @ds.join_table(:natural_right_outer, :nodes).sql.must_equal 'SELECT * FROM `nodes` NATURAL RIGHT OUTER JOIN `nodes`'
311
314
  end
312
- it "should support natural inner joins" do
315
+ deprecated "should support natural inner joins" do
313
316
  @ds.join_table(:natural_inner, :nodes).sql.must_equal 'SELECT * FROM `nodes` NATURAL LEFT JOIN `nodes`'
314
317
  end
315
318
  it "should support cross joins" do
@@ -391,7 +394,7 @@ describe "A MySQL database" do
391
394
  @db.add_column :test2, :xyz, :text
392
395
 
393
396
  @db[:test2].columns.must_equal [:name, :value, :xyz]
394
- @db[:test2] << {:name => 'mmm', :value => 111, :xyz => '000'}
397
+ @db[:test2].insert(:name => 'mmm', :value => 111, :xyz => '000')
395
398
  @db[:test2].first[:xyz].must_equal '000'
396
399
 
397
400
  @db[:test2].columns.must_equal [:name, :value, :xyz]
@@ -401,7 +404,7 @@ describe "A MySQL database" do
401
404
 
402
405
  @db[:test2].delete
403
406
  @db.add_column :test2, :xyz, :text
404
- @db[:test2] << {:name => 'mmm', :value => 111, :xyz => 'qqqq'}
407
+ @db[:test2].insert(:name => 'mmm', :value => 111, :xyz => 'qqqq')
405
408
 
406
409
  @db[:test2].columns.must_equal [:name, :value, :xyz]
407
410
  @db.rename_column :test2, :xyz, :zyx, :type => :text
@@ -410,7 +413,7 @@ describe "A MySQL database" do
410
413
 
411
414
  @db[:test2].delete
412
415
  @db.add_column :test2, :tre, :text
413
- @db[:test2] << {:name => 'mmm', :value => 111, :tre => 'qqqq'}
416
+ @db[:test2].insert(:name => 'mmm', :value => 111, :tre => 'qqqq')
414
417
 
415
418
  @db[:test2].columns.must_equal [:name, :value, :zyx, :tre]
416
419
  @db.rename_column :test2, :tre, :ert, :type => :varchar, :size=>255
@@ -419,7 +422,7 @@ describe "A MySQL database" do
419
422
 
420
423
  @db.add_column :test2, :xyz, :float
421
424
  @db[:test2].delete
422
- @db[:test2] << {:name => 'mmm', :value => 111, :xyz => 56.78}
425
+ @db[:test2].insert(:name => 'mmm', :value => 111, :xyz => 56.78)
423
426
  @db.set_column_type :test2, :xyz, :integer
424
427
 
425
428
  @db[:test2].first[:xyz].must_equal 57
@@ -437,15 +440,62 @@ describe "A MySQL database" do
437
440
  end
438
441
  end
439
442
 
443
+ # SEQUEL5: Remove
440
444
  describe "A MySQL database with table options" do
441
445
  before do
442
446
  @options = {:engine=>'MyISAM', :charset=>'latin1', :collate => 'latin1_swedish_ci'}
443
447
 
444
- Sequel::MySQL.default_engine = 'InnoDB'
445
- Sequel::MySQL.default_charset = 'utf8'
446
- Sequel::MySQL.default_collate = 'utf8_general_ci'
448
+ deprecated do
449
+ Sequel::MySQL.default_engine = 'InnoDB'
450
+ Sequel::MySQL.default_charset = 'utf8'
451
+ Sequel::MySQL.default_collate = 'utf8_general_ci'
452
+ end
453
+
454
+ @db = DB
455
+ @db.drop_table?(:items)
456
+
457
+ DB.sqls.clear
458
+ end
459
+ after do
460
+ @db.drop_table?(:items)
461
+
462
+ deprecated do
463
+ Sequel::MySQL.default_engine = nil
464
+ Sequel::MySQL.default_charset = nil
465
+ Sequel::MySQL.default_collate = nil
466
+ end
467
+ end
468
+
469
+ it "should allow to pass custom options (engine, charset, collate) for table creation" do
470
+ @db.create_table(:items, @options){Integer :size; text :name}
471
+ check_sqls do
472
+ @db.sqls.must_equal ["CREATE TABLE `items` (`size` integer, `name` text) ENGINE=MyISAM DEFAULT CHARSET=latin1 DEFAULT COLLATE=latin1_swedish_ci"]
473
+ end
474
+ end
475
+
476
+ it "should use default options if specified (engine, charset, collate) for table creation" do
477
+ @db.create_table(:items){Integer :size; text :name}
478
+ check_sqls do
479
+ @db.sqls.must_equal ["CREATE TABLE `items` (`size` integer, `name` text) ENGINE=InnoDB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci"]
480
+ end
481
+ end
482
+
483
+ it "should not use default if option has a nil value" do
484
+ @db.create_table(:items, :engine=>nil, :charset=>nil, :collate=>nil){Integer :size; text :name}
485
+ check_sqls do
486
+ @db.sqls.must_equal ["CREATE TABLE `items` (`size` integer, `name` text)"]
487
+ end
488
+ end
489
+ end
490
+
491
+ describe "A MySQL database with table options" do
492
+ before do
493
+ @options = {:engine=>'MyISAM', :charset=>'latin1', :collate => 'latin1_swedish_ci'}
447
494
 
448
495
  @db = DB
496
+ @db.default_engine = 'InnoDB'
497
+ @db.default_charset = 'utf8'
498
+ @db.default_collate = 'utf8_general_ci'
449
499
  @db.drop_table?(:items)
450
500
 
451
501
  DB.sqls.clear
@@ -453,9 +503,9 @@ describe "A MySQL database with table options" do
453
503
  after do
454
504
  @db.drop_table?(:items)
455
505
 
456
- Sequel::MySQL.default_engine = nil
457
- Sequel::MySQL.default_charset = nil
458
- Sequel::MySQL.default_collate = nil
506
+ @db.default_engine = nil
507
+ @db.default_charset = nil
508
+ @db.default_collate = nil
459
509
  end
460
510
 
461
511
  it "should allow to pass custom options (engine, charset, collate) for table creation" do
@@ -707,12 +757,12 @@ describe "A grouped MySQL dataset" do
707
757
  text :name
708
758
  integer :value
709
759
  end
710
- DB[:test2] << {:name => '11', :value => 10}
711
- DB[:test2] << {:name => '11', :value => 20}
712
- DB[:test2] << {:name => '11', :value => 30}
713
- DB[:test2] << {:name => '12', :value => 10}
714
- DB[:test2] << {:name => '12', :value => 20}
715
- DB[:test2] << {:name => '13', :value => 10}
760
+ DB[:test2].insert(:name => '11', :value => 10)
761
+ DB[:test2].insert(:name => '11', :value => 20)
762
+ DB[:test2].insert(:name => '11', :value => 30)
763
+ DB[:test2].insert(:name => '12', :value => 10)
764
+ DB[:test2].insert(:name => '12', :value => 20)
765
+ DB[:test2].insert(:name => '13', :value => 10)
716
766
  end
717
767
  after do
718
768
  DB.drop_table?(:test2)