pytrilogy 0.3.485__tar.gz → 0.3.487__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.
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/PKG-INFO +1 -1
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/__init__.py +1 -1
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/predicate_pushdown.py +23 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/aggregate_rollup.py +31 -1
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/concept_strategies_v4.py +46 -7
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/group_graph.py +170 -104
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/source_planning.py +4 -15
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/Cargo.lock +1 -1
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/Cargo.toml +1 -1
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/.scripts/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/.scripts/build_backend.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/.scripts/sync_version.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/LICENSE.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/README.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/pyproject.toml +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/README.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/constants.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/conversation.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/enums.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/execute.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/models.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/prompts.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/providers/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/providers/anthropic.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/providers/base.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/providers/deepseek.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/providers/google.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/providers/openai.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/providers/openrouter.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/providers/utils.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/ai/syntax_examples.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/authoring/README.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/authoring/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/constants.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/README.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/assertions.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/average_parts.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/casts.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/constants.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/domain_graph.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/domain_validation.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/enums.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/env_processor.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/environment_helpers.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/ergonomics.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/exceptions.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/fingerprint.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/functions.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/grain_pin.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/graph.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/graph_models.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/having_normalization.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/internal.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/like_patterns.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/models/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/models/author.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/models/build.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/models/build_environment.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/models/copying.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/models/core.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/models/datasource.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/models/environment.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/models/execute.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/models/keyspace.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimization.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/atom_contract.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/base_optimization.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/collapse_single_parent.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/existence_having_fold.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/filtered_aggregate.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/full_join_lowering.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/hide_unused_concept.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/identity_group.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/inline_datasource.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/join_hoist.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/join_upgrade.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/merge_irrelevant_group_by.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/null_safe_join.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/order_inner_joins.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/reuse_parent_lookup.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/semi_join_pushdown.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/strip_redundant_not_null.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/union_dim_pushdown.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/utils.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/optimizations/value_set_join_upgrade.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/README.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/basic_graph.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/condition_utility.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/constants.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/discovery_utility.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/discovery_validation.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/grain_utility.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/join_key_groups.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/join_resolution.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/model_ambiguity.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/node_generators/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/node_generators/common.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/node_generators/presence_probe.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/node_generators/select_helpers/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/node_generators/select_helpers/condition_routing.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/node_generators/select_helpers/datasource_nodes.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/node_generators/select_helpers/source_scoring.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/node_generators/select_merge_node.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/node_generators/select_node.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/nodes/README.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/nodes/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/nodes/base_node.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/nodes/filter_node.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/nodes/group_node.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/nodes/merge_node.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/nodes/recursive_node.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/nodes/subselect_node.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/nodes/union_node.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/nodes/unnest_node.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/nodes/window_node.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/null_provenance.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/partial_bridging.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/plan_trace.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/plan_trace_model.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/relation_rollup.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/scan_partials.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/source_dominance.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/statement_scope.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/utility.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/concept_graph.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/condition_injection.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/condition_placement.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/constants.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/edges.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/extent_ownership.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/final_cover.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/functional_dependency.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/group_behaviors.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/group_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/history.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/join_plan.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/keyspace.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/models.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/network_build.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/network_coalescing.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/network_model.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/network_obligations.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/network_search.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/network_topology.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/projection.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/region_domains.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/region_reads.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/renders.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/root_partition.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/staged_where.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/strategy_builder.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/union_arms.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/aggregate.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/basic.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/common.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/condition_sources.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/constant.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/dispatch.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/filter.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/group_to.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/multiselect.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/nested_select.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/recursive.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/root.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/rowset.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/rowset_witness.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/subselect.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/union.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/union_select.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/unnest.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_node_generators/window.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/query_processor.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/scope_diagnostics.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/statements/README.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/statements/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/statements/author.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/statements/build.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/statements/common.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/statements/execute.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/table_processor.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/union_find.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/utility.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/validation/README.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/validation/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/validation/common.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/validation/concept.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/validation/datasource.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/validation/environment.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/validation/fix.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/validation/rows.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/where_scope_normalization.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/base.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/bigquery.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/bigquery_engine.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/bigquery_persist.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/bigquery_staging.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/cancel.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/clickhouse.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/clickhouse_chdb.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/common.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/config.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/dataframe.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/duckdb.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/duckdb_pool.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/duckdb_uv.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/duckdb_vgi.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/enums.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/haybarn_engine.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/metadata.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/mock.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/mock_pattern.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/mysql.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/postgres.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/presto.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/python_source.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/results.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/snowflake.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/source_pushdown.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/sql_server.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/sqlite.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/dialect/table_function.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/engine.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/assertions.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/client_copy.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/config.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/envs.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/model_fingerprint.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/outputs.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/report.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/staged_write.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/state/AGENTS.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/state/CLAUDE.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/state/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/state/cache.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/state/declaration.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/state/exceptions.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/state/isolation.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/state/partitions.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/state/persistence.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/state/phases.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/state/snapshot.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/state/state_store.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/state/watermarks.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/execution/write_order.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/executor.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/hooks/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/hooks/base_hook.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/hooks/graph_hook.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/hooks/query_debugger.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/io/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/io/adapters.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/io/arrow.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/io/click_support.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/io/contract.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/io/describe.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/io/errors.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/io/runner.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/io/sinks.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/io/vgi.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/metadata/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parser.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/README.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/common.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/exceptions.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/helpers.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/parse_engine_v2.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/pretty.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/render.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/trilogy.lark +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/README.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/concept_syntax.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/errors.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/function_syntax.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/hydration.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/import_service.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/lark_backend.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/model.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/pest_backend.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rowset_semantics.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/chart_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/concept_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/conditional_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/datasource_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/expression_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/function_definition_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/function_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/import_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/merge_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/multiselect_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/operational_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/order_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/persist_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/rawsql_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/rowset_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/select_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/select_statement_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/statement_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/subselect_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/token_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/tvf_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules/type_rules.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/rules_context.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/select_finalize.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/semantic_scope.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/semantic_state.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/statement_planner.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/statement_plans.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/symbols.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/parsing/v2/syntax.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/py.typed +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/render.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/rendering/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/rendering/altair_renderer.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/rendering/base.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/rendering/chart_theme.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/rendering/rich_types.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/rendering/terminal_renderer.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/rendering/theme.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/report/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/report/backends/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/report/backends/base.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/report/backends/html.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/report/backends/png.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/report/charts.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/report/document.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/report/runner.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/report/tables.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/AGENTS.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/CLAUDE.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/README.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/agent.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/agent_info.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/agent_info_docs/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/agent_info_docs/cli.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/agent_info_docs/content.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/agent_info_docs/directory.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/agent_sessions.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/agent_sql_tools.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/agent_tools.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/click_utils.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/cloud.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/cloud_models.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/common.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/database.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/README.md +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/build.sh +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/examples/basic_usage.rs +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/src/directory_resolver.rs +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/src/graph.rs +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/src/lib.rs +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/src/main.rs +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/src/network_search.rs +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/src/parser.rs +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/src/python_bindings.rs +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/src/resolver.rs +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/src/trilogy.pest +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/src/trilogy_parser.rs +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/tests/base.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/tests/cli_integration.rs +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/tests/customer.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/tests/main.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/tests/orders.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/tests/parse_cost.rs +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/tests/public_api.rs +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/tests/test_data/base.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency/tests/test_data/consumer.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/dependency.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/display.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/display_core.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/display_execution.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/display_ingest.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/display_init.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/display_models.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/display_parallel.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/display_refresh.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/display_validation.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/env_commands.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/environment.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/explore.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/explore_seen.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/file.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/file_helpers/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/file_helpers/backends.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/file_helpers/preql_description.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/file_helpers/preql_validation.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/fmt.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/ingest.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/ingest_helpers/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/ingest_helpers/fk_inference.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/ingest_helpers/foreign_keys.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/ingest_helpers/formatting.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/ingest_helpers/introspection.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/ingest_helpers/typing.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/init.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/parallel_execution.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/plan.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/project_config.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/public.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/refresh.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/render.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/run.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/serve.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/serve_helpers/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/serve_helpers/connection_spec.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/serve_helpers/file_discovery.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/serve_helpers/index_generation.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/serve_helpers/jobs.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/serve_helpers/mcp_server.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/serve_helpers/models.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/serve_helpers/state_cache.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/serve_helpers/state_computation.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/serve_helpers/studio_bundle.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/single_execution.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/source.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/source_identity.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/state.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/testing.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/trilogy.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/scripts/validate_agent.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/staging.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/__init__.py +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/bytes.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/chart.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/collection.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/color.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/currency.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/date.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/display.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/geography.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/metric.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/money.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/net.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/ranking.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/report.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/std/semantic.preql +0 -0
- {pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/utility.py +0 -0
|
@@ -169,6 +169,23 @@ def _parent_holds_the_same_concepts(candidate: BuildConceptArgs, parent: CTE) ->
|
|
|
169
169
|
)
|
|
170
170
|
|
|
171
171
|
|
|
172
|
+
def _parent_holds_partial(
|
|
173
|
+
candidate: BuildConceptArgs,
|
|
174
|
+
parent: CTE,
|
|
175
|
+
inverse_map: dict[str, list[CTE | UnionCTE]],
|
|
176
|
+
) -> bool:
|
|
177
|
+
"""A child of `parent` re-aggregates a column the predicate reads under
|
|
178
|
+
the same address, so `parent` holds one partial per finer group, not the
|
|
179
|
+
value the predicate tests (`Rollup.coarse_gate_on_partial_misfilters`)."""
|
|
180
|
+
rolled = {
|
|
181
|
+
c.address
|
|
182
|
+
for child in inverse_map.get(parent.name, [])
|
|
183
|
+
if isinstance(child, CTE) and child.group_to_grain
|
|
184
|
+
for c in child.rollup_concepts
|
|
185
|
+
}
|
|
186
|
+
return any(arg.address in rolled for arg in candidate.row_arguments)
|
|
187
|
+
|
|
188
|
+
|
|
172
189
|
def _parent_materialized_addrs(parent: CTE | UnionCTE) -> set[str]:
|
|
173
190
|
"""Addresses a parent CTE exposes as plain output columns: a non-empty
|
|
174
191
|
``source_map`` entry means the concept is pulled from upstream rather than
|
|
@@ -569,6 +586,12 @@ class PredicatePushdown(OptimizationRule):
|
|
|
569
586
|
return False
|
|
570
587
|
if not _parent_holds_the_same_concepts(candidate, parent_cte):
|
|
571
588
|
return False
|
|
589
|
+
if _parent_holds_partial(candidate, parent_cte, inverse_map):
|
|
590
|
+
self.debug(
|
|
591
|
+
f"{parent_cte.name} holds a partial of {candidate}'s value that a "
|
|
592
|
+
"child re-aggregates under the same address; not pushing"
|
|
593
|
+
)
|
|
594
|
+
return False
|
|
572
595
|
materialized = _rendered_source_columns(parent_cte)
|
|
573
596
|
|
|
574
597
|
if not row_conditions or not materialized:
|
|
@@ -212,20 +212,36 @@ def _conditions_supported(
|
|
|
212
212
|
datasource: BuildDatasource,
|
|
213
213
|
conditions: BuildWhereClause | None,
|
|
214
214
|
concepts_by_address: Mapping[str, BuildConcept] | None = None,
|
|
215
|
+
joined: bool = False,
|
|
215
216
|
) -> bool:
|
|
217
|
+
"""With `joined`, an aggregate at a grain inside the summary's
|
|
218
|
+
(`sum(x) by city` beside `(city, species)`) is a function of its key, which
|
|
219
|
+
the joined plan computes in its own group and joins back
|
|
220
|
+
(`Rollup.coarse_group_value_filter_exact`). A scan of the summary alone
|
|
221
|
+
would read the stored partial as that value."""
|
|
216
222
|
if not conditions:
|
|
217
223
|
return True
|
|
224
|
+
grain = set(datasource.grain.components)
|
|
218
225
|
return _concepts_reachable(
|
|
219
226
|
datasource,
|
|
220
227
|
[
|
|
221
228
|
c
|
|
222
229
|
for c in conditions.row_arguments
|
|
223
230
|
if c.granularity != Granularity.SINGLE_ROW
|
|
231
|
+
and not (joined and _keyed_aggregate(c, grain))
|
|
224
232
|
],
|
|
225
233
|
concepts_by_address,
|
|
226
234
|
)
|
|
227
235
|
|
|
228
236
|
|
|
237
|
+
def _keyed_aggregate(concept: BuildConcept, grain: set[str]) -> bool:
|
|
238
|
+
return (
|
|
239
|
+
concept.derivation == Derivation.AGGREGATE
|
|
240
|
+
and bool(concept.grain.components)
|
|
241
|
+
and concept.grain.components <= grain
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
|
|
229
245
|
def filter_finer_row_args(
|
|
230
246
|
conditions: BuildWhereClause | None,
|
|
231
247
|
target_grain: BuildGrain,
|
|
@@ -244,6 +260,20 @@ def filter_finer_row_args(
|
|
|
244
260
|
]
|
|
245
261
|
|
|
246
262
|
|
|
263
|
+
def joinable_property(
|
|
264
|
+
concept: BuildConcept | None, datasource: BuildDatasource
|
|
265
|
+
) -> bool:
|
|
266
|
+
"""A dimension's column keyed on `datasource`'s grain: a join onto its rows
|
|
267
|
+
supplies it at that grain."""
|
|
268
|
+
return (
|
|
269
|
+
concept is not None
|
|
270
|
+
and concept.lineage is None
|
|
271
|
+
and concept.purpose == Purpose.PROPERTY
|
|
272
|
+
and bool(concept.keys)
|
|
273
|
+
and set(concept.keys or ()) <= set(datasource.grain.components)
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
|
|
247
277
|
def finer_than_grain(
|
|
248
278
|
concept: BuildConcept,
|
|
249
279
|
grain: BuildGrain,
|
|
@@ -351,7 +381,7 @@ def get_rollup_concepts(
|
|
|
351
381
|
"""The requested aggregates `datasource` rolls up to `target_grain`. With
|
|
352
382
|
`joined`, `agg(x ? c)` may read `c` from a join onto the summary's rows
|
|
353
383
|
(`_datasource_has_matching_rollup_aggregate`)."""
|
|
354
|
-
if not _conditions_supported(datasource, conditions, concepts_by_address):
|
|
384
|
+
if not _conditions_supported(datasource, conditions, concepts_by_address, joined):
|
|
355
385
|
return []
|
|
356
386
|
reach = concepts_by_address if joined else None
|
|
357
387
|
|
|
@@ -28,7 +28,7 @@ from contextlib import nullcontext
|
|
|
28
28
|
|
|
29
29
|
from trilogy.constants import logger
|
|
30
30
|
from trilogy.core import graph as nx
|
|
31
|
-
from trilogy.core.enums import Derivation
|
|
31
|
+
from trilogy.core.enums import Derivation, Granularity
|
|
32
32
|
from trilogy.core.exceptions import UnbuiltGroupException
|
|
33
33
|
from trilogy.core.graph_models import ReferenceGraph
|
|
34
34
|
from trilogy.core.models.build import (
|
|
@@ -52,6 +52,7 @@ from trilogy.core.processing.aggregate_rollup import (
|
|
|
52
52
|
at_own_grain,
|
|
53
53
|
filter_finer_row_args,
|
|
54
54
|
holds_every_kept_row,
|
|
55
|
+
joinable_property,
|
|
55
56
|
source_rollup_concepts,
|
|
56
57
|
sourced_arguments,
|
|
57
58
|
)
|
|
@@ -849,7 +850,14 @@ def _rollup_sources(
|
|
|
849
850
|
summaries read."""
|
|
850
851
|
out: list[BuildDatasource] = []
|
|
851
852
|
sources: list[BuildDatasource | BuildUnionDatasource] = [*datasources, *unions]
|
|
853
|
+
gated = _coarse_gate_beside_row_columns(where, target_grain)
|
|
852
854
|
for source in sources:
|
|
855
|
+
if (
|
|
856
|
+
gated
|
|
857
|
+
and isinstance(source, BuildDatasource)
|
|
858
|
+
and _coarse_gate(where, source)
|
|
859
|
+
):
|
|
860
|
+
continue
|
|
853
861
|
if not holds_every_kept_row(source, where):
|
|
854
862
|
continue
|
|
855
863
|
if isinstance(source, BuildDatasource) and not (
|
|
@@ -882,6 +890,33 @@ def _rollup_sources(
|
|
|
882
890
|
return out
|
|
883
891
|
|
|
884
892
|
|
|
893
|
+
def _coarse_gate(where: BuildWhereClause | None, source: BuildDatasource) -> bool:
|
|
894
|
+
"""The WHERE reads an aggregate at a grain inside `source`'s but not at
|
|
895
|
+
it (`sum(x) by city` beside `(city, species)`): its value is a re-sum the
|
|
896
|
+
joined plan computes in its own group."""
|
|
897
|
+
grain = set(source.grain.components)
|
|
898
|
+
return where is not None and any(
|
|
899
|
+
c.derivation == Derivation.AGGREGATE
|
|
900
|
+
and c.granularity != Granularity.SINGLE_ROW
|
|
901
|
+
and set(c.grain.components) < grain
|
|
902
|
+
for c in where.row_arguments
|
|
903
|
+
)
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
def _coarse_gate_beside_row_columns(
|
|
907
|
+
where: BuildWhereClause | None, target_grain: BuildGrain
|
|
908
|
+
) -> bool:
|
|
909
|
+
"""A row column beside the gate that the target does not group by
|
|
910
|
+
(`species != 'Tilia'` at `tree_form`) widens the pinned request past the
|
|
911
|
+
target, and the search that takes over re-aggregates the gate at it."""
|
|
912
|
+
return where is not None and any(
|
|
913
|
+
not c.is_aggregate
|
|
914
|
+
and c.granularity != Granularity.SINGLE_ROW
|
|
915
|
+
and c.address not in target_grain.components
|
|
916
|
+
for c in where.row_arguments
|
|
917
|
+
)
|
|
918
|
+
|
|
919
|
+
|
|
885
920
|
def _nested_rollup_roots(
|
|
886
921
|
mandatory_list: list[BuildConcept],
|
|
887
922
|
roots: set[str],
|
|
@@ -988,13 +1023,10 @@ def _finer_filter_reaches_rollup(
|
|
|
988
1023
|
demands = [c for c in mandatory_list if c.address not in rolled_roots]
|
|
989
1024
|
assert where is not None
|
|
990
1025
|
# an atom over a stored aggregate filters only the pinned scan's own rows,
|
|
991
|
-
# so every other demand must be a column of that scan
|
|
1026
|
+
# so every other demand must be a column of that scan, or a dimension's
|
|
1027
|
+
# column keyed on its grain (`_plan_joined_filter_rollup` joins it on)
|
|
992
1028
|
if not is_scalar_condition(where.conditional):
|
|
993
|
-
return any(
|
|
994
|
-
{c.canonical_address for c in demands}
|
|
995
|
-
<= {c.canonical_address for c in ds.output_concepts}
|
|
996
|
-
for ds in rollup_sources
|
|
997
|
-
)
|
|
1029
|
+
return any(_rides_summary_scan(demands, ds) for ds in rollup_sources)
|
|
998
1030
|
reached = walk_lineage(
|
|
999
1031
|
[c for c in mandatory_list if c.address not in rolled_roots],
|
|
1000
1032
|
descend=lambda c: c.address not in rolled_roots,
|
|
@@ -1024,6 +1056,13 @@ def _finer_filter_reaches_rollup(
|
|
|
1024
1056
|
)
|
|
1025
1057
|
|
|
1026
1058
|
|
|
1059
|
+
def _rides_summary_scan(demands: list[BuildConcept], ds: BuildDatasource) -> bool:
|
|
1060
|
+
bound = {c.canonical_address for c in ds.output_concepts}
|
|
1061
|
+
return all(
|
|
1062
|
+
c.canonical_address in bound or joinable_property(c, ds) for c in demands
|
|
1063
|
+
)
|
|
1064
|
+
|
|
1065
|
+
|
|
1027
1066
|
def _aggregates_rolled_groups(
|
|
1028
1067
|
concept: BuildConcept,
|
|
1029
1068
|
rolled_roots: set[str],
|
|
@@ -17,7 +17,7 @@ single bucket). No derivation is privileged in the orchestrator.
|
|
|
17
17
|
|
|
18
18
|
from collections import defaultdict
|
|
19
19
|
from collections.abc import Sequence
|
|
20
|
-
from dataclasses import dataclass, field
|
|
20
|
+
from dataclasses import dataclass, field
|
|
21
21
|
|
|
22
22
|
from trilogy.constants import logger
|
|
23
23
|
from trilogy.core import graph as nx
|
|
@@ -2344,13 +2344,14 @@ def build_group_graph(
|
|
|
2344
2344
|
environment,
|
|
2345
2345
|
rollup_padded,
|
|
2346
2346
|
)
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
)
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
group_graph, group_edges, attrs, buckets, concept_attrs,
|
|
2347
|
+
folds = _elect_folds(group_graph, group_edges, attrs, concept_attrs)
|
|
2348
|
+
grouping = _elect_grouping_providers(group_graph, attrs, environment, folds)
|
|
2349
|
+
placed = _place_projections(group_graph, group_edges, attrs, buckets, grouping)
|
|
2350
|
+
_fold_groups(group_graph, group_edges, attrs, buckets, folds)
|
|
2351
|
+
read = _read_dimensions(
|
|
2352
|
+
group_graph, group_edges, attrs, buckets, concept_attrs, placed
|
|
2353
2353
|
)
|
|
2354
|
+
_rehome_groups(group_graph, group_edges, attrs, buckets, environment, placed | read)
|
|
2354
2355
|
trace_group_graph(
|
|
2355
2356
|
"FINAL added, concept sets computed, sources regrafted",
|
|
2356
2357
|
group_graph,
|
|
@@ -2457,17 +2458,15 @@ def trace_group_graph(
|
|
|
2457
2458
|
|
|
2458
2459
|
@dataclass(frozen=True)
|
|
2459
2460
|
class RowProvider:
|
|
2460
|
-
"""The row source a
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
(`_as_rewrite`)
|
|
2464
|
-
|
|
2461
|
+
"""The row source a group is re-homed onto: the parent it reads, the
|
|
2462
|
+
lineage parents that parent replaces, and the dimension ROOT minted for
|
|
2463
|
+
it. A placement drops; a dimension read drops and mints; a row provider
|
|
2464
|
+
elected in the rehome (`_as_rewrite`) holds only the edge the graph
|
|
2465
|
+
lacks."""
|
|
2465
2466
|
|
|
2466
2467
|
parent: str | None
|
|
2467
2468
|
drop: frozenset[str] = frozenset()
|
|
2468
2469
|
minted: GroupBucket | None = None
|
|
2469
|
-
# the parent renders the group in its own SELECT: the group folds into it
|
|
2470
|
-
inline: bool = False
|
|
2471
2470
|
|
|
2472
2471
|
|
|
2473
2472
|
def _regraft_candidate(
|
|
@@ -2865,28 +2864,54 @@ def _inline_window(
|
|
|
2865
2864
|
return parent
|
|
2866
2865
|
|
|
2867
2866
|
|
|
2868
|
-
def
|
|
2867
|
+
def _elect_folds(
|
|
2869
2868
|
group_graph: nx.DiGraph,
|
|
2870
2869
|
group_edges: EdgeMap,
|
|
2871
2870
|
attrs: dict[str, GroupAttrs],
|
|
2872
2871
|
concept_attrs: dict[str, ConceptAttrs],
|
|
2872
|
+
) -> dict[str, str]:
|
|
2873
|
+
"""Each scalar BASIC a WINDOW renders inline, to that WINDOW, elected over
|
|
2874
|
+
the graph stage 2 built. A fold target is a WINDOW, so no fold removes
|
|
2875
|
+
another's."""
|
|
2876
|
+
folds: dict[str, str] = {}
|
|
2877
|
+
for gid in group_graph.nodes:
|
|
2878
|
+
if gid == FINAL_NODE_ID:
|
|
2879
|
+
continue
|
|
2880
|
+
window = _inline_window(group_graph, group_edges, attrs, concept_attrs, gid)
|
|
2881
|
+
if window is not None:
|
|
2882
|
+
folds[gid] = window
|
|
2883
|
+
return folds
|
|
2884
|
+
|
|
2885
|
+
|
|
2886
|
+
def _fold_groups(
|
|
2887
|
+
group_graph: nx.DiGraph,
|
|
2888
|
+
group_edges: EdgeMap,
|
|
2889
|
+
attrs: dict[str, GroupAttrs],
|
|
2890
|
+
buckets: dict[str, GroupBucket],
|
|
2891
|
+
folds: dict[str, str],
|
|
2892
|
+
) -> None:
|
|
2893
|
+
for gid, window in folds.items():
|
|
2894
|
+
_absorb_group(gid, window, group_graph, group_edges, attrs, buckets)
|
|
2895
|
+
|
|
2896
|
+
|
|
2897
|
+
def _elect_grouping_providers(
|
|
2898
|
+
group_graph: nx.DiGraph,
|
|
2899
|
+
attrs: dict[str, GroupAttrs],
|
|
2873
2900
|
environment: BuildEnvironment,
|
|
2901
|
+
folds: dict[str, str],
|
|
2874
2902
|
) -> dict[str, str]:
|
|
2875
2903
|
"""Each terminal scalar projection's grouping provider, elected over the
|
|
2876
|
-
graph stage 2 built. A
|
|
2877
|
-
|
|
2904
|
+
graph stage 2 built. A fold outranks it: that projection keeps its grain
|
|
2905
|
+
and renders in its WINDOW."""
|
|
2878
2906
|
providers: dict[str, str] = {}
|
|
2879
2907
|
for gid in group_graph.nodes:
|
|
2880
|
-
if gid == FINAL_NODE_ID:
|
|
2908
|
+
if gid == FINAL_NODE_ID or gid in folds:
|
|
2881
2909
|
continue
|
|
2882
2910
|
provider = _terminal_basic_grouping_provider(
|
|
2883
2911
|
group_graph, attrs, gid, environment
|
|
2884
2912
|
)
|
|
2885
|
-
if provider is None
|
|
2886
|
-
|
|
2887
|
-
):
|
|
2888
|
-
continue
|
|
2889
|
-
providers[gid] = provider
|
|
2913
|
+
if provider is not None:
|
|
2914
|
+
providers[gid] = provider
|
|
2890
2915
|
return providers
|
|
2891
2916
|
|
|
2892
2917
|
|
|
@@ -2904,50 +2929,67 @@ def _state_projection_grains(
|
|
|
2904
2929
|
buckets[gid].grain_components = grain
|
|
2905
2930
|
|
|
2906
2931
|
|
|
2907
|
-
def
|
|
2932
|
+
def _projection_placements(
|
|
2908
2933
|
group_graph: nx.DiGraph,
|
|
2909
2934
|
group_edges: EdgeMap,
|
|
2910
2935
|
attrs: dict[str, GroupAttrs],
|
|
2911
|
-
buckets: dict[str, GroupBucket],
|
|
2912
|
-
concept_attrs: dict[str, ConceptAttrs],
|
|
2913
|
-
environment: BuildEnvironment,
|
|
2914
2936
|
grouping: dict[str, str],
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
elif not _grain_needed_by_independent_sibling(
|
|
2927
|
-
group_graph, attrs, gid, grouping_provider, grouping
|
|
2928
|
-
):
|
|
2937
|
+
) -> dict[str, RowProvider]:
|
|
2938
|
+
"""Each stated projection's edge onto its grouping provider and the
|
|
2939
|
+
lineage parents it replaces, read over the graph stage 2 built. A
|
|
2940
|
+
projection whose provider's grain an independent sibling co-grains on is
|
|
2941
|
+
not placed: it keeps its parents and takes a row provider."""
|
|
2942
|
+
placements: dict[str, RowProvider] = {}
|
|
2943
|
+
for gid, provider in grouping.items():
|
|
2944
|
+
if _grain_needed_by_independent_sibling(
|
|
2945
|
+
group_graph, attrs, gid, provider, grouping
|
|
2946
|
+
):
|
|
2947
|
+
continue
|
|
2929
2948
|
# Placed at the provider's grain, the projection has no use for a
|
|
2930
2949
|
# finer relation the provider was built from. Joined back, it pairs
|
|
2931
2950
|
# the provider's groups on a non-key (a region domain on a nullable
|
|
2932
2951
|
# description) and drops or multiplies them.
|
|
2933
|
-
provider_ancestors = nx.ancestors(group_graph,
|
|
2952
|
+
provider_ancestors = nx.ancestors(group_graph, provider)
|
|
2934
2953
|
drop = frozenset(
|
|
2935
2954
|
pred
|
|
2936
2955
|
for pred in lineage_predecessors(group_graph, group_edges, gid)
|
|
2937
2956
|
if pred in provider_ancestors
|
|
2938
2957
|
)
|
|
2939
|
-
|
|
2958
|
+
placements[gid] = RowProvider(provider, drop)
|
|
2959
|
+
return placements
|
|
2960
|
+
|
|
2961
|
+
|
|
2962
|
+
def _place_projections(
|
|
2963
|
+
group_graph: nx.DiGraph,
|
|
2964
|
+
group_edges: EdgeMap,
|
|
2965
|
+
attrs: dict[str, GroupAttrs],
|
|
2966
|
+
buckets: dict[str, GroupBucket],
|
|
2967
|
+
grouping: dict[str, str],
|
|
2968
|
+
) -> frozenset[str]:
|
|
2969
|
+
"""State each terminal projection's grain and, where no independent
|
|
2970
|
+
sibling needs that grain, its lineage: an edge from its grouping provider
|
|
2971
|
+
in place of the parents the provider was built from. Every projection
|
|
2972
|
+
feeds only FINAL, so no placement moves another group's ancestors.
|
|
2973
|
+
Returns the projections placed."""
|
|
2974
|
+
_state_projection_grains(attrs, buckets, grouping)
|
|
2975
|
+
placements = _projection_placements(group_graph, group_edges, attrs, grouping)
|
|
2976
|
+
for gid, placement in placements.items():
|
|
2977
|
+
_apply_row_provider(group_graph, group_edges, attrs, buckets, gid, placement)
|
|
2978
|
+
return frozenset(placements)
|
|
2979
|
+
|
|
2980
|
+
|
|
2981
|
+
def _elect_row_provider(
|
|
2982
|
+
group_graph: nx.DiGraph,
|
|
2983
|
+
group_edges: EdgeMap,
|
|
2984
|
+
attrs: dict[str, GroupAttrs],
|
|
2985
|
+
environment: BuildEnvironment,
|
|
2986
|
+
gid: str,
|
|
2987
|
+
) -> RowProvider | None:
|
|
2988
|
+
"""Pick `gid`'s row source over the graph; mutates nothing. The choices,
|
|
2989
|
+
in order: a full-coverage sibling, a partial spine."""
|
|
2940
2990
|
parent_gid = _regraft_candidate(
|
|
2941
2991
|
group_graph, group_edges, attrs, gid, allow_partial=False
|
|
2942
|
-
)
|
|
2943
|
-
if parent_gid is not None:
|
|
2944
|
-
return RowProvider(parent_gid)
|
|
2945
|
-
dimension = _synthetic_dimension_regraft_parent(
|
|
2946
|
-
group_graph, group_edges, attrs, buckets, concept_attrs, gid
|
|
2947
|
-
)
|
|
2948
|
-
if dimension is not None:
|
|
2949
|
-
return dimension
|
|
2950
|
-
parent_gid = _regraft_candidate(
|
|
2992
|
+
) or _regraft_candidate(
|
|
2951
2993
|
group_graph,
|
|
2952
2994
|
group_edges,
|
|
2953
2995
|
attrs,
|
|
@@ -2958,6 +3000,63 @@ def _elect_row_provider(
|
|
|
2958
3000
|
return None if parent_gid is None else RowProvider(parent_gid)
|
|
2959
3001
|
|
|
2960
3002
|
|
|
3003
|
+
def _rehomeable(
|
|
3004
|
+
attrs: dict[str, GroupAttrs], gid: str, settled: frozenset[str]
|
|
3005
|
+
) -> bool:
|
|
3006
|
+
return (
|
|
3007
|
+
gid != FINAL_NODE_ID
|
|
3008
|
+
and gid not in settled
|
|
3009
|
+
and attrs[gid].derivation in _REGRAFTABLE_DERIVATIONS
|
|
3010
|
+
)
|
|
3011
|
+
|
|
3012
|
+
|
|
3013
|
+
def _elect_dimension_reads(
|
|
3014
|
+
group_graph: nx.DiGraph,
|
|
3015
|
+
group_edges: EdgeMap,
|
|
3016
|
+
attrs: dict[str, GroupAttrs],
|
|
3017
|
+
buckets: dict[str, GroupBucket],
|
|
3018
|
+
concept_attrs: dict[str, ConceptAttrs],
|
|
3019
|
+
placed: frozenset[str],
|
|
3020
|
+
) -> dict[str, RowProvider]:
|
|
3021
|
+
"""Each unplaced BASIC with no full-coverage sibling that reads its inputs
|
|
3022
|
+
off a dimension ROOT, elected over the folded graph. A sibling outranks
|
|
3023
|
+
a dimension, so a group with one is left to the rehome."""
|
|
3024
|
+
reads: dict[str, RowProvider] = {}
|
|
3025
|
+
for gid in group_graph.nodes:
|
|
3026
|
+
if not _rehomeable(attrs, gid, placed):
|
|
3027
|
+
continue
|
|
3028
|
+
if _regraft_candidate(
|
|
3029
|
+
group_graph, group_edges, attrs, gid, allow_partial=False
|
|
3030
|
+
):
|
|
3031
|
+
continue
|
|
3032
|
+
read = _synthetic_dimension_regraft_parent(
|
|
3033
|
+
group_graph, group_edges, attrs, buckets, concept_attrs, gid
|
|
3034
|
+
)
|
|
3035
|
+
if read is not None:
|
|
3036
|
+
reads[gid] = read
|
|
3037
|
+
return reads
|
|
3038
|
+
|
|
3039
|
+
|
|
3040
|
+
def _read_dimensions(
|
|
3041
|
+
group_graph: nx.DiGraph,
|
|
3042
|
+
group_edges: EdgeMap,
|
|
3043
|
+
attrs: dict[str, GroupAttrs],
|
|
3044
|
+
buckets: dict[str, GroupBucket],
|
|
3045
|
+
concept_attrs: dict[str, ConceptAttrs],
|
|
3046
|
+
placed: frozenset[str],
|
|
3047
|
+
) -> frozenset[str]:
|
|
3048
|
+
"""Re-home each dimension read onto its ROOT, minting it when none covers
|
|
3049
|
+
its inputs, in place of the ROOT parents it replaces. Every read is
|
|
3050
|
+
elected before any is applied. Returns the groups read, a pick that
|
|
3051
|
+
changes nothing included: the rehome elects none of them."""
|
|
3052
|
+
reads = _elect_dimension_reads(
|
|
3053
|
+
group_graph, group_edges, attrs, buckets, concept_attrs, placed
|
|
3054
|
+
)
|
|
3055
|
+
for gid, read in reads.items():
|
|
3056
|
+
_apply_row_provider(group_graph, group_edges, attrs, buckets, gid, read)
|
|
3057
|
+
return frozenset(reads)
|
|
3058
|
+
|
|
3059
|
+
|
|
2961
3060
|
def _apply_row_provider(
|
|
2962
3061
|
group_graph: nx.DiGraph,
|
|
2963
3062
|
group_edges: EdgeMap,
|
|
@@ -2983,11 +3082,8 @@ def _apply_row_provider(
|
|
|
2983
3082
|
def _as_rewrite(
|
|
2984
3083
|
group_graph: nx.DiGraph, gid: str, provider: RowProvider
|
|
2985
3084
|
) -> RowProvider | None:
|
|
2986
|
-
"""`provider` less what the graph
|
|
2987
|
-
|
|
2988
|
-
mints nothing."""
|
|
2989
|
-
if provider.inline:
|
|
2990
|
-
return provider
|
|
3085
|
+
"""`provider` less what the graph already holds, or None when it changes
|
|
3086
|
+
nothing: its parent is already a parent, and it drops and mints nothing."""
|
|
2991
3087
|
drop = frozenset(p for p in provider.drop if group_graph.has_edge(p, gid))
|
|
2992
3088
|
minted = provider.minted
|
|
2993
3089
|
if minted is not None and minted.group_id in group_graph:
|
|
@@ -3004,54 +3100,30 @@ def _elect_row_providers(
|
|
|
3004
3100
|
group_graph: nx.DiGraph,
|
|
3005
3101
|
group_edges: EdgeMap,
|
|
3006
3102
|
attrs: dict[str, GroupAttrs],
|
|
3007
|
-
buckets: dict[str, GroupBucket],
|
|
3008
|
-
concept_attrs: dict[str, ConceptAttrs],
|
|
3009
3103
|
environment: BuildEnvironment,
|
|
3010
|
-
|
|
3104
|
+
settled: frozenset[str],
|
|
3011
3105
|
) -> dict[str, RowProvider]:
|
|
3012
|
-
"""Each regraftable group
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
`
|
|
3106
|
+
"""Each regraftable group not placed at its grouping provider nor read
|
|
3107
|
+
off a dimension whose best row source is already built, elected over one
|
|
3108
|
+
graph (stage 2's, with the projections placed, the folds made and the
|
|
3109
|
+
dimensions read), as the rewrite it makes of that graph. A provider only
|
|
3110
|
+
adds a lineage edge.
|
|
3111
|
+
|
|
3112
|
+
Concrete datasource selection remains in `source_planning` and
|
|
3113
|
+
StrategyNode construction in `strategy_builder`.
|
|
3019
3114
|
"""
|
|
3020
3115
|
providers: dict[str, RowProvider] = {}
|
|
3021
3116
|
for gid in list(group_graph.nodes):
|
|
3022
|
-
if (
|
|
3023
|
-
gid == FINAL_NODE_ID
|
|
3024
|
-
or attrs[gid].derivation not in _REGRAFTABLE_DERIVATIONS
|
|
3025
|
-
):
|
|
3117
|
+
if not _rehomeable(attrs, gid, settled):
|
|
3026
3118
|
continue
|
|
3027
3119
|
provider = _elect_row_provider(
|
|
3028
|
-
group_graph,
|
|
3029
|
-
group_edges,
|
|
3030
|
-
attrs,
|
|
3031
|
-
buckets,
|
|
3032
|
-
concept_attrs,
|
|
3033
|
-
environment,
|
|
3034
|
-
grouping,
|
|
3035
|
-
gid,
|
|
3120
|
+
group_graph, group_edges, attrs, environment, gid
|
|
3036
3121
|
)
|
|
3037
3122
|
if provider is not None:
|
|
3038
3123
|
provider = _as_rewrite(group_graph, gid, provider)
|
|
3039
3124
|
if provider is not None:
|
|
3040
3125
|
providers[gid] = provider
|
|
3041
|
-
|
|
3042
|
-
return {
|
|
3043
|
-
gid: replace(p, drop=frozenset(folded.get(pred, pred) for pred in p.drop))
|
|
3044
|
-
for gid, p in providers.items()
|
|
3045
|
-
}
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
def _folds(providers: dict[str, RowProvider]) -> dict[str, str]:
|
|
3049
|
-
"""Each group its provider renders inline, to that provider."""
|
|
3050
|
-
return {
|
|
3051
|
-
gid: p.parent
|
|
3052
|
-
for gid, p in providers.items()
|
|
3053
|
-
if p.inline and p.parent is not None
|
|
3054
|
-
}
|
|
3126
|
+
return providers
|
|
3055
3127
|
|
|
3056
3128
|
|
|
3057
3129
|
def _rehome_groups(
|
|
@@ -3059,19 +3131,13 @@ def _rehome_groups(
|
|
|
3059
3131
|
group_edges: EdgeMap,
|
|
3060
3132
|
attrs: dict[str, GroupAttrs],
|
|
3061
3133
|
buckets: dict[str, GroupBucket],
|
|
3062
|
-
concept_attrs: dict[str, ConceptAttrs],
|
|
3063
3134
|
environment: BuildEnvironment,
|
|
3064
|
-
|
|
3135
|
+
settled: frozenset[str],
|
|
3065
3136
|
) -> None:
|
|
3066
|
-
"""Elect every group's row provider over
|
|
3067
|
-
|
|
3068
|
-
group its provider renders inline and apply the rest: no election reads
|
|
3069
|
-
another's fold or edges."""
|
|
3137
|
+
"""Elect every unsettled group's row provider over one graph, then apply
|
|
3138
|
+
them all: no election reads another's edges."""
|
|
3070
3139
|
providers = _elect_row_providers(
|
|
3071
|
-
group_graph, group_edges, attrs,
|
|
3140
|
+
group_graph, group_edges, attrs, environment, settled
|
|
3072
3141
|
)
|
|
3073
|
-
for gid, parent in _folds(providers).items():
|
|
3074
|
-
_absorb_group(gid, parent, group_graph, group_edges, attrs, buckets)
|
|
3075
3142
|
for gid, provider in providers.items():
|
|
3076
|
-
|
|
3077
|
-
_apply_row_provider(group_graph, group_edges, attrs, buckets, gid, provider)
|
|
3143
|
+
_apply_row_provider(group_graph, group_edges, attrs, buckets, gid, provider)
|
{pytrilogy-0.3.485 → pytrilogy-0.3.487}/trilogy/core/processing/v4_helper/source_planning.py
RENAMED
|
@@ -16,7 +16,7 @@ from typing import cast
|
|
|
16
16
|
|
|
17
17
|
from trilogy.constants import logger
|
|
18
18
|
from trilogy.core.constants import parent_axis_keys
|
|
19
|
-
from trilogy.core.enums import Derivation, Granularity, JoinType
|
|
19
|
+
from trilogy.core.enums import Derivation, Granularity, JoinType
|
|
20
20
|
from trilogy.core.graph_models import ReferenceGraph, concept_to_node
|
|
21
21
|
from trilogy.core.models.build import (
|
|
22
22
|
BuildConcept,
|
|
@@ -33,6 +33,7 @@ from trilogy.core.processing.aggregate_rollup import (
|
|
|
33
33
|
at_own_grain,
|
|
34
34
|
filter_finer_row_args,
|
|
35
35
|
holds_every_kept_row,
|
|
36
|
+
joinable_property,
|
|
36
37
|
joined_condition_columns,
|
|
37
38
|
merge_rollup_concepts,
|
|
38
39
|
source_rollup_concepts,
|
|
@@ -1705,7 +1706,8 @@ def _finer_filter_rollup_source(
|
|
|
1705
1706
|
if not all(
|
|
1706
1707
|
c in canonicals
|
|
1707
1708
|
or (
|
|
1708
|
-
|
|
1709
|
+
len(arms) == 1
|
|
1710
|
+
and joinable_property(environment.concepts.get(c), arms[0])
|
|
1709
1711
|
and all(
|
|
1710
1712
|
at_own_grain(a, target_grain, environment.concepts)
|
|
1711
1713
|
for a in aggregates
|
|
@@ -1744,19 +1746,6 @@ def _finer_filter_rollup_source(
|
|
|
1744
1746
|
return matches[0]
|
|
1745
1747
|
|
|
1746
1748
|
|
|
1747
|
-
def _joinable_property(
|
|
1748
|
-
concept: BuildConcept | None, arms: list[BuildDatasource]
|
|
1749
|
-
) -> bool:
|
|
1750
|
-
return (
|
|
1751
|
-
concept is not None
|
|
1752
|
-
and concept.lineage is None
|
|
1753
|
-
and concept.purpose == Purpose.PROPERTY
|
|
1754
|
-
and bool(concept.keys)
|
|
1755
|
-
and len(arms) == 1
|
|
1756
|
-
and set(concept.keys or ()) <= set(arms[0].grain.components)
|
|
1757
|
-
)
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
1749
|
def _rolls_every_aggregate(
|
|
1761
1750
|
datasource: BuildDatasource | BuildUnionDatasource,
|
|
1762
1751
|
request: SourceRequest,
|
|
@@ -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.
|
|
7
|
+
version = "0.3.487"
|
|
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
|