Skip to content

Commit 6538c2a

Browse files
committed
Make insert_returning_select use RETURNING when using table_select plugin
This changes insert_returning_select to handle SELECT table.* and use RETURNING * for the INSERT. Previously, insert_returning_select only handled explicit column selections, such as those created by the column_select plugin.
1 parent 071d656 commit 6538c2a

File tree

4 files changed

+29
-1
lines changed

4 files changed

+29
-1
lines changed

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
=== master
22

3+
* Make insert_returning_select use RETURNING when using table_select plugin (jeremyevans) (#2339)
4+
35
* Fix Database#listen in postgres adapter to ignore all notifications after UNLISTEN (jeremyevans)
46

57
* Make Model.any? forward to the dataset, to work better with the any_not_empty extension (jeremyevans) (#2337)

lib/sequel/plugins/insert_returning_select.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
module Sequel
44
module Plugins
5-
# If the model's dataset selects explicit columns and the
5+
# If the model's dataset selects explicit columns (or table.*) and the
66
# database supports it, the insert_returning_select plugin will
77
# automatically set the RETURNING clause on the dataset used to
88
# insert rows to the columns selected, which allows the default model
@@ -45,13 +45,22 @@ def reset_instance_dataset
4545
ret
4646
end
4747

48+
RETURN_ALL = [Sequel::Dataset::WILDCARD].freeze
49+
private_constant :RETURN_ALL
50+
4851
# Determine the columns to use for the returning clause, or return nil
4952
# if they can't be determined and a returning clause should not be
5053
# added automatically.
5154
def insert_returning_columns(ds)
5255
return unless ds.supports_returning?(:insert)
5356
return unless values = ds.opts[:select]
5457

58+
# SELECT table.* -> RETURNING *
59+
if values.length == 1 && values[0].is_a?(Sequel::SQL::ColumnAll)
60+
return RETURN_ALL
61+
end
62+
63+
# SELECT column1, table.column2, ... -> RETURNING column1, column2, ...
5564
values = values.map{|v| ds.unqualified_column_for(v)}
5665
if values.all?
5766
values

lib/sequel/plugins/table_select.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ module Plugins
99
# in the result sets (and possibly overwrite columns in the
1010
# current model with the same name).
1111
#
12+
# Note that by default on databases that supporting RETURNING,
13+
# using this plugin will cause instance creations
14+
# to use two queries (insert and refresh) instead of a single
15+
# query using RETURNING. You can use the insert_returning_select
16+
# plugin to automatically use RETURNING for instance creations
17+
# for models using this plugin.
18+
#
1219
# Usage:
1320
#
1421
# # Make all model subclasses select table.*

spec/extensions/insert_returning_select_spec.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ def insert_select(*v) with_sql_first("#{insert_sql(*v)}#{" RETURNING #{opts[:ret
3838
@db.sqls.must_equal ['INSERT INTO albums (x) VALUES (2) RETURNING id, x']
3939
end
4040

41+
it "should add a returning clause when dataset selects all columns from a single table" do
42+
@Album = Class.new(Sequel::Model(@db[:albums]))
43+
@Album.columns :id, :x
44+
@Album.plugin :table_select
45+
@Album.plugin :insert_returning_select
46+
@db.sqls
47+
@Album.create(:x=>2).must_equal @Album.load(:id=>1, :x=>2)
48+
@db.sqls.must_equal ['INSERT INTO albums (x) VALUES (2) RETURNING *']
49+
end
50+
4151
it "should not add a returning clause if no columns are selected" do
4252
@Album.plugin :insert_returning_select
4353
@Album.dataset = @Album.dataset.select_all

0 commit comments

Comments
 (0)