为什么“execute”返回到 shell,而不是直接将 SQL 发送到我的 Postgres 服务器?

发布于 2024-12-04 18:33:22 字数 895 浏览 1 评论 0原文

我有一个迁移,它使用 execute 将原始 SQL 发送到 Postgres 后端。

class TestExecuteMethod < ActiveRecord::Migration
  def self.up
    execute ('SELECT 1;')
  end

  def self.down
  end
end

execute 似乎没有访问我的数据库,而是访问了 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

但是,当我这样做时,

ActiveRecord::Base.connection.execute(sql)

它会按预期工作。

这是为什么呢?

我正在使用 Rails 3.0.9 和 pg gem。

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)

It works as expected.

Why is this?

I'm using Rails 3.0.9 and the pg gem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

久光 2024-12-11 18:33:22

将其添加到您的迁移中:

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

然后将执行调用包装在如下所示的块中:

trace_execute { execute ('SELECT 1;') }

并粘贴跟踪输出的前几行。我怀疑在数据库适配器可以接收执行调用之前,有什么东西正在拦截它。

通常我建议使用类似的东西

puts method(:execute).inspect

,但在这种情况下可能不起作用,因为涉及 method_missing 。

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.

弱骨蛰伏 2024-12-11 18:33:22

乍一看,execute 实际上是一个 shell exec,而不是一个 db exec。

老实说,我通常会在迁移中使用执行 - 这似乎有效,即

  def self.up
    execute <<EOF
some SQL
EOF
  end

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文