pytrilogy 0.0.3.67__tar.gz → 0.0.3.68__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.

Potentially problematic release.


This version of pytrilogy might be problematic. Click here for more details.

Files changed (149) hide show
  1. {pytrilogy-0.0.3.67/pytrilogy.egg-info → pytrilogy-0.0.3.68}/PKG-INFO +1 -1
  2. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68/pytrilogy.egg-info}/PKG-INFO +1 -1
  3. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_statements.py +1 -1
  4. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/__init__.py +1 -1
  5. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/discovery_node_factory.py +8 -7
  6. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/select_merge_node.py +7 -2
  7. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/synonym_node.py +8 -13
  8. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/utility.py +17 -43
  9. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/dialect/base.py +2 -0
  10. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/LICENSE.md +0 -0
  11. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/README.md +0 -0
  12. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/pyproject.toml +0 -0
  13. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/pytrilogy.egg-info/SOURCES.txt +0 -0
  14. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/pytrilogy.egg-info/dependency_links.txt +0 -0
  15. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/pytrilogy.egg-info/entry_points.txt +0 -0
  16. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/pytrilogy.egg-info/requires.txt +0 -0
  17. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/pytrilogy.egg-info/top_level.txt +0 -0
  18. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/setup.cfg +0 -0
  19. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/setup.py +0 -0
  20. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_datatypes.py +0 -0
  21. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_declarations.py +0 -0
  22. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_derived_concepts.py +0 -0
  23. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_discovery_nodes.py +0 -0
  24. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_enums.py +0 -0
  25. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_environment.py +0 -0
  26. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_executor.py +0 -0
  27. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_failure.py +0 -0
  28. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_functions.py +0 -0
  29. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_imports.py +0 -0
  30. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_metadata.py +0 -0
  31. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_models.py +0 -0
  32. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_multi_join_assignments.py +0 -0
  33. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_parse_engine.py +0 -0
  34. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_parsing.py +0 -0
  35. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_parsing_failures.py +0 -0
  36. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_partial_handling.py +0 -0
  37. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_query_processing.py +0 -0
  38. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_query_render.py +0 -0
  39. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_select.py +0 -0
  40. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_show.py +0 -0
  41. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_typing.py +0 -0
  42. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_undefined_concept.py +0 -0
  43. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_user_functions.py +0 -0
  44. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/tests/test_where_clause.py +0 -0
  45. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/authoring/__init__.py +0 -0
  46. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/compiler.py +0 -0
  47. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/constants.py +0 -0
  48. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/__init__.py +0 -0
  49. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/constants.py +0 -0
  50. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/enums.py +0 -0
  51. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/env_processor.py +0 -0
  52. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/environment_helpers.py +0 -0
  53. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/ergonomics.py +0 -0
  54. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/exceptions.py +0 -0
  55. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/functions.py +0 -0
  56. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/graph_models.py +0 -0
  57. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/internal.py +0 -0
  58. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/models/__init__.py +0 -0
  59. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/models/author.py +0 -0
  60. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/models/build.py +0 -0
  61. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/models/build_environment.py +0 -0
  62. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/models/core.py +0 -0
  63. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/models/datasource.py +0 -0
  64. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/models/environment.py +0 -0
  65. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/models/execute.py +0 -0
  66. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/optimization.py +0 -0
  67. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/optimizations/__init__.py +0 -0
  68. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/optimizations/base_optimization.py +0 -0
  69. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/optimizations/inline_datasource.py +0 -0
  70. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
  71. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/__init__.py +0 -0
  72. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/concept_strategies_v3.py +0 -0
  73. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/discovery_loop.py +0 -0
  74. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/discovery_utility.py +0 -0
  75. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/discovery_validation.py +0 -0
  76. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/graph_utils.py +0 -0
  77. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/__init__.py +0 -0
  78. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/basic_node.py +0 -0
  79. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/common.py +0 -0
  80. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/filter_node.py +0 -0
  81. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/group_node.py +0 -0
  82. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/group_to_node.py +0 -0
  83. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/multiselect_node.py +0 -0
  84. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/node_merge_node.py +0 -0
  85. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/recursive_node.py +0 -0
  86. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/rowset_node.py +0 -0
  87. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/select_helpers/__init__.py +0 -0
  88. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +0 -0
  89. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/select_node.py +0 -0
  90. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/union_node.py +0 -0
  91. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/unnest_node.py +0 -0
  92. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/node_generators/window_node.py +0 -0
  93. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/nodes/__init__.py +0 -0
  94. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/nodes/base_node.py +0 -0
  95. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/nodes/filter_node.py +0 -0
  96. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/nodes/group_node.py +0 -0
  97. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/nodes/merge_node.py +0 -0
  98. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/nodes/recursive_node.py +0 -0
  99. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
  100. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/nodes/union_node.py +0 -0
  101. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/nodes/unnest_node.py +0 -0
  102. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/processing/nodes/window_node.py +0 -0
  103. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/query_processor.py +0 -0
  104. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/statements/__init__.py +0 -0
  105. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/statements/author.py +0 -0
  106. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/statements/build.py +0 -0
  107. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/statements/common.py +0 -0
  108. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/statements/execute.py +0 -0
  109. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/core/utility.py +0 -0
  110. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/dialect/__init__.py +0 -0
  111. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/dialect/bigquery.py +0 -0
  112. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/dialect/common.py +0 -0
  113. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/dialect/config.py +0 -0
  114. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/dialect/dataframe.py +0 -0
  115. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/dialect/duckdb.py +0 -0
  116. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/dialect/enums.py +0 -0
  117. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/dialect/postgres.py +0 -0
  118. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/dialect/presto.py +0 -0
  119. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/dialect/snowflake.py +0 -0
  120. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/dialect/sql_server.py +0 -0
  121. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/engine.py +0 -0
  122. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/executor.py +0 -0
  123. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/hooks/__init__.py +0 -0
  124. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/hooks/base_hook.py +0 -0
  125. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/hooks/graph_hook.py +0 -0
  126. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/hooks/query_debugger.py +0 -0
  127. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/metadata/__init__.py +0 -0
  128. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/parser.py +0 -0
  129. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/parsing/__init__.py +0 -0
  130. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/parsing/common.py +0 -0
  131. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/parsing/config.py +0 -0
  132. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/parsing/exceptions.py +0 -0
  133. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/parsing/helpers.py +0 -0
  134. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/parsing/parse_engine.py +0 -0
  135. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/parsing/render.py +0 -0
  136. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/parsing/trilogy.lark +0 -0
  137. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/py.typed +0 -0
  138. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/render.py +0 -0
  139. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/scripts/__init__.py +0 -0
  140. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/scripts/trilogy.py +0 -0
  141. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/std/__init__.py +0 -0
  142. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/std/date.preql +0 -0
  143. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/std/display.preql +0 -0
  144. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/std/geography.preql +0 -0
  145. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/std/money.preql +0 -0
  146. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/std/net.preql +0 -0
  147. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/std/ranking.preql +0 -0
  148. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/std/report.preql +0 -0
  149. {pytrilogy-0.0.3.67 → pytrilogy-0.0.3.68}/trilogy/utility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytrilogy
3
- Version: 0.0.3.67
3
+ Version: 0.0.3.68
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytrilogy
3
- Version: 0.0.3.67
3
+ Version: 0.0.3.68
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -59,7 +59,7 @@ def test_io_statement():
59
59
 
60
60
  auto x <- unnest(array);
61
61
 
62
- copy into csv '{target}' from select x -> test;
62
+ copy into csv '{target}' from select x -> test order by test asc;
63
63
  """
64
64
  exec = Dialects.DUCK_DB.default_executor()
65
65
  results = exec.parse_text(text)
@@ -4,6 +4,6 @@ from trilogy.dialect.enums import Dialects
4
4
  from trilogy.executor import Executor
5
5
  from trilogy.parser import parse
6
6
 
7
- __version__ = "0.0.3.67"
7
+ __version__ = "0.0.3.68"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
@@ -307,16 +307,17 @@ class RootNodeHandler:
307
307
  def _resolve_root_concepts(
308
308
  self, root_targets: List[BuildConcept]
309
309
  ) -> Optional[StrategyNode]:
310
- synonym_node = self._try_synonym_resolution(root_targets)
311
- if synonym_node:
312
- logger.info(
313
- f"{depth_to_prefix(self.ctx.depth)}{LOGGER_PREFIX} "
314
- f"resolved root concepts through synonyms"
315
- )
316
- return synonym_node
317
310
  expanded_node = self._try_merge_expansion(root_targets)
318
311
  if expanded_node:
319
312
  return expanded_node
313
+ if self.ctx.accept_partial:
314
+ synonym_node = self._try_synonym_resolution(root_targets)
315
+ if synonym_node:
316
+ logger.info(
317
+ f"{depth_to_prefix(self.ctx.depth)}{LOGGER_PREFIX} "
318
+ f"resolved root concepts through synonyms"
319
+ )
320
+ return synonym_node
320
321
 
321
322
  return None
322
323
 
@@ -493,7 +493,7 @@ def create_select_node(
493
493
  else:
494
494
 
495
495
  candidate = bcandidate
496
- assert candidate.resolve().output_concepts == all_concepts
496
+
497
497
  return candidate
498
498
 
499
499
 
@@ -536,7 +536,12 @@ def gen_select_merge_node(
536
536
  force_group=False,
537
537
  conditions=conditions.conditional if conditions else None,
538
538
  )
539
- for attempt in [False, True]:
539
+ attempts = [
540
+ False,
541
+ ]
542
+ if accept_partial:
543
+ attempts.append(True)
544
+ for attempt in attempts:
540
545
  pruned_concept_graph = create_pruned_concept_graph(
541
546
  g,
542
547
  non_constant,
@@ -3,8 +3,8 @@ from collections import defaultdict
3
3
  from typing import List
4
4
 
5
5
  from trilogy.constants import logger
6
- from trilogy.core.enums import FunctionType
7
- from trilogy.core.models.build import BuildConcept, BuildFunction, BuildWhereClause
6
+ from trilogy.core.enums import Derivation
7
+ from trilogy.core.models.build import BuildConcept, BuildWhereClause
8
8
  from trilogy.core.models.build_environment import BuildEnvironment
9
9
  from trilogy.core.processing.nodes import History, StrategyNode
10
10
  from trilogy.core.processing.utility import padding
@@ -12,13 +12,6 @@ from trilogy.core.processing.utility import padding
12
12
  LOGGER_PREFIX = "[GEN_SYNONYM_NODE]"
13
13
 
14
14
 
15
- def is_union(c: BuildConcept):
16
- return (
17
- isinstance(c.lineage, BuildFunction)
18
- and c.lineage.operator == FunctionType.UNION
19
- )
20
-
21
-
22
15
  def gen_synonym_node(
23
16
  all_concepts: List[BuildConcept],
24
17
  environment: BuildEnvironment,
@@ -41,7 +34,6 @@ def gen_synonym_node(
41
34
  synonyms[x.address].append(parent)
42
35
  has_synonyms = True
43
36
  for y in x.pseudonyms:
44
-
45
37
  if y in environment.alias_origin_lookup:
46
38
  synonyms[x.address].append(environment.alias_origin_lookup[y])
47
39
  has_synonyms = True
@@ -59,11 +51,14 @@ def gen_synonym_node(
59
51
  itertools.product(*(synonyms[obj] for obj in sorted_keys))
60
52
  )
61
53
 
62
- def similarity_sort_key(combo):
54
+ def similarity_sort_key(combo: tuple[BuildConcept, ...]):
63
55
  addresses = [x.address for x in combo]
64
56
 
65
57
  # Calculate similarity score - count how many pairs share prefixes
66
58
  similarity_score = 0
59
+ roots = sum(
60
+ [1 for x in combo if x.derivation in (Derivation.ROOT, Derivation.CONSTANT)]
61
+ )
67
62
  for i in range(len(addresses)):
68
63
  for j in range(i + 1, len(addresses)):
69
64
  # Find common prefix length
@@ -77,8 +72,8 @@ def gen_synonym_node(
77
72
  break
78
73
  similarity_score += common_prefix_len
79
74
 
80
- # Sort by similarity (descending), then by addresses (ascending) for ties
81
- return (-similarity_score, addresses)
75
+ # Sort by roots, similarity (descending), then by addresses (ascending) for ties
76
+ return (-roots, -similarity_score, addresses)
82
77
 
83
78
  combinations_list.sort(key=similarity_sort_key)
84
79
  for combo in combinations_list:
@@ -322,8 +322,10 @@ def resolve_instantiated_concept(
322
322
  for k in concept.pseudonyms:
323
323
  if k in datasource.output_concepts:
324
324
  return [x for x in datasource.output_concepts if x.address == k].pop()
325
+ if any(k in x.pseudonyms for x in datasource.output_concepts):
326
+ return [x for x in datasource.output_concepts if k in x.pseudonyms].pop()
325
327
  raise SyntaxError(
326
- f"Could not find {concept.address} in {datasource.identifier} output {[c.address for c in datasource.output_concepts]}"
328
+ f"Could not find {concept.address} in {datasource.identifier} output {[c.address for c in datasource.output_concepts]}, acceptable synonyms {concept.pseudonyms}"
327
329
  )
328
330
 
329
331
 
@@ -601,19 +603,28 @@ def find_nullable_concepts(
601
603
 
602
604
 
603
605
  def sort_select_output_processed(
604
- cte: CTE | UnionCTE, query: ProcessedQuery
606
+ cte: CTE | UnionCTE, query: SelectStatement | MultiSelectStatement | ProcessedQuery
605
607
  ) -> CTE | UnionCTE:
606
- output_addresses = [c.address for c in query.output_columns]
608
+ if isinstance(query, ProcessedQuery):
609
+ targets = query.output_columns
610
+ hidden = query.hidden_columns
611
+ else:
612
+ targets = query.output_components
613
+ hidden = query.hidden_components
614
+
615
+ output_addresses = [c.address for c in targets]
607
616
 
608
617
  mapping = {x.address: x for x in cte.output_columns}
609
618
 
610
619
  new_output: list[BuildConcept] = []
611
- for x in query.output_columns:
620
+ for x in targets:
612
621
  if x.address in mapping:
613
622
  new_output.append(mapping[x.address])
614
623
  for oc in cte.output_columns:
615
624
  if x.address in oc.pseudonyms:
616
625
  # create a wrapper BuildConcept to render the pseudonym under the original name
626
+ if any(x.address == y for y in mapping.keys()):
627
+ continue
617
628
  new_output.append(
618
629
  BuildConcept(
619
630
  name=x.name,
@@ -636,10 +647,7 @@ def sort_select_output_processed(
636
647
  [
637
648
  c.address
638
649
  for c in cte.output_columns
639
- if (
640
- c.address not in query.output_columns
641
- or c.address in query.hidden_columns
642
- )
650
+ if (c.address not in targets or c.address in hidden)
643
651
  ]
644
652
  )
645
653
  cte.output_columns = new_output
@@ -650,38 +658,4 @@ def sort_select_output(
650
658
  cte: CTE | UnionCTE, query: SelectStatement | MultiSelectStatement | ProcessedQuery
651
659
  ) -> CTE | UnionCTE:
652
660
 
653
- if isinstance(query, ProcessedQuery):
654
- return sort_select_output_processed(cte, query)
655
-
656
- mapping = {x.address: x for x in cte.output_columns}
657
-
658
- new_output: list[BuildConcept] = []
659
- for x in query.output_components:
660
- if x.address in mapping:
661
- new_output.append(mapping[x.address])
662
- else:
663
- for oc in cte.output_columns:
664
- if x.address in oc.pseudonyms:
665
- # create a wrapper BuildConcept to render the pseudonym under the original name
666
- new_output.append(
667
- BuildConcept(
668
- name=x.name,
669
- namespace=x.namespace,
670
- pseudonyms={oc.address},
671
- datatype=oc.datatype,
672
- purpose=oc.purpose,
673
- grain=oc.grain,
674
- build_is_aggregate=oc.build_is_aggregate,
675
- )
676
- )
677
- break
678
- cte.output_columns = new_output
679
- cte.hidden_concepts = set(
680
- [
681
- c.address
682
- for c in query.output_components
683
- if c.address in query.hidden_components
684
- ]
685
- )
686
-
687
- return cte
661
+ return sort_select_output_processed(cte, query)
@@ -762,6 +762,7 @@ class BaseDialect:
762
762
  ] + [
763
763
  f"{self.QUOTE_CHARACTER}{c.safe_address}{self.QUOTE_CHARACTER}"
764
764
  for c in cte.join_derived_concepts
765
+ if c.address not in cte.hidden_concepts
765
766
  ]
766
767
  elif self.UNNEST_MODE in (UnnestMode.CROSS_JOIN_UNNEST, UnnestMode.PRESTO):
767
768
  select_columns = [
@@ -772,6 +773,7 @@ class BaseDialect:
772
773
  ] + [
773
774
  f"{UNNEST_NAME} as {self.QUOTE_CHARACTER}{c.safe_address}{self.QUOTE_CHARACTER}"
774
775
  for c in cte.join_derived_concepts
776
+ if c.address not in cte.hidden_concepts
775
777
  ]
776
778
  else:
777
779
  # otherwse, assume we are unnesting directly in the select
File without changes
File without changes
File without changes
File without changes