sequel 4.47.0 → 4.48.0

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