sequel 3.30.0 → 3.31.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 +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
|