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,182 @@
|
|
|
1
|
+
# Copyright 2025, 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
"""Catalog CLI commands for VGI.
|
|
4
|
+
|
|
5
|
+
This module provides CLI commands for catalog operations, organized hierarchically:
|
|
6
|
+
|
|
7
|
+
catalog
|
|
8
|
+
├── list # List available catalogs
|
|
9
|
+
├── attach <name> # Attach to a catalog
|
|
10
|
+
├── detach <attach_opaque_data> # Detach from a catalog
|
|
11
|
+
├── create <name> # Create a new catalog
|
|
12
|
+
├── drop <name> # Drop a catalog
|
|
13
|
+
├── version # Get catalog version (--attach-opaque-data or --catalog)
|
|
14
|
+
├── schema # Schema operations
|
|
15
|
+
│ ├── list/get/create/drop/contents
|
|
16
|
+
├── table # Table operations
|
|
17
|
+
│ ├── get/create/drop/rename/...
|
|
18
|
+
├── view # View operations
|
|
19
|
+
│ ├── get/create/drop/rename/...
|
|
20
|
+
└── transaction # Transaction operations
|
|
21
|
+
├── begin/commit/rollback
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import click
|
|
28
|
+
|
|
29
|
+
from vgi.catalog import OnConflict
|
|
30
|
+
from vgi.client.cli_schema import schema
|
|
31
|
+
from vgi.client.cli_table import table
|
|
32
|
+
from vgi.client.cli_transaction import transaction
|
|
33
|
+
from vgi.client.cli_utils import (
|
|
34
|
+
bytes_to_hex,
|
|
35
|
+
catalog_attach_result_to_dict,
|
|
36
|
+
get_attach_opaque_data_from_options,
|
|
37
|
+
hex_to_attach_opaque_data,
|
|
38
|
+
hex_to_transaction_opaque_data,
|
|
39
|
+
output_json,
|
|
40
|
+
parse_json_option,
|
|
41
|
+
)
|
|
42
|
+
from vgi.client.cli_view import view
|
|
43
|
+
from vgi.client.client import Client
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@click.group()
|
|
47
|
+
def catalog() -> None:
|
|
48
|
+
"""Manage catalogs, schemas, tables, views, and transactions."""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@catalog.command("list")
|
|
52
|
+
@click.option("--worker", "-w", required=True, help="VGI worker command")
|
|
53
|
+
def catalog_list(worker: str) -> None:
|
|
54
|
+
"""List available catalogs."""
|
|
55
|
+
client = Client(worker)
|
|
56
|
+
catalogs = client.catalogs()
|
|
57
|
+
output_json(
|
|
58
|
+
[
|
|
59
|
+
{
|
|
60
|
+
"name": c.name,
|
|
61
|
+
"implementation_version": c.implementation_version,
|
|
62
|
+
"data_version_spec": c.data_version_spec,
|
|
63
|
+
}
|
|
64
|
+
for c in catalogs
|
|
65
|
+
]
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@catalog.command("attach")
|
|
70
|
+
@click.argument("name")
|
|
71
|
+
@click.option("--worker", "-w", required=True, help="VGI worker command")
|
|
72
|
+
@click.option("--options", default="{}", help="Catalog options as JSON object")
|
|
73
|
+
def catalog_attach(name: str, worker: str, options: str) -> None:
|
|
74
|
+
"""Attach to a catalog and return attach_opaque_data.
|
|
75
|
+
|
|
76
|
+
NAME is the catalog name to attach to.
|
|
77
|
+
|
|
78
|
+
"""
|
|
79
|
+
opts = parse_json_option(options, "--options")
|
|
80
|
+
client = Client(worker)
|
|
81
|
+
result = client.catalog_attach(
|
|
82
|
+
name=name,
|
|
83
|
+
options=opts,
|
|
84
|
+
data_version_spec=None,
|
|
85
|
+
implementation_version=None,
|
|
86
|
+
)
|
|
87
|
+
output_json(catalog_attach_result_to_dict(result))
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@catalog.command("detach")
|
|
91
|
+
@click.argument("attach_opaque_data")
|
|
92
|
+
@click.option("--worker", "-w", required=True, help="VGI worker command")
|
|
93
|
+
def catalog_detach(attach_opaque_data: str, worker: str) -> None:
|
|
94
|
+
"""Detach from a catalog.
|
|
95
|
+
|
|
96
|
+
ATTACH_ID is the hex-encoded attach ID from catalog attach.
|
|
97
|
+
|
|
98
|
+
"""
|
|
99
|
+
client = Client(worker)
|
|
100
|
+
client.catalog_detach(attach_opaque_data=hex_to_attach_opaque_data(attach_opaque_data))
|
|
101
|
+
output_json({"status": "detached"})
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@catalog.command("create")
|
|
105
|
+
@click.argument("name")
|
|
106
|
+
@click.option("--worker", "-w", required=True, help="VGI worker command")
|
|
107
|
+
@click.option(
|
|
108
|
+
"--on-conflict",
|
|
109
|
+
type=click.Choice(["error", "ignore", "replace"]),
|
|
110
|
+
default="error",
|
|
111
|
+
help="Behavior if catalog already exists",
|
|
112
|
+
)
|
|
113
|
+
@click.option("--options", default="{}", help="Catalog options as JSON object")
|
|
114
|
+
def catalog_create(name: str, worker: str, on_conflict: str, options: str) -> None:
|
|
115
|
+
"""Create a new catalog.
|
|
116
|
+
|
|
117
|
+
NAME is the name for the new catalog.
|
|
118
|
+
|
|
119
|
+
"""
|
|
120
|
+
opts = parse_json_option(options, "--options")
|
|
121
|
+
client = Client(worker)
|
|
122
|
+
client.catalog_create(
|
|
123
|
+
name=name,
|
|
124
|
+
on_conflict=OnConflict(on_conflict),
|
|
125
|
+
options=opts,
|
|
126
|
+
)
|
|
127
|
+
output_json({"status": "created", "name": name})
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@catalog.command("drop")
|
|
131
|
+
@click.argument("name")
|
|
132
|
+
@click.option("--worker", "-w", required=True, help="VGI worker command")
|
|
133
|
+
def catalog_drop(name: str, worker: str) -> None:
|
|
134
|
+
"""Drop a catalog.
|
|
135
|
+
|
|
136
|
+
NAME is the name of the catalog to drop.
|
|
137
|
+
|
|
138
|
+
"""
|
|
139
|
+
client = Client(worker)
|
|
140
|
+
client.catalog_drop(name=name)
|
|
141
|
+
output_json({"status": "dropped", "name": name})
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@catalog.command("version")
|
|
145
|
+
@click.option("--attach-opaque-data", help="Hex-encoded attach ID")
|
|
146
|
+
@click.option("--catalog", "catalog_name", help="Catalog name for auto-attach")
|
|
147
|
+
@click.option("--attach-options", default="{}", help="Attach options as JSON")
|
|
148
|
+
@click.option("--worker", "-w", required=True, help="VGI worker command")
|
|
149
|
+
@click.option("--transaction-opaque-data", help="Transaction ID (hex) for transactional read")
|
|
150
|
+
def catalog_version(
|
|
151
|
+
attach_opaque_data: str | None,
|
|
152
|
+
catalog_name: str | None,
|
|
153
|
+
attach_options: str,
|
|
154
|
+
worker: str,
|
|
155
|
+
transaction_opaque_data: str | None,
|
|
156
|
+
) -> None:
|
|
157
|
+
"""Get the current catalog version."""
|
|
158
|
+
client = Client(worker)
|
|
159
|
+
opts = parse_json_option(attach_options, "--attach-options")
|
|
160
|
+
resolved_attach_opaque_data, is_stateful = get_attach_opaque_data_from_options(
|
|
161
|
+
client, attach_opaque_data, catalog_name, opts
|
|
162
|
+
)
|
|
163
|
+
if is_stateful and catalog_name:
|
|
164
|
+
click.echo(
|
|
165
|
+
"Warning: Using --catalog with a stateful catalog. "
|
|
166
|
+
"Consider using --attach-opaque-data for session persistence.",
|
|
167
|
+
err=True,
|
|
168
|
+
)
|
|
169
|
+
version = client.catalog_version(
|
|
170
|
+
attach_opaque_data=resolved_attach_opaque_data,
|
|
171
|
+
transaction_opaque_data=(
|
|
172
|
+
hex_to_transaction_opaque_data(transaction_opaque_data) if transaction_opaque_data else None
|
|
173
|
+
),
|
|
174
|
+
)
|
|
175
|
+
output_json({"version": version, "attach_opaque_data": bytes_to_hex(resolved_attach_opaque_data)})
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# Add nested subcommand groups
|
|
179
|
+
catalog.add_command(schema)
|
|
180
|
+
catalog.add_command(table)
|
|
181
|
+
catalog.add_command(view)
|
|
182
|
+
catalog.add_command(transaction)
|
vgi/client/cli_schema.py
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# Copyright 2025, 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
"""Schema CLI commands for VGI.
|
|
4
|
+
|
|
5
|
+
This module provides CLI commands for schema operations:
|
|
6
|
+
- list: List schemas in a catalog
|
|
7
|
+
- get: Get schema info
|
|
8
|
+
- create: Create a new schema
|
|
9
|
+
- drop: Drop a schema
|
|
10
|
+
- contents: List contents of a schema (tables, views, functions)
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import click
|
|
17
|
+
|
|
18
|
+
from vgi.catalog import FunctionInfo, SchemaObjectType, TableInfo, ViewInfo
|
|
19
|
+
from vgi.client.cli_utils import (
|
|
20
|
+
function_info_to_dict,
|
|
21
|
+
get_attach_opaque_data_from_options,
|
|
22
|
+
hex_to_transaction_opaque_data,
|
|
23
|
+
output_json,
|
|
24
|
+
parse_json_option,
|
|
25
|
+
schema_info_to_dict,
|
|
26
|
+
table_info_to_dict,
|
|
27
|
+
view_info_to_dict,
|
|
28
|
+
)
|
|
29
|
+
from vgi.client.client import Client
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@click.group()
|
|
33
|
+
def schema() -> None:
|
|
34
|
+
"""Manage schemas in a catalog."""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@schema.command("list")
|
|
38
|
+
@click.option("--attach-opaque-data", help="Hex-encoded attach ID")
|
|
39
|
+
@click.option("--catalog", "catalog_name", help="Catalog name for auto-attach")
|
|
40
|
+
@click.option("--attach-options", default="{}", help="Attach options as JSON")
|
|
41
|
+
@click.option("--worker", "-w", required=True, help="VGI worker command")
|
|
42
|
+
@click.option("--transaction-opaque-data", help="Transaction ID (hex) for transactional read")
|
|
43
|
+
def schema_list(
|
|
44
|
+
attach_opaque_data: str | None,
|
|
45
|
+
catalog_name: str | None,
|
|
46
|
+
attach_options: str,
|
|
47
|
+
worker: str,
|
|
48
|
+
transaction_opaque_data: str | None,
|
|
49
|
+
) -> None:
|
|
50
|
+
"""List schemas in a catalog."""
|
|
51
|
+
client = Client(worker)
|
|
52
|
+
opts = parse_json_option(attach_options, "--attach-options")
|
|
53
|
+
resolved_attach_opaque_data, is_stateful = get_attach_opaque_data_from_options(
|
|
54
|
+
client, attach_opaque_data, catalog_name, opts
|
|
55
|
+
)
|
|
56
|
+
if is_stateful and catalog_name:
|
|
57
|
+
click.echo(
|
|
58
|
+
"Warning: Using --catalog with a stateful catalog. "
|
|
59
|
+
"Consider using --attach-opaque-data for session persistence.",
|
|
60
|
+
err=True,
|
|
61
|
+
)
|
|
62
|
+
for schema_info in client.schemas(
|
|
63
|
+
attach_opaque_data=resolved_attach_opaque_data,
|
|
64
|
+
transaction_opaque_data=(
|
|
65
|
+
hex_to_transaction_opaque_data(transaction_opaque_data) if transaction_opaque_data else None
|
|
66
|
+
),
|
|
67
|
+
):
|
|
68
|
+
output_json(schema_info_to_dict(schema_info))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@schema.command("get")
|
|
72
|
+
@click.argument("name")
|
|
73
|
+
@click.option("--attach-opaque-data", help="Hex-encoded attach ID")
|
|
74
|
+
@click.option("--catalog", "catalog_name", help="Catalog name for auto-attach")
|
|
75
|
+
@click.option("--attach-options", default="{}", help="Attach options as JSON")
|
|
76
|
+
@click.option("--worker", "-w", required=True, help="VGI worker command")
|
|
77
|
+
@click.option("--transaction-opaque-data", help="Transaction ID (hex) for transactional read")
|
|
78
|
+
def schema_get(
|
|
79
|
+
name: str,
|
|
80
|
+
attach_opaque_data: str | None,
|
|
81
|
+
catalog_name: str | None,
|
|
82
|
+
attach_options: str,
|
|
83
|
+
worker: str,
|
|
84
|
+
transaction_opaque_data: str | None,
|
|
85
|
+
) -> None:
|
|
86
|
+
"""Get information about a schema.
|
|
87
|
+
|
|
88
|
+
NAME is the schema name.
|
|
89
|
+
|
|
90
|
+
"""
|
|
91
|
+
client = Client(worker)
|
|
92
|
+
opts = parse_json_option(attach_options, "--attach-options")
|
|
93
|
+
resolved_attach_opaque_data, is_stateful = get_attach_opaque_data_from_options(
|
|
94
|
+
client, attach_opaque_data, catalog_name, opts
|
|
95
|
+
)
|
|
96
|
+
if is_stateful and catalog_name:
|
|
97
|
+
click.echo(
|
|
98
|
+
"Warning: Using --catalog with a stateful catalog. "
|
|
99
|
+
"Consider using --attach-opaque-data for session persistence.",
|
|
100
|
+
err=True,
|
|
101
|
+
)
|
|
102
|
+
schema_info = client.schema_get(
|
|
103
|
+
attach_opaque_data=resolved_attach_opaque_data,
|
|
104
|
+
transaction_opaque_data=(
|
|
105
|
+
hex_to_transaction_opaque_data(transaction_opaque_data) if transaction_opaque_data else None
|
|
106
|
+
),
|
|
107
|
+
name=name,
|
|
108
|
+
)
|
|
109
|
+
if schema_info:
|
|
110
|
+
output_json(schema_info_to_dict(schema_info))
|
|
111
|
+
else:
|
|
112
|
+
output_json({"error": "not_found", "name": name})
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@schema.command("create")
|
|
116
|
+
@click.argument("name")
|
|
117
|
+
@click.option("--attach-opaque-data", help="Hex-encoded attach ID")
|
|
118
|
+
@click.option("--catalog", "catalog_name", help="Catalog name for auto-attach")
|
|
119
|
+
@click.option("--attach-options", default="{}", help="Attach options as JSON")
|
|
120
|
+
@click.option("--worker", "-w", required=True, help="VGI worker command")
|
|
121
|
+
@click.option("--transaction-opaque-data", help="Transaction ID (hex)")
|
|
122
|
+
@click.option("--comment", help="Description of the schema")
|
|
123
|
+
@click.option("--tags", default="{}", help="Metadata tags as JSON object")
|
|
124
|
+
def schema_create(
|
|
125
|
+
name: str,
|
|
126
|
+
attach_opaque_data: str | None,
|
|
127
|
+
catalog_name: str | None,
|
|
128
|
+
attach_options: str,
|
|
129
|
+
worker: str,
|
|
130
|
+
transaction_opaque_data: str | None,
|
|
131
|
+
comment: str | None,
|
|
132
|
+
tags: str,
|
|
133
|
+
) -> None:
|
|
134
|
+
"""Create a new schema.
|
|
135
|
+
|
|
136
|
+
NAME is the name for the new schema.
|
|
137
|
+
|
|
138
|
+
"""
|
|
139
|
+
client = Client(worker)
|
|
140
|
+
opts = parse_json_option(attach_options, "--attach-options")
|
|
141
|
+
resolved_attach_opaque_data, is_stateful = get_attach_opaque_data_from_options(
|
|
142
|
+
client, attach_opaque_data, catalog_name, opts
|
|
143
|
+
)
|
|
144
|
+
if is_stateful and catalog_name:
|
|
145
|
+
click.echo(
|
|
146
|
+
"Warning: Using --catalog with a stateful catalog. "
|
|
147
|
+
"Consider using --attach-opaque-data for session persistence.",
|
|
148
|
+
err=True,
|
|
149
|
+
)
|
|
150
|
+
tags_dict = parse_json_option(tags, "--tags")
|
|
151
|
+
client.schema_create(
|
|
152
|
+
attach_opaque_data=resolved_attach_opaque_data,
|
|
153
|
+
transaction_opaque_data=(
|
|
154
|
+
hex_to_transaction_opaque_data(transaction_opaque_data) if transaction_opaque_data else None
|
|
155
|
+
),
|
|
156
|
+
name=name,
|
|
157
|
+
comment=comment,
|
|
158
|
+
tags=tags_dict,
|
|
159
|
+
)
|
|
160
|
+
output_json({"status": "created", "name": name})
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
@schema.command("drop")
|
|
164
|
+
@click.argument("name")
|
|
165
|
+
@click.option("--attach-opaque-data", help="Hex-encoded attach ID")
|
|
166
|
+
@click.option("--catalog", "catalog_name", help="Catalog name for auto-attach")
|
|
167
|
+
@click.option("--attach-options", default="{}", help="Attach options as JSON")
|
|
168
|
+
@click.option("--worker", "-w", required=True, help="VGI worker command")
|
|
169
|
+
@click.option("--transaction-opaque-data", help="Transaction ID (hex)")
|
|
170
|
+
@click.option("--ignore-not-found", is_flag=True, help="Don't error if not found")
|
|
171
|
+
@click.option("--cascade", is_flag=True, help="Drop contained tables and views")
|
|
172
|
+
def schema_drop(
|
|
173
|
+
name: str,
|
|
174
|
+
attach_opaque_data: str | None,
|
|
175
|
+
catalog_name: str | None,
|
|
176
|
+
attach_options: str,
|
|
177
|
+
worker: str,
|
|
178
|
+
transaction_opaque_data: str | None,
|
|
179
|
+
ignore_not_found: bool,
|
|
180
|
+
cascade: bool,
|
|
181
|
+
) -> None:
|
|
182
|
+
"""Drop a schema.
|
|
183
|
+
|
|
184
|
+
NAME is the name of the schema to drop.
|
|
185
|
+
|
|
186
|
+
"""
|
|
187
|
+
client = Client(worker)
|
|
188
|
+
opts = parse_json_option(attach_options, "--attach-options")
|
|
189
|
+
resolved_attach_opaque_data, is_stateful = get_attach_opaque_data_from_options(
|
|
190
|
+
client, attach_opaque_data, catalog_name, opts
|
|
191
|
+
)
|
|
192
|
+
if is_stateful and catalog_name:
|
|
193
|
+
click.echo(
|
|
194
|
+
"Warning: Using --catalog with a stateful catalog. "
|
|
195
|
+
"Consider using --attach-opaque-data for session persistence.",
|
|
196
|
+
err=True,
|
|
197
|
+
)
|
|
198
|
+
client.schema_drop(
|
|
199
|
+
attach_opaque_data=resolved_attach_opaque_data,
|
|
200
|
+
transaction_opaque_data=(
|
|
201
|
+
hex_to_transaction_opaque_data(transaction_opaque_data) if transaction_opaque_data else None
|
|
202
|
+
),
|
|
203
|
+
name=name,
|
|
204
|
+
ignore_not_found=ignore_not_found,
|
|
205
|
+
cascade=cascade,
|
|
206
|
+
)
|
|
207
|
+
output_json({"status": "dropped", "name": name})
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
@schema.command("contents")
|
|
211
|
+
@click.argument("name")
|
|
212
|
+
@click.option("--attach-opaque-data", help="Hex-encoded attach ID")
|
|
213
|
+
@click.option("--catalog", "catalog_name", help="Catalog name for auto-attach")
|
|
214
|
+
@click.option("--attach-options", default="{}", help="Attach options as JSON")
|
|
215
|
+
@click.option("--worker", "-w", required=True, help="VGI worker command")
|
|
216
|
+
@click.option("--transaction-opaque-data", help="Transaction ID (hex) for transactional read")
|
|
217
|
+
@click.option(
|
|
218
|
+
"--type",
|
|
219
|
+
"object_type",
|
|
220
|
+
type=click.Choice(["table", "view", "scalar_function", "table_function", "aggregate_function"]),
|
|
221
|
+
required=True,
|
|
222
|
+
help="Object type to list (required)",
|
|
223
|
+
)
|
|
224
|
+
def schema_contents(
|
|
225
|
+
name: str,
|
|
226
|
+
attach_opaque_data: str | None,
|
|
227
|
+
catalog_name: str | None,
|
|
228
|
+
attach_options: str,
|
|
229
|
+
worker: str,
|
|
230
|
+
transaction_opaque_data: str | None,
|
|
231
|
+
object_type: str,
|
|
232
|
+
) -> None:
|
|
233
|
+
"""List contents of a schema by object type.
|
|
234
|
+
|
|
235
|
+
NAME is the schema name.
|
|
236
|
+
|
|
237
|
+
Requires --type to specify which object type to list.
|
|
238
|
+
|
|
239
|
+
"""
|
|
240
|
+
client = Client(worker)
|
|
241
|
+
opts = parse_json_option(attach_options, "--attach-options")
|
|
242
|
+
resolved_attach_opaque_data, is_stateful = get_attach_opaque_data_from_options(
|
|
243
|
+
client, attach_opaque_data, catalog_name, opts
|
|
244
|
+
)
|
|
245
|
+
if is_stateful and catalog_name:
|
|
246
|
+
click.echo(
|
|
247
|
+
"Warning: Using --catalog with a stateful catalog. "
|
|
248
|
+
"Consider using --attach-opaque-data for session persistence.",
|
|
249
|
+
err=True,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
# Convert string type to SchemaObjectType enum
|
|
253
|
+
type_filter = SchemaObjectType(object_type)
|
|
254
|
+
|
|
255
|
+
for item in client.schema_contents(
|
|
256
|
+
attach_opaque_data=resolved_attach_opaque_data,
|
|
257
|
+
transaction_opaque_data=(
|
|
258
|
+
hex_to_transaction_opaque_data(transaction_opaque_data) if transaction_opaque_data else None
|
|
259
|
+
),
|
|
260
|
+
name=name,
|
|
261
|
+
type=type_filter,
|
|
262
|
+
):
|
|
263
|
+
if isinstance(item, TableInfo):
|
|
264
|
+
output_json({"type": "table", **table_info_to_dict(item)})
|
|
265
|
+
elif isinstance(item, ViewInfo):
|
|
266
|
+
output_json({"type": "view", **view_info_to_dict(item)})
|
|
267
|
+
elif isinstance(item, FunctionInfo):
|
|
268
|
+
output_json({"type": "function", **function_info_to_dict(item)})
|
|
269
|
+
else:
|
|
270
|
+
output_json({"type": "unknown", "name": getattr(item, "name", "unknown")})
|