Summary
kbagent can already apply BigQuery clustering to an existing Storage table, but only via a
full copy: storage create-table --source-table-id ... --clustering-field ... +
storage swap-tables (shipped v0.67.0/v0.71.0, CLI + REST + the web UI's "Repartition" tab).
BigQuery's own API supports this as a metadata-only PATCH with no data rewrite (tables.patch,
clustering field on the Table resource —
https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#clustering; see also
https://docs.cloud.google.com/bigquery/docs/manage-partition-cluster-recommendations#apply_clusters_directly_to_the_original_table).
Keboola's Storage API doesn't expose that yet: clustering/timePartitioning/
rangePartitioning only exist on the create-time POST .../tables-definition endpoint. The one
endpoint that patches an existing typed table, PUT /v2/storage/tables/{table_id}/definition,
has no such field — checked against the canonical apiary.apib spec; its attributes are limited
to displayName, description, and per-column length/nullable/default/description.
Current workaround, and its cost
The copy+swap path already works end-to-end and is documented in our own team's kbagent skill.
But it:
- requires a full read+write of the table's data, not a metadata change — expensive/slow on
large tables;
- needs a second physical table to exist temporarily (2x storage during the swap window);
- has a known swap-timeout false negative (
STORAGE_JOB_TIMEOUT on a 60s poll can fire even
though the async Storage job actually succeeded server-side), so a swap has to be verified
physically rather than trusted from the client's response.
None of that should be necessary for what's fundamentally a metadata-only change on BigQuery's
side.
Proposal
Extend PUT /v2/storage/tables/{table_id}/definition (Storage API) with an optional
clustering attribute (mirroring the shape already used on the create-time endpoint), proxying
to BigQuery's tables.patch. Once that endpoint exists, the kbagent-side addition is small and
follows the existing pattern exactly:
client/storage_tables.py — a new method calling the new endpoint, mirroring create_table's
existing clustering handling (client/storage_tables.py:556-562).
services/storage_service.py — a sibling to _build_bigquery_layout
(services/storage_service.py:200-273), with the same BigQuery-only pre-flight guard already
used for the create-time flags (services/storage_service.py:943-967).
commands/storage.py — a new command (e.g. storage set-clustering) or a flag addition to an
existing describe/definition command.
server/routers/storage.py — a matching REST route.
No new GCP credential handling is needed anywhere — this stays entirely inside kbagent's existing
"talk only to Keboola's Storage API" model. Confirmed: no google-cloud-bigquery/google-auth
dependency exists in the installed package today.
I recognize the actual gap sits in Keboola's Storage API, not kbagent's code — filing here since
keboola/cli is where I can raise it, and the kbagent-side work is worth tracking alongside
whatever Storage API change it depends on.
Not a duplicate
Checked gh issue list --repo keboola/cli --search "cluster|clustering|partition" --state all.
#621 (closed) is the closest hit — it was about table-detail not returning the table's
registered definition (the create-time layout), fixed in v0.88.0. Nothing found asking for an
in-place/no-rewrite clustering update path.
Environment
- kbagent v0.91.0
- Keboola BigQuery-backed project (stack
connection.europe-west3.gcp.keboola.com)
Summary
kbagent can already apply BigQuery clustering to an existing Storage table, but only via a
full copy:
storage create-table --source-table-id ... --clustering-field ...+storage swap-tables(shipped v0.67.0/v0.71.0, CLI + REST + the web UI's "Repartition" tab).BigQuery's own API supports this as a metadata-only PATCH with no data rewrite (
tables.patch,clusteringfield on theTableresource —https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#clustering; see also
https://docs.cloud.google.com/bigquery/docs/manage-partition-cluster-recommendations#apply_clusters_directly_to_the_original_table).
Keboola's Storage API doesn't expose that yet:
clustering/timePartitioning/rangePartitioningonly exist on the create-timePOST .../tables-definitionendpoint. The oneendpoint that patches an existing typed table,
PUT /v2/storage/tables/{table_id}/definition,has no such field — checked against the canonical
apiary.apibspec; its attributes are limitedto
displayName,description, and per-columnlength/nullable/default/description.Current workaround, and its cost
The copy+swap path already works end-to-end and is documented in our own team's kbagent skill.
But it:
large tables;
STORAGE_JOB_TIMEOUTon a 60s poll can fire eventhough the async Storage job actually succeeded server-side), so a swap has to be verified
physically rather than trusted from the client's response.
None of that should be necessary for what's fundamentally a metadata-only change on BigQuery's
side.
Proposal
Extend
PUT /v2/storage/tables/{table_id}/definition(Storage API) with an optionalclusteringattribute (mirroring the shape already used on the create-time endpoint), proxyingto BigQuery's
tables.patch. Once that endpoint exists, the kbagent-side addition is small andfollows the existing pattern exactly:
client/storage_tables.py— a new method calling the new endpoint, mirroringcreate_table'sexisting
clusteringhandling (client/storage_tables.py:556-562).services/storage_service.py— a sibling to_build_bigquery_layout(
services/storage_service.py:200-273), with the same BigQuery-only pre-flight guard alreadyused for the create-time flags (
services/storage_service.py:943-967).commands/storage.py— a new command (e.g.storage set-clustering) or a flag addition to anexisting describe/definition command.
server/routers/storage.py— a matching REST route.No new GCP credential handling is needed anywhere — this stays entirely inside kbagent's existing
"talk only to Keboola's Storage API" model. Confirmed: no
google-cloud-bigquery/google-authdependency exists in the installed package today.
I recognize the actual gap sits in Keboola's Storage API, not kbagent's code — filing here since
keboola/cliis where I can raise it, and the kbagent-side work is worth tracking alongsidewhatever Storage API change it depends on.
Not a duplicate
Checked
gh issue list --repo keboola/cli --search "cluster|clustering|partition" --state all.#621 (closed) is the closest hit — it was about
table-detailnot returning the table'sregistered
definition(the create-time layout), fixed in v0.88.0. Nothing found asking for anin-place/no-rewrite clustering update path.
Environment
connection.europe-west3.gcp.keboola.com)