From 67d2f9a922314e4ac51d99981efe886a3a7aca86 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 9 Sep 2010 15:20:25 -0700 Subject: adding a Value node so that SqlLiteral values may be used --- lib/arel/insert_manager.rb | 17 ++++++++++++----- lib/arel/nodes.rb | 1 + lib/arel/nodes/insert_statement.rb | 4 ++-- lib/arel/nodes/values.rb | 11 +++++++++++ lib/arel/select_manager.rb | 8 ++++++++ lib/arel/sql/engine.rb | 2 +- lib/arel/visitors/to_sql.rb | 11 +++++++---- spec/arel/insert_manager_spec.rb | 5 ++--- spec/arel/select_manager_spec.rb | 15 +++++++++++++++ 9 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 lib/arel/nodes/values.rb diff --git a/lib/arel/insert_manager.rb b/lib/arel/insert_manager.rb index accabb4377..75e6299def 100644 --- a/lib/arel/insert_manager.rb +++ b/lib/arel/insert_manager.rb @@ -11,16 +11,23 @@ module Arel end def columns; @head.columns end - def values; @head.values end + def values= val; @head.values = val; end def insert fields return if fields.empty? - @head.relation ||= fields.first.first.relation + if String === fields + @head.values = SqlLiteral.new(fields) + else + @head.relation ||= fields.first.first.relation - fields.each do |column, value| - @head.columns << column - @head.values << value + values = [] + + fields.each do |column, value| + @head.columns << column + values << value + end + @head.values = Nodes::Values.new values end end end diff --git a/lib/arel/nodes.rb b/lib/arel/nodes.rb index 3d73de2f7a..2894deab57 100644 --- a/lib/arel/nodes.rb +++ b/lib/arel/nodes.rb @@ -7,6 +7,7 @@ require 'arel/nodes/in' require 'arel/nodes/lock' require 'arel/nodes/function' require 'arel/nodes/count' +require 'arel/nodes/values' require 'arel/nodes/sum' require 'arel/nodes/max' require 'arel/nodes/avg' diff --git a/lib/arel/nodes/insert_statement.rb b/lib/arel/nodes/insert_statement.rb index 629e7a8513..a5e1a0bb9b 100644 --- a/lib/arel/nodes/insert_statement.rb +++ b/lib/arel/nodes/insert_statement.rb @@ -6,13 +6,13 @@ module Arel def initialize @relation = nil @columns = [] - @values = [] + @values = nil end def initialize_copy other super @columns = @columns.clone - @values = @values.clone + @values = @values.clone if @values end end end diff --git a/lib/arel/nodes/values.rb b/lib/arel/nodes/values.rb new file mode 100644 index 0000000000..eab70a362a --- /dev/null +++ b/lib/arel/nodes/values.rb @@ -0,0 +1,11 @@ +module Arel + module Nodes + class Values + attr_accessor :expressions + + def initialize exprs + @expressions = exprs + end + end + end +end diff --git a/lib/arel/select_manager.rb b/lib/arel/select_manager.rb index bcfb1dc4eb..2be6d52fef 100644 --- a/lib/arel/select_manager.rb +++ b/lib/arel/select_manager.rb @@ -102,6 +102,14 @@ module Arel raise NotImplementedError end + # FIXME: this method should go away + def insert values + im = InsertManager.new @engine + im.into @ctx.froms.last + im.insert values + @engine.connection.insert im.to_sql + end + private def collapse exprs return exprs.first if exprs.length == 1 diff --git a/lib/arel/sql/engine.rb b/lib/arel/sql/engine.rb index d1a3880735..8917f5f294 100644 --- a/lib/arel/sql/engine.rb +++ b/lib/arel/sql/engine.rb @@ -2,7 +2,7 @@ module Arel module Sql class Engine def self.new thing - warn "#{caller.first} -- Engine will be removed" + #warn "#{caller.first} -- Engine will be removed" thing end end diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb index 0f2de092ea..25b7f005ea 100644 --- a/lib/arel/visitors/to_sql.rb +++ b/lib/arel/visitors/to_sql.rb @@ -37,13 +37,16 @@ module Arel quote_column_name x.name }.join ', '})" unless o.columns.empty?), - ("VALUES (#{o.values.map { |value| - value ? visit(value) : 'NULL' - }.join ', '})" unless o.values.empty?), - + (visit o.values if o.values), ].compact.join ' ' end + def visit_Arel_Nodes_Values o + "VALUES (#{o.expressions.map { |value| + value ? visit(value) : 'NULL' + }.join ', '})" + end + def visit_Arel_Nodes_SelectStatement o [ o.cores.map { |x| visit x }.join, diff --git a/spec/arel/insert_manager_spec.rb b/spec/arel/insert_manager_spec.rb index ed0725e79d..807f1324d2 100644 --- a/spec/arel/insert_manager_spec.rb +++ b/spec/arel/insert_manager_spec.rb @@ -88,7 +88,7 @@ module Arel manager = Arel::InsertManager.new Table.engine manager.into table - manager.values << 1 + manager.values = Nodes::Values.new [1] manager.to_sql.should be_like %{ INSERT INTO "users" VALUES (1) } @@ -101,8 +101,7 @@ module Arel manager = Arel::InsertManager.new Table.engine manager.into table - manager.values << 1 - manager.values << "aaron" + manager.values = Nodes::Values.new [1, 'aaron'] manager.columns << table[:id] manager.columns << table[:name] manager.to_sql.should be_like %{ diff --git a/spec/arel/select_manager_spec.rb b/spec/arel/select_manager_spec.rb index 0b45b8180c..883a518aca 100644 --- a/spec/arel/select_manager_spec.rb +++ b/spec/arel/select_manager_spec.rb @@ -22,9 +22,24 @@ module Arel end alias :update :execute alias :delete :execute + alias :insert :execute end describe 'select manager' do + describe 'insert' do + it 'uses the select FROM' do + engine = EngineProxy.new Table.engine + table = Table.new :users + manager = Arel::SelectManager.new engine + manager.from table + manager.insert 'VALUES(NULL)' + + engine.executed.last.should be_like %{ + INSERT INTO "users" VALUES(NULL) + } + end + end + describe 'lock' do # This should fail on other databases it 'adds a lock node' do -- cgit v1.2.3