sequel 2.6.0 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/CHANGELOG +64 -0
  2. data/Rakefile +1 -1
  3. data/lib/sequel_core/adapters/jdbc.rb +6 -2
  4. data/lib/sequel_core/adapters/jdbc/oracle.rb +23 -0
  5. data/lib/sequel_core/adapters/oracle.rb +4 -77
  6. data/lib/sequel_core/adapters/postgres.rb +39 -26
  7. data/lib/sequel_core/adapters/shared/mssql.rb +0 -1
  8. data/lib/sequel_core/adapters/shared/mysql.rb +1 -1
  9. data/lib/sequel_core/adapters/shared/oracle.rb +82 -0
  10. data/lib/sequel_core/adapters/shared/postgres.rb +65 -46
  11. data/lib/sequel_core/core_ext.rb +10 -0
  12. data/lib/sequel_core/core_sql.rb +7 -0
  13. data/lib/sequel_core/database.rb +22 -0
  14. data/lib/sequel_core/database/schema.rb +1 -1
  15. data/lib/sequel_core/dataset.rb +29 -11
  16. data/lib/sequel_core/dataset/sql.rb +27 -7
  17. data/lib/sequel_core/migration.rb +20 -2
  18. data/lib/sequel_core/object_graph.rb +24 -10
  19. data/lib/sequel_core/schema/generator.rb +22 -9
  20. data/lib/sequel_core/schema/sql.rb +13 -9
  21. data/lib/sequel_core/sql.rb +27 -2
  22. data/lib/sequel_model/association_reflection.rb +251 -141
  23. data/lib/sequel_model/associations.rb +114 -61
  24. data/lib/sequel_model/base.rb +25 -21
  25. data/lib/sequel_model/eager_loading.rb +17 -40
  26. data/lib/sequel_model/hooks.rb +25 -24
  27. data/lib/sequel_model/record.rb +29 -51
  28. data/lib/sequel_model/schema.rb +1 -1
  29. data/lib/sequel_model/validations.rb +13 -3
  30. data/spec/adapters/postgres_spec.rb +104 -18
  31. data/spec/adapters/spec_helper.rb +4 -1
  32. data/spec/integration/eager_loader_test.rb +5 -4
  33. data/spec/integration/spec_helper.rb +4 -1
  34. data/spec/sequel_core/connection_pool_spec.rb +24 -24
  35. data/spec/sequel_core/core_sql_spec.rb +12 -0
  36. data/spec/sequel_core/dataset_spec.rb +77 -2
  37. data/spec/sequel_core/expression_filters_spec.rb +6 -0
  38. data/spec/sequel_core/object_graph_spec.rb +40 -2
  39. data/spec/sequel_core/schema_spec.rb +13 -0
  40. data/spec/sequel_model/association_reflection_spec.rb +8 -8
  41. data/spec/sequel_model/associations_spec.rb +164 -3
  42. data/spec/sequel_model/caching_spec.rb +2 -1
  43. data/spec/sequel_model/eager_loading_spec.rb +107 -3
  44. data/spec/sequel_model/hooks_spec.rb +38 -22
  45. data/spec/sequel_model/model_spec.rb +11 -35
  46. data/spec/sequel_model/plugins_spec.rb +4 -2
  47. data/spec/sequel_model/record_spec.rb +8 -5
  48. data/spec/sequel_model/validations_spec.rb +25 -0
  49. data/spec/spec_config.rb +4 -3
  50. metadata +21 -19
@@ -4,4 +4,7 @@ unless Object.const_defined?('Sequel')
4
4
  require 'sequel_core'
5
5
  Sequel.quote_identifiers = false
6
6
  end
7
- require File.join(File.dirname(__FILE__), '../spec_config.rb')
7
+ begin
8
+ require File.join(File.dirname(__FILE__), '../spec_config.rb')
9
+ rescue LoadError
10
+ end
@@ -228,7 +228,6 @@ describe "has_many :through has_many and has_one :through belongs_to" do
228
228
  firms.each{|firm| firm.associations[:invoices] = []}
229
229
  Invoice.eager_graph(:client).filter(:client__firm_id=>id_map.keys).all do |inv|
230
230
  id_map[inv.client.firm_id].each do |firm|
231
- inv.client.associations[:firm] = inv.associations[:firm] = firm
232
231
  firm.associations[:invoices] << inv
233
232
  end
234
233
  end
@@ -255,20 +254,22 @@ describe "has_many :through has_many and has_one :through belongs_to" do
255
254
  :after_load=>(proc do |inv, firm|
256
255
  # Delete the cached associations from firm, because it only has the
257
256
  # client with this invoice, instead of all clients of the firm
258
- inv.associations[:client] = firm.associations.delete(:clients).first
257
+ if c = firm.associations.delete(:clients)
258
+ firm.associations[:invoice_client] = c.first
259
+ end
260
+ inv.associations[:client] ||= firm.associations[:invoice_client]
259
261
  end), \
260
262
  :eager_loader=>(proc do |key_hash, invoices, associations|
261
263
  id_map = {}
262
264
  invoices.each do |inv|
263
265
  inv.associations[:firm] = nil
264
- inv.associations[:client] = nil
265
266
  (id_map[inv.client_id] ||= []) << inv
266
267
  end
267
268
  Firm.eager_graph(:clients).filter(:clients__id=>id_map.keys).all do |firm|
268
269
  # Delete the cached associations from firm, because it only has the
269
270
  # clients related the invoices being eagerly loaded, instead of all
270
271
  # clients of the firm.
271
- firm.associations.delete(:clients).each do |client|
272
+ firm.associations[:clients].each do |client|
272
273
  id_map[client.pk].each do |inv|
273
274
  inv.associations[:firm] = firm
274
275
  inv.associations[:client] = client
@@ -3,7 +3,10 @@ unless Object.const_defined?('Sequel')
3
3
  $:.unshift(File.join(File.dirname(__FILE__), "../../lib/"))
4
4
  require 'sequel'
5
5
  end
6
- require File.join(File.dirname(__FILE__), '../spec_config.rb')
6
+ begin
7
+ require File.join(File.dirname(__FILE__), '../spec_config.rb')
8
+ rescue LoadError
9
+ end
7
10
 
8
11
  $sqls = []
9
12
  def clear_sqls
@@ -137,13 +137,13 @@ context "A connection pool with a max size of 1" do
137
137
  specify "should let only one thread access the connection at any time" do
138
138
  cc,c1, c2 = nil
139
139
 
140
- t1 = Thread.new {@pool.hold {|c| cc = c; c1 = c.dup; while c == 'herro';sleep 0.1;end}}
141
- sleep 0.2
140
+ t1 = Thread.new {@pool.hold {|c| cc = c; c1 = c.dup; while c == 'herro';sleep 0.01;end}}
141
+ sleep 0.02
142
142
  cc.should == 'herro'
143
143
  c1.should == 'herro'
144
144
 
145
- t2 = Thread.new {@pool.hold {|c| c2 = c.dup; while c == 'hello';sleep 0.1;end}}
146
- sleep 0.2
145
+ t2 = Thread.new {@pool.hold {|c| c2 = c.dup; while c == 'hello';sleep 0.01;end}}
146
+ sleep 0.02
147
147
 
148
148
  # connection held by t1
149
149
  t1.should be_alive
@@ -157,7 +157,7 @@ context "A connection pool with a max size of 1" do
157
157
  @pool.allocated.should == {t1=>cc}
158
158
 
159
159
  cc.gsub!('rr', 'll')
160
- sleep 0.5
160
+ sleep 0.05
161
161
 
162
162
  # connection held by t2
163
163
  t1.should_not be_alive
@@ -169,7 +169,7 @@ context "A connection pool with a max size of 1" do
169
169
  @pool.allocated.should == {t2=>cc}
170
170
 
171
171
  cc.gsub!('ll', 'rr')
172
- sleep 0.5
172
+ sleep 0.05
173
173
 
174
174
  #connection released
175
175
  t2.should_not be_alive
@@ -215,8 +215,8 @@ context "A connection pool with a max size of 5" do
215
215
  threads = []
216
216
  stop = nil
217
217
 
218
- 5.times {|i| threads << Thread.new {@pool.hold {|c| cc[i] = c; while !stop;sleep 0.1;end}}; sleep 0.1}
219
- sleep 0.2
218
+ 5.times {|i| threads << Thread.new {@pool.hold {|c| cc[i] = c; while !stop;sleep 0.01;end}}; sleep 0.01}
219
+ sleep 0.02
220
220
  threads.each {|t| t.should be_alive}
221
221
  cc.size.should == 5
222
222
  @invoked_count.should == 5
@@ -228,16 +228,16 @@ context "A connection pool with a max size of 5" do
228
228
  @pool.allocated.should == h
229
229
 
230
230
  threads[0].raise "your'e dead"
231
- sleep 0.1
231
+ sleep 0.01
232
232
  threads[3].raise "your'e dead too"
233
233
 
234
- sleep 0.1
234
+ sleep 0.01
235
235
 
236
236
  @pool.available_connections.should == [1, 4]
237
237
  @pool.allocated.should == {threads[1]=>2, threads[2]=>3, threads[4]=>5}
238
238
 
239
239
  stop = true
240
- sleep 0.2
240
+ sleep 0.02
241
241
 
242
242
  @pool.available_connections.size.should == 5
243
243
  @pool.allocated.should be_empty
@@ -248,14 +248,14 @@ context "A connection pool with a max size of 5" do
248
248
  threads = []
249
249
  stop = nil
250
250
 
251
- 5.times {|i| threads << Thread.new {@pool.hold {|c| cc[i] = c; while !stop;sleep 0.1;end}}; sleep 0.1}
252
- sleep 0.2
251
+ 5.times {|i| threads << Thread.new {@pool.hold {|c| cc[i] = c; while !stop;sleep 0.01;end}}; sleep 0.01}
252
+ sleep 0.02
253
253
  threads.each {|t| t.should be_alive}
254
254
  @pool.available_connections.should be_empty
255
255
 
256
256
  3.times {|i| threads << Thread.new {@pool.hold {|c| cc[i + 5] = c}}}
257
257
 
258
- sleep 0.2
258
+ sleep 0.02
259
259
  threads[5].should be_alive
260
260
  threads[6].should be_alive
261
261
  threads[7].should be_alive
@@ -265,7 +265,7 @@ context "A connection pool with a max size of 5" do
265
265
  cc[7].should be_nil
266
266
 
267
267
  stop = true
268
- sleep 0.3
268
+ sleep 0.05
269
269
 
270
270
  threads.each {|t| t.should_not be_alive}
271
271
 
@@ -285,12 +285,12 @@ context "ConnectionPool#disconnect" do
285
285
  specify "should invoke the given block for each available connection" do
286
286
  threads = []
287
287
  stop = nil
288
- 5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.1;end}}; sleep 0.1}
288
+ 5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.01;end}}; sleep 0.01}
289
289
  while @pool.size < 5
290
- sleep 0.2
290
+ sleep 0.02
291
291
  end
292
292
  stop = true
293
- sleep 1
293
+ sleep 0.1
294
294
  threads.each {|t| t.join}
295
295
 
296
296
  @pool.size.should == 5
@@ -304,12 +304,12 @@ context "ConnectionPool#disconnect" do
304
304
  specify "should remove all available connections" do
305
305
  threads = []
306
306
  stop = nil
307
- 5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.1;end}}; sleep 0.1}
307
+ 5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.01;end}}; sleep 0.01}
308
308
  while @pool.size < 5
309
- sleep 0.2
309
+ sleep 0.02
310
310
  end
311
311
  stop = true
312
- sleep 1
312
+ sleep 0.1
313
313
  threads.each {|t| t.join}
314
314
 
315
315
  @pool.size.should == 5
@@ -320,12 +320,12 @@ context "ConnectionPool#disconnect" do
320
320
  specify "should not touch connections in use" do
321
321
  threads = []
322
322
  stop = nil
323
- 5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.1;end}}; sleep 0.1}
323
+ 5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.01;end}}; sleep 0.01}
324
324
  while @pool.size < 5
325
- sleep 0.2
325
+ sleep 0.02
326
326
  end
327
327
  stop = true
328
- sleep 1
328
+ sleep 0.1
329
329
  threads.each {|t| t.join}
330
330
 
331
331
  @pool.size.should == 5
@@ -51,6 +51,18 @@ context "Array#case and Hash#case" do
51
51
  end
52
52
  end
53
53
 
54
+ context "Array#sql_array" do
55
+ setup do
56
+ @d = Sequel::Dataset.new(nil)
57
+ end
58
+
59
+ specify "should treat the array as an SQL array instead of conditions" do
60
+ @d.literal([[:x, 1], [:y, 2]]).should == '((x = 1) AND (y = 2))'
61
+ @d.literal([[:x, 1], [:y, 2]].sql_array).should == '((x, 1), (y, 2))'
62
+ @d.filter([:a, :b]=>[[:x, 1], [:y, 2]].sql_array).sql.should == 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
63
+ end
64
+ end
65
+
54
66
  context "Array#to_sql" do
55
67
  specify "should concatenate multiple lines into a single string" do
56
68
  "SELECT * \r\nFROM items\r\n WHERE a = 1".split.to_sql. \
@@ -725,6 +725,15 @@ context "Dataset#from" do
725
725
  @dataset.from(:a[:i]).select_sql.should ==
726
726
  "SELECT * FROM a(i)"
727
727
  end
728
+
729
+ specify "should accept :schema__table___alias symbol format" do
730
+ @dataset.from(:abc__def).select_sql.should ==
731
+ "SELECT * FROM abc.def"
732
+ @dataset.from(:abc__def___d).select_sql.should ==
733
+ "SELECT * FROM abc.def AS d"
734
+ @dataset.from(:abc___def).select_sql.should ==
735
+ "SELECT * FROM abc AS def"
736
+ end
728
737
  end
729
738
 
730
739
  context "Dataset#select" do
@@ -1111,8 +1120,9 @@ context "Dataset#count" do
1111
1120
  end
1112
1121
 
1113
1122
  def fetch_rows(sql)
1123
+ @columns = [sql =~ /SELECT COUNT/i ? :count : :a]
1114
1124
  @@sql = sql
1115
- yield({1 => 1})
1125
+ yield({@columns.first=>1})
1116
1126
  end
1117
1127
  end
1118
1128
  @dataset = @c.new(nil).from(:test)
@@ -1148,6 +1158,14 @@ context "Dataset#count" do
1148
1158
  @dataset.graph(@dataset, [:a], :table_alias=>:test2).count.should == 1
1149
1159
  @c.sql.should == 'SELECT COUNT(*) FROM test LEFT OUTER JOIN test AS test2 USING (a) LIMIT 1'
1150
1160
  end
1161
+
1162
+ specify "should not cache the columns value" do
1163
+ ds = @dataset.from(:blah)
1164
+ ds.columns.should == [:a]
1165
+ ds.count.should == 1
1166
+ @c.sql.should == 'SELECT COUNT(*) FROM blah LIMIT 1'
1167
+ ds.columns.should == [:a]
1168
+ end
1151
1169
  end
1152
1170
 
1153
1171
 
@@ -1274,16 +1292,28 @@ context "Dataset#join_table" do
1274
1292
  'SELECT * FROM "items" INNER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
1275
1293
  end
1276
1294
 
1277
- specify "should support aliased tables" do
1295
+ specify "should support aliased tables using the deprecated argument" do
1278
1296
  @d.from('stats').join('players', {:id => :player_id}, 'p').sql.should ==
1279
1297
  'SELECT * FROM "stats" INNER JOIN "players" AS "p" ON ("p"."id" = "stats"."player_id")'
1298
+ end
1280
1299
 
1300
+ specify "should support aliased tables using the :table_alias option" do
1301
+ @d.from('stats').join('players', {:id => :player_id}, :table_alias=>:p).sql.should ==
1302
+ 'SELECT * FROM "stats" INNER JOIN "players" AS "p" ON ("p"."id" = "stats"."player_id")'
1303
+ end
1304
+
1305
+ specify "should support using an alias for the FROM when doing the first join with unqualified condition columns" do
1281
1306
  ds = MockDataset.new(nil).from(:foo => :f)
1282
1307
  ds.quote_identifiers = true
1283
1308
  ds.join_table(:inner, :bar, :id => :bar_id).sql.should ==
1284
1309
  'SELECT * FROM "foo" AS "f" INNER JOIN "bar" ON ("bar"."id" = "f"."bar_id")'
1285
1310
  end
1286
1311
 
1312
+ specify "should support the :implicit_qualifier option" do
1313
+ @d.from('stats').join('players', {:id => :player_id}, :implicit_qualifier=>:p).sql.should ==
1314
+ 'SELECT * FROM "stats" INNER JOIN "players" ON ("players"."id" = "p"."player_id")'
1315
+ end
1316
+
1287
1317
  specify "should allow for arbitrary conditions in the JOIN clause" do
1288
1318
  @d.join_table(:left_outer, :categories, :status => 0).sql.should ==
1289
1319
  'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."status" = 0)'
@@ -2953,6 +2983,11 @@ context "Dataset#grep" do
2953
2983
  @ds.grep(:title, [/^ruby/, 'ruby']).sql.should ==
2954
2984
  "SELECT * FROM posts WHERE (((title ~ '^ruby') OR (title LIKE 'ruby')))"
2955
2985
  end
2986
+
2987
+ specify "should support searching against other columns" do
2988
+ @ds.grep(:title, :body).sql.should ==
2989
+ "SELECT * FROM posts WHERE ((title LIKE body))"
2990
+ end
2956
2991
  end
2957
2992
 
2958
2993
  context "Sequel.use_parse_tree" do
@@ -3158,3 +3193,43 @@ context "Sequel::Dataset #set_overrides" do
3158
3193
  @ds.set_overrides(:x=>2).update_sql.should == "UPDATE items SET x = 1"
3159
3194
  end
3160
3195
  end
3196
+
3197
+ context "Sequel::Dataset#each" do
3198
+ before do
3199
+ @ds = Sequel::Dataset.new(nil).from(:items)
3200
+ def @ds.fetch_rows(sql)
3201
+ @columns = /count/i.match(sql) ? [:count] : [:a]
3202
+ yield({@columns.first=>sql})
3203
+ end
3204
+ end
3205
+
3206
+ specify "should not set the columns if passing an option that modifies them" do
3207
+ @ds.each(:select=>[:count]){}
3208
+ @ds.columns.should == [:a]
3209
+ @ds.each(:from=>[:count]){}
3210
+ @ds.columns.should == [:a]
3211
+ @ds.each(:join=>[Sequel::SQL::JoinClause.new(:natural, :count)]){}
3212
+ @ds.columns.should == [:a]
3213
+ @ds.each(:sql=>'SELECT COUNT'){}
3214
+ @ds.columns.should == [:a]
3215
+ end
3216
+
3217
+ specify "should have the correct columns inside the block regardless" do
3218
+ @ds.each(:select=>[:count]) do |x|
3219
+ x[:count].should == 'SELECT count FROM items'
3220
+ @ds.columns.should == [:count]
3221
+ end
3222
+ @ds.each(:from=>[:count]) do |x|
3223
+ x[:count].should == 'SELECT * FROM count'
3224
+ @ds.columns.should == [:count]
3225
+ end
3226
+ @ds.each(:join=>[Sequel::SQL::JoinClause.new(:natural, :count)]) do |x|
3227
+ x[:count].should == 'SELECT * FROM items NATURAL JOIN count'
3228
+ @ds.columns.should == [:count]
3229
+ end
3230
+ @ds.each(:sql=>'SELECT COUNT') do |x|
3231
+ x[:count].should == 'SELECT COUNT'
3232
+ @ds.columns.should == [:count]
3233
+ end
3234
+ end
3235
+ end
@@ -343,4 +343,10 @@ context "Blockless Ruby Filters" do
343
343
  ce.instance_variable_set(:@op, :BANG)
344
344
  proc{@d.lit(ce)}.should raise_error(Sequel::Error)
345
345
  end
346
+
347
+ it "should support equality comparison of two expressions" do
348
+ e1 = ~:comment.like('%:hidden:%')
349
+ e2 = ~:comment.like('%:hidden:%')
350
+ e1.should == e2
351
+ end
346
352
  end
@@ -55,6 +55,11 @@ describe Sequel::Dataset, " graphing" do
55
55
  ds.sql.should == 'SELECT points.id, points.x, points.y, planes.id AS planes_id, planes.x AS planes_x, planes.y AS planes_y, planes.graph_id FROM points LEFT OUTER JOIN lines AS planes ON (planes.x = points.id)'
56
56
  end
57
57
 
58
+ it "#graph should accept a :implicit_qualifier option" do
59
+ ds = @ds1.graph(:lines, {:x=>:id}, :implicit_qualifier=>:planes)
60
+ ds.sql.should == 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = planes.id)'
61
+ end
62
+
58
63
  it "#graph should accept a :join_type option" do
59
64
  ds = @ds1.graph(:lines, {:x=>:id}, :join_type=>:inner)
60
65
  ds.sql.should == 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points INNER JOIN lines ON (lines.x = points.id)'
@@ -104,13 +109,19 @@ describe Sequel::Dataset, " graphing" do
104
109
  proc{@ds1.graph(@ds2, :x=>:id).graph(@ds2, {:x=>:id}, :table_alias=>:blah)}.should_not raise_error
105
110
  end
106
111
 
107
- it "#set_graph_aliases should not modify the current dataset's opts" do
112
+ it "#set_graph_aliases and #add_graph_aliases should not modify the current dataset's opts" do
108
113
  o1 = @ds1.opts
109
114
  o2 = o1.dup
110
115
  ds1 = @ds1.set_graph_aliases(:x=>[:graphs,:id])
111
116
  @ds1.opts.should == o1
112
117
  @ds1.opts.should == o2
113
118
  ds1.opts.should_not == o1
119
+ o3 = ds1.opts
120
+ o4 = o3.dup
121
+ ds2 = ds1.add_graph_aliases(:y=>[:blah,:id])
122
+ ds1.opts.should == o3
123
+ ds1.opts.should == o3
124
+ ds2.opts.should_not == o2
114
125
  end
115
126
 
116
127
  it "#set_graph_aliases should specify the graph mapping" do
@@ -122,6 +133,17 @@ describe Sequel::Dataset, " graphing" do
122
133
  ].should(include(ds.sql))
123
134
  end
124
135
 
136
+ it "#add_graph_aliases should add columns to the graph mapping" do
137
+ @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :q]).add_graph_aliases(:y=>[:lines, :r]).sql.should == 'SELECT points.q AS x, lines.r AS y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
138
+ end
139
+
140
+ it "#set_graph_aliases should allow a third entry to specify an expression to use other than the default" do
141
+ ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x, 1], :y=>[:lines, :y, :random[]])
142
+ ['SELECT 1 AS x, random() AS y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)',
143
+ 'SELECT random() AS y, 1 AS x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
144
+ ].should(include(ds.sql))
145
+ end
146
+
125
147
  it "#set_graph_aliases should only alias columns if necessary" do
126
148
  ds = @ds1.set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y])
127
149
  ['SELECT points.x, lines.y FROM points',
@@ -194,7 +216,7 @@ describe Sequel::Dataset, " graphing" do
194
216
  results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :graphs=>{:id=>8, :name=>9, :x=>10, :y=>11, :lines_x=>12}}
195
217
  end
196
218
 
197
- it "#graph_each should only include the columns selected with #set_graph_aliases, if called" do
219
+ it "#graph_each should only include the columns selected with #set_graph_aliases and #add_graph_aliases, if called" do
198
220
  ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y])
199
221
  def ds.fetch_rows(sql, &block)
200
222
  yield({:x=>2,:y=>3})
@@ -210,6 +232,22 @@ describe Sequel::Dataset, " graphing" do
210
232
  results = ds.all
211
233
  results.length.should == 1
212
234
  results.first.should == {:points=>{:x=>2}, :lines=>nil}
235
+
236
+ ds = ds.add_graph_aliases(:q=>[:points, :r, 18])
237
+ def ds.fetch_rows(sql, &block)
238
+ yield({:x=>2, :q=>18})
239
+ end
240
+ ds.all.should == [{:points=>{:x=>2, :r=>18}, :lines=>nil}]
241
+ end
242
+
243
+ it "#graph_each should correctly map values when #set_graph_aliases is used with a third argument for each entry" do
244
+ ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :z1, 2], :y=>[:lines, :z2, :random[]])
245
+ def ds.fetch_rows(sql, &block)
246
+ yield({:x=>2,:y=>3})
247
+ end
248
+ results = ds.all
249
+ results.length.should == 1
250
+ results.first.should == {:points=>{:z1=>2}, :lines=>{:z2=>3}}
213
251
  end
214
252
 
215
253
  it "#graph_each should run the row_proc and transform for graphed datasets" do
@@ -10,6 +10,19 @@ context "DB#create_table" do
10
10
  @db.sqls.should == ['CREATE TABLE cats ()']
11
11
  end
12
12
 
13
+ specify "should accept the table name in multiple formats" do
14
+ @db.create_table(:cats__cats) {}
15
+ @db.create_table("cats__cats1") {}
16
+ @db.create_table(:cats__cats2.identifier) {}
17
+ @db.create_table(:cats.qualify(:cats3)) {}
18
+ @db.sqls.should == ['CREATE TABLE cats.cats ()', 'CREATE TABLE cats__cats1 ()', 'CREATE TABLE cats__cats2 ()', 'CREATE TABLE cats3.cats ()']
19
+ end
20
+
21
+ specify "should raise an error if the table name argument is not valid" do
22
+ proc{@db.create_table(1) {}}.should raise_error(Sequel::Error)
23
+ proc{@db.create_table(:cats.as(:c)) {}}.should raise_error(Sequel::Error)
24
+ end
25
+
13
26
  specify "should accept multiple columns" do
14
27
  @db.create_table(:cats) do
15
28
  column :id, :integer