Skip to content

feat: support V0 iceberg_tables schema for SqlCatalog - #3032

Merged
CTTY merged 8 commits into
apache:mainfrom
dannycjones:support-sqlcatalogv0
Aug 21, 2026
Merged

feat: support V0 iceberg_tables schema for SqlCatalog#3032
CTTY merged 8 commits into
apache:mainfrom
dannycjones:support-sqlcatalogv0

Conversation

@dannycjones

@dannycjones dannycjones commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Closes #2068.

This change supercedes #2380 originally authored by @rchowell.

What changes are included in this PR?

This PR adds support for using a V0 SqlCatalog from other implementations like iceberg-python or iceberg-java, and it follows the iceberg-java behavior of checking an explicit schema-version property and migrating to V1 only if the user requested this.

SQL catalog tables are always created V1, regardless of the config. This does diverge with Java for now.

The catalog probes to see if we have a V0 or V1 table, then add the iceberg_type column if it does not exist. Reference: apache/iceberg-python#3263

Are these changes tested?

  • Unit tests with migration path

AI Disclosure

AI was used to find out that sqlx does offer a backend-agnostic way to get a list of columns for the table. It also drafted extended tests for the new detect method on the schema version enum.

@CTTY CTTY left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for reviving this PR! mostly LGTM

let sql_bind_style = self
.config
.props
.remove(SQL_CATALOG_PROP_BIND_STYLE)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to consume the property here?

@dannycjones dannycjones Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed this too but didn't have a preference. It is already established convention in the file. The URI and warehouse location would need to clone if we only borrowed from the config map.

I'm happy with it as is, but I can also move the rest of the load method to borrow (and clone if needed) instead of consume.

Let me know if its preferred to make the change.

// Parse the requested schema version up front so invalid values fail fast rather than
// silently falling back to V0.
let mut valid_schema_version = true;
if let Some(schema_version) = self.config.props.remove(SQL_CATALOG_PROP_SCHEMA_VERSION) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, why consume?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will address comment in this thread: #3032 (comment)

Comment thread crates/catalog/sql/src/catalog.rs Outdated
Ok(_) => true,
// The database rejected the query: the `iceberg_type` column (or table) is absent,
// so this is a genuine V0 schema.
Err(sqlx::Error::Database(_)) => false,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still my biggest concern, there is no way for us to ensure that this is not a permission failure. I was thinking about something like an unexhastive enum to at least check the specific errors for Postgres, MySql, Sqlite. or let's create a follow up to add verification calls directly via different drivers like mentioned here: #2380 (comment)

@dannycjones dannycjones Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a deeper look. AI helped me find that sqlx actually abstracts this behind a describe method, and provides an agnostic way to get a list of columns from a SELECT. For the backend, it may execute 2 or more queries to do this compared to the single query for the previous probing approach, but I think that's justified for better error handling.

I've updated a PR that uses this, so it'll propagate errors if it couldn't get a list of columns, otherwise we check the list for the presence of the iceberg_type column.

Copilot AI lite review requested due to automatic review settings August 21, 2026 13:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the SQL catalog implementation to interoperate with existing Iceberg SQL catalog databases that still use the legacy (V0) iceberg_tables schema (without the iceberg_type column), while keeping the current (V1) behavior available via an explicit opt-in migration flag.

Changes:

  • Added schema version detection for iceberg_tables and a new sql.schema-version property to optionally migrate V0 → V1.
  • Updated table lookup queries to only apply the iceberg_type filter when the detected schema supports it.
  • Added unit tests covering schema detection, migration opt-in, legacy bind-style key compatibility, and invalid schema-version validation.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.

File Description
crates/catalog/sql/src/catalog.rs Implements schema version detection/migration and conditionally filters table queries based on schema version; adds new tests.
crates/catalog/sql/public-api.txt Updates the public API surface to include SchemaVersion and the new SQL_CATALOG_PROP_SCHEMA_VERSION constant.
crates/catalog/sql/Cargo.toml Adds tracing dependency for new diagnostic logging.
Cargo.lock Locks the added tracing dependency.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread crates/catalog/sql/src/catalog.rs Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.

Comment thread crates/catalog/sql/src/catalog.rs
Comment thread crates/catalog/sql/src/catalog.rs Outdated
Comment thread crates/catalog/sql/src/catalog.rs Outdated
…ail, clarify docs on created catalog table behavior

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated no new comments.

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

crates/catalog/sql/src/catalog.rs:343

  • SchemaVersion::detect checks for the iceberg_type column using a case-sensitive string comparison. SQL identifiers are generally case-insensitive and some backends/driver metadata can report column names with different casing, which could mis-detect a V1 table as V0. Consider using an ASCII-case-insensitive comparison here (and in the similar test helper) to make detection robust across backends.
        let has_type_column = catalog_table_description
            .columns()
            .iter()
            .any(|column| column.name() == CATALOG_FIELD_RECORD_TYPE);

@dannycjones
dannycjones requested a review from CTTY August 21, 2026 17:04

@CTTY CTTY left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for the PR!

@CTTY
CTTY merged commit e03179f into apache:main Aug 21, 2026
22 checks passed
@dannycjones
dannycjones deleted the support-sqlcatalogv0 branch August 22, 2026 08:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

column "iceberg_type" does not exist

4 participants