supertable 2.3.0__tar.gz → 2.3.1__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.
- {supertable-2.3.0/supertable.egg-info → supertable-2.3.1}/PKG-INFO +1 -1
- {supertable-2.3.0 → supertable-2.3.1}/pyproject.toml +1 -1
- {supertable-2.3.0 → supertable-2.3.1}/setup.py +1 -1
- {supertable-2.3.0 → supertable-2.3.1}/supertable/__init__.py +1 -1
- {supertable-2.3.0 → supertable-2.3.1}/supertable/data_reader.py +7 -1
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/spark_thrift.py +5 -1
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_data_reader.py +121 -0
- {supertable-2.3.0 → supertable-2.3.1/supertable.egg-info}/PKG-INFO +1 -1
- {supertable-2.3.0 → supertable-2.3.1}/LICENSE +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/README.md +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/requirements.txt +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/setup.cfg +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/admin.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/chain.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/consumers.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/crypto.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/events.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/export.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/logger.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/middleware.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/reader.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/retention.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/tests/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/tests/test_chain.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/tests/test_crypto.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/tests/test_emit.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/tests/test_events.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/tests/test_retention.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/writer_parquet.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/audit/writer_redis.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/config/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/config/defaults.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/config/homedir.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/config/settings.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/config/tests/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/config/tests/test_defaults.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/config/tests/test_homedir.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/config/tests/test_settings.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/data_classes.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/data_writer.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/__main__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/check_filter_builder.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/controller.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/data_writer_helpers.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/defaults.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/dummy_data.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/read_parquet_header.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s01_01_01_create_super_table.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s01_01_02_enable_mirroring_formats.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s01_02_create_roles.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s01_03_create_users.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s02_01_write_dummy_data.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s02_02_write_single_data.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s02_03_01_write_staging.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s02_03_02_create_pipe.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s02_04_01_write_monitoring_simple.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s02_04_02_write_monitoring_parallel.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s02_05_write_tombstone.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s03_01_read_data_error.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s03_02_01_read_super_data_ok.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s03_02_02_read_table_data_ok.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s03_03_read_meta.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s03_04_read_staging.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s03_06_01_read_roles.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s03_06_02_read_user.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s03_07_01_estimate_read.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s03_07_02_estimate_files.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s03_08_read_snapshot_history.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s04_01_03_delete_pipe.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s05_01_delete_table.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s05_02_delete_super_table.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/webshop/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/webshop/core.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/webshop/defaults.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/webshop/generate.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/webshop/load.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/demo/webshop/topup.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/data_estimator.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/duckdb_lite.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/duckdb_pro.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/engine_common.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/engine_config.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/engine_enum.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/executor.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/plan_stats.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/tests/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/tests/conftest.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/tests/test_engine.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/tests/test_engine_config.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/tests/test_engine_routing.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/engine/tests/test_engine_spill.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/errors.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/locking/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/locking/benchmarks/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/locking/benchmarks/benchmark_locking.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/locking/benchmarks/measure_lock_speed.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/locking/benchmarks/measure_lock_time.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/locking/file_lock.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/locking/redis_lock.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/locking/tests/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/locking/tests/test_file_lock.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/locking/tests/test_redis_lock.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/logging.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/meta_reader.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/mirroring/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/mirroring/mirror_delta.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/mirroring/mirror_formats.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/mirroring/mirror_iceberg.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/mirroring/mirror_parquet.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/monitoring/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/monitoring/partitions.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/monitoring_writer.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/plan_extender.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/processing.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/query_plan_manager.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/rbac/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/rbac/access_control.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/rbac/filter_builder.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/rbac/permissions.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/rbac/role_manager.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/rbac/row_column_security.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/rbac/tests/test_filter_builder.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/rbac/tests/test_rbac.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/rbac/tests/test_rbac_per_table.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/rbac/user_manager.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/redis_catalog.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/redis_connector.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/redis_infra.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/redis_keys.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/simple_table.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/staging_area.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/storage/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/storage/azure_storage.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/storage/gcp_storage.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/storage/local_storage.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/storage/minio_storage.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/storage/s3_storage.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/storage/storage_factory.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/storage/storage_interface.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/storage/tests/test_storage.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/super_pipe.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/super_table.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/system_query.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_align_to_schema_fix.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_create_if_missing.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_data_reader_preflight.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_data_writer.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_data_writer_compact.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_data_writer_comprehensive.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_errors.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_meta_reader.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_monitoring_partitions.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_monitoring_sink_guard.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_newer_than.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_parquet_statistics.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_processing.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_processing_compact_resources.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_processing_stats.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_query_sql.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_read_pruning_differential.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_read_pruning_integration.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_redis_key_prefix.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_simple_table.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_stats_cache.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_stats_pruning.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_stats_schema_snapshot.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_super_table.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_supertable_all.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/tests/test_system_query.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/utils/__init__.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/utils/helper.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/utils/profiler.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/utils/sql_parser.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/utils/tests/test_sql_parser_columns.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable/utils/timer.py +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable.egg-info/SOURCES.txt +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable.egg-info/dependency_links.txt +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable.egg-info/entry_points.txt +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable.egg-info/requires.txt +0 -0
- {supertable-2.3.0 → supertable-2.3.1}/supertable.egg-info/top_level.txt +0 -0
|
@@ -19,7 +19,7 @@ long_description = readme.read_text(encoding="utf-8") if readme.exists() else ""
|
|
|
19
19
|
|
|
20
20
|
setup(
|
|
21
21
|
name="supertable",
|
|
22
|
-
version="2.3.
|
|
22
|
+
version="2.3.1",
|
|
23
23
|
description="SuperTable — versioned data lake library for SQL analytics on Parquet + Redis.",
|
|
24
24
|
long_description=long_description,
|
|
25
25
|
long_description_content_type="text/markdown",
|
|
@@ -25,7 +25,7 @@ See the ``supertable.demo`` package for runnable end-to-end demos and the
|
|
|
25
25
|
project documentation for the full API surface.
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
|
-
__version__ = "2.3.
|
|
28
|
+
__version__ = "2.3.1"
|
|
29
29
|
|
|
30
30
|
# Re-export the core public surface so users can do ``from supertable import …``
|
|
31
31
|
# instead of remembering submodule paths.
|
|
@@ -314,8 +314,14 @@ class DataReader:
|
|
|
314
314
|
if isinstance(payload, dict):
|
|
315
315
|
tomb_path = payload.get("tombstone")
|
|
316
316
|
if tomb_path:
|
|
317
|
+
# Resolve the deletion-vector key exactly like the
|
|
318
|
+
# data files (estimator._to_duckdb_path, see
|
|
319
|
+
# data_estimator.py:426): the catalog stores a bare
|
|
320
|
+
# object key, which DuckDB/Spark cannot read against
|
|
321
|
+
# an object store and must be presigned. LOCAL
|
|
322
|
+
# storage returns the key unchanged.
|
|
317
323
|
reflection.tombstone_views[td.alias] = TombstoneDef(
|
|
318
|
-
tombstone_path=tomb_path,
|
|
324
|
+
tombstone_path=estimator._to_duckdb_path(tomb_path),
|
|
319
325
|
)
|
|
320
326
|
except Exception as te:
|
|
321
327
|
logger.debug(self._lp(f"[tombstone] leaf lookup failed for {td.alias}: {te}"))
|
|
@@ -239,7 +239,11 @@ def _spark_create_tombstone_view(
|
|
|
239
239
|
has_rowid = "__rowid__" in src_cols
|
|
240
240
|
|
|
241
241
|
if tomb_path and has_rowid:
|
|
242
|
-
|
|
242
|
+
# The data files are converted to s3a:// for Spark (see the data-file
|
|
243
|
+
# loop in the executor); apply the same conversion to the already
|
|
244
|
+
# resolved deletion-vector pointer so Spark reads it via its own S3A
|
|
245
|
+
# client instead of choking on a presigned HTTP URL or bare key.
|
|
246
|
+
escaped = _to_s3a_path(tomb_path).replace("'", "''")
|
|
243
247
|
sql = (
|
|
244
248
|
f"CREATE OR REPLACE TEMPORARY VIEW {view_name} AS "
|
|
245
249
|
f"SELECT {select_cols} FROM {source_table} AS src "
|
|
@@ -388,6 +388,127 @@ class TestExecuteHappyPath:
|
|
|
388
388
|
assert exec_call_kwargs[1]["engine"] == _Engine.DUCKDB_PRO or exec_call_kwargs[0][0] == _Engine.DUCKDB_PRO
|
|
389
389
|
|
|
390
390
|
|
|
391
|
+
# ====================================================================
|
|
392
|
+
# 5b. DataReader.execute — Tombstone deletion-vector path resolution
|
|
393
|
+
# ====================================================================
|
|
394
|
+
|
|
395
|
+
class TestExecuteTombstoneResolution:
|
|
396
|
+
"""Regression: the tombstone deletion-vector pointer must be resolved
|
|
397
|
+
through the SAME path as the data files (``estimator._to_duckdb_path``,
|
|
398
|
+
see data_estimator.py:426). Data files are presigned for object stores;
|
|
399
|
+
the tombstone key used to be embedded raw, so DuckDB/Spark could not read
|
|
400
|
+
it. These lock in 'if the data is presigned, the tombstone is too'.
|
|
401
|
+
"""
|
|
402
|
+
|
|
403
|
+
@patch(_PATCH_EXTEND_PLAN)
|
|
404
|
+
@patch(_PATCH_EXECUTOR)
|
|
405
|
+
@patch(_PATCH_DATA_ESTIMATOR)
|
|
406
|
+
@patch(_PATCH_QUERY_PLAN_MGR)
|
|
407
|
+
@patch(_PATCH_RESTRICT_READ)
|
|
408
|
+
@patch(_PATCH_PLAN_STATS)
|
|
409
|
+
@patch(_PATCH_TIMER)
|
|
410
|
+
@patch(_PATCH_GET_STORAGE)
|
|
411
|
+
@patch(_PATCH_SQL_PARSER)
|
|
412
|
+
def test_tombstone_pointer_resolved_through_same_resolver_as_data(
|
|
413
|
+
self, MockParser, mock_get_storage, MockTimer, MockPlanStats,
|
|
414
|
+
mock_restrict, MockQPM, MockEstimator, MockExecutor, mock_extend,
|
|
415
|
+
_mock_data_reader_redis,
|
|
416
|
+
):
|
|
417
|
+
from types import SimpleNamespace
|
|
418
|
+
|
|
419
|
+
td = SimpleNamespace(alias="t", super_name="s", simple_name="tbl")
|
|
420
|
+
mock_parser = MagicMock()
|
|
421
|
+
mock_parser.get_table_tuples.return_value = [td]
|
|
422
|
+
mock_parser.original_query = "SELECT * FROM tbl"
|
|
423
|
+
MockParser.return_value = mock_parser
|
|
424
|
+
|
|
425
|
+
mock_get_storage.return_value = MagicMock()
|
|
426
|
+
MockTimer.return_value = MagicMock(timings=[])
|
|
427
|
+
MockPlanStats.return_value = MagicMock()
|
|
428
|
+
MockQPM.return_value = MagicMock(query_id="q", query_hash="h")
|
|
429
|
+
|
|
430
|
+
# Catalog leaf carries a deletion-vector pointer (a bare object key).
|
|
431
|
+
raw_tomb_key = "o/s/tables/tbl/tombstone/123_abc_deleted.parquet"
|
|
432
|
+
_mock_data_reader_redis.return_value.get_leaf.return_value = {
|
|
433
|
+
"payload": {"tombstone": raw_tomb_key},
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
# Estimator resolver presigns (object-store behaviour) — the SAME method
|
|
437
|
+
# the estimator applies to data files at data_estimator.py:426.
|
|
438
|
+
reflection = _make_reflection()
|
|
439
|
+
mock_est = MagicMock()
|
|
440
|
+
mock_est.estimate.return_value = reflection
|
|
441
|
+
mock_est._to_duckdb_path.side_effect = lambda k: f"https://signed/{k}"
|
|
442
|
+
MockEstimator.return_value = mock_est
|
|
443
|
+
|
|
444
|
+
mock_exec = MagicMock()
|
|
445
|
+
mock_exec.execute.return_value = (pd.DataFrame(), "duckdb_pinned")
|
|
446
|
+
MockExecutor.return_value = mock_exec
|
|
447
|
+
|
|
448
|
+
from supertable.data_reader import DataReader, engine
|
|
449
|
+
dr = DataReader("s", "o", "SELECT * FROM tbl")
|
|
450
|
+
dr.execute("admin", engine=engine.AUTO)
|
|
451
|
+
|
|
452
|
+
# The raw key was routed through the resolver (not embedded as-is) ...
|
|
453
|
+
mock_est._to_duckdb_path.assert_called_once_with(raw_tomb_key)
|
|
454
|
+
# ... and the RESOLVED (presigned) value is what lands in the reflection.
|
|
455
|
+
assert "t" in reflection.tombstone_views
|
|
456
|
+
assert (
|
|
457
|
+
reflection.tombstone_views["t"].tombstone_path
|
|
458
|
+
== f"https://signed/{raw_tomb_key}"
|
|
459
|
+
)
|
|
460
|
+
|
|
461
|
+
@patch(_PATCH_EXTEND_PLAN)
|
|
462
|
+
@patch(_PATCH_EXECUTOR)
|
|
463
|
+
@patch(_PATCH_DATA_ESTIMATOR)
|
|
464
|
+
@patch(_PATCH_QUERY_PLAN_MGR)
|
|
465
|
+
@patch(_PATCH_RESTRICT_READ)
|
|
466
|
+
@patch(_PATCH_PLAN_STATS)
|
|
467
|
+
@patch(_PATCH_TIMER)
|
|
468
|
+
@patch(_PATCH_GET_STORAGE)
|
|
469
|
+
@patch(_PATCH_SQL_PARSER)
|
|
470
|
+
def test_local_storage_tombstone_left_unchanged(
|
|
471
|
+
self, MockParser, mock_get_storage, MockTimer, MockPlanStats,
|
|
472
|
+
mock_restrict, MockQPM, MockEstimator, MockExecutor, mock_extend,
|
|
473
|
+
_mock_data_reader_redis,
|
|
474
|
+
):
|
|
475
|
+
# LOCAL contract: no presign → _to_duckdb_path returns the key as-is,
|
|
476
|
+
# so the tombstone path stays readable from disk (golden-test path).
|
|
477
|
+
from types import SimpleNamespace
|
|
478
|
+
|
|
479
|
+
td = SimpleNamespace(alias="t", super_name="s", simple_name="tbl")
|
|
480
|
+
mock_parser = MagicMock()
|
|
481
|
+
mock_parser.get_table_tuples.return_value = [td]
|
|
482
|
+
mock_parser.original_query = "SELECT * FROM tbl"
|
|
483
|
+
MockParser.return_value = mock_parser
|
|
484
|
+
|
|
485
|
+
mock_get_storage.return_value = MagicMock()
|
|
486
|
+
MockTimer.return_value = MagicMock(timings=[])
|
|
487
|
+
MockPlanStats.return_value = MagicMock()
|
|
488
|
+
MockQPM.return_value = MagicMock(query_id="q", query_hash="h")
|
|
489
|
+
|
|
490
|
+
raw_tomb_key = "local/dir/tombstone/x_deleted.parquet"
|
|
491
|
+
_mock_data_reader_redis.return_value.get_leaf.return_value = {
|
|
492
|
+
"payload": {"tombstone": raw_tomb_key},
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
reflection = _make_reflection()
|
|
496
|
+
mock_est = MagicMock()
|
|
497
|
+
mock_est.estimate.return_value = reflection
|
|
498
|
+
mock_est._to_duckdb_path.side_effect = lambda k: k # LOCAL no-op
|
|
499
|
+
MockEstimator.return_value = mock_est
|
|
500
|
+
|
|
501
|
+
mock_exec = MagicMock()
|
|
502
|
+
mock_exec.execute.return_value = (pd.DataFrame(), "duckdb_pinned")
|
|
503
|
+
MockExecutor.return_value = mock_exec
|
|
504
|
+
|
|
505
|
+
from supertable.data_reader import DataReader, engine
|
|
506
|
+
dr = DataReader("s", "o", "SELECT * FROM tbl")
|
|
507
|
+
dr.execute("admin", engine=engine.AUTO)
|
|
508
|
+
|
|
509
|
+
assert reflection.tombstone_views["t"].tombstone_path == raw_tomb_key
|
|
510
|
+
|
|
511
|
+
|
|
391
512
|
# ====================================================================
|
|
392
513
|
# 6. DataReader.execute — RBAC Failure
|
|
393
514
|
# ====================================================================
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s01_01_01_create_super_table.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s02_02_write_single_data.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s03_02_01_read_super_data_ok.py
RENAMED
|
File without changes
|
{supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s03_02_02_read_table_data_ok.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s03_07_02_estimate_files.py
RENAMED
|
File without changes
|
{supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s03_08_read_snapshot_history.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{supertable-2.3.0 → supertable-2.3.1}/supertable/demo/quickstart/s05_02_delete_super_table.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|