From 82221d90d107fd17f85f5b0b4a7771be92f150ef Mon Sep 17 00:00:00 2001 From: guillesd Date: Mon, 22 Sep 2025 13:30:16 +0200 Subject: [PATCH 1/7] add supported operations for attached catalogs plus interoperability with DuckLake --- .../iceberg/iceberg_rest_catalogs.md | 78 ++++++++++++++---- .../core_extensions/iceberg/overview.md | 7 +- tmp_ducklake.db | Bin 0 -> 2109440 bytes 3 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 tmp_ducklake.db diff --git a/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md b/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md index 39662597ee..fe8b549cec 100644 --- a/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md +++ b/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md @@ -50,24 +50,74 @@ SHOW ALL TABLES; A REST Catalog with OAuth2 authorization can also be attached with just an `ATTACH` statement. See the complete list of `ATTACH` options for a REST catalog below. -| Parameter | Type | Default | Description | -| ---------------------------- | ---------- | -------- | ---------------------------------------------------------- | -| `ENDPOINT_TYPE` | `VARCHAR` | `NULL` | Used for attaching S3Tables or Glue catalogs. Allowed values are 'GLUE' and 'S3_TABLES' | -| `ENDPOINT` | `VARCHAR` | `NULL` | URL endpoint to communicate with the REST Catalog. Cannot be used in conjunction with `ENDPOINT_TYPE` | -| `SECRET` | `VARCHAR` | `NULL` | Name of secret used to communicate with the REST Catalog | -| `CLIENT_ID` | `VARCHAR` | `NULL` | CLIENT_ID used for Secret | -| `CLIENT_SECRET` | `VARCHAR` | `NULL` | CLIENT_SECRET needed for Secret | -| `DEFAULT_REGION` | `VARCHAR` | `NULL` | A Default region to use when communicating with the storage layer | -| `OAUTH2_SERVER_URI` | `VARCHAR` | `NULL` | OAuth2 server url for getting a Bearer Token | -| `AUTHORIZATION_TYPE` | `VARCHAR` | `OAUTH2` | Pass `SigV4` for Catalogs the require SigV4 authorization | +| Parameter | Type | Default | Description | +|-------------------------------|-----------|----------|-------------------------------------------------------------------------------------------------------| +| `ENDPOINT_TYPE` | `VARCHAR` | `NULL` | Used for attaching S3Tables or Glue catalogs. Allowed values are 'GLUE' and 'S3_TABLES' | +| `ENDPOINT` | `VARCHAR` | `NULL` | URL endpoint to communicate with the REST Catalog. Cannot be used in conjunction with `ENDPOINT_TYPE` | +| `SECRET` | `VARCHAR` | `NULL` | Name of secret used to communicate with the REST Catalog | +| `CLIENT_ID` | `VARCHAR` | `NULL` | CLIENT_ID used for Secret | +| `CLIENT_SECRET` | `VARCHAR` | `NULL` | CLIENT_SECRET needed for Secret | +| `DEFAULT_REGION` | `VARCHAR` | `NULL` | A Default region to use when communicating with the storage layer | +| `OAUTH2_SERVER_URI` | `VARCHAR` | `NULL` | OAuth2 server url for getting a Bearer Token | +| `AUTHORIZATION_TYPE` | `VARCHAR` | `OAUTH2` | Pass `SigV4` for Catalogs the require SigV4 authorization, `none` for catalogs that don't need auth | +| `SUPPORTED_NESTED_NAMESPACES` | `BOOLEAN` | `true` | Option for catalogs that support nested namespaces. | +| `SUPPORT_STAGE_CREATE` | `BOOLEAN` | `false` | Option for catalogs that do not support stage create. | + The following options can only be passed to a `CREATE SECRET` statement, and they require `AUTHORIZATION_TYPE` to be `OAUTH2` -| Parameter | Type | Default | Description | -| ---------------------------- | ---------- | -------- | ---------------------------------------------------------- | -| `OAUTH2_GRANT_TYPE` | `VARCHAR` | `NULL` | Grant Type when requesting an OAuth Token | -| `OAUTH2_SCOPE` | `VARCHAR` | `NULL` | Requested scope for the returned OAuth Access Token | +| Parameter | Type | Default | Description | +|---------------------|-----------|---------|-----------------------------------------------------| +| `OAUTH2_GRANT_TYPE` | `VARCHAR` | `NULL` | Grant Type when requesting an OAuth Token | +| `OAUTH2_SCOPE` | `VARCHAR` | `NULL` | Requested scope for the returned OAuth Access Token | + + +### Supported Operations + +The DuckDB Iceberg extensions supports the following operations when used with a REST catalog attached: + +- `CREATE/DROP SCHEMA` +- `CREATE/DROP TABLE` +- `INSERT INTO` +- `SELECT` +- `ALTER TABLE` + +Since these operations are supported, the following would also work: + +```sql +COPY FROM DATABASE duckdb_db TO iceberg_datalake; + +-- Or +COPY FROM DATABASE iceberg_datalake to duckdb_db; +``` + +This functionality enables deep copies between Iceberg and DuckDB storage. + +### Interoperability with DuckLake + +The DuckDB Iceberg extensions exposes a function to do metadata only copies of the Iceberg metadata to DuckLake, which enables users to query Iceberg tables as if they where DuckLake tables. + +```sql +-- Given that we have an Iceberg catalog attached aliased to iceberg_datalake +ATTACH `ducklake:my_ducklake.ducklake` AS my_ducklake; + +CALL iceberg_to_ducklake('iceberg_datalake', 'my_ducklake'); +``` + +It is also possible to skip a set of tables provided the `skip_tables` parameter. + +```sql +CALL iceberg_to_ducklake('iceberg_datalake', 'my_ducklake', skip_tables := ['table_to_skip']); +``` + +### Unsupported Operations + +The following operations are not supported by the Iceberg DuckDB extension: + +- `UPDATE` +- `DELETE` +- `MERGE INTO` ## Specific Catalog Examples diff --git a/docs/stable/core_extensions/iceberg/overview.md b/docs/stable/core_extensions/iceberg/overview.md index ab0be7d0c1..731cea9eef 100644 --- a/docs/stable/core_extensions/iceberg/overview.md +++ b/docs/stable/core_extensions/iceberg/overview.md @@ -11,7 +11,8 @@ redirect_from: title: Iceberg Extension --- -The `iceberg` extension implements support for the [Apache Iceberg open table format](https://iceberg.apache.org/). +The `iceberg` extension implements support for the [Apache Iceberg open table format](https://iceberg.apache.org/). +In this page we will go over the basic usage of the extension without the need to attach to an Iceberg catalog. For full support —including write support— see [how to attach Iceberg REST catalogs]({% link docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md %}). ## Installing and Loading @@ -186,7 +187,3 @@ FROM iceberg_scan( allow_moved_paths = true ); ``` - -## Limitations - -Writing (i.e., exporting to) Iceberg files is currently not supported. diff --git a/tmp_ducklake.db b/tmp_ducklake.db new file mode 100644 index 0000000000000000000000000000000000000000..38787af93bc5dd2116037634df5bb6960658eae6 GIT binary patch literal 2109440 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 z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF zOozbD@6^8b+ScZ`KWe!VAV7e?;RR;G_Rf!wx#H!yor}F9K!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5Fk)(ft%l{eeJca&2N9yaw9;10D;2`%!KWo zhyA(Y<++`Uy&^z>009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zP;G%V$=eff!4%umI?^l@Q5sW+2GZDZk1vQqz%Pp{OMRzKZUjrp$U>C^pQ z_iXMZ0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zP;r5q->H4=wXMx>f7Eg#K!5;&!wbxW?VZQ{x#H!yor}F9K!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ ifB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5Fk)(f&ULmQe;Q~ literal 0 HcmV?d00001 From 9a7f6677237f0f34cd22d8356488202f1ffcf399 Mon Sep 17 00:00:00 2001 From: guillesd Date: Mon, 22 Sep 2025 13:43:19 +0200 Subject: [PATCH 2/7] ups --- tmp_ducklake.db | Bin 2109440 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tmp_ducklake.db diff --git a/tmp_ducklake.db b/tmp_ducklake.db deleted file mode 100644 index 38787af93bc5dd2116037634df5bb6960658eae6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2109440 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 z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF zOozbD@6^8b+ScZ`KWe!VAV7e?;RR;G_Rf!wx#H!yor}F9K!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5Fk)(ft%l{eeJca&2N9yaw9;10D;2`%!KWo zhyA(Y<++`Uy&^z>009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zP;G%V$=eff!4%umI?^l@Q5sW+2GZDZk1vQqz%Pp{OMRzKZUjrp$U>C^pQ z_iXMZ0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zP;r5q->H4=wXMx>f7Eg#K!5;&!wbxW?VZQ{x#H!yor}F9K!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ ifB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5Fk)(f&ULmQe;Q~ From ecb46b4e92af8be662fb68a78eebeea4f01fba9c Mon Sep 17 00:00:00 2001 From: guillesd Date: Mon, 22 Sep 2025 14:14:29 +0200 Subject: [PATCH 3/7] add section on metadata operations and time traveling --- .../iceberg/iceberg_rest_catalogs.md | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md b/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md index fe8b549cec..cd42057ade 100644 --- a/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md +++ b/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md @@ -81,7 +81,6 @@ The DuckDB Iceberg extensions supports the following operations when used with a - `CREATE/DROP TABLE` - `INSERT INTO` - `SELECT` -- `ALTER TABLE` Since these operations are supported, the following would also work: @@ -94,6 +93,26 @@ COPY FROM DATABASE iceberg_datalake to duckdb_db; This functionality enables deep copies between Iceberg and DuckDB storage. +### Metadata Operations + +The functions `iceberg_metadata` and `iceberg_snapshots` are also available to use with an Iceberg REST catalog using a fully qualified path, e.g. + +```sql +SELECT * FROM iceberg_metadata(my_datalake.default.t) + +-- Or +SELECT * FROM iceberg_snapshots(my_datalake.default.t) +``` + +This functionality enables the user to grab a `snapshot_from_id` to do **time-traveling**. + +```sql +SELECT * FROM iceberg_scan(my_datalake.default.t, snapshot_from_id => ⟨SNAPSHOT_ID⟩); + +-- Or using a timestamp +SELECT * FROM iceberg_scan(my_datalake.default.t, snapshot_from_timestamp => '2025-09-22 12:32:43.217') +``` + ### Interoperability with DuckLake The DuckDB Iceberg extensions exposes a function to do metadata only copies of the Iceberg metadata to DuckLake, which enables users to query Iceberg tables as if they where DuckLake tables. @@ -118,6 +137,7 @@ The following operations are not supported by the Iceberg DuckDB extension: - `UPDATE` - `DELETE` - `MERGE INTO` +- `ALTER TABLE` ## Specific Catalog Examples From 8cf28a4acbec75e690c3584fd8c899828b18d70e Mon Sep 17 00:00:00 2001 From: guillesd Date: Mon, 22 Sep 2025 14:24:57 +0200 Subject: [PATCH 4/7] add new docs to preview --- .../iceberg/iceberg_rest_catalogs.md | 98 ++++++++++++++++--- .../core_extensions/iceberg/overview.md | 9 +- 2 files changed, 87 insertions(+), 20 deletions(-) diff --git a/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md b/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md index f8337281b9..f8a7f9c571 100644 --- a/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md +++ b/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md @@ -50,24 +50,94 @@ SHOW ALL TABLES; A REST Catalog with OAuth2 authorization can also be attached with just an `ATTACH` statement. See the complete list of `ATTACH` options for a REST catalog below. -| Parameter | Type | Default | Description | -| ---------------------------- | ---------- | -------- | ---------------------------------------------------------- | -| `ENDPOINT_TYPE` | `VARCHAR` | `NULL` | Used for attaching S3Tables or Glue catalogs. Allowed values are 'GLUE' and 'S3_TABLES' | -| `ENDPOINT` | `VARCHAR` | `NULL` | URL endpoint to communicate with the REST Catalog. Cannot be used in conjunction with `ENDPOINT_TYPE` | -| `SECRET` | `VARCHAR` | `NULL` | Name of secret used to communicate with the REST Catalog | -| `CLIENT_ID` | `VARCHAR` | `NULL` | CLIENT_ID used for Secret | -| `CLIENT_SECRET` | `VARCHAR` | `NULL` | CLIENT_SECRET needed for Secret | -| `DEFAULT_REGION` | `VARCHAR` | `NULL` | A Default region to use when communicating with the storage layer | -| `OAUTH2_SERVER_URI` | `VARCHAR` | `NULL` | OAuth2 server url for getting a Bearer Token | -| `AUTHORIZATION_TYPE` | `VARCHAR` | `OAUTH2` | Pass `SigV4` for Catalogs the require SigV4 authorization | +| Parameter | Type | Default | Description | +|-------------------------------|-----------|----------|-------------------------------------------------------------------------------------------------------| +| `ENDPOINT_TYPE` | `VARCHAR` | `NULL` | Used for attaching S3Tables or Glue catalogs. Allowed values are 'GLUE' and 'S3_TABLES' | +| `ENDPOINT` | `VARCHAR` | `NULL` | URL endpoint to communicate with the REST Catalog. Cannot be used in conjunction with `ENDPOINT_TYPE` | +| `SECRET` | `VARCHAR` | `NULL` | Name of secret used to communicate with the REST Catalog | +| `CLIENT_ID` | `VARCHAR` | `NULL` | CLIENT_ID used for Secret | +| `CLIENT_SECRET` | `VARCHAR` | `NULL` | CLIENT_SECRET needed for Secret | +| `DEFAULT_REGION` | `VARCHAR` | `NULL` | A Default region to use when communicating with the storage layer | +| `OAUTH2_SERVER_URI` | `VARCHAR` | `NULL` | OAuth2 server url for getting a Bearer Token | +| `AUTHORIZATION_TYPE` | `VARCHAR` | `OAUTH2` | Pass `SigV4` for Catalogs the require SigV4 authorization, `none` for catalogs that don't need auth | +| `SUPPORTED_NESTED_NAMESPACES` | `BOOLEAN` | `true` | Option for catalogs that support nested namespaces. | +| `SUPPORT_STAGE_CREATE` | `BOOLEAN` | `false` | Option for catalogs that do not support stage create. | + The following options can only be passed to a `CREATE SECRET` statement, and they require `AUTHORIZATION_TYPE` to be `OAUTH2` -| Parameter | Type | Default | Description | -| ---------------------------- | ---------- | -------- | ---------------------------------------------------------- | -| `OAUTH2_GRANT_TYPE` | `VARCHAR` | `NULL` | Grant Type when requesting an OAuth Token | -| `OAUTH2_SCOPE` | `VARCHAR` | `NULL` | Requested scope for the returned OAuth Access Token | +| Parameter | Type | Default | Description | +|---------------------|-----------|---------|-----------------------------------------------------| +| `OAUTH2_GRANT_TYPE` | `VARCHAR` | `NULL` | Grant Type when requesting an OAuth Token | +| `OAUTH2_SCOPE` | `VARCHAR` | `NULL` | Requested scope for the returned OAuth Access Token | + + +### Supported Operations + +The DuckDB Iceberg extensions supports the following operations when used with a REST catalog attached: + +- `CREATE/DROP SCHEMA` +- `CREATE/DROP TABLE` +- `INSERT INTO` +- `SELECT` + +Since these operations are supported, the following would also work: + +```sql +COPY FROM DATABASE duckdb_db TO iceberg_datalake; + +-- Or +COPY FROM DATABASE iceberg_datalake to duckdb_db; +``` + +This functionality enables deep copies between Iceberg and DuckDB storage. + +### Metadata Operations + +The functions `iceberg_metadata` and `iceberg_snapshots` are also available to use with an Iceberg REST catalog using a fully qualified path, e.g. + +```sql +SELECT * FROM iceberg_metadata(my_datalake.default.t) + +-- Or +SELECT * FROM iceberg_snapshots(my_datalake.default.t) +``` + +This functionality enables the user to grab a `snapshot_from_id` to do **time-traveling**. + +```sql +SELECT * FROM iceberg_scan(my_datalake.default.t, snapshot_from_id => ⟨SNAPSHOT_ID⟩); + +-- Or using a timestamp +SELECT * FROM iceberg_scan(my_datalake.default.t, snapshot_from_timestamp => '2025-09-22 12:32:43.217') +``` + +### Interoperability with DuckLake + +The DuckDB Iceberg extensions exposes a function to do metadata only copies of the Iceberg metadata to DuckLake, which enables users to query Iceberg tables as if they where DuckLake tables. + +```sql +-- Given that we have an Iceberg catalog attached aliased to iceberg_datalake +ATTACH `ducklake:my_ducklake.ducklake` AS my_ducklake; + +CALL iceberg_to_ducklake('iceberg_datalake', 'my_ducklake'); +``` + +It is also possible to skip a set of tables provided the `skip_tables` parameter. + +```sql +CALL iceberg_to_ducklake('iceberg_datalake', 'my_ducklake', skip_tables := ['table_to_skip']); +``` + +### Unsupported Operations + +The following operations are not supported by the Iceberg DuckDB extension: + +- `UPDATE` +- `DELETE` +- `MERGE INTO` +- `ALTER TABLE` ## Specific Catalog Examples diff --git a/docs/preview/core_extensions/iceberg/overview.md b/docs/preview/core_extensions/iceberg/overview.md index 06b3398c8a..f7d8991899 100644 --- a/docs/preview/core_extensions/iceberg/overview.md +++ b/docs/preview/core_extensions/iceberg/overview.md @@ -4,7 +4,8 @@ layout: docu title: Iceberg Extension --- -The `iceberg` extension implements support for the [Apache Iceberg open table format](https://iceberg.apache.org/). +The `iceberg` extension implements support for the [Apache Iceberg open table format](https://iceberg.apache.org/). +In this page we will go over the basic usage of the extension without the need to attach to an Iceberg catalog. For full support —including write support— see [how to attach Iceberg REST catalogs]({% link docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md %}). ## Installing and Loading @@ -71,7 +72,7 @@ FROM iceberg_scan('lineitem_iceberg/metadata/v1.metadata.json'); |-------------:| | 60175 | -The `iceberg` works together with the [`httpfs` extension]({% link docs/preview/core_extensions/httpfs/overview.md %}) or the [`azure` extension]({% link docs/preview/core_extensions/azure.md %}) to access Iceberg tables in object stores such as S3 or Azure Blob Storage. +The `iceberg` works together with the [`httpfs` extension]({% link docs/stable/core_extensions/httpfs/overview.md %}) or the [`azure` extension]({% link docs/stable/core_extensions/azure.md %}) to access Iceberg tables in object stores such as S3 or Azure Blob Storage. ```sql SELECT count(*) @@ -179,7 +180,3 @@ FROM iceberg_scan( allow_moved_paths = true ); ``` - -## Limitations - -Writing (i.e., exporting to) Iceberg files is currently not supported. From c753a17598928abc6c6158e2571407830f8b9e2c Mon Sep 17 00:00:00 2001 From: guillesd Date: Mon, 22 Sep 2025 14:34:41 +0200 Subject: [PATCH 5/7] reformat time-travel --- docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md | 4 ++-- docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md b/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md index f8a7f9c571..767727d2ab 100644 --- a/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md +++ b/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md @@ -107,10 +107,10 @@ SELECT * FROM iceberg_snapshots(my_datalake.default.t) This functionality enables the user to grab a `snapshot_from_id` to do **time-traveling**. ```sql -SELECT * FROM iceberg_scan(my_datalake.default.t, snapshot_from_id => ⟨SNAPSHOT_ID⟩); +SELECT * FROM my_datalake.default.t AT (VERSION => ⟨SNAPSHOT_ID⟩) -- Or using a timestamp -SELECT * FROM iceberg_scan(my_datalake.default.t, snapshot_from_timestamp => '2025-09-22 12:32:43.217') +SELECT * FROM iceberg_scan(TIMESTAMP => TIMESTAMP '2025-09-22 12:32:43.217') ``` ### Interoperability with DuckLake diff --git a/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md b/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md index cd42057ade..0060f3c81b 100644 --- a/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md +++ b/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md @@ -107,10 +107,10 @@ SELECT * FROM iceberg_snapshots(my_datalake.default.t) This functionality enables the user to grab a `snapshot_from_id` to do **time-traveling**. ```sql -SELECT * FROM iceberg_scan(my_datalake.default.t, snapshot_from_id => ⟨SNAPSHOT_ID⟩); +SELECT * FROM my_datalake.default.t AT (VERSION => ⟨SNAPSHOT_ID⟩) -- Or using a timestamp -SELECT * FROM iceberg_scan(my_datalake.default.t, snapshot_from_timestamp => '2025-09-22 12:32:43.217') +SELECT * FROM iceberg_scan(TIMESTAMP => TIMESTAMP '2025-09-22 12:32:43.217') ``` ### Interoperability with DuckLake From 9bbc25eba5d5f0a0a4550241d125b6ded61765a0 Mon Sep 17 00:00:00 2001 From: guillesd Date: Mon, 22 Sep 2025 14:35:52 +0200 Subject: [PATCH 6/7] missed sth --- docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md | 2 +- docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md b/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md index 767727d2ab..5357e78450 100644 --- a/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md +++ b/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md @@ -110,7 +110,7 @@ This functionality enables the user to grab a `snapshot_from_id` to do **time-tr SELECT * FROM my_datalake.default.t AT (VERSION => ⟨SNAPSHOT_ID⟩) -- Or using a timestamp -SELECT * FROM iceberg_scan(TIMESTAMP => TIMESTAMP '2025-09-22 12:32:43.217') +SELECT * FROM my_datalake.default.t AT (TIMESTAMP => TIMESTAMP '2025-09-22 12:32:43.217') ``` ### Interoperability with DuckLake diff --git a/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md b/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md index 0060f3c81b..6b5db08086 100644 --- a/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md +++ b/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md @@ -110,7 +110,7 @@ This functionality enables the user to grab a `snapshot_from_id` to do **time-tr SELECT * FROM my_datalake.default.t AT (VERSION => ⟨SNAPSHOT_ID⟩) -- Or using a timestamp -SELECT * FROM iceberg_scan(TIMESTAMP => TIMESTAMP '2025-09-22 12:32:43.217') +SELECT * FROM my_datalake.default.t AT (TIMESTAMP => TIMESTAMP '2025-09-22 12:32:43.217') ``` ### Interoperability with DuckLake From 004019642c5dcd8f339bbd3be403b9d45c109bb7 Mon Sep 17 00:00:00 2001 From: guillesd Date: Mon, 22 Sep 2025 14:44:33 +0200 Subject: [PATCH 7/7] address comments --- .../core_extensions/iceberg/iceberg_rest_catalogs.md | 2 +- docs/preview/core_extensions/iceberg/overview.md | 9 +++++++++ .../core_extensions/iceberg/iceberg_rest_catalogs.md | 2 +- docs/stable/core_extensions/iceberg/overview.md | 9 +++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md b/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md index 5357e78450..09f23ce635 100644 --- a/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md +++ b/docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md @@ -60,7 +60,7 @@ A REST Catalog with OAuth2 authorization can also be attached with just an `ATTA | `DEFAULT_REGION` | `VARCHAR` | `NULL` | A Default region to use when communicating with the storage layer | | `OAUTH2_SERVER_URI` | `VARCHAR` | `NULL` | OAuth2 server url for getting a Bearer Token | | `AUTHORIZATION_TYPE` | `VARCHAR` | `OAUTH2` | Pass `SigV4` for Catalogs the require SigV4 authorization, `none` for catalogs that don't need auth | -| `SUPPORTED_NESTED_NAMESPACES` | `BOOLEAN` | `true` | Option for catalogs that support nested namespaces. | +| `SUPPORT_NESTED_NAMESPACES` | `BOOLEAN` | `true` | Option for catalogs that support nested namespaces. | | `SUPPORT_STAGE_CREATE` | `BOOLEAN` | `false` | Option for catalogs that do not support stage create. | diff --git a/docs/preview/core_extensions/iceberg/overview.md b/docs/preview/core_extensions/iceberg/overview.md index f7d8991899..57aa989111 100644 --- a/docs/preview/core_extensions/iceberg/overview.md +++ b/docs/preview/core_extensions/iceberg/overview.md @@ -180,3 +180,12 @@ FROM iceberg_scan( allow_moved_paths = true ); ``` + +## Limitations + +- Updates and deletes. +- Inserts into v3 Iceberg specification tables. +- Reads from v3 tables with v2 data types. +- Geometry data type + +For a set of unsupported operations when attaching to an iceberg catalog, [see]({% link docs/preview/core_extensions/iceberg/iceberg_rest_catalogs.md %}#unsupported-operations). diff --git a/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md b/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md index 6b5db08086..a27ae15de1 100644 --- a/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md +++ b/docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md @@ -60,7 +60,7 @@ A REST Catalog with OAuth2 authorization can also be attached with just an `ATTA | `DEFAULT_REGION` | `VARCHAR` | `NULL` | A Default region to use when communicating with the storage layer | | `OAUTH2_SERVER_URI` | `VARCHAR` | `NULL` | OAuth2 server url for getting a Bearer Token | | `AUTHORIZATION_TYPE` | `VARCHAR` | `OAUTH2` | Pass `SigV4` for Catalogs the require SigV4 authorization, `none` for catalogs that don't need auth | -| `SUPPORTED_NESTED_NAMESPACES` | `BOOLEAN` | `true` | Option for catalogs that support nested namespaces. | +| `SUPPORT_NESTED_NAMESPACES` | `BOOLEAN` | `true` | Option for catalogs that support nested namespaces. | | `SUPPORT_STAGE_CREATE` | `BOOLEAN` | `false` | Option for catalogs that do not support stage create. | diff --git a/docs/stable/core_extensions/iceberg/overview.md b/docs/stable/core_extensions/iceberg/overview.md index 731cea9eef..f5175ee824 100644 --- a/docs/stable/core_extensions/iceberg/overview.md +++ b/docs/stable/core_extensions/iceberg/overview.md @@ -187,3 +187,12 @@ FROM iceberg_scan( allow_moved_paths = true ); ``` + +## Limitations + +- Updates and deletes. +- Inserts into v3 Iceberg specification tables. +- Reads from v3 tables with v2 data types. +- Geometry data type + +For a set of unsupported operations when attaching to an iceberg catalog, [see]({% link docs/stable/core_extensions/iceberg/iceberg_rest_catalogs.md %}#unsupported-operations).