Как я могу вставить строку в поток ввода-вывода в Ruby? - PullRequest
0 голосов
/ 04 июля 2019

Я пытаюсь написать скрипт на Ruby, который настроит дамп SQL (взятый из pg_dump), чтобы он мог правильно настроить таблицу.

Пока все хорошо, как я это настроил; Я смог File.read файл, вставить слово, добавить кое-что в конец, и File.write файл снова.

Тем не менее, я сейчас работаю с дампом размером почти 7 ГБ, и он не справляется (File.read вызывает EINVAL ошибок, и с именем файла проблем нет). Поэтому я хочу использовать один поток, чтобы найти правильное место для вставки этого слова, а затем перейти к концу и добавить дополнительные элементы.

Но я не могу вставить это слово. Я хочу изменить

DROP TABLE public.programmes;
SET search_path = public, pg_catalog;

до

DROP TABLE public.programmes CASCADE;
SET search_path = public, pg_catalog;

но используя file_stream.puts (#write и #<< не лучше), я заканчиваю тем, что перезаписываю часть следующей строки:

DROP TABLE public.programmes CASCADE;
ch_path = public, pg_catalog;

... и я бы предпочел не зацикливаться (читать восемь символов, искать восемь символов, писать предыдущие восемь символов) до конца файла, до 7 ГБ.

(Возможно, я вернусь к тому, чтобы вернуться к началу файла - это всего лишь 460 B - но мне все равно придется знать, как вставить некоторые символы в начале.)

Есть ли способ сделать это?

1 Ответ

1 голос
/ 04 июля 2019

Поскольку место, куда нужно было перейти CASCADE, было так близко к началу, я закончил тем, что сначала записал восемь символов в файл , , а затем добавил результаты pg_restore.Затем я мог бы пройтись по потоку файлов с самого начала и поместить строку на место ...

# Could be any eight characters, but these are a valid SQL comment in case it fails
File.write(path, "-------\n")
system("pg_restore #{pgr_options} >> #{path}")

File.open(path, 'r+') do |stream|
  content = ''
  stream.pos = 8

  # The semicolon is needed to delimit the table name
  content << stream.getc until content =~ /(DROP TABLE public.[a-z_]*);/
  stream.rewind
  stream << content[0..-2] << ' CASCADE;'

... прежде чем перейти к концу и добавить материал.

  stream.seek 0, :END
  stream.puts "ALTER TABLE ONLY blah blah blah..."
end
...