Add pg_lake_polaris extension for two-way Polaris sync#392
Draft
sfc-gh-mslot wants to merge 2 commits into
Draft
Add pg_lake_polaris extension for two-way Polaris sync#392sfc-gh-mslot wants to merge 2 commits into
sfc-gh-mslot wants to merge 2 commits into
Conversation
New optional extension that mirrors metadata between pg_lake's Iceberg catalog (lake_iceberg.tables_internal) and an Apache Polaris metastore (polaris_schema.entities) co-resident in the same Postgres database. Outbound is via trigger; inbound piggybacks on sync_iceberg_metadata_from_external_write to apply Polaris-side commits. Loop prevention is a process-global suppress flag mirroring the SkipIcebergDDLProcessing pattern. v0.1 limitations (single-instance Polaris ID allocator, scalar-only inbound CREATE, flat namespaces) are documented in the SQL.
Two pytest e2e tests exercise the outbound path through pg_lake's
real CREATE TABLE / INSERT / DROP DDL flow against the lake_polaris
extension's triggers. The inbound INSERT path is not e2e-tested in
v0.1 — the test environment lacks a way to write a real Iceberg
metadata file outside pg_lake (PyIceberg-core not installed; PyIceberg
SqlCatalog can't write to the current database's iceberg_tables);
sharing pg_lake-written metadata trips a pg_lake-internal
deletion_queue invariant about two tables referencing the same files.
Documented as a known v0.1 limitation.
In the process, fix two real bugs surfaced by the e2e attempt:
- outbound_remove deleted entity_link AFTER deleting the polaris
entity, so the inbound DELETE trigger queued by the entity DELETE
still found the link and re-attempted the foreign-table drop.
Reverse the order so self-canceling state is the load-bearing
mechanism (the suppress flag is defense-in-depth).
- inbound_sync_insert specified read_only 'true' (a REST-catalog-only
option) and INSERTed into tables_internal even though pg_lake's
CREATE FOREIGN TABLE hook already does. Drop the option and switch
to UPDATE.
Also: skip stale tables_internal rows in outbound_sync, fix conftest
teardown order so DROP EXTENSION removes triggers before clearing
polaris_schema entities.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Work in progress, opening as draft so the branch does not get lost.
Problem
pg_lake stores Iceberg metadata in
lake_iceberg.tables_internal. When Apache Polaris runs co-resident in the same Postgres database (polaris_schema.entities), there is no path to keep the two catalogs in sync. Tables registered through pg_lake are invisible to Polaris clients, and metadata commits made through Polaris (external writers, REST clients) are invisible to pg_lake.Solution
Add a new optional extension
pg_lake_polaristhat mirrors metadata between the two catalogs:tables_internal.sync_iceberg_metadata_from_external_write, which is also added in this branch as a generic external-write entrypoint in pg_lake_table.SkipIcebergDDLProcessingpattern.v0.1 limitations (single-instance Polaris ID allocator, scalar-only inbound CREATE, flat namespaces) are documented inline in the SQL.
The branch also pulls in supporting changes in pg_lake_table: external Iceberg write support via catalog UPDATE, a deletion queue for files unreferenced after external sync, and snapshot/SPI fixes surfaced while wiring this up.
Setup
After
register_catalog, pg_lakeCREATE TABLE ... USING icebergshows up as a table entity under the named Polaris catalog, and metadata commits made through Polaris are reflected back intolake_iceberg.tables_internal. To stop syncing, calllake_polaris.unregister_catalog().Test plan
pg_lake_polaris/tests/pytests/test_polaris_register.py,test_polaris_outbound.py,test_polaris_inbound.py,test_polaris_e2e.pypg_lake_table/tests/pytests/test_external_write.py