mainsequence 4.3.30__tar.gz → 4.4.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.
Files changed (138) hide show
  1. {mainsequence-4.3.30/mainsequence.egg-info → mainsequence-4.4.1}/PKG-INFO +1 -1
  2. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/cli.py +15 -16
  3. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/metatables/core.py +65 -32
  4. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/__init__.py +4 -0
  5. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/data_nodes/data_nodes.py +23 -11
  6. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/data_nodes/persist_managers.py +10 -10
  7. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/data_nodes/run_operations.py +20 -19
  8. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/migrations/__init__.py +0 -12
  9. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/sqlalchemy_contracts.py +65 -113
  10. {mainsequence-4.3.30 → mainsequence-4.4.1/mainsequence.egg-info}/PKG-INFO +1 -1
  11. {mainsequence-4.3.30 → mainsequence-4.4.1}/pyproject.toml +1 -1
  12. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_cli.py +38 -36
  13. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_data_access_mixin_dimension_audit.py +5 -5
  14. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_meta_table_migrations.py +3 -15
  15. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_meta_tables_client_models.py +21 -6
  16. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_meta_tables_sqlalchemy_contracts.py +44 -22
  17. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_run_configuration.py +18 -13
  18. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_update_runner_uid_runtime.py +3 -3
  19. {mainsequence-4.3.30 → mainsequence-4.4.1}/LICENSE +0 -0
  20. {mainsequence-4.3.30 → mainsequence-4.4.1}/README.md +0 -0
  21. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/AGENTS.md +0 -0
  22. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/a2a_communication/SKILL.md +0 -0
  23. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
  24. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/command_center/adapter_from_api/SKILL.md +0 -0
  25. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/command_center/api_mock_prototyping/SKILL.md +0 -0
  26. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/command_center/app_components/SKILL.md +0 -0
  27. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/command_center/connections/SKILL.md +0 -0
  28. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/command_center/workspace_analysis/SKILL.md +0 -0
  29. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/command_center/workspace_builder/SKILL.md +0 -0
  30. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/command_center/workspace_design/SKILL.md +0 -0
  31. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/dashboards/streamlit/SKILL.md +0 -0
  32. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
  33. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
  34. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
  35. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
  36. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  37. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/ms-markets/SKILL.md +0 -0
  38. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  39. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
  40. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/project_builder/SKILL.md +0 -0
  41. {mainsequence-4.3.30 → mainsequence-4.4.1}/agent_scaffold/skills/project_to_agent/SKILL.md +0 -0
  42. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/__init__.py +0 -0
  43. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/__main__.py +0 -0
  44. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/bootstrap.py +0 -0
  45. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/__init__.py +0 -0
  46. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/api.py +0 -0
  47. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/browser_auth.py +0 -0
  48. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/config.py +0 -0
  49. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/docker_utils.py +0 -0
  50. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/doctor.py +0 -0
  51. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/local_ops.py +0 -0
  52. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/migrations.py +0 -0
  53. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/model_filters.py +0 -0
  54. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/project_status.py +0 -0
  55. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/pydantic_cli.py +0 -0
  56. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/sdk_utils.py +0 -0
  57. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/ssh_utils.py +0 -0
  58. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/cli/ui.py +0 -0
  59. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/__init__.py +0 -0
  60. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/agent_runtime_models.py +0 -0
  61. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/base.py +0 -0
  62. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/client.py +0 -0
  63. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/command_center/__init__.py +0 -0
  64. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/command_center/app_component.py +0 -0
  65. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/command_center/connections.py +0 -0
  66. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/command_center/data_models.py +0 -0
  67. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/command_center/workspace.py +0 -0
  68. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/command_center/workspace_snapshot.py +0 -0
  69. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/compute_validation.py +0 -0
  70. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
  71. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
  72. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
  73. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
  74. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/dtype_codec.py +0 -0
  75. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/exceptions.py +0 -0
  76. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/fastapi/__init__.py +0 -0
  77. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/fastapi/auth.py +0 -0
  78. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/metatables/__init__.py +0 -0
  79. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/models_foundry.py +0 -0
  80. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/models_helpers.py +0 -0
  81. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/models_user.py +0 -0
  82. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/client/utils.py +0 -0
  83. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/defaults.py +0 -0
  84. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/instrumentation/__init__.py +0 -0
  85. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/instrumentation/utils.py +0 -0
  86. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/logconf.py +0 -0
  87. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/__main__.py +0 -0
  88. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
  89. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
  90. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
  91. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
  92. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/data_nodes/models.py +0 -0
  93. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
  94. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
  95. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/future_registry.py +0 -0
  96. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/hashing.py +0 -0
  97. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/migrations/alembic.py +0 -0
  98. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/migrations/env.py +0 -0
  99. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/migrations/provider.py +0 -0
  100. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/migrations/registry.py +0 -0
  101. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
  102. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
  103. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
  104. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
  105. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
  106. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/meta_tables/schema_names.py +0 -0
  107. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence/runtime_flags.py +0 -0
  108. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence.egg-info/SOURCES.txt +0 -0
  109. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence.egg-info/dependency_links.txt +0 -0
  110. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence.egg-info/entry_points.txt +0 -0
  111. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence.egg-info/requires.txt +0 -0
  112. {mainsequence-4.3.30 → mainsequence-4.4.1}/mainsequence.egg-info/top_level.txt +0 -0
  113. {mainsequence-4.3.30 → mainsequence-4.4.1}/setup.cfg +0 -0
  114. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_auth_precedence.py +0 -0
  115. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_build_operations_hashing.py +0 -0
  116. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_cli_browser_auth.py +0 -0
  117. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_cli_migrations.py +0 -0
  118. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_client.py +0 -0
  119. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_command_center_app_component_models.py +0 -0
  120. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_command_center_data_models.py +0 -0
  121. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_command_center_models.py +0 -0
  122. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_data_node_storage_dimension_queries.py +0 -0
  123. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_data_node_update_flow.py +0 -0
  124. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_dependency_extras.py +0 -0
  125. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_duckdb_interface_dimensions.py +0 -0
  126. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_filter_normalization.py +0 -0
  127. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_instrumentation.py +0 -0
  128. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_logconf.py +0 -0
  129. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_models_user_request_bound_auth.py +0 -0
  130. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_pod_project_resolution.py +0 -0
  131. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_project_batch_jobs_from_file.py +0 -0
  132. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_schema_names.py +0 -0
  133. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_secret_client_model.py +0 -0
  134. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_source_table_configuration.py +0 -0
  135. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_sqlite_interface_dimensions.py +0 -0
  136. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_update_statistics.py +0 -0
  137. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_update_uid_guards.py +0 -0
  138. {mainsequence-4.3.30 → mainsequence-4.4.1}/tests/test_workspace_snapshot.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 4.3.30
3
+ Version: 4.4.1
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License: MainSequence GmbH SDK License Agreement
@@ -1489,7 +1489,7 @@ def _require_delete_verification(
1489
1489
  def _format_data_node_storage_delete_preview(storage: dict[str, object]) -> list[tuple[str, str]]:
1490
1490
  return [
1491
1491
  ("UID", str(storage.get("uid") or "-")),
1492
- ("Storage Hash", str(storage.get("storage_hash") or "-")),
1492
+ ("Physical Table", str(storage.get("physical_table_name") or "-")),
1493
1493
  ("Identifier", str(storage.get("identifier") or "-")),
1494
1494
  ("Source Class", str(storage.get("source_class_name") or "-")),
1495
1495
  ("Data Source", _format_data_node_storage_data_source(storage.get("data_source"))),
@@ -1500,7 +1500,6 @@ def _format_data_node_storage_delete_preview(storage: dict[str, object]) -> list
1500
1500
  def _format_meta_table_delete_preview(meta_table: dict[str, object]) -> list[tuple[str, str]]:
1501
1501
  return [
1502
1502
  ("UID", str(meta_table.get("uid") or "-")),
1503
- ("Storage Hash", str(meta_table.get("storage_hash") or "-")),
1504
1503
  ("Identifier", str(meta_table.get("identifier") or "-")),
1505
1504
  ("Namespace", str(meta_table.get("namespace") or "-")),
1506
1505
  ("Physical Table", str(meta_table.get("physical_table_name") or "-")),
@@ -5372,7 +5371,6 @@ def _data_node_storage_list_impl(
5372
5371
  "Data Node Storages",
5373
5372
  [
5374
5373
  "UID",
5375
- "Storage Hash",
5376
5374
  "Physical Table",
5377
5375
  "Source Class",
5378
5376
  "Identifier",
@@ -5420,7 +5418,6 @@ def _meta_table_list_impl(
5420
5418
  "MetaTables",
5421
5419
  [
5422
5420
  "UID",
5423
- "Storage Hash",
5424
5421
  "Physical Table",
5425
5422
  "Identifier",
5426
5423
  "Namespace",
@@ -5440,7 +5437,6 @@ def _build_data_node_storage_rows(storages: list[dict[str, object]]) -> list[lis
5440
5437
  rows.append(
5441
5438
  [
5442
5439
  str(storage.get("uid") or "-"),
5443
- str(storage.get("storage_hash") or "-"),
5444
5440
  str(storage.get("physical_table_name") or "-"),
5445
5441
  str(storage.get("source_class_name") or "-"),
5446
5442
  str(storage.get("identifier") or "-"),
@@ -5457,7 +5453,6 @@ def _build_meta_table_rows(meta_tables: list[dict[str, object]]) -> list[list[st
5457
5453
  rows.append(
5458
5454
  [
5459
5455
  str(meta_table.get("uid") or "-"),
5460
- str(meta_table.get("storage_hash") or "-"),
5461
5456
  str(meta_table.get("physical_table_name") or "-"),
5462
5457
  str(meta_table.get("identifier") or "-"),
5463
5458
  str(meta_table.get("namespace") or "-"),
@@ -5536,7 +5531,6 @@ def _data_node_storage_search_impl(
5536
5531
  title,
5537
5532
  [
5538
5533
  "UID",
5539
- "Storage Hash",
5540
5534
  "Physical Table",
5541
5535
  "Source Class",
5542
5536
  "Identifier",
@@ -5575,7 +5569,6 @@ def _print_data_node_storage_search_section(
5575
5569
  title,
5576
5570
  [
5577
5571
  "UID",
5578
- "Storage Hash",
5579
5572
  "Physical Table",
5580
5573
  "Source Class",
5581
5574
  "Identifier",
@@ -6976,7 +6969,6 @@ def _data_node_storage_detail_impl(storage_uid: str, timeout: int | None) -> Non
6976
6969
  "Data Node Storage",
6977
6970
  [
6978
6971
  ("UID", str(storage.get("uid") or storage_uid)),
6979
- ("Storage Hash", str(storage.get("storage_hash") or "-")),
6980
6972
  ("Physical Table", str(storage.get("physical_table_name") or "-")),
6981
6973
  ("Identifier", str(storage.get("identifier") or "-")),
6982
6974
  ("Source Class", str(storage.get("source_class_name") or "-")),
@@ -7018,7 +7010,6 @@ def _meta_table_detail_impl(meta_table_uid: str, timeout: int | None) -> None:
7018
7010
  "MetaTable",
7019
7011
  [
7020
7012
  ("UID", str(meta_table.get("uid") or meta_table_uid)),
7021
- ("Storage Hash", str(meta_table.get("storage_hash") or "-")),
7022
7013
  ("Physical Table", str(meta_table.get("physical_table_name") or "-")),
7023
7014
  ("Identifier", str(meta_table.get("identifier") or "-")),
7024
7015
  ("Namespace", str(meta_table.get("namespace") or "-")),
@@ -7089,7 +7080,12 @@ def _data_node_storage_delete_impl(
7089
7080
  error(f"Data node storage fetch failed: {e}")
7090
7081
  raise typer.Exit(1) from e
7091
7082
 
7092
- verification_value = str(storage.get("storage_hash") or storage.get("uid") or storage_uid)
7083
+ verification_value = str(
7084
+ storage.get("physical_table_name") or storage.get("uid") or storage_uid
7085
+ )
7086
+ verification_label = (
7087
+ "physical table name" if storage.get("physical_table_name") else "storage uid"
7088
+ )
7093
7089
  _require_delete_verification(
7094
7090
  preview_title="Data Node Storage Delete Preview",
7095
7091
  preview_items=_format_data_node_storage_delete_preview(storage)
@@ -7100,7 +7096,7 @@ def _data_node_storage_delete_impl(
7100
7096
  ("override_protection", str(override_protection).lower()),
7101
7097
  ],
7102
7098
  verification_value=verification_value,
7103
- verification_label="storage hash" if storage.get("storage_hash") else "storage uid",
7099
+ verification_label=verification_label,
7104
7100
  )
7105
7101
 
7106
7102
  try:
@@ -7137,13 +7133,16 @@ def _meta_table_delete_impl(
7137
7133
  raise typer.Exit(1) from e
7138
7134
 
7139
7135
  verification_value = str(
7140
- meta_table.get("storage_hash") or meta_table.get("uid") or meta_table_uid
7136
+ meta_table.get("physical_table_name") or meta_table.get("uid") or meta_table_uid
7137
+ )
7138
+ verification_label = (
7139
+ "physical table name" if meta_table.get("physical_table_name") else "MetaTable uid"
7141
7140
  )
7142
7141
  _require_delete_verification(
7143
7142
  preview_title="MetaTable Delete Preview",
7144
7143
  preview_items=_format_meta_table_delete_preview(meta_table),
7145
7144
  verification_value=verification_value,
7146
- verification_label="storage hash" if meta_table.get("storage_hash") else "MetaTable uid",
7145
+ verification_label=verification_label,
7147
7146
  )
7148
7147
 
7149
7148
  try:
@@ -7775,7 +7774,7 @@ def data_node_storage_column_search_cmd(
7775
7774
  --------
7776
7775
  ```bash
7777
7776
  mainsequence data-node column-search weight
7778
- mainsequence data-node column-search close --filter storage_hash__contains=weights
7777
+ mainsequence data-node column-search close --filter physical_table_name__contains=weights
7779
7778
  ```
7780
7779
  """
7781
7780
  filters = _resolve_cli_list_filters(
@@ -8247,7 +8246,7 @@ def _print_project_data_node_updates(
8247
8246
  storage = u.get("data_node_storage")
8248
8247
  if isinstance(storage, dict):
8249
8248
  storage_value = (
8250
- storage.get("storage_hash") or storage.get("uid") or storage.get("id") or "-"
8249
+ storage.get("physical_table_name") or storage.get("uid") or storage.get("id") or "-"
8251
8250
  )
8252
8251
  else:
8253
8252
  storage_value = storage if storage is not None else "-"
@@ -95,6 +95,13 @@ def _local_data_interface(class_type: str):
95
95
  raise ValueError(f"Unsupported local data source class_type: {class_type!r}")
96
96
 
97
97
 
98
+ def _storage_physical_table_name(storage: Any) -> str:
99
+ table_name = getattr(storage, "physical_table_name", None)
100
+ if table_name not in (None, ""):
101
+ return str(table_name)
102
+ raise ValueError("MetaTable local storage operations require physical_table_name.")
103
+
104
+
98
105
  def _storage_time_indexed_contract(storage: Any) -> tuple[str, list[str], dict[str, Any]]:
99
106
  if hasattr(storage, "_require_time_indexed_table_contract"):
100
107
  return storage._require_time_indexed_table_contract()
@@ -401,9 +408,9 @@ class MetaTableForeignKeyPayload(BasePydanticModel):
401
408
  None,
402
409
  description="Public UID of the target MetaTable.",
403
410
  )
404
- target_table_storage_hash: str | None = Field(
411
+ target_table_physical_table_name: str | None = Field(
405
412
  None,
406
- description="Storage hash of the target MetaTable.",
413
+ description="Physical table name of the target MetaTable.",
407
414
  )
408
415
  target_columns: list[str] = Field(
409
416
  default_factory=list,
@@ -415,6 +422,15 @@ class MetaTableForeignKeyPayload(BasePydanticModel):
415
422
  description="Raw normalized contract fragment for this projected foreign key.",
416
423
  )
417
424
 
425
+ @model_validator(mode="before")
426
+ @classmethod
427
+ def _strip_legacy_storage_hash(cls, value: Any) -> Any:
428
+ if isinstance(value, Mapping):
429
+ data = dict(value)
430
+ data.pop("target_table_storage_hash", None)
431
+ return data
432
+ return value
433
+
418
434
 
419
435
  class MetaTableStatementPayload(BasePydanticModel):
420
436
  sql: str = Field(..., min_length=1)
@@ -533,7 +549,6 @@ class MetaTableRequestFields(BasePydanticModel):
533
549
  ...,
534
550
  description="Public UID of the DynamicTableDataSource that owns this MetaTable.",
535
551
  )
536
- storage_hash: str = Field(..., max_length=63, description="Canonical table storage hash.")
537
552
  table_contract: MetaTableContract | dict[str, Any]
538
553
  identifier: str | None = Field(
539
554
  default=None,
@@ -561,6 +576,15 @@ class MetaTableRequestFields(BasePydanticModel):
561
576
  self.table_contract = _normalize_contract_mapping(self.table_contract)
562
577
  return self
563
578
 
579
+ @model_validator(mode="before")
580
+ @classmethod
581
+ def _strip_legacy_storage_hash(cls, value: Any) -> Any:
582
+ if isinstance(value, Mapping):
583
+ data = dict(value)
584
+ data.pop("storage_hash", None)
585
+ return data
586
+ return value
587
+
564
588
 
565
589
  class MetaTableRegistrationRequest(MetaTableRequestFields):
566
590
  management_mode: MetaTableManagementMode
@@ -571,7 +595,15 @@ class MetaTableRegistrationRequest(MetaTableRequestFields):
571
595
  class MetaTableValidateContractRequest(BasePydanticModel):
572
596
  table_contract: MetaTableContract | dict[str, Any]
573
597
  management_mode: MetaTableManagementMode | None = None
574
- storage_hash: str | None = None
598
+
599
+ @model_validator(mode="before")
600
+ @classmethod
601
+ def _strip_legacy_storage_hash(cls, value: Any) -> Any:
602
+ if isinstance(value, Mapping):
603
+ data = dict(value)
604
+ data.pop("storage_hash", None)
605
+ return data
606
+ return value
575
607
 
576
608
  @model_validator(mode="after")
577
609
  def _normalize_table_contract(self) -> MetaTableValidateContractRequest:
@@ -676,7 +708,6 @@ class ManagedMetaTableFinalizeTableResult(BasePydanticModel):
676
708
  None,
677
709
  description="Organization-global logical MetaTable identifier, when present.",
678
710
  )
679
- storage_hash: str = Field(..., description="Canonical MetaTable storage hash.")
680
711
  physical_table_name: str | None = Field(
681
712
  None,
682
713
  description="Physical table name reconciled against the data source.",
@@ -729,7 +760,14 @@ class ManagedMetaTableFinalizeTableResult(BasePydanticModel):
729
760
  def _normalize_cadence(cls, value: str | None) -> str | None:
730
761
  return _normalize_time_indexed_cadence(value)
731
762
 
732
- model_config = ConfigDict(extra="ignore")
763
+ @model_validator(mode="before")
764
+ @classmethod
765
+ def _strip_legacy_storage_hash(cls, value: Any) -> Any:
766
+ if isinstance(value, Mapping):
767
+ data = dict(value)
768
+ data.pop("storage_hash", None)
769
+ return data
770
+ return value
733
771
 
734
772
 
735
773
  class ManagedMetaTableFinalizeResponse(BasePydanticModel):
@@ -847,7 +885,7 @@ class DataSource(BasePydanticModel, BaseObjectOrm):
847
885
  storage = data_node_update.data_node_storage
848
886
  _local_data_interface(self.class_type).upsert(
849
887
  df=serialized_data_frame,
850
- table=getattr(storage, "physical_table_name", None) or storage.storage_hash,
888
+ table=_storage_physical_table_name(storage),
851
889
  index_names=index_names,
852
890
  time_index_name=time_index_name,
853
891
  )
@@ -888,7 +926,7 @@ class DataSource(BasePydanticModel, BaseObjectOrm):
888
926
  if self.class_type in LOCAL_DATA_SOURCE_CLASS_TYPES:
889
927
  db_interface = _local_data_interface(self.class_type)
890
928
  storage = data_node_update.data_node_storage
891
- table_name = getattr(storage, "physical_table_name", None) or storage.storage_hash
929
+ table_name = _storage_physical_table_name(storage)
892
930
  time_index_name, index_names, _ = _storage_time_indexed_contract(storage)
893
931
 
894
932
  adjusted_start, adjusted_end, adjusted_dimension_range_map, _ = (
@@ -964,9 +1002,7 @@ class DataSource(BasePydanticModel, BaseObjectOrm):
964
1002
  if self.class_type in LOCAL_DATA_SOURCE_CLASS_TYPES:
965
1003
  db_interface = _local_data_interface(self.class_type)
966
1004
  storage = data_node_update.data_node_storage
967
- table_name = getattr(storage, "physical_table_name", None) or getattr(
968
- storage, "storage_hash", None
969
- )
1005
+ table_name = _storage_physical_table_name(storage)
970
1006
  time_index_name, index_names, _ = _storage_time_indexed_contract(storage)
971
1007
  return db_interface.time_index_minima(
972
1008
  table=table_name,
@@ -1133,7 +1169,6 @@ class DynamicTableDataSource(BasePydanticModel, BaseObjectOrm):
1133
1169
  class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, BaseObjectOrm):
1134
1170
  ENDPOINT: ClassVar[str] = "ts_manager/meta_table"
1135
1171
  FILTERSET_FIELDS: ClassVar[dict[str, list[str]]] = {
1136
- "storage_hash": ["in", "exact", "contains"],
1137
1172
  "identifier": ["in", "exact", "contains"],
1138
1173
  "uid": ["in", "exact"],
1139
1174
  "data_source__uid": ["in", "exact"],
@@ -1177,7 +1212,6 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
1177
1212
  uid: str | None = Field(None, description="Public uid of this MetaTable.")
1178
1213
  data_source: int | DynamicTableDataSource | dict[str, Any] | None = None
1179
1214
  data_source_uid: str | None = None
1180
- storage_hash: str = Field(..., max_length=63, description="Canonical table storage hash.")
1181
1215
  identifier: str | None = Field(
1182
1216
  default=None,
1183
1217
  description=(
@@ -1215,6 +1249,15 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
1215
1249
 
1216
1250
  model_config = ConfigDict(populate_by_name=True)
1217
1251
 
1252
+ @model_validator(mode="before")
1253
+ @classmethod
1254
+ def _strip_legacy_storage_hash(cls, value: Any) -> Any:
1255
+ if isinstance(value, Mapping):
1256
+ data = dict(value)
1257
+ data.pop("storage_hash", None)
1258
+ return data
1259
+ return value
1260
+
1218
1261
  def _public_uid(self) -> str:
1219
1262
  if self.uid in (None, ""):
1220
1263
  raise ValueError("MetaTable must have a uid before calling this endpoint.")
@@ -1339,11 +1382,6 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
1339
1382
  raise_for_response(response, payload=payload)
1340
1383
  return type(self)(**response.json())
1341
1384
 
1342
- @classmethod
1343
- def patch_by_hash(cls, storage_hash: str, *args, **kwargs):
1344
- metadata = cls.get(storage_hash=storage_hash)
1345
- return metadata.patch(*args, **kwargs)
1346
-
1347
1385
  @classmethod
1348
1386
  def destroy_by_uid(
1349
1387
  cls,
@@ -1819,7 +1857,7 @@ class UpdateNodeRef(TypedDict):
1819
1857
  uid: str
1820
1858
  node_type: str
1821
1859
  update_hash: str
1822
- remote_table_hash_id: str
1860
+ physical_table_name: str | None
1823
1861
 
1824
1862
 
1825
1863
  def _require_public_uid(obj: Any, object_name: str) -> str:
@@ -1872,11 +1910,6 @@ class TimeIndexMetaTableRegistrationRequest(BasePydanticModel):
1872
1910
  model_config = ConfigDict(extra="forbid")
1873
1911
 
1874
1912
  data_source_uid: str = Field(..., description="Public uid of the storage data source")
1875
- storage_hash: str = Field(
1876
- ...,
1877
- max_length=63,
1878
- description="Canonical logical storage identity for the time-indexed MetaTable",
1879
- )
1880
1913
  identifier: str | None = Field(
1881
1914
  None,
1882
1915
  description=(
@@ -1923,6 +1956,7 @@ class TimeIndexMetaTableRegistrationRequest(BasePydanticModel):
1923
1956
  if not isinstance(value, Mapping):
1924
1957
  return value
1925
1958
  data = dict(value)
1959
+ data.pop("storage_hash", None)
1926
1960
  forbidden = [
1927
1961
  field
1928
1962
  for field in ("columns", "index_names", "foreign_keys", "storage_layout")
@@ -2463,11 +2497,11 @@ class DataNodeUpdate(TableUpdateNode, BaseObjectOrm):
2463
2497
  return r.json()
2464
2498
 
2465
2499
  @classmethod
2466
- def get_upstream_nodes(cls, storage_hash, data_source_uid, timeout=None):
2500
+ def get_upstream_nodes(cls, table_name, data_source_uid, timeout=None):
2467
2501
  s = cls.build_session()
2468
2502
  url = (
2469
2503
  cls.get_object_url("DataNode")
2470
- + f"/{storage_hash}/get_upstream_nodes?data_source_uid={data_source_uid}"
2504
+ + f"/{table_name}/get_upstream_nodes?data_source_uid={data_source_uid}"
2471
2505
  )
2472
2506
  r = make_request(s=s, loaders=cls.LOADERS, r_type="GET", url=url, time_out=timeout)
2473
2507
  if r.status_code != 200:
@@ -2952,7 +2986,6 @@ class TableMetaData(BaseModel):
2952
2986
  class TimeIndexMetaTable(MetaTable):
2953
2987
  ENDPOINT: ClassVar[str] = "ts_manager/dynamic_table"
2954
2988
  FILTERSET_FIELDS: ClassVar[dict[str, list[str]]] = {
2955
- "storage_hash": ["in", "exact", "contains"],
2956
2989
  "identifier": ["in", "exact", "contains"],
2957
2990
  "uid": ["in", "exact"],
2958
2991
  "data_source__uid": ["in", "exact"],
@@ -3321,7 +3354,7 @@ class TimeIndexMetaTable(MetaTable):
3321
3354
  related_resource = getattr(session_dynamic_data_source, "related_resource", None)
3322
3355
  class_type = getattr(related_resource, "class_type", None)
3323
3356
  db_interface = _local_data_interface(class_type)
3324
- db_interface.drop_table(self.storage_hash)
3357
+ db_interface.drop_table(self.physical_table_name)
3325
3358
 
3326
3359
  self.delete()
3327
3360
 
@@ -4731,7 +4764,7 @@ class PodDataSource:
4731
4764
  list_tables=True,
4732
4765
  )
4733
4766
  remote_table_names = [
4734
- getattr(t, "physical_table_name", None) or t.storage_hash for t in remote_node_storages
4767
+ t.physical_table_name for t in remote_node_storages if t.physical_table_name
4735
4768
  ]
4736
4769
  db_interface = _local_data_interface(class_type)
4737
4770
  local_table_names = db_interface.list_tables()
@@ -4743,9 +4776,9 @@ class PodDataSource:
4743
4776
 
4744
4777
  tables_to_delete_remotely = set(remote_table_names) - set(local_table_names)
4745
4778
  for remote_table in remote_node_storages:
4746
- remote_physical_table_name = (
4747
- getattr(remote_table, "physical_table_name", None) or remote_table.storage_hash
4748
- )
4779
+ remote_physical_table_name = getattr(remote_table, "physical_table_name", None)
4780
+ if not remote_physical_table_name:
4781
+ continue
4749
4782
  if remote_physical_table_name in tables_to_delete_remotely:
4750
4783
  logger.debug(f"Deleting table remotely {remote_physical_table_name}")
4751
4784
  if remote_table.protect_from_deletion:
@@ -13,6 +13,10 @@ _LAZY_IMPORTS = {
13
13
  "AlembicVersionMetaTable": (".migrations", "AlembicVersionMetaTable"),
14
14
  "PlatformManagedMetaTable": (".sqlalchemy_contracts", "PlatformManagedMetaTable"),
15
15
  "PlatformTimeIndexMetaTable": (".sqlalchemy_contracts", "PlatformTimeIndexMetaTable"),
16
+ "compute_metatable_contract_hash": (
17
+ ".sqlalchemy_contracts",
18
+ "compute_metatable_contract_hash",
19
+ ),
16
20
  "POSTGRES_IDENTIFIER_MAX_LENGTH": (".hashing", "POSTGRES_IDENTIFIER_MAX_LENGTH"),
17
21
  "SchemaTableNameParts": (".schema_names", "SchemaTableNameParts"),
18
22
  "BaseConfiguration": (".data_nodes", "BaseConfiguration"),
@@ -174,12 +174,19 @@ class APIDataNode(DataAccessMixin):
174
174
 
175
175
  @classmethod
176
176
  def build_from_local_time_serie(cls, source_table: "DataNodeUpdate") -> "APIDataNode":
177
+ physical_table_name = getattr(source_table, "physical_table_name", None) or getattr(
178
+ getattr(source_table, "data_node_storage", None),
179
+ "physical_table_name",
180
+ None,
181
+ )
182
+ if physical_table_name in (None, ""):
183
+ raise ValueError("APIDataNode.build_from_local_time_serie requires physical_table_name.")
177
184
  return cls(
178
185
  data_source_uid=cls._require_data_source_uid(
179
186
  source_table.data_source,
180
187
  context="APIDataNode.build_from_local_time_serie",
181
188
  ),
182
- storage_hash=source_table.storage_hash,
189
+ physical_table_name=str(physical_table_name),
183
190
  )
184
191
 
185
192
  @classmethod
@@ -195,7 +202,7 @@ class APIDataNode(DataAccessMixin):
195
202
  storage_table,
196
203
  context=context,
197
204
  ),
198
- storage_hash=cls._require_physical_table_name(
205
+ physical_table_name=cls._require_physical_table_name(
199
206
  storage_table,
200
207
  context=context,
201
208
  ),
@@ -222,7 +229,9 @@ class APIDataNode(DataAccessMixin):
222
229
  def __init__(
223
230
  self,
224
231
  data_source_uid: str,
225
- storage_hash: str,
232
+ physical_table_name: str | None = None,
233
+ *,
234
+ storage_hash: str | None = None,
226
235
  data_source_local_lake: DataSource | None = None,
227
236
  storage_table: MetaTable | None = None,
228
237
  ):
@@ -231,7 +240,7 @@ class APIDataNode(DataAccessMixin):
231
240
 
232
241
  Args:
233
242
  data_source_uid: The UID of the data source.
234
- storage_hash: The storage hash of the data node table.
243
+ physical_table_name: The physical table name of the data node table.
235
244
  data_source_local_lake: Optional local data source for the lake.
236
245
  storage_table: Optional resolved MetaTable backing this read wrapper.
237
246
  """
@@ -242,8 +251,11 @@ class APIDataNode(DataAccessMixin):
242
251
 
243
252
  if data_source_uid in (None, ""):
244
253
  raise ValueError("APIDataNode requires data_source_uid.")
254
+ resolved_physical_table_name = physical_table_name or storage_hash
255
+ if resolved_physical_table_name in (None, ""):
256
+ raise ValueError("APIDataNode requires physical_table_name.")
245
257
  self.data_source_uid = str(data_source_uid)
246
- self.storage_hash = storage_hash
258
+ self.physical_table_name = str(resolved_physical_table_name)
247
259
  self.storage_table = storage_table
248
260
  self.data_source = data_source_local_lake
249
261
  self._local_persist_manager: APIPersistManager = None
@@ -257,19 +269,19 @@ class APIDataNode(DataAccessMixin):
257
269
  return True
258
270
 
259
271
  @staticmethod
260
- def _get_update_hash(storage_hash):
261
- return "API_" + f"{storage_hash}"
272
+ def _get_update_hash(physical_table_name):
273
+ return "API_" + f"{physical_table_name}"
262
274
 
263
275
  @property
264
276
  def update_hash(self):
265
- return self._get_update_hash(storage_hash=self.storage_hash)
277
+ return self._get_update_hash(physical_table_name=self.physical_table_name)
266
278
 
267
279
  @property
268
280
  def local_persist_manager(self) -> Any:
269
281
  """Gets the local persistence manager, initializing it if necessary."""
270
282
  if self._local_persist_manager is None:
271
283
  self._set_local_persist_manager()
272
- self.logger.debug(f"Setting local persist manager for {self.storage_hash}")
284
+ self.logger.debug(f"Setting local persist manager for {self.physical_table_name}")
273
285
  return self._local_persist_manager
274
286
 
275
287
  def set_relation_tree(self) -> None:
@@ -308,12 +320,12 @@ class APIDataNode(DataAccessMixin):
308
320
  def _set_local_persist_manager(self) -> None:
309
321
  self._verify_local_data_source()
310
322
  self._local_persist_manager = APIPersistManager(
311
- storage_hash=self.storage_hash,
323
+ physical_table_name=self.physical_table_name,
312
324
  data_source_uid=self.data_source_uid,
313
325
  )
314
326
  storage_table = self._local_persist_manager.storage_table
315
327
 
316
- assert storage_table is not None, f"Verify that the table {self.storage_hash} exists "
328
+ assert storage_table is not None, f"Verify that the table {self.physical_table_name} exists "
317
329
 
318
330
  def get_update_statistics(self):
319
331
  """
@@ -240,11 +240,11 @@ def _storage_table_identity_summary(storage_table: type[PlatformTimeIndexMetaTab
240
240
  if identifier not in (None, ""):
241
241
  parts.append(f"identifier={identifier!r}")
242
242
  try:
243
- storage_hash = storage_table.get_storage_hash()
243
+ contract_hash = storage_table.get_storage_hash()
244
244
  except Exception:
245
- storage_hash = None
246
- if storage_hash not in (None, ""):
247
- parts.append(f"storage_hash={storage_hash!r}")
245
+ contract_hash = None
246
+ if contract_hash not in (None, ""):
247
+ parts.append(f"contract_hash={contract_hash!r}")
248
248
  data_source_uid = storage_table.get_data_source_uid()
249
249
  if data_source_uid not in (None, ""):
250
250
  parts.append(f"model_data_source_uid={data_source_uid!r}")
@@ -264,7 +264,6 @@ def _time_index_meta_table_candidate_summary(meta_table: TimeIndexMetaTable) ->
264
264
  "data_source_uid",
265
265
  "identifier",
266
266
  "physical_table_name",
267
- "storage_hash",
268
267
  "provisioning_status",
269
268
  ):
270
269
  value = getattr(meta_table, attr, None)
@@ -602,7 +601,7 @@ class BasePersistManager:
602
601
  db_interface = get_sqlite_interface_class()()
603
602
  else:
604
603
  raise ValueError(f"Unsupported local DataSource class_type: {class_type!r}")
605
- db_interface.drop_table(self.storage_metadata.storage_hash)
604
+ db_interface.drop_table(self.storage_metadata.physical_table_name)
606
605
 
607
606
  self.storage_metadata.delete()
608
607
 
@@ -648,21 +647,22 @@ class APIPersistManager:
648
647
  def __init__(
649
648
  self,
650
649
  *,
650
+ physical_table_name: str | None = None,
651
651
  storage_hash: str | None = None,
652
652
  data_source_uid: str,
653
653
  ):
654
654
  if data_source_uid in (None, ""):
655
655
  raise ValueError("APIPersistManager requires data_source_uid.")
656
656
  self.data_source_uid: str = str(data_source_uid)
657
- self.storage_hash: str = storage_hash
657
+ self.physical_table_name: str | None = physical_table_name or storage_hash
658
658
 
659
- logger.debug(f"Initializing Time Serie {self.storage_hash} as APIDataNode")
659
+ logger.debug(f"Initializing Time Serie {self.physical_table_name} as APIDataNode")
660
660
 
661
661
  self._storage_table_future = Future()
662
662
  future_registry.add_future(self._storage_table_future)
663
663
  thread = threading.Thread(
664
664
  target=self._init_storage_table,
665
- name=f"ApiStorageTableThread-{self.storage_hash}",
665
+ name=f"ApiStorageTableThread-{self.physical_table_name}",
666
666
  daemon=False,
667
667
  )
668
668
  thread.start()
@@ -676,7 +676,7 @@ class APIPersistManager:
676
676
  def _init_storage_table(self) -> None:
677
677
  try:
678
678
  result = TimeIndexMetaTable.get_or_none(
679
- physical_table_name=self.storage_hash,
679
+ physical_table_name=self.physical_table_name,
680
680
  data_source__uid=self.data_source_uid,
681
681
  )
682
682
  self._storage_table_future.set_result(result)
@@ -198,23 +198,17 @@ def _metatable_contract_column_dtypes_map(meta_table: Any) -> dict[str, str]:
198
198
  return column_dtypes
199
199
 
200
200
 
201
- def _storage_hash(storage_table: Any) -> str | None:
201
+ def _physical_table_name(storage_table: Any) -> str | None:
202
202
  if storage_table is None:
203
203
  return None
204
204
  if isinstance(storage_table, Mapping):
205
- storage_hash = storage_table.get("storage_hash") or storage_table.get("physical_table_name")
205
+ table_name = storage_table.get("physical_table_name")
206
206
  else:
207
- hash_getter = getattr(storage_table, "get_storage_hash", None)
208
- try:
209
- storage_hash = hash_getter() if callable(hash_getter) else None
210
- except Exception:
211
- storage_hash = None
212
- storage_hash = storage_hash or getattr(storage_table, "storage_hash", None)
213
- storage_hash = storage_hash or getattr(storage_table, "physical_table_name", None)
214
- if storage_hash in (None, ""):
207
+ table_name = getattr(storage_table, "physical_table_name", None)
208
+ if table_name in (None, ""):
215
209
  table = getattr(storage_table, "__table__", None)
216
- storage_hash = getattr(table, "name", None)
217
- return str(storage_hash) if isinstance(storage_hash, str) and storage_hash else None
210
+ table_name = getattr(table, "name", None)
211
+ return str(table_name) if isinstance(table_name, str) and table_name else None
218
212
 
219
213
 
220
214
  def _require_uid(obj: Any, object_name: str) -> str:
@@ -323,11 +317,16 @@ class UpdateRunner:
323
317
  # 3. Collect all UIDs in the dependency graph to fetch their metadata.
324
318
  # This correctly initializes the list, fixing the original bug.
325
319
  if not self.ts.depth_df.empty:
326
- update_nodes_in_tree = self.ts.depth_df[
327
- ["update_node_uid", "node_type", "update_hash", "remote_table_hash_id"]
328
- ].to_dict("records")
320
+ dependency_columns = ["update_node_uid", "node_type", "update_hash"]
321
+ if "physical_table_name" in self.ts.depth_df.columns:
322
+ dependency_columns.append("physical_table_name")
323
+ elif "remote_table_hash_id" in self.ts.depth_df.columns:
324
+ dependency_columns.append("remote_table_hash_id")
325
+ update_nodes_in_tree = self.ts.depth_df[dependency_columns].to_dict("records")
329
326
  for update_node in update_nodes_in_tree:
330
327
  update_node["uid"] = str(update_node.pop("update_node_uid"))
328
+ if "remote_table_hash_id" in update_node:
329
+ update_node["physical_table_name"] = update_node.pop("remote_table_hash_id")
331
330
  else:
332
331
  update_nodes_in_tree = []
333
332
 
@@ -336,7 +335,7 @@ class UpdateRunner:
336
335
  {
337
336
  "uid": _require_uid(self.ts.data_node_update, "DataNodeUpdate"),
338
337
  "update_hash": self.ts.data_node_update.update_hash,
339
- "remote_table_hash_id": _storage_hash(
338
+ "physical_table_name": _physical_table_name(
340
339
  self.ts.local_persist_manager.storage_metadata
341
340
  ),
342
341
  "node_type": self.ts.data_node_update.NODE_TYPE,
@@ -900,9 +899,11 @@ class UpdateRunner:
900
899
  f"Scheduler Head Update: {self.ts.update_hash}"
901
900
  ) as span:
902
901
  span.set_attribute("time_serie_update_hash", self.ts.update_hash)
903
- storage_hash = _storage_hash(self.ts.local_persist_manager.storage_metadata)
904
- if storage_hash is not None:
905
- span.set_attribute("storage_hash", storage_hash)
902
+ physical_table_name = _physical_table_name(
903
+ self.ts.local_persist_manager.storage_metadata
904
+ )
905
+ if physical_table_name is not None:
906
+ span.set_attribute("physical_table_name", physical_table_name)
906
907
  span.set_attribute("head_scheduler", self.scheduler.name)
907
908
 
908
909
  # 3. Prepare the execution environment (Ray actors, dependency metadata)