sequel_core 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/CHANGELOG +74 -0
  2. data/COPYING +1 -0
  3. data/README +17 -6
  4. data/Rakefile +16 -21
  5. data/lib/sequel_core.rb +18 -28
  6. data/lib/sequel_core/adapters/ado.rb +3 -15
  7. data/lib/sequel_core/adapters/dbi.rb +1 -14
  8. data/lib/sequel_core/adapters/informix.rb +3 -3
  9. data/lib/sequel_core/adapters/jdbc.rb +2 -2
  10. data/lib/sequel_core/adapters/mysql.rb +39 -59
  11. data/lib/sequel_core/adapters/odbc.rb +18 -38
  12. data/lib/sequel_core/adapters/openbase.rb +1 -17
  13. data/lib/sequel_core/adapters/oracle.rb +1 -19
  14. data/lib/sequel_core/adapters/postgres.rb +20 -60
  15. data/lib/sequel_core/adapters/sqlite.rb +4 -8
  16. data/lib/sequel_core/connection_pool.rb +150 -0
  17. data/lib/sequel_core/core_ext.rb +41 -0
  18. data/lib/sequel_core/core_sql.rb +35 -38
  19. data/lib/sequel_core/database.rb +20 -17
  20. data/lib/sequel_core/dataset.rb +49 -80
  21. data/lib/sequel_core/dataset/callback.rb +11 -13
  22. data/lib/sequel_core/dataset/convenience.rb +18 -136
  23. data/lib/sequel_core/dataset/pagination.rb +81 -0
  24. data/lib/sequel_core/dataset/sequelizer.rb +5 -4
  25. data/lib/sequel_core/dataset/sql.rb +43 -33
  26. data/lib/sequel_core/deprecated.rb +200 -0
  27. data/lib/sequel_core/exceptions.rb +0 -14
  28. data/lib/sequel_core/object_graph.rb +199 -0
  29. data/lib/sequel_core/pretty_table.rb +27 -24
  30. data/lib/sequel_core/schema/generator.rb +16 -4
  31. data/lib/sequel_core/schema/sql.rb +5 -3
  32. data/lib/sequel_core/worker.rb +1 -1
  33. data/spec/adapters/informix_spec.rb +1 -47
  34. data/spec/adapters/mysql_spec.rb +85 -54
  35. data/spec/adapters/oracle_spec.rb +1 -57
  36. data/spec/adapters/postgres_spec.rb +66 -49
  37. data/spec/adapters/sqlite_spec.rb +4 -29
  38. data/spec/connection_pool_spec.rb +358 -0
  39. data/spec/core_sql_spec.rb +24 -19
  40. data/spec/database_spec.rb +13 -9
  41. data/spec/dataset_spec.rb +59 -78
  42. data/spec/object_graph_spec.rb +202 -0
  43. data/spec/pretty_table_spec.rb +1 -9
  44. data/spec/schema_generator_spec.rb +7 -1
  45. data/spec/schema_spec.rb +27 -0
  46. data/spec/sequelizer_spec.rb +2 -2
  47. data/spec/spec_helper.rb +4 -2
  48. metadata +16 -57
  49. data/lib/sequel_core/array_keys.rb +0 -322
  50. data/lib/sequel_core/model.rb +0 -8
  51. data/spec/array_keys_spec.rb +0 -682
@@ -46,7 +46,7 @@ context "Database#uri" do
46
46
  set_adapter_scheme :mau
47
47
  end
48
48
 
49
- @db = Sequel('mau://user:pass@localhost:9876/maumau')
49
+ @db = Sequel.connect('mau://user:pass@localhost:9876/maumau')
50
50
  end
51
51
 
52
52
  specify "should return the connection URI for the database" do
@@ -442,10 +442,10 @@ context "Database#transaction" do
442
442
  proc {@db.transaction {raise RuntimeError}}.should raise_error(RuntimeError)
443
443
  end
444
444
 
445
- specify "should issue ROLLBACK if rollback! is called in the transaction" do
445
+ specify "should issue ROLLBACK if Sequel::Error::Rollback is called in the transaction" do
446
446
  @db.transaction do
447
447
  @db.drop_table(:a)
448
- rollback!
448
+ raise Sequel::Error::Rollback
449
449
  @db.drop_table(:b)
450
450
  end
451
451
 
@@ -506,6 +506,7 @@ context "A Database adapter with a scheme" do
506
506
  c.opts[:database].should == 'db'
507
507
  end
508
508
 
509
+ ### DEPRECATED
509
510
  specify "should be accessible through Sequel()" do
510
511
  c = Sequel('ccc://localhost/db')
511
512
  c.should be_a_kind_of(CCC)
@@ -514,24 +515,27 @@ context "A Database adapter with a scheme" do
514
515
  end
515
516
 
516
517
  specify "should be accessible through Sequel.<adapter>" do
518
+ class << Sequel
519
+ def_adapter_method(:ccc)
520
+ end
517
521
  # invalid parameters
518
522
  proc {Sequel.ccc('abc', 'def')}.should raise_error(Sequel::Error)
519
523
 
520
524
  c = Sequel.ccc('mydb')
521
525
  c.should be_a_kind_of(CCC)
522
- c.opts.should == {:database => 'mydb'}
526
+ c.opts.should == {:adapter=>:ccc, :database => 'mydb'}
523
527
 
524
528
  c = Sequel.ccc('mydb', :host => 'localhost')
525
529
  c.should be_a_kind_of(CCC)
526
- c.opts.should == {:database => 'mydb', :host => 'localhost'}
530
+ c.opts.should == {:adapter=>:ccc, :database => 'mydb', :host => 'localhost'}
527
531
 
528
532
  c = Sequel.ccc
529
533
  c.should be_a_kind_of(CCC)
530
- c.opts.should == {}
534
+ c.opts.should == {:adapter=>:ccc}
531
535
 
532
536
  c = Sequel.ccc(:database => 'mydb', :host => 'localhost')
533
537
  c.should be_a_kind_of(CCC)
534
- c.opts.should == {:database => 'mydb', :host => 'localhost'}
538
+ c.opts.should == {:adapter=>:ccc, :database => 'mydb', :host => 'localhost'}
535
539
  end
536
540
 
537
541
  specify "should be accessible through Sequel.connect with options" do
@@ -836,7 +840,7 @@ context "Database.connect" do
836
840
  end
837
841
 
838
842
  specify "should accept hashes loaded from YAML files" do
839
- db = Sequel(YAML.load_file(@fn)['development'])
843
+ db = Sequel.connect(YAML.load_file(@fn)['development'])
840
844
  db.class.should == EEE
841
845
  db.opts[:database].should == 'mydb'
842
846
  db.opts[:user].should == 'mau'
@@ -877,4 +881,4 @@ context "Database#get" do
877
881
  @db.get(:version[])
878
882
  @db.sqls.last.should == 'SELECT version()'
879
883
  end
880
- end
884
+ end
data/spec/dataset_spec.rb CHANGED
@@ -127,33 +127,20 @@ context "A simple dataset" do
127
127
  @dataset.insert_sql({}).should == "INSERT INTO test DEFAULT VALUES"
128
128
  end
129
129
 
130
- specify "should format an insert statement with array with keys" do
131
- v = [1, 2, 3]
132
- v.keys = [:a, :b, :c]
133
- @dataset.insert_sql(v).should == "INSERT INTO test (a, b, c) VALUES (1, 2, 3)"
134
-
135
- v = []
136
- v.keys = [:a, :b]
137
- @dataset.insert_sql(v).should == "INSERT INTO test DEFAULT VALUES"
138
- end
139
-
140
130
  specify "should format an insert statement with string keys" do
141
131
  @dataset.insert_sql('name' => 'wxyz', 'price' => 342).
142
132
  should match(/INSERT INTO test \(name, price\) VALUES \('wxyz', 342\)|INSERT INTO test \(price, name\) VALUES \(342, 'wxyz'\)/)
143
133
  end
144
134
 
145
- specify "should format an insert statement with a model instance" do
135
+ specify "should format an insert statement with an object that respond_to? :values" do
146
136
  dbb = Sequel::Database.new
147
137
 
148
- @c = Class.new(Sequel::Model) do
149
- attr_accessor :values
150
- end
151
-
152
- v = @c.new; v.values = {:a => 1}
138
+ v = Object.new
139
+ def v.values; {:a => 1}; end
153
140
 
154
141
  @dataset.insert_sql(v).should == "INSERT INTO test (a) VALUES (1)"
155
142
 
156
- v = @c.new; v.values = {}
143
+ def v.values; {}; end
157
144
  @dataset.insert_sql(v).should == "INSERT INTO test DEFAULT VALUES"
158
145
  end
159
146
 
@@ -180,13 +167,6 @@ context "A simple dataset" do
180
167
  "UPDATE test SET x = y"
181
168
  end
182
169
 
183
- specify "should format an update statement with array with keys" do
184
- v = ['abc']
185
- v.keys = [:name]
186
-
187
- @dataset.update_sql(v).should == "UPDATE test SET name = 'abc'"
188
- end
189
-
190
170
  specify "should be able to return rows for arbitrary SQL" do
191
171
  @dataset.select_sql(:sql => 'xxx yyy zzz').should ==
192
172
  "xxx yyy zzz"
@@ -332,7 +312,7 @@ context "Dataset#where" do
332
312
 
333
313
  specify "should accept a subquery" do
334
314
  # select all countries that have GDP greater than the average for Asia
335
- @dataset.filter('gdp > ?', @d1.select(:gdp.AVG)).sql.should ==
315
+ @dataset.filter('gdp > ?', @d1.select(:avg[:gdp])).sql.should ==
336
316
  "SELECT * FROM test WHERE gdp > (SELECT avg(gdp) FROM test WHERE (region = 'Asia'))"
337
317
 
338
318
  @dataset.filter(:id => @d1.select(:id)).sql.should ==
@@ -346,7 +326,7 @@ context "Dataset#where" do
346
326
  end
347
327
 
348
328
  specify "should accept proc expressions" do
349
- d = @d1.select(:gdp.AVG)
329
+ d = @d1.select(:avg[:gdp])
350
330
  @dataset.filter {:gdp > d}.sql.should ==
351
331
  "SELECT * FROM test WHERE (gdp > (SELECT avg(gdp) FROM test WHERE (region = 'Asia')))"
352
332
 
@@ -501,7 +481,7 @@ end
501
481
  context "Dataset#having" do
502
482
  setup do
503
483
  @dataset = Sequel::Dataset.new(nil).from(:test)
504
- @grouped = @dataset.group(:region).select(:region, :population.SUM, :gdp.AVG)
484
+ @grouped = @dataset.group(:region).select(:region, :sum[:population], :avg[:gdp])
505
485
  @d1 = @grouped.having('sum(population) > 10')
506
486
  @d2 = @grouped.having(:region => 'Asia')
507
487
  @columns = "region, sum(population), avg(gdp)"
@@ -581,6 +561,9 @@ context "Dataset#literal" do
581
561
  @dataset.literal('a"x"bc').should == "'a\"x\"bc'"
582
562
  @dataset.literal("a'bc").should == "'a''bc'"
583
563
  @dataset.literal("a''bc").should == "'a''''bc'"
564
+ @dataset.literal("a\\bc").should == "'a\\\\bc'"
565
+ @dataset.literal("a\\\\bc").should == "'a\\\\\\\\bc'"
566
+ @dataset.literal("a\\'bc").should == "'a\\\\''bc'"
584
567
  end
585
568
 
586
569
  specify "should literalize numbers properly" do
@@ -718,9 +701,9 @@ context "Dataset#select" do
718
701
  'SELECT test.d AS e, test.cc FROM test'
719
702
 
720
703
  # symbol helpers
721
- @d.select(:test.ALL).sql.should ==
704
+ @d.select(:test.*).sql.should ==
722
705
  'SELECT test.* FROM test'
723
- @d.select(:test__name.AS(:n)).sql.should ==
706
+ @d.select(:test__name.as(:n)).sql.should ==
724
707
  'SELECT test.name AS n FROM test'
725
708
  @d.select(:test__name___n).sql.should ==
726
709
  'SELECT test.name AS n FROM test'
@@ -776,7 +759,7 @@ context "Dataset#select_more" do
776
759
 
777
760
  specify "should add to the currently selected columns" do
778
761
  @d.select(:a).select_more(:b).sql.should == 'SELECT a, b FROM test'
779
- @d.select(:a.all).select_more(:b.all).sql.should == 'SELECT a.*, b.* FROM test'
762
+ @d.select(:a.*).select_more(:b.*).sql.should == 'SELECT a.*, b.* FROM test'
780
763
  end
781
764
  end
782
765
 
@@ -791,7 +774,7 @@ context "Dataset#order" do
791
774
  end
792
775
 
793
776
  specify "should accept multiple arguments" do
794
- @dataset.order(:name, :price.DESC).sql.should ==
777
+ @dataset.order(:name, :price.desc).sql.should ==
795
778
  'SELECT * FROM test ORDER BY name, price DESC'
796
779
  end
797
780
 
@@ -833,7 +816,7 @@ context "Dataset#order_by" do
833
816
  end
834
817
 
835
818
  specify "should accept multiple arguments" do
836
- @dataset.order_by(:name, :price.DESC).sql.should ==
819
+ @dataset.order_by(:name, :price.desc).sql.should ==
837
820
  'SELECT * FROM test ORDER BY name, price DESC'
838
821
  end
839
822
 
@@ -864,7 +847,7 @@ context "Dataset#order_more" do
864
847
  end
865
848
 
866
849
  specify "should add to a previous ordering" do
867
- @dataset.order(:name).order_more(:stamp.DESC).sql.should ==
850
+ @dataset.order(:name).order_more(:stamp.desc).sql.should ==
868
851
  'SELECT * FROM test ORDER BY name, stamp DESC'
869
852
  end
870
853
  end
@@ -880,24 +863,24 @@ context "Dataset#reverse_order" do
880
863
  end
881
864
 
882
865
  specify "should invert the order given" do
883
- @dataset.reverse_order(:name.DESC).sql.should ==
866
+ @dataset.reverse_order(:name.desc).sql.should ==
884
867
  'SELECT * FROM test ORDER BY name'
885
868
  end
886
869
 
887
870
  specify "should invert the order for ASC expressions" do
888
- @dataset.reverse_order(:name.ASC).sql.should ==
871
+ @dataset.reverse_order(:name.asc).sql.should ==
889
872
  'SELECT * FROM test ORDER BY name DESC'
890
873
  end
891
874
 
892
875
  specify "should accept multiple arguments" do
893
- @dataset.reverse_order(:name, :price.DESC).sql.should ==
876
+ @dataset.reverse_order(:name, :price.desc).sql.should ==
894
877
  'SELECT * FROM test ORDER BY name DESC, price'
895
878
  end
896
879
 
897
880
  specify "should reverse a previous ordering if no arguments are given" do
898
881
  @dataset.order(:name).reverse_order.sql.should ==
899
882
  'SELECT * FROM test ORDER BY name DESC'
900
- @dataset.order(:clumsy.DESC, :fool).reverse_order.sql.should ==
883
+ @dataset.order(:clumsy.desc, :fool).reverse_order.sql.should ==
901
884
  'SELECT * FROM test ORDER BY clumsy, fool DESC'
902
885
  end
903
886
 
@@ -965,13 +948,13 @@ context "Dataset#qualified_column_name" do
965
948
  end
966
949
 
967
950
  specify "should return the same if already qualified" do
968
- @dataset.qualified_column_name('test.a'.lit, :items).should == 'test.a'
969
- @dataset.qualified_column_name(:ccc__b, :items).should == :ccc__b
951
+ @dataset.send(:qualified_column_name, 'test.a'.lit, :items).should == 'test.a'
952
+ @dataset.send(:qualified_column_name, :ccc__b, :items).should == :ccc__b
970
953
  end
971
954
 
972
955
  specify "should qualify the column with the supplied table name" do
973
- @dataset.qualified_column_name('a'.lit, :items).to_s(@dataset).should == 'items.a'
974
- @dataset.qualified_column_name(:b1, :items).to_s(@dataset).should == 'items.b1'
956
+ @dataset.send(:qualified_column_name, 'a'.lit, :items).to_s(@dataset).should == 'items.a'
957
+ @dataset.send(:qualified_column_name, :b1, :items).to_s(@dataset).should == 'items.b1'
975
958
  end
976
959
  end
977
960
 
@@ -1250,6 +1233,17 @@ context "Dataset#join_table" do
1250
1233
  'SELECT * FROM items LEFT OUTER JOIN (SELECT * FROM categories WHERE (active = \'t\')) t1 ON (t1.item_id = items.id)'
1251
1234
  end
1252
1235
 
1236
+ specify "should support joining multiple datasets" do
1237
+ ds = Sequel::Dataset.new(nil).from(:categories)
1238
+ ds2 = Sequel::Dataset.new(nil).from(:nodes).select(:name)
1239
+ ds3 = Sequel::Dataset.new(nil).from(:attributes).filter("name = 'blah'")
1240
+
1241
+ @d.join_table(:left_outer, ds, :item_id => :id).join_table(:inner, ds2, :node_id=>:id).join_table(:right_outer, ds3, :attribute_id=>:id).sql.should ==
1242
+ 'SELECT * FROM items LEFT OUTER JOIN (SELECT * FROM categories) t1 ON (t1.item_id = items.id) ' \
1243
+ 'INNER JOIN (SELECT name FROM nodes) t2 ON (t2.node_id = t1.id) ' \
1244
+ "RIGHT OUTER JOIN (SELECT * FROM attributes WHERE name = 'blah') t3 ON (t3.attribute_id = t2.id)"
1245
+ end
1246
+
1253
1247
  specify "should support joining objects that respond to :table_name" do
1254
1248
  ds = Object.new
1255
1249
  def ds.table_name; :categories end
@@ -1515,16 +1509,16 @@ context "Dataset#last" do
1515
1509
 
1516
1510
  specify "should invert the order" do
1517
1511
  @d.order(:a).last
1518
- @d.literal(@c.last_dataset.opts[:order]).should == @d.literal([:a.DESC])
1512
+ @d.literal(@c.last_dataset.opts[:order]).should == @d.literal([:a.desc])
1519
1513
 
1520
- @d.order(:b.DESC).last
1514
+ @d.order(:b.desc).last
1521
1515
  @d.literal(@c.last_dataset.opts[:order]).should == @d.literal(:b)
1522
1516
 
1523
1517
  @d.order(:c, :d).last
1524
- @d.literal(@c.last_dataset.opts[:order]).should == @d.literal([:c.DESC, :d.DESC])
1518
+ @d.literal(@c.last_dataset.opts[:order]).should == @d.literal([:c.desc, :d.desc])
1525
1519
 
1526
- @d.order(:e.DESC, :f).last
1527
- @d.literal(@c.last_dataset.opts[:order]).should == @d.literal([:e, :f.DESC])
1520
+ @d.order(:e.desc, :f).last
1521
+ @d.literal(@c.last_dataset.opts[:order]).should == @d.literal([:e, :f.desc])
1528
1522
  end
1529
1523
 
1530
1524
  specify "should return the first matching record if a hash is specified" do
@@ -1704,7 +1698,7 @@ context "Dataset#set_row_proc" do
1704
1698
  end
1705
1699
 
1706
1700
  specify "should cause dataset to pass all rows through the filter" do
1707
- @dataset.set_row_proc {|h| h[:der] = h[:kind] + 2; h}
1701
+ @dataset.row_proc = proc{|h| h[:der] = h[:kind] + 2; h}
1708
1702
 
1709
1703
  rows = @dataset.all
1710
1704
  rows.size.should == 10
@@ -1713,7 +1707,7 @@ context "Dataset#set_row_proc" do
1713
1707
  end
1714
1708
 
1715
1709
  specify "should be copied over when dataset is cloned" do
1716
- @dataset.set_row_proc {|h| h[:der] = h[:kind] + 2; h}
1710
+ @dataset.row_proc = proc{|h| h[:der] = h[:kind] + 2; h}
1717
1711
 
1718
1712
  @dataset.filter(:a => 1).first.should == {:kind => 1, :der => 3}
1719
1713
  end
@@ -2039,6 +2033,11 @@ context "A paginated dataset" do
2039
2033
  @paginated = @d.paginate(1, 20)
2040
2034
  end
2041
2035
 
2036
+ specify "should raise an error if the dataset already has a limit" do
2037
+ proc{@d.limit(10).paginate(1,10)}.should raise_error(Sequel::Error)
2038
+ proc{@paginated.paginate(2,20)}.should raise_error(Sequel::Error)
2039
+ end
2040
+
2042
2041
  specify "should set the limit and offset options correctly" do
2043
2042
  @paginated.opts[:limit].should == 20
2044
2043
  @paginated.opts[:offset].should == 0
@@ -2095,6 +2094,10 @@ context "Dataset#each_page" do
2095
2094
  @d.meta_def(:count) {153}
2096
2095
  end
2097
2096
 
2097
+ specify "should raise an error if the dataset already has a limit" do
2098
+ proc{@d.limit(10).each_page(10){}}.should raise_error(Sequel::Error)
2099
+ end
2100
+
2098
2101
  specify "should iterate over each page in the resultset as a paginated dataset" do
2099
2102
  a = []
2100
2103
  @d.each_page(50) {|p| a << p}
@@ -2484,7 +2487,7 @@ context "Dataset#transform" do
2484
2487
  end
2485
2488
 
2486
2489
  specify "should work correctly together with set_row_proc" do
2487
- @ds.set_row_proc {|r| r[:z] = r[:x] * 2; r}
2490
+ @ds.row_proc = proc{|r| r[:z] = r[:x] * 2; r}
2488
2491
  @ds.raw = {:x => Marshal.dump("wow"), :y => 'hello'}
2489
2492
  @ds.first.should == {:x => "wow", :y => 'hello', :z => "wowwow"}
2490
2493
 
@@ -2550,7 +2553,7 @@ context "Dataset#transform" do
2550
2553
  @ds2.insert(:x => :toast)
2551
2554
  @ds2.sql.should == "INSERT INTO items (x) VALUES ('#{:toast.to_yaml}')"
2552
2555
 
2553
- @ds.set_row_proc {|r| r[:z] = r[:x] * 2; r}
2556
+ @ds.row_proc = proc{|r| r[:z] = r[:x] * 2; r}
2554
2557
  @ds.raw = {:x => "wow".to_yaml, :y => 'hello'}
2555
2558
  @ds.first.should == {:x => "wow", :y => 'hello', :z => "wowwow"}
2556
2559
  f = nil
@@ -2578,7 +2581,7 @@ context "Dataset#transform" do
2578
2581
  @ds2.insert(:x => :toast)
2579
2582
  @ds2.sql.should == "INSERT INTO items (x) VALUES ('#{Base64.encode64(Marshal.dump(:toast))}')"
2580
2583
 
2581
- @ds.set_row_proc {|r| r[:z] = r[:x] * 2; r}
2584
+ @ds.row_proc = proc{|r| r[:z] = r[:x] * 2; r}
2582
2585
  @ds.raw = {:x => Base64.encode64(Marshal.dump("wow")), :y => 'hello'}
2583
2586
  @ds.first.should == {:x => "wow", :y => 'hello', :z => "wowwow"}
2584
2587
  f = nil
@@ -2616,11 +2619,10 @@ context "Dataset#to_csv" do
2616
2619
  setup do
2617
2620
  @c = Class.new(Sequel::Dataset) do
2618
2621
  attr_accessor :data
2619
- attr_accessor :cols
2622
+ attr_accessor :columns
2620
2623
 
2621
2624
  def fetch_rows(sql, &block)
2622
- @columns = @cols
2623
- @data.each {|r| r.keys = @columns; block[r]}
2625
+ @data.each(&block)
2624
2626
  end
2625
2627
 
2626
2628
  # naked should return self here because to_csv wants a naked result set.
@@ -2630,11 +2632,8 @@ context "Dataset#to_csv" do
2630
2632
  end
2631
2633
 
2632
2634
  @ds = @c.new(nil).from(:items)
2633
-
2634
- @ds.cols = [:a, :b, :c]
2635
- @ds.data = [
2636
- [1, 2, 3], [4, 5, 6], [7, 8, 9]
2637
- ]
2635
+ @ds.columns = [:a, :b, :c]
2636
+ @ds.data = [ {:a=>1, :b=>2, :c=>3}, {:a=>4, :b=>5, :c=>6}, {:a=>7, :b=>8, :c=>9} ]
2638
2637
  end
2639
2638
 
2640
2639
  specify "should format a CSV representation of the records" do
@@ -2648,25 +2647,7 @@ context "Dataset#to_csv" do
2648
2647
  end
2649
2648
  end
2650
2649
 
2651
- context "Dataset#each_hash" do
2652
- setup do
2653
- @c = Class.new(Sequel::Dataset) do
2654
- def each(&block)
2655
- a = [[1, 2, 3], [4, 5, 6]]
2656
- a.each {|r| r.keys = [:a, :b, :c]; block[r]}
2657
- end
2658
- end
2659
-
2660
- @ds = @c.new(nil).from(:items)
2661
- end
2662
-
2663
- specify "should yield records converted to hashes" do
2664
- hashes = []
2665
- @ds.each_hash {|h| hashes << h}
2666
- hashes.should == [{:a => 1, :b => 2, :c => 3}, {:a => 4, :b => 5, :c => 6}]
2667
- end
2668
- end
2669
-
2650
+ ### DEPRECATED
2670
2651
  context "Dataset magic methods" do
2671
2652
  setup do
2672
2653
  @c = Class.new(Sequel::Dataset) do
@@ -0,0 +1,202 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Sequel::Dataset, " graphing" do
4
+ before do
5
+ dbc = Class.new
6
+ @db = dbc.new
7
+ @ds1 = Sequel::Dataset.new(@db).from(:points)
8
+ @ds2 = Sequel::Dataset.new(@db).from(:lines)
9
+ @ds3 = Sequel::Dataset.new(@db).from(:graphs)
10
+ dss = {:points=>@ds1, :lines=>@ds2, :graphs=>@ds3}
11
+ dbc.send(:define_method, :[]){|ds| dss[ds]}
12
+ def @ds1.columns; [:id, :x, :y] end
13
+ def @ds2.columns; [:id, :x, :y, :graph_id] end
14
+ def @ds3.columns; [:id, :name, :x, :y, :lines_x] end
15
+ end
16
+
17
+ it "#graph should not modify the current dataset's opts" do
18
+ o1 = @ds1.opts
19
+ o2 = o1.dup
20
+ ds1 = @ds1.graph(@ds2, :x=>:id)
21
+ @ds1.opts.should == o1
22
+ @ds1.opts.should == o2
23
+ ds1.opts.should_not == o1
24
+ end
25
+
26
+ it "#graph should accept a dataset as the dataset" do
27
+ ds = @ds1.graph(@ds2, :x=>:id)
28
+ 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 = points.id)'
29
+ end
30
+
31
+ it "#graph should accept a symbol table name as the dataset" do
32
+ ds = @ds1.graph(:lines, :x=>:id)
33
+ 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 = points.id)'
34
+ end
35
+
36
+ it "#graph should accept an object that responds to dataset as the dataset" do
37
+ oc = Class.new
38
+ o = oc.new
39
+ ds = @ds2
40
+ oc.send(:define_method, :dataset){ds}
41
+ ds = @ds1.graph(o, :x=>:id)
42
+ 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 = points.id)'
43
+ ds = :lines
44
+ oc.send(:define_method, :dataset){ds}
45
+ ds = @ds1.graph(o, :x=>:id)
46
+ 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 = points.id)'
47
+ end
48
+
49
+ it "#graph should accept a :table_alias option" do
50
+ ds = @ds1.graph(:lines, {:x=>:id}, :table_alias=>:planes)
51
+ 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 planes ON (planes.x = points.id)'
52
+ end
53
+
54
+ it "#graph should accept a :join_type option" do
55
+ ds = @ds1.graph(:lines, {:x=>:id}, :join_type=>:inner)
56
+ 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)'
57
+ end
58
+
59
+ it "#graph should accept a :select_option" do
60
+ ds = @ds1.graph(:lines, {:x=>:id}, :select=>false).graph(:graphs, :id=>:graph_id)
61
+ ds.sql.should == 'SELECT points.id, points.x, points.y, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN graphs ON (graphs.id = lines.graph_id)'
62
+ end
63
+
64
+ it "#graph should pass all join_conditions to join_table" do
65
+ ds = @ds1.graph(@ds2, :x=>:id, :y=>:id)
66
+ ['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 = points.id) AND (lines.y = points.id)',
67
+ '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.y = points.id) AND (lines.x = points.id)'
68
+ ].should(include(ds.sql))
69
+ end
70
+
71
+ it "#graph should not add columns if graph is called after set_graph_aliases" do
72
+ ds = @ds1.set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y])
73
+ ['SELECT points.x, lines.y FROM points',
74
+ 'SELECT lines.y, points.x FROM points'
75
+ ].should(include(ds.sql))
76
+ ds = ds.graph(:lines, :x=>:id)
77
+ ['SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)',
78
+ 'SELECT lines.y, points.x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
79
+ ].should(include(ds.sql))
80
+ end
81
+
82
+ it "#graph should allow graphing of multiple datasets" do
83
+ ds = @ds1.graph(@ds2, :x=>:id).graph(@ds3, :id=>:graph_id)
84
+ 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, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x AS graphs_lines_x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN graphs ON (graphs.id = lines.graph_id)'
85
+ end
86
+
87
+ it "#graph should allow graphing of the same dataset multiple times" do
88
+ ds = @ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y=>:points__id}, :table_alias=>:graph)
89
+ 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, graph.id AS graph_id_0, graph.x AS graph_x, graph.y AS graph_y, graph.graph_id AS graph_graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN lines graph ON (graph.y = points.id)'
90
+ end
91
+
92
+ it "#graph should raise an error if the table/table alias has already been used" do
93
+ proc{@ds1.graph(@ds1, :x=>:id)}.should raise_error(Sequel::Error)
94
+ proc{@ds1.graph(@ds2, :x=>:id)}.should_not raise_error
95
+ proc{@ds1.graph(@ds2, :x=>:id).graph(@ds2, :x=>:id)}.should raise_error(Sequel::Error)
96
+ proc{@ds1.graph(@ds2, :x=>:id).graph(@ds2, {:x=>:id}, :table_alias=>:blah)}.should_not raise_error
97
+ end
98
+
99
+ it "#set_graph_aliases should not modify the current dataset's opts" do
100
+ o1 = @ds1.opts
101
+ o2 = o1.dup
102
+ ds1 = @ds1.set_graph_aliases(:x=>[:graphs,:id])
103
+ @ds1.opts.should == o1
104
+ @ds1.opts.should == o2
105
+ ds1.opts.should_not == o1
106
+ end
107
+
108
+ it "#set_graph_aliases should specify the graph mapping" do
109
+ ds = @ds1.graph(:lines, :x=>:id)
110
+ 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 = points.id)'
111
+ ds = ds.set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y])
112
+ ['SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)',
113
+ 'SELECT lines.y, points.x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
114
+ ].should(include(ds.sql))
115
+ end
116
+
117
+ it "#set_graph_aliases should only alias columns if necessary" do
118
+ ds = @ds1.set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y])
119
+ ['SELECT points.x, lines.y FROM points',
120
+ 'SELECT lines.y, points.x FROM points'
121
+ ].should(include(ds.sql))
122
+
123
+ ds = @ds1.set_graph_aliases(:x1=>[:points, :x], :y=>[:lines, :y])
124
+ ['SELECT points.x AS x1, lines.y FROM points',
125
+ 'SELECT lines.y, points.x AS x1 FROM points'
126
+ ].should(include(ds.sql))
127
+ end
128
+
129
+ it "#graph_each should split the result set into component tables" do
130
+ ds = @ds1.graph(@ds2, :x=>:id)
131
+ def ds.fetch_rows(sql, &block)
132
+ yield({:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7})
133
+ end
134
+ results = ds.all
135
+ results.length.should == 1
136
+ results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}}
137
+
138
+ ds = @ds1.graph(@ds2, :x=>:id).graph(@ds3, :id=>:graph_id)
139
+ def ds.fetch_rows(sql, &block)
140
+ yield({:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graphs_id=>8, :name=>9, :graphs_x=>10, :graphs_y=>11, :graphs_lines_x=>12})
141
+ end
142
+ results = ds.all
143
+ results.length.should == 1
144
+ results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>{:id=>8, :name=>9, :x=>10, :y=>11, :lines_x=>12}}
145
+
146
+ ds = @ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y=>:points__id}, :table_alias=>:graph)
147
+ def ds.fetch_rows(sql, &block)
148
+ yield({:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graph_id_0=>8, :graph_x=>9, :graph_y=>10, :graph_graph_id=>11})
149
+ end
150
+ results = ds.all
151
+ results.length.should == 1
152
+ results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graph=>{:id=>8, :x=>9, :y=>10, :graph_id=>11}}
153
+ end
154
+
155
+ it "#graph_each should not included tables graphed with the :select option in the result set" do
156
+ ds = @ds1.graph(:lines, {:x=>:id}, :select=>false).graph(:graphs, :id=>:graph_id)
157
+ def ds.fetch_rows(sql, &block)
158
+ yield({:id=>1,:x=>2,:y=>3,:graphs_id=>8, :name=>9, :graphs_x=>10, :graphs_y=>11, :lines_x=>12})
159
+ end
160
+ results = ds.all
161
+ results.length.should == 1
162
+ results.first.should == {:points=>{:id=>1, :x=>2, :y=>3}, :graphs=>{:id=>8, :name=>9, :x=>10, :y=>11, :lines_x=>12}}
163
+ end
164
+
165
+ it "#graph_each should only include the columns selected with #set_graph_aliases, if called" do
166
+ ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y])
167
+ def ds.fetch_rows(sql, &block)
168
+ yield({:x=>2,:y=>3})
169
+ end
170
+ results = ds.all
171
+ results.length.should == 1
172
+ results.first.should == {:points=>{:x=>2}, :lines=>{:y=>3}}
173
+
174
+ ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x])
175
+ def ds.fetch_rows(sql, &block)
176
+ yield({:x=>2})
177
+ end
178
+ results = ds.all
179
+ results.length.should == 1
180
+ results.first.should == {:points=>{:x=>2}, :lines=>{}}
181
+ end
182
+
183
+ it "#graph_each should run the row_proc and transform for graphed datasets" do
184
+ @ds1.row_proc = proc{|h| h.keys.each{|k| h[k] *= 2}; h}
185
+ @ds2.row_proc = proc{|h| h.keys.each{|k| h[k] *= 3}; h}
186
+ @ds1.transform(:x=>[
187
+ proc{|v| 123},
188
+ proc{|v| 123}
189
+ ])
190
+ @ds2.transform(:x=>[
191
+ proc{|v| 321},
192
+ proc{|v| 321}
193
+ ])
194
+ ds = @ds1.graph(@ds2, :x=>:id)
195
+ def ds.fetch_rows(sql, &block)
196
+ yield({:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7})
197
+ end
198
+ results = ds.all
199
+ results.length.should == 1
200
+ results.first.should == {:points=>{:id=>2, :x=>246, :y=>6}, :lines=>{:id=>12, :x=>963, :y=>18, :graph_id=>21}}
201
+ end
202
+ end