pytrilogy 0.0.2.57__tar.gz → 0.0.2.58__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 (114) hide show
  1. {pytrilogy-0.0.2.57/pytrilogy.egg-info → pytrilogy-0.0.2.58}/PKG-INFO +1 -1
  2. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58/pytrilogy.egg-info}/PKG-INFO +1 -1
  3. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_select.py +1 -1
  4. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/__init__.py +1 -1
  5. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/models.py +16 -16
  6. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/optimization.py +3 -6
  7. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/concept_strategies_v3.py +1 -1
  8. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/common.py +1 -1
  9. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/group_to_node.py +2 -2
  10. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/multiselect_node.py +1 -1
  11. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/rowset_node.py +4 -2
  12. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/nodes/base_node.py +10 -11
  13. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/nodes/group_node.py +5 -5
  14. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/nodes/merge_node.py +2 -2
  15. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/nodes/select_node_v2.py +1 -1
  16. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/utility.py +5 -5
  17. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/query_processor.py +2 -2
  18. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/dialect/base.py +6 -5
  19. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/LICENSE.md +0 -0
  20. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/README.md +0 -0
  21. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/pyproject.toml +0 -0
  22. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/pytrilogy.egg-info/SOURCES.txt +0 -0
  23. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/pytrilogy.egg-info/dependency_links.txt +0 -0
  24. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/pytrilogy.egg-info/entry_points.txt +0 -0
  25. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/pytrilogy.egg-info/requires.txt +0 -0
  26. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/pytrilogy.egg-info/top_level.txt +0 -0
  27. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/setup.cfg +0 -0
  28. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/setup.py +0 -0
  29. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_datatypes.py +0 -0
  30. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_declarations.py +0 -0
  31. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_derived_concepts.py +0 -0
  32. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_discovery_nodes.py +0 -0
  33. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_enums.py +0 -0
  34. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_environment.py +0 -0
  35. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_executor.py +0 -0
  36. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_functions.py +0 -0
  37. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_imports.py +0 -0
  38. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_metadata.py +0 -0
  39. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_models.py +0 -0
  40. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_multi_join_assignments.py +0 -0
  41. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_parse_engine.py +0 -0
  42. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_parsing.py +0 -0
  43. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_partial_handling.py +0 -0
  44. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_query_processing.py +0 -0
  45. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_show.py +0 -0
  46. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_statements.py +0 -0
  47. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_undefined_concept.py +0 -0
  48. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/tests/test_where_clause.py +0 -0
  49. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/compiler.py +0 -0
  50. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/constants.py +0 -0
  51. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/__init__.py +0 -0
  52. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/constants.py +0 -0
  53. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/enums.py +0 -0
  54. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/env_processor.py +0 -0
  55. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/environment_helpers.py +0 -0
  56. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/ergonomics.py +0 -0
  57. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/exceptions.py +0 -0
  58. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/functions.py +0 -0
  59. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/graph_models.py +0 -0
  60. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/internal.py +0 -0
  61. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/optimizations/__init__.py +0 -0
  62. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/optimizations/base_optimization.py +0 -0
  63. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/optimizations/inline_constant.py +0 -0
  64. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/optimizations/inline_datasource.py +0 -0
  65. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
  66. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/__init__.py +0 -0
  67. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/graph_utils.py +0 -0
  68. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/__init__.py +0 -0
  69. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/basic_node.py +0 -0
  70. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/filter_node.py +0 -0
  71. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/group_node.py +0 -0
  72. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/node_merge_node.py +0 -0
  73. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/select_helpers/__init__.py +0 -0
  74. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +0 -0
  75. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/select_merge_node.py +0 -0
  76. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/select_node.py +0 -0
  77. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/union_node.py +0 -0
  78. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/unnest_node.py +0 -0
  79. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/node_generators/window_node.py +0 -0
  80. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/nodes/__init__.py +0 -0
  81. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/nodes/filter_node.py +0 -0
  82. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/nodes/union_node.py +0 -0
  83. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/nodes/unnest_node.py +0 -0
  84. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/core/processing/nodes/window_node.py +0 -0
  85. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/dialect/__init__.py +0 -0
  86. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/dialect/bigquery.py +0 -0
  87. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/dialect/common.py +0 -0
  88. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/dialect/config.py +0 -0
  89. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/dialect/duckdb.py +0 -0
  90. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/dialect/enums.py +0 -0
  91. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/dialect/postgres.py +0 -0
  92. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/dialect/presto.py +0 -0
  93. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/dialect/snowflake.py +0 -0
  94. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/dialect/sql_server.py +0 -0
  95. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/engine.py +0 -0
  96. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/executor.py +0 -0
  97. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/hooks/__init__.py +0 -0
  98. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/hooks/base_hook.py +0 -0
  99. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/hooks/graph_hook.py +0 -0
  100. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/hooks/query_debugger.py +0 -0
  101. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/metadata/__init__.py +0 -0
  102. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/parser.py +0 -0
  103. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/parsing/__init__.py +0 -0
  104. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/parsing/common.py +0 -0
  105. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/parsing/config.py +0 -0
  106. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/parsing/exceptions.py +0 -0
  107. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/parsing/helpers.py +0 -0
  108. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/parsing/parse_engine.py +0 -0
  109. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/parsing/render.py +0 -0
  110. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/parsing/trilogy.lark +0 -0
  111. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/py.typed +0 -0
  112. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/scripts/__init__.py +0 -0
  113. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/scripts/trilogy.py +0 -0
  114. {pytrilogy-0.0.2.57 → pytrilogy-0.0.2.58}/trilogy/utility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pytrilogy
3
- Version: 0.0.2.57
3
+ Version: 0.0.2.58
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.1
2
2
  Name: pytrilogy
3
- Version: 0.0.2.57
3
+ Version: 0.0.2.58
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -123,7 +123,7 @@ def test_modifiers():
123
123
  ;"""
124
124
  env, parsed = parse(q1)
125
125
  select: SelectStatement = parsed[-1]
126
- assert select.hidden_components == [env.concepts["b"]]
126
+ assert select.hidden_components == set([env.concepts["b"].address])
127
127
  assert select.output_components == [env.concepts["a"], env.concepts["b"]]
128
128
  query = process_query(statement=select, environment=env)
129
129
 
@@ -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.2.57"
7
+ __version__ = "0.0.2.58"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
@@ -1870,11 +1870,11 @@ class SelectStatement(HasUUID, Mergeable, Namespaced, SelectTypeMixin, BaseModel
1870
1870
  return output
1871
1871
 
1872
1872
  @property
1873
- def hidden_components(self) -> List[Concept]:
1874
- output = []
1873
+ def hidden_components(self) -> set[str]:
1874
+ output = set()
1875
1875
  for item in self.selection:
1876
1876
  if isinstance(item, SelectItem) and Modifier.HIDDEN in item.modifiers:
1877
- output.append(item.output)
1877
+ output.add(item.output.address)
1878
1878
  return output
1879
1879
 
1880
1880
  @property
@@ -2104,10 +2104,10 @@ class MultiSelectStatement(HasUUID, SelectTypeMixin, Mergeable, Namespaced, Base
2104
2104
 
2105
2105
  @computed_field # type: ignore
2106
2106
  @cached_property
2107
- def hidden_components(self) -> List[Concept]:
2108
- output = []
2107
+ def hidden_components(self) -> set[str]:
2108
+ output: set[str] = set()
2109
2109
  for select in self.selects:
2110
- output += select.hidden_components
2110
+ output = output.union(select.hidden_components)
2111
2111
  return output
2112
2112
 
2113
2113
 
@@ -2508,7 +2508,7 @@ class QueryDatasource(BaseModel):
2508
2508
  filter_concepts: List[Concept] = Field(default_factory=list)
2509
2509
  source_type: SourceType = SourceType.SELECT
2510
2510
  partial_concepts: List[Concept] = Field(default_factory=list)
2511
- hidden_concepts: List[Concept] = Field(default_factory=list)
2511
+ hidden_concepts: set[str] = Field(default_factory=set)
2512
2512
  nullable_concepts: List[Concept] = Field(default_factory=list)
2513
2513
  join_derived_concepts: List[Concept] = Field(default_factory=list)
2514
2514
  force_group: bool | None = None
@@ -2660,10 +2660,10 @@ class QueryDatasource(BaseModel):
2660
2660
  final_source_map[k] = set(
2661
2661
  merged_datasources.get(x.safe_identifier, x) for x in list(v)
2662
2662
  )
2663
- self_hidden = self.hidden_concepts or []
2664
- other_hidden = other.hidden_concepts or []
2663
+ self_hidden: set[str] = self.hidden_concepts or set()
2664
+ other_hidden: set[str] = other.hidden_concepts or set()
2665
2665
  # hidden is the minimum overlapping set
2666
- hidden = [x for x in self_hidden if x.address in other_hidden]
2666
+ hidden = self_hidden.intersection(other_hidden)
2667
2667
  qds = QueryDatasource(
2668
2668
  input_concepts=unique(
2669
2669
  self.input_concepts + other.input_concepts, "address"
@@ -2761,7 +2761,7 @@ class CTE(BaseModel):
2761
2761
  partial_concepts: List[Concept] = Field(default_factory=list)
2762
2762
  nullable_concepts: List[Concept] = Field(default_factory=list)
2763
2763
  join_derived_concepts: List[Concept] = Field(default_factory=list)
2764
- hidden_concepts: List[Concept] = Field(default_factory=list)
2764
+ hidden_concepts: set[str] = Field(default_factory=set)
2765
2765
  order_by: Optional[OrderBy] = None
2766
2766
  limit: Optional[int] = None
2767
2767
  base_name_override: Optional[str] = None
@@ -2947,10 +2947,10 @@ class CTE(BaseModel):
2947
2947
  f" {self.name} {other.name} conditions {self.condition} {other.condition}"
2948
2948
  )
2949
2949
  raise ValueError(error)
2950
- mutually_hidden = []
2950
+ mutually_hidden = set()
2951
2951
  for concept in self.hidden_concepts:
2952
- if concept.address in other.hidden_concepts:
2953
- mutually_hidden.append(concept)
2952
+ if concept in other.hidden_concepts:
2953
+ mutually_hidden.add(concept)
2954
2954
  self.partial_concepts = unique(
2955
2955
  self.partial_concepts + other.partial_concepts, "address"
2956
2956
  )
@@ -3132,7 +3132,7 @@ class UnionCTE(BaseModel):
3132
3132
  operator: str = "UNION ALL"
3133
3133
  order_by: Optional[OrderBy] = None
3134
3134
  limit: Optional[int] = None
3135
- hidden_concepts: list[Concept] = Field(default_factory=list)
3135
+ hidden_concepts: set[str] = Field(default_factory=set)
3136
3136
  partial_concepts: list[Concept] = Field(default_factory=list)
3137
3137
  existence_source_map: Dict[str, list[str]] = Field(default_factory=dict)
3138
3138
 
@@ -4504,7 +4504,7 @@ class ProcessedQuery(BaseModel):
4504
4504
  base: CTE | UnionCTE
4505
4505
  joins: List[Join]
4506
4506
  grain: Grain
4507
- hidden_columns: List[Concept] = Field(default_factory=list)
4507
+ hidden_columns: set[str] = Field(default_factory=set)
4508
4508
  limit: Optional[int] = None
4509
4509
  where_clause: Optional[WhereClause] = None
4510
4510
  having_clause: Optional[HavingClause] = None
@@ -136,15 +136,12 @@ def is_direct_return_eligible(cte: CTE | UnionCTE) -> CTE | UnionCTE | None:
136
136
 
137
137
  assert isinstance(cte, CTE)
138
138
  derived_concepts = [
139
- c
140
- for c in cte.source.output_concepts + cte.source.hidden_concepts
141
- if c not in cte.source.input_concepts
139
+ c for c in cte.source.output_concepts if c not in cte.source.input_concepts
142
140
  ]
143
141
 
144
142
  parent_derived_concepts = [
145
143
  c
146
144
  for c in direct_parent.source.output_concepts
147
- + direct_parent.source.hidden_concepts
148
145
  if c not in direct_parent.source.input_concepts
149
146
  ]
150
147
  condition_arguments = cte.condition.row_arguments if cte.condition else []
@@ -180,8 +177,8 @@ def optimize_ctes(
180
177
  ):
181
178
  direct_parent.order_by = root_cte.order_by
182
179
  direct_parent.limit = root_cte.limit
183
- direct_parent.hidden_concepts = (
184
- root_cte.hidden_concepts + direct_parent.hidden_concepts
180
+ direct_parent.hidden_concepts = root_cte.hidden_concepts.union(
181
+ direct_parent.hidden_concepts
185
182
  )
186
183
  if root_cte.condition:
187
184
  if direct_parent.condition:
@@ -580,7 +580,7 @@ def validate_stack(
580
580
  resolved = node.resolve()
581
581
 
582
582
  for concept in resolved.output_concepts:
583
- if concept in resolved.hidden_concepts:
583
+ if concept.address in resolved.hidden_concepts:
584
584
  continue
585
585
  validate_concept(
586
586
  concept,
@@ -208,7 +208,7 @@ def gen_enrichment_node(
208
208
  non_hidden = [
209
209
  x
210
210
  for x in base_node.output_concepts
211
- if x.address not in [y.address for y in base_node.hidden_concepts]
211
+ if x.address not in base_node.hidden_concepts
212
212
  ]
213
213
  return MergeNode(
214
214
  input_concepts=unique(join_keys + extra_required + non_hidden, "address"),
@@ -49,8 +49,8 @@ def gen_group_to_node(
49
49
  parents=parents,
50
50
  depth=depth,
51
51
  preexisting_conditions=conditions.conditional if conditions else None,
52
- hidden_concepts=(
53
- [group_arg]
52
+ hidden_concepts=set(
53
+ [group_arg.address]
54
54
  if isinstance(group_arg, Concept)
55
55
  and group_arg.address not in local_optional
56
56
  else []
@@ -116,7 +116,7 @@ def gen_multiselect_node(
116
116
  depth=depth,
117
117
  parents=base_parents,
118
118
  node_joins=node_joins,
119
- hidden_concepts=[x for y in base_parents for x in y.hidden_concepts],
119
+ hidden_concepts=set([x for y in base_parents for x in y.hidden_concepts]),
120
120
  )
121
121
 
122
122
  enrichment = set([x.address for x in local_optional])
@@ -47,7 +47,7 @@ def gen_rowset_node(
47
47
  return None
48
48
  enrichment = set([x.address for x in local_optional])
49
49
  rowset_relevant = [x for x in rowset.derived_concepts]
50
- select_hidden = set([x.address for x in select.hidden_components])
50
+ select_hidden = select.hidden_components
51
51
  rowset_hidden = [
52
52
  x
53
53
  for x in rowset.derived_concepts
@@ -80,7 +80,9 @@ def gen_rowset_node(
80
80
  for x in node.output_concepts
81
81
  if x.address
82
82
  not in [
83
- y for y in node.hidden_concepts if y.derivation != PurposeLineage.ROWSET
83
+ y
84
+ for y in node.hidden_concepts
85
+ if environment.concepts[y].derivation != PurposeLineage.ROWSET
84
86
  ]
85
87
  ],
86
88
  )
@@ -40,9 +40,10 @@ def resolve_concept_map(
40
40
  for concept in input.output_concepts:
41
41
  if concept.address not in input.non_partial_concept_addresses:
42
42
  continue
43
- if isinstance(input, QueryDatasource) and concept.address in [
44
- x.address for x in input.hidden_concepts
45
- ]:
43
+ if (
44
+ isinstance(input, QueryDatasource)
45
+ and concept.address in input.hidden_concepts
46
+ ):
46
47
  continue
47
48
  if concept.address in full_addresses:
48
49
  concept_map[concept.address].add(input)
@@ -138,7 +139,7 @@ class StrategyNode:
138
139
  preexisting_conditions: Conditional | Comparison | Parenthetical | None = None,
139
140
  force_group: bool | None = None,
140
141
  grain: Optional[Grain] = None,
141
- hidden_concepts: List[Concept] | None = None,
142
+ hidden_concepts: set[str] | None = None,
142
143
  existence_concepts: List[Concept] | None = None,
143
144
  virtual_output_concepts: List[Concept] | None = None,
144
145
  ):
@@ -165,7 +166,7 @@ class StrategyNode:
165
166
  self.grain = grain
166
167
  self.force_group = force_group
167
168
  self.tainted = False
168
- self.hidden_concepts = hidden_concepts or []
169
+ self.hidden_concepts = hidden_concepts or set()
169
170
  self.existence_concepts = existence_concepts or []
170
171
  self.virtual_output_concepts = virtual_output_concepts or []
171
172
  self.preexisting_conditions = preexisting_conditions
@@ -281,22 +282,20 @@ class StrategyNode:
281
282
 
282
283
  def hide_output_concepts(self, concepts: List[Concept], rebuild: bool = True):
283
284
  for x in concepts:
284
- self.hidden_concepts.append(x)
285
+ self.hidden_concepts.add(x.address)
285
286
  if rebuild:
286
287
  self.rebuild_cache()
287
288
  return self
288
289
 
289
290
  def unhide_output_concepts(self, concepts: List[Concept], rebuild: bool = True):
290
- self.hidden_concepts = [
291
- x for x in self.hidden_concepts if x.address not in concepts
292
- ]
291
+ self.hidden_concepts = set(x for x in self.hidden_concepts if x not in concepts)
293
292
  if rebuild:
294
293
  self.rebuild_cache()
295
294
  return self
296
295
 
297
296
  def remove_output_concepts(self, concepts: List[Concept], rebuild: bool = True):
298
297
  for x in concepts:
299
- self.hidden_concepts.append(x)
298
+ self.hidden_concepts.add(x.address)
300
299
  addresses = [x.address for x in concepts]
301
300
  self.output_concepts = [
302
301
  x for x in self.output_concepts if x.address not in addresses
@@ -388,7 +387,7 @@ class StrategyNode:
388
387
  preexisting_conditions=self.preexisting_conditions,
389
388
  force_group=self.force_group,
390
389
  grain=self.grain,
391
- hidden_concepts=list(self.hidden_concepts),
390
+ hidden_concepts=set(self.hidden_concepts),
392
391
  existence_concepts=list(self.existence_concepts),
393
392
  virtual_output_concepts=list(self.virtual_output_concepts),
394
393
  )
@@ -48,7 +48,7 @@ class GroupNode(StrategyNode):
48
48
  conditions: Conditional | Comparison | Parenthetical | None = None,
49
49
  preexisting_conditions: Conditional | Comparison | Parenthetical | None = None,
50
50
  existence_concepts: List[Concept] | None = None,
51
- hidden_concepts: List[Concept] | None = None,
51
+ hidden_concepts: set[str] | None = None,
52
52
  ):
53
53
  super().__init__(
54
54
  input_concepts=input_concepts,
@@ -154,9 +154,9 @@ class GroupNode(StrategyNode):
154
154
  base.output_concepts + self.conditions.row_arguments, "address"
155
155
  )
156
156
  # re-visible any hidden concepts
157
- base.hidden_concepts = [
158
- x for x in base.hidden_concepts if x not in base.output_concepts
159
- ]
157
+ base.hidden_concepts = set(
158
+ [x for x in base.hidden_concepts if x not in base.output_concepts]
159
+ )
160
160
  source_map = resolve_concept_map(
161
161
  [base],
162
162
  targets=self.output_concepts,
@@ -191,5 +191,5 @@ class GroupNode(StrategyNode):
191
191
  conditions=self.conditions,
192
192
  preexisting_conditions=self.preexisting_conditions,
193
193
  existence_concepts=list(self.existence_concepts),
194
- hidden_concepts=list(self.hidden_concepts),
194
+ hidden_concepts=set(self.hidden_concepts),
195
195
  )
@@ -115,7 +115,7 @@ class MergeNode(StrategyNode):
115
115
  grain: Grain | None = None,
116
116
  conditions: Conditional | Comparison | Parenthetical | None = None,
117
117
  preexisting_conditions: Conditional | Comparison | Parenthetical | None = None,
118
- hidden_concepts: List[Concept] | None = None,
118
+ hidden_concepts: set[str] | None = None,
119
119
  virtual_output_concepts: List[Concept] | None = None,
120
120
  existence_concepts: List[Concept] | None = None,
121
121
  ):
@@ -369,7 +369,7 @@ class MergeNode(StrategyNode):
369
369
  conditions=self.conditions,
370
370
  preexisting_conditions=self.preexisting_conditions,
371
371
  nullable_concepts=list(self.nullable_concepts),
372
- hidden_concepts=list(self.hidden_concepts),
372
+ hidden_concepts=set(self.hidden_concepts),
373
373
  virtual_output_concepts=list(self.virtual_output_concepts),
374
374
  node_joins=list(self.node_joins) if self.node_joins else None,
375
375
  join_concepts=list(self.join_concepts) if self.join_concepts else None,
@@ -45,7 +45,7 @@ class SelectNode(StrategyNode):
45
45
  force_group: bool | None = False,
46
46
  conditions: Conditional | Comparison | Parenthetical | None = None,
47
47
  preexisting_conditions: Conditional | Comparison | Parenthetical | None = None,
48
- hidden_concepts: List[Concept] | None = None,
48
+ hidden_concepts: set[str] | None = None,
49
49
  ):
50
50
  super().__init__(
51
51
  input_concepts=input_concepts,
@@ -347,7 +347,7 @@ def get_node_joins(
347
347
  graph.add_node(ds_node, type=NodeType.NODE)
348
348
  partials[ds_node] = [f"c~{c.address}" for c in datasource.partial_concepts]
349
349
  for concept in datasource.output_concepts:
350
- if concept in datasource.hidden_concepts:
350
+ if concept.address in datasource.hidden_concepts:
351
351
  continue
352
352
  add_node_join_concept(
353
353
  graph=graph,
@@ -567,9 +567,8 @@ def find_nullable_concepts(
567
567
  def sort_select_output_processed(
568
568
  cte: CTE | UnionCTE, query: ProcessedQuery
569
569
  ) -> CTE | UnionCTE:
570
- hidden_addresses = [c.address for c in query.hidden_columns]
571
570
  output_addresses = [
572
- c.address for c in query.output_columns if c.address not in hidden_addresses
571
+ c.address for c in query.output_columns if c.address not in query.hidden_columns
573
572
  ]
574
573
 
575
574
  mapping = {x.address: x for x in cte.output_columns}
@@ -586,9 +585,10 @@ def sort_select_output(
586
585
  ) -> CTE | UnionCTE:
587
586
  if isinstance(query, ProcessedQuery):
588
587
  return sort_select_output_processed(cte, query)
589
- hidden_addresses = [c.address for c in query.hidden_components]
590
588
  output_addresses = [
591
- c.address for c in query.output_components if c.address not in hidden_addresses
589
+ c.address
590
+ for c in query.output_components
591
+ if c.address not in query.hidden_components
592
592
  ]
593
593
 
594
594
  mapping = {x.address: x for x in cte.output_columns}
@@ -500,7 +500,7 @@ def process_query(
500
500
  deduped_ctes: List[CTE | UnionCTE] = list(seen.values())
501
501
  root_cte.order_by = statement.order_by
502
502
  root_cte.limit = statement.limit
503
- root_cte.hidden_concepts = [x for x in statement.hidden_components]
503
+ root_cte.hidden_concepts = statement.hidden_components
504
504
 
505
505
  final_ctes = optimize_ctes(deduped_ctes, root_cte, statement)
506
506
  return ProcessedQuery(
@@ -514,6 +514,6 @@ def process_query(
514
514
  base=root_cte,
515
515
  # we no longer do any joins at final level, this should always happen in parent CTEs
516
516
  joins=[],
517
- hidden_columns=[x for x in statement.hidden_components],
517
+ hidden_columns=set([x for x in statement.hidden_components]),
518
518
  local_concepts=statement.local_concepts,
519
519
  )
@@ -660,7 +660,7 @@ class BaseDialect:
660
660
  self.render_concept_sql(c, cte)
661
661
  for c in cte.output_columns
662
662
  if c.address not in [y.address for y in cte.join_derived_concepts]
663
- and c.address not in [y.address for y in cte.hidden_concepts]
663
+ and c.address not in cte.hidden_concepts
664
664
  ] + [
665
665
  f"{self.QUOTE_CHARACTER}{c.safe_address}{self.QUOTE_CHARACTER}"
666
666
  for c in cte.join_derived_concepts
@@ -670,7 +670,7 @@ class BaseDialect:
670
670
  select_columns = [
671
671
  self.render_concept_sql(c, cte)
672
672
  for c in cte.output_columns
673
- if c.address not in [y.address for y in cte.hidden_concepts]
673
+ if c.address not in cte.hidden_concepts
674
674
  ]
675
675
  if auto_sort:
676
676
  select_columns = sorted(select_columns, key=lambda x: x)
@@ -886,9 +886,10 @@ class BaseDialect:
886
886
  select_columns: Dict[str, str] = {}
887
887
  cte_output_map = {}
888
888
  selected = set()
889
- hidden_addresses = [c.address for c in query.hidden_columns]
890
889
  output_addresses = [
891
- c.address for c in query.output_columns if c.address not in hidden_addresses
890
+ c.address
891
+ for c in query.output_columns
892
+ if c.address not in query.hidden_columns
892
893
  ]
893
894
 
894
895
  for c in query.base.output_columns:
@@ -897,7 +898,7 @@ class BaseDialect:
897
898
  f"{query.base.name}.{safe_quote(c.safe_address, self.QUOTE_CHARACTER)}"
898
899
  )
899
900
  cte_output_map[c.address] = query.base
900
- if c.address not in hidden_addresses:
901
+ if c.address not in query.hidden_columns:
901
902
  selected.add(c.address)
902
903
  if not all([x in selected for x in output_addresses]):
903
904
  missing = [x for x in output_addresses if x not in selected]
File without changes
File without changes
File without changes
File without changes