pytrilogy 0.0.3.45__tar.gz → 0.0.3.46__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 (141) hide show
  1. {pytrilogy-0.0.3.45/pytrilogy.egg-info → pytrilogy-0.0.3.46}/PKG-INFO +1 -1
  2. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46/pytrilogy.egg-info}/PKG-INFO +1 -1
  3. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_partial_handling.py +3 -3
  4. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/__init__.py +1 -1
  5. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/filter_node.py +31 -16
  6. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/LICENSE.md +0 -0
  7. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/README.md +0 -0
  8. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/pyproject.toml +0 -0
  9. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/pytrilogy.egg-info/SOURCES.txt +0 -0
  10. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/pytrilogy.egg-info/dependency_links.txt +0 -0
  11. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/pytrilogy.egg-info/entry_points.txt +0 -0
  12. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/pytrilogy.egg-info/requires.txt +0 -0
  13. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/pytrilogy.egg-info/top_level.txt +0 -0
  14. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/setup.cfg +0 -0
  15. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/setup.py +0 -0
  16. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_datatypes.py +0 -0
  17. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_declarations.py +0 -0
  18. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_derived_concepts.py +0 -0
  19. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_discovery_nodes.py +0 -0
  20. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_enums.py +0 -0
  21. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_environment.py +0 -0
  22. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_executor.py +0 -0
  23. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_failure.py +0 -0
  24. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_functions.py +0 -0
  25. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_imports.py +0 -0
  26. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_metadata.py +0 -0
  27. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_models.py +0 -0
  28. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_multi_join_assignments.py +0 -0
  29. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_parse_engine.py +0 -0
  30. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_parsing.py +0 -0
  31. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_parsing_failures.py +0 -0
  32. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_query_processing.py +0 -0
  33. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_query_render.py +0 -0
  34. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_select.py +0 -0
  35. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_show.py +0 -0
  36. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_statements.py +0 -0
  37. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_typing.py +0 -0
  38. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_undefined_concept.py +0 -0
  39. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_user_functions.py +0 -0
  40. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/tests/test_where_clause.py +0 -0
  41. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/authoring/__init__.py +0 -0
  42. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/compiler.py +0 -0
  43. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/constants.py +0 -0
  44. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/__init__.py +0 -0
  45. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/constants.py +0 -0
  46. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/enums.py +0 -0
  47. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/env_processor.py +0 -0
  48. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/environment_helpers.py +0 -0
  49. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/ergonomics.py +0 -0
  50. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/exceptions.py +0 -0
  51. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/functions.py +0 -0
  52. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/graph_models.py +0 -0
  53. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/internal.py +0 -0
  54. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/models/__init__.py +0 -0
  55. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/models/author.py +0 -0
  56. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/models/build.py +0 -0
  57. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/models/build_environment.py +0 -0
  58. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/models/core.py +0 -0
  59. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/models/datasource.py +0 -0
  60. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/models/environment.py +0 -0
  61. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/models/execute.py +0 -0
  62. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/optimization.py +0 -0
  63. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/optimizations/__init__.py +0 -0
  64. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/optimizations/base_optimization.py +0 -0
  65. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/optimizations/inline_constant.py +0 -0
  66. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/optimizations/inline_datasource.py +0 -0
  67. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
  68. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/__init__.py +0 -0
  69. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/concept_strategies_v3.py +0 -0
  70. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/graph_utils.py +0 -0
  71. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/__init__.py +0 -0
  72. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/basic_node.py +0 -0
  73. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/common.py +0 -0
  74. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/group_node.py +0 -0
  75. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/group_to_node.py +0 -0
  76. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/multiselect_node.py +0 -0
  77. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/node_merge_node.py +0 -0
  78. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/rowset_node.py +0 -0
  79. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/select_helpers/__init__.py +0 -0
  80. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +0 -0
  81. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/select_merge_node.py +0 -0
  82. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/select_node.py +0 -0
  83. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/synonym_node.py +0 -0
  84. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/union_node.py +0 -0
  85. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/unnest_node.py +0 -0
  86. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/node_generators/window_node.py +0 -0
  87. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/nodes/__init__.py +0 -0
  88. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/nodes/base_node.py +0 -0
  89. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/nodes/filter_node.py +0 -0
  90. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/nodes/group_node.py +0 -0
  91. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/nodes/merge_node.py +0 -0
  92. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
  93. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/nodes/union_node.py +0 -0
  94. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/nodes/unnest_node.py +0 -0
  95. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/nodes/window_node.py +0 -0
  96. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/processing/utility.py +0 -0
  97. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/query_processor.py +0 -0
  98. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/statements/__init__.py +0 -0
  99. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/statements/author.py +0 -0
  100. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/statements/build.py +0 -0
  101. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/statements/common.py +0 -0
  102. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/core/statements/execute.py +0 -0
  103. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/dialect/__init__.py +0 -0
  104. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/dialect/base.py +0 -0
  105. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/dialect/bigquery.py +0 -0
  106. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/dialect/common.py +0 -0
  107. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/dialect/config.py +0 -0
  108. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/dialect/dataframe.py +0 -0
  109. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/dialect/duckdb.py +0 -0
  110. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/dialect/enums.py +0 -0
  111. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/dialect/postgres.py +0 -0
  112. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/dialect/presto.py +0 -0
  113. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/dialect/snowflake.py +0 -0
  114. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/dialect/sql_server.py +0 -0
  115. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/engine.py +0 -0
  116. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/executor.py +0 -0
  117. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/hooks/__init__.py +0 -0
  118. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/hooks/base_hook.py +0 -0
  119. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/hooks/graph_hook.py +0 -0
  120. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/hooks/query_debugger.py +0 -0
  121. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/metadata/__init__.py +0 -0
  122. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/parser.py +0 -0
  123. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/parsing/__init__.py +0 -0
  124. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/parsing/common.py +0 -0
  125. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/parsing/config.py +0 -0
  126. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/parsing/exceptions.py +0 -0
  127. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/parsing/helpers.py +0 -0
  128. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/parsing/parse_engine.py +0 -0
  129. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/parsing/render.py +0 -0
  130. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/parsing/trilogy.lark +0 -0
  131. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/py.typed +0 -0
  132. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/render.py +0 -0
  133. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/scripts/__init__.py +0 -0
  134. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/scripts/trilogy.py +0 -0
  135. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/std/__init__.py +0 -0
  136. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/std/date.preql +0 -0
  137. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/std/display.preql +0 -0
  138. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/std/geography.preql +0 -0
  139. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/std/money.preql +0 -0
  140. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/std/report.preql +0 -0
  141. {pytrilogy-0.0.3.45 → pytrilogy-0.0.3.46}/trilogy/utility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytrilogy
3
- Version: 0.0.3.45
3
+ Version: 0.0.3.46
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.45
3
+ Version: 0.0.3.46
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -12,7 +12,7 @@ from trilogy.core.processing.concept_strategies_v3 import History, search_concep
12
12
  from trilogy.core.processing.node_generators import (
13
13
  gen_filter_node,
14
14
  )
15
- from trilogy.core.processing.nodes import MergeNode
15
+ from trilogy.core.processing.nodes import FilterNode
16
16
  from trilogy.core.query_processor import generate_graph
17
17
  from trilogy.hooks.query_debugger import DebuggingHook
18
18
 
@@ -139,8 +139,8 @@ def test_partial_assignment():
139
139
  g=g,
140
140
  depth=0,
141
141
  )
142
- assert isinstance(sourced, MergeNode)
143
- assert len(sourced.parents) == 2
142
+ assert isinstance(sourced, FilterNode)
143
+ assert len(sourced.parents) == 1
144
144
 
145
145
 
146
146
  def test_filter_query():
@@ -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.45"
7
+ __version__ = "0.0.3.46"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
@@ -56,12 +56,40 @@ def gen_filter_node(
56
56
  continue
57
57
  if conditions and conditions == where:
58
58
  optional_included.append(x)
59
+
60
+ # sometimes, it's okay to include other local optional above the filter
61
+ # in case it is, prep our list
62
+ extra_row_level_optional: list[BuildConcept] = []
63
+ for x in local_optional:
64
+ if x.address in optional_included:
65
+ continue
66
+ extra_row_level_optional.append(x)
67
+
68
+ # this flag controls whether we materialize the filter as a where on the prior CTE
69
+ # or do the filtering inline as a case statement
70
+ optimized_pushdown = False
71
+ if not is_scalar_condition(where.conditional):
72
+ optimized_pushdown = False
73
+ elif not local_optional:
74
+ optimized_pushdown = True
75
+ elif conditions and conditions == where:
76
+ logger.info(
77
+ f"{padding(depth)}{LOGGER_PREFIX} query conditions are the same as filter conditions, can optimize across all concepts"
78
+ )
79
+ optimized_pushdown = True
80
+ elif optional_included == local_optional:
81
+ logger.info(
82
+ f"{padding(depth)}{LOGGER_PREFIX} all optional concepts are included in the filter, can optimize across all concepts"
83
+ )
84
+ optimized_pushdown = True
59
85
  logger.info(
60
86
  f"{padding(depth)}{LOGGER_PREFIX} filter `{concept}` condition `{concept.lineage.where}` derived from {immediate_parent.address} row parents {[x.address for x in parent_row_concepts]} and {[[y.address] for x in parent_existence_concepts for y in x]} existence parents"
61
87
  )
62
88
  # we'll populate this with the row parent
63
89
  # and the existence parent(s)
64
90
  core_parents = []
91
+ if not optimized_pushdown:
92
+ parent_row_concepts += extra_row_level_optional
65
93
 
66
94
  row_parent: StrategyNode = source_concepts(
67
95
  mandatory_list=parent_row_concepts,
@@ -99,21 +127,6 @@ def gen_filter_node(
99
127
  )
100
128
  return None
101
129
 
102
- optimized_pushdown = False
103
- if not is_scalar_condition(where.conditional):
104
- optimized_pushdown = False
105
- elif not local_optional:
106
- optimized_pushdown = True
107
- elif conditions and conditions == where:
108
- logger.info(
109
- f"{padding(depth)}{LOGGER_PREFIX} query conditions are the same as filter conditions, can optimize across all concepts"
110
- )
111
- optimized_pushdown = True
112
- elif optional_included == local_optional:
113
- logger.info(
114
- f"{padding(depth)}{LOGGER_PREFIX} all optional concepts are included in the filter, can optimize across all concepts"
115
- )
116
- optimized_pushdown = True
117
130
  if optimized_pushdown:
118
131
  logger.info(
119
132
  f"{padding(depth)}{LOGGER_PREFIX} returning optimized filter node with pushdown to parent with condition {where.conditional}"
@@ -193,7 +206,9 @@ def gen_filter_node(
193
206
  + optional_outputs
194
207
  )
195
208
  return filter_node
196
-
209
+ logger.info(
210
+ f"{padding(depth)}{LOGGER_PREFIX} need to enrich filter node with additional concepts {[x.address for x in local_optional if x.address not in filter_node.output_concepts]}"
211
+ )
197
212
  enrich_node: StrategyNode = source_concepts( # this fetches the parent + join keys
198
213
  # to then connect to the rest of the query
199
214
  mandatory_list=[immediate_parent] + parent_row_concepts + local_optional,
File without changes
File without changes
File without changes
File without changes