我有一个数据库转储文件,其中包含各种插入语句和偶尔的“\ connect”命令
问题是PG::Connection.exec()
不接受psql的\
- \i
或\c
等命令。
有没有办法使用ruby-pg(或者可能是另一个pg-gem)来完成这项工作?
由于数据库位于不同的主机上,因此我无法使用Unix套接字,因此无法在没有密码的情况下以用户postgres
进行连接。
答案 0 :(得分:1)
使用像pg_restore这样的psql命令行工具可能更容易:
pg_restore -d newdb db.dump
如果您对托管原始数据库的框具有ssh访问权限并知道需要转储哪个表,则可以将ssh插入到框中并直接将pg_dump输出管道传输到本地数据库。类似的东西:
ssh user@original_database pg_dump -U remote_user_name -T schema_name.table_name mydb | psql -U local_user_name -d local_database
答案 1 :(得分:0)
答案是“否”,因为反斜杠命令不是Postgres命令。它们是 psql 命令,这是默认的命令行客户端。没有第三方工具会复制这些命令,因为它们不属于 libpq API。
现在,那就是\连接文件中唯一的反斜杠命令?如果是这样,那么您应该能够通过解析出\ connect语句中的数据库名称来实现这一点,然后将转储文件拆分为从每个\ connect语句后面的第一行开始的块。此时,只需针对与该块的\ connect语句中给出的数据库连接正常运行每个块。
据我所知,由于必须重新验证用户的凭据,因此无法在不创建新连接的情况下重新连接到其他数据库。这甚至是psql在幕后做的。
还有另外一个想法,如果只有一个\ connect语句,它紧跟在CREATE DATABASE语句之后,紧接在CREATE ROLE之类的语句之后,那么如果你创建数据库作为一个单独的步骤并同时删除CREATE DATABASE和\连接文件中的语句,你可以在没有分块的情况下完成它。请记住,您仍然需要两个连接,因为在创建数据库之前无法连接到数据库,并且仍然无法在中间连接中更改为新数据库。
答案 2 :(得分:0)
在尝试了很多东西,包括在\ connect行等处分割文件后,我最终将它称为“旧式shell脚本方式”,这就是我想要避免的方式。但我得到某个地方
我现在正在做的是:
insert_command = "cat #{dump_file_path} | " +
"ssh -p #{port} -i #{key} #{ssh_user}@#{db_host} " +
"\"su - postgres -c 'cat > /tmp/rb_dump.sql && psql -f /tmp/rb_dump.sql ; rm /tmp/rb_dump.sql'\""
Open3.popen3 insert_command do |stdin, stdout, stderr, t|
unless t.value.to_s.include? "exit 0"
<handle error>
end
end
在我看来这完全是hacky,但它有效^^
我的另一个解决方案是下一个代码,它有一个很大的问题(如下所述)
def insert_database_dump(dump_file_handle, host, user, password, database = nil)
begin
pg = PG.connect(host: host, user: user, password: password, dbname: database)
until dump_file_handle.eof?
line = dump_file_handle.readline(";")
if line =~ /connect\s(\w*)/
line.gsub!("\\connect", "").strip!
insert_database_dump(dump_file_handle, host, user, password, line)
else
pg.exec(line)
end
end
ensure
pg.finish unless pg.finished?
end
end
代码执行以下操作(仅限重要部分):
尽管事件可能有更优雅的方法来调用自身,但除非在sql转储中有注释,否则这种方法有效。 问题是评论看起来像这样:
-- foo: bar; bam: baz;
所以当用“;”分割时,它会执行“ - foo:bar;”,这是有效的,因为它是一个注释但是失败了“bam:baz;”
我目前没有简单的解决方案来动态删除评论行。所以Open3解决方案必须要做,直到找到。
干杯, 斯蒂芬