Skip to main content

Stream-export filtered PostgreSQL rows to CSV and bulk-import via COPY

Project description

pg-export-import

Stream-export filtered PostgreSQL rows to CSV and bulk-import via COPY. Supports multi-table, FK-aware pipelines with idempotent re-runs.

Installation

pip install pg-export-import

Requirements

  • Python 3.11+
  • PostgreSQL (source and target can be on different servers)

Library usage

Single table

from pg_export_import import ConnectionConfig, export_and_import

src = ConnectionConfig(host="db1.example.com", dbname="prod", user="app", password="...")
tgt = ConnectionConfig(host="db2.example.com", dbname="staging", user="app", password="...")

result = export_and_import(
    source_config=src,
    target_config=tgt,
    source_table="public.orders",
    target_table="public.orders",
    where_clause="created_at >= %s",
    where_params=("2024-01-01",),
    csv_path="/data/exports/orders.csv",   # optional; auto-generated if omitted
    delete_before_import=True,             # optional; delete target rows before importing (default False)
    # delete_where_clause="created_at >= %s",  # optional; defaults to where_clause
    # delete_where_params=("2024-01-01",),     # optional; defaults to where_params
)
print(result.status, result.exported_count, result.imported_count, result.deleted_count)

result.status is one of "success", "export_failed", "delete_failed", or "import_failed".

Multi-table pipeline

from pg_export_import import ConnectionConfig, run_pipeline

src = ConnectionConfig(...)
tgt = ConnectionConfig(...)

tables = [
    # parents before children (FK order)
    {"source_table": "customers",   "target_table": "customers",   "where_clause": ""},
    {"source_table": "orders",      "target_table": "orders",      "where_clause": "created_at >= %s", "where_params": ("2024-01-01",)},
    {"source_table": "order_items", "target_table": "order_items", "where_clause": "created_at >= %s", "where_params": ("2024-01-01",)},
]

results = run_pipeline(
    source_config=src,
    target_config=tgt,
    tables=tables,
    csv_dir="/data/exports",        # optional; defaults to tempdir
    fetch_size=5000,                # optional; rows per round-trip (default 5000)
    delete_before_import=True,      # optional; set False to append without deleting (default True)
)
for r in results:
    print(r["table"], r["status"], r["exported"], r["imported"])

CSV file naming

Each pipeline run captures a single timestamp once at start. All tables in that run share the same timestamp:

{csv_dir}/{source_table}_{YYYYMMDD_HHMMSS}.csv

Dots in schema-qualified names become underscores:

source_table csv_dir filename
orders /data/exports orders_20250320_143022.csv
public.orders /data/exports public_orders_20250320_143022.csv
  • The csv_dir is created automatically if it does not exist.
  • On success, CSV files are deleted.
  • On failure, CSV files are preserved for debugging or re-import.

Table config schema

Each entry in the tables argument to run_pipeline supports:

Key Type Required Description
source_table str yes Source table reference ("table" or "schema.table")
target_table str yes Target table reference
where_clause str yes SQL WHERE fragment (empty string = all rows)
where_params tuple | dict | None no Bind values for where_clause placeholders
delete_where_clause str no WHERE fragment for DELETE on target (defaults to where_clause)
delete_where_params tuple | dict | None no Bind values for delete_where_clause
fetch_size int no Per-table override for rows fetched per round-trip; takes precedence over run_pipeline's fetch_size argument
delete_before_import bool no Per-table override; when False, skips DELETE for this table regardless of the pipeline-level argument

Security notes

  • where_clause is embedded as a raw SQL fragment — it must come from trusted application code, never from user input.
  • Runtime filter values must be passed via where_params, not interpolated into the clause string.
  • All table and column identifiers are validated and safely quoted via psycopg.sql.Identifier.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pg_export_import-0.1.0b3.tar.gz (17.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pg_export_import-0.1.0b3-py3-none-any.whl (17.5 kB view details)

Uploaded Python 3

File details

Details for the file pg_export_import-0.1.0b3.tar.gz.

File metadata

  • Download URL: pg_export_import-0.1.0b3.tar.gz
  • Upload date:
  • Size: 17.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.0 {"installer":{"name":"uv","version":"0.11.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pg_export_import-0.1.0b3.tar.gz
Algorithm Hash digest
SHA256 475f48b67fbe66fbfd65f4e91fdffd7fe6be2bae2910d6df68d14dc2f315b344
MD5 d33fa182396e237f32d6ac729bf7cfba
BLAKE2b-256 a23342407cf25d5d0afaae98e39caf7e6104f77bac165ce7d5f4674389a0c599

See more details on using hashes here.

File details

Details for the file pg_export_import-0.1.0b3-py3-none-any.whl.

File metadata

  • Download URL: pg_export_import-0.1.0b3-py3-none-any.whl
  • Upload date:
  • Size: 17.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.0 {"installer":{"name":"uv","version":"0.11.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pg_export_import-0.1.0b3-py3-none-any.whl
Algorithm Hash digest
SHA256 7d689d1a254c5942b34dcff49ab49c7e2265382a4ffdb481cd0137e66f9f2df4
MD5 1ce4f71c6b9a17eb070f8e76a483caaf
BLAKE2b-256 1489680b8592fcd1c01e9aaf798e6793570d09a3196599bb71d33e7921c29832

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page