sequel 3.29.0 → 3.30.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.
- data/CHANGELOG +35 -3
- data/Rakefile +2 -1
- data/doc/association_basics.rdoc +11 -0
- data/doc/opening_databases.rdoc +2 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/testing.rdoc +17 -3
- data/lib/sequel/adapters/amalgalite.rb +2 -2
- data/lib/sequel/adapters/do/mysql.rb +5 -2
- data/lib/sequel/adapters/ibmdb.rb +2 -2
- data/lib/sequel/adapters/jdbc.rb +126 -43
- data/lib/sequel/adapters/jdbc/as400.rb +11 -3
- data/lib/sequel/adapters/jdbc/db2.rb +2 -1
- data/lib/sequel/adapters/jdbc/derby.rb +44 -19
- data/lib/sequel/adapters/jdbc/h2.rb +32 -19
- data/lib/sequel/adapters/jdbc/hsqldb.rb +21 -17
- data/lib/sequel/adapters/jdbc/jtds.rb +9 -4
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -1
- data/lib/sequel/adapters/jdbc/mysql.rb +2 -1
- data/lib/sequel/adapters/jdbc/oracle.rb +21 -7
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -2
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -1
- data/lib/sequel/adapters/jdbc/sqlserver.rb +48 -18
- data/lib/sequel/adapters/mock.rb +2 -1
- data/lib/sequel/adapters/mysql.rb +4 -2
- data/lib/sequel/adapters/mysql2.rb +2 -2
- data/lib/sequel/adapters/odbc/mssql.rb +1 -1
- data/lib/sequel/adapters/openbase.rb +1 -1
- data/lib/sequel/adapters/oracle.rb +6 -6
- data/lib/sequel/adapters/postgres.rb +25 -12
- data/lib/sequel/adapters/shared/access.rb +14 -6
- data/lib/sequel/adapters/shared/db2.rb +36 -13
- data/lib/sequel/adapters/shared/firebird.rb +12 -5
- data/lib/sequel/adapters/shared/informix.rb +11 -3
- data/lib/sequel/adapters/shared/mssql.rb +94 -47
- data/lib/sequel/adapters/shared/mysql.rb +107 -49
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +2 -2
- data/lib/sequel/adapters/shared/oracle.rb +54 -27
- data/lib/sequel/adapters/shared/postgres.rb +65 -26
- data/lib/sequel/adapters/shared/progress.rb +4 -1
- data/lib/sequel/adapters/shared/sqlite.rb +36 -20
- data/lib/sequel/adapters/sqlite.rb +2 -3
- data/lib/sequel/adapters/swift/mysql.rb +3 -2
- data/lib/sequel/adapters/swift/sqlite.rb +2 -2
- data/lib/sequel/adapters/tinytds.rb +14 -8
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +7 -4
- data/lib/sequel/database/misc.rb +6 -2
- data/lib/sequel/dataset/graph.rb +33 -7
- data/lib/sequel/dataset/prepared_statements.rb +19 -5
- data/lib/sequel/dataset/sql.rb +611 -201
- data/lib/sequel/model/associations.rb +12 -5
- data/lib/sequel/model/base.rb +20 -5
- data/lib/sequel/plugins/sharding.rb +9 -29
- data/lib/sequel/sql.rb +2 -1
- data/lib/sequel/timezones.rb +14 -4
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +10 -0
- data/spec/adapters/oracle_spec.rb +1 -1
- data/spec/core/core_sql_spec.rb +3 -1
- data/spec/core/database_spec.rb +42 -0
- data/spec/core/dataset_spec.rb +10 -3
- data/spec/core/mock_adapter_spec.rb +4 -0
- data/spec/core/object_graph_spec.rb +38 -0
- data/spec/extensions/association_autoreloading_spec.rb +1 -10
- data/spec/extensions/association_dependencies_spec.rb +2 -12
- data/spec/extensions/association_pks_spec.rb +35 -39
- data/spec/extensions/caching_spec.rb +23 -50
- data/spec/extensions/class_table_inheritance_spec.rb +30 -82
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/hook_class_methods_spec.rb +65 -91
- data/spec/extensions/identity_map_spec.rb +33 -103
- data/spec/extensions/instance_filters_spec.rb +10 -21
- data/spec/extensions/instance_hooks_spec.rb +6 -24
- data/spec/extensions/json_serializer_spec.rb +4 -5
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +17 -39
- data/spec/extensions/many_through_many_spec.rb +135 -277
- data/spec/extensions/migration_spec.rb +18 -15
- data/spec/extensions/named_timezones_spec.rb +1 -1
- data/spec/extensions/nested_attributes_spec.rb +97 -92
- data/spec/extensions/optimistic_locking_spec.rb +9 -20
- data/spec/extensions/prepared_statements_associations_spec.rb +22 -37
- data/spec/extensions/prepared_statements_safe_spec.rb +9 -27
- data/spec/extensions/prepared_statements_spec.rb +11 -30
- data/spec/extensions/prepared_statements_with_pk_spec.rb +6 -13
- data/spec/extensions/pretty_table_spec.rb +1 -6
- data/spec/extensions/rcte_tree_spec.rb +41 -43
- data/spec/extensions/schema_dumper_spec.rb +3 -6
- data/spec/extensions/serialization_spec.rb +20 -32
- data/spec/extensions/sharding_spec.rb +66 -140
- data/spec/extensions/single_table_inheritance_spec.rb +14 -36
- data/spec/extensions/spec_helper.rb +10 -64
- data/spec/extensions/sql_expr_spec.rb +20 -60
- data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +1 -2
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/integration/dataset_test.rb +16 -4
- data/spec/integration/prepared_statement_test.rb +4 -2
- data/spec/model/eager_loading_spec.rb +16 -0
- data/spec/model/model_spec.rb +15 -1
- data/spec/model/record_spec.rb +60 -0
- metadata +23 -40
|
@@ -6,11 +6,8 @@ describe "optimistic_locking plugin" do
|
|
|
6
6
|
end
|
|
7
7
|
h = {1=>{:id=>1, :name=>'John', :lock_version=>2}}
|
|
8
8
|
lv = @lv = "lock_version"
|
|
9
|
-
@c.dataset.
|
|
10
|
-
|
|
11
|
-
@c.dataset.meta_def(:lv){lv}
|
|
12
|
-
@c.dataset.meta_def(:update) do |opts|
|
|
13
|
-
case update_sql(opts)
|
|
9
|
+
@c.dataset.numrows = proc do |sql|
|
|
10
|
+
case sql
|
|
14
11
|
when /UPDATE people SET (name|#{lv}) = ('Jim'|'Bob'|\d+), (?:name|#{lv}) = ('Jim'|'Bob'|\d+) WHERE \(\(id = (\d+)\) AND \(#{lv} = (\d+)\)\)/
|
|
15
12
|
name, nlv = $1 == 'name' ? [$2, $3] : [$3, $2]
|
|
16
13
|
m = h[$4.to_i]
|
|
@@ -28,20 +25,6 @@ describe "optimistic_locking plugin" do
|
|
|
28
25
|
else
|
|
29
26
|
0
|
|
30
27
|
end
|
|
31
|
-
else
|
|
32
|
-
puts update_sql(opts)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
@c.dataset.instance_eval do
|
|
36
|
-
def fetch_rows(sql)
|
|
37
|
-
m = h[1].dup
|
|
38
|
-
v = m.delete(:lock_version)
|
|
39
|
-
m[lv.to_sym] = v
|
|
40
|
-
yield(m)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
@c.dataset.meta_def(:delete) do
|
|
44
|
-
case delete_sql
|
|
45
28
|
when /DELETE FROM people WHERE \(\(id = (\d+)\) AND \(#{lv} = (\d+)\)\)/
|
|
46
29
|
m = h[$1.to_i]
|
|
47
30
|
if m && m[lv.to_sym] == $2.to_i
|
|
@@ -51,9 +34,15 @@ describe "optimistic_locking plugin" do
|
|
|
51
34
|
0
|
|
52
35
|
end
|
|
53
36
|
else
|
|
54
|
-
puts
|
|
37
|
+
puts sql
|
|
55
38
|
end
|
|
56
39
|
end
|
|
40
|
+
@c.dataset._fetch = proc do |sql|
|
|
41
|
+
m = h[1].dup
|
|
42
|
+
v = m.delete(:lock_version)
|
|
43
|
+
m[lv.to_sym] = v
|
|
44
|
+
m
|
|
45
|
+
end
|
|
57
46
|
@c.columns :id, :name, :lock_version
|
|
58
47
|
@c.plugin :optimistic_locking
|
|
59
48
|
end
|
|
@@ -2,23 +2,14 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
2
2
|
|
|
3
3
|
describe "Sequel::Plugins::AssociationPks" do
|
|
4
4
|
before do
|
|
5
|
-
@db =
|
|
6
|
-
|
|
7
|
-
def
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
@db = Sequel.mock
|
|
6
|
+
@db.extend_datasets do
|
|
7
|
+
def select_sql
|
|
8
|
+
sql = super
|
|
9
|
+
sql << ' -- prepared' if is_a?(Sequel::Dataset::PreparedStatementMethods)
|
|
10
|
+
sql
|
|
10
11
|
end
|
|
11
12
|
end
|
|
12
|
-
@db.meta_def(:dataset) do |*opts|
|
|
13
|
-
ds = super(*opts)
|
|
14
|
-
ds.extend mod
|
|
15
|
-
ds
|
|
16
|
-
end
|
|
17
|
-
def @db.transaction(opts)
|
|
18
|
-
execute('BEGIN')
|
|
19
|
-
yield
|
|
20
|
-
execute('COMMIT')
|
|
21
|
-
end
|
|
22
13
|
@Artist = Class.new(Sequel::Model(@db[:artists]))
|
|
23
14
|
@Artist.columns :id, :id2
|
|
24
15
|
@Album= Class.new(Sequel::Model(@db[:albums]))
|
|
@@ -32,24 +23,21 @@ describe "Sequel::Plugins::AssociationPks" do
|
|
|
32
23
|
@Album.many_to_many :tags, :class=>@Tag, :join_table=>:albums_tags, :left_key=>:album_id
|
|
33
24
|
@Artist.plugin :many_through_many
|
|
34
25
|
@Artist.many_through_many :tags, [[:albums, :artist_id, :id], [:albums_tags, :album_id, :tag_id]], :class=>@Tag
|
|
35
|
-
@db.
|
|
26
|
+
@db.sqls
|
|
36
27
|
end
|
|
37
28
|
|
|
38
29
|
specify "should run correct SQL for associations" do
|
|
39
30
|
@Artist.load(:id=>1).albums
|
|
40
|
-
@db.sqls.should == [
|
|
41
|
-
@db.reset
|
|
31
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE (albums.artist_id = 1) -- prepared"]
|
|
42
32
|
|
|
43
33
|
@Album.load(:id=>1, :artist_id=>2).artist
|
|
44
|
-
@db.sqls.should == [
|
|
45
|
-
@db.reset
|
|
34
|
+
@db.sqls.should == ["SELECT * FROM artists WHERE (artists.id = 2) LIMIT 1 -- prepared"]
|
|
46
35
|
|
|
47
36
|
@Album.load(:id=>1, :artist_id=>2).tags
|
|
48
|
-
@db.sqls.should == [
|
|
49
|
-
@db.reset
|
|
37
|
+
@db.sqls.should == ["SELECT tags.* FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id = tags.id) AND (albums_tags.album_id = 1)) -- prepared"]
|
|
50
38
|
|
|
51
39
|
@Artist.load(:id=>1).tags
|
|
52
|
-
@db.sqls.should == [
|
|
40
|
+
@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) AND (albums.artist_id = 1)) -- prepared"]
|
|
53
41
|
end
|
|
54
42
|
|
|
55
43
|
specify "should run correct SQL for composite key associations" do
|
|
@@ -59,19 +47,16 @@ describe "Sequel::Plugins::AssociationPks" do
|
|
|
59
47
|
@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]
|
|
60
48
|
|
|
61
49
|
@Artist.load(:id=>1, :id2=>2).albums
|
|
62
|
-
@db.sqls.should == [
|
|
63
|
-
@db.reset
|
|
50
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE ((albums.artist_id = 1) AND (albums.artist_id2 = 2)) -- prepared"]
|
|
64
51
|
|
|
65
52
|
@Album.load(:id=>1, :artist_id=>2, :artist_id2=>3).artist
|
|
66
|
-
@db.sqls.should == [
|
|
67
|
-
@db.reset
|
|
53
|
+
@db.sqls.should == ["SELECT * FROM artists WHERE ((artists.id = 2) AND (artists.id2 = 3)) LIMIT 1 -- prepared"]
|
|
68
54
|
|
|
69
55
|
@Album.load(:id=>1, :artist_id=>2, :id2=>3).tags
|
|
70
|
-
@db.sqls.should == [
|
|
71
|
-
@db.reset
|
|
56
|
+
@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) AND (albums_tags.album_id = 1) AND (albums_tags.album_id2 = 3)) -- prepared"]
|
|
72
57
|
|
|
73
58
|
@Artist.load(:id=>1, :id2=>2).tags
|
|
74
|
-
@db.sqls.should == [
|
|
59
|
+
@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) AND (albums.artist_id = 1) AND (albums.artist_id2 = 2)) -- prepared"]
|
|
75
60
|
end
|
|
76
61
|
|
|
77
62
|
specify "should not run query if no objects can be associated" do
|
|
@@ -82,45 +67,45 @@ describe "Sequel::Plugins::AssociationPks" do
|
|
|
82
67
|
|
|
83
68
|
specify "should run a regular query if there is a callback" do
|
|
84
69
|
@Artist.load(:id=>1).albums(proc{|ds| ds})
|
|
85
|
-
@db.sqls.should == [
|
|
70
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
86
71
|
end
|
|
87
72
|
|
|
88
73
|
specify "should run a regular query if :prepared_statement=>false option is used for the association" do
|
|
89
74
|
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id, :prepared_statement=>false
|
|
90
75
|
@Artist.load(:id=>1).albums
|
|
91
|
-
@db.sqls.should == [
|
|
76
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
92
77
|
end
|
|
93
78
|
|
|
94
79
|
specify "should run a regular query if unrecognized association is used" do
|
|
95
80
|
a = @Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
|
|
96
81
|
a[:type] = :foo
|
|
97
82
|
@Artist.load(:id=>1).albums
|
|
98
|
-
@db.sqls.should == [
|
|
83
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
99
84
|
end
|
|
100
85
|
|
|
101
86
|
specify "should run a regular query if a block is used when defining the association" do
|
|
102
87
|
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id do |ds| ds end
|
|
103
88
|
@Artist.load(:id=>1).albums
|
|
104
|
-
@db.sqls.should == [
|
|
89
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE (albums.artist_id = 1)"]
|
|
105
90
|
end
|
|
106
91
|
|
|
107
92
|
specify "should run a regular query if :conditions option is used when defining the association" do
|
|
108
93
|
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id, :conditions=>{:a=>1}
|
|
109
94
|
@Artist.load(:id=>1).albums
|
|
110
|
-
@db.sqls.should == [
|
|
95
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE ((albums.artist_id = 1) AND (a = 1))"]
|
|
111
96
|
end
|
|
112
97
|
|
|
113
98
|
specify "should run a regular query if :dataset option is used when defining the association" do
|
|
114
99
|
album = @Album
|
|
115
100
|
@Artist.one_to_many :albums, :class=>@Album, :dataset=>proc{album.filter(:artist_id=>id)}
|
|
116
101
|
@Artist.load(:id=>1).albums
|
|
117
|
-
@db.sqls.should == [
|
|
102
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE (artist_id = 1)"]
|
|
118
103
|
end
|
|
119
104
|
|
|
120
105
|
specify "should run a regular query if :cloning an association that doesn't used prepared statements" do
|
|
121
106
|
@Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id, :conditions=>{:a=>1}
|
|
122
107
|
@Artist.one_to_many :oalbums, :clone=>:albums
|
|
123
108
|
@Artist.load(:id=>1).oalbums
|
|
124
|
-
@db.sqls.should == [
|
|
109
|
+
@db.sqls.should == ["SELECT * FROM albums WHERE ((albums.artist_id = 1) AND (a = 1))"]
|
|
125
110
|
end
|
|
126
111
|
end
|
|
@@ -2,29 +2,13 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
2
2
|
|
|
3
3
|
describe "prepared_statements_safe plugin" do
|
|
4
4
|
before do
|
|
5
|
-
@
|
|
5
|
+
@db = Sequel.mock(:fetch=>{:id=>1, :name=>'foo', :i=>2}, :autoid=>proc{|sql| 1}, :numrows=>1, :servers=>{:read_only=>{}})
|
|
6
|
+
@c = Class.new(Sequel::Model(@db[:people]))
|
|
6
7
|
@c.columns :id, :name, :i
|
|
7
|
-
@ds = ds = @c.dataset
|
|
8
8
|
@c.instance_variable_set(:@db_schema, {:i=>{}, :name=>{}, :id=>{:primary_key=>true}})
|
|
9
|
-
def ds.fetch_rows(sql)
|
|
10
|
-
db << {:server=>@opts[:server] || :read_only}.merge(opts)[:server]
|
|
11
|
-
super{|h|}
|
|
12
|
-
yield(:id=>1, :name=>'foo', :i=>2)
|
|
13
|
-
end
|
|
14
|
-
def ds.update(*)
|
|
15
|
-
db << default_server_opts(opts)[:server]
|
|
16
|
-
super
|
|
17
|
-
end
|
|
18
|
-
def ds.insert(*)
|
|
19
|
-
db << default_server_opts(opts)[:server]
|
|
20
|
-
super
|
|
21
|
-
1
|
|
22
|
-
end
|
|
23
9
|
@c.plugin :prepared_statements_safe
|
|
24
10
|
@p = @c.load(:id=>1, :name=>'foo', :i=>2)
|
|
25
|
-
@
|
|
26
|
-
@sqls = @c.db.sqls
|
|
27
|
-
@sqls.clear
|
|
11
|
+
@db.sqls
|
|
28
12
|
end
|
|
29
13
|
|
|
30
14
|
specify "should load the prepared_statements plugin" do
|
|
@@ -39,32 +23,30 @@ describe "prepared_statements_safe plugin" do
|
|
|
39
23
|
|
|
40
24
|
specify "should set default values when creating" do
|
|
41
25
|
@c.create
|
|
42
|
-
@sqls
|
|
43
|
-
@sqls.clear
|
|
26
|
+
@db.sqls.first.should =~ /INSERT INTO people \((i|name), (i|name)\) VALUES \(NULL, NULL\)/
|
|
44
27
|
@c.create(:name=>'foo')
|
|
45
|
-
@sqls
|
|
46
|
-
@sqls.clear
|
|
28
|
+
@db.sqls.first.should =~ /INSERT INTO people \((i|name), (i|name)\) VALUES \((NULL|'foo'), (NULL|'foo')\)/
|
|
47
29
|
@c.create(:name=>'foo', :i=>2)
|
|
48
|
-
@sqls
|
|
30
|
+
@db.sqls.first.should =~ /INSERT INTO people \((i|name), (i|name)\) VALUES \((2|'foo'), (2|'foo')\)/
|
|
49
31
|
end
|
|
50
32
|
|
|
51
33
|
specify "should use database default values" do
|
|
52
34
|
@c.instance_variable_set(:@db_schema, {:i=>{:ruby_default=>2}, :name=>{:ruby_default=>'foo'}, :id=>{:primary_key=>true}})
|
|
53
35
|
c = Class.new(@c)
|
|
54
36
|
c.create
|
|
55
|
-
@sqls
|
|
37
|
+
@db.sqls.first.should =~ /INSERT INTO people \((i|name), (i|name)\) VALUES \((2|'foo'), (2|'foo')\)/
|
|
56
38
|
end
|
|
57
39
|
|
|
58
40
|
specify "should not set defaults for unparseable dataset default values" do
|
|
59
41
|
@c.instance_variable_set(:@db_schema, {:i=>{:default=>'f(x)'}, :name=>{:ruby_default=>'foo'}, :id=>{:primary_key=>true}})
|
|
60
42
|
c = Class.new(@c)
|
|
61
43
|
c.create
|
|
62
|
-
@sqls
|
|
44
|
+
@db.sqls.first.should == "INSERT INTO people (name) VALUES ('foo')"
|
|
63
45
|
end
|
|
64
46
|
|
|
65
47
|
specify "should save all fields when updating" do
|
|
66
48
|
@p.update(:i=>3)
|
|
67
|
-
@sqls
|
|
49
|
+
@db.sqls.first.should =~ /UPDATE people SET (name = 'foo'|i = 3), (name = 'foo'|i = 3) WHERE \(id = 1\)/
|
|
68
50
|
end
|
|
69
51
|
|
|
70
52
|
specify "should work with abstract classes" do
|
|
@@ -2,52 +2,33 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
2
2
|
|
|
3
3
|
describe "prepared_statements plugin" do
|
|
4
4
|
before do
|
|
5
|
-
@
|
|
5
|
+
@db = Sequel.mock(:fetch=>{:id=>1, :name=>'foo', :i=>2}, :autoid=>proc{|sql| 1}, :numrows=>1, :servers=>{:read_only=>{}})
|
|
6
|
+
@c = Class.new(Sequel::Model(@db[:people]))
|
|
6
7
|
@c.columns :id, :name, :i
|
|
7
|
-
@ds = ds = @c.dataset
|
|
8
|
-
def ds.fetch_rows(sql)
|
|
9
|
-
db << {:server=>@opts[:server] || :read_only}.merge(opts)[:server]
|
|
10
|
-
super{|h|}
|
|
11
|
-
yield(:id=>1, :name=>'foo', :i=>2)
|
|
12
|
-
end
|
|
13
|
-
def ds.update(*)
|
|
14
|
-
db << default_server_opts(opts)[:server]
|
|
15
|
-
super
|
|
16
|
-
end
|
|
17
|
-
def ds.insert(*)
|
|
18
|
-
db << default_server_opts(opts)[:server]
|
|
19
|
-
super
|
|
20
|
-
1
|
|
21
|
-
end
|
|
22
|
-
def ds.delete(*)
|
|
23
|
-
db << default_server_opts(opts)[:server]
|
|
24
|
-
super
|
|
25
|
-
end
|
|
26
8
|
@c.plugin :prepared_statements
|
|
27
9
|
@p = @c.load(:id=>1, :name=>'foo', :i=>2)
|
|
28
|
-
@c.
|
|
29
|
-
@
|
|
30
|
-
@sqls.clear
|
|
10
|
+
@ds = @c.dataset
|
|
11
|
+
@db.sqls
|
|
31
12
|
end
|
|
32
13
|
|
|
33
14
|
specify "should correctly lookup by primary key" do
|
|
34
15
|
@c[1].should == @p
|
|
35
|
-
@sqls.should == [
|
|
16
|
+
@db.sqls.should == ["SELECT * FROM people WHERE (id = 1) LIMIT 1 -- read_only"]
|
|
36
17
|
end
|
|
37
18
|
|
|
38
19
|
specify "should correctly delete instance" do
|
|
39
20
|
@p.destroy.should == @p
|
|
40
|
-
@sqls.should == [
|
|
21
|
+
@db.sqls.should == ["DELETE FROM people WHERE (id = 1)"]
|
|
41
22
|
end
|
|
42
23
|
|
|
43
24
|
specify "should correctly update instance" do
|
|
44
25
|
@p.update(:name=>'bar').should == @c.load(:id=>1, :name=>'bar', :i => 2)
|
|
45
|
-
@sqls.should == [
|
|
26
|
+
@db.sqls.should == ["UPDATE people SET name = 'bar' WHERE (id = 1)"]
|
|
46
27
|
end
|
|
47
28
|
|
|
48
29
|
specify "should correctly create instance" do
|
|
49
30
|
@c.create(:name=>'foo').should == @c.load(:id=>1, :name=>'foo', :i => 2)
|
|
50
|
-
@sqls.should == [
|
|
31
|
+
@db.sqls.should == ["INSERT INTO people (name) VALUES ('foo')", "SELECT * FROM people WHERE (id = 1) LIMIT 1"]
|
|
51
32
|
end
|
|
52
33
|
|
|
53
34
|
specify "should correctly create instance if dataset supports insert_select" do
|
|
@@ -55,18 +36,18 @@ describe "prepared_statements plugin" do
|
|
|
55
36
|
true
|
|
56
37
|
end
|
|
57
38
|
def @ds.insert_select(h)
|
|
58
|
-
|
|
39
|
+
{:id=>1, :name=>'foo', :i => 2}
|
|
59
40
|
end
|
|
60
41
|
def @ds.insert_sql(*)
|
|
61
42
|
"#{super}#{' RETURNING *' if opts.has_key?(:returning)}"
|
|
62
43
|
end
|
|
63
44
|
@c.create(:name=>'foo').should == @c.load(:id=>1, :name=>'foo', :i => 2)
|
|
64
|
-
@sqls.should == [
|
|
45
|
+
@db.sqls.should == ["INSERT INTO people (name) VALUES ('foo') RETURNING *"]
|
|
65
46
|
end
|
|
66
47
|
|
|
67
48
|
specify "should work correctly when subclassing" do
|
|
68
49
|
c = Class.new(@c)
|
|
69
50
|
c[1].should == c.load(:id=>1, :name=>'foo', :i=>2)
|
|
70
|
-
@sqls.should == [
|
|
51
|
+
@db.sqls.should == ["SELECT * FROM people WHERE (id = 1) LIMIT 1 -- read_only"]
|
|
71
52
|
end
|
|
72
53
|
end
|
|
@@ -2,19 +2,12 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
2
2
|
|
|
3
3
|
describe "prepared_statements_with_pk plugin" do
|
|
4
4
|
before do
|
|
5
|
-
@
|
|
5
|
+
@db = Sequel.mock(:fetch=>{:id=>1, :name=>'foo', :i=>2}, :autoid=>proc{|sql| 1}, :numrows=>1, :servers=>{:read_only=>{}})
|
|
6
|
+
@c = Class.new(Sequel::Model(@db[:people]))
|
|
6
7
|
@c.columns :id, :name, :i
|
|
7
|
-
@ds = ds = @c.dataset
|
|
8
|
-
def ds.fetch_rows(sql)
|
|
9
|
-
db << {:server=>@opts[:server] || :read_only}.merge(opts)[:server]
|
|
10
|
-
super{|h|}
|
|
11
|
-
yield(:id=>1, :name=>'foo', :i=>2)
|
|
12
|
-
end
|
|
13
8
|
@c.plugin :prepared_statements_with_pk
|
|
14
9
|
@p = @c.load(:id=>1, :name=>'foo', :i=>2)
|
|
15
|
-
@
|
|
16
|
-
@sqls = @c.db.sqls
|
|
17
|
-
@sqls.clear
|
|
10
|
+
@db.sqls
|
|
18
11
|
end
|
|
19
12
|
|
|
20
13
|
specify "should load the prepared_statements plugin" do
|
|
@@ -23,16 +16,16 @@ describe "prepared_statements_with_pk plugin" do
|
|
|
23
16
|
|
|
24
17
|
specify "should correctly lookup by primary key from dataset" do
|
|
25
18
|
@c.dataset.filter(:name=>'foo')[1].should == @p
|
|
26
|
-
@sqls.should == [
|
|
19
|
+
@c.db.sqls.should == ["SELECT * FROM people WHERE ((name = 'foo') AND (people.id = 1)) LIMIT 1 -- read_only"]
|
|
27
20
|
end
|
|
28
21
|
|
|
29
22
|
specify "should still work correctly if there are multiple conflicting variables" do
|
|
30
23
|
@c.dataset.filter(:name=>'foo').or(:name=>'bar')[1].should == @p
|
|
31
|
-
@sqls.should == [
|
|
24
|
+
@c.db.sqls.should == ["SELECT * FROM people WHERE (((name = 'foo') OR (name = 'bar')) AND (people.id = 1)) LIMIT 1 -- read_only"]
|
|
32
25
|
end
|
|
33
26
|
|
|
34
27
|
specify "should still work correctly if the primary key is used elsewhere in the query" do
|
|
35
28
|
@c.dataset.filter{id > 2}[1].should == @p
|
|
36
|
-
@sqls.should == [
|
|
29
|
+
@c.db.sqls.should == ["SELECT * FROM people WHERE ((id > 2) AND (people.id = 1)) LIMIT 1 -- read_only"]
|
|
37
30
|
end
|
|
38
31
|
end
|
|
@@ -7,12 +7,7 @@ describe "Dataset#print" do
|
|
|
7
7
|
@output = StringIO.new
|
|
8
8
|
@orig_stdout = $stdout
|
|
9
9
|
$stdout = @output
|
|
10
|
-
@dataset = Sequel
|
|
11
|
-
def @dataset.fetch_rows(sql)
|
|
12
|
-
yield({:a=>1, :b=>2})
|
|
13
|
-
yield({:a=>3, :b=>4})
|
|
14
|
-
yield({:a=>5, :b=>6})
|
|
15
|
-
end
|
|
10
|
+
@dataset = Sequel.mock(:fetch=>[{:a=>1, :b=>2}, {:a=>3, :b=>4}, {:a=>5, :b=>6}])[:items]
|
|
16
11
|
end
|
|
17
12
|
|
|
18
13
|
after do
|
|
@@ -8,13 +8,6 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
8
8
|
columns :id, :name, :parent_id, :i, :pi
|
|
9
9
|
end
|
|
10
10
|
@ds = @c.dataset
|
|
11
|
-
class << @ds
|
|
12
|
-
attr_accessor :row_sets
|
|
13
|
-
def fetch_rows(sql)
|
|
14
|
-
@db << sql
|
|
15
|
-
row_sets.shift.each{|row| yield row}
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
11
|
@o = @c.load(:id=>2, :parent_id=>1, :name=>'AA', :i=>3, :pi=>4)
|
|
19
12
|
MODEL_DB.reset
|
|
20
13
|
end
|
|
@@ -55,7 +48,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
55
48
|
|
|
56
49
|
it "should add all parent associations when lazily loading ancestors" do
|
|
57
50
|
@c.plugin :rcte_tree
|
|
58
|
-
@ds.
|
|
51
|
+
@ds._fetch = [[{:id=>1, :name=>'A', :parent_id=>3}, {:id=>4, :name=>'B', :parent_id=>nil}, {:id=>3, :name=>'?', :parent_id=>4}]]
|
|
59
52
|
@o.ancestors.should == [@c.load(:id=>1, :name=>'A', :parent_id=>3), @c.load(:id=>4, :name=>'B', :parent_id=>nil), @c.load(:id=>3, :name=>'?', :parent_id=>4)]
|
|
60
53
|
@o.associations[:parent].should == @c.load(:id=>1, :name=>'A', :parent_id=>3)
|
|
61
54
|
@o.associations[:parent].associations[:parent].should == @c.load(:id=>3, :name=>'?', :parent_id=>4)
|
|
@@ -65,7 +58,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
65
58
|
|
|
66
59
|
it "should add all parent associations when lazily loading ancestors and giving options" do
|
|
67
60
|
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :ancestors=>{:name=>:as}, :parent=>{:name=>:p}
|
|
68
|
-
@ds.
|
|
61
|
+
@ds._fetch = [[{:i=>4, :name=>'A', :pi=>5}, {:i=>6, :name=>'B', :pi=>nil}, {:i=>5, :name=>'?', :pi=>6}]]
|
|
69
62
|
@o.as.should == [@c.load(:i=>4, :name=>'A', :pi=>5), @c.load(:i=>6, :name=>'B', :pi=>nil), @c.load(:i=>5, :name=>'?', :pi=>6)]
|
|
70
63
|
@o.associations[:p].should == @c.load(:i=>4, :name=>'A', :pi=>5)
|
|
71
64
|
@o.associations[:p].associations[:p].should == @c.load(:i=>5, :name=>'?', :pi=>6)
|
|
@@ -75,7 +68,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
75
68
|
|
|
76
69
|
it "should add all children associations when lazily loading descendants" do
|
|
77
70
|
@c.plugin :rcte_tree
|
|
78
|
-
@ds.
|
|
71
|
+
@ds._fetch = [[{:id=>3, :name=>'??', :parent_id=>1}, {:id=>1, :name=>'A', :parent_id=>2}, {:id=>4, :name=>'B', :parent_id=>2}, {:id=>5, :name=>'?', :parent_id=>3}]]
|
|
79
72
|
@o.descendants.should == [@c.load(:id=>3, :name=>'??', :parent_id=>1), @c.load(:id=>1, :name=>'A', :parent_id=>2), @c.load(:id=>4, :name=>'B', :parent_id=>2), @c.load(:id=>5, :name=>'?', :parent_id=>3)]
|
|
80
73
|
@o.associations[:children].should == [@c.load(:id=>1, :name=>'A', :parent_id=>2), @c.load(:id=>4, :name=>'B', :parent_id=>2)]
|
|
81
74
|
@o.associations[:children].map{|c1| c1.associations[:children]}.should == [[@c.load(:id=>3, :name=>'??', :parent_id=>1)], []]
|
|
@@ -85,7 +78,7 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
85
78
|
|
|
86
79
|
it "should add all children associations when lazily loading descendants and giving options" do
|
|
87
80
|
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :children=>{:name=>:cs}, :descendants=>{:name=>:ds}
|
|
88
|
-
@ds.
|
|
81
|
+
@ds._fetch = [[{:i=>7, :name=>'??', :pi=>5}, {:i=>5, :name=>'A', :pi=>3}, {:i=>6, :name=>'B', :pi=>3}, {:i=>8, :name=>'?', :pi=>7}]]
|
|
89
82
|
@o.ds.should == [@c.load(:i=>7, :name=>'??', :pi=>5), @c.load(:i=>5, :name=>'A', :pi=>3), @c.load(:i=>6, :name=>'B', :pi=>3), @c.load(:i=>8, :name=>'?', :pi=>7)]
|
|
90
83
|
@o.associations[:cs].should == [@c.load(:i=>5, :name=>'A', :pi=>3), @c.load(:i=>6, :name=>'B', :pi=>3)]
|
|
91
84
|
@o.associations[:cs].map{|c1| c1.associations[:cs]}.should == [[@c.load(:i=>7, :name=>'??', :pi=>5)], []]
|
|
@@ -95,13 +88,14 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
95
88
|
|
|
96
89
|
it "should eagerly load ancestors" do
|
|
97
90
|
@c.plugin :rcte_tree
|
|
98
|
-
@ds.
|
|
91
|
+
@ds._fetch = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}, {:id=>9, :parent_id=>nil, :name=>'E'}],
|
|
99
92
|
[{:id=>2, :name=>'AA', :parent_id=>1, :x_root_x=>2},
|
|
100
93
|
{:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>1}, {:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>2},
|
|
101
94
|
{:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>2}, {:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>1}]]
|
|
102
95
|
os = @ds.eager(:ancestors).all
|
|
103
|
-
MODEL_DB.sqls
|
|
104
|
-
|
|
96
|
+
sqls = MODEL_DB.sqls
|
|
97
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
98
|
+
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/
|
|
105
99
|
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')]
|
|
106
100
|
os.map{|o| o.ancestors}.should == [[@c.load(:id=>1, :name=>'00', :parent_id=>8), @c.load(:id=>8, :name=>'?', :parent_id=>nil)],
|
|
107
101
|
[@c.load(:id=>2, :name=>'AA', :parent_id=>1), @c.load(:id=>1, :name=>'00', :parent_id=>8), @c.load(:id=>8, :name=>'?', :parent_id=>nil)],
|
|
@@ -111,18 +105,19 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
111
105
|
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]
|
|
112
106
|
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]
|
|
113
107
|
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]
|
|
114
|
-
MODEL_DB.
|
|
108
|
+
MODEL_DB.sqls.should == []
|
|
115
109
|
end
|
|
116
110
|
|
|
117
111
|
it "should eagerly load ancestors when giving options" do
|
|
118
112
|
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :key_alias=>:kal, :cte_name=>:cte, :ancestors=>{:name=>:as}, :parent=>{:name=>:p}
|
|
119
|
-
@ds.
|
|
113
|
+
@ds._fetch = [[{:i=>2, :pi=>1, :name=>'AA'}, {:i=>6, :pi=>2, :name=>'C'}, {:i=>7, :pi=>1, :name=>'D'}, {:i=>9, :pi=>nil, :name=>'E'}],
|
|
120
114
|
[{:i=>2, :name=>'AA', :pi=>1, :kal=>2},
|
|
121
115
|
{:i=>1, :name=>'00', :pi=>8, :kal=>1}, {:i=>1, :name=>'00', :pi=>8, :kal=>2},
|
|
122
116
|
{:i=>8, :name=>'?', :pi=>nil, :kal=>2}, {:i=>8, :name=>'?', :pi=>nil, :kal=>1}]]
|
|
123
117
|
os = @ds.eager(:as).all
|
|
124
|
-
MODEL_DB.sqls
|
|
125
|
-
|
|
118
|
+
sqls = MODEL_DB.sqls
|
|
119
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
120
|
+
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/
|
|
126
121
|
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')]
|
|
127
122
|
os.map{|o| o.as}.should == [[@c.load(:i=>1, :name=>'00', :pi=>8), @c.load(:i=>8, :name=>'?', :pi=>nil)],
|
|
128
123
|
[@c.load(:i=>2, :name=>'AA', :pi=>1), @c.load(:i=>1, :name=>'00', :pi=>8), @c.load(:i=>8, :name=>'?', :pi=>nil)],
|
|
@@ -132,30 +127,30 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
132
127
|
os.map{|o| o.p.p if o.p}.should == [@c.load(:i=>8, :name=>'?', :pi=>nil), @c.load(:i=>1, :name=>'00', :pi=>8), @c.load(:i=>8, :name=>'?', :pi=>nil), nil]
|
|
133
128
|
os.map{|o| o.p.p.p if o.p and o.p.p}.should == [nil, @c.load(:i=>8, :name=>'?', :pi=>nil), nil, nil]
|
|
134
129
|
os.map{|o| o.p.p.p.p if o.p and o.p.p and o.p.p.p}.should == [nil, nil, nil, nil]
|
|
135
|
-
MODEL_DB.new_sqls.should == []
|
|
136
130
|
end
|
|
137
131
|
|
|
138
132
|
it "should eagerly load ancestors respecting association option :conditions" do
|
|
139
133
|
@c.plugin :rcte_tree, :conditions => {:i => 1}
|
|
140
|
-
@ds.
|
|
134
|
+
@ds._fetch = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}, {:id=>9, :parent_id=>nil, :name=>'E'}],
|
|
141
135
|
[{:id=>2, :name=>'AA', :parent_id=>1, :x_root_x=>2},
|
|
142
136
|
{:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>1}, {:id=>1, :name=>'00', :parent_id=>8, :x_root_x=>2},
|
|
143
137
|
{:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>2}, {:id=>8, :name=>'?', :parent_id=>nil, :x_root_x=>1}]]
|
|
144
138
|
os = @ds.eager(:ancestors).all
|
|
145
|
-
MODEL_DB.sqls
|
|
146
|
-
|
|
147
|
-
|
|
139
|
+
sqls = MODEL_DB.sqls
|
|
140
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
141
|
+
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\)/
|
|
148
142
|
end
|
|
149
143
|
|
|
150
144
|
it "should eagerly load descendants" do
|
|
151
145
|
@c.plugin :rcte_tree
|
|
152
|
-
@ds.
|
|
146
|
+
@ds._fetch = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}],
|
|
153
147
|
[{:id=>6, :parent_id=>2, :name=>'C', :x_root_x=>2}, {:id=>9, :parent_id=>2, :name=>'E', :x_root_x=>2},
|
|
154
148
|
{:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>6}, {:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>2},
|
|
155
149
|
{:id=>4, :name=>'?', :parent_id=>7, :x_root_x=>7}, {:id=>5, :name=>'?', :parent_id=>4, :x_root_x=>7}]]
|
|
156
150
|
os = @ds.eager(:descendants).all
|
|
157
|
-
MODEL_DB.sqls
|
|
158
|
-
|
|
151
|
+
sqls = MODEL_DB.sqls
|
|
152
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
153
|
+
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/
|
|
159
154
|
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')]
|
|
160
155
|
os.map{|o| o.descendants}.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)],
|
|
161
156
|
[@c.load(:id=>3, :name=>'00', :parent_id=>6)],
|
|
@@ -163,18 +158,19 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
163
158
|
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)]]
|
|
164
159
|
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)]]]
|
|
165
160
|
os.map{|o1| o1.children.map{|o2| o2.children.map{|o3| o3.children}}}.should == [[[[]], []], [[]], [[[]]]]
|
|
166
|
-
MODEL_DB.
|
|
161
|
+
MODEL_DB.sqls.should == []
|
|
167
162
|
end
|
|
168
163
|
|
|
169
164
|
it "should eagerly load descendants when giving options" do
|
|
170
165
|
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :key_alias=>:kal, :cte_name=>:cte, :children=>{:name=>:cs}, :descendants=>{:name=>:ds}
|
|
171
|
-
@ds.
|
|
166
|
+
@ds._fetch = [[{:i=>2, :pi=>1, :name=>'AA'}, {:i=>6, :pi=>2, :name=>'C'}, {:i=>7, :pi=>1, :name=>'D'}],
|
|
172
167
|
[{:i=>6, :pi=>2, :name=>'C', :kal=>2}, {:i=>9, :pi=>2, :name=>'E', :kal=>2},
|
|
173
168
|
{:i=>3, :name=>'00', :pi=>6, :kal=>6}, {:i=>3, :name=>'00', :pi=>6, :kal=>2},
|
|
174
169
|
{:i=>4, :name=>'?', :pi=>7, :kal=>7}, {:i=>5, :name=>'?', :pi=>4, :kal=>7}]]
|
|
175
170
|
os = @ds.eager(:ds).all
|
|
176
|
-
MODEL_DB.sqls
|
|
177
|
-
|
|
171
|
+
sqls = MODEL_DB.sqls
|
|
172
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
173
|
+
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/
|
|
178
174
|
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')]
|
|
179
175
|
os.map{|o| o.ds}.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)],
|
|
180
176
|
[@c.load(:i=>3, :name=>'00', :pi=>6)],
|
|
@@ -182,18 +178,19 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
182
178
|
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)]]
|
|
183
179
|
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)]]]
|
|
184
180
|
os.map{|o1| o1.cs.map{|o2| o2.cs.map{|o3| o3.cs}}}.should == [[[[]], []], [[]], [[[]]]]
|
|
185
|
-
MODEL_DB.
|
|
181
|
+
MODEL_DB.sqls.should == []
|
|
186
182
|
end
|
|
187
183
|
|
|
188
184
|
it "should eagerly load descendants to a given level" do
|
|
189
185
|
@c.plugin :rcte_tree
|
|
190
|
-
@ds.
|
|
186
|
+
@ds._fetch = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}],
|
|
191
187
|
[{:id=>6, :parent_id=>2, :name=>'C', :x_root_x=>2, :x_level_x=>0}, {:id=>9, :parent_id=>2, :name=>'E', :x_root_x=>2, :x_level_x=>0},
|
|
192
188
|
{: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},
|
|
193
189
|
{: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}]]
|
|
194
190
|
os = @ds.eager(:descendants=>2).all
|
|
195
|
-
MODEL_DB.sqls
|
|
196
|
-
|
|
191
|
+
sqls = MODEL_DB.sqls
|
|
192
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
193
|
+
sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x, nodes\.\*, 0 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/
|
|
197
194
|
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')]
|
|
198
195
|
os.map{|o| o.descendants}.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)],
|
|
199
196
|
[@c.load(:id=>3, :name=>'00', :parent_id=>6)],
|
|
@@ -201,18 +198,19 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
201
198
|
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)]]
|
|
202
199
|
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)]]]
|
|
203
200
|
os.map{|o1| o1.associations[:children].map{|o2| o2.associations[:children].map{|o3| o3.associations[:children]}}}.should == [[[[]], []], [[]], [[nil]]]
|
|
204
|
-
MODEL_DB.
|
|
201
|
+
MODEL_DB.sqls.should == []
|
|
205
202
|
end
|
|
206
203
|
|
|
207
204
|
it "should eagerly load descendants to a given level when giving options" do
|
|
208
205
|
@c.plugin :rcte_tree, :primary_key=>:i, :key=>:pi, :key_alias=>:kal, :level_alias=>:lal, :cte_name=>:cte, :children=>{:name=>:cs}, :descendants=>{:name=>:ds}
|
|
209
|
-
@ds.
|
|
206
|
+
@ds._fetch = [[{:i=>2, :pi=>1, :name=>'AA'}, {:i=>6, :pi=>2, :name=>'C'}, {:i=>7, :pi=>1, :name=>'D'}],
|
|
210
207
|
[{:i=>6, :pi=>2, :name=>'C', :kal=>2, :lal=>0}, {:i=>9, :pi=>2, :name=>'E', :kal=>2, :lal=>0},
|
|
211
208
|
{:i=>3, :name=>'00', :pi=>6, :kal=>6, :lal=>0}, {:i=>3, :name=>'00', :pi=>6, :kal=>2, :lal=>1},
|
|
212
209
|
{:i=>4, :name=>'?', :pi=>7, :kal=>7, :lal=>0}, {:i=>5, :name=>'?', :pi=>4, :kal=>7, :lal=>1}]]
|
|
213
210
|
os = @ds.eager(:ds=>2).all
|
|
214
|
-
MODEL_DB.sqls
|
|
215
|
-
|
|
211
|
+
sqls = MODEL_DB.sqls
|
|
212
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
213
|
+
sqls.last.should =~ /WITH cte AS \(SELECT pi AS kal, nodes\.\*, 0 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/
|
|
216
214
|
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')]
|
|
217
215
|
os.map{|o| o.ds}.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)],
|
|
218
216
|
[@c.load(:i=>3, :name=>'00', :pi=>6)],
|
|
@@ -220,18 +218,18 @@ describe Sequel::Model, "rcte_tree" do
|
|
|
220
218
|
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)]]
|
|
221
219
|
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)]]]
|
|
222
220
|
os.map{|o1| o1.associations[:cs].map{|o2| o2.associations[:cs].map{|o3| o3.associations[:cs]}}}.should == [[[[]], []], [[]], [[nil]]]
|
|
223
|
-
MODEL_DB.
|
|
221
|
+
MODEL_DB.sqls.should == []
|
|
224
222
|
end
|
|
225
223
|
|
|
226
224
|
it "should eagerly load descendants respecting association option :conditions" do
|
|
227
225
|
@c.plugin :rcte_tree, :conditions => {:i => 1}
|
|
228
|
-
@ds.
|
|
226
|
+
@ds._fetch = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}],
|
|
229
227
|
[{:id=>6, :parent_id=>2, :name=>'C', :x_root_x=>2}, {:id=>9, :parent_id=>2, :name=>'E', :x_root_x=>2},
|
|
230
228
|
{:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>6}, {:id=>3, :name=>'00', :parent_id=>6, :x_root_x=>2},
|
|
231
229
|
{:id=>4, :name=>'?', :parent_id=>7, :x_root_x=>7}, {:id=>5, :name=>'?', :parent_id=>4, :x_root_x=>7}]]
|
|
232
230
|
os = @ds.eager(:descendants).all
|
|
233
|
-
MODEL_DB.sqls
|
|
234
|
-
|
|
235
|
-
|
|
231
|
+
sqls = MODEL_DB.sqls
|
|
232
|
+
sqls.first.should == "SELECT * FROM nodes"
|
|
233
|
+
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\)/
|
|
236
234
|
end
|
|
237
235
|
end
|