sequel 3.29.0 → 3.30.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/CHANGELOG +35 -3
  2. data/Rakefile +2 -1
  3. data/doc/association_basics.rdoc +11 -0
  4. data/doc/opening_databases.rdoc +2 -0
  5. data/doc/release_notes/3.30.0.txt +135 -0
  6. data/doc/testing.rdoc +17 -3
  7. data/lib/sequel/adapters/amalgalite.rb +2 -2
  8. data/lib/sequel/adapters/do/mysql.rb +5 -2
  9. data/lib/sequel/adapters/ibmdb.rb +2 -2
  10. data/lib/sequel/adapters/jdbc.rb +126 -43
  11. data/lib/sequel/adapters/jdbc/as400.rb +11 -3
  12. data/lib/sequel/adapters/jdbc/db2.rb +2 -1
  13. data/lib/sequel/adapters/jdbc/derby.rb +44 -19
  14. data/lib/sequel/adapters/jdbc/h2.rb +32 -19
  15. data/lib/sequel/adapters/jdbc/hsqldb.rb +21 -17
  16. data/lib/sequel/adapters/jdbc/jtds.rb +9 -4
  17. data/lib/sequel/adapters/jdbc/mssql.rb +3 -1
  18. data/lib/sequel/adapters/jdbc/mysql.rb +2 -1
  19. data/lib/sequel/adapters/jdbc/oracle.rb +21 -7
  20. data/lib/sequel/adapters/jdbc/postgresql.rb +3 -2
  21. data/lib/sequel/adapters/jdbc/sqlite.rb +2 -1
  22. data/lib/sequel/adapters/jdbc/sqlserver.rb +48 -18
  23. data/lib/sequel/adapters/mock.rb +2 -1
  24. data/lib/sequel/adapters/mysql.rb +4 -2
  25. data/lib/sequel/adapters/mysql2.rb +2 -2
  26. data/lib/sequel/adapters/odbc/mssql.rb +1 -1
  27. data/lib/sequel/adapters/openbase.rb +1 -1
  28. data/lib/sequel/adapters/oracle.rb +6 -6
  29. data/lib/sequel/adapters/postgres.rb +25 -12
  30. data/lib/sequel/adapters/shared/access.rb +14 -6
  31. data/lib/sequel/adapters/shared/db2.rb +36 -13
  32. data/lib/sequel/adapters/shared/firebird.rb +12 -5
  33. data/lib/sequel/adapters/shared/informix.rb +11 -3
  34. data/lib/sequel/adapters/shared/mssql.rb +94 -47
  35. data/lib/sequel/adapters/shared/mysql.rb +107 -49
  36. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +2 -2
  37. data/lib/sequel/adapters/shared/oracle.rb +54 -27
  38. data/lib/sequel/adapters/shared/postgres.rb +65 -26
  39. data/lib/sequel/adapters/shared/progress.rb +4 -1
  40. data/lib/sequel/adapters/shared/sqlite.rb +36 -20
  41. data/lib/sequel/adapters/sqlite.rb +2 -3
  42. data/lib/sequel/adapters/swift/mysql.rb +3 -2
  43. data/lib/sequel/adapters/swift/sqlite.rb +2 -2
  44. data/lib/sequel/adapters/tinytds.rb +14 -8
  45. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +7 -4
  46. data/lib/sequel/database/misc.rb +6 -2
  47. data/lib/sequel/dataset/graph.rb +33 -7
  48. data/lib/sequel/dataset/prepared_statements.rb +19 -5
  49. data/lib/sequel/dataset/sql.rb +611 -201
  50. data/lib/sequel/model/associations.rb +12 -5
  51. data/lib/sequel/model/base.rb +20 -5
  52. data/lib/sequel/plugins/sharding.rb +9 -29
  53. data/lib/sequel/sql.rb +2 -1
  54. data/lib/sequel/timezones.rb +14 -4
  55. data/lib/sequel/version.rb +1 -1
  56. data/spec/adapters/mysql_spec.rb +10 -0
  57. data/spec/adapters/oracle_spec.rb +1 -1
  58. data/spec/core/core_sql_spec.rb +3 -1
  59. data/spec/core/database_spec.rb +42 -0
  60. data/spec/core/dataset_spec.rb +10 -3
  61. data/spec/core/mock_adapter_spec.rb +4 -0
  62. data/spec/core/object_graph_spec.rb +38 -0
  63. data/spec/extensions/association_autoreloading_spec.rb +1 -10
  64. data/spec/extensions/association_dependencies_spec.rb +2 -12
  65. data/spec/extensions/association_pks_spec.rb +35 -39
  66. data/spec/extensions/caching_spec.rb +23 -50
  67. data/spec/extensions/class_table_inheritance_spec.rb +30 -82
  68. data/spec/extensions/composition_spec.rb +18 -13
  69. data/spec/extensions/hook_class_methods_spec.rb +65 -91
  70. data/spec/extensions/identity_map_spec.rb +33 -103
  71. data/spec/extensions/instance_filters_spec.rb +10 -21
  72. data/spec/extensions/instance_hooks_spec.rb +6 -24
  73. data/spec/extensions/json_serializer_spec.rb +4 -5
  74. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  75. data/spec/extensions/list_spec.rb +17 -39
  76. data/spec/extensions/many_through_many_spec.rb +135 -277
  77. data/spec/extensions/migration_spec.rb +18 -15
  78. data/spec/extensions/named_timezones_spec.rb +1 -1
  79. data/spec/extensions/nested_attributes_spec.rb +97 -92
  80. data/spec/extensions/optimistic_locking_spec.rb +9 -20
  81. data/spec/extensions/prepared_statements_associations_spec.rb +22 -37
  82. data/spec/extensions/prepared_statements_safe_spec.rb +9 -27
  83. data/spec/extensions/prepared_statements_spec.rb +11 -30
  84. data/spec/extensions/prepared_statements_with_pk_spec.rb +6 -13
  85. data/spec/extensions/pretty_table_spec.rb +1 -6
  86. data/spec/extensions/rcte_tree_spec.rb +41 -43
  87. data/spec/extensions/schema_dumper_spec.rb +3 -6
  88. data/spec/extensions/serialization_spec.rb +20 -32
  89. data/spec/extensions/sharding_spec.rb +66 -140
  90. data/spec/extensions/single_table_inheritance_spec.rb +14 -36
  91. data/spec/extensions/spec_helper.rb +10 -64
  92. data/spec/extensions/sql_expr_spec.rb +20 -60
  93. data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
  94. data/spec/extensions/timestamps_spec.rb +6 -6
  95. data/spec/extensions/to_dot_spec.rb +1 -2
  96. data/spec/extensions/touch_spec.rb +13 -14
  97. data/spec/extensions/tree_spec.rb +11 -26
  98. data/spec/extensions/update_primary_key_spec.rb +30 -24
  99. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  100. data/spec/extensions/validation_helpers_spec.rb +16 -35
  101. data/spec/integration/dataset_test.rb +16 -4
  102. data/spec/integration/prepared_statement_test.rb +4 -2
  103. data/spec/model/eager_loading_spec.rb +16 -0
  104. data/spec/model/model_spec.rb +15 -1
  105. data/spec/model/record_spec.rb +60 -0
  106. 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.quote_identifiers = false
10
- @c.dataset.meta_def(:h){h}
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 delete_sql
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 = MODEL_DB.clone
6
- mod = Module.new do
7
- def fetch_rows(sql)
8
- db << (is_a?(Sequel::Dataset::PreparedStatementMethods) ? :prepared : :regular)
9
- db << sql
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.reset
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 == [:prepared, "SELECT * FROM albums WHERE (albums.artist_id = 1)"]
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 == [:prepared, "SELECT * FROM artists WHERE (artists.id = 2) LIMIT 1"]
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 == [:prepared, "SELECT tags.* FROM tags INNER JOIN albums_tags ON ((albums_tags.tag_id = tags.id) AND (albums_tags.album_id = 1))"]
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 == [:prepared, "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))"]
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 == [:prepared, "SELECT * FROM albums WHERE ((albums.artist_id = 1) AND (albums.artist_id2 = 2))"]
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 == [:prepared, "SELECT * FROM artists WHERE ((artists.id = 2) AND (artists.id2 = 3)) LIMIT 1"]
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 == [:prepared, "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))"]
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 == [:prepared, "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))"]
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 == [:regular, "SELECT * FROM albums WHERE (albums.artist_id = 1)"]
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 == [:regular, "SELECT * FROM albums WHERE (albums.artist_id = 1)"]
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 == [:regular, "SELECT * FROM albums WHERE (albums.artist_id = 1)"]
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 == [:regular, "SELECT * FROM albums WHERE (albums.artist_id = 1)"]
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 == [:regular, "SELECT * FROM albums WHERE ((albums.artist_id = 1) AND (a = 1))"]
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 == [:regular, "SELECT * FROM albums WHERE (artist_id = 1)"]
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 == [:regular, "SELECT * FROM albums WHERE ((albums.artist_id = 1) AND (a = 1))"]
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
- @c = Class.new(Sequel::Model(:people))
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
- @c.db.execute 'foo'
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[1].should =~ /INSERT INTO people \((i|name), (i|name)\) VALUES \(NULL, NULL\)/
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[1].should =~ /INSERT INTO people \((i|name), (i|name)\) VALUES \((NULL|'foo'), (NULL|'foo')\)/
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[1].should =~ /INSERT INTO people \((i|name), (i|name)\) VALUES \((2|'foo'), (2|'foo')\)/
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[1].should =~ /INSERT INTO people \((i|name), (i|name)\) VALUES \((2|'foo'), (2|'foo')\)/
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[1].should == "INSERT INTO people (name) VALUES ('foo')"
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[1].should =~ /UPDATE people SET (name = 'foo'|i = 3), (name = 'foo'|i = 3) WHERE \(id = 1\)/
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
- @c = Class.new(Sequel::Model(:people))
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.db.execute 'foo'
29
- @sqls = @c.db.sqls
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 == [:read_only, "SELECT * FROM people WHERE (id = 1) LIMIT 1"]
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 == [:default, "DELETE FROM people WHERE (id = 1)"]
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 == [:default, "UPDATE people SET name = 'bar' WHERE (id = 1)"]
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 == [:default, "INSERT INTO people (name) VALUES ('foo')", :default, "SELECT * FROM people WHERE (id = 1) LIMIT 1"]
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
- return {:id=>1, :name=>'foo', :i => 2}
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 == [:default, "INSERT INTO people (name) VALUES ('foo') RETURNING *"]
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 == [:read_only, "SELECT * FROM people WHERE (id = 1) LIMIT 1"]
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
- @c = Class.new(Sequel::Model(:people))
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
- @c.db.execute 'foo'
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 == [:read_only, "SELECT * FROM people WHERE ((name = 'foo') AND (people.id = 1)) LIMIT 1"]
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 == [:read_only, "SELECT * FROM people WHERE (((name = 'foo') OR (name = 'bar')) AND (people.id = 1)) LIMIT 1"]
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 == [:read_only, "SELECT * FROM people WHERE ((id > 2) AND (people.id = 1)) LIMIT 1"]
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::Dataset.new(nil).from(:items)
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.row_sets = [[{:id=>1, :name=>'A', :parent_id=>3}, {:id=>4, :name=>'B', :parent_id=>nil}, {:id=>3, :name=>'?', :parent_id=>4}]]
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.row_sets = [[{:i=>4, :name=>'A', :pi=>5}, {:i=>6, :name=>'B', :pi=>nil}, {:i=>5, :name=>'?', :pi=>6}]]
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.row_sets = [[{: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}]]
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.row_sets = [[{:i=>7, :name=>'??', :pi=>5}, {:i=>5, :name=>'A', :pi=>3}, {:i=>6, :name=>'B', :pi=>3}, {:i=>8, :name=>'?', :pi=>7}]]
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.row_sets = [[{: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'}],
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.first.should == "SELECT * FROM nodes"
104
- MODEL_DB.new_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/
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.new_sqls.should == []
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.row_sets = [[{:i=>2, :pi=>1, :name=>'AA'}, {:i=>6, :pi=>2, :name=>'C'}, {:i=>7, :pi=>1, :name=>'D'}, {:i=>9, :pi=>nil, :name=>'E'}],
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.first.should == "SELECT * FROM nodes"
125
- MODEL_DB.new_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/
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.row_sets = [[{: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'}],
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.first.should == "SELECT * FROM nodes"
146
- MODEL_DB.new_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\)/
147
- MODEL_DB.new_sqls.should == []
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.row_sets = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}],
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.first.should == "SELECT * FROM nodes"
158
- MODEL_DB.new_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/
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.new_sqls.should == []
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.row_sets = [[{:i=>2, :pi=>1, :name=>'AA'}, {:i=>6, :pi=>2, :name=>'C'}, {:i=>7, :pi=>1, :name=>'D'}],
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.first.should == "SELECT * FROM nodes"
177
- MODEL_DB.new_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/
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.new_sqls.should == []
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.row_sets = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}],
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.first.should == "SELECT * FROM nodes"
196
- MODEL_DB.new_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/
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.new_sqls.should == []
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.row_sets = [[{:i=>2, :pi=>1, :name=>'AA'}, {:i=>6, :pi=>2, :name=>'C'}, {:i=>7, :pi=>1, :name=>'D'}],
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.first.should == "SELECT * FROM nodes"
215
- MODEL_DB.new_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/
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.new_sqls.should == []
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.row_sets = [[{:id=>2, :parent_id=>1, :name=>'AA'}, {:id=>6, :parent_id=>2, :name=>'C'}, {:id=>7, :parent_id=>1, :name=>'D'}],
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.first.should == "SELECT * FROM nodes"
234
- MODEL_DB.new_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\)/
235
- MODEL_DB.new_sqls.should == []
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