sequel 3.30.0 → 3.31.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +40 -0
- data/Rakefile +12 -2
- data/doc/association_basics.rdoc +28 -0
- data/doc/dataset_filtering.rdoc +8 -0
- data/doc/opening_databases.rdoc +1 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/lib/sequel/adapters/jdbc.rb +7 -6
- data/lib/sequel/adapters/jdbc/derby.rb +5 -0
- data/lib/sequel/adapters/jdbc/h2.rb +6 -1
- data/lib/sequel/adapters/mock.rb +21 -2
- data/lib/sequel/adapters/shared/db2.rb +10 -0
- data/lib/sequel/adapters/shared/mssql.rb +40 -5
- data/lib/sequel/adapters/shared/mysql.rb +19 -2
- data/lib/sequel/adapters/shared/oracle.rb +13 -1
- data/lib/sequel/adapters/shared/postgres.rb +52 -8
- data/lib/sequel/adapters/shared/sqlite.rb +4 -3
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/database/schema_generator.rb +9 -2
- data/lib/sequel/dataset/actions.rb +37 -19
- data/lib/sequel/dataset/features.rb +10 -0
- data/lib/sequel/dataset/prepared_statements.rb +0 -10
- data/lib/sequel/dataset/query.rb +13 -1
- data/lib/sequel/dataset/sql.rb +6 -1
- data/lib/sequel/model/associations.rb +14 -4
- data/lib/sequel/model/base.rb +10 -0
- data/lib/sequel/plugins/serialization.rb +82 -43
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +46 -0
- data/spec/adapters/mysql_spec.rb +3 -0
- data/spec/adapters/postgres_spec.rb +61 -24
- data/spec/core/database_spec.rb +31 -18
- data/spec/core/dataset_spec.rb +90 -13
- data/spec/core/mock_adapter_spec.rb +37 -0
- data/spec/extensions/instance_filters_spec.rb +1 -0
- data/spec/extensions/nested_attributes_spec.rb +1 -1
- data/spec/extensions/serialization_spec.rb +49 -5
- data/spec/extensions/sharding_spec.rb +1 -1
- data/spec/integration/associations_test.rb +15 -0
- data/spec/integration/dataset_test.rb +71 -0
- data/spec/integration/prepared_statement_test.rb +8 -0
- data/spec/model/association_reflection_spec.rb +27 -0
- data/spec/model/associations_spec.rb +18 -3
- data/spec/model/base_spec.rb +20 -0
- data/spec/model/eager_loading_spec.rb +21 -0
- metadata +4 -2
@@ -39,6 +39,12 @@ describe "Simple Dataset operations" do
|
|
39
39
|
@ds.filter(:id=>2).first[:number].should == 20
|
40
40
|
end
|
41
41
|
|
42
|
+
specify "should have insert_multiple return primary key values" do
|
43
|
+
@ds.insert_multiple([{:number=>20}, {:number=>30}]).should == [2, 3]
|
44
|
+
@ds.filter(:id=>2).get(:number).should == 20
|
45
|
+
@ds.filter(:id=>3).get(:number).should == 30
|
46
|
+
end
|
47
|
+
|
42
48
|
specify "should join correctly" do
|
43
49
|
@ds.join(:items___b, :id=>:id).select_all(:items).all.should == [{:id=>1, :number=>10}]
|
44
50
|
end
|
@@ -713,6 +719,55 @@ describe "Sequel::Dataset#import and #multi_insert" do
|
|
713
719
|
end
|
714
720
|
end
|
715
721
|
|
722
|
+
describe "Sequel::Dataset#import and #multi_insert :return=>:primary_key " do
|
723
|
+
before do
|
724
|
+
@db = INTEGRATION_DB
|
725
|
+
@db.create_table!(:imp){primary_key :id; Integer :i}
|
726
|
+
@ds = @db[:imp]
|
727
|
+
end
|
728
|
+
after do
|
729
|
+
@db.drop_table(:imp)
|
730
|
+
end
|
731
|
+
|
732
|
+
specify "should return primary key values " do
|
733
|
+
@ds.multi_insert([{:i=>10}, {:i=>20}, {:i=>30}], :return=>:primary_key).should == [1, 2, 3]
|
734
|
+
@ds.import([:i], [[40], [50], [60]], :return=>:primary_key).should == [4, 5, 6]
|
735
|
+
@ds.order(:id).map([:id, :i]).should == [[1, 10], [2, 20], [3, 30], [4, 40], [5, 50], [6, 60]]
|
736
|
+
end
|
737
|
+
|
738
|
+
specify "should return primary key values when :slice is used" do
|
739
|
+
@ds.multi_insert([{:i=>10}, {:i=>20}, {:i=>30}], :return=>:primary_key, :slice=>2).should == [1, 2, 3]
|
740
|
+
@ds.import([:i], [[40], [50], [60]], :return=>:primary_key, :slice=>2).should == [4, 5, 6]
|
741
|
+
@ds.order(:id).map([:id, :i]).should == [[1, 10], [2, 20], [3, 30], [4, 40], [5, 50], [6, 60]]
|
742
|
+
end
|
743
|
+
end
|
744
|
+
|
745
|
+
describe "Sequel::Dataset convenience methods" do
|
746
|
+
before(:all) do
|
747
|
+
@db = INTEGRATION_DB
|
748
|
+
@db.create_table!(:a){Integer :a; Integer :b; Integer :c}
|
749
|
+
@ds = @db[:a]
|
750
|
+
@ds.insert(1, 3, 5)
|
751
|
+
@ds.insert(1, 3, 6)
|
752
|
+
@ds.insert(1, 4, 5)
|
753
|
+
@ds.insert(2, 3, 5)
|
754
|
+
@ds.insert(2, 4, 6)
|
755
|
+
end
|
756
|
+
after(:all) do
|
757
|
+
@db.drop_table(:a)
|
758
|
+
end
|
759
|
+
|
760
|
+
it "#group_rollup should include hierarchy of groupings" do
|
761
|
+
@ds.group_by(:a).group_rollup.select_map([:a, :sum.sql_function(:b).cast(Integer).as(:b), :sum.sql_function(:c).cast(Integer).as(:c)]).sort_by{|x| x.inspect}.should == [[1, 10, 16], [2, 7, 11], [nil, 17, 27]]
|
762
|
+
@ds.group_by(:a, :b).group_rollup.select_map([:a, :b, :sum.sql_function(:c).cast(Integer).as(:c)]).sort_by{|x| x.inspect}.should == [[1, 3, 11], [1, 4, 5], [1, nil, 16], [2, 3, 5], [2, 4, 6], [2, nil, 11], [nil, nil, 27]]
|
763
|
+
end if INTEGRATION_DB.dataset.supports_group_rollup?
|
764
|
+
|
765
|
+
it "#group_cube should include all combinations of groupings" do
|
766
|
+
@ds.group_by(:a).group_cube.select_map([:a, :sum.sql_function(:b).cast(Integer).as(:b), :sum.sql_function(:c).cast(Integer).as(:c)]).sort_by{|x| x.inspect}.should == [[1, 10, 16], [2, 7, 11], [nil, 17, 27]]
|
767
|
+
@ds.group_by(:a, :b).group_cube.select_map([:a, :b, :sum.sql_function(:c).cast(Integer).as(:c)]).sort_by{|x| x.inspect}.should == [[1, 3, 11], [1, 4, 5], [1, nil, 16], [2, 3, 5], [2, 4, 6], [2, nil, 11], [nil, 3, 16], [nil, 4, 11], [nil, nil, 27]]
|
768
|
+
end if INTEGRATION_DB.dataset.supports_group_cube?
|
769
|
+
end
|
770
|
+
|
716
771
|
describe "Sequel::Dataset convenience methods" do
|
717
772
|
before(:all) do
|
718
773
|
@db = INTEGRATION_DB
|
@@ -738,6 +793,22 @@ describe "Sequel::Dataset convenience methods" do
|
|
738
793
|
@ds.empty?.should == false
|
739
794
|
end
|
740
795
|
|
796
|
+
it "#empty? should work correctly for datasets with limits" do
|
797
|
+
ds = @ds.limit(1)
|
798
|
+
ds.empty?.should == true
|
799
|
+
ds.insert(20, 10)
|
800
|
+
ds.empty?.should == false
|
801
|
+
end
|
802
|
+
|
803
|
+
it "#empty? should work correctly for datasets with limits and offsets" do
|
804
|
+
ds = @ds.limit(1, 1)
|
805
|
+
ds.empty?.should == true
|
806
|
+
ds.insert(20, 10)
|
807
|
+
ds.empty?.should == true
|
808
|
+
ds.insert(20, 10)
|
809
|
+
ds.empty?.should == false
|
810
|
+
end
|
811
|
+
|
741
812
|
it "#group_and_count should return a grouping by count" do
|
742
813
|
@ds.group_and_count(:a).order(:count).all.should == []
|
743
814
|
@ds.insert(20, 10)
|
@@ -66,6 +66,10 @@ describe "Prepared Statements and Bound Arguments" do
|
|
66
66
|
@ds.filter(:id=>:$i).filter(:numb=>@ds.select(:numb).filter(:numb=>:$n)).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :numb=>10}]
|
67
67
|
end
|
68
68
|
|
69
|
+
specify "should support subselects with exists with call" do
|
70
|
+
@ds.filter(:id=>:$i).filter(@ds.select(:numb).filter(:numb=>:$n).exists).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).should == [{:id=>1, :numb=>10}]
|
71
|
+
end
|
72
|
+
|
69
73
|
specify "should support subselects with literal strings with call" do
|
70
74
|
@ds.filter(:id=>:$i, :numb=>@ds.select(:numb).filter("numb = ?", :$n)).call(:select, :n=>10, :i=>1).should == [{:id=>1, :numb=>10}]
|
71
75
|
end
|
@@ -151,6 +155,10 @@ describe "Prepared Statements and Bound Arguments" do
|
|
151
155
|
@ds.filter(:id=>:$i).filter(:numb=>@ds.select(:numb).filter(:numb=>:$n)).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :numb=>10}]
|
152
156
|
end
|
153
157
|
|
158
|
+
specify "should support subselects with exists with prepare" do
|
159
|
+
@ds.filter(:id=>:$i).filter(@ds.select(:numb).filter(:numb=>:$n).exists).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).should == [{:id=>1, :numb=>10}]
|
160
|
+
end
|
161
|
+
|
154
162
|
specify "should support subselects with literal strings with prepare" do
|
155
163
|
@ds.filter(:id=>:$i, :numb=>@ds.select(:numb).filter("numb = ?", :$n)).prepare(:select, :seq_select).call(:n=>10, :i=>1).should == [{:id=>1, :numb=>10}]
|
156
164
|
end
|
@@ -187,6 +187,33 @@ describe Sequel::Model::Associations::AssociationReflection, "#associated_object
|
|
187
187
|
end
|
188
188
|
end
|
189
189
|
|
190
|
+
describe Sequel::Model::Associations::AssociationReflection do
|
191
|
+
before do
|
192
|
+
@c = Class.new(Sequel::Model(:foo))
|
193
|
+
@c.meta_def(:name){"C"}
|
194
|
+
end
|
195
|
+
|
196
|
+
it "one_to_many #qualified_primary_key should be a qualified version of the primary key" do
|
197
|
+
@c.one_to_many :cs, :class=>@c
|
198
|
+
@c.dataset.literal(@c.association_reflection(:cs).qualified_primary_key).should == 'foo.id'
|
199
|
+
end
|
200
|
+
|
201
|
+
it "many_to_many #associated_key_column should be the left key" do
|
202
|
+
@c.many_to_many :cs, :class=>@c
|
203
|
+
@c.association_reflection(:cs).associated_key_column.should == :c_id
|
204
|
+
end
|
205
|
+
|
206
|
+
it "many_to_many #qualified_right_key should be a qualified version of the primary key" do
|
207
|
+
@c.many_to_many :cs, :class=>@c, :right_key=>:c2_id
|
208
|
+
@c.dataset.literal(@c.association_reflection(:cs).qualified_right_key).should == 'cs_cs.c2_id'
|
209
|
+
end
|
210
|
+
|
211
|
+
it "many_to_many #qualified_right_primary_key should be a qualified version of the primary key" do
|
212
|
+
@c.many_to_many :cs, :class=>@c
|
213
|
+
@c.dataset.literal(@c.association_reflection(:cs).qualified_right_primary_key).should == 'foo.id'
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
190
217
|
describe Sequel::Model::Associations::AssociationReflection, "#remove_before_destroy?" do
|
191
218
|
before do
|
192
219
|
@c = Class.new(Sequel::Model(:foo))
|
@@ -148,6 +148,21 @@ describe Sequel::Model, "many_to_one" do
|
|
148
148
|
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 234) LIMIT 1"]
|
149
149
|
end
|
150
150
|
|
151
|
+
it "should allow association with the same name as the key if :key_alias is given" do
|
152
|
+
@c2.def_column_alias(:parent_id_id, :parent_id)
|
153
|
+
@c2.many_to_one :parent_id, :key_column=>:parent_id, :class => @c2
|
154
|
+
d = @c2.load(:id => 1, :parent_id => 234)
|
155
|
+
d.parent_id_dataset.sql.should == "SELECT * FROM nodes WHERE (nodes.id = 234) LIMIT 1"
|
156
|
+
d.parent_id.should == @c2.load(:x => 1, :id => 1)
|
157
|
+
d.parent_id_id.should == 234
|
158
|
+
d[:parent_id].should == 234
|
159
|
+
MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (nodes.id = 234) LIMIT 1"]
|
160
|
+
|
161
|
+
d.parent_id_id = 3
|
162
|
+
d.parent_id_id.should == 3
|
163
|
+
d[:parent_id].should == 3
|
164
|
+
end
|
165
|
+
|
151
166
|
it "should use implicit class if omitted" do
|
152
167
|
begin
|
153
168
|
class ::ParParent < Sequel::Model; end
|
@@ -1181,7 +1196,7 @@ describe Sequel::Model, "one_to_many" do
|
|
1181
1196
|
a = @c1.load(:id => 2345, :node_id => 1234)
|
1182
1197
|
a.should == n.remove_attribute(a)
|
1183
1198
|
a.values.should == {:node_id => nil, :id => 2345}
|
1184
|
-
MODEL_DB.sqls.should == ["SELECT 1 FROM attributes WHERE ((attributes.node_id = 1234) AND (id = 2345)) LIMIT 1", 'UPDATE attributes SET node_id = NULL WHERE (id = 2345)']
|
1199
|
+
MODEL_DB.sqls.should == ["SELECT 1 AS one FROM attributes WHERE ((attributes.node_id = 1234) AND (id = 2345)) LIMIT 1", 'UPDATE attributes SET node_id = NULL WHERE (id = 2345)']
|
1185
1200
|
end
|
1186
1201
|
|
1187
1202
|
it "should have the remove_ method raise an error if the passed object is not already associated" do
|
@@ -1191,7 +1206,7 @@ describe Sequel::Model, "one_to_many" do
|
|
1191
1206
|
a = @c1.load(:id => 2345, :node_id => 1234)
|
1192
1207
|
@c1.dataset._fetch = []
|
1193
1208
|
proc{n.remove_attribute(a)}.should raise_error(Sequel::Error)
|
1194
|
-
MODEL_DB.sqls.should == ["SELECT 1 FROM attributes WHERE ((attributes.node_id = 1234) AND (id = 2345)) LIMIT 1"]
|
1209
|
+
MODEL_DB.sqls.should == ["SELECT 1 AS one FROM attributes WHERE ((attributes.node_id = 1234) AND (id = 2345)) LIMIT 1"]
|
1195
1210
|
end
|
1196
1211
|
|
1197
1212
|
it "should accept a hash for the add_ method and create a new record" do
|
@@ -1287,7 +1302,7 @@ describe Sequel::Model, "one_to_many" do
|
|
1287
1302
|
n.remove_attribute(a).should == a
|
1288
1303
|
sqls = MODEL_DB.sqls
|
1289
1304
|
sqls.pop.should =~ /UPDATE attributes SET (node_id|y) = NULL, (node_id|y) = NULL WHERE \(id = 2345\)/
|
1290
|
-
sqls.should == ["SELECT 1 FROM attributes WHERE ((attributes.node_id = 1234) AND (attributes.y = 5) AND (id = 2345)) LIMIT 1"]
|
1305
|
+
sqls.should == ["SELECT 1 AS one FROM attributes WHERE ((attributes.node_id = 1234) AND (attributes.y = 5) AND (id = 2345)) LIMIT 1"]
|
1291
1306
|
end
|
1292
1307
|
|
1293
1308
|
it "should accept a array of composite primary key values for the remove_ method and remove an existing record" do
|
data/spec/model/base_spec.rb
CHANGED
@@ -35,6 +35,26 @@ describe "Model attribute setters" do
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
describe "Model.def_column_alias" do
|
39
|
+
before do
|
40
|
+
@o = Class.new(Sequel::Model(:items)) do
|
41
|
+
columns :id
|
42
|
+
def_column_alias(:id2, :id)
|
43
|
+
end.load(:id=>1)
|
44
|
+
MODEL_DB.reset
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should create an getter alias for the column" do
|
48
|
+
@o.id2.should == 1
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should create an setter alias for the column" do
|
52
|
+
@o.id2 = 2
|
53
|
+
@o.id2.should == 2
|
54
|
+
@o.values.should == {:id => 2}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
38
58
|
describe Sequel::Model, "dataset" do
|
39
59
|
before do
|
40
60
|
@a = Class.new(Sequel::Model(:items))
|
@@ -102,6 +102,16 @@ describe Sequel::Model, "#eager" do
|
|
102
102
|
MODEL_DB.sqls.should == []
|
103
103
|
end
|
104
104
|
|
105
|
+
it "should eagerly load a single many_to_one association with the same name as the column" do
|
106
|
+
EagerAlbum.def_column_alias(:band_id_id, :band_id)
|
107
|
+
EagerAlbum.many_to_one :band_id, :key_column=>:band_id, :class=>EagerBand
|
108
|
+
a = EagerAlbum.eager(:band_id).all
|
109
|
+
MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT * FROM bands WHERE (bands.id IN (2))']
|
110
|
+
a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
|
111
|
+
a.first.band_id.should == EagerBand.load(:id=>2)
|
112
|
+
MODEL_DB.sqls.should == []
|
113
|
+
end
|
114
|
+
|
105
115
|
it "should eagerly load a single one_to_one association" do
|
106
116
|
EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id
|
107
117
|
a = EagerAlbum.eager(:track).all
|
@@ -757,6 +767,17 @@ describe Sequel::Model, "#eager_graph" do
|
|
757
767
|
a.first.band.should == GraphBand.load(:id => 2, :vocalist_id=>3)
|
758
768
|
end
|
759
769
|
|
770
|
+
it "should eagerly load a single many_to_one association with the same name as a column" do
|
771
|
+
GraphAlbum.def_column_alias(:band_id_id, :band_id)
|
772
|
+
GraphAlbum.many_to_one :band_id, :key_column=>:band_id, :class=>GraphBand
|
773
|
+
ds = GraphAlbum.eager_graph(:band_id)
|
774
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, band_id.id AS band_id_id, band_id.vocalist_id FROM albums LEFT OUTER JOIN bands AS band_id ON (band_id.id = albums.band_id)'
|
775
|
+
ds._fetch = {:id=>1, :band_id=>2, :band_id_id=>2, :vocalist_id=>3}
|
776
|
+
a = ds.all
|
777
|
+
a.should == [GraphAlbum.load(:id => 1, :band_id => 2)]
|
778
|
+
a.first.band_id.should == GraphBand.load(:id => 2, :vocalist_id=>3)
|
779
|
+
end
|
780
|
+
|
760
781
|
it "should eagerly load a single one_to_one association" do
|
761
782
|
GraphAlbum.one_to_one :track, :class=>'GraphTrack', :key=>:album_id
|
762
783
|
ds = GraphAlbum.eager_graph(:track)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.31.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-01-03 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: The Database Toolkit for Ruby
|
15
15
|
email: code@jeremyevans.net
|
@@ -89,6 +89,7 @@ extra_rdoc_files:
|
|
89
89
|
- doc/release_notes/3.28.0.txt
|
90
90
|
- doc/release_notes/3.29.0.txt
|
91
91
|
- doc/release_notes/3.30.0.txt
|
92
|
+
- doc/release_notes/3.31.0.txt
|
92
93
|
files:
|
93
94
|
- MIT-LICENSE
|
94
95
|
- CHANGELOG
|
@@ -156,6 +157,7 @@ files:
|
|
156
157
|
- doc/release_notes/3.28.0.txt
|
157
158
|
- doc/release_notes/3.29.0.txt
|
158
159
|
- doc/release_notes/3.30.0.txt
|
160
|
+
- doc/release_notes/3.31.0.txt
|
159
161
|
- doc/sharding.rdoc
|
160
162
|
- doc/sql.rdoc
|
161
163
|
- doc/validations.rdoc
|