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.
- data/CHANGELOG +74 -0
- data/COPYING +1 -0
- data/README +17 -6
- data/Rakefile +16 -21
- data/lib/sequel_core.rb +18 -28
- data/lib/sequel_core/adapters/ado.rb +3 -15
- data/lib/sequel_core/adapters/dbi.rb +1 -14
- data/lib/sequel_core/adapters/informix.rb +3 -3
- data/lib/sequel_core/adapters/jdbc.rb +2 -2
- data/lib/sequel_core/adapters/mysql.rb +39 -59
- data/lib/sequel_core/adapters/odbc.rb +18 -38
- data/lib/sequel_core/adapters/openbase.rb +1 -17
- data/lib/sequel_core/adapters/oracle.rb +1 -19
- data/lib/sequel_core/adapters/postgres.rb +20 -60
- data/lib/sequel_core/adapters/sqlite.rb +4 -8
- data/lib/sequel_core/connection_pool.rb +150 -0
- data/lib/sequel_core/core_ext.rb +41 -0
- data/lib/sequel_core/core_sql.rb +35 -38
- data/lib/sequel_core/database.rb +20 -17
- data/lib/sequel_core/dataset.rb +49 -80
- data/lib/sequel_core/dataset/callback.rb +11 -13
- data/lib/sequel_core/dataset/convenience.rb +18 -136
- data/lib/sequel_core/dataset/pagination.rb +81 -0
- data/lib/sequel_core/dataset/sequelizer.rb +5 -4
- data/lib/sequel_core/dataset/sql.rb +43 -33
- data/lib/sequel_core/deprecated.rb +200 -0
- data/lib/sequel_core/exceptions.rb +0 -14
- data/lib/sequel_core/object_graph.rb +199 -0
- data/lib/sequel_core/pretty_table.rb +27 -24
- data/lib/sequel_core/schema/generator.rb +16 -4
- data/lib/sequel_core/schema/sql.rb +5 -3
- data/lib/sequel_core/worker.rb +1 -1
- data/spec/adapters/informix_spec.rb +1 -47
- data/spec/adapters/mysql_spec.rb +85 -54
- data/spec/adapters/oracle_spec.rb +1 -57
- data/spec/adapters/postgres_spec.rb +66 -49
- data/spec/adapters/sqlite_spec.rb +4 -29
- data/spec/connection_pool_spec.rb +358 -0
- data/spec/core_sql_spec.rb +24 -19
- data/spec/database_spec.rb +13 -9
- data/spec/dataset_spec.rb +59 -78
- data/spec/object_graph_spec.rb +202 -0
- data/spec/pretty_table_spec.rb +1 -9
- data/spec/schema_generator_spec.rb +7 -1
- data/spec/schema_spec.rb +27 -0
- data/spec/sequelizer_spec.rb +2 -2
- data/spec/spec_helper.rb +4 -2
- metadata +16 -57
- data/lib/sequel_core/array_keys.rb +0 -322
- data/lib/sequel_core/model.rb +0 -8
- data/spec/array_keys_spec.rb +0 -682
data/spec/database_spec.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
135
|
+
specify "should format an insert statement with an object that respond_to? :values" do
|
146
136
|
dbb = Sequel::Database.new
|
147
137
|
|
148
|
-
|
149
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
704
|
+
@d.select(:test.*).sql.should ==
|
722
705
|
'SELECT test.* FROM test'
|
723
|
-
@d.select(:test__name.
|
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
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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
|
969
|
-
@dataset.
|
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
|
974
|
-
@dataset.
|
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.
|
1512
|
+
@d.literal(@c.last_dataset.opts[:order]).should == @d.literal([:a.desc])
|
1519
1513
|
|
1520
|
-
@d.order(:b.
|
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.
|
1518
|
+
@d.literal(@c.last_dataset.opts[:order]).should == @d.literal([:c.desc, :d.desc])
|
1525
1519
|
|
1526
|
-
@d.order(:e.
|
1527
|
-
@d.literal(@c.last_dataset.opts[:order]).should == @d.literal([:e, :f.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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 :
|
2622
|
+
attr_accessor :columns
|
2620
2623
|
|
2621
2624
|
def fetch_rows(sql, &block)
|
2622
|
-
@
|
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.
|
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
|
-
|
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
|