Skip to content

fix(sql): hide namespace exists sentinel property#1411

Open
fallintoplace wants to merge 1 commit into
apache:mainfrom
fallintoplace:fix/sql-namespace-sentinel-filter
Open

fix(sql): hide namespace exists sentinel property#1411
fallintoplace wants to merge 1 commit into
apache:mainfrom
fallintoplace:fix/sql-namespace-sentinel-filter

Conversation

@fallintoplace

@fallintoplace fallintoplace commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Summary

  • hide the internal SQL namespace sentinel property exists from LoadNamespaceProperties;
  • reject updates or removals targeting exists with ErrInvalidProperty;
  • preserve the sentinel internally for namespaces created without user properties;
  • add coverage for both sentinel-present and user-property namespaces.

Testing

  • go test ./catalog/sql

@fallintoplace
fallintoplace requested a review from zeroshade as a code owner July 5, 2026 13:11
@fallintoplace
fallintoplace force-pushed the fix/sql-namespace-sentinel-filter branch 2 times, most recently from 1c58617 to 75fbfa4 Compare July 5, 2026 14:05

@tanmayrauth tanmayrauth left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Core change reads cleanly and the tests pass. One thing worth deciding before merge: this reserves exists on the read path (LoadNamespaceProperties) and the update path (UpdateNamespaceProperties), but CreateNamespace — untouched here — still inserts whatever the caller passes. So CreateNamespace(ns, {"exists": "false", ...}) persists a sentinel the new code then permanently hides on read and refuses to update or remove. Not asking you to change CreateNamespace in this PR necessarily, but it'd be good to confirm whether leaving that path unguarded is intended, since the three paths no longer agree on what "reserved" means. Two small inline notes below.

Comment thread catalog/sql/sql.go Outdated

for _, key := range removals {
if isReservedNamespaceProperty(key) {
return fmt.Errorf("%w: cannot remove reserved namespace property %q", iceberg.ErrInvalidArgument, namespaceExistsProperty)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Small one: the loop binds key but this formats namespaceExistsProperty. Same value today since only "exists" is reserved, but if the reserved set ever grows this will name the wrong key in the error — probably want key here.

Comment thread catalog/sql/sql_test.go Outdated
cat *sqlcat.Catalog
namespace table.Identifier
}{
{s.getCatalogMemory(), table.Identifier{databaseName()}},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since this seeds {"comment": "baseline"}, no sentinel row is actually written, so the guard is only exercised at the argument layer. Could you add a case that creates a namespace with empty props (which does insert the exists=true row) and then asserts remove/update of exists is still rejected and the namespace loads empty? That covers the real-world path where the sentinel is present.

@zeroshade zeroshade left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One latent bug in the removal-branch error message (inline), plus a small coverage gap: the new test always seeds the namespace with non-empty user props, so the exists sentinel row is never actually persisted. Consider adding a case that creates a namespace with nil/empty properties (which does write the sentinel) and asserts it's hidden by LoadNamespaceProperties and rejected on remove — that exercises the sentinel-present path.

Comment thread catalog/sql/sql.go Outdated

for _, key := range removals {
if isReservedNamespaceProperty(key) {
return fmt.Errorf("%w: cannot remove reserved namespace property %q", iceberg.ErrInvalidArgument, namespaceExistsProperty)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This formats the constant namespaceExistsProperty (always exists) instead of the loop variable key. They're identical today because isReservedNamespaceProperty only matches exists, but once the reserved set grows this will report the wrong property name for any reserved-key removal. Use key here.

@fallintoplace
fallintoplace force-pushed the fix/sql-namespace-sentinel-filter branch from 75fbfa4 to 3098b1f Compare July 9, 2026 17:44
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.

3 participants