Skip to content

Commit

Permalink
Support INSERT with multiple values
Browse files Browse the repository at this point in the history
  • Loading branch information
kirs committed May 22, 2017
1 parent 03a2de4 commit 5e6312e
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 0 deletions.
4 changes: 4 additions & 0 deletions lib/arel/insert_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,9 @@ def insert fields
def create_values values, columns
Nodes::Values.new values, columns
end

def create_values_list(rows)
Nodes::ValuesList.new(rows)
end
end
end
1 change: 1 addition & 0 deletions lib/arel/nodes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
require 'arel/nodes/count'
require 'arel/nodes/extract'
require 'arel/nodes/values'
require 'arel/nodes/values_list'
require 'arel/nodes/named_function'

# windows
Expand Down
13 changes: 13 additions & 0 deletions lib/arel/nodes/values_list.rb
Original file line number Diff line number Diff line change
@@ -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
22 changes: 22 additions & 0 deletions lib/arel/visitors/to_sql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,28 @@ def visit_Arel_Nodes_False o, collector
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 ("

Expand Down
54 changes: 54 additions & 0 deletions test/test_insert_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 5e6312e

Please sign in to comment.