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,17 +6,9 @@ describe "AssociationDependencies plugin" do
6
6
  @c = Class.new(Sequel::Model)
7
7
  @c.plugin :association_dependencies
8
8
  @Artist = Class.new(@c).set_dataset(:artists)
9
- ds1 = @Artist.dataset
10
- def ds1.fetch_rows(s)
11
- (MODEL_DB.sqls ||= []) << s
12
- yield({:id=>2, :name=>'Ar'})
13
- end
9
+ @Artist.dataset._fetch = {:id=>2, :name=>'Ar'}
14
10
  @Album = Class.new(@c).set_dataset(:albums)
15
- ds1 = @Album.dataset
16
- def ds1.fetch_rows(s)
17
- (MODEL_DB.sqls ||= []) << s
18
- yield({:id=>1, :name=>'Al', :artist_id=>2})
19
- end
11
+ @Album.dataset._fetch = {:id=>1, :name=>'Al', :artist_id=>2}
20
12
  @Artist.columns :id, :name
21
13
  @Album.columns :id, :name, :artist_id
22
14
  @Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
@@ -113,11 +105,9 @@ describe "AssociationDependencies plugin" do
113
105
  c.add_association_dependencies :artist=>:destroy
114
106
  c.load(:id=>1, :name=>'Al', :artist_id=>2).destroy
115
107
  MODEL_DB.sqls.should == ['DELETE FROM albums WHERE (id = 1)', 'SELECT * FROM artists WHERE (artists.id = 2) LIMIT 1', 'DELETE FROM artists WHERE (id = 2)']
116
- MODEL_DB.reset
117
108
 
118
109
  @Album.load(:id=>1, :name=>'Al', :artist_id=>2).destroy
119
110
  MODEL_DB.sqls.should == ['DELETE FROM albums WHERE (id = 1)']
120
- MODEL_DB.reset
121
111
 
122
112
  @Album.add_association_dependencies :artist=>:destroy
123
113
  c2 = Class.new(@Album)
@@ -2,31 +2,18 @@ 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
- case sql
9
- when "SELECT id FROM albums WHERE (albums.artist_id = 1)"
10
- yield({:id=>1})
11
- yield({:id=>2})
12
- yield({:id=>3})
13
- when /SELECT tag_id FROM albums_tags WHERE \(album_id = (\d)\)/
14
- yield({:tag_id=>1}) if $1 == '1'
15
- yield({:tag_id=>2}) if $1 != '3'
16
- yield({:tag_id=>3}) if $1 == '2'
17
- end
5
+ @db = Sequel.mock(:fetch=>proc do |sql|
6
+ case sql
7
+ when "SELECT id FROM albums WHERE (albums.artist_id = 1)"
8
+ [{:id=>1}, {:id=>2}, {:id=>3}]
9
+ when /SELECT tag_id FROM albums_tags WHERE \(album_id = (\d)\)/
10
+ a = []
11
+ a << {:tag_id=>1} if $1 == '1'
12
+ a << {:tag_id=>2} if $1 != '3'
13
+ a << {:tag_id=>3} if $1 == '2'
14
+ a
18
15
  end
19
- end
20
- @db.meta_def(:dataset) do |*opts|
21
- ds = super(*opts)
22
- ds.extend mod
23
- ds
24
- end
25
- def @db.transaction(opts)
26
- execute('BEGIN')
27
- yield
28
- execute('COMMIT')
29
- end
16
+ end)
30
17
  @Artist = Class.new(Sequel::Model(@db[:artists]))
31
18
  @Artist.columns :id
32
19
  @Album= Class.new(Sequel::Model(@db[:albums]))
@@ -37,7 +24,7 @@ describe "Sequel::Plugins::AssociationPks" do
37
24
  @Album.plugin :association_pks
38
25
  @Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
39
26
  @Album.many_to_many :tags, :class=>@Tag, :join_table=>:albums_tags, :left_key=>:album_id
40
- @db.reset
27
+ @db.sqls
41
28
  end
42
29
 
43
30
  specify "should return correct associated pks for one_to_many associations" do
@@ -66,8 +53,11 @@ describe "Sequel::Plugins::AssociationPks" do
66
53
 
67
54
  specify "should set associated pks correctly for a many_to_many association" do
68
55
  @Album.load(:id=>2).tag_pks = [1, 3]
69
- @db.sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN (1, 3)))"
70
- @db.sqls[1].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, 1|1, 2)\)/
56
+ sqls = @db.sqls
57
+ sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN (1, 3)))"
58
+ sqls[1].should == 'SELECT tag_id FROM albums_tags WHERE (album_id = 2)'
59
+ sqls[2].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, 1|1, 2)\)/
60
+ sqls.length.should == 3
71
61
  end
72
62
 
73
63
  specify "should use transactions if the object is configured to use transactions" do
@@ -78,15 +68,17 @@ describe "Sequel::Plugins::AssociationPks" do
78
68
  "UPDATE albums SET artist_id = 1 WHERE (id IN (1, 2))",
79
69
  "UPDATE albums SET artist_id = NULL WHERE ((albums.artist_id = 1) AND (id NOT IN (1, 2)))",
80
70
  "COMMIT"]
81
- @db.reset
82
71
 
83
72
  album = @Album.load(:id=>2)
84
73
  album.use_transactions = true
85
74
  album.tag_pks = [1, 3]
86
- @db.sqls[0].should == "BEGIN"
87
- @db.sqls[1].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN (1, 3)))"
88
- @db.sqls[2].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, 1|1, 2)\)/
89
- @db.sqls[3].should == "COMMIT"
75
+ sqls = @db.sqls
76
+ sqls[0].should == "BEGIN"
77
+ sqls[1].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN (1, 3)))"
78
+ sqls[2].should == 'SELECT tag_id FROM albums_tags WHERE (album_id = 2)'
79
+ sqls[3].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, 1|1, 2)\)/
80
+ sqls[4].should == "COMMIT"
81
+ sqls.length.should == 5
90
82
  end
91
83
 
92
84
  specify "should automatically convert keys to numbers if the primary key is an integer for one_to_many associations" do
@@ -106,18 +98,22 @@ describe "Sequel::Plugins::AssociationPks" do
106
98
  specify "should automatically convert keys to numbers if the primary key is an integer for one_to_many associations" do
107
99
  @Tag.db_schema[:id][:type] = :integer
108
100
  @Album.load(:id=>2).tag_pks = %w'1 3'
109
- @db.sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN (1, 3)))"
110
- @db.sqls[1].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, 1|1, 2)\)/
111
- @db.sqls.length.should == 2
101
+ sqls = @db.sqls
102
+ sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN (1, 3)))"
103
+ sqls[1].should == 'SELECT tag_id FROM albums_tags WHERE (album_id = 2)'
104
+ sqls[2].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, 1|1, 2)\)/
105
+ sqls.length.should == 3
112
106
  end
113
107
 
114
108
  specify "should not automatically convert keys to numbers if the primary key is an integer for many_to_many associations" do
115
109
  @Tag.db_schema[:id][:type] = :string
116
110
  @Album.load(:id=>2).tag_pks = %w'1 3'
117
- @db.sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN ('1', '3')))"
118
- @db.sqls[1].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, '1'|'1', 2)\)/
119
- @db.sqls[2].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, '3'|'3', 2)\)/
120
- @db.sqls.length.should == 3
111
+ sqls = @db.sqls
112
+ sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN ('1', '3')))"
113
+ sqls[1].should == 'SELECT tag_id FROM albums_tags WHERE (album_id = 2)'
114
+ sqls[2].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, '1'|'1', 2)\)/
115
+ sqls[3].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, '3'|'3', 2)\)/
116
+ sqls.length.should == 4
121
117
  end
122
118
 
123
119
  end
@@ -2,8 +2,6 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe Sequel::Model, "caching" do
4
4
  before do
5
- MODEL_DB.reset
6
-
7
5
  @cache_class = Class.new(Hash) do
8
6
  attr_accessor :ttl
9
7
  def set(k, v, ttl); self[k] = v; @ttl = ttl; end
@@ -44,31 +42,14 @@ describe Sequel::Model, "caching" do
44
42
  columns :name, :id
45
43
  end
46
44
 
47
-
48
- $cache_dataset_row = {:name => 'sharon', :id => 1}
49
45
  @dataset = @c.dataset = @c3.dataset = @c4.dataset
50
- $sqls = []
51
- @dataset.extend(Module.new {
52
- def fetch_rows(sql)
53
- $sqls << sql
54
- yield $cache_dataset_row
55
- end
56
-
57
- def update(values)
58
- $sqls << update_sql(values)
59
- $cache_dataset_row.merge!(values)
60
- 1
61
- end
62
-
63
- def delete
64
- $sqls << delete_sql
65
- 1
66
- end
67
- })
46
+ @dataset._fetch = {:name => 'sharon', :id => 1}
47
+ @dataset.numrows = 1
68
48
 
69
49
  @c2 = Class.new(@c) do
70
50
  def self.name; 'SubItem' end
71
51
  end
52
+ @c.db.reset
72
53
  end
73
54
 
74
55
  it "should set the model's cache store" do
@@ -154,27 +135,26 @@ describe Sequel::Model, "caching" do
154
135
  end
155
136
 
156
137
  it "should set the cache when reading from the database" do
157
- $sqls.should == []
138
+ @c.db.sqls.should == []
158
139
  @cache.should be_empty
159
140
 
160
141
  m = @c[1]
161
- $sqls.should == ['SELECT * FROM items WHERE (id = 1) LIMIT 1']
162
- m.values.should == $cache_dataset_row
142
+ @c.db.sqls.should == ['SELECT * FROM items WHERE id = 1']
143
+ m.values.should == {:name=>"sharon", :id=>1}
163
144
  @cache[m.cache_key].should == m
164
145
  m2 = @c[1]
165
- $sqls.should == ['SELECT * FROM items WHERE (id = 1) LIMIT 1']
146
+ @c.db.sqls.should == []
166
147
  m2.should == m
167
- m2.values.should == $cache_dataset_row
148
+ m2.values.should == {:name=>"sharon", :id=>1}
168
149
 
169
- $sqls.clear
170
150
  m = @c2[1]
171
- $sqls.should == ['SELECT * FROM items WHERE (id = 1) LIMIT 1']
172
- m.values.should == $cache_dataset_row
151
+ @c.db.sqls.should == ['SELECT * FROM items WHERE id = 1']
152
+ m.values.should == {:name=>"sharon", :id=>1}
173
153
  @cache[m.cache_key].should == m
174
154
  m2 = @c2[1]
175
- $sqls.should == ['SELECT * FROM items WHERE (id = 1) LIMIT 1']
155
+ @c.db.sqls.should == []
176
156
  m2.should == m
177
- m2.values.should == $cache_dataset_row
157
+ m2.values.should == {:name=>"sharon", :id=>1}
178
158
  end
179
159
 
180
160
  it "should delete the cache when writing to the database" do
@@ -183,14 +163,14 @@ describe Sequel::Model, "caching" do
183
163
  m.name = 'hey'
184
164
  m.save
185
165
  @cache.has_key?(m.cache_key).should be_false
186
- $sqls.last.should == "UPDATE items SET name = 'hey' WHERE (id = 1)"
166
+ @c.db.sqls.should == ["SELECT * FROM items WHERE id = 1", "UPDATE items SET name = 'hey' WHERE (id = 1)"]
187
167
 
188
168
  m = @c2[1]
189
169
  @cache[m.cache_key].should == m
190
170
  m.name = 'hey'
191
171
  m.save
192
172
  @cache.has_key?(m.cache_key).should be_false
193
- $sqls.last.should == "UPDATE items SET name = 'hey' WHERE (id = 1)"
173
+ @c.db.sqls.should == ["SELECT * FROM items WHERE id = 1", "UPDATE items SET name = 'hey' WHERE (id = 1)"]
194
174
  end
195
175
 
196
176
  it "should delete the cache when deleting the record" do
@@ -198,40 +178,33 @@ describe Sequel::Model, "caching" do
198
178
  @cache[m.cache_key].should == m
199
179
  m.delete
200
180
  @cache.has_key?(m.cache_key).should be_false
201
- $sqls.last.should == "DELETE FROM items WHERE (id = 1)"
181
+ @c.db.sqls.should == ["SELECT * FROM items WHERE id = 1", "DELETE FROM items WHERE (id = 1)"]
202
182
 
203
183
  m = @c2[1]
204
184
  @cache[m.cache_key].should == m
205
185
  m.delete
206
186
  @cache.has_key?(m.cache_key).should be_false
207
- $sqls.last.should == "DELETE FROM items WHERE (id = 1)"
187
+ @c.db.sqls.should == ["SELECT * FROM items WHERE id = 1", "DELETE FROM items WHERE (id = 1)"]
208
188
  end
209
189
 
210
190
  it "should support #[] as a shortcut to #find with hash" do
211
191
  m = @c[:id => 3]
212
192
  @cache[m.cache_key].should be_nil
213
- $sqls.last.should == "SELECT * FROM items WHERE (id = 3) LIMIT 1"
193
+ @c.db.sqls.should == ["SELECT * FROM items WHERE (id = 3) LIMIT 1"]
214
194
  m = @c[1]
215
195
  @cache[m.cache_key].should == m
216
- $sqls.should == ["SELECT * FROM items WHERE (id = 3) LIMIT 1", \
217
- "SELECT * FROM items WHERE (id = 1) LIMIT 1"]
196
+ @c.db.sqls.should == ["SELECT * FROM items WHERE id = 1"]
218
197
  @c[:id => 4]
219
- $sqls.should == ["SELECT * FROM items WHERE (id = 3) LIMIT 1", \
220
- "SELECT * FROM items WHERE (id = 1) LIMIT 1", \
221
- "SELECT * FROM items WHERE (id = 4) LIMIT 1"]
198
+ @c.db.sqls.should == ["SELECT * FROM items WHERE (id = 4) LIMIT 1"]
222
199
 
223
- $sqls.clear
224
200
  m = @c2[:id => 3]
225
201
  @cache[m.cache_key].should be_nil
226
- $sqls.last.should == "SELECT * FROM items WHERE (id = 3) LIMIT 1"
202
+ @c.db.sqls.should == ["SELECT * FROM items WHERE (id = 3) LIMIT 1"]
227
203
  m = @c2[1]
228
204
  @cache[m.cache_key].should == m
229
- $sqls.should == ["SELECT * FROM items WHERE (id = 3) LIMIT 1", \
230
- "SELECT * FROM items WHERE (id = 1) LIMIT 1"]
205
+ @c.db.sqls.should == ["SELECT * FROM items WHERE id = 1"]
231
206
  @c2[:id => 4]
232
- $sqls.should == ["SELECT * FROM items WHERE (id = 3) LIMIT 1", \
233
- "SELECT * FROM items WHERE (id = 1) LIMIT 1", \
234
- "SELECT * FROM items WHERE (id = 4) LIMIT 1"]
207
+ @c.db.sqls.should == ["SELECT * FROM items WHERE (id = 4) LIMIT 1"]
235
208
  end
236
209
 
237
210
  it "should support ignore_exception option" do
@@ -245,6 +218,6 @@ describe Sequel::Model, "caching" do
245
218
  end
246
219
 
247
220
  it "should rescue an exception if cache_store is memcached and ignore_exception is enabled" do
248
- @c4[1].values.should == $cache_dataset_row
221
+ @c4[1].values.should == {:name => 'sharon', :id => 1}
249
222
  end
250
223
  end
@@ -2,17 +2,16 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe "class_table_inheritance plugin" do
4
4
  before do
5
- @db = db = MODEL_DB.clone
6
- def db.schema(table, opts={})
5
+ @db = Sequel.mock(:autoid=>proc{|sql| 1})
6
+ def @db.schema(table, opts={})
7
7
  {:employees=>[[:id, {:primary_key=>true, :type=>:integer}], [:name, {:type=>:string}], [:kind, {:type=>:string}]],
8
8
  :managers=>[[:id, {:type=>:integer}], [:num_staff, {:type=>:integer}]],
9
9
  :executives=>[[:id, {:type=>:integer}], [:num_managers, {:type=>:integer}]],
10
10
  :staff=>[[:id, {:type=>:integer}], [:manager_id, {:type=>:integer}]],
11
11
  }[table.is_a?(Sequel::Dataset) ? table.first_source_table : table]
12
12
  end
13
- def db.dataset(*args)
14
- ds = super(*args)
15
- def ds.columns
13
+ @db.extend_datasets do
14
+ def columns
16
15
  {[:employees]=>[:id, :name, :kind],
17
16
  [:managers]=>[:id, :num_staff],
18
17
  [:executives]=>[:id, :num_managers],
@@ -22,13 +21,8 @@ describe "class_table_inheritance plugin" do
22
21
  [:employees, :staff]=>[:id, :name, :kind, :manager_id],
23
22
  }[opts[:from] + (opts[:join] || []).map{|x| x.table}]
24
23
  end
25
- def ds.insert(*args)
26
- db << insert_sql(*args)
27
- 1
28
- end
29
- ds
30
24
  end
31
- class ::Employee < Sequel::Model(db)
25
+ class ::Employee < Sequel::Model(@db)
32
26
  def _refresh(x); @values[:id] = 1 end
33
27
  def self.columns
34
28
  dataset.columns
@@ -44,7 +38,7 @@ describe "class_table_inheritance plugin" do
44
38
  many_to_one :manager
45
39
  end
46
40
  @ds = Employee.dataset
47
- @db.reset
41
+ @db.sqls
48
42
  end
49
43
  after do
50
44
  Object.send(:remove_const, :Executive)
@@ -53,8 +47,8 @@ describe "class_table_inheritance plugin" do
53
47
  Object.send(:remove_const, :Employee)
54
48
  end
55
49
 
56
- specify "should have simple_table = nil" do
57
- Employee.simple_table.should == nil
50
+ specify "should have simple_table = nil for subclasses" do
51
+ Employee.simple_table.should == "employees"
58
52
  Manager.simple_table.should == nil
59
53
  Executive.simple_table.should == nil
60
54
  Staff.simple_table.should == nil
@@ -68,33 +62,18 @@ describe "class_table_inheritance plugin" do
68
62
  end
69
63
 
70
64
  it "should return rows with the correct class based on the polymorphic_key value" do
71
- def @ds.fetch_rows(sql)
72
- yield({:kind=>'Employee'})
73
- yield({:kind=>'Manager'})
74
- yield({:kind=>'Executive'})
75
- yield({:kind=>'Staff'})
76
- end
65
+ @ds._fetch = [{:kind=>'Employee'}, {:kind=>'Manager'}, {:kind=>'Executive'}, {:kind=>'Staff'}]
77
66
  Employee.all.collect{|x| x.class}.should == [Employee, Manager, Executive, Staff]
78
67
  end
79
68
 
80
69
  it "should return rows with the correct class based on the polymorphic_key value for subclasses" do
81
- ds = Manager.dataset
82
- def ds.fetch_rows(sql)
83
- yield({:kind=>'Manager'})
84
- yield({:kind=>'Executive'})
85
- end
70
+ Manager.dataset._fetch = [{:kind=>'Manager'}, {:kind=>'Executive'}]
86
71
  Manager.all.collect{|x| x.class}.should == [Manager, Executive]
87
72
  end
88
73
 
89
74
  it "should return rows with the current class if cti_key is nil" do
90
75
  Employee.plugin(:class_table_inheritance)
91
- ds = Employee.dataset
92
- def ds.fetch_rows(sql)
93
- yield({:kind=>'Employee'})
94
- yield({:kind=>'Manager'})
95
- yield({:kind=>'Executive'})
96
- yield({:kind=>'Staff'})
97
- end
76
+ @ds._fetch = [{:kind=>'Employee'}, {:kind=>'Manager'}, {:kind=>'Executive'}, {:kind=>'Staff'}]
98
77
  Employee.all.collect{|x| x.class}.should == [Employee, Employee, Employee, Employee]
99
78
  end
100
79
 
@@ -102,35 +81,19 @@ describe "class_table_inheritance plugin" do
102
81
  Employee.plugin(:class_table_inheritance)
103
82
  Object.send(:remove_const, :Executive)
104
83
  Object.send(:remove_const, :Manager)
105
- class ::Manager < Employee
106
- end
107
- class ::Executive < Manager
108
- end
109
- ds = Manager.dataset
110
- def ds.fetch_rows(sql)
111
- yield({:kind=>'Manager'})
112
- yield({:kind=>'Executive'})
113
- end
84
+ class ::Manager < Employee; end
85
+ class ::Executive < Manager; end
86
+ Manager.dataset._fetch = [{:kind=>'Manager'}, {:kind=>'Executive'}]
114
87
  Manager.all.collect{|x| x.class}.should == [Manager, Manager]
115
88
  end
116
89
 
117
90
  it "should fallback to the main class if the given class does not exist" do
118
- def @ds.fetch_rows(sql)
119
- yield({:kind=>'Employee'})
120
- yield({:kind=>'Manager'})
121
- yield({:kind=>'Blah'})
122
- yield({:kind=>'Staff'})
123
- end
91
+ @ds._fetch = [{:kind=>'Employee'}, {:kind=>'Manager'}, {:kind=>'Blah'}, {:kind=>'Staff'}]
124
92
  Employee.all.collect{|x| x.class}.should == [Employee, Manager, Employee, Staff]
125
93
  end
126
94
 
127
95
  it "should fallback to the main class if the given class does not exist in subclasses" do
128
- ds = Manager.dataset
129
- def ds.fetch_rows(sql)
130
- yield({:kind=>'Manager'})
131
- yield({:kind=>'Executive'})
132
- yield({:kind=>'Blah'})
133
- end
96
+ Manager.dataset._fetch = [{:kind=>'Manager'}, {:kind=>'Executive'}, {:kind=>'Blah'}]
134
97
  Manager.all.collect{|x| x.class}.should == [Manager, Executive, Manager]
135
98
  end
136
99
 
@@ -167,19 +130,10 @@ describe "class_table_inheritance plugin" do
167
130
  end
168
131
 
169
132
  it "should lazily load attributes for columns in subclass tables" do
170
- ds = Manager.dataset
171
- def ds.fetch_rows(sql)
172
- @db << sql
173
- yield({:id=>1, :name=>'J', :kind=>'Executive', :num_staff=>2})
174
- end
133
+ Manager.dataset._fetch = {:id=>1, :name=>'J', :kind=>'Executive', :num_staff=>2}
175
134
  m = Manager[1]
176
135
  @db.sqls.should == ['SELECT * FROM employees INNER JOIN managers USING (id) WHERE (id = 1) LIMIT 1']
177
- @db.reset
178
- ds = Executive.dataset
179
- def ds.fetch_rows(sql)
180
- @db << sql
181
- yield({:num_managers=>3})
182
- end
136
+ Executive.dataset._fetch = {:num_managers=>3}
183
137
  m.num_managers.should == 3
184
138
  @db.sqls.should == ['SELECT num_managers FROM employees INNER JOIN managers USING (id) INNER JOIN executives USING (id) WHERE (id = 1) LIMIT 1']
185
139
  m.values.should == {:id=>1, :name=>'J', :kind=>'Executive', :num_staff=>2, :num_managers=>3}
@@ -210,20 +164,22 @@ describe "class_table_inheritance plugin" do
210
164
 
211
165
  it "should insert the correct rows into all tables when inserting" do
212
166
  Executive.create(:num_managers=>3, :num_staff=>2, :name=>'E')
213
- @db.sqls.length.should == 3
214
- @db.sqls[0].should =~ /INSERT INTO employees \((name|kind), (name|kind)\) VALUES \('(E|Executive)', '(E|Executive)'\)/
215
- @db.sqls[1].should =~ /INSERT INTO managers \((num_staff|id), (num_staff|id)\) VALUES \([12], [12]\)/
216
- @db.sqls[2].should =~ /INSERT INTO executives \((num_managers|id), (num_managers|id)\) VALUES \([13], [13]\)/
167
+ sqls = @db.sqls
168
+ sqls.length.should == 3
169
+ sqls[0].should =~ /INSERT INTO employees \((name|kind), (name|kind)\) VALUES \('(E|Executive)', '(E|Executive)'\)/
170
+ sqls[1].should =~ /INSERT INTO managers \((num_staff|id), (num_staff|id)\) VALUES \([12], [12]\)/
171
+ sqls[2].should =~ /INSERT INTO executives \((num_managers|id), (num_managers|id)\) VALUES \([13], [13]\)/
217
172
  end
218
173
 
219
174
  it "should insert the correct rows into all tables with a given primary key" do
220
175
  e = Executive.new(:num_managers=>3, :num_staff=>2, :name=>'E')
221
176
  e.id = 2
222
177
  e.save
223
- @db.sqls.length.should == 3
224
- @db.sqls[0].should =~ /INSERT INTO employees \((name|kind|id), (name|kind|id), (name|kind|id)\) VALUES \(('E'|'Executive'|2), ('E'|'Executive'|2), ('E'|'Executive'|2)\)/
225
- @db.sqls[1].should =~ /INSERT INTO managers \((num_staff|id), (num_staff|id)\) VALUES \(2, 2\)/
226
- @db.sqls[2].should =~ /INSERT INTO executives \((num_managers|id), (num_managers|id)\) VALUES \([23], [23]\)/
178
+ sqls = @db.sqls
179
+ sqls.length.should == 3
180
+ sqls[0].should =~ /INSERT INTO employees \((name|kind|id), (name|kind|id), (name|kind|id)\) VALUES \(('E'|'Executive'|2), ('E'|'Executive'|2), ('E'|'Executive'|2)\)/
181
+ sqls[1].should =~ /INSERT INTO managers \((num_staff|id), (num_staff|id)\) VALUES \(2, 2\)/
182
+ sqls[2].should =~ /INSERT INTO executives \((num_managers|id), (num_managers|id)\) VALUES \([23], [23]\)/
227
183
  end
228
184
 
229
185
  it "should update the correct rows in all tables when updating" do
@@ -232,21 +188,13 @@ describe "class_table_inheritance plugin" do
232
188
  end
233
189
 
234
190
  it "should handle many_to_one relationships correctly" do
235
- ds = Manager.dataset
236
- def ds.fetch_rows(sql)
237
- @db << sql
238
- yield({:id=>3, :name=>'E', :kind=>'Executive', :num_managers=>3})
239
- end
191
+ Manager.dataset._fetch = {:id=>3, :name=>'E', :kind=>'Executive', :num_managers=>3}
240
192
  Staff.load(:manager_id=>3).manager.should == Executive.load(:id=>3, :name=>'E', :kind=>'Executive', :num_managers=>3)
241
193
  @db.sqls.should == ['SELECT * FROM employees INNER JOIN managers USING (id) WHERE (managers.id = 3) LIMIT 1']
242
194
  end
243
195
 
244
196
  it "should handle one_to_many relationships correctly" do
245
- ds = Staff.dataset
246
- def ds.fetch_rows(sql)
247
- @db << sql
248
- yield({:id=>1, :name=>'S', :kind=>'Staff', :manager_id=>3})
249
- end
197
+ Staff.dataset._fetch = {:id=>1, :name=>'S', :kind=>'Staff', :manager_id=>3}
250
198
  Executive.load(:id=>3).staff_members.should == [Staff.load(:id=>1, :name=>'S', :kind=>'Staff', :manager_id=>3)]
251
199
  @db.sqls.should == ['SELECT * FROM employees INNER JOIN staff USING (id) WHERE (staff.manager_id = 3)']
252
200
  end