sequel 5.19.0 → 5.20.0

Sign up to get free protection for your applications and to get access to all the features.
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