pgcopy — CLI-утилита, которая экспортирует выбранные объекты PostgreSQL (таблицы, представления и материализованные
представления) в один bundle-файл и затем импортирует их в другую БД в виде обычных таблиц.
- Возможности
- Демо
- Быстрый старт
- Команды и флаги
- Подключение к PostgreSQL
- Шифрование bundle
config.toml- Типовой workflow
- Сборка проекта
export: снимаетDDL+ данные выбранных объектов в одинbundle(по умолчаниюtar.zst), опционально шифрует паролем.import: разворачиваетbundleв целевую БД как таблицы (стратегииreplace/append, режим--ddl-only).info: показывает метаданныеbundleбез подключения к PostgreSQL.- Параллельная обработка объектов:
--concurrency(дляexportиimport).
Экспорт:
export PGHOST=company-host
export PGPORT=5432
export PGUSER=pguser
export PGPASSWORD=pgpassword
export PGDATABASE=company-dwh
pgcopy export --config config.toml --out bundle.tar.zstИмпорт:
pgcopy import --in bundle.tar.zst --host localhost --dbname gas_dwh --username pguser --pgpassword pguser-
Составьте
config.tomlсо списком объектов. -
Укажите параметры подключения к PostgreSQL через CLI, TOML-конфиг или переменные окружения (см. ниже).
-
На исходной БД выполните экспорт:
pgcopy export --config ./config.toml --out ./bundle.tar.zst -
На целевой стороне выполните импорт:
pgcopy import --in ./bundle.tar.zst --mode replace
Синопсис:
pgcopy export --config <path/to/config.toml> --out <path/to/bundle> [--concurrency N] [--password PASSWORD] [--dry-run] [--quiet] [--no-progress]
pgcopy import --in <path/to/bundle> [--mode replace|append] [--concurrency N] [--ddl-only] [--password PASSWORD] [--dry-run] [--quiet] [--no-progress]
pgcopy info --in <path/to/bundle> [--format text|json] [--objects] [--password PASSWORD] [--quiet]Подсказка: pgcopy --help, pgcopy export --help, pgcopy import --help, pgcopy info --help.
Глобальные флаги:
--quiet: отключает служебный вывод (баннер запуска и progress bars).--no-progress: отключает только progress bars (удобно для CI-логов).--dry-run: разрешает параметры и печатает сводку без подключения к PostgreSQL и записи файлов.
--config: путь кconfig.toml.--out: путь к выходномуbundle(например./bundle.tar.zst).--concurrency: параллелизм экспорта (поддерживается алиас--concurencyбез второйr). Приоритет разрешения значения:CLI > general.concurrency из TOML > PGCOPY_CONCURRENCY > 1.--password: пароль для шифрованияbundle(fallback: envPASSWORD).- Параметры подключения к source PostgreSQL: см. раздел ниже.
--in: путь к входномуbundle, созданному командойexport.--mode: стратегия импорта при наличии целевой таблицы:replace(по умолчанию): дропает целевую таблицу, затем создает заново и загружает данные. Операция выполняется атомарно на уровне объекта (BEGIN/COMMIT): при ошибке во времяreplaceизменения по этому объекту откатываются (ROLLBACK).append: если таблица уже есть, проверяет совместимость и дозаписывает данные.
--ddl-only: выполняет только DDL-часть импорта (создание/подготовка таблиц), без загрузки данных.--concurrency: параллелизм импорта (количество объектов, обрабатываемых параллельно; алиас--concurency).--password: пароль для расшифровкиbundle(fallback: envPASSWORD).- Параметры подключения к target PostgreSQL: см. раздел ниже.
--format text(по умолчанию): человекочитаемый вывод.--format json: машинночитаемый вывод.--objects: печатает метаданные по каждому объекту из manifest.--password: пароль для расшифровкиbundle(fallback: envPASSWORD).
Параметры подключения можно задавать несколькими способами. Приоритет (от высшего к низшему):
| Приоритет | host | port | dbname | user | password |
|---|---|---|---|---|---|
| 1 | --host |
--port |
--dbname |
--username |
--pgpassword |
| 2 | [connection] в TOML |
[connection] в TOML |
[connection] в TOML |
[connection] в TOML |
[connection] в TOML |
| 3 | – | – | – | – | .pgpass |
| 4 | PGHOST |
PGPORT |
PGDATABASE |
PGUSER |
PGPASSWORD |
| Дефолт | Unix-сокет | 5432 |
OS-user / postgres |
OS-user / postgres |
(нет) |
--host--port--dbname--username(alias:--user)--pgpassword
В config.toml (только для команды export) можно указать параметры подключения в секции [connection].
Значения могут ссылаться на переменные окружения через {VAR_NAME}.
Если переменная не установлена — параметр считается не заданным (как будто его нет в конфиге).
[connection]
host = "{MY_PGHOST}"
port = "{MY_PGPORT}"
dbname = "myapp"
user = "app_user"
password = "{MY_PGPASSWORD}"Или просто явные значения:
[connection]
host = "db.example.com"
port = 5433
dbname = "analytics"
user = "reader"Стандартные переменные окружения PostgreSQL:
PGHOST(по умолчанию Unix-сокет /localhost, если не задан)PGPORT(по умолчанию5432, если не задан)PGDATABASE(по умолчанию имя пользователя ОС, если не задана)PGUSER(по умолчанию имя пользователя ОС, если не задан)PGPASSWORD(опционально)
Если пароль не задан через --pgpassword, [connection] или PGPASSWORD, дополнительно используется стандартный .pgpass
(~/.pgpass на Unix, %APPDATA%\postgres\pgpass.conf на Windows).
Пример через env:
export PGHOST=127.0.0.1
export PGPORT=5432
export PGDATABASE=app_db
export PGUSER=app_user
export PGPASSWORD=secretПример через CLI:
pgcopy export \
--config ./config.toml \
--out ./bundle.tar.zst \
--host 127.0.0.1 \
--port 5432 \
--dbname app_db \
--username app_user \
--pgpassword secretПример через TOML-конфиг с env-ссылками:
# config.toml содержит:
# [connection]
# host = "{MY_HOST}"
# dbname = "{MY_DB}"
export MY_HOST=db.internal
export MY_DB=analytics
pgcopy export --config ./config.toml --out ./bundle.tar.zstbundle можно шифровать/расшифровывать паролем:
- через
--password - или через env
PASSWORD(если--passwordне указан)
Если пароль не задан ни там, ни там, bundle создается/читается без шифрования.
Пример экспорта с паролем:
pgcopy export --config ./config.toml --out ./bundle.enc --password "strong-passphrase"Пример импорта с паролем из env:
export PASSWORD="strong-passphrase"
pgcopy import --in ./bundle.enc --mode replaceЕсли bundle зашифрован, а пароль не передан, import/info завершатся ошибкой.
Конфиг используется командой export и описывает список объектов для выгрузки и общие параметры экспорта.
Минимальный пример:
[general]
data_format = "binary"
compression = "zstd"
consistent_snapshot = true
concurrency = 4
[[objects]]
select = "select * from public.orders"
[[objects]]
select = "select id, total_amount, created_at from public.orders"
target_schema = "archive"
target_name = "orders_snapshot"
[[objects]]
select = "select day, region, revenue from reporting.v_sales_daily"
target_schema = "snapshots"
target_name = "sales_daily"
[[objects]]
select = "select * from public.orders where created_at >= date '2026-01-01'"
[[objects]]
select = "select * from reporting.v_sales_daily"
export_as = "view"data_format:binary(по умолчанию) илиcsv.compression: сейчас поддерживается толькоzstd.consistent_snapshot: включает согласованное чтение в одномREPEATABLE READsnapshot (по умолчаниюtrue).concurrency: число параллельных workers экспорта (>= 1, по умолчанию1).
Позволяет задать или переопределить параметры подключения к БД в самом конфиге.
Поддерживает ссылки на переменные окружения через {VAR_NAME}.
Приоритет: CLI-флаги > [connection] > .pgpass/переменные окружения.
[connection]
host = "{MY_PGHOST}"
port = "{MY_PGPORT}"
dbname = "myapp"
user = "app_user"
password = "{MY_PGPASSWORD}"select: строка ограниченногоselectDSL (см. ниже).target_schemaиtarget_name: опционально переопределяют имя целевого объекта. Если задаете — задавайте оба поля, иначе конфиг не пройдет валидацию. Если не заданы — используютсяschema/nameисточника.export_as:table(по умолчанию) илиview.table: текущий режим snapshot/materialize (SELECT -> CREATE TABLE + COPY).view: в bundle сохраняетсяCREATE VIEW, а зависимости этой view автоматически добавляются в экспорт как таблицы. Дляexport_as = "view"разрешен только видselect * from schema.object(безWHERE/ORDER BY/LIMIT).
Поддерживаемые формы:
select * from schema.objectselect col1, col2 from schema.objectselect * except (col1, col2) from schema.objectselect ... from schema.object where <predicate>select ... from schema.object order by <expr>select ... from schema.object limit <N>- комбинация в порядке:
where ... order by ... limit ...
Ограничения:
- только один источник
schema.object; - без
JOIN/GROUP BY; - идентификаторы в
FROM/SELECT/EXCEPTможно указывать:- unquoted (
schema.object,col_name) — автоматически нормализуются в lower-case; - quoted (
"123schema"."Orders","Col Name") — сохраняются как есть;
- unquoted (
WHERE/ORDER BYвставляются в нормализованный SQL как есть;LIMITподдерживается как неотрицательное целое число;- клаузa должна идти в порядке
WHERE -> ORDER BY -> LIMIT; ;в DSL запрещен.
- Для
data_format = "binary"проверка совместимостиCOPYтребует одинаковую мажорную версию PostgreSQL между source и target. - Для
data_format = "csv"проверка по major-версии PostgreSQL не применяется. - Для колонок с
DEFAULT nextval(...::regclass)создается target-local sequence, и после импорта sequence синхронизируется сMAX(column)загруженных данных. - Для bundle, содержащих объекты с
export_as = "view", импорт нужно запускать с--concurrency 1. exportподдерживает параллелизм через--concurrency(алиас--concurency) и разрешает значение так:CLI > general.concurrency из TOML > PGCOPY_CONCURRENCY > 1.- Для
importпараллелизм задается CLI-флагом--concurrency(по умолчанию1).
Пример с CSV:
[general]
data_format = "csv"
compression = "zstd"
consistent_snapshot = true
concurrency = 2Экспорт:
pgcopy export --config ./config.toml --out ./bundle.tar.zstИмпорт:
pgcopy import --in ./bundle.tar.zst --mode replaceПараллельный режим:
[general]
concurrency = 4pgcopy export --config ./config.toml --out ./bundle.tar.zst --concurrency 4
pgcopy import --in ./bundle.tar.zst --mode replace --concurrency 4cargo build --releaseБинарник:
./target/release/pgcopy --help
