PostgreSQL COPY FROM PROGRAM: команда на сервере
COPY ... FROM PROGRAM запускает shell-команду на сервере базы и читает её stdout как входные данные. Так можно импортировать сжатый файл или поток из другой утилиты без промежуточной распаковки. Команда выполняется от имени ОС-пользователя PostgreSQL, поэтому доступ к ней должен быть только у администратора.
Импортировать gzip-файл с сервера
CREATE TABLE events (
id integer PRIMARY KEY,
payload text NOT NULL
);
COPY events (id, payload)
FROM PROGRAM 'gzip -dc /var/backups/events.csv.gz'
WITH (FORMAT csv, HEADER true);
SELECT count(*) FROM events;gzip -dc печатает распакованный CSV в stdout, а COPY разбирает его по формату csv с заголовком. Путь и команда должны быть фиксированными и доверенными: не подставляйте туда имя файла из пользовательского запроса. Если команда завершится с ненулевым кодом, COPY отменится, и строки не попадут в таблицу.
Для выполнения нужен суперпользователь или роль с правом pg_execute_server_program (PostgreSQL 11+), а также INSERT на таблицу. На управляемых сервисах вроде RDS эта возможность часто отключена. Проверьте права заранее: \du покажет роль, а SHOW is_superuser — текущий статус.
Обратная операция COPY ... TO PROGRAM отправляет данные в команду, например в gzip или ssh. Она так же опасна: команда получает доступ к данным и выполняется с правами сервера. Не используйте PROGRAM в веб-приложении и не объединяйте с динамическим SQL.
Безопасная альтернатива для приложения — COPY ... FROM STDIN с потоком из клиента или psql-команда \copy, которая читает файл на машине клиента. Для больших загрузок отдавайте файл в приложение и передавайте его драйвером, а не просите сервер запускать shell.
Проверяйте кодировку, разделители и NULL-маркеры до импорта. COPY FROM вызывает триггеры и проверяет ограничения таблицы, но не выполняет правила CREATE RULE. Если на таблице висят тяжёлые триггеры, импорт большого файла может быть заметно медленнее обычной вставки.
Документация: COPY, pg_execute_server_program.