mainsequence 4.3.30__tar.gz → 4.4.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.
Files changed (138) hide show
  1. {mainsequence-4.3.30/mainsequence.egg-info → mainsequence-4.4.0}/PKG-INFO +1 -1
  2. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/cli.py +15 -16
  3. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/metatables/core.py +63 -34
  4. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/__init__.py +4 -0
  5. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/data_nodes/data_nodes.py +23 -11
  6. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/data_nodes/persist_managers.py +10 -10
  7. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/data_nodes/run_operations.py +20 -19
  8. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/migrations/__init__.py +0 -12
  9. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/sqlalchemy_contracts.py +65 -113
  10. {mainsequence-4.3.30 → mainsequence-4.4.0/mainsequence.egg-info}/PKG-INFO +1 -1
  11. {mainsequence-4.3.30 → mainsequence-4.4.0}/pyproject.toml +1 -1
  12. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_cli.py +38 -36
  13. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_data_access_mixin_dimension_audit.py +5 -5
  14. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_meta_table_migrations.py +3 -15
  15. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_meta_tables_client_models.py +1 -4
  16. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_meta_tables_sqlalchemy_contracts.py +44 -22
  17. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_run_configuration.py +18 -13
  18. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_update_runner_uid_runtime.py +3 -3
  19. {mainsequence-4.3.30 → mainsequence-4.4.0}/LICENSE +0 -0
  20. {mainsequence-4.3.30 → mainsequence-4.4.0}/README.md +0 -0
  21. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/AGENTS.md +0 -0
  22. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/a2a_communication/SKILL.md +0 -0
  23. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
  24. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/command_center/adapter_from_api/SKILL.md +0 -0
  25. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/command_center/api_mock_prototyping/SKILL.md +0 -0
  26. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/command_center/app_components/SKILL.md +0 -0
  27. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/command_center/connections/SKILL.md +0 -0
  28. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/command_center/workspace_analysis/SKILL.md +0 -0
  29. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/command_center/workspace_builder/SKILL.md +0 -0
  30. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/command_center/workspace_design/SKILL.md +0 -0
  31. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/dashboards/streamlit/SKILL.md +0 -0
  32. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
  33. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
  34. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
  35. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
  36. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  37. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/ms-markets/SKILL.md +0 -0
  38. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  39. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
  40. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/project_builder/SKILL.md +0 -0
  41. {mainsequence-4.3.30 → mainsequence-4.4.0}/agent_scaffold/skills/project_to_agent/SKILL.md +0 -0
  42. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/__init__.py +0 -0
  43. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/__main__.py +0 -0
  44. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/bootstrap.py +0 -0
  45. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/__init__.py +0 -0
  46. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/api.py +0 -0
  47. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/browser_auth.py +0 -0
  48. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/config.py +0 -0
  49. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/docker_utils.py +0 -0
  50. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/doctor.py +0 -0
  51. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/local_ops.py +0 -0
  52. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/migrations.py +0 -0
  53. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/model_filters.py +0 -0
  54. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/project_status.py +0 -0
  55. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/pydantic_cli.py +0 -0
  56. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/sdk_utils.py +0 -0
  57. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/ssh_utils.py +0 -0
  58. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/cli/ui.py +0 -0
  59. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/__init__.py +0 -0
  60. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/agent_runtime_models.py +0 -0
  61. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/base.py +0 -0
  62. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/client.py +0 -0
  63. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/command_center/__init__.py +0 -0
  64. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/command_center/app_component.py +0 -0
  65. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/command_center/connections.py +0 -0
  66. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/command_center/data_models.py +0 -0
  67. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/command_center/workspace.py +0 -0
  68. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/command_center/workspace_snapshot.py +0 -0
  69. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/compute_validation.py +0 -0
  70. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
  71. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
  72. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
  73. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
  74. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/dtype_codec.py +0 -0
  75. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/exceptions.py +0 -0
  76. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/fastapi/__init__.py +0 -0
  77. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/fastapi/auth.py +0 -0
  78. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/metatables/__init__.py +0 -0
  79. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/models_foundry.py +0 -0
  80. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/models_helpers.py +0 -0
  81. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/models_user.py +0 -0
  82. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/client/utils.py +0 -0
  83. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/defaults.py +0 -0
  84. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/instrumentation/__init__.py +0 -0
  85. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/instrumentation/utils.py +0 -0
  86. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/logconf.py +0 -0
  87. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/__main__.py +0 -0
  88. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
  89. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
  90. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
  91. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
  92. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/data_nodes/models.py +0 -0
  93. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
  94. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
  95. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/future_registry.py +0 -0
  96. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/hashing.py +0 -0
  97. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/migrations/alembic.py +0 -0
  98. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/migrations/env.py +0 -0
  99. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/migrations/provider.py +0 -0
  100. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/migrations/registry.py +0 -0
  101. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
  102. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
  103. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
  104. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
  105. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
  106. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/meta_tables/schema_names.py +0 -0
  107. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence/runtime_flags.py +0 -0
  108. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence.egg-info/SOURCES.txt +0 -0
  109. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence.egg-info/dependency_links.txt +0 -0
  110. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence.egg-info/entry_points.txt +0 -0
  111. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence.egg-info/requires.txt +0 -0
  112. {mainsequence-4.3.30 → mainsequence-4.4.0}/mainsequence.egg-info/top_level.txt +0 -0
  113. {mainsequence-4.3.30 → mainsequence-4.4.0}/setup.cfg +0 -0
  114. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_auth_precedence.py +0 -0
  115. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_build_operations_hashing.py +0 -0
  116. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_cli_browser_auth.py +0 -0
  117. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_cli_migrations.py +0 -0
  118. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_client.py +0 -0
  119. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_command_center_app_component_models.py +0 -0
  120. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_command_center_data_models.py +0 -0
  121. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_command_center_models.py +0 -0
  122. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_data_node_storage_dimension_queries.py +0 -0
  123. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_data_node_update_flow.py +0 -0
  124. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_dependency_extras.py +0 -0
  125. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_duckdb_interface_dimensions.py +0 -0
  126. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_filter_normalization.py +0 -0
  127. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_instrumentation.py +0 -0
  128. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_logconf.py +0 -0
  129. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_models_user_request_bound_auth.py +0 -0
  130. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_pod_project_resolution.py +0 -0
  131. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_project_batch_jobs_from_file.py +0 -0
  132. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_schema_names.py +0 -0
  133. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_secret_client_model.py +0 -0
  134. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_source_table_configuration.py +0 -0
  135. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_sqlite_interface_dimensions.py +0 -0
  136. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_update_statistics.py +0 -0
  137. {mainsequence-4.3.30 → mainsequence-4.4.0}/tests/test_update_uid_guards.py +0 -0
  138. {mainsequence-4.3.30 → mainsequence-4.4.0}/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.0
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,10 +408,6 @@ 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(
405
- None,
406
- description="Storage hash of the target MetaTable.",
407
- )
408
411
  target_columns: list[str] = Field(
409
412
  default_factory=list,
410
413
  description="Target MetaTable physical column names.",
@@ -415,6 +418,15 @@ class MetaTableForeignKeyPayload(BasePydanticModel):
415
418
  description="Raw normalized contract fragment for this projected foreign key.",
416
419
  )
417
420
 
421
+ @model_validator(mode="before")
422
+ @classmethod
423
+ def _strip_legacy_storage_hash(cls, value: Any) -> Any:
424
+ if isinstance(value, Mapping):
425
+ data = dict(value)
426
+ data.pop("target_table_storage_hash", None)
427
+ return data
428
+ return value
429
+
418
430
 
419
431
  class MetaTableStatementPayload(BasePydanticModel):
420
432
  sql: str = Field(..., min_length=1)
@@ -533,7 +545,6 @@ class MetaTableRequestFields(BasePydanticModel):
533
545
  ...,
534
546
  description="Public UID of the DynamicTableDataSource that owns this MetaTable.",
535
547
  )
536
- storage_hash: str = Field(..., max_length=63, description="Canonical table storage hash.")
537
548
  table_contract: MetaTableContract | dict[str, Any]
538
549
  identifier: str | None = Field(
539
550
  default=None,
@@ -561,6 +572,15 @@ class MetaTableRequestFields(BasePydanticModel):
561
572
  self.table_contract = _normalize_contract_mapping(self.table_contract)
562
573
  return self
563
574
 
575
+ @model_validator(mode="before")
576
+ @classmethod
577
+ def _strip_legacy_storage_hash(cls, value: Any) -> Any:
578
+ if isinstance(value, Mapping):
579
+ data = dict(value)
580
+ data.pop("storage_hash", None)
581
+ return data
582
+ return value
583
+
564
584
 
565
585
  class MetaTableRegistrationRequest(MetaTableRequestFields):
566
586
  management_mode: MetaTableManagementMode
@@ -571,7 +591,15 @@ class MetaTableRegistrationRequest(MetaTableRequestFields):
571
591
  class MetaTableValidateContractRequest(BasePydanticModel):
572
592
  table_contract: MetaTableContract | dict[str, Any]
573
593
  management_mode: MetaTableManagementMode | None = None
574
- storage_hash: str | None = None
594
+
595
+ @model_validator(mode="before")
596
+ @classmethod
597
+ def _strip_legacy_storage_hash(cls, value: Any) -> Any:
598
+ if isinstance(value, Mapping):
599
+ data = dict(value)
600
+ data.pop("storage_hash", None)
601
+ return data
602
+ return value
575
603
 
576
604
  @model_validator(mode="after")
577
605
  def _normalize_table_contract(self) -> MetaTableValidateContractRequest:
@@ -676,7 +704,6 @@ class ManagedMetaTableFinalizeTableResult(BasePydanticModel):
676
704
  None,
677
705
  description="Organization-global logical MetaTable identifier, when present.",
678
706
  )
679
- storage_hash: str = Field(..., description="Canonical MetaTable storage hash.")
680
707
  physical_table_name: str | None = Field(
681
708
  None,
682
709
  description="Physical table name reconciled against the data source.",
@@ -729,7 +756,14 @@ class ManagedMetaTableFinalizeTableResult(BasePydanticModel):
729
756
  def _normalize_cadence(cls, value: str | None) -> str | None:
730
757
  return _normalize_time_indexed_cadence(value)
731
758
 
732
- model_config = ConfigDict(extra="ignore")
759
+ @model_validator(mode="before")
760
+ @classmethod
761
+ def _strip_legacy_storage_hash(cls, value: Any) -> Any:
762
+ if isinstance(value, Mapping):
763
+ data = dict(value)
764
+ data.pop("storage_hash", None)
765
+ return data
766
+ return value
733
767
 
734
768
 
735
769
  class ManagedMetaTableFinalizeResponse(BasePydanticModel):
@@ -847,7 +881,7 @@ class DataSource(BasePydanticModel, BaseObjectOrm):
847
881
  storage = data_node_update.data_node_storage
848
882
  _local_data_interface(self.class_type).upsert(
849
883
  df=serialized_data_frame,
850
- table=getattr(storage, "physical_table_name", None) or storage.storage_hash,
884
+ table=_storage_physical_table_name(storage),
851
885
  index_names=index_names,
852
886
  time_index_name=time_index_name,
853
887
  )
@@ -888,7 +922,7 @@ class DataSource(BasePydanticModel, BaseObjectOrm):
888
922
  if self.class_type in LOCAL_DATA_SOURCE_CLASS_TYPES:
889
923
  db_interface = _local_data_interface(self.class_type)
890
924
  storage = data_node_update.data_node_storage
891
- table_name = getattr(storage, "physical_table_name", None) or storage.storage_hash
925
+ table_name = _storage_physical_table_name(storage)
892
926
  time_index_name, index_names, _ = _storage_time_indexed_contract(storage)
893
927
 
894
928
  adjusted_start, adjusted_end, adjusted_dimension_range_map, _ = (
@@ -964,9 +998,7 @@ class DataSource(BasePydanticModel, BaseObjectOrm):
964
998
  if self.class_type in LOCAL_DATA_SOURCE_CLASS_TYPES:
965
999
  db_interface = _local_data_interface(self.class_type)
966
1000
  storage = data_node_update.data_node_storage
967
- table_name = getattr(storage, "physical_table_name", None) or getattr(
968
- storage, "storage_hash", None
969
- )
1001
+ table_name = _storage_physical_table_name(storage)
970
1002
  time_index_name, index_names, _ = _storage_time_indexed_contract(storage)
971
1003
  return db_interface.time_index_minima(
972
1004
  table=table_name,
@@ -1133,7 +1165,6 @@ class DynamicTableDataSource(BasePydanticModel, BaseObjectOrm):
1133
1165
  class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, BaseObjectOrm):
1134
1166
  ENDPOINT: ClassVar[str] = "ts_manager/meta_table"
1135
1167
  FILTERSET_FIELDS: ClassVar[dict[str, list[str]]] = {
1136
- "storage_hash": ["in", "exact", "contains"],
1137
1168
  "identifier": ["in", "exact", "contains"],
1138
1169
  "uid": ["in", "exact"],
1139
1170
  "data_source__uid": ["in", "exact"],
@@ -1177,7 +1208,6 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
1177
1208
  uid: str | None = Field(None, description="Public uid of this MetaTable.")
1178
1209
  data_source: int | DynamicTableDataSource | dict[str, Any] | None = None
1179
1210
  data_source_uid: str | None = None
1180
- storage_hash: str = Field(..., max_length=63, description="Canonical table storage hash.")
1181
1211
  identifier: str | None = Field(
1182
1212
  default=None,
1183
1213
  description=(
@@ -1215,6 +1245,15 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
1215
1245
 
1216
1246
  model_config = ConfigDict(populate_by_name=True)
1217
1247
 
1248
+ @model_validator(mode="before")
1249
+ @classmethod
1250
+ def _strip_legacy_storage_hash(cls, value: Any) -> Any:
1251
+ if isinstance(value, Mapping):
1252
+ data = dict(value)
1253
+ data.pop("storage_hash", None)
1254
+ return data
1255
+ return value
1256
+
1218
1257
  def _public_uid(self) -> str:
1219
1258
  if self.uid in (None, ""):
1220
1259
  raise ValueError("MetaTable must have a uid before calling this endpoint.")
@@ -1339,11 +1378,6 @@ class MetaTable(BasePydanticModel, LabelableObjectMixin, ShareableObjectMixin, B
1339
1378
  raise_for_response(response, payload=payload)
1340
1379
  return type(self)(**response.json())
1341
1380
 
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
1381
  @classmethod
1348
1382
  def destroy_by_uid(
1349
1383
  cls,
@@ -1819,7 +1853,7 @@ class UpdateNodeRef(TypedDict):
1819
1853
  uid: str
1820
1854
  node_type: str
1821
1855
  update_hash: str
1822
- remote_table_hash_id: str
1856
+ physical_table_name: str | None
1823
1857
 
1824
1858
 
1825
1859
  def _require_public_uid(obj: Any, object_name: str) -> str:
@@ -1872,11 +1906,6 @@ class TimeIndexMetaTableRegistrationRequest(BasePydanticModel):
1872
1906
  model_config = ConfigDict(extra="forbid")
1873
1907
 
1874
1908
  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
1909
  identifier: str | None = Field(
1881
1910
  None,
1882
1911
  description=(
@@ -1923,6 +1952,7 @@ class TimeIndexMetaTableRegistrationRequest(BasePydanticModel):
1923
1952
  if not isinstance(value, Mapping):
1924
1953
  return value
1925
1954
  data = dict(value)
1955
+ data.pop("storage_hash", None)
1926
1956
  forbidden = [
1927
1957
  field
1928
1958
  for field in ("columns", "index_names", "foreign_keys", "storage_layout")
@@ -2463,11 +2493,11 @@ class DataNodeUpdate(TableUpdateNode, BaseObjectOrm):
2463
2493
  return r.json()
2464
2494
 
2465
2495
  @classmethod
2466
- def get_upstream_nodes(cls, storage_hash, data_source_uid, timeout=None):
2496
+ def get_upstream_nodes(cls, table_name, data_source_uid, timeout=None):
2467
2497
  s = cls.build_session()
2468
2498
  url = (
2469
2499
  cls.get_object_url("DataNode")
2470
- + f"/{storage_hash}/get_upstream_nodes?data_source_uid={data_source_uid}"
2500
+ + f"/{table_name}/get_upstream_nodes?data_source_uid={data_source_uid}"
2471
2501
  )
2472
2502
  r = make_request(s=s, loaders=cls.LOADERS, r_type="GET", url=url, time_out=timeout)
2473
2503
  if r.status_code != 200:
@@ -2952,7 +2982,6 @@ class TableMetaData(BaseModel):
2952
2982
  class TimeIndexMetaTable(MetaTable):
2953
2983
  ENDPOINT: ClassVar[str] = "ts_manager/dynamic_table"
2954
2984
  FILTERSET_FIELDS: ClassVar[dict[str, list[str]]] = {
2955
- "storage_hash": ["in", "exact", "contains"],
2956
2985
  "identifier": ["in", "exact", "contains"],
2957
2986
  "uid": ["in", "exact"],
2958
2987
  "data_source__uid": ["in", "exact"],
@@ -3321,7 +3350,7 @@ class TimeIndexMetaTable(MetaTable):
3321
3350
  related_resource = getattr(session_dynamic_data_source, "related_resource", None)
3322
3351
  class_type = getattr(related_resource, "class_type", None)
3323
3352
  db_interface = _local_data_interface(class_type)
3324
- db_interface.drop_table(self.storage_hash)
3353
+ db_interface.drop_table(self.physical_table_name)
3325
3354
 
3326
3355
  self.delete()
3327
3356
 
@@ -4731,7 +4760,7 @@ class PodDataSource:
4731
4760
  list_tables=True,
4732
4761
  )
4733
4762
  remote_table_names = [
4734
- getattr(t, "physical_table_name", None) or t.storage_hash for t in remote_node_storages
4763
+ t.physical_table_name for t in remote_node_storages if t.physical_table_name
4735
4764
  ]
4736
4765
  db_interface = _local_data_interface(class_type)
4737
4766
  local_table_names = db_interface.list_tables()
@@ -4743,9 +4772,9 @@ class PodDataSource:
4743
4772
 
4744
4773
  tables_to_delete_remotely = set(remote_table_names) - set(local_table_names)
4745
4774
  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
- )
4775
+ remote_physical_table_name = getattr(remote_table, "physical_table_name", None)
4776
+ if not remote_physical_table_name:
4777
+ continue
4749
4778
  if remote_physical_table_name in tables_to_delete_remotely:
4750
4779
  logger.debug(f"Deleting table remotely {remote_physical_table_name}")
4751
4780
  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)