sequel 3.24.1 → 3.25.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 +28 -0
- data/doc/association_basics.rdoc +3 -3
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/migration.rdoc +6 -5
- data/doc/opening_databases.rdoc +8 -5
- data/doc/release_notes/3.25.0.txt +88 -0
- data/lib/sequel/adapters/jdbc.rb +2 -2
- data/lib/sequel/adapters/jdbc/postgresql.rb +6 -0
- data/lib/sequel/adapters/shared/postgres.rb +0 -5
- data/lib/sequel/adapters/tinytds.rb +1 -2
- data/lib/sequel/database/schema_generator.rb +6 -4
- data/lib/sequel/database/schema_methods.rb +17 -6
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/dataset/misc.rb +0 -9
- data/lib/sequel/dataset/query.rb +80 -21
- data/lib/sequel/extensions/migration.rb +1 -1
- data/lib/sequel/model/base.rb +15 -6
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/plugins/association_pks.rb +16 -0
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/mysql_spec.rb +7 -0
- data/spec/core/database_spec.rb +0 -295
- data/spec/core/dataset_spec.rb +70 -1
- data/spec/core/expression_filters_spec.rb +39 -0
- data/spec/core/schema_spec.rb +304 -0
- data/spec/core/spec_helper.rb +29 -0
- data/spec/extensions/association_pks_spec.rb +31 -0
- data/spec/extensions/schema_spec.rb +12 -20
- data/spec/integration/dataset_test.rb +17 -0
- data/spec/integration/prepared_statement_test.rb +15 -0
- data/spec/model/model_spec.rb +60 -0
- data/spec/model/plugins_spec.rb +17 -0
- data/spec/model/validations_spec.rb +11 -0
- metadata +7 -5
data/spec/core/spec_helper.rb
CHANGED
@@ -60,3 +60,32 @@ class SchemaDummyDatabase < Sequel::Database
|
|
60
60
|
@sqls << sql
|
61
61
|
end
|
62
62
|
end
|
63
|
+
|
64
|
+
class DummyDataset < Sequel::Dataset
|
65
|
+
def first
|
66
|
+
raise if @opts[:from] == [:a]
|
67
|
+
true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class DummyDatabase < Sequel::Database
|
72
|
+
attr_reader :sqls
|
73
|
+
|
74
|
+
def execute(sql, opts={})
|
75
|
+
@sqls ||= []
|
76
|
+
@sqls << sql
|
77
|
+
end
|
78
|
+
|
79
|
+
def transaction; yield; end
|
80
|
+
|
81
|
+
def dataset
|
82
|
+
DummyDataset.new(self)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class Dummy2Database < Sequel::Database
|
87
|
+
attr_reader :sql
|
88
|
+
def execute(sql); @sql = sql; end
|
89
|
+
def transaction; yield; end
|
90
|
+
end
|
91
|
+
|
@@ -89,4 +89,35 @@ describe "Sequel::Plugins::AssociationPks" do
|
|
89
89
|
@db.sqls[3].should == "COMMIT"
|
90
90
|
end
|
91
91
|
|
92
|
+
specify "should automatically convert keys to numbers if the primary key is an integer for one_to_many associations" do
|
93
|
+
@Album.db_schema[:id][:type] = :integer
|
94
|
+
@Artist.load(:id=>1).album_pks = %w'1 2'
|
95
|
+
@db.sqls.should == ["UPDATE albums SET artist_id = 1 WHERE (id IN (1, 2))",
|
96
|
+
"UPDATE albums SET artist_id = NULL WHERE ((albums.artist_id = 1) AND (id NOT IN (1, 2)))"]
|
97
|
+
end
|
98
|
+
|
99
|
+
specify "should not automatically convert keys if the primary key is not an integer for many_to_many associations" do
|
100
|
+
@Album.db_schema[:id][:type] = :string
|
101
|
+
@Artist.load(:id=>1).album_pks = %w'1 2'
|
102
|
+
@db.sqls.should == ["UPDATE albums SET artist_id = 1 WHERE (id IN ('1', '2'))",
|
103
|
+
"UPDATE albums SET artist_id = NULL WHERE ((albums.artist_id = 1) AND (id NOT IN ('1', '2')))"]
|
104
|
+
end
|
105
|
+
|
106
|
+
specify "should automatically convert keys to numbers if the primary key is an integer for one_to_many associations" do
|
107
|
+
@Tag.db_schema[:id][:type] = :integer
|
108
|
+
@Album.load(:id=>2).tag_pks = %w'1 3'
|
109
|
+
@db.sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN (1, 3)))"
|
110
|
+
@db.sqls[1].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, 1|1, 2)\)/
|
111
|
+
@db.sqls.length.should == 2
|
112
|
+
end
|
113
|
+
|
114
|
+
specify "should not automatically convert keys to numbers if the primary key is an integer for many_to_many associations" do
|
115
|
+
@Tag.db_schema[:id][:type] = :string
|
116
|
+
@Album.load(:id=>2).tag_pks = %w'1 3'
|
117
|
+
@db.sqls[0].should == "DELETE FROM albums_tags WHERE ((album_id = 2) AND (tag_id NOT IN ('1', '3')))"
|
118
|
+
@db.sqls[1].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, '1'|'1', 2)\)/
|
119
|
+
@db.sqls[2].should =~ /INSERT INTO albums_tags \((album_id, tag_id|tag_id, album_id)\) VALUES \((2, '3'|'3', 2)\)/
|
120
|
+
@db.sqls.length.should == 3
|
121
|
+
end
|
122
|
+
|
92
123
|
end
|
@@ -23,22 +23,19 @@ describe Sequel::Model, "dataset & schema" do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
describe Sequel::Model, "table_exists?" do
|
26
|
-
|
27
|
-
before(:each) do
|
26
|
+
before do
|
28
27
|
MODEL_DB.reset
|
29
28
|
@model = Class.new(Sequel::Model(:items))
|
30
29
|
end
|
31
30
|
|
32
31
|
it "should get the table name and question the model's db if table_exists?" do
|
33
|
-
@model.should_receive(:
|
34
|
-
@model.
|
35
|
-
@model.table_exists?
|
32
|
+
@model.db.should_receive(:table_exists?).and_return(false)
|
33
|
+
@model.table_exists?.should == false
|
36
34
|
end
|
37
35
|
end
|
38
36
|
|
39
37
|
describe Sequel::Model, "create_table and schema" do
|
40
|
-
|
41
|
-
before(:each) do
|
38
|
+
before do
|
42
39
|
MODEL_DB.reset
|
43
40
|
@model = Class.new(Sequel::Model) do
|
44
41
|
set_schema(:items) do
|
@@ -84,19 +81,15 @@ describe Sequel::Model, "create_table and schema" do
|
|
84
81
|
end
|
85
82
|
|
86
83
|
describe Sequel::Model, "drop_table" do
|
87
|
-
|
88
|
-
before(:each) do
|
89
|
-
MODEL_DB.reset
|
84
|
+
before do
|
90
85
|
@model = Class.new(Sequel::Model(:items))
|
86
|
+
MODEL_DB.reset
|
91
87
|
end
|
92
88
|
|
93
89
|
it "should get the drop table SQL for the associated table and then execute the SQL." do
|
94
|
-
@model.should_receive(:table_name).and_return(:items)
|
95
|
-
@model.db.should_receive(:drop_table_sql).with(:items)
|
96
|
-
@model.db.should_receive(:execute).and_return(:true)
|
97
90
|
@model.drop_table
|
91
|
+
MODEL_DB.sqls.should == ['DROP TABLE items']
|
98
92
|
end
|
99
|
-
|
100
93
|
end
|
101
94
|
|
102
95
|
describe Sequel::Model, "create_table!" do
|
@@ -106,9 +99,8 @@ describe Sequel::Model, "create_table!" do
|
|
106
99
|
end
|
107
100
|
|
108
101
|
it "should drop table if it exists and then create the table" do
|
109
|
-
@model.should_receive(:drop_table).and_return(true)
|
110
|
-
@model.should_receive(:create_table).and_return(true)
|
111
102
|
@model.create_table!
|
103
|
+
MODEL_DB.sqls.should == ['DROP TABLE items', 'CREATE TABLE items ()']
|
112
104
|
end
|
113
105
|
end
|
114
106
|
|
@@ -120,13 +112,13 @@ describe Sequel::Model, "create_table?" do
|
|
120
112
|
|
121
113
|
it "should not create the table if it already exists" do
|
122
114
|
@model.should_receive(:table_exists?).and_return(true)
|
123
|
-
@model.
|
124
|
-
|
115
|
+
@model.create_table?
|
116
|
+
MODEL_DB.sqls.should == []
|
125
117
|
end
|
126
118
|
|
127
119
|
it "should create the table if it doesn't exist" do
|
128
120
|
@model.should_receive(:table_exists?).and_return(false)
|
129
|
-
@model.
|
130
|
-
|
121
|
+
@model.create_table?
|
122
|
+
MODEL_DB.sqls.should == ['CREATE TABLE items ()']
|
131
123
|
end
|
132
124
|
end
|
@@ -632,6 +632,23 @@ describe "Sequel::Dataset main SQL methods" do
|
|
632
632
|
@ds.filter(:a=>20).or(:b=>15).all.should == [{:a=>20, :b=>30}]
|
633
633
|
@ds.filter(:a=>10).or(:b=>15).all.should == []
|
634
634
|
end
|
635
|
+
|
636
|
+
it "#select_group should work correctly" do
|
637
|
+
@ds.unordered!
|
638
|
+
@ds.select_group(:a).all.should == []
|
639
|
+
@ds.insert(20, 30)
|
640
|
+
@ds.select_group(:a).all.should == [{:a=>20}]
|
641
|
+
@ds.select_group(:b).all.should == [{:b=>30}]
|
642
|
+
@ds.insert(20, 40)
|
643
|
+
@ds.select_group(:a).all.should == [{:a=>20}]
|
644
|
+
@ds.order(:b).select_group(:b).all.should == [{:b=>30}, {:b=>40}]
|
645
|
+
end
|
646
|
+
|
647
|
+
it "#select_group should work correctly when aliasing" do
|
648
|
+
@ds.unordered!
|
649
|
+
@ds.insert(20, 30)
|
650
|
+
@ds.select_group(:b___c).all.should == [{:c=>30}]
|
651
|
+
end
|
635
652
|
|
636
653
|
it "#having should work correctly" do
|
637
654
|
@ds.unordered!
|
@@ -95,6 +95,13 @@ describe "Prepared Statements and Bound Arguments" do
|
|
95
95
|
@ds.order(:id).map(:number).should == [10, 20]
|
96
96
|
end
|
97
97
|
|
98
|
+
specify "should support bound variables with NULL values" do
|
99
|
+
@ds.delete
|
100
|
+
@ds.call(:insert, {:n=>nil}, :number=>@ds.ba(:$n))
|
101
|
+
@ds.count.should == 1
|
102
|
+
@ds.map(:number).should == [nil]
|
103
|
+
end
|
104
|
+
|
98
105
|
specify "should have insert return primary key value when using bound arguments" do
|
99
106
|
@ds.call(:insert, {:n=>20}, :number=>@ds.ba(:$n)).should == 2
|
100
107
|
@ds.filter(:id=>2).first[:number].should == 20
|
@@ -172,6 +179,14 @@ describe "Prepared Statements and Bound Arguments" do
|
|
172
179
|
@ds.order(:id).map(:number).should == [10, 20]
|
173
180
|
end
|
174
181
|
|
182
|
+
specify "should support prepared statements with NULL values" do
|
183
|
+
@ds.delete
|
184
|
+
@ds.prepare(:insert, :insert_n, :number=>@ds.ba(:$n))
|
185
|
+
INTEGRATION_DB.call(:insert_n, :n=>nil)
|
186
|
+
@ds.count.should == 1
|
187
|
+
@ds.map(:number).should == [nil]
|
188
|
+
end
|
189
|
+
|
175
190
|
specify "should have insert return primary key value when using prepared statements" do
|
176
191
|
@ds.prepare(:insert, :insert_n, :number=>@ds.ba(:$n))
|
177
192
|
INTEGRATION_DB.call(:insert_n, :n=>20).should == 2
|
data/spec/model/model_spec.rb
CHANGED
@@ -19,6 +19,27 @@ describe "Sequel::Model()" do
|
|
19
19
|
c.table_name.should == :blah
|
20
20
|
end
|
21
21
|
|
22
|
+
it "should return a model subclass with a dataset with the default database and given table name if given an SQL::Identifier" do
|
23
|
+
c = Sequel::Model(:blah.identifier)
|
24
|
+
c.superclass.should == Sequel::Model
|
25
|
+
c.db.should == @db
|
26
|
+
c.table_name.should == :blah.identifier
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return a model subclass with a dataset with the default database and given table name if given an SQL::QualifiedIdentifier" do
|
30
|
+
c = Sequel::Model(:blah.qualify(:boo))
|
31
|
+
c.superclass.should == Sequel::Model
|
32
|
+
c.db.should == @db
|
33
|
+
c.table_name.should == :blah.qualify(:boo)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return a model subclass with a dataset with the default database and given table name if given an SQL::AliasedExpression" do
|
37
|
+
c = Sequel::Model(:blah.as(:boo))
|
38
|
+
c.superclass.should == Sequel::Model
|
39
|
+
c.db.should == @db
|
40
|
+
c.table_name.should == :boo
|
41
|
+
end
|
42
|
+
|
22
43
|
it "should return a model subclass associated to the given database if given a database" do
|
23
44
|
db = Sequel::Database.new
|
24
45
|
c = Sequel::Model(db)
|
@@ -43,6 +64,27 @@ describe "Sequel::Model()" do
|
|
43
64
|
end.should_not raise_error
|
44
65
|
end
|
45
66
|
|
67
|
+
it "should work without raising an exception with an SQL::Identifier " do
|
68
|
+
proc do
|
69
|
+
class ::Album < Sequel::Model(:table.identifier); end
|
70
|
+
class ::Album < Sequel::Model(:table.identifier); end
|
71
|
+
end.should_not raise_error
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should work without raising an exception with an SQL::QualifiedIdentifier " do
|
75
|
+
proc do
|
76
|
+
class ::Album < Sequel::Model(:table.qualify(:schema)); end
|
77
|
+
class ::Album < Sequel::Model(:table.qualify(:schema)); end
|
78
|
+
end.should_not raise_error
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should work without raising an exception with an SQL::AliasedExpression" do
|
82
|
+
proc do
|
83
|
+
class ::Album < Sequel::Model(:table.as(:alias)); end
|
84
|
+
class ::Album < Sequel::Model(:table.as(:alias)); end
|
85
|
+
end.should_not raise_error
|
86
|
+
end
|
87
|
+
|
46
88
|
it "should work without raising an exception with a database" do
|
47
89
|
proc do
|
48
90
|
class ::Album < Sequel::Model(@db); end
|
@@ -112,6 +154,24 @@ describe Sequel::Model, "dataset & schema" do
|
|
112
154
|
@model.table_name.should == :foo
|
113
155
|
end
|
114
156
|
|
157
|
+
it "set_dataset should take an SQL::Identifier" do
|
158
|
+
@model.db = MODEL_DB
|
159
|
+
@model.set_dataset(:foo.identifier)
|
160
|
+
@model.table_name.should == :foo.identifier
|
161
|
+
end
|
162
|
+
|
163
|
+
it "set_dataset should take an SQL::QualifiedIdentifier" do
|
164
|
+
@model.db = MODEL_DB
|
165
|
+
@model.set_dataset(:foo.qualify(:bar))
|
166
|
+
@model.table_name.should == :foo.qualify(:bar)
|
167
|
+
end
|
168
|
+
|
169
|
+
it "set_dataset should take an SQL::AliasedExpression" do
|
170
|
+
@model.db = MODEL_DB
|
171
|
+
@model.set_dataset(:foo.as(:bar))
|
172
|
+
@model.table_name.should == :bar
|
173
|
+
end
|
174
|
+
|
115
175
|
it "table_name should respect table aliases" do
|
116
176
|
@model.set_dataset(:foo___x)
|
117
177
|
@model.table_name.should == :x
|
data/spec/model/plugins_spec.rb
CHANGED
@@ -233,4 +233,21 @@ describe Sequel::Model, ".plugin" do
|
|
233
233
|
end
|
234
234
|
lambda{@c.plugin m}.should_not raise_error
|
235
235
|
end
|
236
|
+
|
237
|
+
it "should not raise an error if plugin submodule names exist higher up in the namespace hierarchy" do
|
238
|
+
class ::ClassMethods; end
|
239
|
+
@c.plugin(m = Module.new)
|
240
|
+
Object.send(:remove_const, :ClassMethods)
|
241
|
+
@c.plugins.should include(m)
|
242
|
+
|
243
|
+
class ::InstanceMethods; end
|
244
|
+
@c.plugin(m = Module.new)
|
245
|
+
Object.send(:remove_const, :InstanceMethods)
|
246
|
+
@c.plugins.should include(m)
|
247
|
+
|
248
|
+
class ::DatasetMethods; end
|
249
|
+
@c.plugin(m = Module.new)
|
250
|
+
Object.send(:remove_const, :DatasetMethods)
|
251
|
+
@c.plugins.should include(m)
|
252
|
+
end
|
236
253
|
end
|
@@ -61,6 +61,17 @@ describe Sequel::Model::Errors do
|
|
61
61
|
msgs.should include('blow blieuh', 'blow blich', 'blay bliu')
|
62
62
|
end
|
63
63
|
|
64
|
+
specify "should not add column names for LiteralStrings" do
|
65
|
+
@errors.full_messages.should == []
|
66
|
+
|
67
|
+
@errors[:blow] << 'blieuh'
|
68
|
+
@errors[:blow] << 'blich'.lit
|
69
|
+
@errors[:blay] << 'bliu'
|
70
|
+
msgs = @errors.full_messages
|
71
|
+
msgs.size.should == 3
|
72
|
+
msgs.should include('blow blieuh', 'blich', 'blay bliu')
|
73
|
+
end
|
74
|
+
|
64
75
|
specify "should return the number of error messages using #count" do
|
65
76
|
@errors.count.should == 0
|
66
77
|
@errors.add(:a, 'b')
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 99
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 3.
|
8
|
+
- 25
|
9
|
+
- 0
|
10
|
+
version: 3.25.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jeremy Evans
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-07-01 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -88,6 +88,7 @@ extra_rdoc_files:
|
|
88
88
|
- doc/release_notes/3.22.0.txt
|
89
89
|
- doc/release_notes/3.23.0.txt
|
90
90
|
- doc/release_notes/3.24.0.txt
|
91
|
+
- doc/release_notes/3.25.0.txt
|
91
92
|
files:
|
92
93
|
- MIT-LICENSE
|
93
94
|
- CHANGELOG
|
@@ -143,6 +144,7 @@ files:
|
|
143
144
|
- doc/release_notes/3.22.0.txt
|
144
145
|
- doc/release_notes/3.23.0.txt
|
145
146
|
- doc/release_notes/3.24.0.txt
|
147
|
+
- doc/release_notes/3.25.0.txt
|
146
148
|
- doc/sharding.rdoc
|
147
149
|
- doc/sql.rdoc
|
148
150
|
- doc/virtual_rows.rdoc
|