sequel 4.9.0 → 4.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +79 -1
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/Rakefile +2 -12
- data/bin/sequel +1 -0
- data/doc/advanced_associations.rdoc +82 -25
- data/doc/association_basics.rdoc +21 -22
- data/doc/core_extensions.rdoc +1 -1
- data/doc/opening_databases.rdoc +7 -0
- data/doc/release_notes/4.10.0.txt +226 -0
- data/doc/security.rdoc +1 -0
- data/doc/testing.rdoc +7 -7
- data/doc/transactions.rdoc +8 -0
- data/lib/sequel/adapters/jdbc.rb +160 -168
- data/lib/sequel/adapters/jdbc/db2.rb +17 -18
- data/lib/sequel/adapters/jdbc/derby.rb +5 -28
- data/lib/sequel/adapters/jdbc/h2.rb +11 -22
- data/lib/sequel/adapters/jdbc/hsqldb.rb +31 -18
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -15
- data/lib/sequel/adapters/jdbc/oracle.rb +36 -35
- data/lib/sequel/adapters/jdbc/postgresql.rb +72 -90
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +18 -16
- data/lib/sequel/adapters/jdbc/sqlite.rb +7 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +10 -30
- data/lib/sequel/adapters/jdbc/transactions.rb +5 -6
- data/lib/sequel/adapters/openbase.rb +1 -7
- data/lib/sequel/adapters/postgres.rb +1 -1
- data/lib/sequel/adapters/shared/access.rb +3 -6
- data/lib/sequel/adapters/shared/cubrid.rb +24 -9
- data/lib/sequel/adapters/shared/db2.rb +13 -5
- data/lib/sequel/adapters/shared/firebird.rb +16 -16
- data/lib/sequel/adapters/shared/informix.rb +2 -5
- data/lib/sequel/adapters/shared/mssql.rb +72 -63
- data/lib/sequel/adapters/shared/mysql.rb +72 -40
- data/lib/sequel/adapters/shared/oracle.rb +27 -15
- data/lib/sequel/adapters/shared/postgres.rb +24 -44
- data/lib/sequel/adapters/shared/progress.rb +1 -5
- data/lib/sequel/adapters/shared/sqlanywhere.rb +26 -18
- data/lib/sequel/adapters/shared/sqlite.rb +21 -6
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +8 -1
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -2
- data/lib/sequel/adapters/utils/split_alter_table.rb +8 -0
- data/lib/sequel/core.rb +14 -9
- data/lib/sequel/database/dataset_defaults.rb +1 -0
- data/lib/sequel/database/misc.rb +12 -0
- data/lib/sequel/database/query.rb +4 -1
- data/lib/sequel/database/schema_methods.rb +3 -2
- data/lib/sequel/database/transactions.rb +47 -17
- data/lib/sequel/dataset/features.rb +12 -2
- data/lib/sequel/dataset/mutation.rb +2 -0
- data/lib/sequel/dataset/placeholder_literalizer.rb +12 -4
- data/lib/sequel/dataset/prepared_statements.rb +6 -0
- data/lib/sequel/dataset/query.rb +1 -1
- data/lib/sequel/dataset/sql.rb +132 -70
- data/lib/sequel/extensions/columns_introspection.rb +1 -1
- data/lib/sequel/extensions/null_dataset.rb +8 -4
- data/lib/sequel/extensions/pg_array.rb +4 -4
- data/lib/sequel/extensions/pg_row.rb +1 -0
- data/lib/sequel/model/associations.rb +468 -188
- data/lib/sequel/model/base.rb +88 -13
- data/lib/sequel/plugins/association_pks.rb +23 -64
- data/lib/sequel/plugins/auto_validations.rb +3 -2
- data/lib/sequel/plugins/dataset_associations.rb +1 -3
- data/lib/sequel/plugins/many_through_many.rb +18 -65
- data/lib/sequel/plugins/pg_array_associations.rb +97 -86
- data/lib/sequel/plugins/prepared_statements.rb +2 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +36 -27
- data/lib/sequel/plugins/rcte_tree.rb +12 -16
- data/lib/sequel/plugins/sharding.rb +21 -3
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -1
- data/lib/sequel/plugins/subclasses.rb +1 -9
- data/lib/sequel/plugins/tactical_eager_loading.rb +9 -0
- data/lib/sequel/plugins/tree.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +57 -15
- data/spec/adapters/mysql_spec.rb +11 -0
- data/spec/bin_spec.rb +2 -2
- data/spec/core/database_spec.rb +38 -4
- data/spec/core/dataset_spec.rb +45 -7
- data/spec/core/placeholder_literalizer_spec.rb +17 -0
- data/spec/core/schema_spec.rb +6 -1
- data/spec/extensions/active_model_spec.rb +18 -9
- data/spec/extensions/association_pks_spec.rb +20 -18
- data/spec/extensions/association_proxies_spec.rb +9 -9
- data/spec/extensions/auto_validations_spec.rb +6 -0
- data/spec/extensions/columns_introspection_spec.rb +1 -0
- data/spec/extensions/constraint_validations_spec.rb +3 -1
- data/spec/extensions/many_through_many_spec.rb +191 -111
- data/spec/extensions/pg_array_associations_spec.rb +133 -103
- data/spec/extensions/prepared_statements_associations_spec.rb +23 -4
- data/spec/extensions/rcte_tree_spec.rb +35 -27
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -1
- data/spec/extensions/sharding_spec.rb +2 -2
- data/spec/extensions/tactical_eager_loading_spec.rb +4 -0
- data/spec/extensions/to_dot_spec.rb +1 -0
- data/spec/extensions/touch_spec.rb +2 -2
- data/spec/integration/associations_test.rb +130 -37
- data/spec/integration/dataset_test.rb +17 -0
- data/spec/integration/model_test.rb +17 -0
- data/spec/integration/schema_test.rb +14 -0
- data/spec/integration/transaction_test.rb +25 -1
- data/spec/model/association_reflection_spec.rb +63 -24
- data/spec/model/associations_spec.rb +104 -57
- data/spec/model/base_spec.rb +14 -1
- data/spec/model/class_dataset_methods_spec.rb +1 -0
- data/spec/model/eager_loading_spec.rb +221 -74
- data/spec/model/model_spec.rb +119 -1
- metadata +4 -2
@@ -22,8 +22,10 @@ describe "Sequel::Plugins::PreparedStatementsAssociations" do
|
|
22
22
|
@Artist.one_to_one :album, :class=>@Album, :key=>:artist_id
|
23
23
|
@Album.many_to_one :artist, :class=>@Artist
|
24
24
|
@Album.many_to_many :tags, :class=>@Tag, :join_table=>:albums_tags, :left_key=>:album_id
|
25
|
+
@Album.one_through_one :tag, :clone=>:tags
|
25
26
|
@Artist.plugin :many_through_many
|
26
27
|
@Artist.many_through_many :tags, [[:albums, :artist_id, :id], [:albums_tags, :album_id, :tag_id]], :class=>@Tag
|
28
|
+
@Artist.one_through_many :tag, :clone=>:tags
|
27
29
|
@db.sqls
|
28
30
|
end
|
29
31
|
|
@@ -38,10 +40,16 @@ describe "Sequel::Plugins::PreparedStatementsAssociations" do
|
|
38
40
|
@db.sqls.should == ["SELECT * FROM artists WHERE (artists.id = 2) LIMIT 1 -- prepared"]
|
39
41
|
|
40
42
|
@Album.load(:id=>1, :artist_id=>2).tags
|
41
|
-
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON (
|
43
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE (albums_tags.album_id = 1) -- prepared"]
|
44
|
+
|
45
|
+
@Album.load(:id=>1, :artist_id=>2).tag
|
46
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE (albums_tags.album_id = 1) LIMIT 1 -- prepared"]
|
42
47
|
|
43
48
|
@Artist.load(:id=>1).tags
|
44
|
-
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (
|
49
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) WHERE (albums.artist_id = 1) -- prepared"]
|
50
|
+
|
51
|
+
@Artist.load(:id=>1).tag
|
52
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) WHERE (albums.artist_id = 1) LIMIT 1 -- prepared"]
|
45
53
|
end
|
46
54
|
|
47
55
|
specify "should run correct SQL for composite key associations" do
|
@@ -49,7 +57,10 @@ describe "Sequel::Plugins::PreparedStatementsAssociations" do
|
|
49
57
|
@Artist.one_to_one :album, :class=>@Album, :key=>[:artist_id, :artist_id2], :primary_key=>[:id, :id2]
|
50
58
|
@Album.many_to_one :artist, :class=>@Artist, :key=>[:artist_id, :artist_id2], :primary_key=>[:id, :id2]
|
51
59
|
@Album.many_to_many :tags, :class=>@Tag, :join_table=>:albums_tags, :left_key=>[:album_id, :album_id2], :right_key=>[:tag_id, :tag_id2], :right_primary_key=>[:id, :id2], :left_primary_key=>[:id, :id2]
|
60
|
+
@Album.one_through_one :tag, :clone=>:tags
|
61
|
+
|
52
62
|
@Artist.many_through_many :tags, [[:albums, [:artist_id, :artist_id2], [:id, :id2]], [:albums_tags, [:album_id, :album_id2], [:tag_id, :tag_id2]]], :class=>@Tag, :right_primary_key=>[:id, :id2], :left_primary_key=>[:id, :id2]
|
63
|
+
@Artist.one_through_many :tag, :clone=>:tags
|
53
64
|
|
54
65
|
@Artist.load(:id=>1, :id2=>2).albums
|
55
66
|
@db.sqls.should == ["SELECT * FROM albums WHERE ((albums.artist_id = 1) AND (albums.artist_id2 = 2)) -- prepared"]
|
@@ -61,10 +72,16 @@ describe "Sequel::Plugins::PreparedStatementsAssociations" do
|
|
61
72
|
@db.sqls.should == ["SELECT * FROM artists WHERE ((artists.id = 2) AND (artists.id2 = 3)) LIMIT 1 -- prepared"]
|
62
73
|
|
63
74
|
@Album.load(:id=>1, :artist_id=>2, :id2=>3).tags
|
64
|
-
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id = tags.id) AND (albums_tags.tag_id2 = tags.id2)
|
75
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id = tags.id) AND (albums_tags.tag_id2 = tags.id2)) WHERE ((albums_tags.album_id = 1) AND (albums_tags.album_id2 = 3)) -- prepared"]
|
76
|
+
|
77
|
+
@Album.load(:id=>1, :artist_id=>2, :id2=>3).tag
|
78
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id = tags.id) AND (albums_tags.tag_id2 = tags.id2)) WHERE ((albums_tags.album_id = 1) AND (albums_tags.album_id2 = 3)) LIMIT 1 -- prepared"]
|
65
79
|
|
66
80
|
@Artist.load(:id=>1, :id2=>2).tags
|
67
|
-
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id = tags.id) AND (albums_tags.tag_id2 = tags.id2)) INNER JOIN albums ON ((albums.id = albums_tags.album_id) AND (albums.id2 = albums_tags.album_id2)
|
81
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id = tags.id) AND (albums_tags.tag_id2 = tags.id2)) INNER JOIN albums ON ((albums.id = albums_tags.album_id) AND (albums.id2 = albums_tags.album_id2)) WHERE ((albums.artist_id = 1) AND (albums.artist_id2 = 2)) -- prepared"]
|
82
|
+
|
83
|
+
@Artist.load(:id=>1, :id2=>2).tag
|
84
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id = tags.id) AND (albums_tags.tag_id2 = tags.id2)) INNER JOIN albums ON ((albums.id = albums_tags.album_id) AND (albums.id2 = albums_tags.album_id2)) WHERE ((albums.artist_id = 1) AND (albums.artist_id2 = 2)) LIMIT 1 -- prepared"]
|
68
85
|
end
|
69
86
|
|
70
87
|
specify "should not run query if no objects can be associated" do
|
@@ -76,6 +93,8 @@ describe "Sequel::Plugins::PreparedStatementsAssociations" do
|
|
76
93
|
specify "should run a regular query if there is a callback" do
|
77
94
|
@Artist.load(:id=>1).albums(proc{|ds| ds})
|
78
95
|
@db.sqls.should == ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
96
|
+
@Artist.load(:id=>1).album(proc{|ds| ds})
|
97
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE (albums.artist_id = 1) LIMIT 1"]
|
79
98
|
end
|
80
99
|
|
81
100
|
specify "should run a regular query if :prepared_statement=>false option is used for the association" do
|
@@ -2,14 +2,18 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
3
3
|
describe Sequel::Model, "rcte_tree" do
|
4
4
|
before do
|
5
|
-
@
|
5
|
+
@db = Sequel.mock
|
6
|
+
@db.extend_datasets do
|
7
|
+
def supports_cte?(*) true end
|
8
|
+
end
|
9
|
+
@c = Class.new(Sequel::Model(@db[:nodes]))
|
6
10
|
@c.class_eval do
|
7
11
|
def self.name; 'Node'; end
|
8
12
|
columns :id, :name, :parent_id, :i, :pi
|
9
13
|
end
|
10
14
|
@ds = @c.dataset
|
11
15
|
@o = @c.load(:id=>2, :parent_id=>1, :name=>'AA', :i=>3, :pi=>4)
|
12
|
-
|
16
|
+
@db.sqls
|
13
17
|
end
|
14
18
|
|
15
19
|
it "should define the correct associations" do
|
@@ -44,11 +48,11 @@ describe Sequel::Model, "rcte_tree" do
|
|
44
48
|
@c.plugin :rcte_tree
|
45
49
|
@ds._fetch = [[{:id=>1, :name=>'A', :parent_id=>3}]]
|
46
50
|
@c.eager(:ancestors).all
|
47
|
-
|
51
|
+
@db.sqls.should == ["SELECT * FROM nodes", "WITH t(x_root_x, id, name, parent_id, i, pi) AS (SELECT id AS x_root_x, nodes.id, nodes.name, nodes.parent_id, nodes.i, nodes.pi FROM nodes WHERE (id IN (3)) UNION ALL SELECT t.x_root_x, nodes.id, nodes.name, nodes.parent_id, nodes.i, nodes.pi FROM nodes INNER JOIN t ON (t.parent_id = nodes.id)) SELECT * FROM t AS nodes"]
|
48
52
|
|
49
53
|
@ds._fetch = [[{:id=>1, :name=>'A', :parent_id=>3}]]
|
50
54
|
@c.eager(:descendants).all
|
51
|
-
|
55
|
+
@db.sqls.should == ["SELECT * FROM nodes", "WITH t(x_root_x, id, name, parent_id, i, pi) AS (SELECT parent_id AS x_root_x, nodes.id, nodes.name, nodes.parent_id, nodes.i, nodes.pi FROM nodes WHERE (parent_id IN (1)) UNION ALL SELECT t.x_root_x, nodes.id, nodes.name, nodes.parent_id, nodes.i, nodes.pi FROM nodes INNER JOIN t ON (t.id = nodes.parent_id)) SELECT * FROM t AS nodes"]
|
52
56
|
end
|
53
57
|
|
54
58
|
it "should use the correct SQL for lazy associations when giving options" do
|
@@ -114,7 +118,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
114
118
|
{:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>1}, {:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>2},
|
115
119
|
{:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>2}, {:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>1}]]
|
116
120
|
os = @ds.eager(:ancestors).all
|
117
|
-
sqls =
|
121
|
+
sqls = @db.sqls
|
118
122
|
sqls.first.should == "SELECT * FROM nodes"
|
119
123
|
sqls.last.should =~ /WITH t AS \(SELECT id AS x_root_x, nodes\.\* FROM nodes WHERE \(id IN \([12], [12]\)\) UNION ALL SELECT t\.x_root_x, nodes\.\* FROM nodes INNER JOIN t ON \(t\.parent_id = nodes\.id\)\) SELECT \* FROM t AS nodes/
|
120
124
|
os.should == [@c.load(:id=>2, :parent_id=>1, :name=>'AA'), @c.load(:id=>6, :parent_id=>2, :name=>'C'), @c.load(:id=>7, :parent_id=>1, :name=>'D'), @c.load(:id=>9, :parent_id=>nil, :name=>'E')]
|
@@ -126,7 +130,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
126
130
|
os.map{|o| o.parent.parent if o.parent}.should == [@c.load(:id=>8, :name=>'?', :parent_id=>nil), @c.load(:id=>1, :name=>'00', :parent_id=>8), @c.load(:id=>8, :name=>'?', :parent_id=>nil), nil]
|
127
131
|
os.map{|o| o.parent.parent.parent if o.parent and o.parent.parent}.should == [nil, @c.load(:id=>8, :name=>'?', :parent_id=>nil), nil, nil]
|
128
132
|
os.map{|o| o.parent.parent.parent.parent if o.parent and o.parent.parent and o.parent.parent.parent}.should == [nil, nil, nil, nil]
|
129
|
-
|
133
|
+
@db.sqls.should == []
|
130
134
|
end
|
131
135
|
|
132
136
|
it "should eagerly load ancestors when giving options" do
|
@@ -136,7 +140,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
136
140
|
{:i=>1, :name=>'00', :pi=>8, :kal=>1}, {:i=>1, :name=>'00', :pi=>8, :kal=>2},
|
137
141
|
{:i=>8, :name=>'?', :pi=>nil, :kal=>2}, {:i=>8, :name=>'?', :pi=>nil, :kal=>1}]]
|
138
142
|
os = @ds.eager(:as).all
|
139
|
-
sqls =
|
143
|
+
sqls = @db.sqls
|
140
144
|
sqls.first.should == "SELECT * FROM nodes"
|
141
145
|
sqls.last.should =~ /WITH cte AS \(SELECT i AS kal, nodes\.\* FROM nodes WHERE \(i IN \([12], [12]\)\) UNION ALL SELECT cte\.kal, nodes\.\* FROM nodes INNER JOIN cte ON \(cte\.pi = nodes\.i\)\) SELECT \* FROM cte/
|
142
146
|
os.should == [@c.load(:i=>2, :pi=>1, :name=>'AA'), @c.load(:i=>6, :pi=>2, :name=>'C'), @c.load(:i=>7, :pi=>1, :name=>'D'), @c.load(:i=>9, :pi=>nil, :name=>'E')]
|
@@ -157,7 +161,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
157
161
|
{:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>1}, {:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>2},
|
158
162
|
{:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>2}, {:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>1}]]
|
159
163
|
@ds.eager(:ancestors).all
|
160
|
-
sqls =
|
164
|
+
sqls = @db.sqls
|
161
165
|
sqls.first.should == "SELECT * FROM nodes"
|
162
166
|
sqls.last.should =~ /WITH t AS \(SELECT id AS x_root_x, nodes\.\* FROM nodes WHERE \(\(id IN \([12], [12]\)\) AND \(i = 1\)\) UNION ALL SELECT t\.x_root_x, nodes\.\* FROM nodes INNER JOIN t ON \(t\.parent_id = nodes\.id\) WHERE \(i = 1\)\) SELECT \* FROM t AS nodes WHERE \(i = 1\)/
|
163
167
|
end
|
@@ -169,7 +173,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
169
173
|
{:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>6}, {:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>2},
|
170
174
|
{:id=>4, :name=>'?', :parent_id=>7, :x_root_x=>7}, {:id=>5, :name=>'?', :parent_id=>4, :x_root_x=>7}]]
|
171
175
|
os = @ds.eager(:descendants).all
|
172
|
-
sqls =
|
176
|
+
sqls = @db.sqls
|
173
177
|
sqls.first.should == "SELECT * FROM nodes"
|
174
178
|
sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x, nodes\.\* FROM nodes WHERE \(parent_id IN \([267], [267], [267]\)\) UNION ALL SELECT t\.x_root_x, nodes\.\* FROM nodes INNER JOIN t ON \(t\.id = nodes\.parent_id\)\) SELECT \* FROM t AS nodes/
|
175
179
|
os.should == [@c.load(:id=>2, :parent_id=>1, :name=>'AA'), @c.load(:id=>6, :parent_id=>2, :name=>'C'), @c.load(:id=>7, :parent_id=>1, :name=>'D')]
|
@@ -179,7 +183,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
179
183
|
os.map{|o| o.children}.should == [[@c.load(:id=>6, :parent_id=>2, :name=>'C'), @c.load(:id=>9, :parent_id=>2, :name=>'E')], [@c.load(:id=>3, :name=>'00', :parent_id=>6)], [@c.load(:id=>4, :name=>'?', :parent_id=>7)]]
|
180
184
|
os.map{|o1| o1.children.map{|o2| o2.children}}.should == [[[@c.load(:id=>3, :name=>'00', :parent_id=>6)], []], [[]], [[@c.load(:id=>5, :name=>'?', :parent_id=>4)]]]
|
181
185
|
os.map{|o1| o1.children.map{|o2| o2.children.map{|o3| o3.children}}}.should == [[[[]], []], [[]], [[[]]]]
|
182
|
-
|
186
|
+
@db.sqls.should == []
|
183
187
|
end
|
184
188
|
|
185
189
|
it "should eagerly load descendants when giving options" do
|
@@ -189,7 +193,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
189
193
|
{:i=>3, :name=>'00', :pi=>6, :kal=>6}, {:i=>3, :name=>'00', :pi=>6, :kal=>2},
|
190
194
|
{:i=>4, :name=>'?', :pi=>7, :kal=>7}, {:i=>5, :name=>'?', :pi=>4, :kal=>7}]]
|
191
195
|
os = @ds.eager(:ds).all
|
192
|
-
sqls =
|
196
|
+
sqls = @db.sqls
|
193
197
|
sqls.first.should == "SELECT * FROM nodes"
|
194
198
|
sqls.last.should =~ /WITH cte AS \(SELECT pi AS kal, nodes\.\* FROM nodes WHERE \(pi IN \([267], [267], [267]\)\) UNION ALL SELECT cte\.kal, nodes\.\* FROM nodes INNER JOIN cte ON \(cte\.i = nodes\.pi\)\) SELECT \* FROM cte/
|
195
199
|
os.should == [@c.load(:i=>2, :pi=>1, :name=>'AA'), @c.load(:i=>6, :pi=>2, :name=>'C'), @c.load(:i=>7, :pi=>1, :name=>'D')]
|
@@ -199,7 +203,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
199
203
|
os.map{|o| o.cs}.should == [[@c.load(:i=>6, :pi=>2, :name=>'C'), @c.load(:i=>9, :pi=>2, :name=>'E')], [@c.load(:i=>3, :name=>'00', :pi=>6)], [@c.load(:i=>4, :name=>'?', :pi=>7)]]
|
200
204
|
os.map{|o1| o1.cs.map{|o2| o2.cs}}.should == [[[@c.load(:i=>3, :name=>'00', :pi=>6)], []], [[]], [[@c.load(:i=>5, :name=>'?', :pi=>4)]]]
|
201
205
|
os.map{|o1| o1.cs.map{|o2| o2.cs.map{|o3| o3.cs}}}.should == [[[[]], []], [[]], [[[]]]]
|
202
|
-
|
206
|
+
@db.sqls.should == []
|
203
207
|
end
|
204
208
|
|
205
209
|
it "should eagerly load descendants to a given level" do
|
@@ -209,7 +213,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
209
213
|
{:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>6, :x_level_x=>0}, {:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>2, :x_level_x=>1},
|
210
214
|
{:id=>4, :name=>'?', :parent_id=>7, :x_root_x=>7, :x_level_x=>0}, {:id=>5, :name=>'?', :parent_id=>4, :x_root_x=>7, :x_level_x=>1}]]
|
211
215
|
os = @ds.eager(:descendants=>2).all
|
212
|
-
sqls =
|
216
|
+
sqls = @db.sqls
|
213
217
|
sqls.first.should == "SELECT * FROM nodes"
|
214
218
|
sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x, nodes\.\*, CAST\(0 AS integer\) AS x_level_x FROM nodes WHERE \(parent_id IN \([267], [267], [267]\)\) UNION ALL SELECT t\.x_root_x, nodes\.\*, \(t\.x_level_x \+ 1\) AS x_level_x FROM nodes INNER JOIN t ON \(t\.id = nodes\.parent_id\) WHERE \(t\.x_level_x < 1\)\) SELECT \* FROM t AS nodes/
|
215
219
|
os.should == [@c.load(:id=>2, :parent_id=>1, :name=>'AA'), @c.load(:id=>6, :parent_id=>2, :name=>'C'), @c.load(:id=>7, :parent_id=>1, :name=>'D')]
|
@@ -219,7 +223,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
219
223
|
os.map{|o| o.associations[:children]}.should == [[@c.load(:id=>6, :parent_id=>2, :name=>'C'), @c.load(:id=>9, :parent_id=>2, :name=>'E')], [@c.load(:id=>3, :name=>'00', :parent_id=>6)], [@c.load(:id=>4, :name=>'?', :parent_id=>7)]]
|
220
224
|
os.map{|o1| o1.associations[:children].map{|o2| o2.associations[:children]}}.should == [[[@c.load(:id=>3, :name=>'00', :parent_id=>6)], []], [[]], [[@c.load(:id=>5, :name=>'?', :parent_id=>4)]]]
|
221
225
|
os.map{|o1| o1.associations[:children].map{|o2| o2.associations[:children].map{|o3| o3.associations[:children]}}}.should == [[[[]], []], [[]], [[nil]]]
|
222
|
-
|
226
|
+
@db.sqls.should == []
|
223
227
|
end
|
224
228
|
|
225
229
|
it "should eagerly load descendants to a given level when giving options" do
|
@@ -229,7 +233,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
229
233
|
{:i=>3, :name=>'00', :pi=>6, :kal=>6, :lal=>0}, {:i=>3, :name=>'00', :pi=>6, :kal=>2, :lal=>1},
|
230
234
|
{:i=>4, :name=>'?', :pi=>7, :kal=>7, :lal=>0}, {:i=>5, :name=>'?', :pi=>4, :kal=>7, :lal=>1}]]
|
231
235
|
os = @ds.eager(:ds=>2).all
|
232
|
-
sqls =
|
236
|
+
sqls = @db.sqls
|
233
237
|
sqls.first.should == "SELECT * FROM nodes"
|
234
238
|
sqls.last.should =~ /WITH cte AS \(SELECT pi AS kal, nodes\.\*, CAST\(0 AS integer\) AS lal FROM nodes WHERE \(pi IN \([267], [267], [267]\)\) UNION ALL SELECT cte\.kal, nodes\.\*, \(cte\.lal \+ 1\) AS lal FROM nodes INNER JOIN cte ON \(cte\.i = nodes\.pi\) WHERE \(cte\.lal < 1\)\) SELECT \* FROM cte/
|
235
239
|
os.should == [@c.load(:i=>2, :pi=>1, :name=>'AA'), @c.load(:i=>6, :pi=>2, :name=>'C'), @c.load(:i=>7, :pi=>1, :name=>'D')]
|
@@ -239,7 +243,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
239
243
|
os.map{|o| o.associations[:cs]}.should == [[@c.load(:i=>6, :pi=>2, :name=>'C'), @c.load(:i=>9, :pi=>2, :name=>'E')], [@c.load(:i=>3, :name=>'00', :pi=>6)], [@c.load(:i=>4, :name=>'?', :pi=>7)]]
|
240
244
|
os.map{|o1| o1.associations[:cs].map{|o2| o2.associations[:cs]}}.should == [[[@c.load(:i=>3, :name=>'00', :pi=>6)], []], [[]], [[@c.load(:i=>5, :name=>'?', :pi=>4)]]]
|
241
245
|
os.map{|o1| o1.associations[:cs].map{|o2| o2.associations[:cs].map{|o3| o3.associations[:cs]}}}.should == [[[[]], []], [[]], [[nil]]]
|
242
|
-
|
246
|
+
@db.sqls.should == []
|
243
247
|
end
|
244
248
|
|
245
249
|
it "should eagerly load descendants respecting association option :conditions" do
|
@@ -249,7 +253,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
249
253
|
{:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>6}, {:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>2},
|
250
254
|
{:id=>4, :name=>'?', :parent_id=>7, :x_root_x=>7}, {:id=>5, :name=>'?', :parent_id=>4, :x_root_x=>7}]]
|
251
255
|
@ds.eager(:descendants).all
|
252
|
-
sqls =
|
256
|
+
sqls = @db.sqls
|
253
257
|
sqls.first.should == "SELECT * FROM nodes"
|
254
258
|
sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x, nodes\.\* FROM nodes WHERE \(\(parent_id IN \([267], [267], [267]\)\) AND \(i = 1\)\) UNION ALL SELECT t\.x_root_x, nodes\.\* FROM nodes INNER JOIN t ON \(t\.id = nodes\.parent_id\) WHERE \(i = 1\)\) SELECT \* FROM t AS nodes WHERE \(i = 1\)/
|
255
259
|
end
|
@@ -257,7 +261,11 @@ end
|
|
257
261
|
|
258
262
|
describe Sequel::Model, "rcte_tree with composite keys" do
|
259
263
|
before do
|
260
|
-
@
|
264
|
+
@db = Sequel.mock
|
265
|
+
@db.extend_datasets do
|
266
|
+
def supports_cte?(*) true end
|
267
|
+
end
|
268
|
+
@c = Class.new(Sequel::Model(@db[:nodes]))
|
261
269
|
@c.class_eval do
|
262
270
|
def self.name; 'Node'; end
|
263
271
|
columns :id, :id2, :name, :parent_id, :parent_id2, :i, :pi
|
@@ -265,7 +273,7 @@ describe Sequel::Model, "rcte_tree with composite keys" do
|
|
265
273
|
end
|
266
274
|
@ds = @c.dataset
|
267
275
|
@o = @c.load(:id=>2, :id2=>5, :parent_id=>1, :parent_id2=>6, :name=>'AA', :i=>3, :pi=>4)
|
268
|
-
|
276
|
+
@db.sqls
|
269
277
|
end
|
270
278
|
|
271
279
|
it "should use the correct SQL for lazy associations" do
|
@@ -288,11 +296,11 @@ describe Sequel::Model, "rcte_tree with composite keys" do
|
|
288
296
|
@c.plugin :rcte_tree, :key=>[:parent_id, :parent_id2]
|
289
297
|
@ds._fetch = [[{:id=>1, :id2=>2, :name=>'A', :parent_id=>3, :parent_id2=>4}]]
|
290
298
|
@c.eager(:ancestors).all
|
291
|
-
|
299
|
+
@db.sqls.should == ["SELECT * FROM nodes", "WITH t(x_root_x_0, x_root_x_1, id, id2, name, parent_id, parent_id2, i, pi) AS (SELECT id AS x_root_x_0, id2 AS x_root_x_1, nodes.id, nodes.id2, nodes.name, nodes.parent_id, nodes.parent_id2, nodes.i, nodes.pi FROM nodes WHERE ((id, id2) IN ((3, 4))) UNION ALL SELECT t.x_root_x_0, t.x_root_x_1, nodes.id, nodes.id2, nodes.name, nodes.parent_id, nodes.parent_id2, nodes.i, nodes.pi FROM nodes INNER JOIN t ON ((t.parent_id = nodes.id) AND (t.parent_id2 = nodes.id2))) SELECT * FROM t AS nodes"]
|
292
300
|
|
293
301
|
@ds._fetch = [[{:id=>1, :id2=>2, :name=>'A', :parent_id=>3, :parent_id2=>4}]]
|
294
302
|
@c.eager(:descendants).all
|
295
|
-
|
303
|
+
@db.sqls.should == ["SELECT * FROM nodes", "WITH t(x_root_x_0, x_root_x_1, id, id2, name, parent_id, parent_id2, i, pi) AS (SELECT parent_id AS x_root_x_0, parent_id2 AS x_root_x_1, nodes.id, nodes.id2, nodes.name, nodes.parent_id, nodes.parent_id2, nodes.i, nodes.pi FROM nodes WHERE ((parent_id, parent_id2) IN ((1, 2))) UNION ALL SELECT t.x_root_x_0, t.x_root_x_1, nodes.id, nodes.id2, nodes.name, nodes.parent_id, nodes.parent_id2, nodes.i, nodes.pi FROM nodes INNER JOIN t ON ((t.id = nodes.parent_id) AND (t.id2 = nodes.parent_id2))) SELECT * FROM t AS nodes"]
|
296
304
|
end
|
297
305
|
|
298
306
|
it "should add all parent associations when lazily loading ancestors" do
|
@@ -322,7 +330,7 @@ describe Sequel::Model, "rcte_tree with composite keys" do
|
|
322
330
|
{:id=>1, :id2=>2, :name=>'00', :parent_id=>8, :parent_id2=>9, :x_root_x_0=>1, :x_root_x_1=>2}, {:id=>1, :id2=>2, :name=>'00', :parent_id=>8, :parent_id2=>9, :x_root_x_0=>2, :x_root_x_1=>3},
|
323
331
|
{:id=>8, :id2=>9, :name=>'?', :parent_id=>nil, :parent_id2=>nil, :x_root_x_0=>2, :x_root_x_1=>3}, {:id=>8, :id2=>9, :name=>'?', :parent_id=>nil, :parent_id2=>nil, :x_root_x_0=>1, :x_root_x_1=>2}]]
|
324
332
|
os = @ds.eager(:ancestors).all
|
325
|
-
sqls =
|
333
|
+
sqls = @db.sqls
|
326
334
|
sqls.first.should == "SELECT * FROM nodes"
|
327
335
|
sqls.last.should =~ /WITH t AS \(SELECT id AS x_root_x_0, id2 AS x_root_x_1, nodes\.\* FROM nodes WHERE \(\(id, id2\) IN \(\([12], [23]\), \([12], [23]\)\)\) UNION ALL SELECT t\.x_root_x_0, t\.x_root_x_1, nodes\.\* FROM nodes INNER JOIN t ON \(\(t\.parent_id = nodes\.id\) AND \(t\.parent_id2 = nodes\.id2\)\)\) SELECT \* FROM t AS nodes/
|
328
336
|
os.should == [@c.load(:id=>2, :id2=>3, :parent_id=>1, :parent_id2=>2, :name=>'AA'), @c.load(:id=>6, :id2=>7, :parent_id=>2, :parent_id2=>3, :name=>'C'), @c.load(:id=>7, :id2=>8, :parent_id=>1, :parent_id2=>2, :name=>'D'), @c.load(:id=>9, :id2=>10, :parent_id=>nil, :parent_id2=>nil, :name=>'E')]
|
@@ -334,7 +342,7 @@ describe Sequel::Model, "rcte_tree with composite keys" do
|
|
334
342
|
os.map{|o| o.parent.parent if o.parent}.should == [@c.load(:id=>8, :id2=>9, :name=>'?', :parent_id=>nil, :parent_id2=>nil), @c.load(:id=>1, :id2=>2, :name=>'00', :parent_id=>8, :parent_id2=>9), @c.load(:id=>8, :id2=>9, :name=>'?', :parent_id=>nil, :parent_id2=>nil), nil]
|
335
343
|
os.map{|o| o.parent.parent.parent if o.parent and o.parent.parent}.should == [nil, @c.load(:id=>8, :id2=>9, :name=>'?', :parent_id=>nil, :parent_id2=>nil), nil, nil]
|
336
344
|
os.map{|o| o.parent.parent.parent.parent if o.parent and o.parent.parent and o.parent.parent.parent}.should == [nil, nil, nil, nil]
|
337
|
-
|
345
|
+
@db.sqls.should == []
|
338
346
|
end
|
339
347
|
|
340
348
|
it "should eagerly load descendants" do
|
@@ -344,7 +352,7 @@ describe Sequel::Model, "rcte_tree with composite keys" do
|
|
344
352
|
{:id=>3, :id2=>4, :name=>'00', :parent_id=>6, :parent_id2=>7, :x_root_x_0=>6, :x_root_x_1=>7}, {:id=>3, :id2=>4, :name=>'00', :parent_id=>6, :parent_id2=>7, :x_root_x_0=>2, :x_root_x_1=>3},
|
345
353
|
{:id=>4, :id2=>5, :name=>'?', :parent_id=>7, :parent_id2=>8, :x_root_x_0=>7, :x_root_x_1=>8}, {:id=>5, :id2=>6, :name=>'?', :parent_id=>4, :parent_id2=>5, :x_root_x_0=>7, :x_root_x_1=>8}]]
|
346
354
|
os = @ds.eager(:descendants).all
|
347
|
-
sqls =
|
355
|
+
sqls = @db.sqls
|
348
356
|
sqls.first.should == "SELECT * FROM nodes"
|
349
357
|
sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x_0, parent_id2 AS x_root_x_1, nodes\.\* FROM nodes WHERE \(\(parent_id, parent_id2\) IN \(\([267], [378]\), \([267], [378]\), \([267], [378]\)\)\) UNION ALL SELECT t\.x_root_x_0, t\.x_root_x_1, nodes\.\* FROM nodes INNER JOIN t ON \(\(t\.id = nodes\.parent_id\) AND \(t\.id2 = nodes\.parent_id2\)\)\) SELECT \* FROM t AS nodes/
|
350
358
|
os.should == [@c.load(:id=>2, :id2=>3, :parent_id=>1, :parent_id2=>2, :name=>'AA'), @c.load(:id=>6, :id2=>7, :parent_id=>2, :parent_id2=>3, :name=>'C'), @c.load(:id=>7, :id2=>8, :parent_id=>1, :parent_id2=>2, :name=>'D')]
|
@@ -354,7 +362,7 @@ describe Sequel::Model, "rcte_tree with composite keys" do
|
|
354
362
|
os.map{|o| o.children}.should == [[@c.load(:id=>6, :id2=>7, :parent_id=>2, :parent_id2=>3, :name=>'C'), @c.load(:id=>9, :id2=>10, :parent_id=>2, :parent_id2=>3, :name=>'E')], [@c.load(:id=>3, :id2=>4, :name=>'00', :parent_id=>6, :parent_id2=>7)], [@c.load(:id=>4, :id2=>5, :name=>'?', :parent_id=>7, :parent_id2=>8)]]
|
355
363
|
os.map{|o1| o1.children.map{|o2| o2.children}}.should == [[[@c.load(:id=>3, :id2=>4, :name=>'00', :parent_id=>6, :parent_id2=>7)], []], [[]], [[@c.load(:id=>5, :id2=>6, :name=>'?', :parent_id=>4, :parent_id2=>5)]]]
|
356
364
|
os.map{|o1| o1.children.map{|o2| o2.children.map{|o3| o3.children}}}.should == [[[[]], []], [[]], [[[]]]]
|
357
|
-
|
365
|
+
@db.sqls.should == []
|
358
366
|
end
|
359
367
|
|
360
368
|
it "should eagerly load descendants to a given level" do
|
@@ -364,7 +372,7 @@ describe Sequel::Model, "rcte_tree with composite keys" do
|
|
364
372
|
{:id=>3, :id2=>4, :name=>'00', :parent_id=>6, :parent_id2=>7, :x_root_x_0=>6, :x_root_x_1=>7, :x_level_x=>0}, {:id=>3, :id2=>4, :name=>'00', :parent_id=>6, :parent_id2=>7, :x_root_x_0=>2, :x_root_x_1=>3, :x_level_x=>1},
|
365
373
|
{:id=>4, :id2=>5, :name=>'?', :parent_id=>7, :parent_id2=>8, :x_root_x_0=>7, :x_root_x_1=>8, :x_level_x=>0}, {:id=>5, :id2=>6, :name=>'?', :parent_id=>4, :parent_id2=>5, :x_root_x_0=>7, :x_root_x_1=>8, :x_level_x=>1}]]
|
366
374
|
os = @ds.eager(:descendants=>2).all
|
367
|
-
sqls =
|
375
|
+
sqls = @db.sqls
|
368
376
|
sqls.first.should == "SELECT * FROM nodes"
|
369
377
|
sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x_0, parent_id2 AS x_root_x_1, nodes\.\*, CAST\(0 AS integer\) AS x_level_x FROM nodes WHERE \(\(parent_id, parent_id2\) IN \(\([267], [378]\), \([267], [378]\), \([267], [378]\)\)\) UNION ALL SELECT t\.x_root_x_0, t\.x_root_x_1, nodes\.\*, \(t\.x_level_x \+ 1\) AS x_level_x FROM nodes INNER JOIN t ON \(\(t\.id = nodes\.parent_id\) AND \(t\.id2 = nodes\.parent_id2\)\) WHERE \(t\.x_level_x < 1\)\) SELECT \* FROM t AS nodes/
|
370
378
|
os.should == [@c.load(:id=>2, :id2=>3, :parent_id=>1, :parent_id=>2, :name=>'AA'), @c.load(:id=>6, :id2=>7, :parent_id=>2, :parent_id2=>3, :name=>'C'), @c.load(:id=>7, :id2=>8, :parent_id=>1, :parent_id2=>2, :name=>'D')]
|
@@ -374,6 +382,6 @@ describe Sequel::Model, "rcte_tree with composite keys" do
|
|
374
382
|
os.map{|o| o.associations[:children]}.should == [[@c.load(:id=>6, :id2=>7, :parent_id=>2, :parent_id2=>3, :name=>'C'), @c.load(:id=>9, :id2=>10, :parent_id=>2, :parent_id2=>3, :name=>'E')], [@c.load(:id=>3, :id2=>4, :name=>'00', :parent_id=>6, :parent_id2=>7)], [@c.load(:id=>4, :id2=>5, :name=>'?', :parent_id=>7, :parent_id2=>8)]]
|
375
383
|
os.map{|o1| o1.associations[:children].map{|o2| o2.associations[:children]}}.should == [[[@c.load(:id=>3, :id2=>4, :name=>'00', :parent_id=>6, :parent_id2=>7)], []], [[]], [[@c.load(:id=>5, :id2=>6, :name=>'?', :parent_id=>4, :parent_id2=>5)]]]
|
376
384
|
os.map{|o1| o1.associations[:children].map{|o2| o2.associations[:children].map{|o3| o3.associations[:children]}}}.should == [[[[]], []], [[]], [[nil]]]
|
377
|
-
|
385
|
+
@db.sqls.should == []
|
378
386
|
end
|
379
387
|
end
|
@@ -71,7 +71,6 @@ describe "Dataset#opts=" do
|
|
71
71
|
specify "should change the dataset's opts" do
|
72
72
|
db = Sequel.mock
|
73
73
|
ds = db[:items].extension(:sequel_3_dataset_methods)
|
74
|
-
db2 = Sequel.mock
|
75
74
|
ds.sql.should == 'SELECT * FROM items'
|
76
75
|
ds.opts = {}
|
77
76
|
ds.sql.should == 'SELECT *'
|
@@ -113,7 +113,7 @@ describe "sharding plugin" do
|
|
113
113
|
album.artist.update(:name=>'AS')
|
114
114
|
@db.sqls.should == ["SELECT * FROM artists WHERE (artists.id = 2) LIMIT 1 -- s1", "UPDATE artists SET name = 'AS' WHERE (id = 2) -- s1"]
|
115
115
|
album.tags.map{|a| a.update(:name=>'SR')}
|
116
|
-
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON (
|
116
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE (albums_tags.album_id = 1) -- s1", "UPDATE tags SET name = 'SR' WHERE (id = 3) -- s1"]
|
117
117
|
@Artist.server(:s2).first.albums.map{|a| a.update(:name=>'MO')}
|
118
118
|
@db.sqls.should == ["SELECT * FROM artists LIMIT 1 -- s2", "SELECT * FROM albums WHERE (albums.artist_id = 2) -- s2", "UPDATE albums SET name = 'MO' WHERE (id = 1) -- s2"]
|
119
119
|
end
|
@@ -145,7 +145,7 @@ describe "sharding plugin" do
|
|
145
145
|
sqls.should == ["SELECT * FROM albums WHERE ((albums.artist_id = 2) AND (albums.id = 1)) LIMIT 1 -- s2"]
|
146
146
|
|
147
147
|
album.remove_tag(3)
|
148
|
-
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON (
|
148
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((albums_tags.album_id = 1) AND (tags.id = 3)) LIMIT 1 -- s1", "DELETE FROM albums_tags WHERE ((album_id = 1) AND (tag_id = 3)) -- s1"]
|
149
149
|
end
|
150
150
|
|
151
151
|
specify "should have objects retrieved from a specific shard remove all associated objects from that shard" do
|
@@ -75,4 +75,8 @@ describe "Sequel::Plugins::TacticalEagerLoading" do
|
|
75
75
|
ts.map{|x| x.children}.should == [[], [], [ts[0]], [ts[1]]]
|
76
76
|
DB.sqls.length.should == 1
|
77
77
|
end
|
78
|
+
|
79
|
+
it "#marshallable should make marshalling not fail" do
|
80
|
+
proc{Marshal.dump(@c.all.map{|x| x.marshallable!})}.should_not raise_error
|
81
|
+
end
|
78
82
|
end
|
@@ -25,6 +25,7 @@ END
|
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should handle WITH" do
|
28
|
+
def @ds.supports_cte?(*) true end
|
28
29
|
a = dot(@ds.with(:a, @ds))
|
29
30
|
a[0..3].should == ["1 -> 2 [label=\"with\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"Hash\"];"]
|
30
31
|
[["3 -> 4 [label=\"dataset\"];", "4 [label=\"Dataset\"];", "3 -> 5 [label=\"name\"];", "5 [label=\":a\"];"],
|
@@ -139,7 +139,7 @@ describe "Touch plugin" do
|
|
139
139
|
@Artist.plugin :touch, :associations=>:albums
|
140
140
|
@a.touch
|
141
141
|
DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)",
|
142
|
-
"SELECT albums.* FROM albums INNER JOIN aa ON (
|
142
|
+
"SELECT albums.* FROM albums INNER JOIN aa ON (aa.album_id = albums.id) WHERE (aa.artist_id = 1)",
|
143
143
|
"UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)"]
|
144
144
|
end
|
145
145
|
|
@@ -149,7 +149,7 @@ describe "Touch plugin" do
|
|
149
149
|
@Artist.plugin :touch, :associations=>:albums
|
150
150
|
@a.touch
|
151
151
|
DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)",
|
152
|
-
"SELECT albums.* FROM albums INNER JOIN aa ON (
|
152
|
+
"SELECT albums.* FROM albums INNER JOIN aa ON (aa.album_id = albums.id) WHERE (aa.artist_id = 1)",
|
153
153
|
"UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)"]
|
154
154
|
end
|
155
155
|
|
@@ -4,7 +4,7 @@ shared_examples_for "one_to_one eager limit strategies" do
|
|
4
4
|
specify "eager loading one_to_one associations should work correctly" do
|
5
5
|
Artist.one_to_one :first_album, {:clone=>:first_album}.merge(@els) if @els
|
6
6
|
Artist.one_to_one :last_album, {:clone=>:last_album}.merge(@els) if @els
|
7
|
-
Artist.one_to_one :second_album, {:clone=>:second_album}.merge(@els) if @els
|
7
|
+
Artist.one_to_one :second_album, {:clone=>:second_album}.merge(@els) if @els && @els[:eager_limit_strategy] != :distinct_on
|
8
8
|
@album.update(:artist => @artist)
|
9
9
|
diff_album = @diff_album.call
|
10
10
|
ar = @pr.call[1]
|
@@ -29,7 +29,9 @@ shared_examples_for "one_to_one eager limit strategies" do
|
|
29
29
|
[@album, same_album].should include(a.first.first_album)
|
30
30
|
a.last.first_album.should == nil
|
31
31
|
end
|
32
|
+
end
|
32
33
|
|
34
|
+
shared_examples_for "one_to_one eager_graph limit strategies" do
|
33
35
|
specify "eager graphing one_to_one associations should work correctly" do
|
34
36
|
@album.update(:artist => @artist)
|
35
37
|
diff_album = @diff_album.call
|
@@ -50,12 +52,14 @@ shared_examples_for "one_to_one eager limit strategies" do
|
|
50
52
|
a.last.last_album.should == nil
|
51
53
|
a.first.last_album.values.should == diff_album.values
|
52
54
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
55
|
+
if @els[:eager_limit_strategy] != :distinct_on && (@els[:eager_limit_strategy] != :correlated_subquery || Album.dataset.supports_offsets_in_correlated_subqueries?)
|
56
|
+
a = ds.eager_graph_with_options(:second_album, limit_strategy).all
|
57
|
+
a = ds.eager_graph(:second_album).all
|
58
|
+
a.should == [@artist, ar]
|
59
|
+
a.first.second_album.should == diff_album
|
60
|
+
a.last.second_album.should == nil
|
61
|
+
a.first.second_album.values.should == diff_album.values
|
62
|
+
end
|
59
63
|
|
60
64
|
same_album = @same_album.call
|
61
65
|
a = ds.eager_graph_with_options(:first_album, limit_strategy).all
|
@@ -93,7 +97,9 @@ shared_examples_for "one_to_many eager limit strategies" do
|
|
93
97
|
ars.first.not_first_albums.map{|x| x.values}.should == [middle_album, diff_album].map{|x| x.values}
|
94
98
|
ars.first.last_two_albums.map{|x| x.values}.should == [diff_album, middle_album].map{|x| x.values}
|
95
99
|
end
|
100
|
+
end
|
96
101
|
|
102
|
+
shared_examples_for "one_to_many eager_graph limit strategies" do
|
97
103
|
specify "should correctly handle limits and offsets when eager graphing one_to_many associations" do
|
98
104
|
@album.update(:artist => @artist)
|
99
105
|
middle_album = @middle_album.call
|
@@ -108,17 +114,19 @@ shared_examples_for "one_to_many eager limit strategies" do
|
|
108
114
|
ars.last.first_two_albums.should == []
|
109
115
|
ars.first.first_two_albums.map{|x| x.values}.should == [@album, middle_album].map{|x| x.values}
|
110
116
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
117
|
+
if @els[:eager_limit_strategy] != :correlated_subquery || Album.dataset.supports_offsets_in_correlated_subqueries?
|
118
|
+
ars = ds.eager_graph_with_options(:second_two_albums, limit_strategy).all
|
119
|
+
ars.should == [@artist, ar]
|
120
|
+
ars.first.second_two_albums.should == [middle_album, diff_album]
|
121
|
+
ars.last.second_two_albums.should == []
|
122
|
+
ars.first.second_two_albums.map{|x| x.values}.should == [middle_album, diff_album].map{|x| x.values}
|
116
123
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
124
|
+
ars = ds.eager_graph_with_options(:not_first_albums, limit_strategy).all
|
125
|
+
ars.should == [@artist, ar]
|
126
|
+
ars.first.not_first_albums.should == [middle_album, diff_album]
|
127
|
+
ars.last.not_first_albums.should == []
|
128
|
+
ars.first.not_first_albums.map{|x| x.values}.should == [middle_album, diff_album].map{|x| x.values}
|
129
|
+
end
|
122
130
|
|
123
131
|
ars = ds.eager_graph_with_options(:last_two_albums, limit_strategy).all
|
124
132
|
ars.should == [@artist, ar]
|
@@ -131,7 +139,7 @@ end
|
|
131
139
|
shared_examples_for "one_through_one eager limit strategies" do
|
132
140
|
specify "should correctly handle offsets when eager loading one_through_one associations" do
|
133
141
|
Album.one_through_one :first_tag, {:clone=>:first_tag}.merge(@els) if @els
|
134
|
-
Album.one_through_one :second_tag, {:clone=>:second_tag}.merge(@els) if @els
|
142
|
+
Album.one_through_one :second_tag, {:clone=>:second_tag}.merge(@els) if @els && @els[:eager_limit_strategy] != :distinct_on
|
135
143
|
Album.one_through_one :last_tag, {:clone=>:last_tag}.merge(@els) if @els
|
136
144
|
tu, tv = @other_tags.call
|
137
145
|
al = @pr.call.first
|
@@ -150,7 +158,9 @@ shared_examples_for "one_through_one eager limit strategies" do
|
|
150
158
|
als.first.second_tag.values.should == tu.values
|
151
159
|
als.first.last_tag.values.should == tv.values
|
152
160
|
end
|
161
|
+
end
|
153
162
|
|
163
|
+
shared_examples_for "one_through_one eager_graph limit strategies" do
|
154
164
|
specify "should correctly handle offsets when eager graphing one_through_one associations" do
|
155
165
|
tu, tv = @other_tags.call
|
156
166
|
al = @pr.call.first
|
@@ -163,7 +173,7 @@ shared_examples_for "one_through_one eager limit strategies" do
|
|
163
173
|
als.last.first_tag.should == nil
|
164
174
|
als.first.first_tag.values.should == @tag.values
|
165
175
|
|
166
|
-
als = ds.eager_graph_with_options(:second_tag, limit_strategy).all
|
176
|
+
als = ds.eager_graph_with_options(:second_tag, @els[:eager_limit_strategy] != :distinct_on ? limit_strategy : {}).all
|
167
177
|
als.should == [@album, al]
|
168
178
|
als.first.second_tag.should == tu
|
169
179
|
als.last.second_tag.should == nil
|
@@ -203,7 +213,9 @@ shared_examples_for "many_to_many eager limit strategies" do
|
|
203
213
|
als.first.not_first_tags.map{|x| x.values}.should == [tu, tv].map{|x| x.values}
|
204
214
|
als.first.last_two_tags.map{|x| x.values}.should == [tv, tu].map{|x| x.values}
|
205
215
|
end
|
216
|
+
end
|
206
217
|
|
218
|
+
shared_examples_for "many_to_many eager_graph limit strategies" do
|
207
219
|
specify "should correctly handle limits and offsets when eager loading many_to_many associations" do
|
208
220
|
tu, tv = @other_tags.call
|
209
221
|
al = @pr.call.first
|
@@ -266,7 +278,9 @@ shared_examples_for "many_through_many eager limit strategies" do
|
|
266
278
|
ars.first.not_first_tags.map{|x| x.values}.should == [tu, tv].map{|x| x.values}
|
267
279
|
ars.first.last_two_tags.map{|x| x.values}.should == [tv, tu].map{|x| x.values}
|
268
280
|
end
|
281
|
+
end
|
269
282
|
|
283
|
+
shared_examples_for "many_through_many eager_graph limit strategies" do
|
270
284
|
specify "should correctly handle limits and offsets when eager loading many_through_many associations" do
|
271
285
|
@album.update(:artist => @artist)
|
272
286
|
tu, tv = @other_tags.call
|
@@ -305,7 +319,7 @@ end
|
|
305
319
|
shared_examples_for "one_through_many eager limit strategies" do
|
306
320
|
specify "should correctly handle offsets when eager loading one_through_many associations" do
|
307
321
|
Artist.one_through_many :first_tag, {:clone=>:first_tag}.merge(@els) if @els
|
308
|
-
Artist.one_through_many :second_tag, {:clone=>:second_tag}.merge(@els) if @els
|
322
|
+
Artist.one_through_many :second_tag, {:clone=>:second_tag}.merge(@els) if @els && @els[:eager_limit_strategy] != :distinct_on
|
309
323
|
Artist.one_through_many :last_tag, {:clone=>:last_tag}.merge(@els) if @els
|
310
324
|
@album.update(:artist => @artist)
|
311
325
|
tu, tv = @other_tags.call
|
@@ -327,7 +341,9 @@ shared_examples_for "one_through_many eager limit strategies" do
|
|
327
341
|
ars.first.second_tag.values.should == tu.values
|
328
342
|
ars.first.last_tag.values.should == tv.values
|
329
343
|
end
|
344
|
+
end
|
330
345
|
|
346
|
+
shared_examples_for "one_through_many eager_graph limit strategies" do
|
331
347
|
specify "should correctly handle offsets when eager graphing one_through_many associations" do
|
332
348
|
@album.update(:artist => @artist)
|
333
349
|
tu, tv = @other_tags.call
|
@@ -343,7 +359,7 @@ shared_examples_for "one_through_many eager limit strategies" do
|
|
343
359
|
ars.last.first_tag.should == tu
|
344
360
|
ars.first.first_tag.values.should == @tag.values
|
345
361
|
|
346
|
-
ars = ds.eager_graph_with_options(:second_tag, limit_strategy).all
|
362
|
+
ars = ds.eager_graph_with_options(:second_tag, @els[:eager_limit_strategy] != :distinct_on ? limit_strategy : {}).all
|
347
363
|
ars.should == [@artist, ar]
|
348
364
|
ars.first.second_tag.should == tu
|
349
365
|
ars.last.second_tag.should == nil
|
@@ -366,6 +382,15 @@ shared_examples_for "eager limit strategies" do
|
|
366
382
|
it_should_behave_like "one_through_many eager limit strategies"
|
367
383
|
end
|
368
384
|
|
385
|
+
shared_examples_for "eager_graph limit strategies" do
|
386
|
+
it_should_behave_like "one_to_one eager_graph limit strategies"
|
387
|
+
it_should_behave_like "one_to_many eager_graph limit strategies"
|
388
|
+
it_should_behave_like "many_to_many eager_graph limit strategies"
|
389
|
+
it_should_behave_like "one_through_one eager_graph limit strategies"
|
390
|
+
it_should_behave_like "many_through_many eager_graph limit strategies"
|
391
|
+
it_should_behave_like "one_through_many eager_graph limit strategies"
|
392
|
+
end
|
393
|
+
|
369
394
|
shared_examples_for "filtering/excluding by associations" do
|
370
395
|
specify "should handle association inner joins" do
|
371
396
|
@Artist.association_join(:albums).all.should == []
|
@@ -1008,7 +1033,7 @@ shared_examples_for "filtering/excluding by associations" do
|
|
1008
1033
|
end
|
1009
1034
|
end
|
1010
1035
|
|
1011
|
-
shared_examples_for "filter by associations
|
1036
|
+
shared_examples_for "filter by associations one_to_one limit strategies" do
|
1012
1037
|
specify "filter by associations with limited one_to_one associations should work correctly" do
|
1013
1038
|
Artist.one_to_one :first_album, {:clone=>:first_album}.merge(@els)
|
1014
1039
|
Artist.one_to_one :last_album, {:clone=>:last_album}.merge(@els)
|
@@ -1023,10 +1048,12 @@ shared_examples_for "filter by associations singular association limit strategie
|
|
1023
1048
|
ds.exclude(:first_album=>@album).all.should == [ar]
|
1024
1049
|
ds.exclude(:first_album=>diff_album).all.should == [@artist, ar]
|
1025
1050
|
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1051
|
+
if @els[:eager_limit_strategy] != :distinct_on && (@els[:eager_limit_strategy] != :correlated_subquery || Album.dataset.supports_offsets_in_correlated_subqueries?)
|
1052
|
+
ds.where(:second_album=>@album).all.should == []
|
1053
|
+
ds.where(:second_album=>diff_album).all.should == [@artist]
|
1054
|
+
ds.exclude(:second_album=>@album).all.should == [@artist, ar]
|
1055
|
+
ds.exclude(:second_album=>diff_album).all.should == [ar]
|
1056
|
+
end
|
1030
1057
|
|
1031
1058
|
ds.where(:last_album=>@album).all.should == []
|
1032
1059
|
ds.where(:last_album=>diff_album).all.should == [@artist]
|
@@ -1038,11 +1065,15 @@ shared_examples_for "filter by associations singular association limit strategie
|
|
1038
1065
|
ds.where(:first_album=>[@album, diff_album]).all.should == [ar]
|
1039
1066
|
ds.exclude(:first_album=>[@album, diff_album]).all.should == [@artist]
|
1040
1067
|
end
|
1068
|
+
end
|
1069
|
+
|
1070
|
+
shared_examples_for "filter by associations singular association limit strategies" do
|
1071
|
+
it_should_behave_like "filter by associations one_to_one limit strategies"
|
1041
1072
|
|
1042
1073
|
specify "dataset associations with limited one_to_one associations should work correctly" do
|
1043
1074
|
Artist.one_to_one :first_album, {:clone=>:first_album}.merge(@els)
|
1044
1075
|
Artist.one_to_one :last_album, {:clone=>:last_album}.merge(@els)
|
1045
|
-
Artist.one_to_one :second_album, {:clone=>:second_album}.merge(@els)
|
1076
|
+
Artist.one_to_one :second_album, {:clone=>:second_album}.merge(@els) if @els[:eager_limit_strategy] != :distinct_on
|
1046
1077
|
@album.update(:artist => @artist)
|
1047
1078
|
diff_album = @diff_album.call
|
1048
1079
|
ar = @pr.call[1]
|
@@ -1063,7 +1094,7 @@ shared_examples_for "filter by associations singular association limit strategie
|
|
1063
1094
|
|
1064
1095
|
specify "filter by associations with limited one_through_one associations should work correctly" do
|
1065
1096
|
Album.one_through_one :first_tag, {:clone=>:first_tag}.merge(@els)
|
1066
|
-
Album.one_through_one :second_tag, {:clone=>:second_tag}.merge(@els)
|
1097
|
+
Album.one_through_one :second_tag, {:clone=>:second_tag}.merge(@els) if @els[:eager_limit_strategy] != :distinct_on
|
1067
1098
|
Album.one_through_one :last_tag, {:clone=>:last_tag}.merge(@els)
|
1068
1099
|
tu, tv = @other_tags.call
|
1069
1100
|
al = @pr.call.first
|
@@ -1104,7 +1135,7 @@ shared_examples_for "filter by associations singular association limit strategie
|
|
1104
1135
|
|
1105
1136
|
specify "dataset associations with limited one_through_one associations should work correctly" do
|
1106
1137
|
Album.one_through_one :first_tag, {:clone=>:first_tag}.merge(@els)
|
1107
|
-
Album.one_through_one :second_tag, {:clone=>:second_tag}.merge(@els)
|
1138
|
+
Album.one_through_one :second_tag, {:clone=>:second_tag}.merge(@els) if @els[:eager_limit_strategy] != :distinct_on
|
1108
1139
|
Album.one_through_one :last_tag, {:clone=>:last_tag}.merge(@els)
|
1109
1140
|
tu, tv = @other_tags.call
|
1110
1141
|
al = @pr.call.first
|
@@ -1135,7 +1166,7 @@ shared_examples_for "filter by associations singular association limit strategie
|
|
1135
1166
|
|
1136
1167
|
specify "filter by associations with limited one_through_many associations should work correctly" do
|
1137
1168
|
Artist.one_through_many :first_tag, {:clone=>:first_tag}.merge(@els)
|
1138
|
-
Artist.one_through_many :second_tag, {:clone=>:second_tag}.merge(@els)
|
1169
|
+
Artist.one_through_many :second_tag, {:clone=>:second_tag}.merge(@els) if @els[:eager_limit_strategy] != :distinct_on
|
1139
1170
|
Artist.one_through_many :last_tag, {:clone=>:last_tag}.merge(@els)
|
1140
1171
|
@album.update(:artist => @artist)
|
1141
1172
|
tu, tv = @other_tags.call
|
@@ -1178,7 +1209,7 @@ shared_examples_for "filter by associations singular association limit strategie
|
|
1178
1209
|
|
1179
1210
|
specify "dataset associations with limited one_through_many associations should work correctly" do
|
1180
1211
|
Artist.one_through_many :first_tag, {:clone=>:first_tag}.merge(@els)
|
1181
|
-
Artist.one_through_many :second_tag, {:clone=>:second_tag}.merge(@els)
|
1212
|
+
Artist.one_through_many :second_tag, {:clone=>:second_tag}.merge(@els) if @els[:eager_limit_strategy] != :distinct_on
|
1182
1213
|
Artist.one_through_many :last_tag, {:clone=>:last_tag}.merge(@els)
|
1183
1214
|
@album.update(:artist => @artist)
|
1184
1215
|
tu, tv = @other_tags.call
|
@@ -1210,9 +1241,7 @@ shared_examples_for "filter by associations singular association limit strategie
|
|
1210
1241
|
end
|
1211
1242
|
end
|
1212
1243
|
|
1213
|
-
shared_examples_for "filter by associations limit strategies" do
|
1214
|
-
it_should_behave_like "filter by associations singular association limit strategies"
|
1215
|
-
|
1244
|
+
shared_examples_for "filter by associations one_to_many limit strategies" do
|
1216
1245
|
specify "filter by associations with limited one_to_many associations should work correctly" do
|
1217
1246
|
Artist.one_to_many :first_two_albums, {:clone=>:first_two_albums}.merge(@els)
|
1218
1247
|
Artist.one_to_many :second_two_albums, {:clone=>:second_two_albums}.merge(@els)
|
@@ -1231,7 +1260,13 @@ shared_examples_for "filter by associations limit strategies" do
|
|
1231
1260
|
ds.exclude(:first_two_albums=>middle_album).all.should == [ar]
|
1232
1261
|
ds.exclude(:first_two_albums=>diff_album).all.should == [@artist, ar]
|
1233
1262
|
|
1234
|
-
[:
|
1263
|
+
assocs = if @els[:eager_limit_strategy] != :correlated_subquery || Album.dataset.supports_offsets_in_correlated_subqueries?
|
1264
|
+
[:second_two_albums, :not_first_albums, :last_two_albums]
|
1265
|
+
else
|
1266
|
+
[:last_two_albums]
|
1267
|
+
end
|
1268
|
+
|
1269
|
+
assocs.each do |a|
|
1235
1270
|
ds.where(a=>@album).all.should == []
|
1236
1271
|
ds.where(a=>middle_album).all.should == [@artist]
|
1237
1272
|
ds.where(a=>diff_album).all.should == [@artist]
|
@@ -1245,6 +1280,11 @@ shared_examples_for "filter by associations limit strategies" do
|
|
1245
1280
|
ds.where(:first_two_albums=>[@album, diff_album]).all.should == [ar]
|
1246
1281
|
ds.exclude(:first_two_albums=>[@album, diff_album]).all.should == [@artist]
|
1247
1282
|
end
|
1283
|
+
end
|
1284
|
+
|
1285
|
+
shared_examples_for "filter by associations limit strategies" do
|
1286
|
+
it_should_behave_like "filter by associations singular association limit strategies"
|
1287
|
+
it_should_behave_like "filter by associations one_to_many limit strategies"
|
1248
1288
|
|
1249
1289
|
specify "dataset associations with limited one_to_many associations should work correctly" do
|
1250
1290
|
Artist.one_to_many :first_two_albums, {:clone=>:first_two_albums}.merge(@els)
|
@@ -1660,20 +1700,31 @@ shared_examples_for "regular and composite key associations" do
|
|
1660
1700
|
it_should_behave_like "filtering/excluding by associations"
|
1661
1701
|
end
|
1662
1702
|
|
1703
|
+
describe "with default/union :eager_limit_strategy" do
|
1704
|
+
before do
|
1705
|
+
@els = {}
|
1706
|
+
end
|
1707
|
+
it_should_behave_like "eager limit strategies"
|
1708
|
+
end
|
1709
|
+
|
1663
1710
|
describe "with :eager_limit_strategy=>:ruby" do
|
1664
1711
|
before do
|
1665
1712
|
@els = {:eager_limit_strategy=>:ruby}
|
1666
1713
|
end
|
1667
1714
|
it_should_behave_like "eager limit strategies"
|
1715
|
+
it_should_behave_like "eager_graph limit strategies"
|
1668
1716
|
end
|
1669
1717
|
|
1670
|
-
describe "with :eager_limit_strategy
|
1718
|
+
describe "with :eager_limit_strategy=>:distinct_on" do
|
1671
1719
|
before do
|
1672
|
-
@els = {:eager_limit_strategy
|
1720
|
+
@els = {:eager_limit_strategy=>:distinct_on}
|
1673
1721
|
end
|
1674
1722
|
it_should_behave_like "one_to_one eager limit strategies"
|
1675
1723
|
it_should_behave_like "one_through_one eager limit strategies"
|
1676
1724
|
it_should_behave_like "one_through_many eager limit strategies"
|
1725
|
+
it_should_behave_like "one_to_one eager_graph limit strategies"
|
1726
|
+
it_should_behave_like "one_through_one eager_graph limit strategies"
|
1727
|
+
it_should_behave_like "one_through_many eager_graph limit strategies"
|
1677
1728
|
it_should_behave_like "filter by associations singular association limit strategies"
|
1678
1729
|
end if DB.dataset.supports_ordered_distinct_on?
|
1679
1730
|
|
@@ -1682,6 +1733,7 @@ shared_examples_for "regular and composite key associations" do
|
|
1682
1733
|
@els = {:eager_limit_strategy=>:window_function}
|
1683
1734
|
end
|
1684
1735
|
it_should_behave_like "eager limit strategies"
|
1736
|
+
it_should_behave_like "eager_graph limit strategies"
|
1685
1737
|
it_should_behave_like "filter by associations limit strategies"
|
1686
1738
|
end if DB.dataset.supports_window_functions?
|
1687
1739
|
|
@@ -1833,6 +1885,34 @@ describe "Sequel::Model Simple Associations" do
|
|
1833
1885
|
|
1834
1886
|
it_should_behave_like "regular and composite key associations"
|
1835
1887
|
|
1888
|
+
describe "with :correlated_subquery limit strategy" do
|
1889
|
+
before do
|
1890
|
+
@els = {:eager_limit_strategy=>:correlated_subquery}
|
1891
|
+
end
|
1892
|
+
|
1893
|
+
it_should_behave_like "one_to_one eager_graph limit strategies"
|
1894
|
+
it_should_behave_like "one_to_many eager_graph limit strategies"
|
1895
|
+
it_should_behave_like "filter by associations one_to_one limit strategies"
|
1896
|
+
it_should_behave_like "filter by associations one_to_many limit strategies"
|
1897
|
+
end if DB.dataset.supports_limits_in_correlated_subqueries?
|
1898
|
+
|
1899
|
+
specify "should handle eager loading limited associations for many objects" do
|
1900
|
+
@db[:artists].import([:name], (1..99).map{|i| [i.to_s]})
|
1901
|
+
artists = Artist.eager(:albums).all
|
1902
|
+
artists.length.should == 100
|
1903
|
+
artists.each{|a| a.albums.should == []}
|
1904
|
+
artists = Artist.eager(:first_two_albums).all
|
1905
|
+
artists.length.should == 100
|
1906
|
+
artists.each{|a| a.first_two_albums.should == []}
|
1907
|
+
@db[:albums].insert([:artist_id], @db[:artists].select(:id))
|
1908
|
+
artists = Artist.eager(:albums).all
|
1909
|
+
artists.length.should == 100
|
1910
|
+
artists.each{|a| a.albums.length.should == 1}
|
1911
|
+
artists = Artist.eager(:first_two_albums).all
|
1912
|
+
artists.length.should == 100
|
1913
|
+
artists.each{|a| a.first_two_albums.length.should == 1}
|
1914
|
+
end
|
1915
|
+
|
1836
1916
|
specify "should handle many_to_one associations with same name as :key" do
|
1837
1917
|
Album.def_column_alias(:artist_id_id, :artist_id)
|
1838
1918
|
Album.many_to_one :artist_id, :key_column =>:artist_id, :class=>Artist
|
@@ -2058,6 +2138,17 @@ describe "Sequel::Model Composite Key Associations" do
|
|
2058
2138
|
|
2059
2139
|
it_should_behave_like "regular and composite key associations"
|
2060
2140
|
|
2141
|
+
describe "with :correlated_subquery limit strategy" do
|
2142
|
+
before do
|
2143
|
+
@els = {:eager_limit_strategy=>:correlated_subquery}
|
2144
|
+
end
|
2145
|
+
|
2146
|
+
it_should_behave_like "one_to_one eager_graph limit strategies"
|
2147
|
+
it_should_behave_like "one_to_many eager_graph limit strategies"
|
2148
|
+
it_should_behave_like "filter by associations one_to_one limit strategies"
|
2149
|
+
it_should_behave_like "filter by associations one_to_many limit strategies"
|
2150
|
+
end if DB.dataset.supports_limits_in_correlated_subqueries? && DB.dataset.supports_multiple_column_in?
|
2151
|
+
|
2061
2152
|
specify "should have add method accept hashes and create new records" do
|
2062
2153
|
@artist.remove_all_albums
|
2063
2154
|
Album.dataset.delete
|
@@ -2168,6 +2259,7 @@ describe "Sequel::Model pg_array_to_many" do
|
|
2168
2259
|
|
2169
2260
|
it_should_behave_like "basic regular and composite key associations"
|
2170
2261
|
it_should_behave_like "many_to_many eager limit strategies"
|
2262
|
+
it_should_behave_like "many_to_many eager_graph limit strategies"
|
2171
2263
|
|
2172
2264
|
it "should handle adding and removing entries in array" do
|
2173
2265
|
a = Album.create
|
@@ -2248,6 +2340,7 @@ describe "Sequel::Model many_to_pg_array" do
|
|
2248
2340
|
|
2249
2341
|
it_should_behave_like "basic regular and composite key associations"
|
2250
2342
|
it_should_behave_like "many_to_many eager limit strategies"
|
2343
|
+
it_should_behave_like "many_to_many eager_graph limit strategies"
|
2251
2344
|
|
2252
2345
|
it "should handle adding and removing entries in array" do
|
2253
2346
|
a = Album.create
|