sequel 4.9.0 → 4.10.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 +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
|