sequel 5.19.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +24 -0
  3. data/doc/release_notes/5.20.0.txt +89 -0
  4. data/doc/transactions.rdoc +38 -0
  5. data/lib/sequel/adapters/mysql2.rb +2 -2
  6. data/lib/sequel/adapters/shared/postgres.rb +5 -7
  7. data/lib/sequel/database/query.rb +1 -1
  8. data/lib/sequel/database/schema_generator.rb +1 -1
  9. data/lib/sequel/database/transactions.rb +57 -5
  10. data/lib/sequel/dataset/placeholder_literalizer.rb +4 -1
  11. data/lib/sequel/dataset/query.rb +1 -1
  12. data/lib/sequel/extensions/schema_dumper.rb +1 -1
  13. data/lib/sequel/model/associations.rb +35 -9
  14. data/lib/sequel/model/plugins.rb +104 -0
  15. data/lib/sequel/plugins/association_dependencies.rb +3 -3
  16. data/lib/sequel/plugins/association_pks.rb +14 -4
  17. data/lib/sequel/plugins/class_table_inheritance.rb +1 -0
  18. data/lib/sequel/plugins/composition.rb +13 -9
  19. data/lib/sequel/plugins/finder.rb +2 -2
  20. data/lib/sequel/plugins/hook_class_methods.rb +17 -5
  21. data/lib/sequel/plugins/inverted_subsets.rb +2 -2
  22. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +61 -32
  23. data/lib/sequel/plugins/subset_conditions.rb +2 -2
  24. data/lib/sequel/plugins/validation_class_methods.rb +5 -3
  25. data/lib/sequel/version.rb +1 -1
  26. data/spec/adapters/postgres_spec.rb +32 -0
  27. data/spec/core/database_spec.rb +73 -2
  28. data/spec/core/schema_spec.rb +6 -0
  29. data/spec/extensions/class_table_inheritance_spec.rb +30 -8
  30. data/spec/extensions/core_refinements_spec.rb +1 -1
  31. data/spec/extensions/hook_class_methods_spec.rb +22 -0
  32. data/spec/extensions/migration_spec.rb +13 -0
  33. data/spec/extensions/pg_auto_constraint_validations_spec.rb +8 -0
  34. data/spec/extensions/s_spec.rb +1 -1
  35. data/spec/extensions/schema_dumper_spec.rb +4 -2
  36. data/spec/integration/plugin_test.rb +15 -0
  37. data/spec/integration/transaction_test.rb +50 -0
  38. data/spec/model/associations_spec.rb +84 -4
  39. data/spec/model/plugins_spec.rb +111 -0
  40. metadata +4 -2
@@ -99,13 +99,13 @@ describe Sequel::Model, "associate" do
99
99
  class ::ParParent < Sequel::Model; end
100
100
  klass = Class.new(Sequel::Model(:nodes))
101
101
 
102
- klass.many_to_one(:par_parent, :order=>:a){1}
103
- klass.one_to_many(:par_parent1s, :class=>'ParParent', :limit=>12){4}
104
- klass.many_to_many(:par_parent2s, :class=>:ParParent, :uniq=>true){2}
102
+ klass.many_to_one(:par_parent, :order=>:a){|ds| 1}
103
+ klass.one_to_many(:par_parent1s, :class=>'ParParent', :limit=>12){|ds| 4}
104
+ klass.many_to_many(:par_parent2s, :class=>:ParParent, :uniq=>true){|ds| 2}
105
105
 
106
106
  klass.many_to_one :par, :clone=>:par_parent, :select=>:b
107
107
  klass.one_to_many :par1s, :clone=>:par_parent1s, :order=>:b, :limit=>10, :block=>nil
108
- klass.many_to_many(:par2s, :clone=>:par_parent2s, :order=>:c){3}
108
+ klass.many_to_many(:par2s, :clone=>:par_parent2s, :order=>:c){|ds| 3}
109
109
  klass.many_to_one :par3, :clone=>:par
110
110
 
111
111
  klass.association_reflection(:par).associated_class.must_equal ParParent
@@ -861,6 +861,50 @@ describe Sequel::Model, "one_to_one" do
861
861
  "UPDATE attributes SET y = 5, node_id = 1234 WHERE (id = 3)"]
862
862
  end
863
863
 
864
+ it "should have setter method handle associations to models with joined datasets" do
865
+ db = Sequel.mock
866
+ c = Class.new(Sequel::Model(db)) do
867
+ set_dataset(db[:attributes].join(:foo, :attribute_id=>:id))
868
+ def _insert_dataset
869
+ db[:attributes]
870
+ end
871
+ def _update_dataset
872
+ db[:attributes].where(pk_hash)
873
+ end
874
+ @instance_dataset = dataset.limit(1).naked.skip_limit_check
875
+ unrestrict_primary_key
876
+ columns :id, :node_id, :y
877
+ end
878
+
879
+ @c2.one_to_one :attribute, :class => c
880
+ attrib = c.new(:id=>3)
881
+
882
+ db.fetch = [[], {:id=>3}]
883
+ @c2.load(:id => 1234).attribute = attrib
884
+ DB.sqls.must_equal []
885
+ db.sqls.must_equal [
886
+ "SELECT * FROM (SELECT * FROM attributes INNER JOIN foo ON (foo.attribute_id = attributes.id)) AS attributes LIMIT 1",
887
+ "SELECT * FROM (SELECT * FROM attributes INNER JOIN foo ON (foo.attribute_id = attributes.id)) AS attributes WHERE (node_id = 1234) LIMIT 1",
888
+ "INSERT INTO attributes (id, node_id) VALUES (3, 1234)",
889
+ "SELECT * FROM (SELECT * FROM attributes INNER JOIN foo ON (foo.attribute_id = attributes.id)) AS attributes WHERE (id = 3) LIMIT 1"]
890
+
891
+ db.fetch = [[{:id=>4}], {:id=>3, :node_id=>1234}]
892
+ db.numrows = 1
893
+ @c2.load(:id => 1234).attribute = c.load(:id=>3)
894
+ db.sqls.must_equal [
895
+ "SELECT * FROM (SELECT * FROM attributes INNER JOIN foo ON (foo.attribute_id = attributes.id)) AS attributes WHERE (node_id = 1234) LIMIT 1",
896
+ "UPDATE attributes SET node_id = NULL WHERE (id = 4)",
897
+ "UPDATE attributes SET node_id = 1234 WHERE (id = 3)"]
898
+
899
+ db.fetch = [[{:id=>4}], {:id=>3, :node_id=>1234}]
900
+ @c2.load(:id => 1234).attribute = c.new(:id=>3)
901
+ db.sqls.must_equal [
902
+ "SELECT * FROM (SELECT * FROM attributes INNER JOIN foo ON (foo.attribute_id = attributes.id)) AS attributes WHERE (node_id = 1234) LIMIT 1",
903
+ "UPDATE attributes SET node_id = NULL WHERE (id = 4)",
904
+ "INSERT INTO attributes (id, node_id) VALUES (3, 1234)",
905
+ "SELECT * FROM (SELECT * FROM attributes INNER JOIN foo ON (foo.attribute_id = attributes.id)) AS attributes WHERE (id = 3) LIMIT 1"]
906
+ end
907
+
864
908
  it "should use implicit key if omitted" do
865
909
  @c2.dataset = @c2.dataset.with_fetch({})
866
910
  @c2.one_to_one :parent, :class => @c2
@@ -958,6 +1002,42 @@ describe Sequel::Model, "one_to_one" do
958
1002
  DB.sqls.must_equal ["SELECT * FROM nodes WHERE ((parent_id = 100) AND (x > 1)) ORDER BY name LIMIT 1 OFFSET 20"]
959
1003
  end
960
1004
 
1005
+ it "should support :dataset options with different types of arity" do
1006
+ @c2.one_to_one :child_20, :class => @c2, :key=>:id, :dataset=>proc{model.filter(:parent_id=>pk)}
1007
+ @c2.load(:id => 100).child_20
1008
+ DB.sqls.must_equal ["SELECT * FROM nodes WHERE (parent_id = 100) LIMIT 1"]
1009
+
1010
+ @c2.one_to_one :child_20, :class => @c2, :key=>:id, :dataset=>proc{|_| model.filter(:parent_id=>pk)}
1011
+ @c2.load(:id => 100).child_20
1012
+ DB.sqls.must_equal ["SELECT * FROM nodes WHERE (parent_id = 100) LIMIT 1"]
1013
+
1014
+ @c2.one_to_one :child_20, :class => @c2, :key=>:id, :dataset=>proc{|_, *| model.filter(:parent_id=>pk)}
1015
+ @c2.load(:id => 100).child_20
1016
+ DB.sqls.must_equal ["SELECT * FROM nodes WHERE (parent_id = 100) LIMIT 1"]
1017
+
1018
+ @c2.one_to_one :child_20, :class => @c2, :key=>:id, :dataset=>proc{|*| model.filter(:parent_id=>pk)}
1019
+ @c2.load(:id => 100).child_20
1020
+ DB.sqls.must_equal ["SELECT * FROM nodes WHERE (parent_id = 100) LIMIT 1"]
1021
+ end
1022
+
1023
+ deprecated "should support :dataset option that requires multiple arguments" do
1024
+ @c2.one_to_one :child_20, :class => @c2, :key=>:id, :dataset=>proc{|_, _| model.filter(:parent_id=>pk)}
1025
+ @c2.load(:id => 100).child_20
1026
+ DB.sqls.must_equal ["SELECT * FROM nodes WHERE (parent_id = 100) LIMIT 1"]
1027
+ end
1028
+
1029
+ deprecated "should support association block requires no arguments" do
1030
+ @c2.one_to_one :child_20, :class => @c2, :key=>:id do model.filter(:parent_id=>pk) end
1031
+ @c2.load(:id => 100).child_20
1032
+ DB.sqls.must_equal ["SELECT * FROM nodes WHERE (parent_id = 100)"]
1033
+ end
1034
+
1035
+ deprecated "should support association block requires multiple arguments" do
1036
+ @c2.one_to_one :child_20, :class => @c2, :key=>:id do |_, _| model.filter(:parent_id=>pk) end
1037
+ @c2.load(:id => 100).child_20
1038
+ DB.sqls.must_equal ["SELECT * FROM nodes WHERE (parent_id = 100)"]
1039
+ end
1040
+
961
1041
  it "should return nil if primary_key value is nil" do
962
1042
  @c2.one_to_one :parent, :class => @c2, :primary_key=>:node_id
963
1043
 
@@ -316,3 +316,114 @@ describe "Sequel::Model.plugin" do
316
316
  a.must_equal ['sequel/plugins/something_or_other']
317
317
  end
318
318
  end
319
+
320
+ describe "Sequel::Plugins.def_sequel_method" do
321
+ before do
322
+ @m = Class.new
323
+ @scope = @m.new
324
+ end
325
+
326
+ it "should define methods using block" do
327
+ m0 = Sequel::Plugins.def_sequel_method(@m, "x", 0){1}
328
+ m0.must_be_kind_of Symbol
329
+ m0.must_match /\A_sequel_x_\d+\z/
330
+ @scope.send(m0).must_equal 1
331
+
332
+ m1 = Sequel::Plugins.def_sequel_method(@m, "x", 1){|x| [x, 2]}
333
+ m1.must_be_kind_of Symbol
334
+ m1.must_match /\A_sequel_x_\d+\z/
335
+ @scope.send(m1, 3).must_equal [3, 2]
336
+ end
337
+
338
+ it "should define public methods" do
339
+ proc{@scope.public_send(Sequel::Plugins.def_sequel_method(@m, "x", 0){1})}.must_raise NoMethodError
340
+ end
341
+
342
+ it "should accept symbols as method name and return the same symbol" do
343
+ m0 = Sequel::Plugins.def_sequel_method(@m, :_roda_foo, 0){1}
344
+ m0.must_equal :_roda_foo
345
+ @scope.send(m0).must_equal 1
346
+ end
347
+
348
+ it "should handle optional arguments and splats for expected_arity 0" do
349
+ m2 = Sequel::Plugins.def_sequel_method(@m, "x", 0){|*x| [x, 3]}
350
+ @scope.send(m2).must_equal [[], 3]
351
+
352
+ m3 = Sequel::Plugins.def_sequel_method(@m, "x", 0){|x=5| [x, 4]}
353
+ @scope.send(m3).must_equal [5, 4]
354
+
355
+ m4 = Sequel::Plugins.def_sequel_method(@m, "x", 0){|x=6, *y| [x, y, 5]}
356
+ @scope.send(m4).must_equal [6, [], 5]
357
+ end
358
+
359
+ it "should should optional arguments and splats for expected_arity 1" do
360
+ m2 = Sequel::Plugins.def_sequel_method(@m, "x", 1){|y, *x| [y, x, 3]}
361
+ @scope.send(m2, :a).must_equal [:a, [], 3]
362
+
363
+ m3 = Sequel::Plugins.def_sequel_method(@m, "x", 1){|y, x=5| [y, x, 4]}
364
+ @scope.send(m3, :b).must_equal [:b, 5, 4]
365
+
366
+ m4 = Sequel::Plugins.def_sequel_method(@m, "x", 1){|y, x=6, *z| [y, x, z, 5]}
367
+ @scope.send(m4, :c).must_equal [:c, 6, [], 5]
368
+ end
369
+
370
+ deprecated "should handle differences in arity" do
371
+ m0 = Sequel::Plugins.def_sequel_method(@m, "x", 0){|x| [x, 1]}
372
+ @scope.send(m0).must_equal [nil, 1]
373
+
374
+ m1 = Sequel::Plugins.def_sequel_method(@m, "x", 1){2}
375
+ @scope.send(m1, 3).must_equal 2
376
+
377
+ m1 = Sequel::Plugins.def_sequel_method(@m, "x", 1){|x, y| [x, y]}
378
+ @scope.send(m1, 4).must_equal [4, nil]
379
+ end
380
+
381
+ it "should raise for unexpected expected_arity" do
382
+ proc{Sequel::Plugins.def_sequel_method(@m, "x", 2){|x|}}.must_raise Sequel::Error
383
+ end
384
+
385
+ it "should fail if a lambda with invalid arity is passed" do
386
+ m0 = Sequel::Plugins.def_sequel_method(@m, "x", 0, &lambda{|x| [x, 1]})
387
+ proc{@scope.send(m0)}.must_raise ArgumentError
388
+
389
+ m1 = Sequel::Plugins.def_sequel_method(@m, "x", 1, &lambda{2})
390
+ proc{@scope.send(m1, 1)}.must_raise ArgumentError
391
+ end
392
+
393
+ if RUBY_VERSION > '2.1'
394
+ it "should raise for required keyword arguments for expected_arity 0 or 1" do
395
+ proc{eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|b:| [b, 1]}", binding)}.must_raise Sequel::Error
396
+ proc{eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|c=1, b:| [c, b, 1]}", binding)}.must_raise Sequel::Error
397
+ proc{eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|x, b:| [b, 1]}", binding)}.must_raise Sequel::Error
398
+ proc{eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|x, c=1, b:| [c, b, 1]}", binding)}.must_raise Sequel::Error
399
+ end
400
+
401
+ it "should ignore keyword arguments for expected_arity 0" do
402
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|b:2| [b, 1]}", binding)).must_equal [2, 1]
403
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|**b| [b, 1]}", binding)).must_equal [{}, 1]
404
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|c=1, b:2| [c, b, 1]}", binding)).must_equal [1, 2, 1]
405
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|c=1, **b| [c, b, 1]}", binding)).must_equal [1, {}, 1]
406
+ end
407
+
408
+ deprecated "should ignore keyword arguments for expected_arity 0 with invalid arity" do
409
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|x, b:2| [x, b, 1]}", binding)).must_equal [nil, 2, 1]
410
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|x, **b| [x, b, 1]}", binding)).must_equal [nil, {}, 1]
411
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|x, c=1, b:2| [x, c, b, 1]}", binding)).must_equal [nil, 1, 2, 1]
412
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|x, c=1, **b| [x, c, b, 1]}", binding)).must_equal [nil, 1, {}, 1]
413
+ end
414
+
415
+ deprecated "should ignore keyword arguments for expected_arity 1 with invalid arity" do
416
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|b:2| [b, 1]}", binding), 3).must_equal [2, 1]
417
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|**b| [b, 1]}", binding), 3).must_equal [{}, 1]
418
+ end
419
+
420
+ it "should ignore keyword arguments for expected_arity 1" do
421
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|c=1, b:2| [c, b, 1]}", binding), 3).must_equal [3, 2, 1]
422
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|c=1, **b| [c, b, 1]}", binding), 3).must_equal [3, {}, 1]
423
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|x, b:2| [x, b, 1]}", binding), 3).must_equal [3, 2, 1]
424
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|x, **b| [x, b, 1]}", binding), 3).must_equal [3, {}, 1]
425
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|x, c=1, b:2| [x, c, b, 1]}", binding), 3).must_equal [3, 1, 2, 1]
426
+ @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|x, c=1, **b| [x, c, b, 1]}", binding), 3).must_equal [3, 1, {}, 1]
427
+ end
428
+ end
429
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.19.0
4
+ version: 5.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-02 00:00:00.000000000 Z
11
+ date: 2019-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -203,6 +203,7 @@ extra_rdoc_files:
203
203
  - doc/release_notes/5.17.0.txt
204
204
  - doc/release_notes/5.18.0.txt
205
205
  - doc/release_notes/5.19.0.txt
206
+ - doc/release_notes/5.20.0.txt
206
207
  files:
207
208
  - CHANGELOG
208
209
  - MIT-LICENSE
@@ -293,6 +294,7 @@ files:
293
294
  - doc/release_notes/5.18.0.txt
294
295
  - doc/release_notes/5.19.0.txt
295
296
  - doc/release_notes/5.2.0.txt
297
+ - doc/release_notes/5.20.0.txt
296
298
  - doc/release_notes/5.3.0.txt
297
299
  - doc/release_notes/5.4.0.txt
298
300
  - doc/release_notes/5.5.0.txt