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.
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