Iceberg (REST Catalog)

Driver keys: iceberg Optional dependency: none

A small PHP client for the Apache Iceberg REST Catalog API.

Metadata only. This driver talks to the catalog: namespaces, tables, schemas and snapshot metadata. It never reads or writes Iceberg data files (or manifests) itself.

Driver name iceberg
Client Erikwang2013\BigData\Driver\Iceberg\RestCatalogClient
Config Erikwang2013\BigData\Driver\Iceberg\RestCatalogConfig
Optional dependency none

Quick start

use Erikwang2013\BigData\BigData;

$catalog = BigData::driver('iceberg', [
    'base_url' => 'https://catalog.example.com',
    'warehouse' => 's3://bucket/warehouse',
    'token' => 'my-bearer-token',
]);

foreach ($catalog->namespaces() as $namespace) {
    echo implode('.', $namespace), PHP_EOL;
}

Direct instantiation:

use Erikwang2013\BigData\Driver\Iceberg\RestCatalogClient;
use Erikwang2013\BigData\Driver\Iceberg\RestCatalogConfig;

$catalog = new RestCatalogClient(RestCatalogConfig::fromArray([
    'base_url' => 'https://catalog.example.com',
    'token' => 'my-bearer-token',
]));
// Optional HTTP client and PSR-3 logger: new RestCatalogClient($config, $http, $logger)

Configuration

RestCatalogConfig::fromArray() accepts:

Key Default Description
base_url required Catalog base URL; /v1 is appended to it.
token null Bearer token.
client_id null OAuth client id, used when token is not set.
client_secret null OAuth client secret, used when token is not set.
scope catalog OAuth scope.
warehouse null Warehouse location sent to /v1/config.
prefix null Catalog prefix, inserted between /v1 and the resource path.
verify_ssl true Verify TLS certificates.
timeout 30.0 Request timeout in seconds.

The config can also be constructed directly with camelCase properties.

Catalog operations

$catalog->config();          // ['defaults' => [...], 'overrides' => [...]]

$catalog->namespaces();             // [['analytics'], ['raw'], ...]
$catalog->namespaces('parent_ns');  // child namespaces
$catalog->createNamespace('analytics', ['owner' => 'data-team']);
$catalog->loadNamespace('analytics');
$catalog->dropNamespace('analytics');

$catalog->tables('analytics');      // [['namespace' => ['analytics'], 'name' => 'events'], ...]
$catalog->createTable('analytics', 'events', $schema, ['owner' => 'data-team']);

$table = $catalog->loadTable('analytics', 'events');
$table->location();          // s3://bucket/warehouse/analytics/events
$table->schema();            // Iceberg schema struct
$table->partitionSpec();     // partition fields
$table->snapshots();         // snapshot list
$table->properties();        // table properties
$table->currentSnapshotId(); // null when the table has no current snapshot

$catalog->tableExists('analytics', 'events'); // HEAD request, false on 404
$catalog->dropTable('analytics', 'events');

List requests send pageSize and follow the catalog's next page token (next-page-token, also accepting nextPageToken) until the catalog stops returning one. All methods return the catalog's decoded response payloads verbatim.

Authentication

When token is set it is sent as a Bearer token. Otherwise, if client_id and client_secret are set, the client requests a token from /v1/oauth/tokens (client_credentials grant, form encoded) and reuses it until 30 seconds before expires_in.

Logging

RestCatalogClient accepts an optional PSR-3 logger as its third constructor argument and defaults to Psr\Log\NullLogger. Debug records contain the HTTP method and URI only — auth headers are never logged.

Errors

Transport failures throw Erikwang2013\BigData\Exception\ConnectionException. HTTP status >= 400 or an invalid JSON response raises Erikwang2013\BigData\Exception\RequestException, which exposes public $statusCode and $body. Both exceptions extend Erikwang2013\BigData\Exception\BigDataException.

Notes

  • Metadata/catalog only: no data or manifest files are read.
  • currentSnapshotId() normalizes Iceberg's -1 ("no snapshot") to null.
  • No automatic retries are performed.

Search this site

Try “Trino”, “Laravel” or “Airflow”.