pytrilogy 0.3.484__tar.gz → 0.3.485__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 (450) hide show
  1. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/PKG-INFO +1 -1
  2. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/__init__.py +1 -1
  3. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/graph_models.py +9 -4
  4. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/group_graph.py +105 -71
  5. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/network_build.py +16 -4
  6. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/network_model.py +5 -4
  7. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/network_search.py +93 -19
  8. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/Cargo.lock +1 -1
  9. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/Cargo.toml +1 -1
  10. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/.scripts/__init__.py +0 -0
  11. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/.scripts/build_backend.py +0 -0
  12. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/.scripts/sync_version.py +0 -0
  13. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/LICENSE.md +0 -0
  14. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/README.md +0 -0
  15. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/pyproject.toml +0 -0
  16. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/README.md +0 -0
  17. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/__init__.py +0 -0
  18. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/constants.py +0 -0
  19. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/conversation.py +0 -0
  20. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/enums.py +0 -0
  21. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/execute.py +0 -0
  22. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/models.py +0 -0
  23. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/prompts.py +0 -0
  24. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/providers/__init__.py +0 -0
  25. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/providers/anthropic.py +0 -0
  26. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/providers/base.py +0 -0
  27. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/providers/deepseek.py +0 -0
  28. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/providers/google.py +0 -0
  29. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/providers/openai.py +0 -0
  30. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/providers/openrouter.py +0 -0
  31. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/providers/utils.py +0 -0
  32. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/ai/syntax_examples.py +0 -0
  33. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/authoring/README.md +0 -0
  34. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/authoring/__init__.py +0 -0
  35. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/constants.py +0 -0
  36. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/README.md +0 -0
  37. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/__init__.py +0 -0
  38. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/assertions.py +0 -0
  39. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/average_parts.py +0 -0
  40. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/casts.py +0 -0
  41. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/constants.py +0 -0
  42. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/domain_graph.py +0 -0
  43. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/domain_validation.py +0 -0
  44. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/enums.py +0 -0
  45. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/env_processor.py +0 -0
  46. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/environment_helpers.py +0 -0
  47. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/ergonomics.py +0 -0
  48. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/exceptions.py +0 -0
  49. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/fingerprint.py +0 -0
  50. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/functions.py +0 -0
  51. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/grain_pin.py +0 -0
  52. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/graph.py +0 -0
  53. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/having_normalization.py +0 -0
  54. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/internal.py +0 -0
  55. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/like_patterns.py +0 -0
  56. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/models/__init__.py +0 -0
  57. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/models/author.py +0 -0
  58. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/models/build.py +0 -0
  59. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/models/build_environment.py +0 -0
  60. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/models/copying.py +0 -0
  61. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/models/core.py +0 -0
  62. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/models/datasource.py +0 -0
  63. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/models/environment.py +0 -0
  64. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/models/execute.py +0 -0
  65. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/models/keyspace.py +0 -0
  66. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimization.py +0 -0
  67. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/__init__.py +0 -0
  68. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/atom_contract.py +0 -0
  69. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/base_optimization.py +0 -0
  70. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/collapse_single_parent.py +0 -0
  71. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/existence_having_fold.py +0 -0
  72. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/filtered_aggregate.py +0 -0
  73. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/full_join_lowering.py +0 -0
  74. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/hide_unused_concept.py +0 -0
  75. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/identity_group.py +0 -0
  76. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/inline_datasource.py +0 -0
  77. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/join_hoist.py +0 -0
  78. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/join_upgrade.py +0 -0
  79. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/merge_irrelevant_group_by.py +0 -0
  80. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/null_safe_join.py +0 -0
  81. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/order_inner_joins.py +0 -0
  82. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
  83. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/reuse_parent_lookup.py +0 -0
  84. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/semi_join_pushdown.py +0 -0
  85. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/strip_redundant_not_null.py +0 -0
  86. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/union_dim_pushdown.py +0 -0
  87. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/utils.py +0 -0
  88. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/optimizations/value_set_join_upgrade.py +0 -0
  89. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/README.md +0 -0
  90. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/__init__.py +0 -0
  91. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/aggregate_rollup.py +0 -0
  92. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/basic_graph.py +0 -0
  93. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/concept_strategies_v4.py +0 -0
  94. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/condition_utility.py +0 -0
  95. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/constants.py +0 -0
  96. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/discovery_utility.py +0 -0
  97. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/discovery_validation.py +0 -0
  98. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/grain_utility.py +0 -0
  99. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/join_key_groups.py +0 -0
  100. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/join_resolution.py +0 -0
  101. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/model_ambiguity.py +0 -0
  102. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/node_generators/__init__.py +0 -0
  103. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/node_generators/common.py +0 -0
  104. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/node_generators/presence_probe.py +0 -0
  105. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/node_generators/select_helpers/__init__.py +0 -0
  106. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/node_generators/select_helpers/condition_routing.py +0 -0
  107. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +0 -0
  108. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/node_generators/select_helpers/datasource_nodes.py +0 -0
  109. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/node_generators/select_helpers/source_scoring.py +0 -0
  110. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/node_generators/select_merge_node.py +0 -0
  111. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/node_generators/select_node.py +0 -0
  112. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/nodes/README.md +0 -0
  113. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/nodes/__init__.py +0 -0
  114. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/nodes/base_node.py +0 -0
  115. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/nodes/filter_node.py +0 -0
  116. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/nodes/group_node.py +0 -0
  117. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/nodes/merge_node.py +0 -0
  118. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/nodes/recursive_node.py +0 -0
  119. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
  120. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/nodes/subselect_node.py +0 -0
  121. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/nodes/union_node.py +0 -0
  122. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/nodes/unnest_node.py +0 -0
  123. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/nodes/window_node.py +0 -0
  124. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/null_provenance.py +0 -0
  125. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/partial_bridging.py +0 -0
  126. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/plan_trace.py +0 -0
  127. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/plan_trace_model.py +0 -0
  128. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/relation_rollup.py +0 -0
  129. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/scan_partials.py +0 -0
  130. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/source_dominance.py +0 -0
  131. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/statement_scope.py +0 -0
  132. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/utility.py +0 -0
  133. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/__init__.py +0 -0
  134. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/concept_graph.py +0 -0
  135. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/condition_injection.py +0 -0
  136. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/condition_placement.py +0 -0
  137. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/constants.py +0 -0
  138. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/edges.py +0 -0
  139. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/extent_ownership.py +0 -0
  140. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/final_cover.py +0 -0
  141. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/functional_dependency.py +0 -0
  142. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/group_behaviors.py +0 -0
  143. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/group_rules.py +0 -0
  144. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/history.py +0 -0
  145. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/join_plan.py +0 -0
  146. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/keyspace.py +0 -0
  147. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/models.py +0 -0
  148. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/network_coalescing.py +0 -0
  149. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/network_obligations.py +0 -0
  150. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/network_topology.py +0 -0
  151. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/projection.py +0 -0
  152. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/region_domains.py +0 -0
  153. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/region_reads.py +0 -0
  154. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/renders.py +0 -0
  155. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/root_partition.py +0 -0
  156. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/source_planning.py +0 -0
  157. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/staged_where.py +0 -0
  158. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/strategy_builder.py +0 -0
  159. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_helper/union_arms.py +0 -0
  160. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/__init__.py +0 -0
  161. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/aggregate.py +0 -0
  162. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/basic.py +0 -0
  163. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/common.py +0 -0
  164. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/condition_sources.py +0 -0
  165. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/constant.py +0 -0
  166. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/dispatch.py +0 -0
  167. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/filter.py +0 -0
  168. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/group_to.py +0 -0
  169. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/multiselect.py +0 -0
  170. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/nested_select.py +0 -0
  171. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/recursive.py +0 -0
  172. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/root.py +0 -0
  173. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/rowset.py +0 -0
  174. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/rowset_witness.py +0 -0
  175. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/subselect.py +0 -0
  176. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/union.py +0 -0
  177. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/union_select.py +0 -0
  178. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/unnest.py +0 -0
  179. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/processing/v4_node_generators/window.py +0 -0
  180. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/query_processor.py +0 -0
  181. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/scope_diagnostics.py +0 -0
  182. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/statements/README.md +0 -0
  183. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/statements/__init__.py +0 -0
  184. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/statements/author.py +0 -0
  185. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/statements/build.py +0 -0
  186. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/statements/common.py +0 -0
  187. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/statements/execute.py +0 -0
  188. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/table_processor.py +0 -0
  189. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/union_find.py +0 -0
  190. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/utility.py +0 -0
  191. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/validation/README.md +0 -0
  192. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/validation/__init__.py +0 -0
  193. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/validation/common.py +0 -0
  194. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/validation/concept.py +0 -0
  195. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/validation/datasource.py +0 -0
  196. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/validation/environment.py +0 -0
  197. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/validation/fix.py +0 -0
  198. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/validation/rows.py +0 -0
  199. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/core/where_scope_normalization.py +0 -0
  200. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/__init__.py +0 -0
  201. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/base.py +0 -0
  202. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/bigquery.py +0 -0
  203. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/bigquery_engine.py +0 -0
  204. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/bigquery_persist.py +0 -0
  205. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/bigquery_staging.py +0 -0
  206. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/cancel.py +0 -0
  207. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/clickhouse.py +0 -0
  208. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/clickhouse_chdb.py +0 -0
  209. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/common.py +0 -0
  210. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/config.py +0 -0
  211. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/dataframe.py +0 -0
  212. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/duckdb.py +0 -0
  213. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/duckdb_pool.py +0 -0
  214. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/duckdb_uv.py +0 -0
  215. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/duckdb_vgi.py +0 -0
  216. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/enums.py +0 -0
  217. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/haybarn_engine.py +0 -0
  218. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/metadata.py +0 -0
  219. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/mock.py +0 -0
  220. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/mock_pattern.py +0 -0
  221. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/mysql.py +0 -0
  222. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/postgres.py +0 -0
  223. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/presto.py +0 -0
  224. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/python_source.py +0 -0
  225. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/results.py +0 -0
  226. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/snowflake.py +0 -0
  227. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/source_pushdown.py +0 -0
  228. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/sql_server.py +0 -0
  229. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/sqlite.py +0 -0
  230. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/dialect/table_function.py +0 -0
  231. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/engine.py +0 -0
  232. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/__init__.py +0 -0
  233. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/assertions.py +0 -0
  234. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/client_copy.py +0 -0
  235. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/config.py +0 -0
  236. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/envs.py +0 -0
  237. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/model_fingerprint.py +0 -0
  238. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/outputs.py +0 -0
  239. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/report.py +0 -0
  240. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/staged_write.py +0 -0
  241. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/state/AGENTS.md +0 -0
  242. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/state/CLAUDE.md +0 -0
  243. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/state/__init__.py +0 -0
  244. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/state/cache.py +0 -0
  245. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/state/declaration.py +0 -0
  246. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/state/exceptions.py +0 -0
  247. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/state/isolation.py +0 -0
  248. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/state/partitions.py +0 -0
  249. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/state/persistence.py +0 -0
  250. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/state/phases.py +0 -0
  251. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/state/snapshot.py +0 -0
  252. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/state/state_store.py +0 -0
  253. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/state/watermarks.py +0 -0
  254. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/execution/write_order.py +0 -0
  255. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/executor.py +0 -0
  256. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/hooks/__init__.py +0 -0
  257. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/hooks/base_hook.py +0 -0
  258. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/hooks/graph_hook.py +0 -0
  259. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/hooks/query_debugger.py +0 -0
  260. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/io/__init__.py +0 -0
  261. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/io/adapters.py +0 -0
  262. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/io/arrow.py +0 -0
  263. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/io/click_support.py +0 -0
  264. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/io/contract.py +0 -0
  265. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/io/describe.py +0 -0
  266. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/io/errors.py +0 -0
  267. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/io/runner.py +0 -0
  268. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/io/sinks.py +0 -0
  269. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/io/vgi.py +0 -0
  270. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/metadata/__init__.py +0 -0
  271. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parser.py +0 -0
  272. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/README.md +0 -0
  273. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/__init__.py +0 -0
  274. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/common.py +0 -0
  275. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/exceptions.py +0 -0
  276. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/helpers.py +0 -0
  277. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/parse_engine_v2.py +0 -0
  278. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/pretty.py +0 -0
  279. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/render.py +0 -0
  280. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/trilogy.lark +0 -0
  281. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/README.md +0 -0
  282. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/__init__.py +0 -0
  283. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/concept_syntax.py +0 -0
  284. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/errors.py +0 -0
  285. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/function_syntax.py +0 -0
  286. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/hydration.py +0 -0
  287. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/import_service.py +0 -0
  288. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/lark_backend.py +0 -0
  289. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/model.py +0 -0
  290. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/pest_backend.py +0 -0
  291. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rowset_semantics.py +0 -0
  292. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/__init__.py +0 -0
  293. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/chart_rules.py +0 -0
  294. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/concept_rules.py +0 -0
  295. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/conditional_rules.py +0 -0
  296. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/datasource_rules.py +0 -0
  297. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/expression_rules.py +0 -0
  298. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/function_definition_rules.py +0 -0
  299. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/function_rules.py +0 -0
  300. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/import_rules.py +0 -0
  301. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/merge_rules.py +0 -0
  302. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/multiselect_rules.py +0 -0
  303. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/operational_rules.py +0 -0
  304. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/order_rules.py +0 -0
  305. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/persist_rules.py +0 -0
  306. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/rawsql_rules.py +0 -0
  307. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/rowset_rules.py +0 -0
  308. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/select_rules.py +0 -0
  309. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/select_statement_rules.py +0 -0
  310. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/statement_rules.py +0 -0
  311. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/subselect_rules.py +0 -0
  312. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/token_rules.py +0 -0
  313. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/tvf_rules.py +0 -0
  314. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules/type_rules.py +0 -0
  315. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/rules_context.py +0 -0
  316. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/select_finalize.py +0 -0
  317. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/semantic_scope.py +0 -0
  318. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/semantic_state.py +0 -0
  319. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/statement_planner.py +0 -0
  320. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/statement_plans.py +0 -0
  321. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/symbols.py +0 -0
  322. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/parsing/v2/syntax.py +0 -0
  323. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/py.typed +0 -0
  324. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/render.py +0 -0
  325. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/rendering/__init__.py +0 -0
  326. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/rendering/altair_renderer.py +0 -0
  327. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/rendering/base.py +0 -0
  328. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/rendering/chart_theme.py +0 -0
  329. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/rendering/rich_types.py +0 -0
  330. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/rendering/terminal_renderer.py +0 -0
  331. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/rendering/theme.py +0 -0
  332. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/report/__init__.py +0 -0
  333. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/report/backends/__init__.py +0 -0
  334. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/report/backends/base.py +0 -0
  335. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/report/backends/html.py +0 -0
  336. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/report/backends/png.py +0 -0
  337. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/report/charts.py +0 -0
  338. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/report/document.py +0 -0
  339. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/report/runner.py +0 -0
  340. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/report/tables.py +0 -0
  341. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/AGENTS.md +0 -0
  342. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/CLAUDE.md +0 -0
  343. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/README.md +0 -0
  344. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/__init__.py +0 -0
  345. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/agent.py +0 -0
  346. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/agent_info.py +0 -0
  347. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/agent_info_docs/__init__.py +0 -0
  348. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/agent_info_docs/cli.py +0 -0
  349. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/agent_info_docs/content.py +0 -0
  350. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/agent_info_docs/directory.py +0 -0
  351. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/agent_sessions.py +0 -0
  352. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/agent_sql_tools.py +0 -0
  353. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/agent_tools.py +0 -0
  354. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/click_utils.py +0 -0
  355. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/cloud.py +0 -0
  356. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/cloud_models.py +0 -0
  357. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/common.py +0 -0
  358. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/database.py +0 -0
  359. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/README.md +0 -0
  360. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/build.sh +0 -0
  361. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/examples/basic_usage.rs +0 -0
  362. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/src/directory_resolver.rs +0 -0
  363. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/src/graph.rs +0 -0
  364. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/src/lib.rs +0 -0
  365. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/src/main.rs +0 -0
  366. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/src/network_search.rs +0 -0
  367. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/src/parser.rs +0 -0
  368. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/src/python_bindings.rs +0 -0
  369. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/src/resolver.rs +0 -0
  370. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/src/trilogy.pest +0 -0
  371. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/src/trilogy_parser.rs +0 -0
  372. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/tests/base.preql +0 -0
  373. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/tests/cli_integration.rs +0 -0
  374. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/tests/customer.preql +0 -0
  375. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/tests/main.preql +0 -0
  376. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/tests/orders.preql +0 -0
  377. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/tests/parse_cost.rs +0 -0
  378. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/tests/public_api.rs +0 -0
  379. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/tests/test_data/base.preql +0 -0
  380. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency/tests/test_data/consumer.preql +0 -0
  381. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/dependency.py +0 -0
  382. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/display.py +0 -0
  383. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/display_core.py +0 -0
  384. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/display_execution.py +0 -0
  385. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/display_ingest.py +0 -0
  386. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/display_init.py +0 -0
  387. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/display_models.py +0 -0
  388. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/display_parallel.py +0 -0
  389. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/display_refresh.py +0 -0
  390. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/display_validation.py +0 -0
  391. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/env_commands.py +0 -0
  392. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/environment.py +0 -0
  393. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/explore.py +0 -0
  394. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/explore_seen.py +0 -0
  395. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/file.py +0 -0
  396. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/file_helpers/__init__.py +0 -0
  397. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/file_helpers/backends.py +0 -0
  398. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/file_helpers/preql_description.py +0 -0
  399. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/file_helpers/preql_validation.py +0 -0
  400. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/fmt.py +0 -0
  401. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/ingest.py +0 -0
  402. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/ingest_helpers/__init__.py +0 -0
  403. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/ingest_helpers/fk_inference.py +0 -0
  404. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/ingest_helpers/foreign_keys.py +0 -0
  405. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/ingest_helpers/formatting.py +0 -0
  406. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/ingest_helpers/introspection.py +0 -0
  407. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/ingest_helpers/typing.py +0 -0
  408. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/init.py +0 -0
  409. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/parallel_execution.py +0 -0
  410. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/plan.py +0 -0
  411. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/project_config.py +0 -0
  412. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/public.py +0 -0
  413. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/refresh.py +0 -0
  414. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/render.py +0 -0
  415. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/run.py +0 -0
  416. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/serve.py +0 -0
  417. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/serve_helpers/__init__.py +0 -0
  418. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/serve_helpers/connection_spec.py +0 -0
  419. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/serve_helpers/file_discovery.py +0 -0
  420. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/serve_helpers/index_generation.py +0 -0
  421. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/serve_helpers/jobs.py +0 -0
  422. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/serve_helpers/mcp_server.py +0 -0
  423. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/serve_helpers/models.py +0 -0
  424. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/serve_helpers/state_cache.py +0 -0
  425. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/serve_helpers/state_computation.py +0 -0
  426. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/serve_helpers/studio_bundle.py +0 -0
  427. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/single_execution.py +0 -0
  428. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/source.py +0 -0
  429. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/source_identity.py +0 -0
  430. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/state.py +0 -0
  431. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/testing.py +0 -0
  432. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/trilogy.py +0 -0
  433. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/scripts/validate_agent.py +0 -0
  434. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/staging.py +0 -0
  435. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/__init__.py +0 -0
  436. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/bytes.preql +0 -0
  437. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/chart.preql +0 -0
  438. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/collection.preql +0 -0
  439. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/color.preql +0 -0
  440. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/currency.preql +0 -0
  441. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/date.preql +0 -0
  442. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/display.preql +0 -0
  443. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/geography.preql +0 -0
  444. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/metric.preql +0 -0
  445. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/money.preql +0 -0
  446. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/net.preql +0 -0
  447. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/ranking.preql +0 -0
  448. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/report.preql +0 -0
  449. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/std/semantic.preql +0 -0
  450. {pytrilogy-0.3.484 → pytrilogy-0.3.485}/trilogy/utility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytrilogy
3
- Version: 0.3.484
3
+ Version: 0.3.485
4
4
  Classifier: Programming Language :: Python
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: Programming Language :: Python :: 3.11
@@ -7,7 +7,7 @@ if TYPE_CHECKING:
7
7
  from trilogy.executor import Executor
8
8
  from trilogy.parser import parse
9
9
 
10
- __version__ = "0.3.484"
10
+ __version__ = "0.3.485"
11
11
 
12
12
  __all__ = [
13
13
  "CONFIG",
@@ -132,6 +132,11 @@ def datasource_has_filter_sensitive_aggregate(
132
132
  return True
133
133
 
134
134
 
135
+ def _reads_subselect(groups: Iterable[tuple[BuildConcept, ...]]) -> bool:
136
+ """A literal `in (...)` list reports one empty existence group."""
137
+ return any(group for group in groups)
138
+
139
+
135
140
  def _datasource_is_exact_match(
136
141
  ds: BuildDatasource,
137
142
  criteria: SearchCriteria,
@@ -158,7 +163,7 @@ def _datasource_is_exact_match(
158
163
  requested_addresses = relevant_concepts or ds_output_addresses
159
164
  if (
160
165
  allow_filter_application
161
- and not conditions.existence_arguments
166
+ and not _reads_subselect(conditions.existence_arguments)
162
167
  and condition_addresses.issubset(ds_output_addresses)
163
168
  and condition_addresses.issubset(requested_addresses)
164
169
  ) and requested_addresses.isdisjoint(partial_addresses):
@@ -173,7 +178,7 @@ def _datasource_is_exact_match(
173
178
  has_aggregate_output
174
179
  and partial_addresses
175
180
  and allow_filter_application
176
- and not conditions.existence_arguments
181
+ and not _reads_subselect(conditions.existence_arguments)
177
182
  and condition_addresses
178
183
  and condition_addresses.issubset(ds_output_addresses - partial_addresses)
179
184
  ):
@@ -188,7 +193,7 @@ def _datasource_is_exact_match(
188
193
  has_aggregate_output
189
194
  and canonical_to_concept is not None
190
195
  and allow_filter_application
191
- and not conditions.existence_arguments
196
+ and not _reads_subselect(conditions.existence_arguments)
192
197
  and condition_addresses
193
198
  ):
194
199
  ds_grain_components = set(ds.grain.components)
@@ -275,7 +280,7 @@ def _get_collective_condition_matches(
275
280
  if not datasources:
276
281
  return keep
277
282
  for atom in decompose_condition(conditions.conditional):
278
- if any(arg for group in atom.existence_arguments for arg in group):
283
+ if _reads_subselect(atom.existence_arguments):
279
284
  return set()
280
285
  if not is_scalar_condition(atom):
281
286
  return set()
@@ -2344,7 +2344,13 @@ def build_group_graph(
2344
2344
  environment,
2345
2345
  rollup_padded,
2346
2346
  )
2347
- _rehome_groups(group_graph, group_edges, attrs, buckets, concept_attrs, environment)
2347
+ grouping = _elect_grouping_providers(
2348
+ group_graph, group_edges, attrs, concept_attrs, environment
2349
+ )
2350
+ _state_projection_grains(attrs, buckets, grouping)
2351
+ _rehome_groups(
2352
+ group_graph, group_edges, attrs, buckets, concept_attrs, environment, grouping
2353
+ )
2348
2354
  trace_group_graph(
2349
2355
  "FINAL added, concept sets computed, sources regrafted",
2350
2356
  group_graph,
@@ -2452,13 +2458,12 @@ def trace_group_graph(
2452
2458
  @dataclass(frozen=True)
2453
2459
  class RowProvider:
2454
2460
  """The row source a regraftable group is re-homed onto: the parent it
2455
- reads, the grain it adopts from a grouping provider, the lineage parents
2456
- that parent replaces, the dimension ROOT minted for it, and whether the
2457
- parent renders the group inline. Once elected (`_as_rewrite`) it holds
2458
- only what the graph lacks: `parent` is None when already a parent."""
2461
+ reads, the lineage parents that parent replaces, the dimension ROOT minted
2462
+ for it, and whether the parent renders the group inline. Once elected
2463
+ (`_as_rewrite`) it holds only what the graph lacks: `parent` is None when
2464
+ already a parent."""
2459
2465
 
2460
2466
  parent: str | None
2461
- grain: frozenset[str] | None = None
2462
2467
  drop: frozenset[str] = frozenset()
2463
2468
  minted: GroupBucket | None = None
2464
2469
  # the parent renders the group in its own SELECT: the group folds into it
@@ -2473,7 +2478,6 @@ def _regraft_candidate(
2473
2478
  *,
2474
2479
  allow_partial: bool,
2475
2480
  environment: BuildEnvironment | None = None,
2476
- grain: frozenset[str] | None = None,
2477
2481
  ) -> str | None:
2478
2482
  """Find the richest row-compatible sibling to source `gid`'s inputs.
2479
2483
 
@@ -2506,8 +2510,7 @@ def _regraft_candidate(
2506
2510
  merge.
2507
2511
  """
2508
2512
  current = attrs[gid]
2509
- if grain is None:
2510
- grain = current.grain_components
2513
+ grain = current.grain_components
2511
2514
  needed = set(current.input_concepts)
2512
2515
  if not needed:
2513
2516
  return None
@@ -2586,14 +2589,16 @@ def _grain_needed_by_independent_sibling(
2586
2589
  attrs: dict[str, GroupAttrs],
2587
2590
  gid: str,
2588
2591
  provider_gid: str,
2592
+ grouping: dict[str, str],
2589
2593
  ) -> bool:
2590
2594
  """Whether an independent FINAL-bound group co-grains on the provider's grain.
2591
2595
 
2592
2596
  Grafting the projection onto the provider fuses it into that group, which
2593
2597
  re-labels the provider's grouping key as this alias. Groups inside the
2594
- provider's own lineage follow that relabeling, but one that merges with it as
2595
- a separate arm does not: it would look for a key that no longer exists and
2596
- the merge would degenerate to a cross join.
2598
+ provider's own lineage follow that relabeling, and so does a projection
2599
+ placed at the same provider, but one that merges with it as a separate arm
2600
+ does not: it would look for a key that no longer exists and the merge
2601
+ would degenerate to a cross join.
2597
2602
  """
2598
2603
  provider_grain = attrs[provider_gid].grain_components
2599
2604
  if not provider_grain:
@@ -2601,6 +2606,7 @@ def _grain_needed_by_independent_sibling(
2601
2606
  related = (
2602
2607
  nx.ancestors(group_graph, provider_gid)
2603
2608
  | nx.descendants(group_graph, provider_gid)
2609
+ | {g for g, p in grouping.items() if p == provider_gid}
2604
2610
  | {gid, provider_gid, FINAL_NODE_ID}
2605
2611
  )
2606
2612
  for other in group_graph.nodes:
@@ -2680,7 +2686,6 @@ def _synthetic_dimension_regraft_parent(
2680
2686
  buckets: dict[str, GroupBucket],
2681
2687
  concept_attrs: dict[str, ConceptAttrs],
2682
2688
  gid: str,
2683
- grain: frozenset[str],
2684
2689
  ) -> RowProvider | None:
2685
2690
  current = attrs[gid]
2686
2691
  if current.derivation != Derivation.BASIC:
@@ -2691,7 +2696,7 @@ def _synthetic_dimension_regraft_parent(
2691
2696
  # condition's derived arg needs.
2692
2697
  if current.depth_label == DepthLabel.D1:
2693
2698
  return None
2694
- key = set(grain)
2699
+ key = set(current.grain_components)
2695
2700
  if not key:
2696
2701
  return None
2697
2702
  lineage_preds = lineage_predecessors(group_graph, group_edges, gid)
@@ -2860,6 +2865,45 @@ def _inline_window(
2860
2865
  return parent
2861
2866
 
2862
2867
 
2868
+ def _elect_grouping_providers(
2869
+ group_graph: nx.DiGraph,
2870
+ group_edges: EdgeMap,
2871
+ attrs: dict[str, GroupAttrs],
2872
+ concept_attrs: dict[str, ConceptAttrs],
2873
+ environment: BuildEnvironment,
2874
+ ) -> dict[str, str]:
2875
+ """Each terminal scalar projection's grouping provider, elected over the
2876
+ graph stage 2 built. A WINDOW that renders the projection inline outranks
2877
+ it: that projection folds and keeps its grain."""
2878
+ providers: dict[str, str] = {}
2879
+ for gid in group_graph.nodes:
2880
+ if gid == FINAL_NODE_ID:
2881
+ continue
2882
+ provider = _terminal_basic_grouping_provider(
2883
+ group_graph, attrs, gid, environment
2884
+ )
2885
+ if provider is None or _inline_window(
2886
+ group_graph, group_edges, attrs, concept_attrs, gid
2887
+ ):
2888
+ continue
2889
+ providers[gid] = provider
2890
+ return providers
2891
+
2892
+
2893
+ def _state_projection_grains(
2894
+ attrs: dict[str, GroupAttrs],
2895
+ buckets: dict[str, GroupBucket],
2896
+ grouping: dict[str, str],
2897
+ ) -> None:
2898
+ """Place each terminal projection at its grouping provider's grain. No
2899
+ provider is a BASIC, so no statement reads another."""
2900
+ for gid, provider in grouping.items():
2901
+ grain = attrs[provider].grain_components
2902
+ attrs[gid].grain_components = grain
2903
+ if gid in buckets:
2904
+ buckets[gid].grain_components = grain
2905
+
2906
+
2863
2907
  def _elect_row_provider(
2864
2908
  group_graph: nx.DiGraph,
2865
2909
  group_edges: EdgeMap,
@@ -2867,45 +2911,42 @@ def _elect_row_provider(
2867
2911
  buckets: dict[str, GroupBucket],
2868
2912
  concept_attrs: dict[str, ConceptAttrs],
2869
2913
  environment: BuildEnvironment,
2914
+ grouping: dict[str, str],
2870
2915
  gid: str,
2871
2916
  ) -> RowProvider | None:
2872
2917
  """Pick `gid`'s row source over the graph; mutates nothing. The choices,
2873
- in order: a WINDOW that renders it inline, a terminal BASIC's grouping
2874
- provider, a full-coverage sibling, a dimension ROOT, a partial spine."""
2875
- window = _inline_window(group_graph, group_edges, attrs, concept_attrs, gid)
2876
- if window is not None:
2877
- return RowProvider(window, inline=True)
2878
- grain = None
2879
- provider_gid = _terminal_basic_grouping_provider(
2880
- group_graph, attrs, gid, environment
2881
- )
2882
- if provider_gid is not None:
2883
- grain = attrs[provider_gid].grain_components
2884
- if not _grain_needed_by_independent_sibling(
2885
- group_graph, attrs, gid, provider_gid
2886
- ):
2887
- # Placed at the provider's grain, the projection has no use for
2888
- # a finer relation the provider was built from. Joined back, it
2889
- # pairs the provider's groups on a non-key (a region domain on
2890
- # a nullable description) and drops or multiplies them.
2891
- provider_ancestors = nx.ancestors(group_graph, provider_gid)
2892
- drop = frozenset(
2893
- pred
2894
- for pred in lineage_predecessors(group_graph, group_edges, gid)
2895
- if pred in provider_ancestors
2896
- )
2897
- return RowProvider(provider_gid, grain, drop)
2898
- own_grain = attrs[gid].grain_components if grain is None else grain
2918
+ in order: a WINDOW that renders it inline, its grouping provider (whose
2919
+ grain it already stands at), a full-coverage sibling, a dimension ROOT, a
2920
+ partial spine."""
2921
+ grouping_provider = grouping.get(gid)
2922
+ if grouping_provider is None:
2923
+ window = _inline_window(group_graph, group_edges, attrs, concept_attrs, gid)
2924
+ if window is not None:
2925
+ return RowProvider(window, inline=True)
2926
+ elif not _grain_needed_by_independent_sibling(
2927
+ group_graph, attrs, gid, grouping_provider, grouping
2928
+ ):
2929
+ # Placed at the provider's grain, the projection has no use for a
2930
+ # finer relation the provider was built from. Joined back, it pairs
2931
+ # the provider's groups on a non-key (a region domain on a nullable
2932
+ # description) and drops or multiplies them.
2933
+ provider_ancestors = nx.ancestors(group_graph, grouping_provider)
2934
+ drop = frozenset(
2935
+ pred
2936
+ for pred in lineage_predecessors(group_graph, group_edges, gid)
2937
+ if pred in provider_ancestors
2938
+ )
2939
+ return RowProvider(grouping_provider, drop)
2899
2940
  parent_gid = _regraft_candidate(
2900
2941
  group_graph, group_edges, attrs, gid, allow_partial=False
2901
2942
  )
2902
2943
  if parent_gid is not None:
2903
- return RowProvider(parent_gid, grain)
2944
+ return RowProvider(parent_gid)
2904
2945
  dimension = _synthetic_dimension_regraft_parent(
2905
- group_graph, group_edges, attrs, buckets, concept_attrs, gid, own_grain
2946
+ group_graph, group_edges, attrs, buckets, concept_attrs, gid
2906
2947
  )
2907
2948
  if dimension is not None:
2908
- return replace(dimension, grain=grain)
2949
+ return dimension
2909
2950
  parent_gid = _regraft_candidate(
2910
2951
  group_graph,
2911
2952
  group_edges,
@@ -2913,11 +2954,8 @@ def _elect_row_provider(
2913
2954
  gid,
2914
2955
  allow_partial=True,
2915
2956
  environment=environment,
2916
- grain=own_grain,
2917
2957
  )
2918
- if parent_gid is None and grain is None:
2919
- return None
2920
- return RowProvider(parent_gid, grain)
2958
+ return None if parent_gid is None else RowProvider(parent_gid)
2921
2959
 
2922
2960
 
2923
2961
  def _apply_row_provider(
@@ -2928,10 +2966,6 @@ def _apply_row_provider(
2928
2966
  gid: str,
2929
2967
  provider: RowProvider,
2930
2968
  ) -> None:
2931
- if provider.grain is not None:
2932
- attrs[gid].grain_components = provider.grain
2933
- if gid in buckets:
2934
- buckets[gid].grain_components = provider.grain
2935
2969
  minted = provider.minted
2936
2970
  if minted is not None and minted.group_id not in group_graph:
2937
2971
  group_graph.add_node(minted.group_id)
@@ -2947,23 +2981,13 @@ def _apply_row_provider(
2947
2981
 
2948
2982
 
2949
2983
  def _as_rewrite(
2950
- group_graph: nx.DiGraph,
2951
- attrs: dict[str, GroupAttrs],
2952
- buckets: dict[str, GroupBucket],
2953
- gid: str,
2954
- provider: RowProvider,
2984
+ group_graph: nx.DiGraph, gid: str, provider: RowProvider
2955
2985
  ) -> RowProvider | None:
2956
2986
  """`provider` less what the graph stage 2 built already holds, or None
2957
- when it changes nothing: its parent is already a parent, its grain is
2958
- already the group's, and it drops and mints nothing."""
2987
+ when it changes nothing: its parent is already a parent, and it drops and
2988
+ mints nothing."""
2959
2989
  if provider.inline:
2960
2990
  return provider
2961
- grain = provider.grain
2962
- bucket = buckets.get(gid)
2963
- if grain == attrs[gid].grain_components and (
2964
- bucket is None or grain == bucket.grain_components
2965
- ):
2966
- grain = None
2967
2991
  drop = frozenset(p for p in provider.drop if group_graph.has_edge(p, gid))
2968
2992
  minted = provider.minted
2969
2993
  if minted is not None and minted.group_id in group_graph:
@@ -2971,9 +2995,9 @@ def _as_rewrite(
2971
2995
  parent = provider.parent
2972
2996
  if parent is not None and group_graph.has_edge(parent, gid):
2973
2997
  parent = None
2974
- if parent is None and grain is None and not drop and minted is None:
2998
+ if parent is None and not drop and minted is None:
2975
2999
  return None
2976
- return RowProvider(parent, grain, drop, minted)
3000
+ return RowProvider(parent, drop, minted)
2977
3001
 
2978
3002
 
2979
3003
  def _elect_row_providers(
@@ -2983,6 +3007,7 @@ def _elect_row_providers(
2983
3007
  buckets: dict[str, GroupBucket],
2984
3008
  concept_attrs: dict[str, ConceptAttrs],
2985
3009
  environment: BuildEnvironment,
3010
+ grouping: dict[str, str],
2986
3011
  ) -> dict[str, RowProvider]:
2987
3012
  """Each regraftable group whose best row source is already built, elected
2988
3013
  over the graph as stage 2 built it, as the rewrite it makes of that graph.
@@ -3000,10 +3025,17 @@ def _elect_row_providers(
3000
3025
  ):
3001
3026
  continue
3002
3027
  provider = _elect_row_provider(
3003
- group_graph, group_edges, attrs, buckets, concept_attrs, environment, gid
3028
+ group_graph,
3029
+ group_edges,
3030
+ attrs,
3031
+ buckets,
3032
+ concept_attrs,
3033
+ environment,
3034
+ grouping,
3035
+ gid,
3004
3036
  )
3005
3037
  if provider is not None:
3006
- provider = _as_rewrite(group_graph, attrs, buckets, gid, provider)
3038
+ provider = _as_rewrite(group_graph, gid, provider)
3007
3039
  if provider is not None:
3008
3040
  providers[gid] = provider
3009
3041
  folded = _folds(providers)
@@ -3029,12 +3061,14 @@ def _rehome_groups(
3029
3061
  buckets: dict[str, GroupBucket],
3030
3062
  concept_attrs: dict[str, ConceptAttrs],
3031
3063
  environment: BuildEnvironment,
3064
+ grouping: dict[str, str],
3032
3065
  ) -> None:
3033
3066
  """Elect every group's row provider over the graph as stage 2 built it,
3034
- then fold each group its provider renders inline and apply the rest: no
3035
- election reads another's fold, edges or adopted grain."""
3067
+ each projection already at its grouping provider's grain, then fold each
3068
+ group its provider renders inline and apply the rest: no election reads
3069
+ another's fold or edges."""
3036
3070
  providers = _elect_row_providers(
3037
- group_graph, group_edges, attrs, buckets, concept_attrs, environment
3071
+ group_graph, group_edges, attrs, buckets, concept_attrs, environment, grouping
3038
3072
  )
3039
3073
  for gid, parent in _folds(providers).items():
3040
3074
  _absorb_group(gid, parent, group_graph, group_edges, attrs, buckets)
@@ -96,6 +96,7 @@ from trilogy.core.processing.v4_helper.projection import (
96
96
  def _condition_fit(
97
97
  datasource: BuildDatasource | BuildUnionDatasource,
98
98
  conditions: BuildWhereClause | None,
99
+ environment: BuildEnvironment,
99
100
  ) -> ConditionFit:
100
101
  if conditions is None:
101
102
  return ConditionFit.NEUTRAL
@@ -104,9 +105,20 @@ def _condition_fit(
104
105
  conditions.conditional, non_partial_for.conditional
105
106
  ):
106
107
  return ConditionFit.IMPLIED_EXACT
107
- if isinstance(
108
- datasource, BuildDatasource
109
- ) and datasource_has_filter_sensitive_aggregate(datasource, conditions):
108
+ # A condition on a property of the grain's keys selects whole groups, so
109
+ # the aggregate is kept (`Cover.joined_case_exact`); the map is only built
110
+ # when the plain check would refuse.
111
+ if (
112
+ isinstance(datasource, BuildDatasource)
113
+ and datasource_has_filter_sensitive_aggregate(datasource, conditions)
114
+ and datasource_has_filter_sensitive_aggregate(
115
+ datasource,
116
+ conditions,
117
+ canonical_to_concept={
118
+ c.canonical_address: c for c in environment.concepts.values()
119
+ },
120
+ )
121
+ ):
110
122
  return ConditionFit.SENSITIVE
111
123
  return ConditionFit.NEUTRAL
112
124
 
@@ -257,7 +269,7 @@ def _candidate(
257
269
  node=node,
258
270
  datasource=datasource,
259
271
  bindings=_bindings_for(emitted, partial, stored, equivalence),
260
- condition=_condition_fit(datasource, conditions),
272
+ condition=_condition_fit(datasource, conditions, environment),
261
273
  is_union=isinstance(datasource, BuildUnionDatasource),
262
274
  grain=_grain_classes(datasource, equivalence),
263
275
  )
@@ -509,10 +509,11 @@ class SolutionCost:
509
509
  # connector's subplan. At equal scan count the cover storing the column
510
510
  # wins, instead of whichever source sorts first.
511
511
  derived_terminals: int
512
- # Sources read in full beside a twin the WHERE pre-filters: a `complete
513
- # where` binding the query implies (IMPLIED_EXACT) reading the same
514
- # columns holds only the rows the query keeps, so it outranks them.
515
- unfiltered_sources: int
512
+ # Sources another candidate reading the same columns holds no more of the
513
+ # query's rows than (`Cost.filtered_dominated_le`): one read in full beside
514
+ # a twin the WHERE pre-filters (IMPLIED_EXACT), or a pre-filtered table
515
+ # beside a coarser source that applies the same WHERE.
516
+ dominated_reads: int
516
517
  connectors: int
517
518
  derived_joins: int
518
519
 
@@ -39,6 +39,7 @@ from _preql_import_resolver import enumerate_network_covers
39
39
  from trilogy.core.graph_models import ReferenceGraph
40
40
  from trilogy.core.models.build import (
41
41
  BuildConcept,
42
+ BuildDatasource,
42
43
  BuildUnionDatasource,
43
44
  BuildWhereClause,
44
45
  )
@@ -287,24 +288,65 @@ def _stored_key(candidate: SourceCandidate, address: str) -> bool:
287
288
  return binding is not None and binding.stored
288
289
 
289
290
 
290
- def _has_filtered_twin(network: SourceNetwork, node: str, read: frozenset[str]) -> bool:
291
- """Another source the WHERE pre-filters (IMPLIED_EXACT) reads every value
292
- `node` provides or joins on from the same column, so it holds the rows of
293
- `node` the query keeps."""
291
+ def _reads_alike(
292
+ candidate: SourceCandidate, other: SourceCandidate, read: frozenset[str]
293
+ ) -> bool:
294
+ return all(
295
+ (mine := candidate.bindings.get(address)) is not None
296
+ and (theirs := other.bindings.get(address)) is not None
297
+ and mine.address == theirs.address
298
+ for address in read
299
+ )
300
+
301
+
302
+ def _arm_columns(network: SourceNetwork, candidate: SourceCandidate) -> frozenset[str]:
303
+ arm = candidate.datasource.non_partial_for if candidate.datasource else None
304
+ return frozenset(
305
+ network.equivalence.get(c.address, c.address)
306
+ for c in (arm.conditional.concept_arguments if arm else ())
307
+ )
308
+
309
+
310
+ def _filters_coarser(
311
+ network: SourceNetwork, coarse: SourceCandidate, filtered: SourceCandidate
312
+ ) -> bool:
313
+ """`coarse`'s grain is a function of `filtered`'s rows and `coarse` binds
314
+ the WHERE columns `filtered`'s arm reads, so under that WHERE it reads no
315
+ more rows (`Cost.filtered_dominated_le`)."""
316
+ arm = _arm_columns(network, filtered)
317
+ return (
318
+ bool(arm)
319
+ and coarse.grain != filtered.grain
320
+ and all(filtered.binds(address) for address in coarse.grain)
321
+ and all(coarse.binds(address) for address in arm)
322
+ )
323
+
324
+
325
+ def _dominated_read(network: SourceNetwork, node: str, read: frozenset[str]) -> bool:
326
+ """Another candidate reading every value `node` provides or joins on, from
327
+ the same columns, holds no more of the rows the query keeps: a source the
328
+ WHERE pre-filters (IMPLIED_EXACT) beside one read in full, unless the full
329
+ one is the coarser and applies that WHERE itself; or a row-complete source
330
+ at a coarser grain applying the arm of a pre-filtered `node`."""
294
331
  candidate = network.candidates[node]
295
- if not read or candidate.condition.partial_is_full:
332
+ if not read:
296
333
  return False
297
- return any(
298
- other.condition.partial_is_full
299
- and all(
300
- (mine := candidate.bindings.get(address)) is not None
301
- and (theirs := other.bindings.get(address)) is not None
302
- and mine.address == theirs.address
303
- for address in read
304
- )
305
- for name, other in network.candidates.items()
306
- if name != node
307
- )
334
+ filtered = candidate.condition.partial_is_full
335
+ for name, other in network.candidates.items():
336
+ if name == node or not _reads_alike(candidate, other, read):
337
+ continue
338
+ if filtered:
339
+ if (
340
+ network.row_complete(name)
341
+ and all(other.binds_fully(address) for address in read)
342
+ and _filters_coarser(network, other, candidate)
343
+ ):
344
+ return True
345
+ elif other.condition.partial_is_full and not _filters_coarser(
346
+ network, candidate, other
347
+ ):
348
+ return True
349
+ return False
308
350
 
309
351
 
310
352
  def _solution_for(
@@ -364,10 +406,10 @@ def _solution_for(
364
406
  for address in addresses
365
407
  if not _stored_key(network.candidates[node], address)
366
408
  ),
367
- unfiltered_sources=sum(
409
+ dominated_reads=sum(
368
410
  1
369
411
  for node in sources
370
- if _has_filtered_twin(network, node, assignments[node] | joined_on[node])
412
+ if _dominated_read(network, node, assignments[node] | joined_on[node])
371
413
  ),
372
414
  connectors=len(connectors),
373
415
  derived_joins=derived_joins,
@@ -478,7 +520,11 @@ def search_sources(network: SourceNetwork) -> SearchResult:
478
520
  continue
479
521
  connected = _reduce(network, cover, targets)
480
522
  key = tuple(sorted(connected))
481
- if key in seen or not _reads_a_scan(network, connected):
523
+ if (
524
+ key in seen
525
+ or not _reads_a_scan(network, connected)
526
+ or _bridges_unclaimed_rows(network, connected)
527
+ ):
482
528
  continue
483
529
  seen.add(key)
484
530
  reduced.append((connected, _binding_profile(network, connected, targets)))
@@ -501,6 +547,34 @@ def search_sources(network: SourceNetwork) -> SearchResult:
501
547
  return SearchResult(solution=best, limit=limit)
502
548
 
503
549
 
550
+ def _unclaimed_partial(candidate: SourceCandidate) -> bool:
551
+ """A `partial datasource` the WHERE does not complete: every grain column
552
+ holds only some rows, and no `~` claims the rest have none."""
553
+ datasource = candidate.datasource
554
+ if candidate.condition.partial_is_full or not isinstance(
555
+ datasource, BuildDatasource
556
+ ):
557
+ return False
558
+ grain = [candidate.bindings.get(address) for address in candidate.grain]
559
+ return bool(grain) and all(
560
+ binding is not None
561
+ and binding.partial
562
+ and binding.address not in datasource.column_level_partial_addresses
563
+ for binding in grain
564
+ )
565
+
566
+
567
+ def _bridges_unclaimed_rows(network: SourceNetwork, sources: frozenset[str]) -> bool:
568
+ """A source holding an unknown subset of its rows relates the sources on
569
+ either side of it only for that subset (`Cost.unimplied_partial_summary_loses_rows`):
570
+ it may end a join path, never be the only link between two others."""
571
+ return len(sources) > 2 and any(
572
+ _unclaimed_partial(network.candidates[node])
573
+ and not is_connected(network, sources - {node})
574
+ for node in sources
575
+ )
576
+
577
+
504
578
  def _reads_a_scan(network: SourceNetwork, sources: frozenset[str]) -> bool:
505
579
  """A derived connector exists to RELATE scans, so a cover made only of
506
580
  connectors reads no rows and is not an answer, however cheap it prices
@@ -546,7 +546,7 @@ dependencies = [
546
546
 
547
547
  [[package]]
548
548
  name = "trilogy-parser"
549
- version = "0.3.484"
549
+ version = "0.3.485"
550
550
  dependencies = [
551
551
  "clap",
552
552
  "pathdiff",
@@ -4,7 +4,7 @@ name = "trilogy-parser"
4
4
  # crates.io releases ride the same stream (see pythonpublish.yml), so a
5
5
  # published crate version always corresponds to the pytrilogy release
6
6
  # whose grammar it carries.
7
- version = "0.3.484"
7
+ version = "0.3.485"
8
8
  edition = "2021"
9
9
  description = "Parser and import/datasource dependency resolver for the Trilogy language"
10
10
  license = "MIT"
File without changes
File without changes
File without changes