sequel 0.3.0.1 → 0.3.1
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 +26 -0
- data/Rakefile +2 -2
- data/lib/sequel/dataset.rb +1 -0
- data/lib/sequel/dataset/sql.rb +8 -8
- data/lib/sequel/model.rb +205 -141
- data/lib/sequel/model/record.rb +41 -6
- data/lib/sequel/model/relations.rb +97 -21
- data/lib/sequel/mysql.rb +1 -0
- data/lib/sequel/oracle.rb +109 -0
- data/lib/sequel/postgres.rb +9 -2
- data/lib/sequel/schema/schema_sql.rb +4 -1
- data/spec/adapters/mysql_spec.rb +7 -0
- data/spec/adapters/sqlite_spec.rb +3 -3
- data/spec/array_keys_spec.rb +2 -2
- data/spec/connection_pool_spec.rb +1 -1
- data/spec/database_spec.rb +1 -1
- data/spec/dataset_spec.rb +20 -4
- data/spec/migration_spec.rb +1 -1
- data/spec/model_spec.rb +240 -32
- data/spec/schema_spec.rb +13 -0
- data/spec/spec_helper.rb +1 -0
- metadata +20 -20
data/spec/database_spec.rb
CHANGED
@@ -265,7 +265,7 @@ context "Database#table_exists?" do
|
|
265
265
|
@db.table_exists?(:c).should be_false
|
266
266
|
end
|
267
267
|
|
268
|
-
specify "should
|
268
|
+
specify "should otherwise try to select the first record from the table's dataset" do
|
269
269
|
@db2.table_exists?(:a).should be_false
|
270
270
|
@db2.table_exists?(:b).should be_true
|
271
271
|
end
|
data/spec/dataset_spec.rb
CHANGED
@@ -119,6 +119,22 @@ context "A simple dataset" do
|
|
119
119
|
@dataset.insert_sql(v).should == "INSERT INTO test DEFAULT VALUES;"
|
120
120
|
end
|
121
121
|
|
122
|
+
specify "should format an insert statement with a model instance" do
|
123
|
+
dbb = Sequel::Database.new
|
124
|
+
|
125
|
+
@c = Class.new(Sequel::Model) do
|
126
|
+
db = dbb
|
127
|
+
set_dataset Sequel::Dataset.new(dbb)
|
128
|
+
end
|
129
|
+
|
130
|
+
v = @c.new(:a => 1)
|
131
|
+
|
132
|
+
@dataset.insert_sql(v).should == "INSERT INTO test (a) VALUES (1);"
|
133
|
+
|
134
|
+
v = @c.new({})
|
135
|
+
@dataset.insert_sql(v).should == "INSERT INTO test DEFAULT VALUES;"
|
136
|
+
end
|
137
|
+
|
122
138
|
specify "should format an insert statement with an arbitrary value" do
|
123
139
|
@dataset.insert_sql(123).should == "INSERT INTO test VALUES (123);"
|
124
140
|
end
|
@@ -425,7 +441,7 @@ context "Dataset#exclude" do
|
|
425
441
|
"SELECT * FROM test WHERE (NOT (region = 'Asia' AND name = 'Japan'))"
|
426
442
|
end
|
427
443
|
|
428
|
-
specify "should
|
444
|
+
specify "should correctly parenthesize when it is used twice" do
|
429
445
|
@dataset.exclude(:region => 'Asia').exclude(:name => 'Japan').select_sql.should ==
|
430
446
|
"SELECT * FROM test WHERE (NOT (region = 'Asia')) AND (NOT (name = 'Japan'))"
|
431
447
|
end
|
@@ -858,7 +874,7 @@ context "Dataset#count" do
|
|
858
874
|
@dataset = @c.new(nil).from(:test)
|
859
875
|
end
|
860
876
|
|
861
|
-
specify "should format SQL
|
877
|
+
specify "should format SQL properly" do
|
862
878
|
@dataset.count.should == 1
|
863
879
|
@c.sql.should == 'SELECT COUNT(*) FROM test'
|
864
880
|
end
|
@@ -918,7 +934,7 @@ context "Dataset#join_table" do
|
|
918
934
|
'SELECT * FROM items INNER JOIN b ON (b.items_id = items.id) LEFT OUTER JOIN c ON (c.b_id = b.id)'
|
919
935
|
end
|
920
936
|
|
921
|
-
specify "should use id as implicit relation primary key if
|
937
|
+
specify "should use id as implicit relation primary key if omitted" do
|
922
938
|
@d.join_table(:left_outer, :categories, :category_id).sql.should ==
|
923
939
|
@d.join_table(:left_outer, :categories, :category_id => :id).sql
|
924
940
|
|
@@ -1725,7 +1741,7 @@ context "Dataset#multi_insert" do
|
|
1725
1741
|
]
|
1726
1742
|
end
|
1727
1743
|
|
1728
|
-
specify "should accept the commit_every option for
|
1744
|
+
specify "should accept the commit_every option for committing every x records" do
|
1729
1745
|
@ds.multi_insert(@list, :commit_every => 2)
|
1730
1746
|
@db.sqls.should == [
|
1731
1747
|
'BEGIN;',
|
data/spec/migration_spec.rb
CHANGED
@@ -212,7 +212,7 @@ context "Sequel::Migrator" do
|
|
212
212
|
Sequel::Migrator.get_current_migration_version(@db).should == 4321
|
213
213
|
end
|
214
214
|
|
215
|
-
specify "should set the migration
|
215
|
+
specify "should set the migration version stored in the database" do
|
216
216
|
Sequel::Migrator.get_current_migration_version(@db).should == 0
|
217
217
|
Sequel::Migrator.set_current_migration_version(@db, 6666)
|
218
218
|
Sequel::Migrator.get_current_migration_version(@db).should == 6666
|
data/spec/model_spec.rb
CHANGED
@@ -28,7 +28,6 @@ describe Sequel::Model do
|
|
28
28
|
end
|
29
29
|
|
30
30
|
describe Sequel::Model, 'w/ primary key' do
|
31
|
-
|
32
31
|
it "should default to ':id'" do
|
33
32
|
model_a = Class.new Sequel::Model
|
34
33
|
model_a.primary_key.should be_equal(:id)
|
@@ -48,11 +47,9 @@ describe Sequel::Model, 'w/ primary key' do
|
|
48
47
|
model_a = Class.new(Sequel::Model) { set_primary_key [:a, :b] }
|
49
48
|
model_a.primary_key.should be_eql([:a, :b])
|
50
49
|
end
|
51
|
-
|
52
50
|
end
|
53
51
|
|
54
52
|
describe Sequel::Model, 'w/o primary key' do
|
55
|
-
|
56
53
|
it "should return nil for primary key" do
|
57
54
|
Class.new(Sequel::Model) { no_primary_key }.primary_key.should be_nil
|
58
55
|
end
|
@@ -61,7 +58,6 @@ describe Sequel::Model, 'w/o primary key' do
|
|
61
58
|
instance = Class.new(Sequel::Model) { no_primary_key }.new
|
62
59
|
proc { instance.this }.should raise_error(SequelError)
|
63
60
|
end
|
64
|
-
|
65
61
|
end
|
66
62
|
|
67
63
|
describe Sequel::Model, 'with this' do
|
@@ -256,13 +252,13 @@ context "A model class" do
|
|
256
252
|
specify "should be able to create rows in the associated table" do
|
257
253
|
o = @c.create(:x => 1)
|
258
254
|
o.class.should == @c
|
259
|
-
MODEL_DB.sqls.should == ['INSERT INTO items (x) VALUES (1);']
|
255
|
+
MODEL_DB.sqls.should == ['INSERT INTO items (x) VALUES (1);', "SELECT * FROM items WHERE (id IN ('INSERT INTO items (x) VALUES (1);')) LIMIT 1"]
|
260
256
|
end
|
261
257
|
|
262
258
|
specify "should be able to create rows without any values specified" do
|
263
259
|
o = @c.create
|
264
260
|
o.class.should == @c
|
265
|
-
MODEL_DB.sqls.should == ['INSERT INTO items DEFAULT VALUES;']
|
261
|
+
MODEL_DB.sqls.should == ["INSERT INTO items DEFAULT VALUES;", "SELECT * FROM items WHERE (id IN ('INSERT INTO items DEFAULT VALUES;')) LIMIT 1"]
|
266
262
|
end
|
267
263
|
end
|
268
264
|
|
@@ -404,13 +400,6 @@ context "Model attribute accessors" do
|
|
404
400
|
[:id, :x, :y]
|
405
401
|
end
|
406
402
|
end
|
407
|
-
|
408
|
-
ds = @c.dataset
|
409
|
-
ds.extend(Module.new {
|
410
|
-
def columns
|
411
|
-
[:id, :x, :y]
|
412
|
-
end
|
413
|
-
})
|
414
403
|
end
|
415
404
|
|
416
405
|
specify "should be created dynamically" do
|
@@ -433,7 +422,26 @@ context "Model attribute accessors" do
|
|
433
422
|
proc {o.xx}.should raise_error(SequelError)
|
434
423
|
|
435
424
|
proc {o.x = 3}.should_not raise_error
|
436
|
-
proc {o.yy = 4}.should raise_error
|
425
|
+
proc {o.yy = 4}.should raise_error(SequelError)
|
426
|
+
|
427
|
+
proc {o.yy?}.should raise_error(NoMethodError)
|
428
|
+
end
|
429
|
+
|
430
|
+
specify "should not raise for a column not in the dataset, but for which there's a value" do
|
431
|
+
o = @c.new
|
432
|
+
|
433
|
+
proc {o.xx}.should raise_error(SequelError)
|
434
|
+
proc {o.yy}.should raise_error(SequelError)
|
435
|
+
|
436
|
+
o.values[:xx] = 123
|
437
|
+
o.values[:yy] = nil
|
438
|
+
|
439
|
+
proc {o.xx; o.yy}.should_not raise_error(SequelError)
|
440
|
+
|
441
|
+
o.xx.should == 123
|
442
|
+
o.yy.should == nil
|
443
|
+
|
444
|
+
proc {o.xx = 3}.should raise_error(SequelError)
|
437
445
|
end
|
438
446
|
end
|
439
447
|
|
@@ -482,8 +490,8 @@ context "Model.after_create" do
|
|
482
490
|
end
|
483
491
|
|
484
492
|
n = @c.create(:x => 1)
|
485
|
-
MODEL_DB.sqls.should == [
|
486
|
-
s.should == [
|
493
|
+
MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1);", "SELECT * FROM items WHERE (id = 1) LIMIT 1"]
|
494
|
+
s.should == ["INSERT INTO items (x) VALUES (1);", "SELECT * FROM items WHERE (id = 1) LIMIT 1"]
|
487
495
|
end
|
488
496
|
|
489
497
|
specify "should allow calling save in the hook" do
|
@@ -494,7 +502,7 @@ context "Model.after_create" do
|
|
494
502
|
end
|
495
503
|
|
496
504
|
n = @c.create(:id => 1)
|
497
|
-
MODEL_DB.sqls.should == [
|
505
|
+
MODEL_DB.sqls.should == ["INSERT INTO items (id) VALUES (1);", "SELECT * FROM items WHERE (id = 1) LIMIT 1", "UPDATE items SET id = 2 WHERE (id = 1)"]
|
498
506
|
end
|
499
507
|
end
|
500
508
|
|
@@ -502,11 +510,7 @@ context "Model.subset" do
|
|
502
510
|
setup do
|
503
511
|
MODEL_DB.reset
|
504
512
|
|
505
|
-
@c = Class.new(Sequel::Model(:items))
|
506
|
-
def columns
|
507
|
-
[:id, :x, :y]
|
508
|
-
end
|
509
|
-
end
|
513
|
+
@c = Class.new(Sequel::Model(:items))
|
510
514
|
end
|
511
515
|
|
512
516
|
specify "should create a filter on the underlying dataset" do
|
@@ -532,11 +536,7 @@ context "Model.find" do
|
|
532
536
|
setup do
|
533
537
|
MODEL_DB.reset
|
534
538
|
|
535
|
-
@c = Class.new(Sequel::Model(:items))
|
536
|
-
def self.columns
|
537
|
-
[:name, :id]
|
538
|
-
end
|
539
|
-
end
|
539
|
+
@c = Class.new(Sequel::Model(:items))
|
540
540
|
|
541
541
|
$cache_dataset_row = {:name => 'sharon', :id => 1}
|
542
542
|
@dataset = @c.dataset
|
@@ -570,11 +570,7 @@ context "Model.[]" do
|
|
570
570
|
setup do
|
571
571
|
MODEL_DB.reset
|
572
572
|
|
573
|
-
@c = Class.new(Sequel::Model(:items))
|
574
|
-
def self.columns
|
575
|
-
[:name, :id]
|
576
|
-
end
|
577
|
-
end
|
573
|
+
@c = Class.new(Sequel::Model(:items))
|
578
574
|
|
579
575
|
$cache_dataset_row = {:name => 'sharon', :id => 1}
|
580
576
|
@dataset = @c.dataset
|
@@ -761,4 +757,216 @@ context "A cached model" do
|
|
761
757
|
"SELECT * FROM items WHERE (id = 1) LIMIT 1", \
|
762
758
|
"SELECT * FROM items WHERE (id = 4) LIMIT 1"]
|
763
759
|
end
|
760
|
+
end
|
761
|
+
|
762
|
+
context "Model.one_to_one" do
|
763
|
+
setup do
|
764
|
+
MODEL_DB.reset
|
765
|
+
|
766
|
+
@c1 = Class.new(Sequel::Model(:attributes)) do
|
767
|
+
end
|
768
|
+
|
769
|
+
@c2 = Class.new(Sequel::Model(:nodes)) do
|
770
|
+
end
|
771
|
+
|
772
|
+
@dataset = @c2.dataset
|
773
|
+
|
774
|
+
$sqls = []
|
775
|
+
@dataset.extend(Module.new {
|
776
|
+
def fetch_rows(sql)
|
777
|
+
$sqls << sql
|
778
|
+
yield({:hey => 1})
|
779
|
+
end
|
780
|
+
|
781
|
+
def update(values)
|
782
|
+
$sqls << update_sql(values)
|
783
|
+
end
|
784
|
+
})
|
785
|
+
end
|
786
|
+
|
787
|
+
specify "should use implicit key if omitted" do
|
788
|
+
@c2.one_to_one :parent, :from => @c2
|
789
|
+
|
790
|
+
d = @c2.new(:id => 1, :parent_id => 234)
|
791
|
+
p = d.parent
|
792
|
+
p.class.should == @c2
|
793
|
+
p.values.should == {:hey => 1}
|
794
|
+
|
795
|
+
$sqls.should == ["SELECT * FROM nodes WHERE (id = 234) LIMIT 1"]
|
796
|
+
end
|
797
|
+
|
798
|
+
specify "should use explicit key if given" do
|
799
|
+
@c2.one_to_one :parent, :from => @c2, :key => :blah
|
800
|
+
|
801
|
+
d = @c2.new(:id => 1, :blah => 567)
|
802
|
+
p = d.parent
|
803
|
+
p.class.should == @c2
|
804
|
+
p.values.should == {:hey => 1}
|
805
|
+
|
806
|
+
$sqls.should == ["SELECT * FROM nodes WHERE (id = 567) LIMIT 1"]
|
807
|
+
end
|
808
|
+
|
809
|
+
specify "should support plain dataset in the from option" do
|
810
|
+
@c2.one_to_one :parent, :from => MODEL_DB[:xyz]
|
811
|
+
|
812
|
+
d = @c2.new(:id => 1, :parent_id => 789)
|
813
|
+
p = d.parent
|
814
|
+
p.class.should == Hash
|
815
|
+
|
816
|
+
MODEL_DB.sqls.should == ["SELECT * FROM xyz WHERE (id = 789) LIMIT 1"]
|
817
|
+
end
|
818
|
+
|
819
|
+
specify "should support table name in the from option" do
|
820
|
+
@c2.one_to_one :parent, :from => :abc
|
821
|
+
|
822
|
+
d = @c2.new(:id => 1, :parent_id => 789)
|
823
|
+
p = d.parent
|
824
|
+
p.class.should == Hash
|
825
|
+
|
826
|
+
MODEL_DB.sqls.should == ["SELECT * FROM abc WHERE (id = 789) LIMIT 1"]
|
827
|
+
end
|
828
|
+
|
829
|
+
specify "should return nil if key value is nil" do
|
830
|
+
@c2.one_to_one :parent, :from => @c2
|
831
|
+
|
832
|
+
d = @c2.new(:id => 1)
|
833
|
+
d.parent.should == nil
|
834
|
+
end
|
835
|
+
|
836
|
+
specify "should define a setter method" do
|
837
|
+
@c2.one_to_one :parent, :from => @c2
|
838
|
+
|
839
|
+
d = @c2.new(:id => 1)
|
840
|
+
d.parent = {:id => 4321}
|
841
|
+
d.values.should == {:id => 1, :parent_id => 4321}
|
842
|
+
$sqls.last.should == "UPDATE nodes SET parent_id = 4321 WHERE (id = 1)"
|
843
|
+
|
844
|
+
d.parent = nil
|
845
|
+
d.values.should == {:id => 1, :parent_id => nil}
|
846
|
+
$sqls.last.should == "UPDATE nodes SET parent_id = NULL WHERE (id = 1)"
|
847
|
+
|
848
|
+
e = @c2.new(:id => 6677)
|
849
|
+
d.parent = e
|
850
|
+
d.values.should == {:id => 1, :parent_id => 6677}
|
851
|
+
$sqls.last.should == "UPDATE nodes SET parent_id = 6677 WHERE (id = 1)"
|
852
|
+
end
|
853
|
+
end
|
854
|
+
|
855
|
+
context "Model.one_to_many" do
|
856
|
+
setup do
|
857
|
+
MODEL_DB.reset
|
858
|
+
|
859
|
+
@c1 = Class.new(Sequel::Model(:attributes)) do
|
860
|
+
end
|
861
|
+
|
862
|
+
@c2 = Class.new(Sequel::Model(:nodes)) do
|
863
|
+
end
|
864
|
+
end
|
865
|
+
|
866
|
+
specify "should define a getter method" do
|
867
|
+
@c2.one_to_many :attributes, :from => @c1, :key => :node_id
|
868
|
+
|
869
|
+
n = @c2.new(:id => 1234)
|
870
|
+
a = n.attributes
|
871
|
+
a.should be_a_kind_of(Sequel::Dataset)
|
872
|
+
a.sql.should == 'SELECT * FROM attributes WHERE (node_id = 1234)'
|
873
|
+
end
|
874
|
+
|
875
|
+
specify "should support plain dataset in the from option" do
|
876
|
+
@c2.one_to_many :attributes, :from => MODEL_DB[:xyz], :key => :node_id
|
877
|
+
|
878
|
+
n = @c2.new(:id => 1234)
|
879
|
+
a = n.attributes
|
880
|
+
a.should be_a_kind_of(Sequel::Dataset)
|
881
|
+
a.sql.should == 'SELECT * FROM xyz WHERE (node_id = 1234)'
|
882
|
+
end
|
883
|
+
|
884
|
+
specify "should support table name in the from option" do
|
885
|
+
@c2.one_to_many :attributes, :from => :abc, :key => :node_id
|
886
|
+
|
887
|
+
n = @c2.new(:id => 1234)
|
888
|
+
a = n.attributes
|
889
|
+
a.should be_a_kind_of(Sequel::Dataset)
|
890
|
+
a.sql.should == 'SELECT * FROM abc WHERE (node_id = 1234)'
|
891
|
+
end
|
892
|
+
end
|
893
|
+
|
894
|
+
context "Model#pk" do
|
895
|
+
setup do
|
896
|
+
@m = Class.new(Sequel::Model)
|
897
|
+
end
|
898
|
+
|
899
|
+
specify "should be default return the value of the :id column" do
|
900
|
+
m = @m.new(:id => 111, :x => 2, :y => 3)
|
901
|
+
m.pk.should == 111
|
902
|
+
end
|
903
|
+
|
904
|
+
specify "should be return the primary key value for custom primary key" do
|
905
|
+
@m.set_primary_key :x
|
906
|
+
m = @m.new(:id => 111, :x => 2, :y => 3)
|
907
|
+
m.pk.should == 2
|
908
|
+
end
|
909
|
+
|
910
|
+
specify "should be return the primary key value for composite primary key" do
|
911
|
+
@m.set_primary_key [:y, :x]
|
912
|
+
m = @m.new(:id => 111, :x => 2, :y => 3)
|
913
|
+
m.pk.should == [3, 2]
|
914
|
+
end
|
915
|
+
|
916
|
+
specify "should raise if no primary key" do
|
917
|
+
@m.set_primary_key nil
|
918
|
+
m = @m.new(:id => 111, :x => 2, :y => 3)
|
919
|
+
proc {m.pk}.should raise_error(SequelError)
|
920
|
+
|
921
|
+
@m.no_primary_key
|
922
|
+
m = @m.new(:id => 111, :x => 2, :y => 3)
|
923
|
+
proc {m.pk}.should raise_error(SequelError)
|
924
|
+
end
|
925
|
+
end
|
926
|
+
|
927
|
+
context "Model#pk_hash" do
|
928
|
+
setup do
|
929
|
+
@m = Class.new(Sequel::Model)
|
930
|
+
end
|
931
|
+
|
932
|
+
specify "should be default return the value of the :id column" do
|
933
|
+
m = @m.new(:id => 111, :x => 2, :y => 3)
|
934
|
+
m.pk_hash.should == {:id => 111}
|
935
|
+
end
|
936
|
+
|
937
|
+
specify "should be return the primary key value for custom primary key" do
|
938
|
+
@m.set_primary_key :x
|
939
|
+
m = @m.new(:id => 111, :x => 2, :y => 3)
|
940
|
+
m.pk_hash.should == {:x => 2}
|
941
|
+
end
|
942
|
+
|
943
|
+
specify "should be return the primary key value for composite primary key" do
|
944
|
+
@m.set_primary_key [:y, :x]
|
945
|
+
m = @m.new(:id => 111, :x => 2, :y => 3)
|
946
|
+
m.pk_hash.should == {:y => 3, :x => 2}
|
947
|
+
end
|
948
|
+
|
949
|
+
specify "should raise if no primary key" do
|
950
|
+
@m.set_primary_key nil
|
951
|
+
m = @m.new(:id => 111, :x => 2, :y => 3)
|
952
|
+
proc {m.pk_hash}.should raise_error(SequelError)
|
953
|
+
|
954
|
+
@m.no_primary_key
|
955
|
+
m = @m.new(:id => 111, :x => 2, :y => 3)
|
956
|
+
proc {m.pk_hash}.should raise_error(SequelError)
|
957
|
+
end
|
958
|
+
end
|
959
|
+
|
960
|
+
context "A Model constructor" do
|
961
|
+
setup do
|
962
|
+
@m = Class.new(Sequel::Model)
|
963
|
+
end
|
964
|
+
|
965
|
+
specify "should accept a hash" do
|
966
|
+
m = @m.new(:a => 1, :b => 2)
|
967
|
+
m.values.should == {:a => 1, :b => 2}
|
968
|
+
m.should be_new
|
969
|
+
end
|
970
|
+
|
971
|
+
specify "should "
|
764
972
|
end
|
data/spec/schema_spec.rb
CHANGED
@@ -104,6 +104,19 @@ context "DB#create_table" do
|
|
104
104
|
@db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects);"]
|
105
105
|
end
|
106
106
|
|
107
|
+
specify "should accept foreign keys with arbitrary keys" do
|
108
|
+
@db.create_table(:cats) do
|
109
|
+
foreign_key :project_id, :table => :projects, :key => :id
|
110
|
+
end
|
111
|
+
@db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects(id));"]
|
112
|
+
|
113
|
+
@db.sqls.clear
|
114
|
+
@db.create_table(:cats) do
|
115
|
+
foreign_key :project_id, :table => :projects, :key => :zzz
|
116
|
+
end
|
117
|
+
@db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects(zzz));"]
|
118
|
+
end
|
119
|
+
|
107
120
|
specify "should accept foreign keys with ON DELETE clause" do
|
108
121
|
@db.create_table(:cats) do
|
109
122
|
foreign_key :project_id, :table => :projects, :on_delete => :restrict
|