sequel 4.31.0 → 4.32.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.
- checksums.yaml +4 -4
- data/CHANGELOG +24 -0
- data/Rakefile +17 -15
- data/doc/association_basics.rdoc +7 -3
- data/doc/opening_databases.rdoc +7 -0
- data/doc/release_notes/4.32.0.txt +132 -0
- data/doc/schema_modification.rdoc +1 -1
- data/doc/security.rdoc +70 -26
- data/doc/testing.rdoc +1 -0
- data/lib/sequel/adapters/jdbc.rb +2 -1
- data/lib/sequel/adapters/postgres.rb +3 -4
- data/lib/sequel/adapters/shared/mysql.rb +14 -1
- data/lib/sequel/adapters/shared/sqlite.rb +2 -2
- data/lib/sequel/extensions/_pretty_table.rb +2 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +2 -0
- data/lib/sequel/extensions/columns_introspection.rb +2 -0
- data/lib/sequel/extensions/connection_validator.rb +2 -0
- data/lib/sequel/extensions/constraint_validations.rb +2 -0
- data/lib/sequel/extensions/core_extensions.rb +1 -5
- data/lib/sequel/extensions/current_datetime_timestamp.rb +2 -0
- data/lib/sequel/extensions/dataset_source_alias.rb +2 -0
- data/lib/sequel/extensions/date_arithmetic.rb +2 -0
- data/lib/sequel/extensions/empty_array_consider_nulls.rb +3 -1
- data/lib/sequel/extensions/error_sql.rb +2 -0
- data/lib/sequel/extensions/eval_inspect.rb +2 -0
- data/lib/sequel/extensions/filter_having.rb +2 -0
- data/lib/sequel/extensions/from_block.rb +2 -0
- data/lib/sequel/extensions/graph_each.rb +2 -0
- data/lib/sequel/extensions/hash_aliases.rb +2 -0
- data/lib/sequel/extensions/inflector.rb +2 -0
- data/lib/sequel/extensions/looser_typecasting.rb +3 -1
- data/lib/sequel/extensions/meta_def.rb +2 -0
- data/lib/sequel/extensions/migration.rb +4 -0
- data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +2 -0
- data/lib/sequel/extensions/named_timezones.rb +2 -0
- data/lib/sequel/extensions/no_auto_literal_strings.rb +84 -0
- data/lib/sequel/extensions/null_dataset.rb +2 -0
- data/lib/sequel/extensions/pagination.rb +2 -0
- data/lib/sequel/extensions/pg_array.rb +2 -4
- data/lib/sequel/extensions/pg_array_ops.rb +2 -0
- data/lib/sequel/extensions/pg_enum.rb +2 -0
- data/lib/sequel/extensions/pg_hstore.rb +2 -4
- data/lib/sequel/extensions/pg_hstore_ops.rb +2 -0
- data/lib/sequel/extensions/pg_inet.rb +2 -4
- data/lib/sequel/extensions/pg_inet_ops.rb +2 -0
- data/lib/sequel/extensions/pg_interval.rb +2 -4
- data/lib/sequel/extensions/pg_json.rb +4 -4
- data/lib/sequel/extensions/pg_json_ops.rb +3 -0
- data/lib/sequel/extensions/pg_loose_count.rb +2 -0
- data/lib/sequel/extensions/pg_range.rb +2 -4
- data/lib/sequel/extensions/pg_range_ops.rb +2 -0
- data/lib/sequel/extensions/pg_row.rb +2 -4
- data/lib/sequel/extensions/pg_row_ops.rb +2 -0
- data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -0
- data/lib/sequel/extensions/pretty_table.rb +2 -0
- data/lib/sequel/extensions/query.rb +3 -0
- data/lib/sequel/extensions/query_literals.rb +7 -5
- data/lib/sequel/extensions/round_timestamps.rb +4 -3
- data/lib/sequel/extensions/schema_caching.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +2 -0
- data/lib/sequel/extensions/select_remove.rb +2 -0
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +2 -0
- data/lib/sequel/extensions/server_block.rb +3 -0
- data/lib/sequel/extensions/set_overrides.rb +2 -0
- data/lib/sequel/extensions/split_array_nil.rb +2 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +2 -0
- data/lib/sequel/extensions/to_dot.rb +2 -0
- data/lib/sequel/model/associations.rb +95 -55
- data/lib/sequel/plugins/association_pks.rb +58 -33
- data/lib/sequel/plugins/eager_each.rb +22 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +3 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +44 -3
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/mysql_spec.rb +34 -6
- data/spec/adapters/oracle_spec.rb +1 -1
- data/spec/bin_spec.rb +2 -2
- data/spec/core/dataset_spec.rb +7 -0
- data/spec/extensions/association_pks_spec.rb +38 -0
- data/spec/extensions/class_table_inheritance_spec.rb +24 -0
- data/spec/extensions/eager_each_spec.rb +25 -1
- data/spec/extensions/no_auto_literal_strings_spec.rb +65 -0
- data/spec/extensions/pg_range_spec.rb +1 -0
- data/spec/extensions/spec_helper.rb +5 -5
- data/spec/extensions/tactical_eager_loading_spec.rb +71 -17
- data/spec/integration/associations_test.rb +77 -62
- data/spec/integration/dataset_test.rb +3 -3
- data/spec/integration/plugin_test.rb +22 -0
- data/spec/integration/prepared_statement_test.rb +8 -8
- data/spec/integration/spec_helper.rb +4 -0
- data/spec/model/association_reflection_spec.rb +30 -0
- data/spec/model/associations_spec.rb +177 -16
- metadata +6 -2
@@ -26,7 +26,6 @@ describe "Sequel::Plugins::EagerEach" do
|
|
26
26
|
it "should make #each on an eager_graph dataset do eager loading" do
|
27
27
|
a = []
|
28
28
|
ds = @c.eager_graph(:children)
|
29
|
-
ds._fetch = []
|
30
29
|
ds._fetch = [{:id=>1, :parent_id=>nil, :children_id=>3, :children_parent_id=>1}, {:id=>1, :parent_id=>nil, :children_id=>4, :children_parent_id=>1}, {:id=>2, :parent_id=>nil, :children_id=>5, :children_parent_id=>2}, {:id=>2, :parent_id=>nil, :children_id=>6, :children_parent_id=>2}]
|
31
30
|
ds.each{|c| a << c}
|
32
31
|
a.must_equal [@c.load(:id=>1, :parent_id=>nil), @c.load(:id=>2, :parent_id=>nil)]
|
@@ -34,6 +33,31 @@ describe "Sequel::Plugins::EagerEach" do
|
|
34
33
|
@c.db.sqls.must_equal ['SELECT items.id, items.parent_id, children.id AS children_id, children.parent_id AS children_parent_id FROM items LEFT OUTER JOIN items AS children ON (children.parent_id = items.id)']
|
35
34
|
end
|
36
35
|
|
36
|
+
it "should make #first on an eager dataset do eager loading" do
|
37
|
+
ds = @c.eager(:children)
|
38
|
+
ds._fetch = [{:id=>1, :parent_id=>nil}]
|
39
|
+
@c.dataset._fetch = [{:id=>3, :parent_id=>1}, {:id=>4, :parent_id=>1}]
|
40
|
+
a = ds.first
|
41
|
+
a.values.must_equal(:id=>1, :parent_id=>nil)
|
42
|
+
a.associations[:children].must_equal [@c.load(:id=>3, :parent_id=>1), @c.load(:id=>4, :parent_id=>1)]
|
43
|
+
@c.db.sqls.must_equal ['SELECT * FROM items LIMIT 1','SELECT * FROM items WHERE (items.parent_id IN (1))']
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should make #first on an eager_graph dataset do eager loading" do
|
47
|
+
ds = @c.eager_graph(:children)
|
48
|
+
ds._fetch = [[{:id=>1, :parent_id=>nil, :children_id=>3, :children_parent_id=>1}], [{:id=>1, :parent_id=>nil, :children_id=>3, :children_parent_id=>1}, {:id=>1, :parent_id=>nil, :children_id=>4, :children_parent_id=>1}]]
|
49
|
+
a = ds.first
|
50
|
+
a.values.must_equal(:id=>1, :parent_id=>nil)
|
51
|
+
a.associations[:children].must_equal [@c.load(:id=>3, :parent_id=>1), @c.load(:id=>4, :parent_id=>1)]
|
52
|
+
@c.db.sqls.must_equal ['SELECT items.id, items.parent_id, children.id AS children_id, children.parent_id AS children_parent_id FROM items LEFT OUTER JOIN items AS children ON (children.parent_id = items.id) LIMIT 1',
|
53
|
+
'SELECT items.id, items.parent_id, children.id AS children_id, children.parent_id AS children_parent_id FROM items LEFT OUTER JOIN items AS children ON (children.parent_id = items.id) WHERE (items.id = 1)']
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should make #first on a non-eager dataset work correctly" do
|
57
|
+
@c.dataset._fetch = [{:id=>1, :parent_id=>nil}]
|
58
|
+
@c.first.must_equal @c.load(:id=>1, :parent_id=>nil)
|
59
|
+
end
|
60
|
+
|
37
61
|
it "should not attempt to eager load when getting the columns" do
|
38
62
|
ds = @c.eager(:children)
|
39
63
|
def ds.all; raise; end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
+
|
3
|
+
describe "no_auto_literal_strings extension" do
|
4
|
+
before do
|
5
|
+
@ds = Sequel.mock[:t].extension(:no_auto_literal_strings)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should raise exception for plain strings in filter methods" do
|
9
|
+
proc{@ds.where("a")}.must_raise Sequel::Error
|
10
|
+
proc{@ds.having("a")}.must_raise Sequel::Error
|
11
|
+
proc{@ds.filter("a")}.must_raise Sequel::Error
|
12
|
+
proc{@ds.exclude_where("a")}.must_raise Sequel::Error
|
13
|
+
proc{@ds.exclude_having("a")}.must_raise Sequel::Error
|
14
|
+
proc{@ds.and("a")}.must_raise Sequel::Error
|
15
|
+
proc{@ds.where(:a).or("a")}.must_raise Sequel::Error
|
16
|
+
proc{@ds.first("a")}.must_raise Sequel::Error
|
17
|
+
proc{@ds.order(:a).last("a")}.must_raise Sequel::Error
|
18
|
+
proc{@ds["a"]}.must_raise Sequel::Error
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should raise exception for plain strings arrays in filter methods" do
|
22
|
+
proc{@ds.where(["a"])}.must_raise Sequel::Error
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should handle explicit literal strings in filter methods" do
|
26
|
+
@ds.where(Sequel.lit("a")).sql.must_equal 'SELECT * FROM t WHERE (a)'
|
27
|
+
@ds.having(Sequel.lit("a")).sql.must_equal 'SELECT * FROM t HAVING (a)'
|
28
|
+
@ds.filter(Sequel.lit("a")).sql.must_equal 'SELECT * FROM t WHERE (a)'
|
29
|
+
@ds.exclude_where(Sequel.lit("a")).sql.must_equal 'SELECT * FROM t WHERE NOT (a)'
|
30
|
+
@ds.exclude_having(Sequel.lit("a")).sql.must_equal 'SELECT * FROM t HAVING NOT (a)'
|
31
|
+
@ds.and(Sequel.lit("a")).sql.must_equal 'SELECT * FROM t WHERE (a)'
|
32
|
+
@ds.where(:a).or(Sequel.lit("a")).sql.must_equal 'SELECT * FROM t WHERE (a OR (a))'
|
33
|
+
@ds.first(Sequel.lit("a"))
|
34
|
+
@ds.order(:a).last(Sequel.lit("a"))
|
35
|
+
@ds[Sequel.lit("a")]
|
36
|
+
@ds.db.sqls.must_equal ["SELECT * FROM t WHERE (a) LIMIT 1",
|
37
|
+
"SELECT * FROM t WHERE (a) ORDER BY a DESC LIMIT 1",
|
38
|
+
"SELECT * FROM t WHERE (a) LIMIT 1"]
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should handle literal strings in arrays in filter methods" do
|
42
|
+
@ds.where([Sequel.lit("a")]).sql.must_equal 'SELECT * FROM t WHERE (a)'
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should handle other objects in filter methods" do
|
46
|
+
@ds.where(:a).sql.must_equal 'SELECT * FROM t WHERE a'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should raise exception for plain strings in update methods" do
|
50
|
+
proc{@ds.update("a = a + 1")}.must_raise Sequel::Error
|
51
|
+
proc{@ds.update_sql("a = a + 1")}.must_raise Sequel::Error
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should handle explicit literal strings in update methods" do
|
55
|
+
@ds.update_sql(Sequel.lit("a = a + 1")).must_equal "UPDATE t SET a = a + 1"
|
56
|
+
@ds.update(Sequel.lit("a = a + 1"))
|
57
|
+
@ds.db.sqls.must_equal ["UPDATE t SET a = a + 1"]
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should handle other objects in update methods" do
|
61
|
+
@ds.update_sql(:a=>:a).must_equal "UPDATE t SET a = a"
|
62
|
+
@ds.update(:a=>:a)
|
63
|
+
@ds.db.sqls.must_equal ["UPDATE t SET a = a"]
|
64
|
+
end
|
65
|
+
end
|
@@ -38,6 +38,7 @@ describe "pg_range extension" do
|
|
38
38
|
@db.literal(@R.new(1, nil)).must_equal "'[1,]'"
|
39
39
|
@db.literal(@R.new(1, 2, :db_type=>'int8range')).must_equal "int8range(1,2,'[]')"
|
40
40
|
@db.literal(@R.new(nil, nil, :empty=>true)).must_equal "'empty'"
|
41
|
+
@db.literal(@R.new(nil, nil, :empty=>true, :db_type=>'int8range')).must_equal "'empty'::int8range"
|
41
42
|
@db.literal(@R.new("", 2)).must_equal "'[\"\",2]'"
|
42
43
|
end
|
43
44
|
|
@@ -1,15 +1,15 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
|
3
|
-
gem 'minitest'
|
4
|
-
require 'minitest/autorun'
|
5
|
-
require 'minitest/hooks/default'
|
6
|
-
require 'minitest/shared_description'
|
7
|
-
|
8
3
|
if ENV['COVERAGE']
|
9
4
|
require File.join(File.dirname(File.expand_path(__FILE__)), "../sequel_coverage")
|
10
5
|
SimpleCov.sequel_coverage(:filter=>%r{lib/sequel/(extensions|plugins)/\w+\.rb\z})
|
11
6
|
end
|
12
7
|
|
8
|
+
gem 'minitest'
|
9
|
+
require 'minitest/autorun'
|
10
|
+
require 'minitest/hooks/default'
|
11
|
+
require 'minitest/shared_description'
|
12
|
+
|
13
13
|
unless Object.const_defined?('Sequel') && Sequel.const_defined?('Model')
|
14
14
|
$:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), "../../lib/"))
|
15
15
|
require 'sequel'
|
@@ -1,8 +1,22 @@
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
2
|
|
3
3
|
describe "Sequel::Plugins::TacticalEagerLoading" do
|
4
|
+
def sql_match(*args)
|
5
|
+
sqls = DB.sqls
|
6
|
+
sqls.length.must_equal args.length
|
7
|
+
sqls.zip(args).each do |is, should|
|
8
|
+
if should.is_a?(Regexp)
|
9
|
+
is.must_match should
|
10
|
+
else
|
11
|
+
is.must_equal should
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :ts
|
17
|
+
|
4
18
|
before do
|
5
|
-
class ::TacticalEagerLoadingModel < Sequel::Model
|
19
|
+
class ::TacticalEagerLoadingModel < Sequel::Model(:t)
|
6
20
|
plugin :tactical_eager_loading
|
7
21
|
columns :id, :parent_id
|
8
22
|
many_to_one :parent, :class=>self
|
@@ -22,61 +36,101 @@ describe "Sequel::Plugins::TacticalEagerLoading" do
|
|
22
36
|
@c = ::TacticalEagerLoadingModel
|
23
37
|
@ds = TacticalEagerLoadingModel.dataset
|
24
38
|
DB.reset
|
39
|
+
@ts = @c.all
|
40
|
+
sql_match('SELECT * FROM t')
|
25
41
|
end
|
26
42
|
after do
|
27
43
|
Object.send(:remove_const, :TacticalEagerLoadingModel)
|
44
|
+
sql_match
|
28
45
|
end
|
29
46
|
|
30
47
|
it "Dataset#all should set the retrieved_by and retrieved_with attributes" do
|
31
|
-
ts = @c.all
|
32
48
|
ts.map{|x| [x.retrieved_by, x.retrieved_with]}.must_equal [[@ds,ts], [@ds,ts], [@ds,ts], [@ds,ts]]
|
33
49
|
end
|
34
50
|
|
35
51
|
it "Dataset#all shouldn't raise an error if a Sequel::Model instance is not returned" do
|
36
52
|
@c.naked.all
|
53
|
+
sql_match('SELECT * FROM t')
|
37
54
|
end
|
38
55
|
|
39
56
|
it "association getter methods should eagerly load the association if the association isn't cached" do
|
40
|
-
DB.sqls.length.must_equal 0
|
41
|
-
ts = @c.all
|
42
|
-
DB.sqls.length.must_equal 1
|
43
57
|
ts.map{|x| x.parent}.must_equal [ts[2], ts[3], nil, nil]
|
44
|
-
|
58
|
+
sql_match(/\ASELECT \* FROM t WHERE \(t\.id IN \(10[12], 10[12]\)\)\z/)
|
45
59
|
ts.map{|x| x.children}.must_equal [[], [], [ts[0]], [ts[1]]]
|
46
|
-
|
60
|
+
sql_match(/\ASELECT \* FROM t WHERE \(t\.parent_id IN/)
|
47
61
|
end
|
48
62
|
|
49
63
|
it "association getter methods should not eagerly load the association if the association is cached" do
|
50
|
-
DB.sqls.length.must_equal 0
|
51
|
-
ts = @c.all
|
52
|
-
DB.sqls.length.must_equal 1
|
53
64
|
ts.map{|x| x.parent}.must_equal [ts[2], ts[3], nil, nil]
|
65
|
+
sql_match(/\ASELECT \* FROM t WHERE \(t\.id IN \(10[12], 10[12]\)\)\z/)
|
54
66
|
def @ds.eager_load(*) raise end
|
55
67
|
ts.map{|x| x.parent}.must_equal [ts[2], ts[3], nil, nil]
|
56
68
|
end
|
57
69
|
|
70
|
+
it "association getter methods should not eagerly load the association if a block is given" do
|
71
|
+
ts.map{|x| x.parent{|ds| ds}}.must_equal [ts[2], ts[3], nil, nil]
|
72
|
+
sql_match('SELECT * FROM t WHERE (t.id = 101) LIMIT 1', 'SELECT * FROM t WHERE (t.id = 102) LIMIT 1')
|
73
|
+
end
|
74
|
+
|
75
|
+
it "association getter methods should not eagerly load the association if a callback proc is given" do
|
76
|
+
ts.map{|x| x.parent(:callback=>proc{|ds| ds})}.must_equal [ts[2], ts[3], nil, nil]
|
77
|
+
sql_match('SELECT * FROM t WHERE (t.id = 101) LIMIT 1', 'SELECT * FROM t WHERE (t.id = 102) LIMIT 1')
|
78
|
+
end
|
79
|
+
|
80
|
+
it "association getter methods should not eagerly load the association if true is passed" do
|
81
|
+
ts.map{|x| x.parent(true)}.must_equal [ts[2], ts[3], nil, nil]
|
82
|
+
sql_match('SELECT * FROM t WHERE id = 101', 'SELECT * FROM t WHERE id = 102')
|
83
|
+
end
|
84
|
+
|
85
|
+
it "association getter methods should not eagerly load the association if :reload=>true is passed" do
|
86
|
+
ts.map{|x| x.parent(:reload=>true)}.must_equal [ts[2], ts[3], nil, nil]
|
87
|
+
sql_match('SELECT * FROM t WHERE id = 101', 'SELECT * FROM t WHERE id = 102')
|
88
|
+
end
|
89
|
+
|
90
|
+
it "association getter methods should eagerly reload the association if :eager_reload=>true is passed" do
|
91
|
+
ts.first.parent(:reload=>true)
|
92
|
+
sql_match('SELECT * FROM t WHERE id = 101')
|
93
|
+
ts.map{|x| x.associations.fetch(:parent, 1)}.must_equal [ts[2], 1, 1, 1]
|
94
|
+
ts.first.parent(:eager_reload=>true)
|
95
|
+
sql_match(/\ASELECT \* FROM t WHERE \(t\.id IN \(10[12], 10[12]\)\)\z/)
|
96
|
+
ts.map{|x| x.associations.fetch(:parent, 1)}.must_equal [ts[2], ts[3], nil, nil]
|
97
|
+
end
|
98
|
+
|
99
|
+
it "association getter methods should support eagerly loading dependent associations via :eager" do
|
100
|
+
parents = ts.map{|x| x.parent(:eager=>:children)}
|
101
|
+
sql_match(/\ASELECT \* FROM t WHERE \(t\.id IN \(10[12], 10[12]\)\)\z/, /\ASELECT \* FROM t WHERE \(t\.parent_id IN/)
|
102
|
+
parents.must_equal [ts[2], ts[3], nil, nil]
|
103
|
+
parents[0..1].map{|x| x.children}.must_equal [[ts[0]], [ts[1]]]
|
104
|
+
end
|
105
|
+
|
106
|
+
it "association getter methods should support eager callbacks via :eager" do
|
107
|
+
parents = ts.map{|x| x.parent(:eager=>proc{|ds| ds.where{name > 'M'}.eager(:children)})}
|
108
|
+
sql_match(/\ASELECT \* FROM t WHERE \(\(t\.id IN \(10[12], 10[12]\)\) AND \(name > 'M'\)\)\z/, /\ASELECT \* FROM t WHERE \(t\.parent_id IN/)
|
109
|
+
parents.must_equal [ts[2], ts[3], nil, nil]
|
110
|
+
parents[0..1].map{|x| x.children}.must_equal [[ts[0]], [ts[1]]]
|
111
|
+
end
|
112
|
+
|
58
113
|
it "should handle case where an association is valid on an instance, but not on all instances" do
|
59
114
|
c = Class.new(@c)
|
60
115
|
c.many_to_one :parent2, :class=>@c, :key=>:parent_id
|
61
116
|
@c.dataset.row_proc = proc{|r| (r[:parent_id] == 101 ? c : @c).call(r)}
|
62
117
|
@c.all{|x| x.parent2 if x.is_a?(c)}
|
118
|
+
sql_match('SELECT * FROM t', 'SELECT * FROM t WHERE id = 101')
|
63
119
|
end
|
64
120
|
|
65
121
|
it "association getter methods should not eagerly load the association if an instance is frozen" do
|
66
|
-
ts = @c.all
|
67
122
|
ts.first.freeze
|
68
|
-
DB.sqls.length.must_equal 1
|
69
123
|
ts.map{|x| x.parent}.must_equal [ts[2], ts[3], nil, nil]
|
70
|
-
|
124
|
+
sql_match('SELECT * FROM t WHERE id = 101', 'SELECT * FROM t WHERE (t.id IN (102))')
|
71
125
|
ts.map{|x| x.children}.must_equal [[], [], [ts[0]], [ts[1]]]
|
72
|
-
|
126
|
+
sql_match('SELECT * FROM t WHERE (t.parent_id = 1)', /\ASELECT \* FROM t WHERE \(t\.parent_id IN/)
|
73
127
|
ts.map{|x| x.parent}.must_equal [ts[2], ts[3], nil, nil]
|
74
|
-
|
128
|
+
sql_match('SELECT * FROM t WHERE id = 101')
|
75
129
|
ts.map{|x| x.children}.must_equal [[], [], [ts[0]], [ts[1]]]
|
76
|
-
|
130
|
+
sql_match('SELECT * FROM t WHERE (t.parent_id = 1)')
|
77
131
|
end
|
78
132
|
|
79
133
|
it "#marshallable should make marshalling not fail" do
|
80
|
-
Marshal.dump(
|
134
|
+
Marshal.dump(ts.map{|x| x.marshallable!})
|
81
135
|
end
|
82
136
|
end
|
@@ -1501,22 +1501,83 @@ BasicRegularAndCompositeKeyAssociations = shared_description do
|
|
1501
1501
|
@album.tags.must_equal []
|
1502
1502
|
@album.alias_tags.must_equal []
|
1503
1503
|
@tag.albums.must_equal []
|
1504
|
+
unless @no_many_through_many
|
1505
|
+
@album.first_tag.must_equal nil
|
1506
|
+
end
|
1504
1507
|
end
|
1505
1508
|
|
1506
|
-
it "should have
|
1509
|
+
it "should have set methods work" do
|
1510
|
+
# many to one
|
1507
1511
|
@album.update(:artist => @artist)
|
1512
|
+
@album.reload.artist.must_equal @artist
|
1513
|
+
@album.update(:artist => nil)
|
1514
|
+
@album.reload.artist.must_equal nil
|
1515
|
+
|
1516
|
+
# one to one
|
1517
|
+
@artist.update(:first_album => @album)
|
1518
|
+
@artist.reload.first_album.must_equal @album
|
1519
|
+
@artist.update(:first_album => nil)
|
1520
|
+
@artist.reload.first_album.must_equal nil
|
1521
|
+
|
1522
|
+
unless @no_many_through_many
|
1523
|
+
tag = @pr.call.last
|
1524
|
+
# one through one
|
1525
|
+
@album.update(:first_tag => @tag)
|
1526
|
+
@album.reload.first_tag.must_equal @tag
|
1527
|
+
@album.update(:first_tag => @tag)
|
1528
|
+
@album.reload.first_tag.must_equal @tag
|
1529
|
+
@album.update(:first_tag => tag)
|
1530
|
+
@album.reload.first_tag.must_equal tag
|
1531
|
+
@album.update(:first_tag => nil)
|
1532
|
+
@album.reload.first_tag.must_equal nil
|
1533
|
+
@album.update(:first_tag => nil)
|
1534
|
+
@album.reload.first_tag.must_equal nil
|
1535
|
+
|
1536
|
+
# one through one with alias
|
1537
|
+
@album.update(:alias_t_tag => @tag)
|
1538
|
+
@album.reload.alias_t_tag.must_equal @tag
|
1539
|
+
@album.update(:alias_t_tag => nil)
|
1540
|
+
@album.reload.alias_t_tag.must_equal nil
|
1541
|
+
end
|
1542
|
+
end
|
1543
|
+
|
1544
|
+
it "should have add and remove methods work" do
|
1545
|
+
# one to many
|
1546
|
+
@artist.add_album(@album)
|
1547
|
+
@artist.reload.albums.must_equal [@album]
|
1548
|
+
@artist.remove_album(@album)
|
1549
|
+
@artist.reload.albums.must_equal []
|
1550
|
+
|
1551
|
+
# many to many
|
1508
1552
|
@album.add_tag(@tag)
|
1509
|
-
|
1510
|
-
@
|
1511
|
-
@artist.reload
|
1512
|
-
@tag.reload
|
1513
|
-
|
1514
|
-
@album.artist.must_equal @artist
|
1515
|
-
@artist.first_album.must_equal @album
|
1516
|
-
@artist.albums.must_equal [@album]
|
1517
|
-
@album.tags.must_equal [@tag]
|
1553
|
+
@album.reload.tags.must_equal [@tag]
|
1554
|
+
@tag.reload.albums.must_equal [@album]
|
1518
1555
|
@album.alias_tags.must_equal [@tag]
|
1519
|
-
@
|
1556
|
+
@album.remove_tag(@tag)
|
1557
|
+
@album.reload.tags.must_equal []
|
1558
|
+
|
1559
|
+
# many to many with alias
|
1560
|
+
@album.add_alias_tag(@tag)
|
1561
|
+
@album.reload.alias_tags.must_equal [@tag]
|
1562
|
+
@album.remove_alias_tag(@tag)
|
1563
|
+
@album.reload.alias_tags.must_equal []
|
1564
|
+
end
|
1565
|
+
|
1566
|
+
it "should have remove_all methods work" do
|
1567
|
+
# one to many
|
1568
|
+
@artist.add_album(@album)
|
1569
|
+
@artist.remove_all_albums
|
1570
|
+
@artist.reload.albums.must_equal []
|
1571
|
+
|
1572
|
+
# many to many
|
1573
|
+
@album.add_tag(@tag)
|
1574
|
+
@album.remove_all_tags
|
1575
|
+
@album.reload.tags.must_equal []
|
1576
|
+
|
1577
|
+
# many to many with alias
|
1578
|
+
@album.add_alias_tag(@tag)
|
1579
|
+
@album.remove_all_alias_tags
|
1580
|
+
@album.reload.alias_tags.must_equal []
|
1520
1581
|
end
|
1521
1582
|
|
1522
1583
|
it "should work correctly with prepared_statements_association plugin" do
|
@@ -1534,6 +1595,9 @@ BasicRegularAndCompositeKeyAssociations = shared_description do
|
|
1534
1595
|
@album.tags.must_equal [@tag]
|
1535
1596
|
@album.alias_tags.must_equal [@tag]
|
1536
1597
|
@tag.albums.must_equal [@album]
|
1598
|
+
unless @no_many_through_many
|
1599
|
+
@album.first_tag.must_equal @tag
|
1600
|
+
end
|
1537
1601
|
end
|
1538
1602
|
|
1539
1603
|
it "should have working dataset associations" do
|
@@ -1599,55 +1663,6 @@ BasicRegularAndCompositeKeyAssociations = shared_description do
|
|
1599
1663
|
Artist.filter(Artist.qualified_primary_key_hash(artist.pk)).albums.filter(Album.qualified_primary_key_hash(@album.pk)).tags.all.must_equal []
|
1600
1664
|
end
|
1601
1665
|
|
1602
|
-
it "should have remove methods work" do
|
1603
|
-
@album.update(:artist => @artist)
|
1604
|
-
@album.add_tag(@tag)
|
1605
|
-
|
1606
|
-
@album.update(:artist => nil)
|
1607
|
-
@album.remove_tag(@tag)
|
1608
|
-
|
1609
|
-
@album.add_alias_tag(@tag)
|
1610
|
-
@album.remove_alias_tag(@tag)
|
1611
|
-
|
1612
|
-
@album.reload
|
1613
|
-
@artist.reload
|
1614
|
-
@tag.reload
|
1615
|
-
|
1616
|
-
@album.artist.must_equal nil
|
1617
|
-
@artist.albums.must_equal []
|
1618
|
-
@album.tags.must_equal []
|
1619
|
-
@tag.albums.must_equal []
|
1620
|
-
|
1621
|
-
@album.add_alias_tag(@tag)
|
1622
|
-
@album.remove_alias_tag(@tag)
|
1623
|
-
|
1624
|
-
@album.reload
|
1625
|
-
@album.alias_tags.must_equal []
|
1626
|
-
end
|
1627
|
-
|
1628
|
-
it "should have remove_all methods work" do
|
1629
|
-
@artist.add_album(@album)
|
1630
|
-
@album.add_tag(@tag)
|
1631
|
-
|
1632
|
-
@album.remove_all_tags
|
1633
|
-
@artist.remove_all_albums
|
1634
|
-
|
1635
|
-
@album.reload
|
1636
|
-
@artist.reload
|
1637
|
-
@tag.reload
|
1638
|
-
|
1639
|
-
@album.artist.must_equal nil
|
1640
|
-
@artist.albums.must_equal []
|
1641
|
-
@album.tags.must_equal []
|
1642
|
-
@tag.albums.must_equal []
|
1643
|
-
|
1644
|
-
@album.add_alias_tag(@tag)
|
1645
|
-
@album.remove_all_alias_tags
|
1646
|
-
|
1647
|
-
@album.reload
|
1648
|
-
@album.alias_tags.must_equal []
|
1649
|
-
end
|
1650
|
-
|
1651
1666
|
it "should eager load via eager correctly" do
|
1652
1667
|
@album.update(:artist => @artist)
|
1653
1668
|
@album.add_tag(@tag)
|
@@ -1684,8 +1699,6 @@ BasicRegularAndCompositeKeyAssociations = shared_description do
|
|
1684
1699
|
end
|
1685
1700
|
|
1686
1701
|
RegularAndCompositeKeyAssociations = shared_description do
|
1687
|
-
include BasicRegularAndCompositeKeyAssociations
|
1688
|
-
|
1689
1702
|
describe "when filtering/excluding by associations when joining" do
|
1690
1703
|
def self_join(c)
|
1691
1704
|
c.join(Sequel.as(c.table_name, :b), Array(c.primary_key).zip(Array(c.primary_key))).select_all(c.table_name)
|
@@ -1884,6 +1897,7 @@ describe "Sequel::Model Simple Associations" do
|
|
1884
1897
|
@db.drop_table?(:albums_tags, :tags, :albums, :artists)
|
1885
1898
|
end
|
1886
1899
|
|
1900
|
+
include BasicRegularAndCompositeKeyAssociations
|
1887
1901
|
include RegularAndCompositeKeyAssociations
|
1888
1902
|
|
1889
1903
|
describe "with :correlated_subquery limit strategy" do
|
@@ -2160,6 +2174,7 @@ describe "Sequel::Model Composite Key Associations" do
|
|
2160
2174
|
@db.drop_table?(:albums_tags, :tags, :albums, :artists)
|
2161
2175
|
end
|
2162
2176
|
|
2177
|
+
include BasicRegularAndCompositeKeyAssociations
|
2163
2178
|
include RegularAndCompositeKeyAssociations
|
2164
2179
|
|
2165
2180
|
describe "with :correlated_subquery limit strategy" do
|