pytrilogy 0.0.3.65__tar.gz → 0.0.3.66__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 (150) hide show
  1. {pytrilogy-0.0.3.65/pytrilogy.egg-info → pytrilogy-0.0.3.66}/PKG-INFO +1 -1
  2. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66/pytrilogy.egg-info}/PKG-INFO +1 -1
  3. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_parsing.py +44 -1
  4. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/__init__.py +1 -1
  5. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/models/author.py +17 -4
  6. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/models/build.py +4 -1
  7. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/query_processor.py +3 -0
  8. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/parsing/common.py +28 -3
  9. pytrilogy-0.0.3.66/trilogy/std/display.preql +6 -0
  10. pytrilogy-0.0.3.65/trilogy/std/display.preql +0 -3
  11. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/LICENSE.md +0 -0
  12. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/README.md +0 -0
  13. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/pyproject.toml +0 -0
  14. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/pytrilogy.egg-info/SOURCES.txt +0 -0
  15. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/pytrilogy.egg-info/dependency_links.txt +0 -0
  16. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/pytrilogy.egg-info/entry_points.txt +0 -0
  17. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/pytrilogy.egg-info/requires.txt +0 -0
  18. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/pytrilogy.egg-info/top_level.txt +0 -0
  19. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/setup.cfg +0 -0
  20. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/setup.py +0 -0
  21. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_datatypes.py +0 -0
  22. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_declarations.py +0 -0
  23. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_derived_concepts.py +0 -0
  24. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_discovery_nodes.py +0 -0
  25. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_enums.py +0 -0
  26. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_environment.py +0 -0
  27. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_executor.py +0 -0
  28. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_failure.py +0 -0
  29. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_functions.py +0 -0
  30. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_imports.py +0 -0
  31. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_metadata.py +0 -0
  32. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_models.py +0 -0
  33. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_multi_join_assignments.py +0 -0
  34. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_parse_engine.py +0 -0
  35. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_parsing_failures.py +0 -0
  36. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_partial_handling.py +0 -0
  37. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_query_processing.py +0 -0
  38. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_query_render.py +0 -0
  39. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_select.py +0 -0
  40. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_show.py +0 -0
  41. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_statements.py +0 -0
  42. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_typing.py +0 -0
  43. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_undefined_concept.py +0 -0
  44. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_user_functions.py +0 -0
  45. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/tests/test_where_clause.py +0 -0
  46. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/authoring/__init__.py +0 -0
  47. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/compiler.py +0 -0
  48. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/constants.py +0 -0
  49. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/__init__.py +0 -0
  50. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/constants.py +0 -0
  51. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/enums.py +0 -0
  52. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/env_processor.py +0 -0
  53. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/environment_helpers.py +0 -0
  54. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/ergonomics.py +0 -0
  55. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/exceptions.py +0 -0
  56. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/functions.py +0 -0
  57. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/graph_models.py +0 -0
  58. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/internal.py +0 -0
  59. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/models/__init__.py +0 -0
  60. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/models/build_environment.py +0 -0
  61. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/models/core.py +0 -0
  62. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/models/datasource.py +0 -0
  63. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/models/environment.py +0 -0
  64. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/models/execute.py +0 -0
  65. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/optimization.py +0 -0
  66. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/optimizations/__init__.py +0 -0
  67. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/optimizations/base_optimization.py +0 -0
  68. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/optimizations/inline_datasource.py +0 -0
  69. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
  70. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/__init__.py +0 -0
  71. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/concept_strategies_v3.py +0 -0
  72. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/discovery_loop.py +0 -0
  73. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/discovery_node_factory.py +0 -0
  74. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/discovery_utility.py +0 -0
  75. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/discovery_validation.py +0 -0
  76. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/graph_utils.py +0 -0
  77. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/__init__.py +0 -0
  78. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/basic_node.py +0 -0
  79. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/common.py +0 -0
  80. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/filter_node.py +0 -0
  81. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/group_node.py +0 -0
  82. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/group_to_node.py +0 -0
  83. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/multiselect_node.py +0 -0
  84. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/node_merge_node.py +0 -0
  85. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/recursive_node.py +0 -0
  86. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/rowset_node.py +0 -0
  87. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/select_helpers/__init__.py +0 -0
  88. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +0 -0
  89. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/select_merge_node.py +0 -0
  90. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/select_node.py +0 -0
  91. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/synonym_node.py +0 -0
  92. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/union_node.py +0 -0
  93. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/unnest_node.py +0 -0
  94. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/node_generators/window_node.py +0 -0
  95. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/nodes/__init__.py +0 -0
  96. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/nodes/base_node.py +0 -0
  97. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/nodes/filter_node.py +0 -0
  98. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/nodes/group_node.py +0 -0
  99. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/nodes/merge_node.py +0 -0
  100. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/nodes/recursive_node.py +0 -0
  101. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
  102. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/nodes/union_node.py +0 -0
  103. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/nodes/unnest_node.py +0 -0
  104. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/nodes/window_node.py +0 -0
  105. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/processing/utility.py +0 -0
  106. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/statements/__init__.py +0 -0
  107. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/statements/author.py +0 -0
  108. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/statements/build.py +0 -0
  109. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/statements/common.py +0 -0
  110. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/statements/execute.py +0 -0
  111. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/core/utility.py +0 -0
  112. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/dialect/__init__.py +0 -0
  113. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/dialect/base.py +0 -0
  114. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/dialect/bigquery.py +0 -0
  115. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/dialect/common.py +0 -0
  116. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/dialect/config.py +0 -0
  117. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/dialect/dataframe.py +0 -0
  118. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/dialect/duckdb.py +0 -0
  119. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/dialect/enums.py +0 -0
  120. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/dialect/postgres.py +0 -0
  121. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/dialect/presto.py +0 -0
  122. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/dialect/snowflake.py +0 -0
  123. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/dialect/sql_server.py +0 -0
  124. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/engine.py +0 -0
  125. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/executor.py +0 -0
  126. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/hooks/__init__.py +0 -0
  127. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/hooks/base_hook.py +0 -0
  128. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/hooks/graph_hook.py +0 -0
  129. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/hooks/query_debugger.py +0 -0
  130. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/metadata/__init__.py +0 -0
  131. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/parser.py +0 -0
  132. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/parsing/__init__.py +0 -0
  133. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/parsing/config.py +0 -0
  134. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/parsing/exceptions.py +0 -0
  135. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/parsing/helpers.py +0 -0
  136. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/parsing/parse_engine.py +0 -0
  137. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/parsing/render.py +0 -0
  138. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/parsing/trilogy.lark +0 -0
  139. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/py.typed +0 -0
  140. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/render.py +0 -0
  141. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/scripts/__init__.py +0 -0
  142. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/scripts/trilogy.py +0 -0
  143. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/std/__init__.py +0 -0
  144. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/std/date.preql +0 -0
  145. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/std/geography.preql +0 -0
  146. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/std/money.preql +0 -0
  147. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/std/net.preql +0 -0
  148. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/std/ranking.preql +0 -0
  149. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/std/report.preql +0 -0
  150. {pytrilogy-0.0.3.65 → pytrilogy-0.0.3.66}/trilogy/utility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytrilogy
3
- Version: 0.0.3.65
3
+ Version: 0.0.3.66
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.65
3
+ Version: 0.0.3.66
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -2,7 +2,7 @@ from trilogy import Dialects
2
2
  from trilogy.constants import MagicConstants
3
3
  from trilogy.core.enums import BooleanOperator, ComparisonOperator, Purpose
4
4
  from trilogy.core.functions import argument_to_purpose, function_args_to_output_purpose
5
- from trilogy.core.models.author import Comparison
5
+ from trilogy.core.models.author import Comparison, Conditional, SubselectComparison
6
6
  from trilogy.core.models.core import (
7
7
  DataType,
8
8
  TupleWrapper,
@@ -16,6 +16,7 @@ from trilogy.core.models.environment import (
16
16
  from trilogy.core.statements.author import SelectStatement, ShowStatement
17
17
  from trilogy.core.statements.execute import ProcessedQuery
18
18
  from trilogy.dialect.base import BaseDialect
19
+ from trilogy.parsing.common import atom_is_relevant
19
20
  from trilogy.parsing.parse_engine import (
20
21
  arg_to_datatype,
21
22
  parse_text,
@@ -685,3 +686,45 @@ select x % 10 -> x_mod_10;
685
686
 
686
687
  """
687
688
  )
689
+
690
+
691
+ def test_is_atom():
692
+ env = Environment()
693
+
694
+ env.parse(
695
+ """
696
+ key x int;
697
+ auto x_sum <- sum(x);
698
+ """
699
+ )
700
+
701
+ assert not atom_is_relevant(
702
+ Comparison(left=env.concepts["x_sum"], right=0, operator=ComparisonOperator.GT),
703
+ [env.concepts["x"]],
704
+ env,
705
+ )
706
+ assert atom_is_relevant(
707
+ Comparison(left=env.concepts["x"], right=0, operator=ComparisonOperator.GT),
708
+ [env.concepts["x_sum"]],
709
+ env,
710
+ )
711
+
712
+ assert not atom_is_relevant(
713
+ Conditional(left=env.concepts["x_sum"], right=0, operator=BooleanOperator.AND),
714
+ [env.concepts["x"]],
715
+ env,
716
+ )
717
+ assert atom_is_relevant(
718
+ Conditional(left=env.concepts["x"], right=0, operator=BooleanOperator.AND),
719
+ [env.concepts["x_sum"]],
720
+ env,
721
+ )
722
+ assert not atom_is_relevant(
723
+ SubselectComparison(
724
+ left=env.concepts["x_sum"],
725
+ right=env.concepts["x"],
726
+ operator=ComparisonOperator.IN,
727
+ ),
728
+ [env.concepts["x_sum"]],
729
+ env,
730
+ )
@@ -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.65"
7
+ __version__ = "0.0.3.66"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
@@ -271,6 +271,20 @@ class Conditional(Mergeable, ConceptArgs, Namespaced, DataTyped, BaseModel):
271
271
  right: Expr
272
272
  operator: BooleanOperator
273
273
 
274
+ @field_validator("left", mode="before")
275
+ @classmethod
276
+ def left_validator(cls, v, info: ValidationInfo):
277
+ if isinstance(v, Concept):
278
+ return v.reference
279
+ return v
280
+
281
+ @field_validator("right", mode="before")
282
+ @classmethod
283
+ def right_validator(cls, v, info: ValidationInfo):
284
+ if isinstance(v, Concept):
285
+ return v.reference
286
+ return v
287
+
274
288
  def __add__(self, other) -> "Conditional":
275
289
  if other is None:
276
290
  return self
@@ -346,7 +360,6 @@ class Conditional(Mergeable, ConceptArgs, Namespaced, DataTyped, BaseModel):
346
360
 
347
361
  @property
348
362
  def concept_arguments(self) -> Sequence[ConceptRef]:
349
- """Return concepts directly referenced in where clause"""
350
363
  output = []
351
364
  output += get_concept_arguments(self.left)
352
365
  output += get_concept_arguments(self.right)
@@ -575,11 +588,11 @@ class Comparison(ConceptArgs, Mergeable, DataTyped, Namespaced, BaseModel):
575
588
  date,
576
589
  Function,
577
590
  ConceptRef,
578
- "Conditional",
591
+ Conditional,
579
592
  DataType,
580
- "Comparison",
593
+ Comparison,
581
594
  FunctionCallWrapper,
582
- "Parenthetical",
595
+ Parenthetical,
583
596
  MagicConstants,
584
597
  WindowItem,
585
598
  AggregateWrapper,
@@ -1631,7 +1631,10 @@ class Factory:
1631
1631
 
1632
1632
  @build.register
1633
1633
  def _(self, base: CaseElse) -> BuildCaseElse:
1634
- return BuildCaseElse.model_construct(expr=self.build(base.expr))
1634
+ expr: Concept | FuncArgs = base.expr
1635
+ if isinstance(expr, (AggregateWrapper, FilterItem, WindowItem)):
1636
+ expr, _ = self.instantiate_concept(expr)
1637
+ return BuildCaseElse.model_construct(expr=self.build(expr))
1635
1638
 
1636
1639
  @build.register
1637
1640
  def _(self, base: Concept) -> BuildConcept:
@@ -395,6 +395,9 @@ def get_query_node(
395
395
  if not statement.output_components:
396
396
  raise ValueError(f"Statement has no output components {statement}")
397
397
  history = history or History(base_environment=environment)
398
+ print(
399
+ f"{LOGGER_PREFIX} building query node for {statement.output_components} grain {statement.grain}"
400
+ )
398
401
  build_statement: BuildSelectLineage | BuildMultiSelectLineage = Factory(
399
402
  environment=environment,
400
403
  ).build(statement)
@@ -23,9 +23,13 @@ from trilogy.core.models.author import (
23
23
  AggregateWrapper,
24
24
  AlignClause,
25
25
  AlignItem,
26
+ CaseElse,
27
+ CaseWhen,
28
+ Comparison,
26
29
  Concept,
27
30
  ConceptArgs,
28
31
  ConceptRef,
32
+ Conditional,
29
33
  FilterItem,
30
34
  Function,
31
35
  FunctionCallWrapper,
@@ -38,6 +42,7 @@ from trilogy.core.models.author import (
38
42
  Parenthetical,
39
43
  RowsetItem,
40
44
  RowsetLineage,
45
+ SubselectComparison,
41
46
  TraitDataType,
42
47
  UndefinedConcept,
43
48
  WhereClause,
@@ -198,6 +203,7 @@ def atom_is_relevant(
198
203
  others: list[Concept | ConceptRef],
199
204
  environment: Environment | None = None,
200
205
  ):
206
+
201
207
  if isinstance(atom, (ConceptRef, Concept)):
202
208
  # when we are looking at atoms, if there is a concept that is in others
203
209
  # return directly
@@ -210,9 +216,10 @@ def atom_is_relevant(
210
216
  elif isinstance(atom, AggregateWrapper):
211
217
  return any(atom_is_relevant(x, others, environment) for x in atom.by)
212
218
 
213
- if isinstance(atom, Function):
219
+ elif isinstance(atom, Function):
214
220
  relevant = False
215
221
  for arg in atom.arguments:
222
+
216
223
  relevant = relevant or atom_is_relevant(arg, others, environment)
217
224
  return relevant
218
225
  elif isinstance(atom, FunctionCallWrapper):
@@ -220,8 +227,27 @@ def atom_is_relevant(
220
227
  [atom_is_relevant(atom.content, others, environment)]
221
228
  + [atom_is_relevant(x, others, environment) for x in atom.args]
222
229
  )
230
+ elif isinstance(atom, CaseWhen):
231
+ rval = atom_is_relevant(atom.expr, others, environment) or atom_is_relevant(
232
+ atom.comparison, others, environment
233
+ )
234
+ return rval
235
+ elif isinstance(atom, CaseElse):
236
+
237
+ rval = atom_is_relevant(atom.expr, others, environment)
238
+ return rval
239
+ elif isinstance(atom, SubselectComparison):
240
+ return atom_is_relevant(atom.left, others, environment)
241
+ elif isinstance(atom, Comparison):
242
+ return atom_is_relevant(atom.left, others, environment) or atom_is_relevant(
243
+ atom.right, others, environment
244
+ )
245
+ elif isinstance(atom, Conditional):
246
+ return atom_is_relevant(atom.left, others, environment) or atom_is_relevant(
247
+ atom.right, others, environment
248
+ )
223
249
  elif isinstance(atom, ConceptArgs):
224
- # use atom is relevant here to trigger the early exit behavior for concpets in set
250
+ # use atom is relevant here to trigger the early exit behavior for concepts in set
225
251
  return any(
226
252
  [atom_is_relevant(x, others, environment) for x in atom.concept_arguments]
227
253
  )
@@ -233,7 +259,6 @@ def concept_is_relevant(
233
259
  others: list[Concept | ConceptRef],
234
260
  environment: Environment | None = None,
235
261
  ) -> bool:
236
-
237
262
  if isinstance(concept, UndefinedConcept):
238
263
  return False
239
264
  if concept.datatype == DataType.UNKNOWN:
@@ -0,0 +1,6 @@
1
+
2
+
3
+ type percent float; # Percentage value
4
+
5
+ def calc_percent(a, b, digits=-1) -> case when digits =-1 then (a/b):: float::percent
6
+ else round((a/b):: float::percent, digits) end;
@@ -1,3 +0,0 @@
1
-
2
-
3
- type percent float; # Percentage value
File without changes
File without changes
File without changes
File without changes