sequel 4.47.0 → 4.48.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +134 -0
- data/Rakefile +1 -1
- data/doc/release_notes/4.48.0.txt +293 -0
- data/lib/sequel/adapters/ado/access.rb +2 -1
- data/lib/sequel/adapters/do/postgres.rb +5 -2
- data/lib/sequel/adapters/ibmdb.rb +24 -7
- data/lib/sequel/adapters/jdbc.rb +36 -22
- data/lib/sequel/adapters/jdbc/db2.rb +12 -3
- data/lib/sequel/adapters/jdbc/derby.rb +4 -5
- data/lib/sequel/adapters/jdbc/oracle.rb +16 -2
- data/lib/sequel/adapters/jdbc/postgresql.rb +43 -18
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +9 -7
- data/lib/sequel/adapters/jdbc/sqlserver.rb +11 -4
- data/lib/sequel/adapters/mock.rb +24 -19
- data/lib/sequel/adapters/mysql.rb +17 -16
- data/lib/sequel/adapters/mysql2.rb +4 -5
- data/lib/sequel/adapters/oracle.rb +5 -9
- data/lib/sequel/adapters/postgres.rb +89 -102
- data/lib/sequel/adapters/shared/db2.rb +22 -6
- data/lib/sequel/adapters/shared/mssql.rb +5 -4
- data/lib/sequel/adapters/shared/mysql.rb +75 -24
- data/lib/sequel/adapters/shared/postgres.rb +196 -94
- data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
- data/lib/sequel/adapters/shared/sqlite.rb +72 -82
- data/lib/sequel/adapters/sqlanywhere.rb +4 -1
- data/lib/sequel/adapters/sqlite.rb +5 -3
- data/lib/sequel/adapters/swift/postgres.rb +5 -2
- data/lib/sequel/adapters/tinytds.rb +0 -5
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
- data/lib/sequel/adapters/utils/pg_types.rb +2 -76
- data/lib/sequel/core.rb +2 -2
- data/lib/sequel/database/connecting.rb +5 -5
- data/lib/sequel/database/dataset.rb +6 -3
- data/lib/sequel/database/misc.rb +1 -1
- data/lib/sequel/database/query.rb +3 -0
- data/lib/sequel/database/schema_methods.rb +1 -1
- data/lib/sequel/dataset/actions.rb +18 -10
- data/lib/sequel/dataset/graph.rb +1 -1
- data/lib/sequel/dataset/misc.rb +1 -0
- data/lib/sequel/dataset/prepared_statements.rb +3 -3
- data/lib/sequel/dataset/query.rb +19 -8
- data/lib/sequel/extensions/core_extensions.rb +4 -1
- data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -0
- data/lib/sequel/extensions/filter_having.rb +2 -0
- data/lib/sequel/extensions/freeze_datasets.rb +2 -0
- data/lib/sequel/extensions/from_block.rb +1 -1
- data/lib/sequel/extensions/graph_each.rb +2 -2
- data/lib/sequel/extensions/hash_aliases.rb +2 -0
- data/lib/sequel/extensions/identifier_mangling.rb +0 -7
- data/lib/sequel/extensions/meta_def.rb +2 -0
- data/lib/sequel/extensions/migration.rb +6 -6
- data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +207 -130
- data/lib/sequel/extensions/pg_hstore.rb +38 -20
- data/lib/sequel/extensions/pg_inet.rb +18 -6
- data/lib/sequel/extensions/pg_interval.rb +19 -12
- data/lib/sequel/extensions/pg_json.rb +25 -14
- data/lib/sequel/extensions/pg_json_ops.rb +2 -2
- data/lib/sequel/extensions/pg_range.rb +133 -100
- data/lib/sequel/extensions/pg_range_ops.rb +4 -3
- data/lib/sequel/extensions/pg_row.rb +68 -39
- data/lib/sequel/extensions/pg_row_ops.rb +11 -5
- data/lib/sequel/extensions/query_literals.rb +2 -0
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +2 -0
- data/lib/sequel/extensions/s.rb +1 -1
- data/lib/sequel/extensions/schema_dumper.rb +24 -24
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +3 -1
- data/lib/sequel/extensions/sequel_4_dataset_methods.rb +83 -0
- data/lib/sequel/extensions/set_overrides.rb +2 -2
- data/lib/sequel/extensions/string_agg.rb +0 -1
- data/lib/sequel/extensions/symbol_aref.rb +0 -4
- data/lib/sequel/model.rb +25 -57
- data/lib/sequel/model/associations.rb +14 -5
- data/lib/sequel/model/base.rb +96 -32
- data/lib/sequel/plugins/association_pks.rb +73 -46
- data/lib/sequel/plugins/association_proxies.rb +1 -1
- data/lib/sequel/plugins/auto_validations.rb +6 -2
- data/lib/sequel/plugins/boolean_readers.rb +1 -1
- data/lib/sequel/plugins/caching.rb +19 -13
- data/lib/sequel/plugins/class_table_inheritance.rb +19 -10
- data/lib/sequel/plugins/column_conflicts.rb +7 -2
- data/lib/sequel/plugins/column_select.rb +1 -1
- data/lib/sequel/plugins/csv_serializer.rb +8 -8
- data/lib/sequel/plugins/defaults_setter.rb +10 -0
- data/lib/sequel/plugins/eager_each.rb +1 -1
- data/lib/sequel/plugins/force_encoding.rb +2 -2
- data/lib/sequel/plugins/hook_class_methods.rb +9 -12
- data/lib/sequel/plugins/identifier_columns.rb +2 -0
- data/lib/sequel/plugins/instance_filters.rb +3 -1
- data/lib/sequel/plugins/instance_hooks.rb +17 -9
- data/lib/sequel/plugins/json_serializer.rb +17 -10
- data/lib/sequel/plugins/lazy_attributes.rb +8 -7
- data/lib/sequel/plugins/modification_detection.rb +3 -0
- data/lib/sequel/plugins/nested_attributes.rb +5 -1
- data/lib/sequel/plugins/pg_array_associations.rb +5 -0
- data/lib/sequel/plugins/prepared_statements.rb +1 -0
- data/lib/sequel/plugins/rcte_tree.rb +4 -4
- data/lib/sequel/plugins/serialization.rb +3 -10
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/split_values.rb +6 -5
- data/lib/sequel/plugins/static_cache.rb +31 -25
- data/lib/sequel/plugins/subset_conditions.rb +3 -1
- data/lib/sequel/plugins/table_select.rb +1 -1
- data/lib/sequel/plugins/touch.rb +2 -1
- data/lib/sequel/plugins/validation_class_methods.rb +5 -6
- data/lib/sequel/plugins/validation_helpers.rb +2 -4
- data/lib/sequel/plugins/xml_serializer.rb +4 -4
- data/lib/sequel/sql.rb +2 -2
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +115 -14
- data/spec/adapters/mysql_spec.rb +78 -28
- data/spec/adapters/oracle_spec.rb +24 -24
- data/spec/adapters/postgres_spec.rb +38 -24
- data/spec/adapters/sqlanywhere_spec.rb +88 -86
- data/spec/adapters/sqlite_spec.rb +29 -24
- data/spec/core/connection_pool_spec.rb +17 -0
- data/spec/core/database_spec.rb +6 -0
- data/spec/core/dataset_spec.rb +46 -36
- data/spec/core/schema_spec.rb +16 -0
- data/spec/core/spec_helper.rb +1 -0
- data/spec/core_extensions_spec.rb +6 -2
- data/spec/extensions/active_model_spec.rb +1 -1
- data/spec/extensions/arbitrary_servers_spec.rb +1 -1
- data/spec/extensions/association_pks_spec.rb +34 -2
- data/spec/extensions/auto_literal_strings_spec.rb +5 -1
- data/spec/extensions/auto_validations_spec.rb +2 -0
- data/spec/extensions/boolean_readers_spec.rb +1 -1
- data/spec/extensions/boolean_subsets_spec.rb +1 -1
- data/spec/extensions/class_table_inheritance_spec.rb +48 -2
- data/spec/extensions/column_conflicts_spec.rb +11 -0
- data/spec/extensions/connection_validator_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +8 -8
- data/spec/extensions/defaults_setter_spec.rb +1 -1
- data/spec/extensions/filter_having_spec.rb +5 -3
- data/spec/extensions/hash_aliases_spec.rb +3 -1
- data/spec/extensions/identifier_columns_spec.rb +3 -1
- data/spec/extensions/implicit_subquery_spec.rb +4 -2
- data/spec/extensions/json_serializer_spec.rb +18 -0
- data/spec/extensions/lazy_attributes_spec.rb +3 -3
- data/spec/extensions/meta_def_spec.rb +9 -0
- data/spec/extensions/migration_spec.rb +3 -3
- data/spec/extensions/nested_attributes_spec.rb +14 -3
- data/spec/extensions/no_auto_literal_strings_spec.rb +8 -4
- data/spec/extensions/pg_array_associations_spec.rb +29 -18
- data/spec/extensions/pg_array_spec.rb +44 -25
- data/spec/extensions/pg_hstore_spec.rb +10 -0
- data/spec/extensions/pg_inet_spec.rb +26 -0
- data/spec/extensions/pg_interval_spec.rb +20 -0
- data/spec/extensions/pg_json_spec.rb +24 -0
- data/spec/extensions/pg_range_spec.rb +98 -14
- data/spec/extensions/pg_row_spec.rb +14 -4
- data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
- data/spec/extensions/query_literals_spec.rb +3 -1
- data/spec/extensions/schema_dumper_spec.rb +96 -98
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +10 -6
- data/spec/extensions/sequel_4_dataset_methods_spec.rb +121 -0
- data/spec/extensions/single_table_inheritance_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +7 -1
- data/spec/extensions/static_cache_spec.rb +75 -24
- data/spec/extensions/string_agg_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +9 -0
- data/spec/extensions/validation_helpers_spec.rb +9 -3
- data/spec/extensions/whitelist_security_spec.rb +26 -0
- data/spec/integration/dataset_test.rb +45 -44
- data/spec/integration/plugin_test.rb +20 -0
- data/spec/integration/prepared_statement_test.rb +3 -0
- data/spec/integration/schema_test.rb +21 -1
- data/spec/integration/transaction_test.rb +40 -40
- data/spec/model/class_dataset_methods_spec.rb +14 -4
- data/spec/model/dataset_methods_spec.rb +12 -3
- data/spec/model/model_spec.rb +8 -0
- metadata +6 -4
- data/spec/adapters/firebird_spec.rb +0 -405
- data/spec/adapters/informix_spec.rb +0 -100
data/spec/core/spec_helper.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
|
@@ -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
|
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
|
-
|
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
|
@@ -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.
|
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.
|
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
|
-
|
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
|
-
|
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.
|
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.
|
18
|
-
@Album.
|
19
|
-
@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)),
|
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.
|
265
|
-
@Album.
|
266
|
-
@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|
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
@@ -9,13 +9,15 @@ describe "Sequel::Dataset::ImplicitSubquery" do
|
|
9
9
|
ods = db[:c]
|
10
10
|
ods.columns(:id, :b)
|
11
11
|
|
12
|
-
|
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.
|
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
|
-
|
12
|
+
def self.columns; [:id, :name] end
|
13
13
|
lazy_attributes :name
|
14
|
-
|
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/
|