Add support for ALTER TABLE path changes on external Iceberg tables#314
Add support for ALTER TABLE path changes on external Iceberg tables#314cbrianpace wants to merge 2 commits into
Conversation
Signed-off-by: brian.pace <brian.pace@outlook.com>
sfc-gh-okalaci
left a comment
There was a problem hiding this comment.
Thanks for the PR, Brian! It's a useful feature to have. I'm happy to take over from here if you prefer, or we can iterate together, you choose!
I dug through the history and this was actually already supported — we unintentionally broke it in commit b447e29 ("Refactor read-only iceberg table errors") when we broadened the ProcessAlterTable() guard to use IsIcebergTable(), which pulled these tables into scope where they hit ErrorIfReadOnlyIcebergTable(). So your PR is really a fix, not a new feature.
That said, there are a few things we should address before merging:
Schema validation
The biggest concern is schema drift. If the new metadata.json has a different schema than what PostgreSQL has in pg_attribute (from the original CREATE FOREIGN TABLE), we'd get silent data corruption or crashes.
We already have ErrorIfSchemasDoNotMatch() in snapshot.c — it compares the Iceberg metadata schema against the Postgres column definitions. It's currently called for REST_CATALOG_READ_ONLY and OBJECT_STORE_READ_ONLY, but not for NONE_CATALOG (the path-based case this PR targets):
if (catalogType == REST_CATALOG_READ_ONLY ||
catalogType == OBJECT_STORE_READ_ONLY)
ErrorIfSchemasDoNotMatch(relationId, metadata);We should extend this condition to also cover NONE_CATALOG external Iceberg tables. For consistency with the other catalog types, let's add the check in the same place (the read path in snapshot.c) rather than in alter_table.c. This way all external Iceberg types are validated uniformly.
Permission check
The FDW validator (pg_lake_table_validator) calls CheckURLReadAccess() on both CREATE and ALTER, so I believe this is already covered. But it would be good to verify with a test: create a user without the lake_read role, and confirm that ALTER FOREIGN TABLE ... OPTIONS (SET path '...') is denied.
Tests
We'll need tests covering:
-
Happy path: Create an internal Iceberg table (
CREATE TABLE ... USING iceberg), create an external foreign table pointing to its metadata, insert data into the internal table, thenALTER FOREIGN TABLE ... OPTIONS (SET path '<new_metadata.json>')to point to the updated snapshot — and verify the external table sees the new data. -
Schema mismatch: Same setup, but after the ALTER, the new metadata has a different schema (e.g., an added/dropped column on the internal table). Verify we get the
ErrorIfSchemasDoNotMatch()error. -
Permission denied: A user without
lake_readattempting the ALTER should be denied. -
Dependent objects: Create views and materialized views on top of the external table, change the underlying path, and verify everything still works (or fails gracefully if schema changed). This is the real-world use case you're solving for, so it's important we cover it to prevent future regressions.
For writing the tests, Claude is great at generating pytest scenarios — you should mostly need to describe what you want, and it can come up with a good test structure. Look at test_data_file_pruning.py for examples of how we create external Iceberg tables in tests (the create_external_iceberg_table() helper function).
Let me know how you'd like to proceed!
Description
External Iceberg foreign tables (created via SERVER pg_lake OPTIONS (path '...metadata.json')) were previously immutable — to point to a newer snapshot you had to DROP and re-CREATE the table, losing any dependent views, permissions, or references.
This change adds a narrow ALTER TABLE ... OPTIONS (SET path '...') path for these read-only external tables, allowing callers to redirect to a different metadata snapshot in-place.
Changes
pg_lake_table/src/ddl/alter_table.c: Added a branch in ProcessAlterTable() that detects NONE_CATALOG external Iceberg tables and permits only the path option to be changed, rejecting all other option modifications via ErrorIfUnsupportedTableOptionChange.
Checklist
DCO Reminder (important)
This project uses the Developer Certificate of Origin (DCO).
DCO is a simple way for you to confirm that you wrote your code and that you have the right to contribute it.
If the DCO check fails, please sign off your commits.
How to sign off
For your last commit:
git commit --amend -s
git push --force
For multiple commits:
git rebase --signoff main
git push --force
More info: https://developercertificate.org/