Why is `execute` dropping back to the shell instead of sending SQL directly to my Postgres server?
I have a migration which is using execute
to send raw SQL to the Postgres backend.
class TestExecuteMethod < ActiveRecord::Migration
def self.up
execute ('SELECT 1;')
end
def self.down
end
end
Instead of going to my database, it seems execute
is going to the shell:
** Invoke db:migrate (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute db:migrate
== TestExecuteMethod: migrating ==============================================
++ executing: SELECT 1;
sh: SELECT: command not found
++ [FAIL]
== TestExecuteMethod: migrated (0.0041s) =====================================
** Invoke db:schema:dump (first_time)
** Invoke environment
** Execute db:schema:dump
But, when I instead do
ActiveRecord::Base.connection.execute(sql)
开发者_JAVA百科
It works as expected.
Why is this?
I'm using Rails 3.0.9 and the pg
gem.
Add this to your migration:
def self.trace_execute(io=$stderr, &block)
set_trace_func proc {|event, file, line, id, binding, classname|
io.printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname if id.to_s == 'execute'
}
# trace the passed block
yield
ensure
# disable (note: the disable call is the last thing traced)
set_trace_func nil
end
Then wrap your execute call in a block like this:
trace_execute { execute ('SELECT 1;') }
and paste the first few lines of trace output. I suspect something is intercepting the execute call before the db adapter can receive it.
Usually I'd recommend using something like
puts method(:execute).inspect
but that probably won't work in this case because method_missing is involved.
First glance is that execute is actually a shell exec - not a db exec.
I will be honest, I normally do use execute inside migrations - and that seems to work, i.e.
def self.up
execute <<EOF
some SQL
EOF
end
精彩评论