vgi-python 0.31.4__tar.gz → 0.32.0__tar.gz
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_python-0.31.4 → vgi_python-0.32.0}/PKG-INFO +1 -1
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/protocol/vgi-protocol-proposed-changes.md +54 -8
- {vgi_python-0.31.4 → vgi_python-0.32.0}/pyproject.toml +1 -1
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_writable_table.py +47 -21
- vgi_python-0.32.0/tests/test_write_results.py +50 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/transactor/test_transactor.py +10 -5
- {vgi_python-0.31.4 → vgi_python-0.32.0}/uv.lock +1 -1
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/__init__.py +5 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/schema_reconcile/worker.py +1 -3
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/simple_writable.py +72 -32
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/writable/generic.py +14 -10
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/writable/table.py +10 -10
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/writable/worker.py +1 -4
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/__init__.py +5 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/catalog_interface.py +7 -11
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/descriptors.py +27 -3
- vgi_python-0.32.0/vgi/http/vgi-client.js +22 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/transactor/protocol.py +4 -3
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/transactor/server.py +54 -21
- vgi_python-0.32.0/vgi/write_results.py +73 -0
- vgi_python-0.31.4/vgi/http/vgi-client.js +0 -23
- {vgi_python-0.31.4 → vgi_python-0.32.0}/.dockerignore +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/.gitattributes +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/.github/dependabot.yml +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/.github/styles/config/vocabularies/VGI/accept.txt +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/.github/workflows/ci.yml +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/.github/workflows/docs.yml +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/.github/workflows/integration.yml +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/.github/workflows/release.yml +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/.github/workflows/tailnet-integration.yml +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/.gitignore +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/.python-version +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/.vale.ini +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/CLAUDE.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/DOCS_ACCEPTANCE_CRITERIA.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/DOCS_REVIEW_RUBRIC.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/DOCS_USABILITY_TEST.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/LICENSE +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/PROTOCOL.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/README.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/RELEASE-RUNBOOK.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/SECURITY.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/ci/README.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/ci/preprocess-require.awk +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/ci/run-integration.sh +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/README.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/and-too-few-children.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/delta-required-upsert.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/nested-runtime-filter.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/remove-with-expression.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/required-runtime-filter.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/snapshot-nonzero-revision.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/unknown-document-property.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/negative/unknown-node.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/positive/advisory-upsert-delta.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/positive/empty-snapshot.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/positive/nested-required-snapshot.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/positive/remove-delta.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/cases/positive/runtime-filter-snapshot.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/filter-v2.schema.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/generate_runtime.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/manifest.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/run_worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-add/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-add/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-add/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-multiply/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-multiply/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-multiply/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-negate/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-negate/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-negate/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-subtract/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-subtract/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/arithmetic-subtract/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/cast-integer-to-double/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/cast-integer-to-double/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/cast-integer-to-double/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-distinct_from/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-distinct_from/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-distinct_from/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-distinct_from/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-eq/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-eq/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-eq/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-eq/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ge/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ge/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ge/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ge/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-gt/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-gt/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-gt/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-gt/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-le/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-le/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-le/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-le/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-lt/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-lt/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-lt/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-lt/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ne/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ne/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ne/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-ne/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-not_distinct_from/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-not_distinct_from/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-not_distinct_from/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/comparison-not_distinct_from/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-atomic-multi-update/delta-0.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-atomic-multi-update/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-atomic-multi-update/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-atomic-multi-update/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-empty-noop/delta-0.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-empty-noop/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-empty-noop/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-empty-noop/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-0.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-1.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/delta-2.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/delta-upsert-remove-stale/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/empty-snapshot/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/empty-snapshot/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/empty-snapshot/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/empty-snapshot/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-cast-type-not-null/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-cast-type-not-null/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-column-index/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-column-index/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-column-name/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-column-name/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-contextual-cast-without-session/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-contextual-cast-without-session/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-duplicate-predicate-id/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-duplicate-predicate-id/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-external-column-index/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-external-column-index/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-external-column-index/join-keys-0.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-external-column-name/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-external-column-name/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-external-column-name/join-keys-0.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-field-non-struct/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-field-non-struct/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-in-payload-not-list/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-in-payload-not-list/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-in-payload-null-list/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-in-payload-null-list/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-invalid-overload/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-invalid-overload/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-missing-literal/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-missing-literal/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-non-boolean-root/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-non-boolean-root/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-unknown-standard-function/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/error-unknown-standard-function/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/external-in-nonzero-column/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/external-in-nonzero-column/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/external-in-nonzero-column/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/external-in-nonzero-column/join-keys-0.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/external-in-nonzero-column/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-contains/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-contains/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-contains/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-ends-with/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-ends-with/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-ends-with/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-list-contains/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-list-contains/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-list-contains/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-starts-with/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-starts-with/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/function-starts-with/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-empty/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-empty/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-empty/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-empty/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-with-null/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-with-null/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-with-null/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/in-with-null/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-not-null/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-not-null/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-not-null/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-not-null/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-null/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-null/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-null/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/is-null/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-and/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-and/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-and/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-not/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-not/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-not/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-or/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-or/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/kleene-or/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/nan-comparison/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/nan-comparison/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/nan-comparison/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/negative-zero-membership/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/negative-zero-membership/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/negative-zero-membership/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/nested-null-propagation/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/nested-null-propagation/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/nested-null-propagation/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-empty/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-empty/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-empty/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-empty/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-with-null/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-with-null/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-with-null/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/not-in-with-null/worker-expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/session-integer-division/expected.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/session-integer-division/filter.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime/session-integer-division/input.arrow +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/conformance/filter-v2/runtime-manifest.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/dist-vgi/.gitignore +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/aggregate-functions.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/arguments.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/auth.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/catalogs.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/client.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/exceptions.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/filters.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/functions.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/http.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/index.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/metadata.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/observability.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/storage.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/transactor.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/api/worker.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/argument-serialization.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/apple-touch-icon.png +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/favicon-16x16.png +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/favicon-32x32.png +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/favicon.ico +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/kinds/aggregate.svg +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/kinds/buffering.svg +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/kinds/scalar.svg +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/kinds/table-in-out.svg +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/kinds/table.svg +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/logo.png +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/assets/social-card.png +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/authentication.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/catalog-interface.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/cli.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/column-statistics.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/concepts/index.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/contributing-docs.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/filter-pushdown.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/generator-api.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/global-functions.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/catalogs.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/function-patterns.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/http-auth.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/index.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/iroh.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/pushdown-and-statistics.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/state-storage.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/how-to/tailnet.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/index.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/lifecycle.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/metadata.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/overrides/main.html +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/protocol/index.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/protocol/vgi-duckdb-filter-adapter.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/protocol/vgi-filter-encoding-v2-spec.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/protocol/vgi-runtime-filter-artifacts.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/robots.txt +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/shared-storage.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/stylesheets/extra.css +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/tutorial/index.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/tutorial/scalar.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/tutorial/table.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/docs/vgi-logo.png +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/batch_index_worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/cache_worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/calc_scalar_worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/calc_worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/copy_format_worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/filter_worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/greeting_scalar_worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/row_count_worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/series_streaming_worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/examples/sum_worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/mkdocs.yml +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/packages/vgi-fixtures/LICENSE +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/packages/vgi-fixtures/README.md +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/packages/vgi-fixtures/docker/Dockerfile +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/packages/vgi-fixtures/docker/docker-entrypoint.sh +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/packages/vgi-fixtures/pyproject.toml +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/scripts/measure_startup.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/scripts/run_all_tests.sh +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/test-data/generate.sh +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/_http_fixtures.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_attach_option.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_catalog_interface.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_client_catalog.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_column_statistics.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_declarative.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_example_worker_catalog.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_integration.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_required_filters.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_scan_branches.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_serialization.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_setting.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_storage.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/catalog/test_time_travel.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_aggregate_client.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_batch_metadata_callback.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_bind_and_join_keys.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_broken_pipe.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_cli.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_cli_catalog_functions.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_copy_client.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_http_response_budget.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_iroh_client.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_scan_branches_client.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_split_client.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_stop_force.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_table_column_statistics.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_time_travel_client.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/client/test_worker_debug.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/_stub.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/conftest.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_accumulate.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_aggregate.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_attach.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_bearer_auth.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_const_param_enforcement.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_container.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_copy_from.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_copy_to.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_directory_parity.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_function_inventory.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_github.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_http_client.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_http_external_location.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_http_upload_url.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_macro.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_overload.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_protocol_inventory.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_protocol_version.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_resumable_scan.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_scalar.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_scalar_attach_opaque_data.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_secret.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_settings.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_splits.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_table.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_table_in_out.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_view.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conformance/test_writable.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/conftest.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/anchor_len_overrun.bin +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/bad_fingerprint.bin +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/bad_flags_unsealed_but_key_present.bin +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/bad_version.bin +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/generate.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/manifest.json +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/reserved_flag_bit.bin +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/stale_anchor.bin +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/truncated.bin +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/valid_sealed.bin +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/data/split_tokens/valid_unsealed.bin +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_bernoulli_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_binary_packet_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_client.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_conditional_message_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_hash_seed_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_multiply_by_setting_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_multiply_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_random_bytes_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/scalar/test_return_secret_value_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_constant_columns_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_double_sequence_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_exception_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_filter_echo_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_logging_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_nested_sequence_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_partitioned_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_projected_data_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_sequence_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_settings_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_struct_settings_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/generator/test_ten_thousand_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table/test_wide_columns.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/test_buffer_input_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/test_echo_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/test_exception_functions.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/test_filter_by_setting_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/test_repeat_inputs_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/test_substream_partial_sum_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/generator/test_sum_all_columns_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/test_blended_exchange.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/test_blended_metadata.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/table_in_out/test_client.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/tailnet/Dockerfile +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/tailnet/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/tailnet/compose.yaml +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/tailnet/probe.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/tailnet/run.sh +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/tailnet/test_worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/tailnet/worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_access_log_audit.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_aggregate_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_argument_spec.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_auth.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_bind_exceptions.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_bind_request_at_clause.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_bound_storage_conformance.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_cache_control.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_call_state_attach.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_catalog_auth_binding.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_client_oauth.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_codegen_request_inventory.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_copy_from_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_copy_to_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_docstrings.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_documentation_examples.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_example_function_arg_types.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_examples_workers.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_exception_handling.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_exceptions.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_filter_pushdown.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_filter_pushdown_extension.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_filter_v2.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_filter_v2_builder.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_filter_v2_runtime_corpus.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_filter_v2_spec_schema.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_fixture_catalog_parity.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_function_shape_mismatch.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_function_storage.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_function_storage_azure_sql.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_function_storage_cf_do.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_function_storage_cf_do_integration.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_function_storage_conformance.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_cpp_constants.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_cpp_protocol_version.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_cpp_request_builders.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_cpp_schemas.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_cpp_secret.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_go_schemas.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_java_schemas.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_protocol_version.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_rust_request_builders.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_rust_schemas.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_schemas_cross_lang.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_ts_client.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_generated_ts_schemas.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_http_demo_storage.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_http_s3_offload_input.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_http_s3_offload_output.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_launch_transport.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_metadata.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_mypy_consolidated.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_nest_tensor.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_otel.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_projection_enforcement.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_projection_repro.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_protocol_classes.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_resolved_secrets.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_schema_paths_v2.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_schema_scoped_functions.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_schema_utils.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_serve.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_setting_secret_annotations.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_signing_key.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_split_token.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_table_buffering_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_table_function_dynamic_to_string.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_tcp_transport.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_type_bounds.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_union_argument.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_wire_record_schema_parity.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_worker_cli.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/test_worker_page.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/tests/transactor/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_duckdb.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_storage_profile.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/accumulate/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/accumulate/worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/_common.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/basic.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/dynamic.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/generic.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/listagg.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/percentile.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/same_name.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/secret_typed.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/streaming.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/varargs.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/aggregate/window.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/attach_options.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/bad_enum.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/bad_protocol.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/cancellable.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/catalog.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/companion.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/copy_from.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/copy_to.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/global_functions.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/http_server.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/narrow_bind/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/narrow_bind/worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/nest_tensor.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/orchard_catalog.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/projection_repro/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/projection_repro/worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/_common.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/arithmetic.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/bench_ladder.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/binary.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/formatting.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/geo.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/null_handling.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/random_demo.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/same_name.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/settings_secrets.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/scalar/type_info.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/schema_reconcile/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/_common.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/batch_index.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/batch_index_broken.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/cache.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/catalog_scans.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/filters.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/late_materialization.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/make_series.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/misc.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/order_modes.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/pairs.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/partition_columns.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/partition_columns_broken.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/profiling_example.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/required_filters.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/same_name_cached.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/same_name_schemas.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/sequence.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/settings.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/splits.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/transaction_storage.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/tt_pushdown.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/typed_probe.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/versioned.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table/wide.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table_in_out.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/table_in_out_same_name.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/twin_catalogs.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/versioned.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/versioned_tables.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/_test_fixtures/writable/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/aggregate_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/argument_spec.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/arguments.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/attach_header.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/auth.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/cache_control.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/_descriptor_spec.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/attach_option.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/duckdb_statistics.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/secret_type.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/setting.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/catalog/storage.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/aggregate.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/catalog_mixin.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/cli.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/cli_catalog.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/cli_schema.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/cli_table.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/cli_transaction.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/cli_utils.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/cli_view.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/client.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/client/errors.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/_common.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/cpp_constants.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/cpp_protocol_version.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/cpp_request_builders.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/cpp_schemas.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/cpp_secret_protocol_version.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/cpp_secret_request_builders.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/cpp_secret_schemas.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/go_schemas.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/java_schemas.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/protocol_version.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/rust_request_builders.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/rust_schemas.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/ts_client.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/codegen/ts_schemas.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/copy_from_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/copy_to_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/exceptions.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/filter_v2.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/filter_v2_builder.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/function_storage.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/function_storage_azure_sql.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/function_storage_cf_do.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/http/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/http/demo_storage.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/http/landing.html +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/http/landing_page.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/http/worker_page.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/invocation.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/logging_config.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/meta_worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/metadata.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/otel.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/profiling.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/protocol.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/protocol_version.txt +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/py.typed +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/scalar_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/schema_path.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/schema_utils.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/secret_protocol.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/secret_service.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/serve.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/split_token.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/table_buffering_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/table_filter_pushdown.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/table_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/table_in_out_function.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/transactor/__init__.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/transactor/_duckdb_compat.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/transactor/client.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/vgi/worker.py +0 -0
- {vgi_python-0.31.4 → vgi_python-0.32.0}/wrangler.jsonc +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: vgi-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.32.0
|
|
4
4
|
Summary: Vector Gateway Interface - Connect DuckDB to external programs via Apache Arrow
|
|
5
5
|
Project-URL: Homepage, https://query.farm
|
|
6
6
|
Project-URL: Repository, https://github.com/Query-farm/vgi-python
|
|
@@ -453,7 +453,34 @@ Triggers are different. Supporting a trigger in a virtual catalog would require
|
|
|
453
453
|
|
|
454
454
|
The same principle applies to secure views, composable COPY, remote-plan pushdown, coordinate systems, and any catalog object VGI does not currently virtualize: they are not protocol requirements simply because DuckDB implements them. They should be gated through explicit catalog capabilities and fail early.
|
|
455
455
|
|
|
456
|
-
### 6.1
|
|
456
|
+
### 6.1 Writable result modes and OLD/NEW images
|
|
457
|
+
|
|
458
|
+
VGI 2.0 replaces the four `TableInfo` booleans `supports_insert`,
|
|
459
|
+
`supports_update`, `supports_delete`, and `supports_returning` with one required,
|
|
460
|
+
non-null Arrow map:
|
|
461
|
+
|
|
462
|
+
```text
|
|
463
|
+
write_result_modes: map<utf8, utf8>
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
The only operation keys are `insert`, `update`, and `delete`; absence means the
|
|
467
|
+
operation is unsupported. Each value is the maximum supported mode in the
|
|
468
|
+
ordered lattice `count < rows < changes`, and therefore promises every lower
|
|
469
|
+
mode. Duplicate keys and unknown operations or modes are protocol errors.
|
|
470
|
+
|
|
471
|
+
The serialized `write_options` batch replaces `return_chunks: bool` with the
|
|
472
|
+
required `result_mode: utf8`. `count` returns `(count int64 not null)`. `rows`
|
|
473
|
+
returns NEW rows for INSERT/UPDATE and OLD rows for DELETE. `changes` returns
|
|
474
|
+
two nullable structs, `old` and `new`, each shaped exactly like the table:
|
|
475
|
+
INSERT populates only `new`, DELETE only `old`, and UPDATE both. The operation
|
|
476
|
+
is known from the invoked write function and is not repeated in each result row.
|
|
477
|
+
|
|
478
|
+
The DuckDB 1.5 adapter requests `count` for ordinary DML and `rows` for DML with
|
|
479
|
+
RETURNING. It validates and preserves `changes` capability metadata but never
|
|
480
|
+
requests that mode. A DuckDB 2.0 adapter can request `changes` when trigger
|
|
481
|
+
planning needs OLD/NEW images without another protocol revision.
|
|
482
|
+
|
|
483
|
+
### 6.2 New catalog kinds in DuckDB 2.0
|
|
457
484
|
|
|
458
485
|
The `CatalogType` enum has exactly two additions relative to DuckDB 1.5.5:
|
|
459
486
|
|
|
@@ -464,7 +491,7 @@ The `CatalogType` enum has exactly two additions relative to DuckDB 1.5.5:
|
|
|
464
491
|
|
|
465
492
|
Nested schemas are recursively contained `SCHEMA_ENTRY` objects, not another kind. Secure views remain `VIEW_ENTRY`; changes to aggregate-state representation belong to the logical type system rather than the catalog enum.
|
|
466
493
|
|
|
467
|
-
### 6.
|
|
494
|
+
### 6.3 How native DuckDB stores triggers
|
|
468
495
|
|
|
469
496
|
Triggers are first-class `TriggerCatalogEntry` objects, but they do not live in the schema's ordinary catalog set. Each `DuckTableEntry` owns a separate transactional `CatalogSet`:
|
|
470
497
|
|
|
@@ -496,7 +523,7 @@ The dependency manager has special trigger identity/lookup handling because sche
|
|
|
496
523
|
|
|
497
524
|
At bind time DuckDB scans the table's triggers and expands them into the DML plan. Statement triggers form a materialized CTE chain (BEFORE actions, base DML, AFTER actions), including materialized OLD/NEW transition tables when requested. Supported row triggers use `LogicalTrigger` and correlated `NEW.col`/`OLD.col` bindings. The current catalog set yields triggers in case-insensitive alphabetical name order.
|
|
498
525
|
|
|
499
|
-
### 6.
|
|
526
|
+
### 6.4 DuckDB changes needed by custom table implementations
|
|
500
527
|
|
|
501
528
|
DuckDB 2.0 already exposes virtual `TableCatalogEntry::CreateTrigger`, `ScanTriggers`, and `GetTrigger` hooks, and its trigger binder consumes the generic scan hook. Two remaining native-table assumptions should be fixed upstream:
|
|
502
529
|
|
|
@@ -509,7 +536,7 @@ Upstream PR: [duckdb/duckdb#25539 — Support triggers on custom table catalog e
|
|
|
509
536
|
|
|
510
537
|
The `ScanTriggers` contract also implies that returned catalog entries remain alive beyond the callback: both trigger selection and introspection retain references. VGI should materialize trigger entries in a table-owned metadata cache, invalidated through the existing catalog-version mechanism, rather than returning callback-local objects.
|
|
511
538
|
|
|
512
|
-
### 6.
|
|
539
|
+
### 6.5 Proposed VGI trigger protocol
|
|
513
540
|
|
|
514
541
|
The remote VGI catalog should be authoritative for persistent trigger definitions. Keeping definitions only in a local extension cache would lose them on detach and would give different clients inconsistent catalogs.
|
|
515
542
|
|
|
@@ -529,13 +556,22 @@ TriggerInfo
|
|
|
529
556
|
for_each: statement | row
|
|
530
557
|
referencing_new_table: optional<string>
|
|
531
558
|
referencing_old_table: optional<string>
|
|
532
|
-
|
|
559
|
+
definitions: map<string, string>
|
|
533
560
|
dependencies: list<TriggerDependency>
|
|
534
561
|
comment: optional<string>
|
|
535
562
|
tags: map<string, string>
|
|
536
563
|
```
|
|
537
564
|
|
|
538
|
-
Use structured fields plus
|
|
565
|
+
Use structured fields plus engine-specific textual definitions keyed by stable
|
|
566
|
+
lowercase engine identifiers such as `duckdb`, `datafusion`, `spark`, and
|
|
567
|
+
`sqlite`. An engine executes only its matching definition; a missing entry means
|
|
568
|
+
that trigger is unavailable on that engine, with no implicit SQL-dialect
|
|
569
|
+
fallback. Do not put DuckDB's binary `QueryNode` serialization on the VGI wire:
|
|
570
|
+
it is an internal, version-coupled representation. The DuckDB extension parses
|
|
571
|
+
the `duckdb` definition and creates cached `TriggerCatalogEntry` objects. Each
|
|
572
|
+
resolved dependency should carry its qualified object reference plus ownership,
|
|
573
|
+
drop-blocking, and alter-blocking flags so the remote catalog can enforce DDL
|
|
574
|
+
integrity across clients.
|
|
539
575
|
|
|
540
576
|
Suggested methods:
|
|
541
577
|
|
|
@@ -545,7 +581,10 @@ Suggested methods:
|
|
|
545
581
|
- `catalog_table_trigger_drop`
|
|
546
582
|
- optional trigger comment/tag alteration
|
|
547
583
|
|
|
548
|
-
Add explicit catalog/table capability metadata such as `supports_triggers`. A
|
|
584
|
+
Add explicit catalog/table capability metadata such as `supports_triggers`. A
|
|
585
|
+
DuckDB-managed trigger-capable table must advertise `changes` for every event it
|
|
586
|
+
uses, because DuckDB's statement-trigger expansion needs exact OLD/NEW images
|
|
587
|
+
even when the user did not write a RETURNING clause.
|
|
549
588
|
|
|
550
589
|
All base and trigger-body writes must use the same VGI transaction token and roll back atomically. Stable statement/sub-operation identifiers are recommended so transport retries cannot apply a trigger side effect twice. Trigger support should be rejected when the VGI catalog cannot provide transactional atomicity.
|
|
551
590
|
|
|
@@ -673,4 +712,11 @@ The first protocol-breaking phase is now implemented in Python:
|
|
|
673
712
|
|
|
674
713
|
`CatalogAttachResult.default_schema` intentionally remains a scalar root-schema identifier for the reason described in section 2.
|
|
675
714
|
|
|
676
|
-
|
|
715
|
+
The writable-result phase replaces the legacy write booleans and
|
|
716
|
+
`return_chunks` option with the `write_result_modes`/`result_mode` contract from
|
|
717
|
+
section 6.1. Python implements and directly tests all three modes. The DuckDB
|
|
718
|
+
1.5 extension consumes only `count` and `rows`; `changes` is reserved for the
|
|
719
|
+
future DuckDB 2.0 trigger adapter. Trigger catalog metadata and RPCs remain
|
|
720
|
+
unimplemented.
|
|
721
|
+
|
|
722
|
+
This phase does **not** implement the other proposed protocol areas: logical-type identity annotations, trigger RPCs, or standalone window-function catalog entries. The sibling C++, C#, Go, Java, Rust, and TypeScript schema migrations are maintained in their corresponding repositories. The vendored browser `vgi-client.js` remains generated from the TypeScript SDK and must never be edited manually in the Python repository.
|
|
@@ -129,11 +129,11 @@ class TestTableDescriptorWriteFields:
|
|
|
129
129
|
)
|
|
130
130
|
|
|
131
131
|
|
|
132
|
-
class
|
|
133
|
-
"""TableInfo
|
|
132
|
+
class TestTableInfoWriteResultModes:
|
|
133
|
+
"""TableInfo serializes per-operation maximum result modes."""
|
|
134
134
|
|
|
135
|
-
def
|
|
136
|
-
"""
|
|
135
|
+
def test_count_modes_inferred_when_functions_present(self) -> None:
|
|
136
|
+
"""Configured functions default to the count result mode."""
|
|
137
137
|
table = Table(
|
|
138
138
|
name="t",
|
|
139
139
|
function=WritableTableScan,
|
|
@@ -142,35 +142,63 @@ class TestTableInfoWriteFlags:
|
|
|
142
142
|
delete_function=WritableTableDelete,
|
|
143
143
|
)
|
|
144
144
|
info = table.to_table_info(["main"])
|
|
145
|
-
assert info.
|
|
146
|
-
assert info.supports_update is True
|
|
147
|
-
assert info.supports_delete is True
|
|
145
|
+
assert info.write_result_modes == {"insert": "count", "update": "count", "delete": "count"}
|
|
148
146
|
|
|
149
|
-
def
|
|
150
|
-
"""
|
|
147
|
+
def test_read_only_table_has_empty_modes(self) -> None:
|
|
148
|
+
"""An empty map describes a read-only table."""
|
|
151
149
|
table = Table(
|
|
152
150
|
name="t",
|
|
153
151
|
function=WritableTableScan,
|
|
154
152
|
)
|
|
155
153
|
info = table.to_table_info(["main"])
|
|
156
|
-
assert info.
|
|
157
|
-
assert info.supports_update is False
|
|
158
|
-
assert info.supports_delete is False
|
|
154
|
+
assert info.write_result_modes == {}
|
|
159
155
|
|
|
160
|
-
def
|
|
161
|
-
"""Only
|
|
156
|
+
def test_partial_write_modes(self) -> None:
|
|
157
|
+
"""Only operations with functions appear in the map."""
|
|
162
158
|
table = Table(
|
|
163
159
|
name="t",
|
|
164
160
|
function=WritableTableScan,
|
|
165
161
|
insert_function=WritableTableInsert,
|
|
166
162
|
)
|
|
167
163
|
info = table.to_table_info(["main"])
|
|
168
|
-
assert info.
|
|
169
|
-
|
|
170
|
-
|
|
164
|
+
assert info.write_result_modes == {"insert": "count"}
|
|
165
|
+
|
|
166
|
+
def test_explicit_maximum_modes(self) -> None:
|
|
167
|
+
"""Authors can opt each configured operation into rows or changes."""
|
|
168
|
+
table = Table(
|
|
169
|
+
name="t",
|
|
170
|
+
function=WritableTableScan,
|
|
171
|
+
insert_function=WritableTableInsert,
|
|
172
|
+
update_function=WritableTableUpdate,
|
|
173
|
+
write_result_modes={"insert": "rows", "update": "changes"},
|
|
174
|
+
)
|
|
175
|
+
assert table.to_table_info(["main"]).write_result_modes == {
|
|
176
|
+
"insert": "rows",
|
|
177
|
+
"update": "changes",
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@pytest.mark.parametrize("modes", [{"merge": "count"}, {"insert": "invalid"}])
|
|
181
|
+
def test_invalid_modes_rejected(self, modes: dict[str, str]) -> None:
|
|
182
|
+
"""Unknown operations and modes fail at descriptor construction."""
|
|
183
|
+
with pytest.raises(ValueError):
|
|
184
|
+
Table(
|
|
185
|
+
name="t",
|
|
186
|
+
columns=pa.schema([("id", pa.int64())]),
|
|
187
|
+
insert_function=WritableTableInsert,
|
|
188
|
+
write_result_modes=modes,
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
def test_mode_without_function_rejected(self) -> None:
|
|
192
|
+
"""Capability metadata cannot claim a missing implementation."""
|
|
193
|
+
with pytest.raises(ValueError, match="without a corresponding update_function"):
|
|
194
|
+
Table(
|
|
195
|
+
name="t",
|
|
196
|
+
columns=pa.schema([("id", pa.int64())]),
|
|
197
|
+
write_result_modes={"update": "rows"},
|
|
198
|
+
)
|
|
171
199
|
|
|
172
200
|
def test_table_info_serialization_roundtrip(self) -> None:
|
|
173
|
-
"""Write
|
|
201
|
+
"""Write modes survive Arrow serialization roundtrip."""
|
|
174
202
|
table = Table(
|
|
175
203
|
name="t",
|
|
176
204
|
function=WritableTableScan,
|
|
@@ -181,9 +209,7 @@ class TestTableInfoWriteFlags:
|
|
|
181
209
|
info = table.to_table_info(["main"])
|
|
182
210
|
data = info.serialize_to_bytes()
|
|
183
211
|
restored = TableInfo.deserialize_from_bytes(data)
|
|
184
|
-
assert restored.
|
|
185
|
-
assert restored.supports_update is True
|
|
186
|
-
assert restored.supports_delete is True
|
|
212
|
+
assert restored.write_result_modes == {"insert": "count", "update": "count", "delete": "count"}
|
|
187
213
|
|
|
188
214
|
|
|
189
215
|
class TestReadOnlyCatalogInterfaceWriteMethods:
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Copyright 2025, 2026 Query Farm LLC - https://query.farm
|
|
2
|
+
|
|
3
|
+
"""Tests for the VGI 2.0 writable result-mode contract."""
|
|
4
|
+
|
|
5
|
+
import pyarrow as pa
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from vgi.schema_utils import schema
|
|
9
|
+
from vgi.write_results import supports_write_result_mode, write_changes_batch, write_result_schema
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_ordered_result_modes() -> None:
|
|
13
|
+
"""A maximum mode promises itself and every lower mode."""
|
|
14
|
+
assert supports_write_result_mode("count", "count")
|
|
15
|
+
assert not supports_write_result_mode("count", "rows")
|
|
16
|
+
assert supports_write_result_mode("rows", "count")
|
|
17
|
+
assert supports_write_result_mode("changes", "rows")
|
|
18
|
+
assert supports_write_result_mode("changes", "changes")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_result_schemas() -> None:
|
|
22
|
+
"""Every mode has the exact canonical Arrow schema."""
|
|
23
|
+
table = schema(id=pa.int64(), name=pa.string())
|
|
24
|
+
assert write_result_schema("count", table) == pa.schema([pa.field("count", pa.int64(), nullable=False)])
|
|
25
|
+
assert write_result_schema("rows", table) == table
|
|
26
|
+
changes = write_result_schema("changes", table)
|
|
27
|
+
assert changes.names == ["old", "new"]
|
|
28
|
+
assert changes.field("old").nullable
|
|
29
|
+
assert changes.field("old").type == pa.struct(list(table))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@pytest.mark.parametrize(
|
|
33
|
+
("old", "new"),
|
|
34
|
+
[
|
|
35
|
+
(None, {"id": 1, "name": "inserted"}),
|
|
36
|
+
({"id": 1, "name": "old"}, {"id": 1, "name": "new"}),
|
|
37
|
+
({"id": 1, "name": "deleted"}, None),
|
|
38
|
+
],
|
|
39
|
+
)
|
|
40
|
+
def test_change_images(old: dict[str, object] | None, new: dict[str, object] | None) -> None:
|
|
41
|
+
"""INSERT, UPDATE, and DELETE preserve the required OLD/NEW nullability."""
|
|
42
|
+
table = schema(id=pa.int64(), name=pa.string())
|
|
43
|
+
batch = write_changes_batch(table, [old], [new])
|
|
44
|
+
assert batch.to_pylist() == [{"old": old, "new": new}]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_change_image_lengths_must_match() -> None:
|
|
48
|
+
"""Every output row must contain one OLD/NEW pair."""
|
|
49
|
+
with pytest.raises(ValueError, match="equal length"):
|
|
50
|
+
write_changes_batch(pa.schema([("id", pa.int64())]), [], [{"id": 1}])
|
|
@@ -24,7 +24,7 @@ pytestmark = pytest.mark.skip(reason="Transactor/write subsystem disabled — se
|
|
|
24
24
|
# Helpers
|
|
25
25
|
# ============================================================================
|
|
26
26
|
|
|
27
|
-
_COUNT_SCHEMA = schema(count
|
|
27
|
+
_COUNT_SCHEMA = pa.schema([pa.field("count", pa.int64(), nullable=False)])
|
|
28
28
|
_FILTER_METADATA = {b"vgi_filter_version": b"1"}
|
|
29
29
|
|
|
30
30
|
|
|
@@ -66,7 +66,7 @@ def _insert_into(
|
|
|
66
66
|
t: TransactorImpl, tx_id: bytes, table_name: str, rows: list[tuple[int, str]], *, returning: bool = False
|
|
67
67
|
) -> pa.RecordBatch:
|
|
68
68
|
"""Insert rows into an arbitrary table and return the response batch."""
|
|
69
|
-
stream = t.insert(tx_id=tx_id, table_name=table_name,
|
|
69
|
+
stream = t.insert(tx_id=tx_id, table_name=table_name, result_mode="rows" if returning else "count")
|
|
70
70
|
batch = pa.record_batch(
|
|
71
71
|
{"id": [r[0] for r in rows], "name": [r[1] for r in rows]},
|
|
72
72
|
schema=schema(id=pa.int64(), name=pa.string()),
|
|
@@ -79,7 +79,7 @@ def _insert_into(
|
|
|
79
79
|
|
|
80
80
|
def _insert(t: TransactorImpl, tx_id: bytes, rows: list[tuple[int, str]], *, returning: bool = False) -> pa.RecordBatch:
|
|
81
81
|
"""Insert rows via the transactor and return the response batch."""
|
|
82
|
-
stream = t.insert(tx_id=tx_id, table_name="data",
|
|
82
|
+
stream = t.insert(tx_id=tx_id, table_name="data", result_mode="rows" if returning else "count")
|
|
83
83
|
batch = pa.record_batch(
|
|
84
84
|
{"id": [r[0] for r in rows], "name": [r[1] for r in rows]},
|
|
85
85
|
schema=schema(id=pa.int64(), name=pa.string()),
|
|
@@ -119,7 +119,7 @@ def _scan(
|
|
|
119
119
|
|
|
120
120
|
def _delete(t: TransactorImpl, tx_id: bytes, rowids: list[int], *, returning: bool = False) -> pa.RecordBatch:
|
|
121
121
|
"""Delete rows by rowid, return the response batch."""
|
|
122
|
-
stream = t.delete(tx_id=tx_id, table_name="data",
|
|
122
|
+
stream = t.delete(tx_id=tx_id, table_name="data", result_mode="rows" if returning else "count")
|
|
123
123
|
batch = pa.record_batch({"rowid": rowids}, schema=schema(rowid=pa.int64()))
|
|
124
124
|
out = OutputCollector(stream.output_schema, producer_mode=False)
|
|
125
125
|
assert isinstance(stream.state, ExchangeState)
|
|
@@ -136,7 +136,12 @@ def _update(
|
|
|
136
136
|
t: TransactorImpl, tx_id: bytes, rowids: list[int], names: list[str], *, returning: bool = False
|
|
137
137
|
) -> pa.RecordBatch:
|
|
138
138
|
"""Update name column by rowid, return the response batch."""
|
|
139
|
-
stream = t.update(
|
|
139
|
+
stream = t.update(
|
|
140
|
+
tx_id=tx_id,
|
|
141
|
+
table_name="data",
|
|
142
|
+
columns=["name"],
|
|
143
|
+
result_mode="rows" if returning else "count",
|
|
144
|
+
)
|
|
140
145
|
batch = pa.record_batch(
|
|
141
146
|
{"name": names, "rowid": rowids},
|
|
142
147
|
schema=schema(name=pa.string(), rowid=pa.int64()),
|
|
@@ -129,10 +129,15 @@ from vgi.table_in_out_function import (
|
|
|
129
129
|
TableInOutGenerator,
|
|
130
130
|
)
|
|
131
131
|
from vgi.worker import Worker
|
|
132
|
+
from vgi.write_results import WriteOperation, WriteResultMode, write_changes_batch, write_result_schema
|
|
132
133
|
|
|
133
134
|
__all__ = [
|
|
134
135
|
"AggregateBindParams",
|
|
135
136
|
"AggregateFunction",
|
|
137
|
+
"WriteOperation",
|
|
138
|
+
"WriteResultMode",
|
|
139
|
+
"write_result_schema",
|
|
140
|
+
"write_changes_batch",
|
|
136
141
|
"AnyArrow",
|
|
137
142
|
"AnyArrowValue",
|
|
138
143
|
"Arg",
|
|
@@ -528,9 +528,7 @@ class SchemaReconcileCatalog(ReadOnlyCatalogInterface):
|
|
|
528
528
|
not_null_constraints=[],
|
|
529
529
|
unique_constraints=[],
|
|
530
530
|
check_constraints=[],
|
|
531
|
-
|
|
532
|
-
supports_update=True,
|
|
533
|
-
supports_delete=True,
|
|
531
|
+
write_result_modes={"insert": "changes", "update": "changes", "delete": "changes"},
|
|
534
532
|
)
|
|
535
533
|
|
|
536
534
|
def schemas(
|
|
@@ -13,7 +13,7 @@ Three pre-defined tables are exposed under the ``main`` schema:
|
|
|
13
13
|
|
|
14
14
|
* ``items`` — supports INSERT/UPDATE/DELETE with RETURNING.
|
|
15
15
|
* ``items_no_returning`` — supports INSERT/UPDATE/DELETE *without* RETURNING.
|
|
16
|
-
Used to exercise the
|
|
16
|
+
Used to exercise the ``count``-only RETURNING rejection path.
|
|
17
17
|
* ``items_insert_only`` — supports INSERT only (no UPDATE/DELETE/RETURNING).
|
|
18
18
|
|
|
19
19
|
State is held module-global, keyed by ``attach_opaque_data``. Per the
|
|
@@ -60,6 +60,7 @@ from vgi.schema_utils import schema as build_schema
|
|
|
60
60
|
from vgi.table_function import BindParams, InitParams, ProcessParams, TableFunctionGenerator
|
|
61
61
|
from vgi.table_in_out_function import TableInOutGenerator
|
|
62
62
|
from vgi.worker import Worker
|
|
63
|
+
from vgi.write_results import WriteResultMode, coerce_write_result_mode, write_changes_batch, write_result_schema
|
|
63
64
|
|
|
64
65
|
if TYPE_CHECKING:
|
|
65
66
|
from vgi.catalog.catalog_interface import (
|
|
@@ -82,7 +83,7 @@ CATALOG_NAME = "simple_writable"
|
|
|
82
83
|
_ROWID_FIELD = pa.field("rowid", pa.int64(), metadata={b"is_row_id": b""})
|
|
83
84
|
|
|
84
85
|
# Output schema for write functions returning affected row counts.
|
|
85
|
-
_COUNT_SCHEMA =
|
|
86
|
+
_COUNT_SCHEMA = pa.schema([pa.field("count", pa.int64(), nullable=False)])
|
|
86
87
|
|
|
87
88
|
|
|
88
89
|
# ============================================================================
|
|
@@ -116,7 +117,7 @@ def _table_specs() -> dict[str, pa.Schema]:
|
|
|
116
117
|
"items": build_schema(id=pa.int64(), name=pa.string(), qty=pa.int64()),
|
|
117
118
|
"items_no_returning": build_schema(id=pa.int64(), name=pa.string(), qty=pa.int64()),
|
|
118
119
|
"items_insert_only": build_schema(id=pa.int64(), name=pa.string()),
|
|
119
|
-
# Lies: catalog advertises
|
|
120
|
+
# Lies: catalog advertises rows support but the insert
|
|
120
121
|
# function always emits a (count BIGINT) batch. Used by tests to verify
|
|
121
122
|
# the C++ extension rejects the mismatched batch with a clean IOException
|
|
122
123
|
# instead of crashing inside ArrowToDuckDB.
|
|
@@ -124,8 +125,12 @@ def _table_specs() -> dict[str, pa.Schema]:
|
|
|
124
125
|
}
|
|
125
126
|
|
|
126
127
|
|
|
127
|
-
def
|
|
128
|
-
|
|
128
|
+
def _table_result_mode(name: str) -> str:
|
|
129
|
+
if name == "items_no_returning":
|
|
130
|
+
return "count"
|
|
131
|
+
if name == "items_broken_returning":
|
|
132
|
+
return "rows"
|
|
133
|
+
return "changes"
|
|
129
134
|
|
|
130
135
|
|
|
131
136
|
def _table_supports_update_delete(name: str) -> bool:
|
|
@@ -224,20 +229,25 @@ def _attach_opaque_data_from_process(params: ProcessParams[None]) -> bytes:
|
|
|
224
229
|
return bytes(aid)
|
|
225
230
|
|
|
226
231
|
|
|
227
|
-
def _parse_write_options(params: BindParams[None]) -> dict[str, Any]:
|
|
232
|
+
def _parse_write_options(params: BindParams[None] | ProcessParams[None]) -> dict[str, Any]:
|
|
228
233
|
"""Decode the write_options batch passed in named arguments."""
|
|
229
|
-
defaults: dict[str, Any] = {"
|
|
230
|
-
if
|
|
234
|
+
defaults: dict[str, Any] = {"result_mode": "count", "on_conflict": "throw", "on_conflict_columns": []}
|
|
235
|
+
if isinstance(params, BindParams):
|
|
236
|
+
bind_call = params.bind_call
|
|
237
|
+
else:
|
|
238
|
+
assert params.init_call is not None
|
|
239
|
+
bind_call = params.init_call.bind_call
|
|
240
|
+
if not (bind_call.arguments and bind_call.arguments.named):
|
|
231
241
|
return defaults
|
|
232
|
-
val =
|
|
242
|
+
val = bind_call.arguments.named.get("write_options")
|
|
233
243
|
if val is None:
|
|
234
244
|
return defaults
|
|
235
245
|
from vgi_rpc.utils import deserialize_record_batch
|
|
236
246
|
|
|
237
247
|
batch, _ = deserialize_record_batch(val.as_py())
|
|
238
248
|
out = dict(defaults)
|
|
239
|
-
if "
|
|
240
|
-
out["
|
|
249
|
+
if "result_mode" in batch.schema.names:
|
|
250
|
+
out["result_mode"] = coerce_write_result_mode(batch.column("result_mode")[0].as_py())
|
|
241
251
|
if "on_conflict" in batch.schema.names:
|
|
242
252
|
out["on_conflict"] = batch.column("on_conflict")[0].as_py()
|
|
243
253
|
if "on_conflict_columns" in batch.schema.names:
|
|
@@ -245,6 +255,26 @@ def _parse_write_options(params: BindParams[None]) -> dict[str, Any]:
|
|
|
245
255
|
return out
|
|
246
256
|
|
|
247
257
|
|
|
258
|
+
def _emit_changes(
|
|
259
|
+
out: OutputCollector,
|
|
260
|
+
table_schema: pa.Schema,
|
|
261
|
+
old_rows: Sequence[tuple[Any, ...] | None],
|
|
262
|
+
new_rows: Sequence[tuple[Any, ...] | None],
|
|
263
|
+
) -> None:
|
|
264
|
+
names = table_schema.names
|
|
265
|
+
|
|
266
|
+
def as_struct(row: tuple[Any, ...] | None) -> dict[str, Any] | None:
|
|
267
|
+
return None if row is None else dict(zip(names, row, strict=True))
|
|
268
|
+
|
|
269
|
+
out.emit(
|
|
270
|
+
write_changes_batch(
|
|
271
|
+
table_schema,
|
|
272
|
+
[as_struct(row) for row in old_rows],
|
|
273
|
+
[as_struct(row) for row in new_rows],
|
|
274
|
+
)
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
|
|
248
278
|
def _user_schema_from_bind(params: BindParams[None]) -> pa.Schema:
|
|
249
279
|
qualified = _qualified_from_bind(params)
|
|
250
280
|
return _get_user_schema(qualified)
|
|
@@ -329,9 +359,8 @@ class SimpleInsert(TableInOutGenerator[None, None]):
|
|
|
329
359
|
@classmethod
|
|
330
360
|
def on_bind(cls, params: BindParams[None]) -> BindResponse:
|
|
331
361
|
opts = _parse_write_options(params)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
return BindResponse(output_schema=_COUNT_SCHEMA)
|
|
362
|
+
mode = opts["result_mode"]
|
|
363
|
+
return BindResponse(output_schema=write_result_schema(mode, _user_schema_from_bind(params)))
|
|
335
364
|
|
|
336
365
|
@classmethod
|
|
337
366
|
def process(
|
|
@@ -345,7 +374,7 @@ class SimpleInsert(TableInOutGenerator[None, None]):
|
|
|
345
374
|
attach_opaque_data = _attach_opaque_data_from_process(params)
|
|
346
375
|
bare = _bare_name(qualified)
|
|
347
376
|
user_schema = _get_user_schema(qualified)
|
|
348
|
-
|
|
377
|
+
result_mode: WriteResultMode = _parse_write_options(params)["result_mode"]
|
|
349
378
|
|
|
350
379
|
col_names = [f.name for f in user_schema]
|
|
351
380
|
cols_sql = ", ".join(f'"{c}"' for c in col_names)
|
|
@@ -362,12 +391,14 @@ class SimpleInsert(TableInOutGenerator[None, None]):
|
|
|
362
391
|
)
|
|
363
392
|
conn.execute("COMMIT")
|
|
364
393
|
|
|
365
|
-
if
|
|
394
|
+
if result_mode == "rows":
|
|
366
395
|
out_cols: dict[str, list[Any]] = {c: [] for c in col_names}
|
|
367
396
|
for row in rows_to_insert:
|
|
368
397
|
for c, v in zip(col_names, row, strict=True):
|
|
369
398
|
out_cols[c].append(v)
|
|
370
399
|
out.emit(pa.RecordBatch.from_pydict(out_cols, schema=user_schema))
|
|
400
|
+
elif result_mode == "changes":
|
|
401
|
+
_emit_changes(out, user_schema, [None] * len(rows_to_insert), rows_to_insert)
|
|
371
402
|
else:
|
|
372
403
|
out.emit(pa.RecordBatch.from_pydict({"count": [batch.num_rows]}, schema=_COUNT_SCHEMA))
|
|
373
404
|
|
|
@@ -381,9 +412,8 @@ class SimpleUpdate(TableInOutGenerator[None, None]):
|
|
|
381
412
|
@classmethod
|
|
382
413
|
def on_bind(cls, params: BindParams[None]) -> BindResponse:
|
|
383
414
|
opts = _parse_write_options(params)
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
return BindResponse(output_schema=_COUNT_SCHEMA)
|
|
415
|
+
mode = opts["result_mode"]
|
|
416
|
+
return BindResponse(output_schema=write_result_schema(mode, _user_schema_from_bind(params)))
|
|
387
417
|
|
|
388
418
|
@classmethod
|
|
389
419
|
def process(
|
|
@@ -397,7 +427,7 @@ class SimpleUpdate(TableInOutGenerator[None, None]):
|
|
|
397
427
|
attach_opaque_data = _attach_opaque_data_from_process(params)
|
|
398
428
|
bare = _bare_name(qualified)
|
|
399
429
|
user_schema = _get_user_schema(qualified)
|
|
400
|
-
|
|
430
|
+
result_mode: WriteResultMode = _parse_write_options(params)["result_mode"]
|
|
401
431
|
|
|
402
432
|
update_cols = [n for n in batch.schema.names if n != "rowid"]
|
|
403
433
|
set_clause = ", ".join(f'"{c}"=?' for c in update_cols)
|
|
@@ -405,23 +435,31 @@ class SimpleUpdate(TableInOutGenerator[None, None]):
|
|
|
405
435
|
select_list = ", ".join(f'"{c}"' for c in user_col_names)
|
|
406
436
|
|
|
407
437
|
rowid_col = batch.column("rowid")
|
|
438
|
+
old_rows: list[tuple[Any, ...]] = []
|
|
408
439
|
updated: list[tuple[Any, ...]] = []
|
|
409
440
|
with _connect(attach_opaque_data) as conn:
|
|
410
441
|
conn.execute("BEGIN")
|
|
411
442
|
for i in range(batch.num_rows):
|
|
412
443
|
rowid = rowid_col[i].as_py()
|
|
444
|
+
old_row = conn.execute(f'SELECT {select_list} FROM "{bare}" WHERE rowid=?', (rowid,)).fetchone()
|
|
445
|
+
if old_row is None:
|
|
446
|
+
conn.execute("ROLLBACK")
|
|
447
|
+
raise ValueError(f"Update target rowid {rowid} not in table {qualified}")
|
|
413
448
|
values = tuple(batch.column(c)[i].as_py() for c in update_cols)
|
|
414
449
|
cur = conn.execute(f'UPDATE "{bare}" SET {set_clause} WHERE rowid=?', (*values, rowid))
|
|
415
450
|
if cur.rowcount == 0:
|
|
416
451
|
conn.execute("ROLLBACK")
|
|
417
452
|
raise ValueError(f"Update target rowid {rowid} not in table {qualified}")
|
|
418
453
|
row = conn.execute(f'SELECT {select_list} FROM "{bare}" WHERE rowid=?', (rowid,)).fetchone()
|
|
454
|
+
old_rows.append(old_row)
|
|
419
455
|
updated.append(row)
|
|
420
456
|
conn.execute("COMMIT")
|
|
421
457
|
|
|
422
|
-
if
|
|
458
|
+
if result_mode == "rows":
|
|
423
459
|
cols = {c: [row[i] for row in updated] for i, c in enumerate(user_col_names)}
|
|
424
460
|
out.emit(pa.RecordBatch.from_pydict(cols, schema=user_schema))
|
|
461
|
+
elif result_mode == "changes":
|
|
462
|
+
_emit_changes(out, user_schema, old_rows, updated)
|
|
425
463
|
else:
|
|
426
464
|
out.emit(pa.RecordBatch.from_pydict({"count": [batch.num_rows]}, schema=_COUNT_SCHEMA))
|
|
427
465
|
|
|
@@ -435,9 +473,8 @@ class SimpleDelete(TableInOutGenerator[None, None]):
|
|
|
435
473
|
@classmethod
|
|
436
474
|
def on_bind(cls, params: BindParams[None]) -> BindResponse:
|
|
437
475
|
opts = _parse_write_options(params)
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
return BindResponse(output_schema=_COUNT_SCHEMA)
|
|
476
|
+
mode = opts["result_mode"]
|
|
477
|
+
return BindResponse(output_schema=write_result_schema(mode, _user_schema_from_bind(params)))
|
|
441
478
|
|
|
442
479
|
@classmethod
|
|
443
480
|
def process(
|
|
@@ -451,7 +488,7 @@ class SimpleDelete(TableInOutGenerator[None, None]):
|
|
|
451
488
|
attach_opaque_data = _attach_opaque_data_from_process(params)
|
|
452
489
|
bare = _bare_name(qualified)
|
|
453
490
|
user_schema = _get_user_schema(qualified)
|
|
454
|
-
|
|
491
|
+
result_mode: WriteResultMode = _parse_write_options(params)["result_mode"]
|
|
455
492
|
|
|
456
493
|
user_col_names = [f.name for f in user_schema]
|
|
457
494
|
select_list = ", ".join(f'"{c}"' for c in user_col_names)
|
|
@@ -470,9 +507,11 @@ class SimpleDelete(TableInOutGenerator[None, None]):
|
|
|
470
507
|
deleted.append(row)
|
|
471
508
|
conn.execute("COMMIT")
|
|
472
509
|
|
|
473
|
-
if
|
|
510
|
+
if result_mode == "rows":
|
|
474
511
|
cols = {c: [row[i] for row in deleted] for i, c in enumerate(user_col_names)}
|
|
475
512
|
out.emit(pa.RecordBatch.from_pydict(cols, schema=user_schema))
|
|
513
|
+
elif result_mode == "changes":
|
|
514
|
+
_emit_changes(out, user_schema, deleted, [None] * len(deleted))
|
|
476
515
|
else:
|
|
477
516
|
out.emit(pa.RecordBatch.from_pydict({"count": [batch.num_rows]}, schema=_COUNT_SCHEMA))
|
|
478
517
|
|
|
@@ -491,7 +530,7 @@ class BrokenReturningInsert(TableInOutGenerator[None, None]):
|
|
|
491
530
|
|
|
492
531
|
@classmethod
|
|
493
532
|
def on_bind(cls, params: BindParams[None]) -> BindResponse:
|
|
494
|
-
# Always advertise the count surface, even when
|
|
533
|
+
# Always advertise the count surface, even when result_mode=rows.
|
|
495
534
|
# The C++ side will see this at bind via the worker's output schema and
|
|
496
535
|
# tries to route the responses through ArrowToDuckDB on the table-row
|
|
497
536
|
# schema — that mismatch is what we want to catch at runtime.
|
|
@@ -524,7 +563,7 @@ class BrokenReturningInsert(TableInOutGenerator[None, None]):
|
|
|
524
563
|
rows_to_insert,
|
|
525
564
|
)
|
|
526
565
|
conn.execute("COMMIT")
|
|
527
|
-
# Always emit count, regardless of
|
|
566
|
+
# Always emit count, regardless of result_mode — that's the bug.
|
|
528
567
|
out.emit(pa.RecordBatch.from_pydict({"count": [batch.num_rows]}, schema=_COUNT_SCHEMA))
|
|
529
568
|
|
|
530
569
|
|
|
@@ -619,10 +658,11 @@ class SimpleWritableCatalog(ReadOnlyCatalogInterface):
|
|
|
619
658
|
check_constraints=[],
|
|
620
659
|
primary_key_constraints=[],
|
|
621
660
|
foreign_key_constraints=[],
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
661
|
+
write_result_modes={
|
|
662
|
+
operation: _table_result_mode(name)
|
|
663
|
+
for operation, supported in (("insert", True), ("update", ud), ("delete", ud))
|
|
664
|
+
if supported
|
|
665
|
+
},
|
|
626
666
|
)
|
|
627
667
|
|
|
628
668
|
def table_get(
|