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
@@ -19,6 +19,7 @@ require 'minitest/shared_description'
19
19
  require "#{File.dirname(File.dirname(__FILE__))}/deprecation_helper.rb"
20
20
 
21
21
  class Minitest::HooksSpec
22
+ # SEQUEL5: Replace with define_singleton_method
22
23
  def meta_def(obj, name, &block)
23
24
  (class << obj; self end).send(:define_method, name, &block)
24
25
  end
@@ -316,13 +316,17 @@ describe "Array#sql_value_list and #sql_array" do
316
316
  it "should treat the array as an SQL value list instead of conditions when used as a placeholder value" do
317
317
  @d.filter(Sequel.lit("(a, b) IN ?", [[:x, 1], [:y, 2]])).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x = 1) AND (y = 2)))'
318
318
  @d.filter(Sequel.lit("(a, b) IN ?", [[:x, 1], [:y, 2]].sql_value_list)).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
319
- @d.filter(Sequel.lit("(a, b) IN ?", [[:x, 1], [:y, 2]].sql_array)).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
319
+ deprecated do
320
+ @d.filter(Sequel.lit("(a, b) IN ?", [[:x, 1], [:y, 2]].sql_array)).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
321
+ end
320
322
  end
321
323
 
322
324
  it "should be no difference when used as a hash value" do
323
325
  @d.filter([:a, :b]=>[[:x, 1], [:y, 2]]).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
324
326
  @d.filter([:a, :b]=>[[:x, 1], [:y, 2]].sql_value_list).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
325
- @d.filter([:a, :b]=>[[:x, 1], [:y, 2]].sql_array).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
327
+ deprecated do
328
+ @d.filter([:a, :b]=>[[:x, 1], [:y, 2]].sql_array).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
329
+ end
326
330
  end
327
331
  end
328
332
 
@@ -59,7 +59,7 @@ describe "ActiveModel plugin" do
59
59
  @c.freeze
60
60
  @o.id2 = 2
61
61
  @o.to_param.must_equal '2-1'
62
- @o.meta_def(:to_param_joiner){'|'}
62
+ def @o.to_param_joiner; '|' end
63
63
  @o.to_param.must_equal '2|1'
64
64
  @o.destroy
65
65
  @o.to_param.must_be_nil
@@ -33,7 +33,7 @@ describe "arbtirary servers" do
33
33
 
34
34
  it "should disconnect when connection is finished" do
35
35
  x, x1 = nil, nil
36
- @db.meta_def(:disconnect_connection){|c| x = c}
36
+ meta_def(@db, :disconnect_connection){|c| x = c}
37
37
  @db.synchronize(:host=>'host1', :database=>'db1') do |c|
38
38
  x1 = c
39
39
  @db.synchronize(:host=>'host1', :database=>'db1') do |c2|
@@ -8,7 +8,8 @@ describe "Sequel::Plugins::AssociationPks" do
8
8
  {:id=>$1.to_i}
9
9
  when "SELECT id FROM albums WHERE (albums.artist_id = 1)"
10
10
  [{:id=>1}, {:id=>2}, {:id=>3}]
11
- when /SELECT tag_id FROM albums_tags WHERE \(album_id = (\d)\)/
11
+ when /SELECT tag_id FROM albums_tags WHERE \(album_id = (\d)\)/,
12
+ /SELECT tags.id FROM tags INNER JOIN albums_tags ON \(albums_tags.tag_id = tags.id\) WHERE \(albums_tags.album_id = (\d)\)/
12
13
  a = []
13
14
  a << {:tag_id=>1} if $1 == '1'
14
15
  a << {:tag_id=>2} if $1 != '3'
@@ -32,7 +33,8 @@ describe "Sequel::Plugins::AssociationPks" do
32
33
  a
33
34
  when "SELECT year, week FROM hits WHERE ((hits.first = 'F1') AND (hits.last = 'L1'))"
34
35
  [{:year=>1997, :week=>1}, {:year=>1997, :week=>2}]
35
- when /SELECT year, week FROM vocalists_hits WHERE \(\((?:first|last) = '?[FL1](\d)/
36
+ when /SELECT year, week FROM vocalists_hits WHERE \(\((?:first|last) = '?[FL1](\d)/,
37
+ /SELECT hits.year, hits.week FROM hits INNER JOIN vocalists_hits ON \(\(vocalists_hits.(?:year|week) = hits.(?:year|week)\) AND \(vocalists_hits.(?:year|week) = hits.(?:year|week)\)\) WHERE \(\(vocalists_hits.(?:first|last) = '?[FL1](\d)/
36
38
  a = []
37
39
  a << {:year=>1997, :week=>1} if $1 == "1"
38
40
  a << {:year=>1997, :week=>2} if $1 != "3"
@@ -64,13 +66,28 @@ describe "Sequel::Plugins::AssociationPks" do
64
66
 
65
67
  it "should return correct associated pks for one_to_many associations" do
66
68
  @Artist.load(:id=>1).album_pks.must_equal [1,2,3]
69
+ @db.sqls.must_equal ["SELECT id FROM albums WHERE (albums.artist_id = 1)"]
67
70
  @Artist.load(:id=>2).album_pks.must_equal []
71
+ @db.sqls.must_equal ["SELECT id FROM albums WHERE (albums.artist_id = 2)"]
68
72
  end
69
73
 
70
74
  it "should return correct associated pks for many_to_many associations" do
71
75
  @Album.load(:id=>1).tag_pks.must_equal [1, 2]
76
+ @db.sqls.must_equal ["SELECT tag_id FROM albums_tags WHERE (album_id = 1)"]
72
77
  @Album.load(:id=>2).tag_pks.must_equal [2, 3]
78
+ @db.sqls.must_equal ["SELECT tag_id FROM albums_tags WHERE (album_id = 2)"]
73
79
  @Album.load(:id=>3).tag_pks.must_equal []
80
+ @db.sqls.must_equal ["SELECT tag_id FROM albums_tags WHERE (album_id = 3)"]
81
+ end
82
+
83
+ it "should return correct associated pks for many_to_many associations using :association_pks_use_associated_table" do
84
+ @Album.many_to_many :tags, :class=>@Tag, :join_table=>:albums_tags, :left_key=>:album_id, :delay_pks=>false, :association_pks_use_associated_table=>true
85
+ @Album.load(:id=>1).tag_pks.must_equal [1, 2]
86
+ @db.sqls.must_equal ["SELECT tags.id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE (albums_tags.album_id = 1)"]
87
+ @Album.load(:id=>2).tag_pks.must_equal [2, 3]
88
+ @db.sqls.must_equal ["SELECT tags.id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE (albums_tags.album_id = 2)"]
89
+ @Album.load(:id=>3).tag_pks.must_equal []
90
+ @db.sqls.must_equal ["SELECT tags.id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE (albums_tags.album_id = 3)"]
74
91
  end
75
92
 
76
93
  deprecated "should set associated pks correctly for a one_to_many association when :delay_pks is not set" do
@@ -171,14 +188,29 @@ describe "Sequel::Plugins::AssociationPks" do
171
188
  it "should return correct right-side associated cpks for left-side cpks for one_to_many associations" do
172
189
  @Vocalist.one_to_many :hits, :class=>@Hit, :key=>[:first, :last]
173
190
  @Vocalist.load(:first=>'F1', :last=>'L1').hit_pks.must_equal [[1997, 1], [1997, 2]]
191
+ @db.sqls.must_equal ["SELECT year, week FROM hits WHERE ((hits.first = 'F1') AND (hits.last = 'L1'))"]
174
192
  @Vocalist.load(:first=>'F2', :last=>'L2').hit_pks.must_equal []
193
+ @db.sqls.must_equal ["SELECT year, week FROM hits WHERE ((hits.first = 'F2') AND (hits.last = 'L2'))"]
175
194
  end
176
195
 
177
196
  it "should return correct right-side associated cpks for left-side cpks for many_to_many associations" do
178
197
  @Vocalist.many_to_many :hits, :class=>@Hit, :join_table=>:vocalists_hits, :left_key=>[:first, :last], :right_key=>[:year, :week]
179
198
  @Vocalist.load(:first=>'F1', :last=>'L1').hit_pks.must_equal [[1997, 1], [1997, 2]]
199
+ @db.sqls.must_equal ["SELECT year, week FROM vocalists_hits WHERE ((first = 'F1') AND (last = 'L1'))"]
200
+ @Vocalist.load(:first=>'F2', :last=>'L2').hit_pks.must_equal [[1997, 2], [1997, 3]]
201
+ @db.sqls.must_equal ["SELECT year, week FROM vocalists_hits WHERE ((first = 'F2') AND (last = 'L2'))"]
202
+ @Vocalist.load(:first=>'F3', :last=>'L3').hit_pks.must_equal []
203
+ @db.sqls.must_equal ["SELECT year, week FROM vocalists_hits WHERE ((first = 'F3') AND (last = 'L3'))"]
204
+ end
205
+
206
+ it "should return correct right-side associated cpks for left-side cpks for many_to_many associations when using :association_pks_use_associated_table" do
207
+ @Vocalist.many_to_many :hits, :class=>@Hit, :join_table=>:vocalists_hits, :left_key=>[:first, :last], :right_key=>[:year, :week], :association_pks_use_associated_table=>true
208
+ @Vocalist.load(:first=>'F1', :last=>'L1').hit_pks.must_equal [[1997, 1], [1997, 2]]
209
+ @db.sqls.must_equal ["SELECT hits.year, hits.week FROM hits INNER JOIN vocalists_hits ON ((vocalists_hits.year = hits.year) AND (vocalists_hits.week = hits.week)) WHERE ((vocalists_hits.first = 'F1') AND (vocalists_hits.last = 'L1'))"]
180
210
  @Vocalist.load(:first=>'F2', :last=>'L2').hit_pks.must_equal [[1997, 2], [1997, 3]]
211
+ @db.sqls.must_equal ["SELECT hits.year, hits.week FROM hits INNER JOIN vocalists_hits ON ((vocalists_hits.year = hits.year) AND (vocalists_hits.week = hits.week)) WHERE ((vocalists_hits.first = 'F2') AND (vocalists_hits.last = 'L2'))"]
181
212
  @Vocalist.load(:first=>'F3', :last=>'L3').hit_pks.must_equal []
213
+ @db.sqls.must_equal ["SELECT hits.year, hits.week FROM hits INNER JOIN vocalists_hits ON ((vocalists_hits.year = hits.year) AND (vocalists_hits.week = hits.week)) WHERE ((vocalists_hits.first = 'F3') AND (vocalists_hits.last = 'L3'))"]
182
214
  end
183
215
 
184
216
  it "should set associated right-side cpks correctly for left-side cpks for a one_to_many association" do
@@ -9,6 +9,10 @@ describe "Dataset#where" do
9
9
  @dataset.where('price < ? AND id in ?', 100, [1, 2, 3]).select_sql.must_equal "SELECT * FROM test WHERE (price < 100 AND id in (1, 2, 3))"
10
10
  end
11
11
 
12
+ it "should use default behavior for array of conditions" do
13
+ @dataset.where([[:a, 1], [:b, 2]]).sql.must_equal 'SELECT * FROM test WHERE ((a = 1) AND (b = 2))'
14
+ end
15
+
12
16
  it "should not modify passed array with placeholders" do
13
17
  a = ['price < ? AND id in ?', 100, 1, 2, 3]
14
18
  b = a.dup
@@ -114,7 +118,7 @@ describe "Dataset#and" do
114
118
  @d1 = @dataset.where(:x => 1)
115
119
  end
116
120
 
117
- it "should accept string filters with placeholders" do
121
+ deprecated "should accept string filters with placeholders" do
118
122
  @d1.and('y > ?', 2).sql.must_equal 'SELECT * FROM test WHERE ((x = 1) AND (y > 2))'
119
123
  end
120
124
  end
@@ -98,6 +98,8 @@ describe "Sequel::Plugins::AutoValidations" do
98
98
  @m = @c.new
99
99
  @c.skip_auto_validations(:not_null)
100
100
  @m.valid?.must_equal true
101
+ @m.nnd = nil
102
+ @m.valid?.must_equal true
101
103
 
102
104
  @m.set(:d=>'/', :num=>'a', :name=>'1')
103
105
  @m.valid?.must_equal false
@@ -86,7 +86,7 @@ describe Sequel::Model, "BooleanReaders plugin" do
86
86
  end
87
87
 
88
88
  it "should handle cases where getting the columns raises an error" do
89
- @c.meta_def(:columns){raise Sequel::Error}
89
+ def @c.columns; raise Sequel::Error end
90
90
  @c.plugin(:boolean_readers)
91
91
  proc{@c.new.b?}.must_raise(NoMethodError)
92
92
  end
@@ -40,7 +40,7 @@ describe "boolean_subsets plugin" do
40
40
  end
41
41
 
42
42
  it "should handle cases where getting the columns raises an error" do
43
- @c.meta_def(:columns){raise Sequel::Error}
43
+ def @c.columns; raise Sequel::Error end
44
44
  @c.plugin(:boolean_subsets)
45
45
  @c.respond_to?(:active).must_equal false
46
46
  end
@@ -62,6 +62,11 @@ describe "class_table_inheritance plugin" do
62
62
  Employee.cti_table_map.frozen?.must_equal true
63
63
  end
64
64
 
65
+ deprecated "should support cti_key and cti_model_map" do
66
+ Employee.cti_key.must_equal Employee.sti_key
67
+ Employee.cti_model_map.must_equal Employee.sti_model_map
68
+ end
69
+
65
70
  deprecated "should not attempt to use prepared statements" do
66
71
  Manager.plugin :prepared_statements
67
72
  Manager[1]
@@ -572,10 +577,14 @@ describe "class_table_inheritance plugin with :alias option" do
572
577
  @db.sqls.must_equal ["SELECT * FROM (SELECT employees.id, employees.name, employees.kind, managers.num_staff FROM employees INNER JOIN managers ON (managers.id = employees.id)) AS employees WHERE (id = 1) LIMIT 1"]
573
578
  end
574
579
 
575
- it "#cti_base_model should be the model that loaded the plugin" do
580
+ deprecated "#cti_base_model should be the model that loaded the plugin" do
576
581
  Executive.cti_base_model.must_equal Employee
577
582
  end
578
583
 
584
+ it "#cti_models.first should be the model that loaded the plugin" do
585
+ Executive.cti_models.first.must_equal Employee
586
+ end
587
+
579
588
  it "#cti_columns should be a mapping of table names to columns" do
580
589
  Executive.cti_columns.must_equal(:employees=>[:id, :name, :kind], :managers=>[:id, :num_staff], :executives=>[:id, :num_managers])
581
590
  end
@@ -668,6 +677,39 @@ describe "class_table_inheritance plugin with :alias option" do
668
677
  "INSERT INTO executives (id) VALUES (1)"]
669
678
  end
670
679
 
680
+ it "should sets the model class name for the key when creating new subclass records" do
681
+ Employee.plugin(:class_table_inheritance, :key=>:kind, :model_map=>{0=>:Employee, 1=>:Manager, 2=>:Executive, 3=>:Ceo}, :alias=>:employees)
682
+ Object.send(:remove_const, :Ceo)
683
+ Object.send(:remove_const, :Executive)
684
+ Object.send(:remove_const, :Manager)
685
+ class ::Manager < Employee; end
686
+ class ::Executive < Manager; end
687
+ class ::Ceo < Executive; end
688
+ Ceo.create
689
+ @db.sqls.must_equal ["INSERT INTO employees (kind) VALUES ('3')",
690
+ "INSERT INTO managers (id) VALUES (1)",
691
+ "INSERT INTO executives (id) VALUES (1)"]
692
+ end
693
+
694
+ it "should sets the model class name for the key when creating new subclass records" do
695
+ Employee.plugin(:class_table_inheritance, :key=>:kind, :model_map=>{0=>:Employee, 1=>:Manager, 2=>:Executive, 3=>:Ceo}, :alias=>:employees)
696
+ Object.send(:remove_const, :Ceo)
697
+ Object.send(:remove_const, :Executive)
698
+ Object.send(:remove_const, :Manager)
699
+ class ::Manager < Employee; end
700
+ class ::Executive < Employee; end
701
+ class ::Ceo < Employee; end
702
+ Ceo.create
703
+ @db.sqls.must_equal ["INSERT INTO employees (kind) VALUES ('3')"]
704
+ end
705
+
706
+ it "should not use a subquery for a class that doesn't join to a separate table" do
707
+ Employee.plugin(:class_table_inheritance, :key=>:kind, :model_map=>{0=>:Employee, 1=>:Manager, 2=>:Executive, 3=>:Ceo}, :alias=>:employees)
708
+ Object.send(:remove_const, :Ceo)
709
+ class ::Ceo < Employee; end
710
+ Ceo.dataset.sql.must_equal 'SELECT * FROM employees WHERE (employees.kind IN (3))'
711
+ end
712
+
671
713
  it "should ignore existing cti_key value when creating new records" do
672
714
  Employee.create(:kind=>'Manager')
673
715
  @db.sqls.must_equal ["INSERT INTO employees (kind) VALUES ('Employee')"]
@@ -1069,10 +1111,14 @@ describe "class_table_inheritance plugin with :alias option" do
1069
1111
  @db.sqls.must_equal ["SELECT * FROM (SELECT employees.id, employees.name, employees.kind, managers.num_staff FROM employees INNER JOIN managers ON (managers.id = employees.id)) AS employees WHERE (id = 1) LIMIT 1"]
1070
1112
  end
1071
1113
 
1072
- it "#cti_base_model should be the model that loaded the plugin" do
1114
+ deprecated "#cti_base_model should be the model that loaded the plugin" do
1073
1115
  Executive.cti_base_model.must_equal Employee
1074
1116
  end
1075
1117
 
1118
+ it "#cti_models.first should be the model that loaded the plugin" do
1119
+ Executive.cti_models.first.must_equal Employee
1120
+ end
1121
+
1076
1122
  it "#cti_columns should be a mapping of table names to columns" do
1077
1123
  Executive.cti_columns.must_equal(:employees=>[:id, :name, :kind], :managers=>[:id, :num_staff], :executives=>[:id, :num_managers])
1078
1124
  end
@@ -39,6 +39,17 @@ describe "column_conflicts plugin" do
39
39
  @o.get_column_value(:model).must_equal 2
40
40
  end
41
41
 
42
+ it "should not erase existing column conflicts when loading the plugin" do
43
+ @c.send(:define_method, :foo){raise}
44
+ @c.send(:define_method, :model=){raise}
45
+ @c.get_column_conflict!(:foo)
46
+ @c.set_column_conflict!(:model)
47
+ @c.plugin :column_conflicts
48
+ @o.get_column_value(:foo).must_equal 4
49
+ @o.set_column_value(:model=, 2).must_equal 2
50
+ @o.get_column_value(:model).must_equal 2
51
+ end
52
+
42
53
  it "should work correctly in subclasses" do
43
54
  @o = Class.new(@c).load(:model=>1, :use_transactions=>2)
44
55
  @o.get_column_value(:model).must_equal 1
@@ -104,7 +104,7 @@ connection_validator_specs = shared_description do
104
104
  end
105
105
 
106
106
  it "should handle case where determining validity requires a connection" do
107
- @db.meta_def(:valid_connection?){|c| synchronize{}; true}
107
+ def @db.valid_connection?(c) synchronize{}; true end
108
108
  @db.pool.connection_validation_timeout = -1
109
109
  c1 = @db.synchronize{|c| c}
110
110
  @db.synchronize{|c| c}.must_be_same_as(c1)
@@ -2,7 +2,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe "Sequel::Plugins::DatasetAssociations" do
4
4
  before do
5
- @db = Sequel.mock
5
+ @db = Sequel.mock(:host=>'postgres')
6
6
  @db.extend_datasets do
7
7
  def supports_window_functions?; true; end
8
8
  def supports_distinct_on?; true; end
@@ -14,9 +14,9 @@ describe "Sequel::Plugins::DatasetAssociations" do
14
14
  @Album = Class.new(@Base)
15
15
  @Tag = Class.new(@Base)
16
16
 
17
- @Artist.meta_def(:name){'Artist'}
18
- @Album.meta_def(:name){'Album'}
19
- @Tag.meta_def(:name){'Tag'}
17
+ def @Artist.name; 'Artist' end
18
+ def @Album.name; 'Album' end
19
+ def @Tag.name; 'Tag' end
20
20
 
21
21
  @Artist.dataset = @db[:artists]
22
22
  @Album.dataset = @db[:albums]
@@ -142,7 +142,7 @@ describe "Sequel::Plugins::DatasetAssociations" do
142
142
  ds = @Tag.artists
143
143
  ds.must_be_kind_of(Sequel::Dataset)
144
144
  ds.model.must_equal @Artist
145
- ds.sql.must_equal "SELECT * FROM artists WHERE coalesce((tag_ids && (SELECT array_agg(tags.id) FROM tags)), 'f')"
145
+ ds.sql.must_equal "SELECT * FROM artists WHERE coalesce((tag_ids && (SELECT array_agg(tags.id) FROM tags)), false)"
146
146
  end
147
147
 
148
148
  it "should have an associated method that takes an association symbol" do
@@ -261,9 +261,9 @@ describe "Sequel::Plugins::DatasetAssociations with composite keys" do
261
261
  @Album = Class.new(@Base)
262
262
  @Tag = Class.new(@Base)
263
263
 
264
- @Artist.meta_def(:name){'Artist'}
265
- @Album.meta_def(:name){'Album'}
266
- @Tag.meta_def(:name){'Tag'}
264
+ def @Artist.name; 'Artist' end
265
+ def @Album.name; 'Album' end
266
+ def @Tag.name; 'Tag' end
267
267
 
268
268
  @Artist.dataset = @db[:artists]
269
269
  @Album.dataset = @db[:albums]
@@ -9,7 +9,7 @@ describe "Sequel::Plugins::DefaultsSetter" do
9
9
  @c.instance_variable_set(:@db_schema, {:a=>{}})
10
10
  @c.plugin :defaults_setter
11
11
  @c.columns :a
12
- @pr = proc{|x| db.meta_def(:schema){|*| [[:id, {:primary_key=>true}], [:a, {:ruby_default => x, :primary_key=>false}]]}; c.dataset = c.dataset; c}
12
+ @pr = proc{|x| meta_def(db, :schema){|*| [[:id, {:primary_key=>true}], [:a, {:ruby_default => x, :primary_key=>false}]]}; c.dataset = c.dataset; c}
13
13
  end
14
14
  after do
15
15
  Sequel.datetime_class = Time
@@ -2,7 +2,9 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe "filter_having extension" do
4
4
  before do
5
- @ds = Sequel.mock[:t].extension(:filter_having)
5
+ deprecated do
6
+ @ds = Sequel.mock[:t].extension(:filter_having)
7
+ end
6
8
  @dsh = @ds.having(:a)
7
9
  end
8
10
 
@@ -14,11 +16,11 @@ describe "filter_having extension" do
14
16
  @ds.filter(:b).sql.must_equal 'SELECT * FROM t WHERE b'
15
17
  end
16
18
 
17
- it "should make and operate on HAVING clause if dataset has a HAVING clause" do
19
+ deprecated "should make and operate on HAVING clause if dataset has a HAVING clause" do
18
20
  @dsh.and(:b).sql.must_equal 'SELECT * FROM t HAVING (a AND b)'
19
21
  end
20
22
 
21
- it "should make and operate on WHERE clause if dataset does not have a HAVING clause" do
23
+ deprecated "should make and operate on WHERE clause if dataset does not have a HAVING clause" do
22
24
  @ds.where(:a).and(:b).sql.must_equal 'SELECT * FROM t WHERE (a AND b)'
23
25
  end
24
26
 
@@ -2,7 +2,9 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe "hash_aliases extension" do
4
4
  before do
5
- @ds = Sequel.mock.dataset.extension(:hash_aliases)
5
+ deprecated do
6
+ @ds = Sequel.mock.dataset.extension(:hash_aliases)
7
+ end
6
8
  end
7
9
 
8
10
  it "should make from treat hash arguments as alias specifiers" do
@@ -6,7 +6,9 @@ describe "identifier_columns plugin" do
6
6
  @c = Class.new(Sequel::Model(@db[:test]))
7
7
  @ds = @c.dataset
8
8
  @c.columns :id, :a__b
9
- @c.plugin :identifier_columns
9
+ deprecated do
10
+ @c.plugin :identifier_columns
11
+ end
10
12
  @db.sqls
11
13
  end
12
14
 
@@ -9,13 +9,15 @@ describe "Sequel::Dataset::ImplicitSubquery" do
9
9
  ods = db[:c]
10
10
  ods.columns(:id, :b)
11
11
 
12
- ds.and(:c).sql.must_equal "SELECT * FROM (SELECT * FROM table) AS t1 WHERE c"
12
+ deprecated do
13
+ ds.and(:c).sql.must_equal "SELECT * FROM (SELECT * FROM table) AS t1 WHERE c"
14
+ ds.exclude_where(:c).sql.must_equal "SELECT * FROM (SELECT * FROM table) AS t1 WHERE NOT c"
15
+ end
13
16
  ds.cross_join(:c).sql.must_equal "SELECT * FROM (SELECT * FROM table) AS t1 CROSS JOIN c"
14
17
  ds.distinct.sql.must_equal "SELECT DISTINCT * FROM (SELECT * FROM table) AS t1"
15
18
  ds.except(ods).sql.must_equal "SELECT * FROM (SELECT * FROM (SELECT * FROM table) AS t1 EXCEPT SELECT * FROM c) AS t1"
16
19
  ds.exclude(:c).sql.must_equal "SELECT * FROM (SELECT * FROM table) AS t1 WHERE NOT c"
17
20
  ds.exclude_having(:c).sql.must_equal "SELECT * FROM (SELECT * FROM table) AS t1 HAVING NOT c"
18
- ds.exclude_where(:c).sql.must_equal "SELECT * FROM (SELECT * FROM table) AS t1 WHERE NOT c"
19
21
  ds.filter(:c).sql.must_equal "SELECT * FROM (SELECT * FROM table) AS t1 WHERE c"
20
22
  ds.for_update.sql.must_equal "SELECT * FROM (SELECT * FROM table) AS t1 FOR UPDATE"
21
23
  ds.full_join(:c).sql.must_equal "SELECT * FROM (SELECT * FROM table) AS t1 FULL JOIN c"
@@ -65,6 +65,12 @@ describe "Sequel::Plugins::JsonSerializer" do
65
65
  Album.from_json(@album.to_json(:include=>:artist), :associations=>:artist).artist.must_equal @artist
66
66
  end
67
67
 
68
+ it "should have #to_json support blocks for transformations" do
69
+ values = {}
70
+ @artist.values.each{|k,v| values[k.to_s] = v}
71
+ Sequel.parse_json(@artist.to_json{|h| {'data'=>h}}).must_equal({'data'=>values})
72
+ end
73
+
68
74
  it "should raise an error if attempting to parse json when providing array to non-array association or vice-versa" do
69
75
  proc{Artist.from_json('{"albums":{"id":1,"name":"RF","artist_id":2},"id":2,"name":"YJM"}', :associations=>:albums)}.must_raise(Sequel::Error)
70
76
  proc{Album.from_json('{"artist":[{"id":2,"name":"YJM"}],"id":1,"name":"RF","artist_id":2}', :associations=>:artist)}.must_raise(Sequel::Error)
@@ -186,6 +192,18 @@ describe "Sequel::Plugins::JsonSerializer" do
186
192
  Sequel.parse_json(ds.to_json).must_equal [@album.values.inject({}){|h, (k, v)| h[k.to_s] = v; h}]
187
193
  end
188
194
 
195
+ it "should have class and dataset to_json method accept blocks for transformations" do
196
+ Album.dataset = Album.dataset.with_fetch(:id=>1, :name=>'RF', :artist_id=>2)
197
+ Sequel.parse_json(Album.to_json{|h| {'data'=>h}}).must_equal('data'=>[@album.values.inject({}){|h, (k, v)| h[k.to_s] = v; h}])
198
+ Sequel.parse_json(Album.dataset.to_json{|h| {'data'=>h}}).must_equal('data'=>[@album.values.inject({}){|h, (k, v)| h[k.to_s] = v; h}])
199
+ end
200
+
201
+ it "should have class and dataset to_json method support :instance_block option for instance_transformations" do
202
+ Album.dataset = Album.dataset.with_fetch(:id=>1, :name=>'RF', :artist_id=>2)
203
+ Sequel.parse_json(Album.to_json(:instance_block=>lambda{|h| {'data'=>h}})).must_equal [{'data'=>@album.values.inject({}){|h, (k, v)| h[k.to_s] = v; h}}]
204
+ Sequel.parse_json(Album.dataset.to_json(:instance_block=>lambda{|h| {'data'=>h}})).must_equal [{'data'=>@album.values.inject({}){|h, (k, v)| h[k.to_s] = v; h}}]
205
+ end
206
+
189
207
  it "should have dataset to_json method respect :array option for the array to use" do
190
208
  a = Album.new(:name=>'RF', :artist_id=>3)
191
209
  Album.array_from_json(Album.to_json(:array=>[a])).must_equal [a]
@@ -5,13 +5,13 @@ describe "Sequel::Plugins::LazyAttributes" do
5
5
  before do
6
6
  @db = Sequel.mock
7
7
  def @db.supports_schema_parsing?() true end
8
- @db.meta_def(:schema){|*a| [[:id, {:type=>:integer}], [:name,{:type=>:string}]]}
8
+ def @db.schema(*a) [[:id, {:type=>:integer}], [:name,{:type=>:string}]] end
9
9
  class ::LazyAttributesModel < Sequel::Model(@db[:la])
10
10
  plugin :lazy_attributes
11
11
  set_columns([:id, :name])
12
- meta_def(:columns){[:id, :name]}
12
+ def self.columns; [:id, :name] end
13
13
  lazy_attributes :name
14
- meta_def(:columns){[:id]}
14
+ def self.columns; [:id] end
15
15
  set_dataset dataset.with_fetch(proc do |sql|
16
16
  if sql !~ /WHERE/
17
17
  if sql =~ /name/