Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用ruby pg插入数据库转储_Ruby_Postgresql_Dump_Psql - Fatal编程技术网

使用ruby pg插入数据库转储

使用ruby pg插入数据库转储,ruby,postgresql,dump,psql,Ruby,Postgresql,Dump,Psql,我有一个数据库转储文件,其中包含各种insert语句和偶尔使用的“\connect”命令 问题是PG::Connection.exec()不接受psql的\-命令,如\i或\c等 有没有办法使用ruby pg(或者其他pg gem)来完成这项工作 由于数据库位于不同的主机上,我无法使用Unix套接字,因此无法在没有密码的情况下以用户身份连接。使用psql命令行工具可能更容易,例如: 如果您对原始数据库所在的框具有ssh访问权限,并且知道需要转储哪个表,那么可以通过ssh将输出直接传输到本地数据库

我有一个数据库转储文件,其中包含各种insert语句和偶尔使用的“\connect”命令

问题是
PG::Connection.exec()
不接受psql的
\
-命令,如
\i
\c

有没有办法使用ruby pg(或者其他pg gem)来完成这项工作


由于数据库位于不同的主机上,我无法使用Unix套接字,因此无法在没有密码的情况下以用户身份连接。

使用psql命令行工具可能更容易,例如:

如果您对原始数据库所在的框具有ssh访问权限,并且知道需要转储哪个表,那么可以通过ssh将输出直接传输到本地数据库。比如:

ssh user@original_database pg_dump -U remote_user_name -T schema_name.table_name mydb | psql -U local_user_name -d local_database
答案是“否”,因为反斜杠命令不是Postgres命令。它们是psql命令,这是默认的命令行客户端。没有第三方工具会复制这些命令,因为它们不是libpq API的一部分

那么,\ connect是文件中唯一的反斜杠命令吗?如果是这样,那么您应该能够通过解析\connect语句中的数据库名称来实现这一点,然后将转储文件拆分为从每个\connect语句后的第一行开始的块。此时,只需对该块的\connect语句中给定的数据库连接正常运行每个块

据我所知,如果不创建新连接,就无法重新连接到其他数据库,因为必须重新验证用户的凭据。甚至psql在幕后也是这样做的


还有一个想法,如果只有一个\connect语句,并且它紧跟在CREATE ROLE等语句之后的CREATE DATABASE语句之后,那么如果将数据库作为单独的步骤创建,并从文件中删除CREATE DATABASE和\connect语句,则可以在不分块的情况下执行此操作。请记住,您仍然需要两个连接,因为在创建数据库之前无法连接到数据库,在连接到新数据库的过程中也无法更改。

在尝试了很多东西后,包括在\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
该代码执行以下操作(仅限重要部分):

  • 从sql中读取一行直到“;”(查询被分成几行,因此仅读取直到换行都不起作用
  • 执行查询
  • 如果该行看起来像“connect word”,则会选择“word”作为数据库名称,并使用“word”作为数据库名称再次调用该方法,当前文件句柄指向要从中继续操作的正确行
尽管可能有更优雅的方法来调用自己,但除非sql转储中有注释,否则这种方法是有效的。 问题是这些评论看起来像这样:

-- foo: bar; bam: baz;
因此,当使用“;”进行拆分时,它会执行“-foo:bar;”,这很有效,因为它是一个注释,但在使用“bam:baz;”时失败

我目前还没有一个简单的解决方案来即时删除评论行。所以Open3解决方案将不得不这样做,直到我找到答案

干杯,
Stefan

我的答案是直接针对这个问题的,但我必须问一个更具哲理的问题:如果您无法连接到数据库来加载脚本,并且显然无法安排由能够加载脚本的人来完成,那么您首先应该这样做吗?如果您无法在本地登录并且不知道密码,我认为您不应该这样做也许这是你的DBA的工作(或者你需要找一个更好的DBA)。请不要误以为这对我来说很难,但脚本应该使用psql加载。为什么你不能这样做是一个管理问题,而不是技术问题。这有点不同。我是dba和unix管理员。问题是我必须为那些没有太多经验的客户提供工具。我想写一百万个工具shell中的10个使我的生活更轻松。包括故障切换和恢复整个unix系统和数据库的整套套件。因此,我希望我知道我在做什么;)我目前正在将大部分shell内容迁移到ruby,因为我希望它是可测试的,并且更易于维护。我在shell中做了一些扭曲,我希望在ruby中不必这样做。包括大量嵌套的cmds。还有一件事&请不要误解我的意思。我觉得我必须在这里解释我自己。我维护这个系统(现在有20个,其中一些漂亮的复制工作正在进行),因为机器第一次进入数据中心。我是一个对系统了如指掌的人,我只是想让我的生活更轻松。是的,这是一种技术。问题我只是太懒了,我的生命也太短了,不能每天手工做每件事。信不信由你,我可以在8小时后离开工作岗位,因为工作是自动化的。我感谢你尽可能有效地做一些事情,因此问了一些愚蠢的问题,这是可行的,但我希望避免这种情况。如上所述,我已经在迁移ruby的shell脚本套件中使用了很难维护的大量嵌套命令,原因有很多。我有点想(作为最后的手段)用一种黑麦和管道的混合物通过那里或Open3。但我希望这会比那容易。我希望有一个pg gem能够做到这一点,这一切都令人不满意。但是,将sql分为两部分进行剥离并这样做更容易、更干净。建立两个(或更多)sql连接不是问题。它(如上所述)是回滚脚本的一部分,如果系统仍处于关闭状态,将执行该脚本。嗯,我从未使用过我正在迁移到ruby的shell,也从未希望在ruby迁移之后我必须使用它。但更好
 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
-- foo: bar; bam: baz;