diff options
author | Kir Shatrov <shatrov@me.com> | 2017-05-21 13:12:08 +0100 |
---|---|---|
committer | Kir Shatrov <shatrov@me.com> | 2017-05-22 15:03:36 +0100 |
commit | 5e6312e1745dc278ba0a99bf2bc7b78977785d35 (patch) | |
tree | 88a91eaf40b79c1c06e211b59a7e28daeba852e7 | |
parent | 03a2de4d063f52250105c08c0c05d64c5d42561d (diff) | |
download | rails-5e6312e1745dc278ba0a99bf2bc7b78977785d35.tar.gz rails-5e6312e1745dc278ba0a99bf2bc7b78977785d35.tar.bz2 rails-5e6312e1745dc278ba0a99bf2bc7b78977785d35.zip |
Support INSERT with multiple values
-rw-r--r-- | lib/arel/insert_manager.rb | 4 | ||||
-rw-r--r-- | lib/arel/nodes.rb | 1 | ||||
-rw-r--r-- | lib/arel/nodes/values_list.rb | 13 | ||||
-rw-r--r-- | lib/arel/visitors/to_sql.rb | 22 | ||||
-rw-r--r-- | test/test_insert_manager.rb | 54 |
5 files changed, 94 insertions, 0 deletions
diff --git a/lib/arel/insert_manager.rb b/lib/arel/insert_manager.rb index f9a598e8b7..dcbac6cb43 100644 --- a/lib/arel/insert_manager.rb +++ b/lib/arel/insert_manager.rb @@ -40,5 +40,9 @@ module Arel def create_values values, columns Nodes::Values.new values, columns end + + def create_values_list(rows) + Nodes::ValuesList.new(rows) + end end end diff --git a/lib/arel/nodes.rb b/lib/arel/nodes.rb index 8c9815a96b..bb8ad6500b 100644 --- a/lib/arel/nodes.rb +++ b/lib/arel/nodes.rb @@ -44,6 +44,7 @@ require 'arel/nodes/function' require 'arel/nodes/count' require 'arel/nodes/extract' require 'arel/nodes/values' +require 'arel/nodes/values_list' require 'arel/nodes/named_function' # windows diff --git a/lib/arel/nodes/values_list.rb b/lib/arel/nodes/values_list.rb new file mode 100644 index 0000000000..b39aaa1465 --- /dev/null +++ b/lib/arel/nodes/values_list.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true +module Arel + module Nodes + class ValuesList < Node + attr_reader :rows + + def initialize(rows) + @rows = rows + super() + end + end + end +end diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb index 486c51a183..3f1e390dcc 100644 --- a/lib/arel/visitors/to_sql.rb +++ b/lib/arel/visitors/to_sql.rb @@ -166,6 +166,28 @@ module Arel collector << "FALSE" end + def visit_Arel_Nodes_ValuesList o, collector + collector << "VALUES " + + len = o.rows.length - 1 + o.rows.each_with_index { |row, i| + collector << '(' + row_len = row.length - 1 + row.each_with_index do |value, k| + case value + when Nodes::SqlLiteral, Nodes::BindParam + collector = visit(value, collector) + else + collector << quote(value) + end + collector << COMMA unless k == row_len + end + collector << ')' + collector << COMMA unless i == len + } + collector + end + def visit_Arel_Nodes_Values o, collector collector << "VALUES (" diff --git a/test/test_insert_manager.rb b/test/test_insert_manager.rb index 97317791fe..8b61a2791e 100644 --- a/test/test_insert_manager.rb +++ b/test/test_insert_manager.rb @@ -28,6 +28,60 @@ module Arel } end + it 'works with multiple values' do + table = Table.new(:users) + manager = Arel::InsertManager.new + manager.into table + + manager.columns << table[:id] + manager.columns << table[:name] + + manager.values = manager.create_values_list([ + %w{1 david}, + %w{2 kir}, + ["3", Arel.sql('DEFAULT')], + ]) + + manager.to_sql.must_be_like %{ + INSERT INTO \"users\" (\"id\", \"name\") VALUES ('1', 'david'), ('2', 'kir'), ('3', DEFAULT) + } + end + + it 'literals in multiple values are not escaped' do + table = Table.new(:users) + manager = Arel::InsertManager.new + manager.into table + + manager.columns << table[:name] + + manager.values = manager.create_values_list([ + [Arel.sql('*')], + [Arel.sql('DEFAULT')], + ]) + + manager.to_sql.must_be_like %{ + INSERT INTO \"users\" (\"name\") VALUES (*), (DEFAULT) + } + end + + it 'works with multiple single values' do + table = Table.new(:users) + manager = Arel::InsertManager.new + manager.into table + + manager.columns << table[:name] + + manager.values = manager.create_values_list([ + %w{david}, + %w{kir}, + [Arel.sql('DEFAULT')], + ]) + + manager.to_sql.must_be_like %{ + INSERT INTO \"users\" (\"name\") VALUES ('david'), ('kir'), (DEFAULT) + } + end + it "inserts false" do table = Table.new(:users) manager = Arel::InsertManager.new |