Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions open-api/rest-catalog-open-api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1575,6 +1575,19 @@ class CreateTableRequest(BaseModel):
properties: dict[str, str] | None = None


class UnregisterTableResult(BaseModel):
"""
Last metadata location and the corresponding table metadata for the table that was successfully unregistered and is no longer tracked by the catalog.
"""

metadata_location: str = Field(
...,
alias='metadata-location',
description='The last metadata location for the table at the time it was unregistered.',
)
metadata: TableMetadata


class CreateViewRequest(BaseModel):
name: str
location: str | None = None
Expand Down
74 changes: 74 additions & 0 deletions open-api/rest-catalog-open-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1217,6 +1217,56 @@ paths:
5XX:
$ref: '#/components/responses/ServerErrorResponse'

/v1/{prefix}/namespaces/{namespace}/tables/{table}/unregister:
parameters:
- $ref: '#/components/parameters/prefix'
- $ref: '#/components/parameters/namespace'
- $ref: '#/components/parameters/table'
Comment thread
rdblue marked this conversation as resolved.

post:
tags:
- Catalog API
summary: Unregister a table without removing its data or metadata files
operationId: unregisterTable
parameters:
- $ref: '#/components/parameters/idempotency-key'
description:
Unregister a table from the catalog. This is the opposite of
`registerTable`. The table no longer exists in the catalog, but the
underlying data and metadata files are left in place so that the table
can be registered in another catalog.
Copy link
Copy Markdown
Contributor

@xndai xndai May 20, 2026

Choose a reason for hiding this comment

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

can you also add comment to explain the difference between this and the delete request with purgeRequested set to false? And may be also updating the description of delete especially regarding the purgeRequested semantics.

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.

This seems unnecessary to me. The DELETE request is called dropTable and the semantics of dropping a table are clear in most SQL systems and are no different in this spec. The purge flag is also already correct: it signals whether the caller requested a purge; how to interpret that is not dictated by the spec.

In addition, this description already calls out the relevant parts: that data and metadata are left in place so they can be registered in another catalog.

I think this is another example of "less is more" in our specs. If we were to call out that "unlike drop" this doesn't delete data and metadata, we're making the requirements more confusing because we don't specify when data should be deleted (if at all) for DROP. It may seem like a good idea to point out how this differs from drop, but I think the specification is more clear if this focuses on the correct behavior of this endpoint and let the drop documentations focus on its correct behavior.

Copy link
Copy Markdown
Contributor

@xndai xndai May 21, 2026

Choose a reason for hiding this comment

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

the semantics of dropping a table are clear in most SQL systems

True for the traditional DBs, but not so for the data lake engines. Both AWS Redshift and AWS Athena do not purge table data when running DROP TABLE. Apache Spark also says for external table, DROP TABLE is merely a metadata operation.

I am afraid that if we don't call out the semantics of purgeRequested clearly, people might face catastrophic data loss when they interpret purgeRequested = false in a wrong way.

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.

An interesting experiment using Claude and the latest mainline. If LLM is confused, I bet many human, and human who use LLMs, would be confused too.

  Read rest-catalog-open-api.yaml carefully. Now if I want to implement 'DROP TABLE' for a query
    engine, which only removes the table entry from catalog, but not the data and metadata on cloud storage, which IRC interface should I use, what parameters should be set?

  Searched for 1 pattern, read 1 file (ctrl+o to expand)

● You should use the DELETE /v1/{prefix}/namespaces/{namespace}/tables/{table} endpoint (operation: dropTable).

  To only remove the catalog entry without purging data and metadata on storage, set the query parameter:

  purgeRequested=false

  This is also the default (default: false), so you can simply omit the parameter entirely. The request would look like:

  DELETE /v1/{prefix}/namespaces/{namespace}/tables/{table}

  A successful response returns 204 No Content.

  The key distinction: when purgeRequested=true, the catalog is asked to also delete the underlying data and metadata files. When false (or
  omitted), only the catalog entry is removed — the files on cloud storage remain intact.

✻ Baked for 15s



On success, this returns the table's last metadata location and the
corresponding table metadata. This table metadata must include all
commits that happened before the unregister operation. All attempted
commits after the unregister operation in this catalog must fail.
responses:
200:
$ref: '#/components/responses/UnregisterTableResponse'
400:
$ref: '#/components/responses/BadRequestErrorResponse'
401:
$ref: '#/components/responses/UnauthorizedResponse'
403:
$ref: '#/components/responses/ForbiddenResponse'
404:
description:
Not Found - NoSuchTableException, table to unregister does not exist
content:
application/json:
schema:
$ref: '#/components/schemas/IcebergErrorResponse'
examples:
TableToUnregisterDoesNotExist:
$ref: '#/components/examples/NoSuchTableError'
419:
$ref: '#/components/responses/AuthenticationTimeoutResponse'
503:
$ref: '#/components/responses/ServiceUnavailableResponse'
5XX:
$ref: '#/components/responses/ServerErrorResponse'

/v1/{prefix}/namespaces/{namespace}/tables/{table}/credentials:
parameters:
- $ref: '#/components/parameters/prefix'
Expand Down Expand Up @@ -3792,6 +3842,23 @@ components:
type: boolean
default: false

UnregisterTableResult:
description:
Last metadata location and the corresponding table metadata for the
table that was successfully unregistered and is no longer tracked by
the catalog.
type: object
required:
- metadata-location
- metadata
properties:
metadata-location:
type: string
description:
The last metadata location for the table at the time it was unregistered.
metadata:
$ref: '#/components/schemas/TableMetadata'

CreateViewRequest:
type: object
required:
Expand Down Expand Up @@ -5059,6 +5126,13 @@ components:
etag:
$ref: '#/components/parameters/etag'

UnregisterTableResponse:
description: Response when a table is successfully unregistered.
content:
application/json:
schema:
$ref: '#/components/schemas/UnregisterTableResult'

LoadViewResponse:
description: View metadata result when loading a view
content:
Expand Down