vgi-python 0.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vgi/__init__.py +152 -0
- vgi/_duckdb.py +62 -0
- vgi/_storage_profile.py +132 -0
- vgi/_test_fixtures/__init__.py +20 -0
- vgi/_test_fixtures/accumulate/__init__.py +19 -0
- vgi/_test_fixtures/accumulate/worker.py +762 -0
- vgi/_test_fixtures/aggregate/__init__.py +62 -0
- vgi/_test_fixtures/aggregate/_common.py +21 -0
- vgi/_test_fixtures/aggregate/basic.py +232 -0
- vgi/_test_fixtures/aggregate/dynamic.py +409 -0
- vgi/_test_fixtures/aggregate/generic.py +86 -0
- vgi/_test_fixtures/aggregate/listagg.py +71 -0
- vgi/_test_fixtures/aggregate/percentile.py +107 -0
- vgi/_test_fixtures/aggregate/streaming.py +192 -0
- vgi/_test_fixtures/aggregate/varargs.py +75 -0
- vgi/_test_fixtures/aggregate/window.py +380 -0
- vgi/_test_fixtures/attach_options.py +308 -0
- vgi/_test_fixtures/bad_protocol.py +62 -0
- vgi/_test_fixtures/cancellable.py +336 -0
- vgi/_test_fixtures/catalog.py +813 -0
- vgi/_test_fixtures/http_server.py +394 -0
- vgi/_test_fixtures/nest_tensor.py +614 -0
- vgi/_test_fixtures/orchard_catalog.py +47 -0
- vgi/_test_fixtures/projection_repro/__init__.py +6 -0
- vgi/_test_fixtures/projection_repro/worker.py +454 -0
- vgi/_test_fixtures/scalar/__init__.py +116 -0
- vgi/_test_fixtures/scalar/_common.py +69 -0
- vgi/_test_fixtures/scalar/arithmetic.py +321 -0
- vgi/_test_fixtures/scalar/binary.py +120 -0
- vgi/_test_fixtures/scalar/formatting.py +176 -0
- vgi/_test_fixtures/scalar/geo.py +300 -0
- vgi/_test_fixtures/scalar/null_handling.py +107 -0
- vgi/_test_fixtures/scalar/random_demo.py +171 -0
- vgi/_test_fixtures/scalar/settings_secrets.py +102 -0
- vgi/_test_fixtures/scalar/type_info.py +219 -0
- vgi/_test_fixtures/schema_reconcile/__init__.py +29 -0
- vgi/_test_fixtures/schema_reconcile/worker.py +653 -0
- vgi/_test_fixtures/simple_writable.py +793 -0
- vgi/_test_fixtures/table/__init__.py +221 -0
- vgi/_test_fixtures/table/_common.py +162 -0
- vgi/_test_fixtures/table/batch_index.py +283 -0
- vgi/_test_fixtures/table/batch_index_broken.py +200 -0
- vgi/_test_fixtures/table/catalog_scans.py +162 -0
- vgi/_test_fixtures/table/filters.py +1005 -0
- vgi/_test_fixtures/table/late_materialization.py +249 -0
- vgi/_test_fixtures/table/make_series.py +273 -0
- vgi/_test_fixtures/table/misc.py +499 -0
- vgi/_test_fixtures/table/order_modes.py +164 -0
- vgi/_test_fixtures/table/pairs.py +437 -0
- vgi/_test_fixtures/table/partition_columns.py +472 -0
- vgi/_test_fixtures/table/partition_columns_broken.py +304 -0
- vgi/_test_fixtures/table/profiling_example.py +195 -0
- vgi/_test_fixtures/table/required_filters.py +234 -0
- vgi/_test_fixtures/table/sequence.py +710 -0
- vgi/_test_fixtures/table/settings.py +426 -0
- vgi/_test_fixtures/table/transaction_storage.py +162 -0
- vgi/_test_fixtures/table/tt_pushdown.py +191 -0
- vgi/_test_fixtures/table/versioned.py +230 -0
- vgi/_test_fixtures/table_in_out.py +1392 -0
- vgi/_test_fixtures/versioned.py +155 -0
- vgi/_test_fixtures/versioned_tables.py +595 -0
- vgi/_test_fixtures/worker.py +1631 -0
- vgi/_test_fixtures/writable/__init__.py +8 -0
- vgi/_test_fixtures/writable/generic.py +236 -0
- vgi/_test_fixtures/writable/table.py +149 -0
- vgi/_test_fixtures/writable/worker.py +1148 -0
- vgi/aggregate_function.py +607 -0
- vgi/argument_spec.py +472 -0
- vgi/arguments.py +1747 -0
- vgi/auth.py +55 -0
- vgi/catalog/__init__.py +88 -0
- vgi/catalog/attach_option.py +206 -0
- vgi/catalog/catalog_interface.py +2767 -0
- vgi/catalog/descriptors.py +870 -0
- vgi/catalog/duckdb_statistics.py +377 -0
- vgi/catalog/secret_type.py +96 -0
- vgi/catalog/setting.py +253 -0
- vgi/catalog/storage.py +372 -0
- vgi/client/__init__.py +67 -0
- vgi/client/catalog_mixin.py +1251 -0
- vgi/client/cli.py +582 -0
- vgi/client/cli_catalog.py +182 -0
- vgi/client/cli_schema.py +270 -0
- vgi/client/cli_table.py +907 -0
- vgi/client/cli_transaction.py +97 -0
- vgi/client/cli_utils.py +441 -0
- vgi/client/cli_view.py +303 -0
- vgi/client/client.py +2183 -0
- vgi/exceptions.py +205 -0
- vgi/function.py +245 -0
- vgi/function_storage.py +1636 -0
- vgi/function_storage_azure_sql.py +922 -0
- vgi/function_storage_cf_do.py +740 -0
- vgi/http/__init__.py +25 -0
- vgi/http/demo_storage.py +212 -0
- vgi/http/worker_page.py +1252 -0
- vgi/invocation.py +154 -0
- vgi/logging_config.py +93 -0
- vgi/meta_worker.py +661 -0
- vgi/metadata.py +1403 -0
- vgi/otel.py +406 -0
- vgi/protocol.py +2418 -0
- vgi/protocol_version.txt +1 -0
- vgi/py.typed +0 -0
- vgi/scalar_function.py +1211 -0
- vgi/schema_utils.py +234 -0
- vgi/secret_protocol.py +124 -0
- vgi/secret_service.py +238 -0
- vgi/serve.py +769 -0
- vgi/table_buffering_function.py +443 -0
- vgi/table_filter_pushdown.py +1528 -0
- vgi/table_function.py +1130 -0
- vgi/table_in_out_function.py +383 -0
- vgi/transactor/__init__.py +24 -0
- vgi/transactor/_duckdb_compat.py +27 -0
- vgi/transactor/client.py +137 -0
- vgi/transactor/protocol.py +149 -0
- vgi/transactor/server.py +740 -0
- vgi/worker.py +4761 -0
- vgi_python-0.8.0.dist-info/METADATA +735 -0
- vgi_python-0.8.0.dist-info/RECORD +124 -0
- vgi_python-0.8.0.dist-info/WHEEL +4 -0
- vgi_python-0.8.0.dist-info/entry_points.txt +5 -0
- vgi_python-0.8.0.dist-info/licenses/LICENSE +134 -0
|
@@ -0,0 +1,1251 @@
|
|
|
1
|
+
# Copyright 2025, 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
"""CatalogClientMixin for adding catalog operations to Client.
|
|
4
|
+
|
|
5
|
+
This module provides a mixin class that adds catalog operation methods
|
|
6
|
+
to the VGI Client. It handles the ephemeral subprocess pattern for
|
|
7
|
+
catalog calls while using the Client's server_path and correlation_id.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
class CatalogEnabledClient(CatalogClientMixin, Client):
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
client = CatalogEnabledClient("vgi-my-worker")
|
|
14
|
+
|
|
15
|
+
# List available catalogs
|
|
16
|
+
catalogs = client.catalogs()
|
|
17
|
+
|
|
18
|
+
# Attach to a catalog and work with schemas
|
|
19
|
+
result = client.catalog_attach(
|
|
20
|
+
name="my_catalog", data_version_spec=None, implementation_version=None
|
|
21
|
+
)
|
|
22
|
+
schemas = client.schemas(attach_opaque_data=result.attach_opaque_data)
|
|
23
|
+
|
|
24
|
+
# Use transactions for atomic operations
|
|
25
|
+
tx_id = client.catalog_transaction_begin(attach_opaque_data=result.attach_opaque_data)
|
|
26
|
+
client.schema_create(
|
|
27
|
+
attach_opaque_data=result.attach_opaque_data, transaction_opaque_data=tx_id, name="new_schema"
|
|
28
|
+
)
|
|
29
|
+
client.catalog_transaction_commit(
|
|
30
|
+
attach_opaque_data=result.attach_opaque_data, transaction_opaque_data=tx_id
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
Error Handling:
|
|
34
|
+
Worker exceptions are propagated via vgi_rpc's RpcError mechanism.
|
|
35
|
+
These are wrapped in CatalogClientError for a consistent client API.
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
from __future__ import annotations
|
|
40
|
+
|
|
41
|
+
import shlex
|
|
42
|
+
import sys
|
|
43
|
+
from collections.abc import Iterator, Sequence
|
|
44
|
+
from contextlib import contextmanager
|
|
45
|
+
from typing import Any, Literal, overload
|
|
46
|
+
|
|
47
|
+
import pyarrow as pa
|
|
48
|
+
from vgi_rpc import WorkerPool
|
|
49
|
+
from vgi_rpc.rpc import RpcError
|
|
50
|
+
from vgi_rpc.utils import deserialize_record_batch
|
|
51
|
+
|
|
52
|
+
from vgi.catalog import (
|
|
53
|
+
AttachOpaqueData,
|
|
54
|
+
CatalogAttachResult,
|
|
55
|
+
CatalogInfo,
|
|
56
|
+
FunctionInfo,
|
|
57
|
+
MacroInfo,
|
|
58
|
+
MacroType,
|
|
59
|
+
OnConflict,
|
|
60
|
+
ScanFunctionResult,
|
|
61
|
+
SchemaInfo,
|
|
62
|
+
SchemaObjectType,
|
|
63
|
+
SerializedSchema,
|
|
64
|
+
SqlExpression,
|
|
65
|
+
TableInfo,
|
|
66
|
+
TransactionOpaqueData,
|
|
67
|
+
ViewInfo,
|
|
68
|
+
)
|
|
69
|
+
from vgi.protocol import (
|
|
70
|
+
CatalogAttachRequest,
|
|
71
|
+
CatalogCreateRequest,
|
|
72
|
+
MacroCreateRequest,
|
|
73
|
+
TableCreateRequest,
|
|
74
|
+
VgiProtocol,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# Module-level worker pool shared across all CatalogClientMixin instances.
|
|
78
|
+
# Workers are cached by command and reused across catalog calls, avoiding
|
|
79
|
+
# the overhead of spawning/tearing down a subprocess for each call.
|
|
80
|
+
_catalog_pool = WorkerPool(max_idle=4, idle_timeout=30.0)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class CatalogClientError(Exception):
|
|
84
|
+
"""Error raised by catalog operations."""
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class CatalogClientMixin:
|
|
88
|
+
"""Mixin that adds catalog operations to a VGI Client.
|
|
89
|
+
|
|
90
|
+
Catalog methods spawn ephemeral connections under the hood — for
|
|
91
|
+
subprocess transport a pooled subprocess worker; for HTTP transport a
|
|
92
|
+
short-lived ``http_connect`` session reusing the ``Client``'s shared
|
|
93
|
+
``httpx.Client`` (bearer token, headers). Browsing catalogs over HTTP
|
|
94
|
+
is the canonical non-DuckDB use case this mixin supports.
|
|
95
|
+
|
|
96
|
+
Expected attributes from ``Client``:
|
|
97
|
+
server_path: str — worker shell command (subprocess transport).
|
|
98
|
+
_transport: Literal["subprocess", "http"].
|
|
99
|
+
_base_url: str | None — HTTP base URL.
|
|
100
|
+
_get_or_create_httpx_client(): shared HTTP client factory.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
# Type hints for attributes expected from Client
|
|
104
|
+
server_path: str
|
|
105
|
+
_transport: Literal["subprocess", "http"]
|
|
106
|
+
_base_url: str | None
|
|
107
|
+
_external_location: Any | None
|
|
108
|
+
|
|
109
|
+
def _get_or_create_httpx_client(self) -> Any: # implemented by Client
|
|
110
|
+
raise NotImplementedError
|
|
111
|
+
|
|
112
|
+
@contextmanager
|
|
113
|
+
def _catalog_connect(self) -> Iterator[VgiProtocol]:
|
|
114
|
+
"""Yield a typed ``VgiProtocol`` proxy honoring the client's transport.
|
|
115
|
+
|
|
116
|
+
Subprocess: borrows from a module-level ``WorkerPool`` keyed by
|
|
117
|
+
command, so repeated catalog calls reuse a warm worker.
|
|
118
|
+
|
|
119
|
+
HTTP: opens a short-lived ``http_connect`` session per call. The
|
|
120
|
+
underlying ``httpx.Client`` is shared across calls via
|
|
121
|
+
``Client._get_or_create_httpx_client`` so auth headers and
|
|
122
|
+
connection pooling are consistent.
|
|
123
|
+
|
|
124
|
+
Worker errors are caught and re-raised as ``CatalogClientError``.
|
|
125
|
+
"""
|
|
126
|
+
try:
|
|
127
|
+
if getattr(self, "_transport", "subprocess") == "http":
|
|
128
|
+
from vgi_rpc.http import http_connect
|
|
129
|
+
|
|
130
|
+
httpx_client = self._get_or_create_httpx_client()
|
|
131
|
+
with http_connect(
|
|
132
|
+
VgiProtocol, # type: ignore[type-abstract]
|
|
133
|
+
base_url=self._base_url,
|
|
134
|
+
client=httpx_client,
|
|
135
|
+
external_location=getattr(self, "_external_location", None),
|
|
136
|
+
) as proxy:
|
|
137
|
+
yield proxy
|
|
138
|
+
else:
|
|
139
|
+
cmd = shlex.split(self.server_path, posix=sys.platform != "win32")
|
|
140
|
+
with _catalog_pool.connect(VgiProtocol, cmd) as proxy: # type: ignore[type-abstract]
|
|
141
|
+
yield proxy
|
|
142
|
+
except RpcError as e:
|
|
143
|
+
raise CatalogClientError(str(e)) from e
|
|
144
|
+
except CatalogClientError:
|
|
145
|
+
raise
|
|
146
|
+
except Exception as e:
|
|
147
|
+
raise CatalogClientError(f"Failed catalog call: {e}") from e
|
|
148
|
+
|
|
149
|
+
@staticmethod
|
|
150
|
+
def _options_to_batch(options: dict[str, Any] | None) -> pa.RecordBatch | None:
|
|
151
|
+
"""Convert an options dict to a one-row RecordBatch for wire transport.
|
|
152
|
+
|
|
153
|
+
Returns None if options is empty/None.
|
|
154
|
+
"""
|
|
155
|
+
if not options:
|
|
156
|
+
return None
|
|
157
|
+
return pa.RecordBatch.from_pylist([options])
|
|
158
|
+
|
|
159
|
+
# ========== Discovery Methods ==========
|
|
160
|
+
|
|
161
|
+
def catalogs(self) -> list[CatalogInfo]:
|
|
162
|
+
"""Get list of catalog discovery records from the worker.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
List of CatalogInfo records carrying per-catalog name,
|
|
166
|
+
implementation_version, and data_version_spec.
|
|
167
|
+
|
|
168
|
+
"""
|
|
169
|
+
with self._catalog_connect() as proxy:
|
|
170
|
+
return proxy.catalog_catalogs().to_infos()
|
|
171
|
+
|
|
172
|
+
# ========== Catalog Lifecycle Methods ==========
|
|
173
|
+
|
|
174
|
+
def catalog_attach(
|
|
175
|
+
self,
|
|
176
|
+
*,
|
|
177
|
+
name: str,
|
|
178
|
+
options: dict[str, Any] | None = None,
|
|
179
|
+
data_version_spec: str | None,
|
|
180
|
+
implementation_version: str | None,
|
|
181
|
+
) -> CatalogAttachResult:
|
|
182
|
+
"""Attach to a catalog.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
name: The catalog name to attach to.
|
|
186
|
+
options: Optional dictionary of catalog-specific options.
|
|
187
|
+
data_version_spec: Semver constraint for the catalog's data version
|
|
188
|
+
(``None`` = unconstrained — worker picks).
|
|
189
|
+
implementation_version: Semver constraint for the worker's
|
|
190
|
+
implementation version (``None`` = unconstrained).
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
CatalogAttachResult with attach_opaque_data, catalog capabilities, and
|
|
194
|
+
the resolved concrete versions the worker picked.
|
|
195
|
+
|
|
196
|
+
"""
|
|
197
|
+
with self._catalog_connect() as proxy:
|
|
198
|
+
return proxy.catalog_attach(
|
|
199
|
+
request=CatalogAttachRequest(
|
|
200
|
+
name=name,
|
|
201
|
+
options=self._options_to_batch(options),
|
|
202
|
+
data_version_spec=data_version_spec,
|
|
203
|
+
implementation_version=implementation_version,
|
|
204
|
+
)
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
def catalog_detach(self, *, attach_opaque_data: AttachOpaqueData) -> None:
|
|
208
|
+
"""Detach from a catalog.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
212
|
+
|
|
213
|
+
"""
|
|
214
|
+
with self._catalog_connect() as proxy:
|
|
215
|
+
proxy.catalog_detach(attach_opaque_data=attach_opaque_data)
|
|
216
|
+
|
|
217
|
+
def catalog_create(
|
|
218
|
+
self,
|
|
219
|
+
*,
|
|
220
|
+
name: str,
|
|
221
|
+
on_conflict: OnConflict = OnConflict.ERROR,
|
|
222
|
+
options: dict[str, Any] | None = None,
|
|
223
|
+
) -> None:
|
|
224
|
+
"""Create a new catalog.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
name: The name for the new catalog.
|
|
228
|
+
on_conflict: Behavior if catalog already exists.
|
|
229
|
+
options: Optional dictionary of catalog-specific options.
|
|
230
|
+
|
|
231
|
+
"""
|
|
232
|
+
with self._catalog_connect() as proxy:
|
|
233
|
+
proxy.catalog_create(
|
|
234
|
+
request=CatalogCreateRequest(
|
|
235
|
+
name=name,
|
|
236
|
+
on_conflict=on_conflict,
|
|
237
|
+
options=self._options_to_batch(options),
|
|
238
|
+
)
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
def catalog_drop(self, *, name: str) -> None:
|
|
242
|
+
"""Drop a catalog.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
name: The name of the catalog to drop.
|
|
246
|
+
|
|
247
|
+
"""
|
|
248
|
+
with self._catalog_connect() as proxy:
|
|
249
|
+
proxy.catalog_drop(name=name)
|
|
250
|
+
|
|
251
|
+
def catalog_version(
|
|
252
|
+
self, *, attach_opaque_data: AttachOpaqueData, transaction_opaque_data: TransactionOpaqueData | None = None
|
|
253
|
+
) -> int:
|
|
254
|
+
"""Get the current catalog version.
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
258
|
+
transaction_opaque_data: Optional transaction ID for transactional reads.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
The current catalog version number, or 0 if empty.
|
|
262
|
+
|
|
263
|
+
"""
|
|
264
|
+
with self._catalog_connect() as proxy:
|
|
265
|
+
return proxy.catalog_version(
|
|
266
|
+
attach_opaque_data=attach_opaque_data,
|
|
267
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
268
|
+
).version
|
|
269
|
+
|
|
270
|
+
# ========== Transaction Methods ==========
|
|
271
|
+
|
|
272
|
+
def catalog_transaction_begin(self, *, attach_opaque_data: AttachOpaqueData) -> TransactionOpaqueData | None:
|
|
273
|
+
"""Begin a new transaction.
|
|
274
|
+
|
|
275
|
+
Args:
|
|
276
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
TransactionOpaqueData for the new transaction, or None if transactions
|
|
280
|
+
are not supported by this catalog.
|
|
281
|
+
|
|
282
|
+
"""
|
|
283
|
+
with self._catalog_connect() as proxy:
|
|
284
|
+
tx_id = proxy.catalog_transaction_begin(attach_opaque_data=attach_opaque_data).transaction_opaque_data
|
|
285
|
+
return TransactionOpaqueData(tx_id) if tx_id else None
|
|
286
|
+
|
|
287
|
+
def catalog_transaction_commit(
|
|
288
|
+
self, *, attach_opaque_data: AttachOpaqueData, transaction_opaque_data: TransactionOpaqueData
|
|
289
|
+
) -> None:
|
|
290
|
+
"""Commit a transaction.
|
|
291
|
+
|
|
292
|
+
Args:
|
|
293
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
294
|
+
transaction_opaque_data: The transaction ID to commit.
|
|
295
|
+
|
|
296
|
+
"""
|
|
297
|
+
with self._catalog_connect() as proxy:
|
|
298
|
+
proxy.catalog_transaction_commit(
|
|
299
|
+
attach_opaque_data=attach_opaque_data,
|
|
300
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
def catalog_transaction_rollback(
|
|
304
|
+
self, *, attach_opaque_data: AttachOpaqueData, transaction_opaque_data: TransactionOpaqueData
|
|
305
|
+
) -> None:
|
|
306
|
+
"""Rollback a transaction.
|
|
307
|
+
|
|
308
|
+
Args:
|
|
309
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
310
|
+
transaction_opaque_data: The transaction ID to rollback.
|
|
311
|
+
|
|
312
|
+
"""
|
|
313
|
+
with self._catalog_connect() as proxy:
|
|
314
|
+
proxy.catalog_transaction_rollback(
|
|
315
|
+
attach_opaque_data=attach_opaque_data,
|
|
316
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
# ========== Schema Methods ==========
|
|
320
|
+
|
|
321
|
+
def schemas(
|
|
322
|
+
self, *, attach_opaque_data: AttachOpaqueData, transaction_opaque_data: TransactionOpaqueData | None = None
|
|
323
|
+
) -> list[SchemaInfo]:
|
|
324
|
+
"""List schemas in the catalog.
|
|
325
|
+
|
|
326
|
+
Args:
|
|
327
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
328
|
+
transaction_opaque_data: Optional transaction ID for transactional reads.
|
|
329
|
+
|
|
330
|
+
Returns:
|
|
331
|
+
List of SchemaInfo for each schema in the catalog.
|
|
332
|
+
|
|
333
|
+
"""
|
|
334
|
+
with self._catalog_connect() as proxy:
|
|
335
|
+
return proxy.catalog_schemas(
|
|
336
|
+
attach_opaque_data=attach_opaque_data,
|
|
337
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
338
|
+
).to_infos()
|
|
339
|
+
|
|
340
|
+
def schema_get(
|
|
341
|
+
self,
|
|
342
|
+
*,
|
|
343
|
+
attach_opaque_data: AttachOpaqueData,
|
|
344
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
345
|
+
name: str,
|
|
346
|
+
) -> SchemaInfo | None:
|
|
347
|
+
"""Get information about a schema.
|
|
348
|
+
|
|
349
|
+
Args:
|
|
350
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
351
|
+
transaction_opaque_data: Optional transaction ID for transactional reads.
|
|
352
|
+
name: The schema name.
|
|
353
|
+
|
|
354
|
+
Returns:
|
|
355
|
+
SchemaInfo for the schema, or None if not found.
|
|
356
|
+
|
|
357
|
+
"""
|
|
358
|
+
with self._catalog_connect() as proxy:
|
|
359
|
+
return proxy.catalog_schema_get( # type: ignore[no-any-return]
|
|
360
|
+
attach_opaque_data=attach_opaque_data,
|
|
361
|
+
name=name,
|
|
362
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
363
|
+
).to_optional()
|
|
364
|
+
|
|
365
|
+
def schema_create(
|
|
366
|
+
self,
|
|
367
|
+
*,
|
|
368
|
+
attach_opaque_data: AttachOpaqueData,
|
|
369
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
370
|
+
name: str,
|
|
371
|
+
comment: str | None = None,
|
|
372
|
+
tags: dict[str, str] | None = None,
|
|
373
|
+
) -> None:
|
|
374
|
+
"""Create a new schema.
|
|
375
|
+
|
|
376
|
+
Args:
|
|
377
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
378
|
+
transaction_opaque_data: Optional transaction ID.
|
|
379
|
+
name: The name for the new schema.
|
|
380
|
+
comment: Optional description of the schema.
|
|
381
|
+
tags: Optional key-value tags for the schema.
|
|
382
|
+
|
|
383
|
+
"""
|
|
384
|
+
with self._catalog_connect() as proxy:
|
|
385
|
+
proxy.catalog_schema_create(
|
|
386
|
+
attach_opaque_data=attach_opaque_data,
|
|
387
|
+
name=name,
|
|
388
|
+
comment=comment,
|
|
389
|
+
tags=tags,
|
|
390
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
def schema_drop(
|
|
394
|
+
self,
|
|
395
|
+
*,
|
|
396
|
+
attach_opaque_data: AttachOpaqueData,
|
|
397
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
398
|
+
name: str,
|
|
399
|
+
ignore_not_found: bool = False,
|
|
400
|
+
cascade: bool = False,
|
|
401
|
+
) -> None:
|
|
402
|
+
"""Drop a schema.
|
|
403
|
+
|
|
404
|
+
Args:
|
|
405
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
406
|
+
transaction_opaque_data: Optional transaction ID.
|
|
407
|
+
name: The name of the schema to drop.
|
|
408
|
+
ignore_not_found: If True, don't error if schema doesn't exist.
|
|
409
|
+
cascade: If True, drop all contained tables and views.
|
|
410
|
+
|
|
411
|
+
"""
|
|
412
|
+
with self._catalog_connect() as proxy:
|
|
413
|
+
proxy.catalog_schema_drop(
|
|
414
|
+
attach_opaque_data=attach_opaque_data,
|
|
415
|
+
name=name,
|
|
416
|
+
ignore_not_found=ignore_not_found,
|
|
417
|
+
cascade=cascade,
|
|
418
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
@overload
|
|
422
|
+
def schema_contents(
|
|
423
|
+
self,
|
|
424
|
+
*,
|
|
425
|
+
attach_opaque_data: AttachOpaqueData,
|
|
426
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
427
|
+
name: str,
|
|
428
|
+
type: Literal[SchemaObjectType.TABLE],
|
|
429
|
+
) -> Sequence[TableInfo]: ...
|
|
430
|
+
|
|
431
|
+
@overload
|
|
432
|
+
def schema_contents(
|
|
433
|
+
self,
|
|
434
|
+
*,
|
|
435
|
+
attach_opaque_data: AttachOpaqueData,
|
|
436
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
437
|
+
name: str,
|
|
438
|
+
type: Literal[SchemaObjectType.VIEW],
|
|
439
|
+
) -> Sequence[ViewInfo]: ...
|
|
440
|
+
|
|
441
|
+
@overload
|
|
442
|
+
def schema_contents(
|
|
443
|
+
self,
|
|
444
|
+
*,
|
|
445
|
+
attach_opaque_data: AttachOpaqueData,
|
|
446
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
447
|
+
name: str,
|
|
448
|
+
type: Literal[SchemaObjectType.SCALAR_FUNCTION, SchemaObjectType.TABLE_FUNCTION],
|
|
449
|
+
) -> Sequence[FunctionInfo]: ...
|
|
450
|
+
|
|
451
|
+
@overload
|
|
452
|
+
def schema_contents(
|
|
453
|
+
self,
|
|
454
|
+
*,
|
|
455
|
+
attach_opaque_data: AttachOpaqueData,
|
|
456
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
457
|
+
name: str,
|
|
458
|
+
type: Literal[SchemaObjectType.SCALAR_MACRO, SchemaObjectType.TABLE_MACRO],
|
|
459
|
+
) -> Sequence[MacroInfo]: ...
|
|
460
|
+
|
|
461
|
+
@overload
|
|
462
|
+
def schema_contents(
|
|
463
|
+
self,
|
|
464
|
+
*,
|
|
465
|
+
attach_opaque_data: AttachOpaqueData,
|
|
466
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
467
|
+
name: str,
|
|
468
|
+
type: SchemaObjectType,
|
|
469
|
+
) -> Sequence[TableInfo | ViewInfo | FunctionInfo | MacroInfo]: ...
|
|
470
|
+
|
|
471
|
+
def schema_contents(
|
|
472
|
+
self,
|
|
473
|
+
*,
|
|
474
|
+
attach_opaque_data: AttachOpaqueData,
|
|
475
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
476
|
+
name: str,
|
|
477
|
+
type: SchemaObjectType,
|
|
478
|
+
) -> Sequence[TableInfo | ViewInfo | FunctionInfo | MacroInfo]:
|
|
479
|
+
"""List contents of a schema (tables, views, functions, macros).
|
|
480
|
+
|
|
481
|
+
Args:
|
|
482
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
483
|
+
transaction_opaque_data: Optional transaction ID for transactional reads.
|
|
484
|
+
name: The schema name.
|
|
485
|
+
type: The type of objects to return. Must be a SchemaObjectType enum:
|
|
486
|
+
- SchemaObjectType.TABLE: Return only tables
|
|
487
|
+
- SchemaObjectType.VIEW: Return only views
|
|
488
|
+
- SchemaObjectType.SCALAR_FUNCTION: Return only scalar functions
|
|
489
|
+
- SchemaObjectType.TABLE_FUNCTION: Return only table functions
|
|
490
|
+
- SchemaObjectType.SCALAR_MACRO: Return only scalar macros
|
|
491
|
+
- SchemaObjectType.TABLE_MACRO: Return only table macros
|
|
492
|
+
|
|
493
|
+
Returns:
|
|
494
|
+
List of TableInfo, ViewInfo, FunctionInfo, or MacroInfo depending on the type.
|
|
495
|
+
|
|
496
|
+
"""
|
|
497
|
+
with self._catalog_connect() as proxy:
|
|
498
|
+
if type == SchemaObjectType.TABLE:
|
|
499
|
+
return proxy.catalog_schema_contents_tables(
|
|
500
|
+
attach_opaque_data=attach_opaque_data,
|
|
501
|
+
name=name,
|
|
502
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
503
|
+
).to_infos()
|
|
504
|
+
elif type == SchemaObjectType.VIEW:
|
|
505
|
+
return proxy.catalog_schema_contents_views(
|
|
506
|
+
attach_opaque_data=attach_opaque_data,
|
|
507
|
+
name=name,
|
|
508
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
509
|
+
).to_infos()
|
|
510
|
+
elif type in (SchemaObjectType.SCALAR_MACRO, SchemaObjectType.TABLE_MACRO):
|
|
511
|
+
return proxy.catalog_schema_contents_macros(
|
|
512
|
+
attach_opaque_data=attach_opaque_data,
|
|
513
|
+
name=name,
|
|
514
|
+
type=type,
|
|
515
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
516
|
+
).to_infos()
|
|
517
|
+
else:
|
|
518
|
+
return proxy.catalog_schema_contents_functions(
|
|
519
|
+
attach_opaque_data=attach_opaque_data,
|
|
520
|
+
name=name,
|
|
521
|
+
type=type,
|
|
522
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
523
|
+
).to_infos()
|
|
524
|
+
|
|
525
|
+
# ========== Table Methods ==========
|
|
526
|
+
|
|
527
|
+
def table_get(
|
|
528
|
+
self,
|
|
529
|
+
*,
|
|
530
|
+
attach_opaque_data: AttachOpaqueData,
|
|
531
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
532
|
+
schema_name: str,
|
|
533
|
+
name: str,
|
|
534
|
+
) -> TableInfo | None:
|
|
535
|
+
"""Get information about a table.
|
|
536
|
+
|
|
537
|
+
Args:
|
|
538
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
539
|
+
transaction_opaque_data: Optional transaction ID for transactional reads.
|
|
540
|
+
schema_name: The schema containing the table.
|
|
541
|
+
name: The table name.
|
|
542
|
+
|
|
543
|
+
Returns:
|
|
544
|
+
TableInfo for the table, or None if not found.
|
|
545
|
+
|
|
546
|
+
"""
|
|
547
|
+
with self._catalog_connect() as proxy:
|
|
548
|
+
return proxy.catalog_table_get( # type: ignore[no-any-return]
|
|
549
|
+
attach_opaque_data=attach_opaque_data,
|
|
550
|
+
schema_name=schema_name,
|
|
551
|
+
name=name,
|
|
552
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
553
|
+
).to_optional()
|
|
554
|
+
|
|
555
|
+
def table_create(
|
|
556
|
+
self,
|
|
557
|
+
*,
|
|
558
|
+
attach_opaque_data: AttachOpaqueData,
|
|
559
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
560
|
+
schema_name: str,
|
|
561
|
+
name: str,
|
|
562
|
+
columns: SerializedSchema,
|
|
563
|
+
on_conflict: OnConflict = OnConflict.ERROR,
|
|
564
|
+
not_null_constraints: list[int] | None = None,
|
|
565
|
+
unique_constraints: list[list[int]] | None = None,
|
|
566
|
+
check_constraints: list[str] | None = None,
|
|
567
|
+
) -> None:
|
|
568
|
+
"""Create a new table.
|
|
569
|
+
|
|
570
|
+
Args:
|
|
571
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
572
|
+
transaction_opaque_data: Optional transaction ID.
|
|
573
|
+
schema_name: The schema to create the table in.
|
|
574
|
+
name: The name for the new table.
|
|
575
|
+
columns: Serialized PyArrow schema for the table columns.
|
|
576
|
+
on_conflict: Behavior if table already exists.
|
|
577
|
+
not_null_constraints: Column indices that must not be null.
|
|
578
|
+
unique_constraints: Lists of column indices for unique constraints.
|
|
579
|
+
check_constraints: SQL expressions for check constraints.
|
|
580
|
+
|
|
581
|
+
"""
|
|
582
|
+
with self._catalog_connect() as proxy:
|
|
583
|
+
proxy.catalog_table_create(
|
|
584
|
+
request=TableCreateRequest(
|
|
585
|
+
attach_opaque_data=attach_opaque_data,
|
|
586
|
+
schema_name=schema_name,
|
|
587
|
+
name=name,
|
|
588
|
+
columns=columns,
|
|
589
|
+
on_conflict=on_conflict,
|
|
590
|
+
not_null_constraints=not_null_constraints or [],
|
|
591
|
+
unique_constraints=unique_constraints or [],
|
|
592
|
+
check_constraints=check_constraints or [],
|
|
593
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
594
|
+
)
|
|
595
|
+
)
|
|
596
|
+
|
|
597
|
+
def table_drop(
|
|
598
|
+
self,
|
|
599
|
+
*,
|
|
600
|
+
attach_opaque_data: AttachOpaqueData,
|
|
601
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
602
|
+
schema_name: str,
|
|
603
|
+
name: str,
|
|
604
|
+
ignore_not_found: bool = False,
|
|
605
|
+
cascade: bool = False,
|
|
606
|
+
) -> None:
|
|
607
|
+
"""Drop a table.
|
|
608
|
+
|
|
609
|
+
Args:
|
|
610
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
611
|
+
transaction_opaque_data: Optional transaction ID.
|
|
612
|
+
schema_name: The schema containing the table.
|
|
613
|
+
name: The name of the table to drop.
|
|
614
|
+
ignore_not_found: If True, don't error if table doesn't exist.
|
|
615
|
+
cascade: If True, also drop dependent objects.
|
|
616
|
+
|
|
617
|
+
"""
|
|
618
|
+
with self._catalog_connect() as proxy:
|
|
619
|
+
proxy.catalog_table_drop(
|
|
620
|
+
attach_opaque_data=attach_opaque_data,
|
|
621
|
+
schema_name=schema_name,
|
|
622
|
+
name=name,
|
|
623
|
+
ignore_not_found=ignore_not_found,
|
|
624
|
+
cascade=cascade,
|
|
625
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
def table_scan_function_get(
|
|
629
|
+
self,
|
|
630
|
+
*,
|
|
631
|
+
attach_opaque_data: AttachOpaqueData,
|
|
632
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
633
|
+
schema_name: str,
|
|
634
|
+
name: str,
|
|
635
|
+
at_unit: str | None = None,
|
|
636
|
+
at_value: str | None = None,
|
|
637
|
+
) -> ScanFunctionResult:
|
|
638
|
+
"""Get the scan function for a table.
|
|
639
|
+
|
|
640
|
+
Returns a ScanFunctionResult that tells the VGI DuckDB extension which
|
|
641
|
+
DuckDB function to call to obtain the table data.
|
|
642
|
+
|
|
643
|
+
Args:
|
|
644
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
645
|
+
transaction_opaque_data: Optional transaction ID for transactional reads.
|
|
646
|
+
schema_name: The schema containing the table.
|
|
647
|
+
name: The table name.
|
|
648
|
+
at_unit: Optional time travel unit (e.g., 'timestamp', 'version').
|
|
649
|
+
at_value: Optional time travel value.
|
|
650
|
+
|
|
651
|
+
Returns:
|
|
652
|
+
ScanFunctionResult with function_name, arguments, and extensions.
|
|
653
|
+
|
|
654
|
+
Raises:
|
|
655
|
+
CatalogClientError: If table_scan_function_get returned no result.
|
|
656
|
+
|
|
657
|
+
"""
|
|
658
|
+
with self._catalog_connect() as proxy:
|
|
659
|
+
result_bytes = proxy.catalog_table_scan_function_get(
|
|
660
|
+
attach_opaque_data=attach_opaque_data,
|
|
661
|
+
schema_name=schema_name,
|
|
662
|
+
name=name,
|
|
663
|
+
at_unit=at_unit,
|
|
664
|
+
at_value=at_value,
|
|
665
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
666
|
+
)
|
|
667
|
+
batch, _ = deserialize_record_batch(result_bytes)
|
|
668
|
+
return ScanFunctionResult.deserialize(batch)
|
|
669
|
+
|
|
670
|
+
def table_comment_set(
|
|
671
|
+
self,
|
|
672
|
+
*,
|
|
673
|
+
attach_opaque_data: AttachOpaqueData,
|
|
674
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
675
|
+
schema_name: str,
|
|
676
|
+
name: str,
|
|
677
|
+
comment: str | None,
|
|
678
|
+
ignore_not_found: bool = False,
|
|
679
|
+
) -> None:
|
|
680
|
+
"""Set or clear the comment on a table.
|
|
681
|
+
|
|
682
|
+
Args:
|
|
683
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
684
|
+
transaction_opaque_data: Optional transaction ID.
|
|
685
|
+
schema_name: The schema containing the table.
|
|
686
|
+
name: The table name.
|
|
687
|
+
comment: The new comment, or None to clear.
|
|
688
|
+
ignore_not_found: If True, don't error if table doesn't exist.
|
|
689
|
+
|
|
690
|
+
"""
|
|
691
|
+
with self._catalog_connect() as proxy:
|
|
692
|
+
proxy.catalog_table_comment_set(
|
|
693
|
+
attach_opaque_data=attach_opaque_data,
|
|
694
|
+
schema_name=schema_name,
|
|
695
|
+
name=name,
|
|
696
|
+
comment=comment,
|
|
697
|
+
ignore_not_found=ignore_not_found,
|
|
698
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
699
|
+
)
|
|
700
|
+
|
|
701
|
+
def table_rename(
|
|
702
|
+
self,
|
|
703
|
+
*,
|
|
704
|
+
attach_opaque_data: AttachOpaqueData,
|
|
705
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
706
|
+
schema_name: str,
|
|
707
|
+
name: str,
|
|
708
|
+
new_name: str,
|
|
709
|
+
ignore_not_found: bool = False,
|
|
710
|
+
) -> None:
|
|
711
|
+
"""Rename a table.
|
|
712
|
+
|
|
713
|
+
Args:
|
|
714
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
715
|
+
transaction_opaque_data: Optional transaction ID.
|
|
716
|
+
schema_name: The schema containing the table.
|
|
717
|
+
name: The current name of the table.
|
|
718
|
+
new_name: The new name for the table.
|
|
719
|
+
ignore_not_found: If True, don't error if table doesn't exist.
|
|
720
|
+
|
|
721
|
+
"""
|
|
722
|
+
with self._catalog_connect() as proxy:
|
|
723
|
+
proxy.catalog_table_rename(
|
|
724
|
+
attach_opaque_data=attach_opaque_data,
|
|
725
|
+
schema_name=schema_name,
|
|
726
|
+
name=name,
|
|
727
|
+
new_name=new_name,
|
|
728
|
+
ignore_not_found=ignore_not_found,
|
|
729
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
730
|
+
)
|
|
731
|
+
|
|
732
|
+
def table_column_add(
|
|
733
|
+
self,
|
|
734
|
+
*,
|
|
735
|
+
attach_opaque_data: AttachOpaqueData,
|
|
736
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
737
|
+
schema_name: str,
|
|
738
|
+
name: str,
|
|
739
|
+
column_definition: SerializedSchema,
|
|
740
|
+
ignore_not_found: bool = False,
|
|
741
|
+
if_column_not_exists: bool = False,
|
|
742
|
+
) -> None:
|
|
743
|
+
"""Add a new column to a table.
|
|
744
|
+
|
|
745
|
+
Args:
|
|
746
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
747
|
+
transaction_opaque_data: Optional transaction ID.
|
|
748
|
+
schema_name: The schema containing the table.
|
|
749
|
+
name: The table name.
|
|
750
|
+
column_definition: Serialized schema with single field for the new column.
|
|
751
|
+
ignore_not_found: If True, don't error if table doesn't exist.
|
|
752
|
+
if_column_not_exists: If True, don't error if column already exists.
|
|
753
|
+
|
|
754
|
+
"""
|
|
755
|
+
with self._catalog_connect() as proxy:
|
|
756
|
+
proxy.catalog_table_column_add(
|
|
757
|
+
attach_opaque_data=attach_opaque_data,
|
|
758
|
+
schema_name=schema_name,
|
|
759
|
+
name=name,
|
|
760
|
+
column_definition=column_definition,
|
|
761
|
+
ignore_not_found=ignore_not_found,
|
|
762
|
+
if_column_not_exists=if_column_not_exists,
|
|
763
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
764
|
+
)
|
|
765
|
+
|
|
766
|
+
def table_column_drop(
|
|
767
|
+
self,
|
|
768
|
+
*,
|
|
769
|
+
attach_opaque_data: AttachOpaqueData,
|
|
770
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
771
|
+
schema_name: str,
|
|
772
|
+
name: str,
|
|
773
|
+
column_name: str,
|
|
774
|
+
ignore_not_found: bool = False,
|
|
775
|
+
if_column_exists: bool = False,
|
|
776
|
+
cascade: bool = False,
|
|
777
|
+
) -> None:
|
|
778
|
+
"""Drop a column from a table.
|
|
779
|
+
|
|
780
|
+
Args:
|
|
781
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
782
|
+
transaction_opaque_data: Optional transaction ID.
|
|
783
|
+
schema_name: The schema containing the table.
|
|
784
|
+
name: The table name.
|
|
785
|
+
column_name: The name of the column to drop.
|
|
786
|
+
ignore_not_found: If True, don't error if table doesn't exist.
|
|
787
|
+
if_column_exists: If True, don't error if column doesn't exist.
|
|
788
|
+
cascade: If True, drop dependent constraints.
|
|
789
|
+
|
|
790
|
+
"""
|
|
791
|
+
with self._catalog_connect() as proxy:
|
|
792
|
+
proxy.catalog_table_column_drop(
|
|
793
|
+
attach_opaque_data=attach_opaque_data,
|
|
794
|
+
schema_name=schema_name,
|
|
795
|
+
name=name,
|
|
796
|
+
column_name=column_name,
|
|
797
|
+
ignore_not_found=ignore_not_found,
|
|
798
|
+
if_column_exists=if_column_exists,
|
|
799
|
+
cascade=cascade,
|
|
800
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
801
|
+
)
|
|
802
|
+
|
|
803
|
+
def table_column_rename(
|
|
804
|
+
self,
|
|
805
|
+
*,
|
|
806
|
+
attach_opaque_data: AttachOpaqueData,
|
|
807
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
808
|
+
schema_name: str,
|
|
809
|
+
name: str,
|
|
810
|
+
column_name: str,
|
|
811
|
+
new_column_name: str,
|
|
812
|
+
ignore_not_found: bool = False,
|
|
813
|
+
) -> None:
|
|
814
|
+
"""Rename a column.
|
|
815
|
+
|
|
816
|
+
Args:
|
|
817
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
818
|
+
transaction_opaque_data: Optional transaction ID.
|
|
819
|
+
schema_name: The schema containing the table.
|
|
820
|
+
name: The table name.
|
|
821
|
+
column_name: The current name of the column.
|
|
822
|
+
new_column_name: The new name for the column.
|
|
823
|
+
ignore_not_found: If True, don't error if table doesn't exist.
|
|
824
|
+
|
|
825
|
+
"""
|
|
826
|
+
with self._catalog_connect() as proxy:
|
|
827
|
+
proxy.catalog_table_column_rename(
|
|
828
|
+
attach_opaque_data=attach_opaque_data,
|
|
829
|
+
schema_name=schema_name,
|
|
830
|
+
name=name,
|
|
831
|
+
column_name=column_name,
|
|
832
|
+
new_column_name=new_column_name,
|
|
833
|
+
ignore_not_found=ignore_not_found,
|
|
834
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
835
|
+
)
|
|
836
|
+
|
|
837
|
+
def table_column_default_set(
|
|
838
|
+
self,
|
|
839
|
+
*,
|
|
840
|
+
attach_opaque_data: AttachOpaqueData,
|
|
841
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
842
|
+
schema_name: str,
|
|
843
|
+
name: str,
|
|
844
|
+
column_name: str,
|
|
845
|
+
expression: SqlExpression,
|
|
846
|
+
ignore_not_found: bool = False,
|
|
847
|
+
) -> None:
|
|
848
|
+
"""Set the default value expression for a column.
|
|
849
|
+
|
|
850
|
+
Args:
|
|
851
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
852
|
+
transaction_opaque_data: Optional transaction ID.
|
|
853
|
+
schema_name: The schema containing the table.
|
|
854
|
+
name: The table name.
|
|
855
|
+
column_name: The column to set the default for.
|
|
856
|
+
expression: The SQL expression for the default value.
|
|
857
|
+
ignore_not_found: If True, don't error if table doesn't exist.
|
|
858
|
+
|
|
859
|
+
"""
|
|
860
|
+
with self._catalog_connect() as proxy:
|
|
861
|
+
proxy.catalog_table_column_default_set(
|
|
862
|
+
attach_opaque_data=attach_opaque_data,
|
|
863
|
+
schema_name=schema_name,
|
|
864
|
+
name=name,
|
|
865
|
+
column_name=column_name,
|
|
866
|
+
expression=expression,
|
|
867
|
+
ignore_not_found=ignore_not_found,
|
|
868
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
869
|
+
)
|
|
870
|
+
|
|
871
|
+
def table_column_default_drop(
|
|
872
|
+
self,
|
|
873
|
+
*,
|
|
874
|
+
attach_opaque_data: AttachOpaqueData,
|
|
875
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
876
|
+
schema_name: str,
|
|
877
|
+
name: str,
|
|
878
|
+
column_name: str,
|
|
879
|
+
ignore_not_found: bool = False,
|
|
880
|
+
) -> None:
|
|
881
|
+
"""Remove the default value from a column.
|
|
882
|
+
|
|
883
|
+
Args:
|
|
884
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
885
|
+
transaction_opaque_data: Optional transaction ID.
|
|
886
|
+
schema_name: The schema containing the table.
|
|
887
|
+
name: The table name.
|
|
888
|
+
column_name: The column to remove the default from.
|
|
889
|
+
ignore_not_found: If True, don't error if table doesn't exist.
|
|
890
|
+
|
|
891
|
+
"""
|
|
892
|
+
with self._catalog_connect() as proxy:
|
|
893
|
+
proxy.catalog_table_column_default_drop(
|
|
894
|
+
attach_opaque_data=attach_opaque_data,
|
|
895
|
+
schema_name=schema_name,
|
|
896
|
+
name=name,
|
|
897
|
+
column_name=column_name,
|
|
898
|
+
ignore_not_found=ignore_not_found,
|
|
899
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
900
|
+
)
|
|
901
|
+
|
|
902
|
+
def table_column_type_change(
|
|
903
|
+
self,
|
|
904
|
+
*,
|
|
905
|
+
attach_opaque_data: AttachOpaqueData,
|
|
906
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
907
|
+
schema_name: str,
|
|
908
|
+
name: str,
|
|
909
|
+
column_definition: SerializedSchema,
|
|
910
|
+
expression: SqlExpression | None = None,
|
|
911
|
+
ignore_not_found: bool = False,
|
|
912
|
+
) -> None:
|
|
913
|
+
"""Change the type of a column.
|
|
914
|
+
|
|
915
|
+
Args:
|
|
916
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
917
|
+
transaction_opaque_data: Optional transaction ID.
|
|
918
|
+
schema_name: The schema containing the table.
|
|
919
|
+
name: The table name.
|
|
920
|
+
column_definition: Serialized schema with single field defining the
|
|
921
|
+
new type. Column name is taken from the schema field name.
|
|
922
|
+
expression: Optional SQL expression to convert existing values.
|
|
923
|
+
ignore_not_found: If True, don't error if table doesn't exist.
|
|
924
|
+
|
|
925
|
+
"""
|
|
926
|
+
with self._catalog_connect() as proxy:
|
|
927
|
+
proxy.catalog_table_column_type_change(
|
|
928
|
+
attach_opaque_data=attach_opaque_data,
|
|
929
|
+
schema_name=schema_name,
|
|
930
|
+
name=name,
|
|
931
|
+
column_definition=column_definition,
|
|
932
|
+
expression=expression,
|
|
933
|
+
ignore_not_found=ignore_not_found,
|
|
934
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
935
|
+
)
|
|
936
|
+
|
|
937
|
+
def table_not_null_drop(
|
|
938
|
+
self,
|
|
939
|
+
*,
|
|
940
|
+
attach_opaque_data: AttachOpaqueData,
|
|
941
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
942
|
+
schema_name: str,
|
|
943
|
+
name: str,
|
|
944
|
+
column_name: str,
|
|
945
|
+
ignore_not_found: bool = False,
|
|
946
|
+
) -> None:
|
|
947
|
+
"""Remove NOT NULL constraint from a column.
|
|
948
|
+
|
|
949
|
+
Args:
|
|
950
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
951
|
+
transaction_opaque_data: Optional transaction ID.
|
|
952
|
+
schema_name: The schema containing the table.
|
|
953
|
+
name: The table name.
|
|
954
|
+
column_name: The column to remove NOT NULL from.
|
|
955
|
+
ignore_not_found: If True, don't error if table doesn't exist.
|
|
956
|
+
|
|
957
|
+
"""
|
|
958
|
+
with self._catalog_connect() as proxy:
|
|
959
|
+
proxy.catalog_table_not_null_drop(
|
|
960
|
+
attach_opaque_data=attach_opaque_data,
|
|
961
|
+
schema_name=schema_name,
|
|
962
|
+
name=name,
|
|
963
|
+
column_name=column_name,
|
|
964
|
+
ignore_not_found=ignore_not_found,
|
|
965
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
966
|
+
)
|
|
967
|
+
|
|
968
|
+
def table_not_null_set(
|
|
969
|
+
self,
|
|
970
|
+
*,
|
|
971
|
+
attach_opaque_data: AttachOpaqueData,
|
|
972
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
973
|
+
schema_name: str,
|
|
974
|
+
name: str,
|
|
975
|
+
column_name: str,
|
|
976
|
+
ignore_not_found: bool = False,
|
|
977
|
+
) -> None:
|
|
978
|
+
"""Add NOT NULL constraint to a column.
|
|
979
|
+
|
|
980
|
+
Args:
|
|
981
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
982
|
+
transaction_opaque_data: Optional transaction ID.
|
|
983
|
+
schema_name: The schema containing the table.
|
|
984
|
+
name: The table name.
|
|
985
|
+
column_name: The column to add NOT NULL to.
|
|
986
|
+
ignore_not_found: If True, don't error if table doesn't exist.
|
|
987
|
+
|
|
988
|
+
"""
|
|
989
|
+
with self._catalog_connect() as proxy:
|
|
990
|
+
proxy.catalog_table_not_null_set(
|
|
991
|
+
attach_opaque_data=attach_opaque_data,
|
|
992
|
+
schema_name=schema_name,
|
|
993
|
+
name=name,
|
|
994
|
+
column_name=column_name,
|
|
995
|
+
ignore_not_found=ignore_not_found,
|
|
996
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
997
|
+
)
|
|
998
|
+
|
|
999
|
+
# ========== View Methods ==========
|
|
1000
|
+
|
|
1001
|
+
def view_get(
|
|
1002
|
+
self,
|
|
1003
|
+
*,
|
|
1004
|
+
attach_opaque_data: AttachOpaqueData,
|
|
1005
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
1006
|
+
schema_name: str,
|
|
1007
|
+
name: str,
|
|
1008
|
+
) -> ViewInfo | None:
|
|
1009
|
+
"""Get information about a view.
|
|
1010
|
+
|
|
1011
|
+
Args:
|
|
1012
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
1013
|
+
transaction_opaque_data: Optional transaction ID for transactional reads.
|
|
1014
|
+
schema_name: The schema containing the view.
|
|
1015
|
+
name: The view name.
|
|
1016
|
+
|
|
1017
|
+
Returns:
|
|
1018
|
+
ViewInfo for the view, or None if not found.
|
|
1019
|
+
|
|
1020
|
+
"""
|
|
1021
|
+
with self._catalog_connect() as proxy:
|
|
1022
|
+
return proxy.catalog_view_get( # type: ignore[no-any-return]
|
|
1023
|
+
attach_opaque_data=attach_opaque_data,
|
|
1024
|
+
schema_name=schema_name,
|
|
1025
|
+
name=name,
|
|
1026
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
1027
|
+
).to_optional()
|
|
1028
|
+
|
|
1029
|
+
def view_create(
|
|
1030
|
+
self,
|
|
1031
|
+
*,
|
|
1032
|
+
attach_opaque_data: AttachOpaqueData,
|
|
1033
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
1034
|
+
schema_name: str,
|
|
1035
|
+
name: str,
|
|
1036
|
+
definition: str,
|
|
1037
|
+
on_conflict: OnConflict = OnConflict.ERROR,
|
|
1038
|
+
) -> None:
|
|
1039
|
+
"""Create a new view.
|
|
1040
|
+
|
|
1041
|
+
Args:
|
|
1042
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
1043
|
+
transaction_opaque_data: Optional transaction ID.
|
|
1044
|
+
schema_name: The schema to create the view in.
|
|
1045
|
+
name: The name for the new view.
|
|
1046
|
+
definition: The SQL SELECT statement defining the view.
|
|
1047
|
+
on_conflict: Behavior if view already exists.
|
|
1048
|
+
|
|
1049
|
+
"""
|
|
1050
|
+
with self._catalog_connect() as proxy:
|
|
1051
|
+
proxy.catalog_view_create(
|
|
1052
|
+
attach_opaque_data=attach_opaque_data,
|
|
1053
|
+
schema_name=schema_name,
|
|
1054
|
+
name=name,
|
|
1055
|
+
definition=definition,
|
|
1056
|
+
on_conflict=on_conflict,
|
|
1057
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
1058
|
+
)
|
|
1059
|
+
|
|
1060
|
+
def view_drop(
|
|
1061
|
+
self,
|
|
1062
|
+
*,
|
|
1063
|
+
attach_opaque_data: AttachOpaqueData,
|
|
1064
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
1065
|
+
schema_name: str,
|
|
1066
|
+
name: str,
|
|
1067
|
+
ignore_not_found: bool = False,
|
|
1068
|
+
cascade: bool = False,
|
|
1069
|
+
) -> None:
|
|
1070
|
+
"""Drop a view.
|
|
1071
|
+
|
|
1072
|
+
Args:
|
|
1073
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
1074
|
+
transaction_opaque_data: Optional transaction ID.
|
|
1075
|
+
schema_name: The schema containing the view.
|
|
1076
|
+
name: The name of the view to drop.
|
|
1077
|
+
ignore_not_found: If True, don't error if view doesn't exist.
|
|
1078
|
+
cascade: If True, also drop dependent objects.
|
|
1079
|
+
|
|
1080
|
+
"""
|
|
1081
|
+
with self._catalog_connect() as proxy:
|
|
1082
|
+
proxy.catalog_view_drop(
|
|
1083
|
+
attach_opaque_data=attach_opaque_data,
|
|
1084
|
+
schema_name=schema_name,
|
|
1085
|
+
name=name,
|
|
1086
|
+
ignore_not_found=ignore_not_found,
|
|
1087
|
+
cascade=cascade,
|
|
1088
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
1089
|
+
)
|
|
1090
|
+
|
|
1091
|
+
def view_rename(
|
|
1092
|
+
self,
|
|
1093
|
+
*,
|
|
1094
|
+
attach_opaque_data: AttachOpaqueData,
|
|
1095
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
1096
|
+
schema_name: str,
|
|
1097
|
+
name: str,
|
|
1098
|
+
new_name: str,
|
|
1099
|
+
ignore_not_found: bool = False,
|
|
1100
|
+
) -> None:
|
|
1101
|
+
"""Rename a view.
|
|
1102
|
+
|
|
1103
|
+
Args:
|
|
1104
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
1105
|
+
transaction_opaque_data: Optional transaction ID.
|
|
1106
|
+
schema_name: The schema containing the view.
|
|
1107
|
+
name: The current name of the view.
|
|
1108
|
+
new_name: The new name for the view.
|
|
1109
|
+
ignore_not_found: If True, don't error if view doesn't exist.
|
|
1110
|
+
|
|
1111
|
+
"""
|
|
1112
|
+
with self._catalog_connect() as proxy:
|
|
1113
|
+
proxy.catalog_view_rename(
|
|
1114
|
+
attach_opaque_data=attach_opaque_data,
|
|
1115
|
+
schema_name=schema_name,
|
|
1116
|
+
name=name,
|
|
1117
|
+
new_name=new_name,
|
|
1118
|
+
ignore_not_found=ignore_not_found,
|
|
1119
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
1120
|
+
)
|
|
1121
|
+
|
|
1122
|
+
def view_comment_set(
|
|
1123
|
+
self,
|
|
1124
|
+
*,
|
|
1125
|
+
attach_opaque_data: AttachOpaqueData,
|
|
1126
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
1127
|
+
schema_name: str,
|
|
1128
|
+
name: str,
|
|
1129
|
+
comment: str | None,
|
|
1130
|
+
ignore_not_found: bool = False,
|
|
1131
|
+
) -> None:
|
|
1132
|
+
"""Set or clear the comment on a view.
|
|
1133
|
+
|
|
1134
|
+
Args:
|
|
1135
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
1136
|
+
transaction_opaque_data: Optional transaction ID.
|
|
1137
|
+
schema_name: The schema containing the view.
|
|
1138
|
+
name: The view name.
|
|
1139
|
+
comment: The new comment, or None to clear.
|
|
1140
|
+
ignore_not_found: If True, don't error if view doesn't exist.
|
|
1141
|
+
|
|
1142
|
+
"""
|
|
1143
|
+
with self._catalog_connect() as proxy:
|
|
1144
|
+
proxy.catalog_view_comment_set(
|
|
1145
|
+
attach_opaque_data=attach_opaque_data,
|
|
1146
|
+
schema_name=schema_name,
|
|
1147
|
+
name=name,
|
|
1148
|
+
comment=comment,
|
|
1149
|
+
ignore_not_found=ignore_not_found,
|
|
1150
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
1151
|
+
)
|
|
1152
|
+
|
|
1153
|
+
# ========== Macro Methods ==========
|
|
1154
|
+
|
|
1155
|
+
def macro_get(
|
|
1156
|
+
self,
|
|
1157
|
+
*,
|
|
1158
|
+
attach_opaque_data: AttachOpaqueData,
|
|
1159
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
1160
|
+
schema_name: str,
|
|
1161
|
+
name: str,
|
|
1162
|
+
) -> MacroInfo | None:
|
|
1163
|
+
"""Get information about a macro.
|
|
1164
|
+
|
|
1165
|
+
Args:
|
|
1166
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
1167
|
+
transaction_opaque_data: Optional transaction ID for transactional reads.
|
|
1168
|
+
schema_name: The schema containing the macro.
|
|
1169
|
+
name: The macro name.
|
|
1170
|
+
|
|
1171
|
+
Returns:
|
|
1172
|
+
MacroInfo for the macro, or None if not found.
|
|
1173
|
+
|
|
1174
|
+
"""
|
|
1175
|
+
with self._catalog_connect() as proxy:
|
|
1176
|
+
return proxy.catalog_macro_get( # type: ignore[no-any-return]
|
|
1177
|
+
attach_opaque_data=attach_opaque_data,
|
|
1178
|
+
schema_name=schema_name,
|
|
1179
|
+
name=name,
|
|
1180
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
1181
|
+
).to_optional()
|
|
1182
|
+
|
|
1183
|
+
def macro_create(
|
|
1184
|
+
self,
|
|
1185
|
+
*,
|
|
1186
|
+
attach_opaque_data: AttachOpaqueData,
|
|
1187
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
1188
|
+
schema_name: str,
|
|
1189
|
+
name: str,
|
|
1190
|
+
macro_type: MacroType,
|
|
1191
|
+
parameters: list[str],
|
|
1192
|
+
definition: str,
|
|
1193
|
+
on_conflict: OnConflict = OnConflict.ERROR,
|
|
1194
|
+
parameter_default_values: pa.RecordBatch | None = None,
|
|
1195
|
+
) -> None:
|
|
1196
|
+
"""Create a new macro.
|
|
1197
|
+
|
|
1198
|
+
Args:
|
|
1199
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
1200
|
+
transaction_opaque_data: Optional transaction ID.
|
|
1201
|
+
schema_name: The schema to create the macro in.
|
|
1202
|
+
name: The name for the new macro.
|
|
1203
|
+
macro_type: Whether this is a scalar or table macro.
|
|
1204
|
+
parameters: Ordered list of parameter names.
|
|
1205
|
+
definition: SQL expression (scalar) or query (table).
|
|
1206
|
+
on_conflict: Behavior if macro already exists.
|
|
1207
|
+
parameter_default_values: One-row RecordBatch with typed defaults.
|
|
1208
|
+
|
|
1209
|
+
"""
|
|
1210
|
+
with self._catalog_connect() as proxy:
|
|
1211
|
+
proxy.catalog_macro_create(
|
|
1212
|
+
request=MacroCreateRequest(
|
|
1213
|
+
attach_opaque_data=attach_opaque_data,
|
|
1214
|
+
schema_name=schema_name,
|
|
1215
|
+
name=name,
|
|
1216
|
+
macro_type=macro_type,
|
|
1217
|
+
parameters=parameters,
|
|
1218
|
+
definition=definition,
|
|
1219
|
+
on_conflict=on_conflict,
|
|
1220
|
+
parameter_default_values=parameter_default_values,
|
|
1221
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
1222
|
+
)
|
|
1223
|
+
)
|
|
1224
|
+
|
|
1225
|
+
def macro_drop(
|
|
1226
|
+
self,
|
|
1227
|
+
*,
|
|
1228
|
+
attach_opaque_data: AttachOpaqueData,
|
|
1229
|
+
transaction_opaque_data: TransactionOpaqueData | None = None,
|
|
1230
|
+
schema_name: str,
|
|
1231
|
+
name: str,
|
|
1232
|
+
ignore_not_found: bool = False,
|
|
1233
|
+
) -> None:
|
|
1234
|
+
"""Drop a macro.
|
|
1235
|
+
|
|
1236
|
+
Args:
|
|
1237
|
+
attach_opaque_data: The attachment ID from catalog_attach.
|
|
1238
|
+
transaction_opaque_data: Optional transaction ID.
|
|
1239
|
+
schema_name: The schema containing the macro.
|
|
1240
|
+
name: The name of the macro to drop.
|
|
1241
|
+
ignore_not_found: If True, don't error if macro doesn't exist.
|
|
1242
|
+
|
|
1243
|
+
"""
|
|
1244
|
+
with self._catalog_connect() as proxy:
|
|
1245
|
+
proxy.catalog_macro_drop(
|
|
1246
|
+
attach_opaque_data=attach_opaque_data,
|
|
1247
|
+
schema_name=schema_name,
|
|
1248
|
+
name=name,
|
|
1249
|
+
ignore_not_found=ignore_not_found,
|
|
1250
|
+
transaction_opaque_data=transaction_opaque_data,
|
|
1251
|
+
)
|