sequel 5.18.0 → 5.20.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.
- checksums.yaml +4 -4
- data/CHANGELOG +40 -0
- data/doc/opening_databases.rdoc +5 -2
- data/doc/release_notes/5.19.0.txt +28 -0
- data/doc/release_notes/5.20.0.txt +89 -0
- data/doc/sharding.rdoc +12 -0
- data/doc/transactions.rdoc +38 -0
- data/lib/sequel/adapters/jdbc.rb +7 -2
- data/lib/sequel/adapters/mysql2.rb +2 -2
- data/lib/sequel/adapters/shared/postgres.rb +8 -8
- data/lib/sequel/adapters/shared/sqlite.rb +3 -1
- data/lib/sequel/adapters/sqlanywhere.rb +33 -17
- data/lib/sequel/adapters/sqlite.rb +20 -13
- data/lib/sequel/connection_pool.rb +0 -5
- data/lib/sequel/database/misc.rb +10 -9
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +1 -1
- data/lib/sequel/database/transactions.rb +57 -5
- data/lib/sequel/dataset/actions.rb +6 -5
- data/lib/sequel/dataset/graph.rb +2 -2
- data/lib/sequel/dataset/placeholder_literalizer.rb +4 -1
- data/lib/sequel/dataset/prepared_statements.rb +1 -1
- data/lib/sequel/dataset/query.rb +1 -1
- data/lib/sequel/extensions/constraint_validations.rb +14 -0
- data/lib/sequel/extensions/pg_enum.rb +23 -15
- data/lib/sequel/extensions/schema_dumper.rb +1 -1
- data/lib/sequel/model/associations.rb +38 -12
- data/lib/sequel/model/base.rb +1 -1
- data/lib/sequel/model/plugins.rb +104 -0
- data/lib/sequel/plugins/association_dependencies.rb +3 -3
- data/lib/sequel/plugins/association_pks.rb +14 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +1 -0
- data/lib/sequel/plugins/composition.rb +13 -9
- data/lib/sequel/plugins/finder.rb +2 -2
- data/lib/sequel/plugins/hook_class_methods.rb +17 -5
- data/lib/sequel/plugins/inverted_subsets.rb +2 -2
- data/lib/sequel/plugins/json_serializer.rb +3 -3
- data/lib/sequel/plugins/nested_attributes.rb +1 -1
- data/lib/sequel/plugins/pg_array_associations.rb +8 -4
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +61 -32
- data/lib/sequel/plugins/prepared_statements.rb +1 -1
- data/lib/sequel/plugins/prepared_statements_safe.rb +1 -1
- data/lib/sequel/plugins/subset_conditions.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +5 -3
- data/lib/sequel/plugins/validation_helpers.rb +2 -2
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +40 -0
- data/spec/core/database_spec.rb +73 -2
- data/spec/core/schema_spec.rb +7 -1
- data/spec/extensions/class_table_inheritance_spec.rb +30 -8
- data/spec/extensions/constraint_validations_spec.rb +20 -2
- data/spec/extensions/core_refinements_spec.rb +1 -1
- data/spec/extensions/hook_class_methods_spec.rb +22 -0
- data/spec/extensions/migration_spec.rb +13 -0
- data/spec/extensions/pg_auto_constraint_validations_spec.rb +8 -0
- data/spec/extensions/pg_enum_spec.rb +5 -0
- data/spec/extensions/s_spec.rb +1 -1
- data/spec/extensions/schema_dumper_spec.rb +4 -2
- data/spec/integration/plugin_test.rb +15 -0
- data/spec/integration/transaction_test.rb +50 -0
- data/spec/model/associations_spec.rb +84 -4
- data/spec/model/plugins_spec.rb +111 -0
- metadata +7 -3
@@ -149,7 +149,7 @@ module Sequel
|
|
149
149
|
# Use a prepared statement to update this model's columns in the database.
|
150
150
|
def _update_without_checking(columns)
|
151
151
|
if use_prepared_statements_for?(:update)
|
152
|
-
_set_prepared_statement_server(model.send(:prepared_update, columns.keys)).call(
|
152
|
+
_set_prepared_statement_server(model.send(:prepared_update, columns.keys)).call(columns.merge(pk_hash))
|
153
153
|
else
|
154
154
|
super
|
155
155
|
end
|
@@ -26,8 +26,8 @@ module Sequel
|
|
26
26
|
# Album.where(Album.published_conditions | {ready: true}).sql
|
27
27
|
# # SELECT * FROM albums WHERE ((published IS TRUE) OR (ready IS TRUE))
|
28
28
|
module SubsetConditions
|
29
|
-
def self.apply(
|
30
|
-
|
29
|
+
def self.apply(model, &block)
|
30
|
+
model.instance_exec do
|
31
31
|
@dataset_module_class = Class.new(@dataset_module_class) do
|
32
32
|
include DatasetModuleMethods
|
33
33
|
end
|
@@ -188,13 +188,17 @@ module Sequel
|
|
188
188
|
# Sequel will attempt to insert a NULL value into the database, instead of using the
|
189
189
|
# database's default.
|
190
190
|
# :allow_nil :: Whether to skip the validation if the value is nil.
|
191
|
-
# :if :: A symbol (indicating an instance_method) or proc (which is
|
191
|
+
# :if :: A symbol (indicating an instance_method) or proc (which is used to define an instance method)
|
192
192
|
# skipping this validation if it returns nil or false.
|
193
193
|
# :tag :: The tag to use for this validation.
|
194
194
|
def validates_each(*atts, &block)
|
195
195
|
opts = extract_options!(atts)
|
196
196
|
blank_meth = db.method(:blank_object?).to_proc
|
197
197
|
blk = if (i = opts[:if]) || (am = opts[:allow_missing]) || (an = opts[:allow_nil]) || (ab = opts[:allow_blank])
|
198
|
+
if i.is_a?(Proc)
|
199
|
+
i = Plugins.def_sequel_method(self, "validation_class_methods_if", 0, &i)
|
200
|
+
end
|
201
|
+
|
198
202
|
proc do |o,a,v|
|
199
203
|
next if i && !validation_if_proc(o, i)
|
200
204
|
next if an && Array(v).all?(&:nil?)
|
@@ -434,8 +438,6 @@ module Sequel
|
|
434
438
|
case i
|
435
439
|
when Symbol
|
436
440
|
o.get_column_value(i)
|
437
|
-
when Proc
|
438
|
-
o.instance_exec(&i)
|
439
441
|
else
|
440
442
|
raise(::Sequel::Error, "invalid value for :if validation option")
|
441
443
|
end
|
@@ -244,7 +244,7 @@ module Sequel
|
|
244
244
|
def validates_unique(*atts)
|
245
245
|
opts = default_validation_helpers_options(:unique)
|
246
246
|
if atts.last.is_a?(Hash)
|
247
|
-
opts =
|
247
|
+
opts = opts.merge(atts.pop)
|
248
248
|
end
|
249
249
|
message = validation_error_message(opts[:message])
|
250
250
|
from_values = opts[:from] == :values
|
@@ -302,7 +302,7 @@ module Sequel
|
|
302
302
|
# Merge the given options with the default options for the given type
|
303
303
|
# and call validatable_attributes with the merged options.
|
304
304
|
def validatable_attributes_for_type(type, atts, opts, &block)
|
305
|
-
validatable_attributes(atts,
|
305
|
+
validatable_attributes(atts, default_validation_helpers_options(type).merge(opts), &block)
|
306
306
|
end
|
307
307
|
|
308
308
|
# The validation error message to use, as a string. If message
|
data/lib/sequel/sql.rb
CHANGED
@@ -1472,7 +1472,7 @@ module Sequel
|
|
1472
1472
|
|
1473
1473
|
# Return a new function call with the given opts merged into the current opts.
|
1474
1474
|
def with_opts(opts)
|
1475
|
-
self.class.new!(name, args,
|
1475
|
+
self.class.new!(name, args, @opts.merge(opts))
|
1476
1476
|
end
|
1477
1477
|
end
|
1478
1478
|
|
data/lib/sequel/version.rb
CHANGED
@@ -6,7 +6,7 @@ module Sequel
|
|
6
6
|
|
7
7
|
# The minor version of Sequel. Bumped for every non-patch level
|
8
8
|
# release, generally around once a month.
|
9
|
-
MINOR =
|
9
|
+
MINOR = 20
|
10
10
|
|
11
11
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
12
12
|
# releases that fix regressions from previous versions.
|
@@ -104,6 +104,24 @@ describe "PostgreSQL", '#create_table' do
|
|
104
104
|
@db.check_constraints(:tmp_dolls).must_equal(:ic=>{:definition=>"CHECK ((i > 2))", :columns=>[:i]}, :jc=>{:definition=>"CHECK ((j > 2))", :columns=>[:j]}, :ijc=>{:definition=>"CHECK (((i - j) > 2))", :columns=>[:i, :j]})
|
105
105
|
end
|
106
106
|
|
107
|
+
it "should have #check_constraints return check constraints where columns are unknown" do
|
108
|
+
begin
|
109
|
+
@db.create_table(:tmp_dolls) do
|
110
|
+
Integer :i
|
111
|
+
Integer :j
|
112
|
+
end
|
113
|
+
@db.run "CREATE OR REPLACE FUNCTION valid_tmp_dolls(t1 tmp_dolls) RETURNS boolean AS 'SELECT false' LANGUAGE SQL;"
|
114
|
+
@db.alter_table(:tmp_dolls) do
|
115
|
+
add_constraint(:valid_tmp_dolls, Sequel.function(:valid_tmp_dolls, :tmp_dolls))
|
116
|
+
end
|
117
|
+
|
118
|
+
@db.check_constraints(:tmp_dolls).must_equal(:valid_tmp_dolls=>{:definition=>"CHECK (valid_tmp_dolls(tmp_dolls.*))", :columns=>[]})
|
119
|
+
ensure
|
120
|
+
@db.run "ALTER TABLE tmp_dolls DROP CONSTRAINT IF EXISTS valid_tmp_dolls"
|
121
|
+
@db.run "DROP FUNCTION IF EXISTS valid_tmp_dolls(tmp_dolls)"
|
122
|
+
end
|
123
|
+
end if DB.server_version >= 90000
|
124
|
+
|
107
125
|
it "should not allow to pass both :temp and :unlogged" do
|
108
126
|
proc do
|
109
127
|
@db.create_table(:temp_unlogged_dolls, :temp => true, :unlogged => true){text :name}
|
@@ -3930,6 +3948,14 @@ describe 'PostgreSQL enum types' do
|
|
3930
3948
|
@db.schema(:test_enumt, :reload=>true).first.last[:enum_values].must_equal @initial_enum_values
|
3931
3949
|
@db.rename_enum(:new_enum, :test_enum)
|
3932
3950
|
end
|
3951
|
+
|
3952
|
+
it "should rename enum values" do
|
3953
|
+
@db.rename_enum_value(:test_enum, :b, :x)
|
3954
|
+
new_enum_values = @initial_enum_values
|
3955
|
+
new_enum_values[new_enum_values.index('b')] = 'x'
|
3956
|
+
@db.schema(:test_enumt, :reload=>true).first.last[:enum_values].must_equal new_enum_values
|
3957
|
+
@db.rename_enum_value(:test_enum, :x, :b)
|
3958
|
+
end if DB.server_version >= 100000
|
3933
3959
|
end
|
3934
3960
|
|
3935
3961
|
describe "PostgreSQL stored procedures for datasets" do
|
@@ -3980,6 +4006,10 @@ describe "pg_auto_constraint_validations plugin" do
|
|
3980
4006
|
constraint :valid_i, Sequel[:i] < 10
|
3981
4007
|
constraint(:valid_i_id, Sequel[:i] + Sequel[:id] < 20)
|
3982
4008
|
end
|
4009
|
+
@db.run "CREATE OR REPLACE FUNCTION valid_test1(t1 test1) RETURNS boolean AS 'SELECT t1.i != -100' LANGUAGE SQL;"
|
4010
|
+
@db.alter_table(:test1) do
|
4011
|
+
add_constraint(:valid_test1, Sequel.function(:valid_test1, :test1))
|
4012
|
+
end
|
3983
4013
|
@db.create_table!(:test2) do
|
3984
4014
|
Integer :test2_id, :primary_key=>true
|
3985
4015
|
foreign_key :test1_id, :test1
|
@@ -4000,6 +4030,8 @@ describe "pg_auto_constraint_validations plugin" do
|
|
4000
4030
|
@c2.insert(:test2_id=>3, :test1_id=>1)
|
4001
4031
|
end
|
4002
4032
|
after(:all) do
|
4033
|
+
@db.run "ALTER TABLE test1 DROP CONSTRAINT IF EXISTS valid_test1"
|
4034
|
+
@db.run "DROP FUNCTION IF EXISTS valid_test1(test1)"
|
4003
4035
|
@db.drop_table?(:test2, :test1)
|
4004
4036
|
end
|
4005
4037
|
|
@@ -4009,6 +4041,14 @@ describe "pg_auto_constraint_validations plugin" do
|
|
4009
4041
|
o.errors.must_equal(:i=>['is invalid'])
|
4010
4042
|
end
|
4011
4043
|
|
4044
|
+
it "should handle check constraint failures where the columns are unknown, if columns are explicitly specified" do
|
4045
|
+
o = @c1.new(:id=>5, :i=>-100)
|
4046
|
+
proc{o.save}.must_raise Sequel::CheckConstraintViolation
|
4047
|
+
@c1.pg_auto_constraint_validation_override(:valid_test1, :i, "should not be -100")
|
4048
|
+
proc{o.save}.must_raise Sequel::ValidationFailed
|
4049
|
+
o.errors.must_equal(:i=>['should not be -100'])
|
4050
|
+
end
|
4051
|
+
|
4012
4052
|
it "should handle check constraint failures as validation errors when updating" do
|
4013
4053
|
o = @c1.new(:id=>5, :i=>3)
|
4014
4054
|
o.save
|
data/spec/core/database_spec.rb
CHANGED
@@ -1140,15 +1140,86 @@ describe "Database#transaction with savepoint support" do
|
|
1140
1140
|
end
|
1141
1141
|
|
1142
1142
|
it "should support after_rollback inside savepoints" do
|
1143
|
-
@db.transaction do
|
1143
|
+
@db.transaction(:rollback=>:always) do
|
1144
1144
|
@db.after_rollback{@db.execute('foo')}
|
1145
1145
|
@db.transaction(:savepoint=>true){@db.after_rollback{@db.execute('bar')}}
|
1146
1146
|
@db.after_rollback{@db.execute('baz')}
|
1147
|
-
raise Sequel::Rollback
|
1148
1147
|
end
|
1149
1148
|
@db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'RELEASE SAVEPOINT autopoint_1', 'ROLLBACK', 'foo', 'bar', 'baz']
|
1150
1149
|
end
|
1151
1150
|
|
1151
|
+
it "should run after_commit if savepoint rolled back" do
|
1152
|
+
@db.transaction do
|
1153
|
+
@db.after_commit{@db.execute('foo')}
|
1154
|
+
@db.transaction(:savepoint=>true, :rollback=>:always){@db.after_commit{@db.execute('bar')}}
|
1155
|
+
end
|
1156
|
+
@db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'ROLLBACK TO SAVEPOINT autopoint_1', 'COMMIT', 'foo', 'bar']
|
1157
|
+
end
|
1158
|
+
|
1159
|
+
it "should not run after_commit if savepoint rolled back and :savepoint option used" do
|
1160
|
+
@db.transaction do
|
1161
|
+
@db.after_commit{@db.execute('foo')}
|
1162
|
+
@db.transaction(:savepoint=>true, :rollback=>:always){@db.after_commit(:savepoint=>true){@db.execute('bar')}}
|
1163
|
+
end
|
1164
|
+
@db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'ROLLBACK TO SAVEPOINT autopoint_1', 'COMMIT', 'foo']
|
1165
|
+
end
|
1166
|
+
|
1167
|
+
it "should not run after_commit if higher-level savepoint rolled back and :savepoint option used" do
|
1168
|
+
@db.transaction do
|
1169
|
+
@db.after_commit{@db.execute('foo')}
|
1170
|
+
@db.transaction(:savepoint=>true, :rollback=>:always){@db.transaction(:savepoint=>true){@db.after_commit(:savepoint=>true){@db.execute('bar')}}}
|
1171
|
+
end
|
1172
|
+
@db.sqls.must_equal ["BEGIN", "SAVEPOINT autopoint_1", "SAVEPOINT autopoint_2", "RELEASE SAVEPOINT autopoint_2", "ROLLBACK TO SAVEPOINT autopoint_1", "COMMIT", "foo"]
|
1173
|
+
end
|
1174
|
+
|
1175
|
+
it "should not run after_commit if transaction rolled back and :savepoint option used" do
|
1176
|
+
@db.transaction(:rollback=>:always) do
|
1177
|
+
@db.after_commit{@db.execute('foo')}
|
1178
|
+
@db.transaction(:savepoint=>true){@db.transaction(:savepoint=>true){@db.after_commit(:savepoint=>true){@db.execute('bar')}}}
|
1179
|
+
end
|
1180
|
+
@db.sqls.must_equal ["BEGIN", "SAVEPOINT autopoint_1", "SAVEPOINT autopoint_2", "RELEASE SAVEPOINT autopoint_2", "RELEASE SAVEPOINT autopoint_1", "ROLLBACK"]
|
1181
|
+
end
|
1182
|
+
|
1183
|
+
it "should run after_rollback if savepoint rolls back" do
|
1184
|
+
@db.transaction(:rollback=>:always) do
|
1185
|
+
@db.after_rollback{@db.execute('foo')}
|
1186
|
+
@db.transaction(:savepoint=>true, :rollback=>:always){@db.after_rollback{@db.execute('bar')}}
|
1187
|
+
@db.after_rollback{@db.execute('baz')}
|
1188
|
+
end
|
1189
|
+
@db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK', 'foo', 'bar', 'baz']
|
1190
|
+
end
|
1191
|
+
|
1192
|
+
it "should run after_rollback when savepoint rolls back if :savepoint option used" do
|
1193
|
+
@db.transaction(:rollback=>:always) do
|
1194
|
+
@db.after_rollback{@db.execute('foo')}
|
1195
|
+
@db.transaction(:savepoint=>true, :rollback=>:always){@db.after_rollback(:savepoint=>true){@db.execute('bar')}}
|
1196
|
+
@db.after_rollback{@db.execute('baz')}
|
1197
|
+
end
|
1198
|
+
@db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'ROLLBACK TO SAVEPOINT autopoint_1', 'bar', 'ROLLBACK', 'foo', 'baz']
|
1199
|
+
end
|
1200
|
+
|
1201
|
+
it "should run after_rollback if savepoint rolled back and :savepoint option used, even if transaction commits" do
|
1202
|
+
@db.transaction do
|
1203
|
+
@db.after_commit{@db.execute('foo')}
|
1204
|
+
@db.transaction(:savepoint=>true, :rollback=>:always){@db.after_rollback(:savepoint=>true){@db.execute('bar')}}
|
1205
|
+
end
|
1206
|
+
@db.sqls.must_equal ['BEGIN', 'SAVEPOINT autopoint_1', 'ROLLBACK TO SAVEPOINT autopoint_1', 'bar', 'COMMIT', 'foo']
|
1207
|
+
end
|
1208
|
+
|
1209
|
+
it "should run after_rollback if higher-level savepoint rolled back and :savepoint option used" do
|
1210
|
+
@db.transaction do
|
1211
|
+
@db.transaction(:savepoint=>true, :rollback=>:always){@db.transaction(:savepoint=>true){@db.after_rollback(:savepoint=>true){@db.execute('bar')}}}
|
1212
|
+
end
|
1213
|
+
@db.sqls.must_equal ["BEGIN", "SAVEPOINT autopoint_1", "SAVEPOINT autopoint_2", "RELEASE SAVEPOINT autopoint_2", "ROLLBACK TO SAVEPOINT autopoint_1", "bar", "COMMIT"]
|
1214
|
+
end
|
1215
|
+
|
1216
|
+
it "should run after_rollback if transaction rolled back and :savepoint option used" do
|
1217
|
+
@db.transaction(:rollback=>:always) do
|
1218
|
+
@db.transaction(:savepoint=>true){@db.transaction(:savepoint=>true){@db.after_rollback(:savepoint=>true){@db.execute('bar')}}}
|
1219
|
+
end
|
1220
|
+
@db.sqls.must_equal ["BEGIN", "SAVEPOINT autopoint_1", "SAVEPOINT autopoint_2", "RELEASE SAVEPOINT autopoint_2", "RELEASE SAVEPOINT autopoint_1", "ROLLBACK", "bar"]
|
1221
|
+
end
|
1222
|
+
|
1152
1223
|
it "should raise an error if you attempt to use after_commit inside a savepoint in a prepared transaction" do
|
1153
1224
|
@db.define_singleton_method(:supports_prepared_transactions?){true}
|
1154
1225
|
proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_commit{@db.execute('foo')}}}}.must_raise(Sequel::Error)
|
data/spec/core/schema_spec.rb
CHANGED
@@ -1679,7 +1679,7 @@ describe "Schema Parser" do
|
|
1679
1679
|
sch = @db.schema(:x)
|
1680
1680
|
sch.must_equal [[:a, {:db_type=>"x", :ruby_default=>nil}], [:b, {:db_type=>"x", :ruby_default=>nil}]]
|
1681
1681
|
sch[0][1][:db_type].must_be_same_as(sch[1][1][:db_type])
|
1682
|
-
end if RUBY_VERSION >= '2.5'
|
1682
|
+
end if RUBY_VERSION >= '2.5'
|
1683
1683
|
|
1684
1684
|
it "should set :auto_increment to true by default if unset and a single integer primary key is used" do
|
1685
1685
|
@db.define_singleton_method(:schema_parse_table){|*| [[:a, {:primary_key=>true, :db_type=>'integer'}]]}
|
@@ -1777,17 +1777,21 @@ describe "Schema Parser" do
|
|
1777
1777
|
@db.schema(:text).first.last[:type].must_equal :string
|
1778
1778
|
@db.schema(:date).first.last[:type].must_equal :date
|
1779
1779
|
@db.schema(:datetime).first.last[:type].must_equal :datetime
|
1780
|
+
@db.schema(:smalldatetime).first.last[:type].must_equal :datetime
|
1780
1781
|
@db.schema(:timestamp).first.last[:type].must_equal :datetime
|
1781
1782
|
@db.schema(:"timestamp with time zone").first.last[:type].must_equal :datetime
|
1782
1783
|
@db.schema(:"timestamp without time zone").first.last[:type].must_equal :datetime
|
1783
1784
|
@db.schema(:time).first.last[:type].must_equal :time
|
1784
1785
|
@db.schema(:"time with time zone").first.last[:type].must_equal :time
|
1785
1786
|
@db.schema(:"time without time zone").first.last[:type].must_equal :time
|
1787
|
+
@db.schema(:bool).first.last[:type].must_equal :boolean
|
1786
1788
|
@db.schema(:boolean).first.last[:type].must_equal :boolean
|
1787
1789
|
@db.schema(:real).first.last[:type].must_equal :float
|
1788
1790
|
@db.schema(:float).first.last[:type].must_equal :float
|
1791
|
+
@db.schema(:"float unsigned").first.last[:type].must_equal :float
|
1789
1792
|
@db.schema(:double).first.last[:type].must_equal :float
|
1790
1793
|
@db.schema(:"double(1,2)").first.last[:type].must_equal :float
|
1794
|
+
@db.schema(:"double(1,2) unsigned").first.last[:type].must_equal :float
|
1791
1795
|
@db.schema(:"double precision").first.last[:type].must_equal :float
|
1792
1796
|
@db.schema(:number).first.last[:type].must_equal :decimal
|
1793
1797
|
@db.schema(:numeric).first.last[:type].must_equal :decimal
|
@@ -1801,6 +1805,8 @@ describe "Schema Parser" do
|
|
1801
1805
|
@db.schema(:nchar).first.last[:type].must_equal :string
|
1802
1806
|
@db.schema(:nvarchar).first.last[:type].must_equal :string
|
1803
1807
|
@db.schema(:ntext).first.last[:type].must_equal :string
|
1808
|
+
@db.schema(:clob).first.last[:type].must_equal :string
|
1809
|
+
@db.schema(:ntext).first.last[:type].must_equal :string
|
1804
1810
|
@db.schema(:smalldatetime).first.last[:type].must_equal :datetime
|
1805
1811
|
@db.schema(:binary).first.last[:type].must_equal :blob
|
1806
1812
|
@db.schema(:varbinary).first.last[:type].must_equal :blob
|
@@ -5,8 +5,8 @@ describe "class_table_inheritance plugin" do
|
|
5
5
|
@db = Sequel.mock(:numrows=>1, :autoid=>proc{|sql| 1})
|
6
6
|
def @db.supports_schema_parsing?() true end
|
7
7
|
def @db.schema(table, opts={})
|
8
|
-
{:employees=>[[:id, {:primary_key=>true, :type=>:integer}], [:name, {:type=>:string}], [:kind, {:type=>:string}]],
|
9
|
-
:managers=>[[:id, {:type=>:integer}], [:num_staff, {:type=>:integer}] ],
|
8
|
+
{:employees=>[[:id, {:primary_key=>true, :type=>:integer}], [:name, {:type=>:string, :allow_null=>false}], [:kind, {:type=>:string}]],
|
9
|
+
:managers=>[[:id, {:type=>:integer}], [:num_staff, {:type=>:integer, :allow_null=>false}] ],
|
10
10
|
:executives=>[[:id, {:type=>:integer}], [:num_managers, {:type=>:integer}]],
|
11
11
|
:staff=>[[:id, {:type=>:integer}], [:manager_id, {:type=>:integer}]],
|
12
12
|
}[table.is_a?(Sequel::Dataset) ? table.first_source_table : table]
|
@@ -23,7 +23,9 @@ describe "class_table_inheritance plugin" do
|
|
23
23
|
}[opts[:from] + (opts[:join] || []).map{|x| x.table}]
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|
26
|
+
base = Sequel::Model(@db)
|
27
|
+
base.plugin :auto_validations if @use_auto_validations
|
28
|
+
class ::Employee < base
|
27
29
|
def _save_refresh; @values[:id] = 1 end
|
28
30
|
def self.columns
|
29
31
|
dataset.columns || dataset.opts[:from].first.expression.columns
|
@@ -114,6 +116,26 @@ describe "class_table_inheritance plugin" do
|
|
114
116
|
"SELECT * FROM (SELECT employees.id, employees.name, employees.kind, managers.num_staff, executives.num_managers FROM employees INNER JOIN managers ON (managers.id = employees.id) INNER JOIN executives ON (executives.id = managers.id) WHERE (employees.kind IN ('Ceo'))) AS employees WHERE (id = 1) LIMIT 1"]
|
115
117
|
end
|
116
118
|
|
119
|
+
describe "with auto_validations plugin" do
|
120
|
+
before(:all) do
|
121
|
+
@use_auto_validations = true
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should work" do
|
125
|
+
e = Employee.new
|
126
|
+
e.valid?.must_equal false
|
127
|
+
e.errors.must_equal(:name=>["is not present"])
|
128
|
+
|
129
|
+
e = Manager.new
|
130
|
+
e.valid?.must_equal false
|
131
|
+
e.errors.must_equal(:name=>["is not present"], :num_staff=>["is not present"])
|
132
|
+
|
133
|
+
e = Executive.new
|
134
|
+
e.valid?.must_equal false
|
135
|
+
e.errors.must_equal(:name=>["is not present"], :num_staff=>["is not present"])
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
117
139
|
it "should return rows with the current class if sti_key is nil" do
|
118
140
|
Employee.plugin :class_table_inheritance
|
119
141
|
Employee.dataset.with_fetch([{:kind=>'Employee'}, {:kind=>'Manager'}, {:kind=>'Executive'}, {:kind=>'Ceo'}, {:kind=>'Staff'}, {:kind=>'Intern'}]).all.map{|x| x.class}.must_equal [Employee, Employee, Employee, Employee, Employee, Employee]
|
@@ -232,11 +254,11 @@ describe "class_table_inheritance plugin" do
|
|
232
254
|
end
|
233
255
|
|
234
256
|
it "should include schema for columns for tables for ancestor classes" do
|
235
|
-
Employee.db_schema.must_equal(:id=>{:primary_key=>true, :type=>:integer}, :name=>{:type=>:string}, :kind=>{:type=>:string})
|
236
|
-
Manager.db_schema.must_equal(:id=>{:primary_key=>true, :type=>:integer}, :name=>{:type=>:string}, :kind=>{:type=>:string}, :num_staff=>{:type=>:integer})
|
237
|
-
Executive.db_schema.must_equal(:id=>{:primary_key=>true, :type=>:integer}, :name=>{:type=>:string}, :kind=>{:type=>:string}, :num_staff=>{:type=>:integer}, :num_managers=>{:type=>:integer})
|
238
|
-
Staff.db_schema.must_equal(:id=>{:primary_key=>true, :type=>:integer}, :name=>{:type=>:string}, :kind=>{:type=>:string}, :manager_id=>{:type=>:integer})
|
239
|
-
Intern.db_schema.must_equal(:id=>{:primary_key=>true, :type=>:integer}, :name=>{:type=>:string}, :kind=>{:type=>:string})
|
257
|
+
Employee.db_schema.must_equal(:id=>{:primary_key=>true, :type=>:integer}, :name=>{:type=>:string, :allow_null=>false}, :kind=>{:type=>:string})
|
258
|
+
Manager.db_schema.must_equal(:id=>{:primary_key=>true, :type=>:integer}, :name=>{:type=>:string, :allow_null=>false}, :kind=>{:type=>:string}, :num_staff=>{:type=>:integer, :allow_null=>false})
|
259
|
+
Executive.db_schema.must_equal(:id=>{:primary_key=>true, :type=>:integer}, :name=>{:type=>:string, :allow_null=>false}, :kind=>{:type=>:string}, :num_staff=>{:type=>:integer, :allow_null=>false}, :num_managers=>{:type=>:integer})
|
260
|
+
Staff.db_schema.must_equal(:id=>{:primary_key=>true, :type=>:integer}, :name=>{:type=>:string, :allow_null=>false}, :kind=>{:type=>:string}, :manager_id=>{:type=>:integer})
|
261
|
+
Intern.db_schema.must_equal(:id=>{:primary_key=>true, :type=>:integer}, :name=>{:type=>:string, :allow_null=>false}, :kind=>{:type=>:string})
|
240
262
|
end
|
241
263
|
|
242
264
|
it "should use the correct primary key (which should have the same name in all subclasses)" do
|
@@ -20,6 +20,7 @@ describe "constraint_validations extension" do
|
|
20
20
|
before do
|
21
21
|
@db = Sequel.mock
|
22
22
|
@db.extend(Module.new{attr_writer :schema; def schema(table, *) execute("parse schema for #{table}"); @schema; end})
|
23
|
+
def @db.table_exists?(_) true; end
|
23
24
|
@db.extension(:constraint_validations)
|
24
25
|
end
|
25
26
|
|
@@ -36,13 +37,13 @@ describe "constraint_validations extension" do
|
|
36
37
|
|
37
38
|
it "should allow dropping the sequel_constraint_validations table" do
|
38
39
|
@db.drop_constraint_validations_table
|
39
|
-
@db.sqls.must_equal ["DROP TABLE sequel_constraint_validations"]
|
40
|
+
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'sequel_constraint_validations')", "DROP TABLE sequel_constraint_validations"]
|
40
41
|
end
|
41
42
|
|
42
43
|
it "should allow dropping the sequel_constraint_validations table with a non-default table name" do
|
43
44
|
@db.constraint_validations_table = :foo
|
44
45
|
@db.drop_constraint_validations_table
|
45
|
-
@db.sqls.must_equal ["DROP TABLE foo"]
|
46
|
+
@db.sqls.must_equal ["DELETE FROM foo WHERE (table = 'foo')", "DROP TABLE foo"]
|
46
47
|
end
|
47
48
|
|
48
49
|
it "should allow dropping validations for a given table" do
|
@@ -50,6 +51,23 @@ describe "constraint_validations extension" do
|
|
50
51
|
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'foo')"]
|
51
52
|
end
|
52
53
|
|
54
|
+
it "should drop validations for a given table when dropping the table" do
|
55
|
+
@db.drop_table(:foo)
|
56
|
+
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'foo')", "DROP TABLE foo"]
|
57
|
+
|
58
|
+
@db.drop_table(:foo, :if_exists => true)
|
59
|
+
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'foo')", "DROP TABLE IF EXISTS foo"]
|
60
|
+
|
61
|
+
@db.drop_table?(:foo)
|
62
|
+
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'foo')", "DROP TABLE foo"]
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should not drop validations for a given table if the constraint validations table does not exist" do
|
66
|
+
def @db.table_exists?(_) false; end
|
67
|
+
@db.drop_table(:foo)
|
68
|
+
@db.sqls.must_equal ["DROP TABLE foo"]
|
69
|
+
end
|
70
|
+
|
53
71
|
it "should allow dropping validations for a given table and column" do
|
54
72
|
@db.drop_constraint_validations_for(:table=>:foo, :column=>:bar)
|
55
73
|
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE ((table = 'foo') AND (column = 'bar'))"]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require_relative "spec_helper"
|
2
2
|
|
3
|
-
if (RUBY_VERSION >= '2.0.0' && RUBY_ENGINE == 'ruby')
|
3
|
+
if (RUBY_VERSION >= '2.0.0' && RUBY_ENGINE == 'ruby') || (RUBY_ENGINE == 'jruby' && (JRUBY_VERSION >= '9.3' || (JRUBY_VERSION.match(/\A9\.2\.(\d+)/) && $1.to_i >= 7)))
|
4
4
|
Sequel.extension :core_refinements, :pg_array, :pg_hstore, :pg_row, :pg_range, :pg_row_ops, :pg_range_ops, :pg_array_ops, :pg_hstore_ops, :pg_json, :pg_json_ops
|
5
5
|
using Sequel::CoreRefinements
|
6
6
|
|
@@ -22,6 +22,28 @@ describe Sequel::Model, "hook_class_methods plugin" do
|
|
22
22
|
hooks.values.all?(&:frozen?).must_equal true
|
23
23
|
end
|
24
24
|
|
25
|
+
deprecated ".hook_blocks method should yield each hook block" do
|
26
|
+
c = model_class.call Sequel::Model
|
27
|
+
a = []
|
28
|
+
c.hook_blocks(:before_save){|b| a << b}
|
29
|
+
a.must_equal []
|
30
|
+
|
31
|
+
pr = proc{adds << 'hi'}
|
32
|
+
c.before_save(&pr)
|
33
|
+
a = []
|
34
|
+
c.hook_blocks(:before_save){|b| a << b}
|
35
|
+
a.must_equal [pr]
|
36
|
+
|
37
|
+
c.before_save(&pr)
|
38
|
+
a = []
|
39
|
+
c.hook_blocks(:before_save){|b| a << b}
|
40
|
+
a.must_equal [pr, pr]
|
41
|
+
|
42
|
+
a = []
|
43
|
+
c.hook_blocks(:after_save){|b| a << b}
|
44
|
+
a.must_equal []
|
45
|
+
end
|
46
|
+
|
25
47
|
it "should be definable using a block" do
|
26
48
|
adds = []
|
27
49
|
c = model_class.call Sequel::Model do
|