pg-logical-repl 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pg_logical_repl-0.2.0/.github/workflows/publish.yml +126 -0
- pg_logical_repl-0.2.0/IMPLEMENTATION_STATUS.md +207 -0
- pg_logical_repl-0.2.0/MANIFEST.in +15 -0
- pg_logical_repl-0.2.0/PKG-INFO +425 -0
- pg_logical_repl-0.2.0/README.md +406 -0
- pg_logical_repl-0.2.0/docs/DDL_IMPLEMENTATION.md +170 -0
- pg_logical_repl-0.2.0/docs/RELEASING.md +92 -0
- pg_logical_repl-0.2.0/docs/TESTING.md +142 -0
- pg_logical_repl-0.2.0/examples/local.yaml +55 -0
- pg_logical_repl-0.2.0/infra/benchmark_validation.py +143 -0
- pg_logical_repl-0.2.0/infra/build_pg16.py +24 -0
- pg_logical_repl-0.2.0/infra/checkpoint_local.py +35 -0
- pg_logical_repl-0.2.0/infra/pg15.yaml +75 -0
- pg_logical_repl-0.2.0/infra/pg16.yaml +76 -0
- pg_logical_repl-0.2.0/infra/pg17.yaml +75 -0
- pg_logical_repl-0.2.0/infra/pg18.yaml +75 -0
- pg_logical_repl-0.2.0/infra/quality.py +233 -0
- pg_logical_repl-0.2.0/infra/reconfigure_local_wal.py +63 -0
- pg_logical_repl-0.2.0/infra/release_report.py +162 -0
- pg_logical_repl-0.2.0/infra/test_matrix.py +190 -0
- pg_logical_repl-0.2.0/pyproject.toml +62 -0
- pg_logical_repl-0.2.0/setup.cfg +4 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/__init__.py +3 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/__main__.py +6 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/capabilities.py +136 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/catalog.py +320 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/cli.py +277 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/component.py +66 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/config.py +356 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/coverage.py +117 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/cutover.py +239 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/db.py +131 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/ddl.py +352 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/ddl_queue.py +461 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/emergency.py +296 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/errors.py +44 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/health.py +194 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/integrity.py +185 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/logging_config.py +45 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/monitoring.py +277 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/plans.py +167 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/preflight.py +290 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/process.py +150 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/recovery.py +188 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/resync.py +267 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/roles.py +123 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/schema.py +89 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/security.py +117 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/service.py +773 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/sql/base.sql +67 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/sql/capture.sql +215 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/sql/ddl_support.sql +109 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/sql/freeze.sql +117 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/sql/replay.sql +48 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/state.py +160 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl/validation.py +353 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl.egg-info/PKG-INFO +425 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl.egg-info/SOURCES.txt +86 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl.egg-info/dependency_links.txt +1 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl.egg-info/entry_points.txt +2 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl.egg-info/requires.txt +11 -0
- pg_logical_repl-0.2.0/src/pg_logical_repl.egg-info/top_level.txt +1 -0
- pg_logical_repl-0.2.0/tests/check_distribution.py +107 -0
- pg_logical_repl-0.2.0/tests/fixtures/quality/recovery.json +13 -0
- pg_logical_repl-0.2.0/tests/integration/conftest.py +23 -0
- pg_logical_repl-0.2.0/tests/integration/spike_native_ddl.py +159 -0
- pg_logical_repl-0.2.0/tests/integration/test_ddl_expanded.py +463 -0
- pg_logical_repl-0.2.0/tests/integration/test_lifecycle.py +949 -0
- pg_logical_repl-0.2.0/tests/integration/test_p0_edges.py +268 -0
- pg_logical_repl-0.2.0/tests/integration/test_p0_recovery.py +323 -0
- pg_logical_repl-0.2.0/tests/integration/test_pg_play.py +497 -0
- pg_logical_repl-0.2.0/tests/integration/test_quality_cli.py +48 -0
- pg_logical_repl-0.2.0/tests/integration/test_quality_ddl_validation.py +118 -0
- pg_logical_repl-0.2.0/tests/integration/test_quality_generated.py +246 -0
- pg_logical_repl-0.2.0/tests/integration/test_quality_network.py +144 -0
- pg_logical_repl-0.2.0/tests/integration/test_quality_oracle.py +90 -0
- pg_logical_repl-0.2.0/tests/integration/test_quality_process.py +123 -0
- pg_logical_repl-0.2.0/tests/support/__init__.py +1 -0
- pg_logical_repl-0.2.0/tests/support/child.py +116 -0
- pg_logical_repl-0.2.0/tests/support/cli.py +113 -0
- pg_logical_repl-0.2.0/tests/support/network.py +36 -0
- pg_logical_repl-0.2.0/tests/support/oracle.py +229 -0
- pg_logical_repl-0.2.0/tests/support/wire.py +104 -0
- pg_logical_repl-0.2.0/tests/support/workload.py +248 -0
- pg_logical_repl-0.2.0/tests/test_component.py +118 -0
- pg_logical_repl-0.2.0/tests/test_foundations.py +155 -0
- pg_logical_repl-0.2.0/tests/test_p0.py +68 -0
- pg_logical_repl-0.2.0/tests/test_quality_stateio.py +77 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
name: Test and publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["**"]
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
pull_request:
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
tests:
|
|
15
|
+
name: Unit tests on Python ${{ matrix.python-version }}
|
|
16
|
+
runs-on: ubuntu-24.04
|
|
17
|
+
timeout-minutes: 15
|
|
18
|
+
strategy:
|
|
19
|
+
fail-fast: false
|
|
20
|
+
matrix:
|
|
21
|
+
python-version: ["3.11", "3.12"]
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
|
24
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
25
|
+
with:
|
|
26
|
+
python-version: ${{ matrix.python-version }}
|
|
27
|
+
- name: Install test dependencies
|
|
28
|
+
run: python -m pip install -e '.[test]'
|
|
29
|
+
- name: Check code style
|
|
30
|
+
run: |
|
|
31
|
+
ruff check .
|
|
32
|
+
ruff format --check .
|
|
33
|
+
- name: Run tests without PostgreSQL endpoints
|
|
34
|
+
run: python -m pytest -q --ignore=tests/integration
|
|
35
|
+
|
|
36
|
+
build:
|
|
37
|
+
name: Build and verify distributions
|
|
38
|
+
needs: tests
|
|
39
|
+
runs-on: ubuntu-24.04
|
|
40
|
+
timeout-minutes: 15
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
|
43
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
44
|
+
with:
|
|
45
|
+
python-version: "3.11"
|
|
46
|
+
- name: Install build tools
|
|
47
|
+
run: python -m pip install 'build>=1.2,<2' 'twine>=6,<7'
|
|
48
|
+
- name: Verify package and tag versions
|
|
49
|
+
run: |
|
|
50
|
+
python - <<'PY'
|
|
51
|
+
import ast
|
|
52
|
+
import os
|
|
53
|
+
import pathlib
|
|
54
|
+
import tomllib
|
|
55
|
+
|
|
56
|
+
version = tomllib.loads(pathlib.Path("pyproject.toml").read_text())["project"]["version"]
|
|
57
|
+
module = ast.parse(pathlib.Path("src/pg_logical_repl/__init__.py").read_text())
|
|
58
|
+
runtime = next(
|
|
59
|
+
ast.literal_eval(node.value)
|
|
60
|
+
for node in module.body
|
|
61
|
+
if isinstance(node, ast.Assign)
|
|
62
|
+
and any(isinstance(target, ast.Name) and target.id == "__version__" for target in node.targets)
|
|
63
|
+
)
|
|
64
|
+
if runtime != version:
|
|
65
|
+
raise SystemExit(f"Runtime version {runtime} differs from package version {version}")
|
|
66
|
+
if os.environ.get("GITHUB_REF_TYPE") == "tag" and os.environ["GITHUB_REF_NAME"] != f"v{version}":
|
|
67
|
+
raise SystemExit(f"Release tag must be v{version}")
|
|
68
|
+
PY
|
|
69
|
+
- name: Build sdist and wheel from sdist
|
|
70
|
+
run: python -m build
|
|
71
|
+
- name: Validate metadata and packaged documentation
|
|
72
|
+
run: |
|
|
73
|
+
python -m twine check dist/*
|
|
74
|
+
python tests/check_distribution.py dist/*.whl dist/*.tar.gz
|
|
75
|
+
- name: Smoke-test installed wheel outside the checkout
|
|
76
|
+
run: |
|
|
77
|
+
python -m venv "${RUNNER_TEMP}/pg-logical-repl-wheel"
|
|
78
|
+
"${RUNNER_TEMP}/pg-logical-repl-wheel/bin/python" -m pip install dist/*.whl
|
|
79
|
+
"${RUNNER_TEMP}/pg-logical-repl-wheel/bin/python" -m pip check
|
|
80
|
+
cd "${RUNNER_TEMP}"
|
|
81
|
+
"${RUNNER_TEMP}/pg-logical-repl-wheel/bin/pg-logical-repl" --version
|
|
82
|
+
"${RUNNER_TEMP}/pg-logical-repl-wheel/bin/pg-logical-repl" --machine --capabilities
|
|
83
|
+
"${RUNNER_TEMP}/pg-logical-repl-wheel/bin/pg-logical-repl" --machine --component-capabilities
|
|
84
|
+
"${RUNNER_TEMP}/pg-logical-repl-wheel/bin/python" - <<'PY'
|
|
85
|
+
import pathlib
|
|
86
|
+
import sysconfig
|
|
87
|
+
from importlib.resources import files
|
|
88
|
+
|
|
89
|
+
docs = pathlib.Path(sysconfig.get_path("data")) / "share/doc/pg-logical-repl"
|
|
90
|
+
for name in (
|
|
91
|
+
"README.md", "IMPLEMENTATION_STATUS.md", "docs/DDL_IMPLEMENTATION.md",
|
|
92
|
+
"docs/TESTING.md", "docs/RELEASING.md", "examples/local.yaml",
|
|
93
|
+
):
|
|
94
|
+
if not (docs / name).is_file():
|
|
95
|
+
raise SystemExit(f"Missing installed documentation: {name}")
|
|
96
|
+
if not files("pg_logical_repl").joinpath("sql/capture.sql").is_file():
|
|
97
|
+
raise SystemExit("Missing installed SQL resources")
|
|
98
|
+
print(f"Installed documentation: {docs}")
|
|
99
|
+
PY
|
|
100
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
101
|
+
with:
|
|
102
|
+
name: python-distributions
|
|
103
|
+
path: dist/
|
|
104
|
+
if-no-files-found: error
|
|
105
|
+
retention-days: 7
|
|
106
|
+
|
|
107
|
+
publish:
|
|
108
|
+
name: Publish to PyPI with OIDC
|
|
109
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && github.repository == 'O2eg/pg_logical_repl'
|
|
110
|
+
needs: build
|
|
111
|
+
runs-on: ubuntu-24.04
|
|
112
|
+
timeout-minutes: 15
|
|
113
|
+
concurrency:
|
|
114
|
+
group: pypi-publish
|
|
115
|
+
cancel-in-progress: false
|
|
116
|
+
environment:
|
|
117
|
+
name: pypi
|
|
118
|
+
url: https://pypi.org/p/pg-logical-repl
|
|
119
|
+
permissions:
|
|
120
|
+
id-token: write
|
|
121
|
+
steps:
|
|
122
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
123
|
+
with:
|
|
124
|
+
name: python-distributions
|
|
125
|
+
path: dist/
|
|
126
|
+
- uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Implementation status — 2026-11-11
|
|
2
|
+
|
|
3
|
+
The current `pg-logical-repl` package version is `0.2.0`.
|
|
4
|
+
|
|
5
|
+
The pip package and CLI were renamed on 2026-11-10; Python imports use
|
|
6
|
+
`pg_logical_repl`. Configuration, state, and JSON contract formats retain
|
|
7
|
+
`pg_logical_connector/*` identifiers for format compatibility.
|
|
8
|
+
|
|
9
|
+
**The production readiness criteria for version 1.0 have not yet been met.**
|
|
10
|
+
|
|
11
|
+
Tests run in local pg-stand environments. Cloud and managed PostgreSQL services
|
|
12
|
+
require separate qualification.
|
|
13
|
+
|
|
14
|
+
## 0.2.0: pg_play integration and distribution
|
|
15
|
+
|
|
16
|
+
Version 0.2.0 adds an optional pg_play component transport, capability discovery
|
|
17
|
+
and credential-free configuration inspection. Native machine output, config/state
|
|
18
|
+
formats and database ownership rules remain compatible. Laboratory image names
|
|
19
|
+
and SQL diagnostic prefixes now use `pg-logical-repl`.
|
|
20
|
+
|
|
21
|
+
Wheels and source distributions include the public Markdown guides and example
|
|
22
|
+
configuration. The release workflow checks both archives, verifies installation
|
|
23
|
+
outside the checkout, and publishes versioned tags through the PyPI Trusted
|
|
24
|
+
Publisher. See [RELEASING.md](docs/RELEASING.md).
|
|
25
|
+
|
|
26
|
+
Cross-project tests are in `tests/integration/test_pg_play.py`. They require the
|
|
27
|
+
optional pg_play installation and an explicitly owned PostgreSQL stand. Test
|
|
28
|
+
artifacts remain under `.runtime/`; they are excluded from the source repository.
|
|
29
|
+
|
|
30
|
+
Native completion events include the operation's exact plan hash and resulting
|
|
31
|
+
state, allowing pg_play to reconcile a lost response without replaying a completed
|
|
32
|
+
stage. CLI logging releases only its own handlers and restores previous logger
|
|
33
|
+
settings, including when used repeatedly by an embedding application or tests.
|
|
34
|
+
|
|
35
|
+
## 0.1.0a4: concurrent DDL and background validation
|
|
36
|
+
|
|
37
|
+
Background validation discards a chunk if captured DDL changes the schema between
|
|
38
|
+
reading the catalog and computing the aggregate. The cursor now includes the DDL
|
|
39
|
+
journal version, so a sequence of changes that restores the original schema also
|
|
40
|
+
invalidates the old result. Corruption confined to the target still moves the
|
|
41
|
+
migration to BLOCKED. Deterministic regressions cover column rename/drop, table
|
|
42
|
+
drop, changes at both aggregate computation boundaries, and restoration of the
|
|
43
|
+
original schema.
|
|
44
|
+
|
|
45
|
+
## Extended testing
|
|
46
|
+
|
|
47
|
+
Added an independent exact oracle, actual CLI process interruptions at operation
|
|
48
|
+
boundaries, a TCP fault proxy on three paths, sustained CLI migration with DML/DDL,
|
|
49
|
+
and a Hypothesis state machine with replay of saved operations. The runner builds
|
|
50
|
+
and installs a clean wheel. Profiles, verified properties, and limitations are
|
|
51
|
+
documented in [TESTING.md](docs/TESTING.md). New run results are stored separately
|
|
52
|
+
in `.runtime/quality-runs/`, excluded through `.gitignore`.
|
|
53
|
+
|
|
54
|
+
## P0 in 0.1.0a3
|
|
55
|
+
|
|
56
|
+
- Accepted settings have implemented behavior or a fixed supported profile.
|
|
57
|
+
`validate` rejects unsupported policies and parameters. Online validation,
|
|
58
|
+
drift and sequence intervals, textfile metrics, lag/queue/refresh alerts,
|
|
59
|
+
catchup stability, and ANALYZE at cutover are connected to runtime behavior.
|
|
60
|
+
- Continuous scans of primary key ranges persist the cursor, aggregate, and
|
|
61
|
+
awaited LSN. Confirmed mismatches block migration; source changes are
|
|
62
|
+
distinguished from mismatches. Waiting for apply does not stall the entire
|
|
63
|
+
daemon iteration.
|
|
64
|
+
- Checks cover supported schema/ACLs, the initial role state, verifiers and
|
|
65
|
+
membership, SQL resource identities and definitions, and DDL journal integrity.
|
|
66
|
+
The baseline is created during prepare; role changes on both sides are detected.
|
|
67
|
+
Verifiers are excluded from public reports. Pruning the acknowledged journal
|
|
68
|
+
preserves compact managed DDL receipts and resumes after a failure.
|
|
69
|
+
- Planned pause/resume/resolve operations include a WAL budget and pause deadline,
|
|
70
|
+
checks before leaving BLOCKED, whole-transaction skip by finish LSN, and
|
|
71
|
+
applied-manually resolution. Skipping without restoring the complete transaction
|
|
72
|
+
result leaves the migration BLOCKED.
|
|
73
|
+
- Resync of ordinary logged tables uses native tablesync and preserves incoming
|
|
74
|
+
foreign keys, validation flags, and comments. The original plan resumes an
|
|
75
|
+
interrupted step. Abort preserves partial data and restores removed foreign
|
|
76
|
+
keys as NOT VALID, explicitly listing them in state. This repair does not
|
|
77
|
+
support partitions or extension tables.
|
|
78
|
+
- Emergency abort and post-finalize commit with an unavailable source support
|
|
79
|
+
target-only detachment, ABORT_CLEANUP_PENDING/DETACH_CLEANUP_PENDING states, and
|
|
80
|
+
separate cleanup with ownership checks. The target is checked for changes and
|
|
81
|
+
finalize evidence for freshness. Unknown additional slots are not deleted
|
|
82
|
+
automatically.
|
|
83
|
+
- Partial status remains available when an endpoint is unavailable or the internal
|
|
84
|
+
schema is damaged. Schema/permission errors during a daemon iteration persist
|
|
85
|
+
a diagnosable BLOCKED state.
|
|
86
|
+
|
|
87
|
+
Commands, parameters, recovery, and limitations are documented in [README.md](README.md).
|
|
88
|
+
This version requires a new migration to record an integrity baseline. Automatic
|
|
89
|
+
adoption of old state, recovery from lost local state, takeover, and arbitrary
|
|
90
|
+
repair of damaged server resources are not implemented.
|
|
91
|
+
|
|
92
|
+
## 0.1.0a4 validation
|
|
93
|
+
|
|
94
|
+
The local PostgreSQL 15–18 matrix completed **417 successful test executions**, with
|
|
95
|
+
no failures, errors, or skipped tests. Each version passed 93 integration scenarios;
|
|
96
|
+
PG18 also passed 45 unit tests.
|
|
97
|
+
|
|
98
|
+
A separate 30-minute CLI run used 10,000 initial rows and four writers, executing
|
|
99
|
+
128,759 transactions and 892 DDL commands. It verified controller SIGKILL/SIGTERM,
|
|
100
|
+
a replication connection interruption, exact data and metadata comparisons,
|
|
101
|
+
finalize/commit, and independent writes on the target.
|
|
102
|
+
|
|
103
|
+
Ruff, formatting, wheel installation in a separate environment, both CLI entry
|
|
104
|
+
points, and SQL resources were checked. Instructions and the scope of these
|
|
105
|
+
results are documented in [TESTING.md](docs/TESTING.md). Machine reports, dumps,
|
|
106
|
+
credentials, and logs from individual runs remain local and are not included in
|
|
107
|
+
the repository.
|
|
108
|
+
|
|
109
|
+
## Implemented and verified in the test environment
|
|
110
|
+
|
|
111
|
+
- CLI and asynchronous service API; JSON `pg_logical_connector/result-v2`,
|
|
112
|
+
capabilities, request ID, JSON events to stderr/file, private files, and redaction.
|
|
113
|
+
- Validation of configuration, identities, major versions, locale/collation,
|
|
114
|
+
target emptiness, roles/verifiers, extensions, replica identity, and slot/disk
|
|
115
|
+
capacity.
|
|
116
|
+
- Conservative preflight rejection of unsupported FDW, RLS, rules, extended
|
|
117
|
+
statistics, custom collations/types/operators/casts/aggregates, text search,
|
|
118
|
+
tablespaces, and security labels; a partial coverage manifest excludes external
|
|
119
|
+
mapping secrets. Fingerprints include partition bounds/parents, column
|
|
120
|
+
storage/collation, and sequence definitions. Unknown classes require further
|
|
121
|
+
qualification.
|
|
122
|
+
- Basic health controller: identities, publication options/membership, subscription,
|
|
123
|
+
slot, and WAL retention; BLOCKED on drift and repeated apply/sync errors within
|
|
124
|
+
a 300-second window. These checks also run before finalize/commit. Conflicting
|
|
125
|
+
data is not skipped automatically, and slots are not automatically deleted.
|
|
126
|
+
- RFC 8785/SHA-256 plans bound to configuration and catalogs; HMAC for verifiers.
|
|
127
|
+
- Server validation using count + MD5 sum, chunks based on single/composite primary
|
|
128
|
+
keys, waiting for confirmed_flush_lsn, retries of changing chunks, concurrency
|
|
129
|
+
and pause limits, identical GUC settings, and table/level selection. Python
|
|
130
|
+
receives only aggregates and key boundaries. Large objects are checked using
|
|
131
|
+
server page aggregates. Tables without primary keys require a full scan with a
|
|
132
|
+
warning; cold chunk caching is not yet implemented.
|
|
133
|
+
- Transfer of roles, passwords, membership/options, settings, owners, ACLs, and the
|
|
134
|
+
database comment. Existing roles that differ are not overwritten.
|
|
135
|
+
- Schema-only pg_dump/pg_restore with matching major versions, pre-data/indexes
|
|
136
|
+
before loading, post-data after tablesync, and transactional step completion
|
|
137
|
+
receipts.
|
|
138
|
+
- Native publication/slot/subscription, tablesync and DML, initial partitions,
|
|
139
|
+
TOAST, RI FULL for tested types; a target → source connection probe without
|
|
140
|
+
creating a slot.
|
|
141
|
+
- Extended DDL in captured/managed_only modes: new tables/partitions/CTAS, columns,
|
|
142
|
+
types, DEFAULT, constraints, views/functions/procedures/triggers, sequences,
|
|
143
|
+
enum/domain, owners, ACLs/default privileges, and comments. See the
|
|
144
|
+
[matrix and limitations](docs/DDL_IMPLEMENTATION.md). Replica identity checks,
|
|
145
|
+
rewrite/SET NOT NULL limits, and safe session context requirements remain enforced.
|
|
146
|
+
- New tables: publication changes in the source transaction, REFRESH with
|
|
147
|
+
copy_data=true, native tablesync, and READY tracking; source data written before
|
|
148
|
+
refresh is preserved.
|
|
149
|
+
- Durable sequential DDL queue: CONCURRENTLY, NOT VALID → VALIDATE, UNIQUE/PK via
|
|
150
|
+
indexes, partitioned index trees, intents/OIDs, retries, and skip with a plan
|
|
151
|
+
hash and evidence. An unfinished queue blocks cutover; skips are recorded as
|
|
152
|
+
interventions and do not disable schema validation.
|
|
153
|
+
- Recovery of source CONCURRENTLY operations from the catalog and saved intent
|
|
154
|
+
after loss of the final journal record or response. Further source DDL must wait
|
|
155
|
+
for the queue to finish (receiving an explicit rejection/retry); DML continues.
|
|
156
|
+
- Finalize: external fence, SHARE locks, barrier, exact last_value/is_called,
|
|
157
|
+
unlogged tables, large objects with OID/owner/ACL, materialized views in dependency
|
|
158
|
+
order, and data validation.
|
|
159
|
+
- Commit rechecks the fence and changes since finalize, leaving an independent
|
|
160
|
+
target. Cutover abort returns to replication before the irreversible boundary.
|
|
161
|
+
- Abort preserves application data and transferred roles while removing owned
|
|
162
|
+
resources.
|
|
163
|
+
- Retrying prepare after a lost restore response, start after a lost CREATE
|
|
164
|
+
SUBSCRIPTION response, and ddl exec after a lost acknowledgment.
|
|
165
|
+
|
|
166
|
+
## Remaining readiness gaps
|
|
167
|
+
|
|
168
|
+
1. The rest of the full DDL matrix: synthesis of supported DO/compound statements,
|
|
169
|
+
exhaustive sql_drop metadata, qualification of volatility/casts, temporary and
|
|
170
|
+
unlogged objects, and all SPEC variants. See DDL_IMPLEMENTATION.md for exact
|
|
171
|
+
limitations.
|
|
172
|
+
2. Full object and dependency coverage: FDW/user mappings, extension configuration
|
|
173
|
+
data, application event triggers, ALWAYS/REPLICA triggers, security labels,
|
|
174
|
+
nonstandard types/casts/aggregates/tablespaces, and exhaustive comparison.
|
|
175
|
+
Preflight blocks these known unsupported categories; a comprehensive object
|
|
176
|
+
manifest and qualification of all properties remain incomplete. Full support
|
|
177
|
+
for arbitrary databases is not claimed.
|
|
178
|
+
3. Cold chunk caching, incremental cutover, lag history, lease/takeover, extended
|
|
179
|
+
observability, and operational qualification of the daemon.
|
|
180
|
+
4. Resync of partition trees; reconciliation of arbitrary partial states, unknown
|
|
181
|
+
tablesync slots, lost state, and disk exhaustion.
|
|
182
|
+
5. Qualification of TLS/mTLS, RLS, complex grantor graphs, large transactions,
|
|
183
|
+
parallel apply, failover, and SQL resource upgrades.
|
|
184
|
+
6. Not all SPEC options are implemented, including waivers and reconciliation of
|
|
185
|
+
existing roles. Configuration validation rejects unsupported values; a full
|
|
186
|
+
acceptance matrix covering every setting remains outstanding.
|
|
187
|
+
7. Qualification at production scale and with extended overnight profiles has not
|
|
188
|
+
been completed. The local 30-minute run checks correctness on small datasets
|
|
189
|
+
and does not replace testing with the intended production workload.
|
|
190
|
+
|
|
191
|
+
Next priorities: complete the object manifest, incremental validation, and remaining
|
|
192
|
+
DDL variants. Passing the current matrix does not mean the requirements above
|
|
193
|
+
have been met.
|
|
194
|
+
|
|
195
|
+
## Environment and artifacts
|
|
196
|
+
|
|
197
|
+
- The `infra/pg15.yaml` … `infra/pg18.yaml` environments run sequentially; PG18
|
|
198
|
+
remains active after the matrix.
|
|
199
|
+
- Credentials are stored in `.pg_stand/`, results in `.runtime/`, and builds in
|
|
200
|
+
`dist/`. These directories are excluded through `.gitignore`.
|
|
201
|
+
- Tests normalize bootstrap role verifiers only in their own environment; the
|
|
202
|
+
utility does not change verifiers of existing roles on arbitrary targets.
|
|
203
|
+
- Matching major versions of `pg_dump`/`pg_restore` are required. PG16 has a helper
|
|
204
|
+
image build script, `infra/build_pg16.py`.
|
|
205
|
+
- Tested environment: Python 3.12, Linux ARM64. A separate Python 3.11 run has not
|
|
206
|
+
yet been completed.
|
|
207
|
+
- Guide: [README.md](README.md); example: [examples/local.yaml](examples/local.yaml).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
include pyproject.toml MANIFEST.in
|
|
2
|
+
include README.md IMPLEMENTATION_STATUS.md
|
|
3
|
+
include docs/DDL_IMPLEMENTATION.md docs/TESTING.md docs/RELEASING.md
|
|
4
|
+
include examples/local.yaml
|
|
5
|
+
include .github/workflows/publish.yml
|
|
6
|
+
recursive-include tests *.py
|
|
7
|
+
include tests/fixtures/quality/recovery.json
|
|
8
|
+
recursive-include infra *.py *.yaml
|
|
9
|
+
exclude todo.md docs/SPEC.md docs/SPEC_REVIEW.md docs/OPEN_SOURCE_REVIEW.md
|
|
10
|
+
prune .runtime
|
|
11
|
+
prune .pg_stand
|
|
12
|
+
prune .venv
|
|
13
|
+
prune build
|
|
14
|
+
prune dist
|
|
15
|
+
global-exclude __pycache__ *.py[cod] *.log *.pid *.pgpass *.key *.pem
|