sequel_core 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|