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
@@ -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/