File: insert_conflict_spec.rb

package info (click to toggle)
ruby-sequel 5.63.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 10,408 kB
  • sloc: ruby: 113,747; makefile: 3
file content (103 lines) | stat: -rw-r--r-- 4,531 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
require_relative "spec_helper"

describe "insert_conflict plugin" do
  def model_class(adapter)
    db = Sequel.mock(:host=>adapter, :fetch=>{:id=>1, :s=>2}, :autoid=>1)
    db.extend_datasets{def quote_identifiers?; false end}
    model = Class.new(Sequel::Model)
    model.dataset = db[:t]
    model.columns :id, :s, :o
    model.plugin :insert_conflict
    db.sqls
    model
  end

  def model_class_plugin_first(adapter)
    model = Class.new(Sequel::Model)
    model.plugin :insert_conflict
    model = Class.new(model)
    db = Sequel.mock(:host=>adapter, :fetch=>{:id=>1, :s=>2}, :autoid=>1)
    db.extend_datasets{def quote_identifiers?; false end}
    model.dataset = db[:t]
    model.columns :id, :s, :o
    db.sqls
    model
  end

  it "should use INSERT ON CONFLICT when inserting on PostgreSQL" do
    model = model_class(:postgres)
    model.new(:s=>'A', :o=>1).insert_conflict.save
    model.db.sqls.must_equal ["INSERT INTO t (s, o) VALUES ('A', 1) ON CONFLICT DO NOTHING RETURNING *"]

    model.new(:s=>'A', :o=>1).insert_conflict(:target=>:s, :update => {:o => Sequel[:excluded][:o]}).save
    model.db.sqls.must_equal ["INSERT INTO t (s, o) VALUES ('A', 1) ON CONFLICT (s) DO UPDATE SET o = excluded.o RETURNING *"]
  end

  it "should use INSERT ON CONFLICT when inserting on SQLITE" do
    model = model_class(:sqlite)
    model.new(:s=>'A', :o=>1).insert_conflict.save
    model.db.sqls.must_equal ["INSERT INTO t (s, o) VALUES ('A', 1) ON CONFLICT DO NOTHING",
      "SELECT * FROM t WHERE (id = 1) LIMIT 1"]

    model.new(:s=>'A', :o=>1).insert_conflict(:target=>:s, :update => {:o => Sequel[:excluded][:o]}).save
    model.db.sqls.must_equal ["INSERT INTO t (s, o) VALUES ('A', 1) ON CONFLICT (s) DO UPDATE SET o = excluded.o",
      "SELECT * FROM t WHERE (id = 2) LIMIT 1"]
  end

  it "should raise Error if calling insert_conflict on a model instance that isn't new" do
    m = model_class(:postgres).load(:s=>'A', :o=>1)
    proc{m.insert_conflict}.must_raise Sequel::Error
  end

  it "should raise if loading plugin into a model class with a dataset that doesn't support insert_conflict" do
    model = Class.new(Sequel::Model)
    model.dataset = Sequel.mock[:t]
    proc{model.plugin :insert_conflict}.must_raise Sequel::Error
  end

  it "should work if loading into a model class without a dataset on PostgreSQL" do
    model = model_class_plugin_first(:postgres)
    model.new(:s=>'A', :o=>1).insert_conflict.save
    model.db.sqls.must_equal ["INSERT INTO t (s, o) VALUES ('A', 1) ON CONFLICT DO NOTHING RETURNING *"]

    model.new(:s=>'A', :o=>1).insert_conflict(:target=>:s, :update => {:o => Sequel[:excluded][:o]}).save
    model.db.sqls.must_equal ["INSERT INTO t (s, o) VALUES ('A', 1) ON CONFLICT (s) DO UPDATE SET o = excluded.o RETURNING *"]
  end

  it "should work if loading into a model class without a dataset on SQLITE" do
    model = model_class_plugin_first(:sqlite)
    model.new(:s=>'A', :o=>1).insert_conflict.save
    model.db.sqls.must_equal ["INSERT INTO t (s, o) VALUES ('A', 1) ON CONFLICT DO NOTHING",
      "SELECT * FROM t WHERE (id = 1) LIMIT 1"]

    model.new(:s=>'A', :o=>1).insert_conflict(:target=>:s, :update => {:o => Sequel[:excluded][:o]}).save
    model.db.sqls.must_equal ["INSERT INTO t (s, o) VALUES ('A', 1) ON CONFLICT (s) DO UPDATE SET o = excluded.o",
      "SELECT * FROM t WHERE (id = 2) LIMIT 1"]
  end

  it "should work if the prepared_statements plugin is loaded before" do
    db = Sequel.mock(:host=>'sqlite', :fetch=>{:id=>1, :s=>2}, :autoid=>1, :numrows=>1)
    db.extend_datasets{def quote_identifiers?; false end}
    model = Class.new(Sequel::Model)
    model.dataset = db[:t]
    model.columns :id, :s
    model.plugin :prepared_statements
    model.plugin :insert_conflict
    db.sqls
    model.create(:s=>'a').update(:s=>'b')
    db.sqls.must_equal ["INSERT INTO t (s) VALUES ('a')", "SELECT * FROM t WHERE (id = 1) LIMIT 1", "UPDATE t SET s = 'b' WHERE (id = 1)"]
  end

  it "should work if the prepared_statements plugin is loaded after" do
    db = Sequel.mock(:host=>'postgres', :fetch=>{:id=>1, :s=>2}, :autoid=>1, :numrows=>1)
    db.extend_datasets{def quote_identifiers?; false end}
    model = Class.new(Sequel::Model)
    model.dataset = db[:t]
    model.columns :id, :s
    model.plugin :insert_conflict
    model.plugin :prepared_statements
    db.sqls
    model.create(:s=>'a').update(:s=>'b')
    db.sqls.must_equal ["INSERT INTO t (s) VALUES ('a') RETURNING *", "UPDATE t SET s = 'b' WHERE (id = 1)"]
  end
end