pytrilogy 0.0.2.9__py3-none-any.whl → 0.0.2.10__py3-none-any.whl
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.
- {pytrilogy-0.0.2.9.dist-info → pytrilogy-0.0.2.10.dist-info}/METADATA +1 -1
- {pytrilogy-0.0.2.9.dist-info → pytrilogy-0.0.2.10.dist-info}/RECORD +16 -16
- trilogy/__init__.py +1 -1
- trilogy/constants.py +1 -1
- trilogy/core/models.py +17 -5
- trilogy/core/processing/node_generators/filter_node.py +7 -2
- trilogy/core/processing/nodes/group_node.py +1 -5
- trilogy/core/processing/utility.py +18 -5
- trilogy/core/query_processor.py +1 -1
- trilogy/dialect/base.py +17 -11
- trilogy/dialect/duckdb.py +1 -1
- trilogy/parsing/parse_engine.py +19 -1
- {pytrilogy-0.0.2.9.dist-info → pytrilogy-0.0.2.10.dist-info}/LICENSE.md +0 -0
- {pytrilogy-0.0.2.9.dist-info → pytrilogy-0.0.2.10.dist-info}/WHEEL +0 -0
- {pytrilogy-0.0.2.9.dist-info → pytrilogy-0.0.2.10.dist-info}/entry_points.txt +0 -0
- {pytrilogy-0.0.2.9.dist-info → pytrilogy-0.0.2.10.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
trilogy/__init__.py,sha256
|
|
1
|
+
trilogy/__init__.py,sha256=-fwTLWZDBATA0SPkOXcsRS3py_W_F1oq7wt2cVysbNg,291
|
|
2
2
|
trilogy/compiler.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
trilogy/constants.py,sha256=
|
|
3
|
+
trilogy/constants.py,sha256=HRQq4i3cpSEJCywt61QKEzRO1jd4tEPZNSBuxUA_7yg,922
|
|
4
4
|
trilogy/engine.py,sha256=R5ubIxYyrxRExz07aZCUfrTsoXCHQ8DKFTDsobXdWdA,1102
|
|
5
5
|
trilogy/executor.py,sha256=5cRbU4Rj7p1pNV76rfp1pz704Hx_0q8_O8HFURjgXxQ,11016
|
|
6
6
|
trilogy/parser.py,sha256=UtuqSiGiCjpMAYgo1bvNq-b7NSzCA5hzbUW31RXaMII,281
|
|
@@ -16,9 +16,9 @@ trilogy/core/exceptions.py,sha256=NvV_4qLOgKXbpotgRf7c8BANDEvHxlqRPaA53IThQ2o,56
|
|
|
16
16
|
trilogy/core/functions.py,sha256=ARJAyBjeS415-54k3G_bx807rkPZonEulMaLRxSP7vU,10371
|
|
17
17
|
trilogy/core/graph_models.py,sha256=oJUMSpmYhqXlavckHLpR07GJxuQ8dZ1VbB1fB0KaS8c,2036
|
|
18
18
|
trilogy/core/internal.py,sha256=jNGFHKENnbMiMCtAgsnLZYVSENDK4b5ALecXFZpTDzQ,1075
|
|
19
|
-
trilogy/core/models.py,sha256=
|
|
19
|
+
trilogy/core/models.py,sha256=mjORKd_RFvNc_c7QqCHCM4GrJSb5VA50tMqo7fX5-Bw,142855
|
|
20
20
|
trilogy/core/optimization.py,sha256=RJmDr2f9hyFePF-B6LpmHkj69-AzUm-nNtvO59899O8,6601
|
|
21
|
-
trilogy/core/query_processor.py,sha256=
|
|
21
|
+
trilogy/core/query_processor.py,sha256=N5Jdbb8D8_mdeJufIch0uCbfuf2psSSkLxGXwC5CqCg,18663
|
|
22
22
|
trilogy/core/optimizations/__init__.py,sha256=pxRzNzd2g8oRMy4f_ub5va6bNS2pd4hnyp9JBzTKc1E,300
|
|
23
23
|
trilogy/core/optimizations/base_optimization.py,sha256=tWWT-xnTbnEU-mNi_isMNbywm8B9WTRsNFwGpeh3rqE,468
|
|
24
24
|
trilogy/core/optimizations/inline_constant.py,sha256=kHNyc2UoaPVdYfVAPAFwnWuk4sJ_IF5faRtVcDOrBtw,1110
|
|
@@ -27,11 +27,11 @@ trilogy/core/optimizations/predicate_pushdown.py,sha256=4Y6zfJN3VVexkD6p9IYWN4BT
|
|
|
27
27
|
trilogy/core/processing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
28
|
trilogy/core/processing/concept_strategies_v3.py,sha256=yjCiGKzghjAc0E0QAcdJ1Xr5RXHAQL2zMPOz-dMhEzM,25431
|
|
29
29
|
trilogy/core/processing/graph_utils.py,sha256=aq-kqk4Iado2HywDxWEejWc-7PGO6Oa-ZQLAM6XWPHw,1199
|
|
30
|
-
trilogy/core/processing/utility.py,sha256=
|
|
30
|
+
trilogy/core/processing/utility.py,sha256=15Qi68ktmnQmMt5jxrpueQ34oG5fSSgst3kIEejwF8A,14519
|
|
31
31
|
trilogy/core/processing/node_generators/__init__.py,sha256=-mzYkRsaRNa_dfTckYkKVFSR8h8a3ihEiPJDU_tAmDo,672
|
|
32
32
|
trilogy/core/processing/node_generators/basic_node.py,sha256=4242PNGTCm2tklqMIkqVu5Iv4m_IeTnOYXxDveuCDZM,2856
|
|
33
33
|
trilogy/core/processing/node_generators/common.py,sha256=lDBRq9X6dQ_xSwXxLLNDq2pW8D-XwAY-ylTJLMugkLw,9525
|
|
34
|
-
trilogy/core/processing/node_generators/filter_node.py,sha256=
|
|
34
|
+
trilogy/core/processing/node_generators/filter_node.py,sha256=N8PoPvj-_ZQbucTyNqpZ1EyPTDAy6oB7DuEYCQxQBOs,7411
|
|
35
35
|
trilogy/core/processing/node_generators/group_node.py,sha256=JwT8qYeGbozrZNGAlpndc9aaIN7K9ROYkkc2rAS8Qz8,3079
|
|
36
36
|
trilogy/core/processing/node_generators/group_to_node.py,sha256=nzITnhaALIT7FMonyo16nNo-kSrLfefa9sZBYecrvkU,2887
|
|
37
37
|
trilogy/core/processing/node_generators/multiselect_node.py,sha256=vP84dnLQy6dtypi6mUbt9sMAcmmrTgQ1Oz4GI6X1IEo,6421
|
|
@@ -43,17 +43,17 @@ trilogy/core/processing/node_generators/window_node.py,sha256=lFfmEjX_mLB7MuOM6C
|
|
|
43
43
|
trilogy/core/processing/nodes/__init__.py,sha256=jyduHk96j5fpju72sc8swOiBjR3Md866kt8JZGkp3ZU,4866
|
|
44
44
|
trilogy/core/processing/nodes/base_node.py,sha256=KVLAPLlo5QQq9Cm6lTLsqLN7l8EyXGxQkKrZFHdyRp8,12871
|
|
45
45
|
trilogy/core/processing/nodes/filter_node.py,sha256=DBOSGFfkiILrZa1BlLv2uxUSkgWtSIKiZplqyKXPjg8,2132
|
|
46
|
-
trilogy/core/processing/nodes/group_node.py,sha256=
|
|
46
|
+
trilogy/core/processing/nodes/group_node.py,sha256=RKqODYxbY8wmClvI8-k3UgXWL7qQv5Hxhz5AB-RVUu0,6344
|
|
47
47
|
trilogy/core/processing/nodes/merge_node.py,sha256=ZUcFIm5v4hip_Ml_oJXqVMrevUkE62wvPrvCrO9FWAc,14272
|
|
48
48
|
trilogy/core/processing/nodes/select_node_v2.py,sha256=QuXNcwgjTRYamOoIooGrp4ie6INcqA9whtC5LZWjD8s,7180
|
|
49
49
|
trilogy/core/processing/nodes/unnest_node.py,sha256=JFtm90IVM-46aCYkTNIaJah6v9ApAfonjVhcVM1HmDE,1903
|
|
50
50
|
trilogy/core/processing/nodes/window_node.py,sha256=X7qxLUKd3tekjUUsmH_4vz5b-U89gMnGd04VBxuu2Ns,1280
|
|
51
51
|
trilogy/dialect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
52
|
-
trilogy/dialect/base.py,sha256=
|
|
52
|
+
trilogy/dialect/base.py,sha256=_WKy2YJyDZdelHVX4mcnwKzAp2J-56UjoBpS5hG2yrg,30819
|
|
53
53
|
trilogy/dialect/bigquery.py,sha256=15KJ-cOpBlk9O7FPviPgmg8xIydJeKx7WfmL3SSsPE8,2953
|
|
54
54
|
trilogy/dialect/common.py,sha256=HVNPL8dGyQjT2REruV5C2YPpBbVR7KlD0akVM7GcuPI,3329
|
|
55
55
|
trilogy/dialect/config.py,sha256=tLVEMctaTDhUgARKXUNfHUcIolGaALkQ0RavUvXAY4w,2994
|
|
56
|
-
trilogy/dialect/duckdb.py,sha256=
|
|
56
|
+
trilogy/dialect/duckdb.py,sha256=u_gpL35kouWxoBLas1h0ABYY2QzlVtEh22hm5h0lCOM,3182
|
|
57
57
|
trilogy/dialect/enums.py,sha256=4NdpsydBpDn6jnh0JzFz5VvQEtnShErWtWHVyT6TNpw,3948
|
|
58
58
|
trilogy/dialect/postgres.py,sha256=ev1RJZsC8BB3vJSxJ4q-TTYqZ4Hk1NXUtuRkLrQEBX0,3254
|
|
59
59
|
trilogy/dialect/presto.py,sha256=2Rs53UfPxKU0rJTcEbiS-Lxm-CDiqUGojh7yRpQgyRE,3416
|
|
@@ -69,14 +69,14 @@ trilogy/parsing/common.py,sha256=zNd5buKxK4z9WSszOk4zOI0GexDFukzZtdNfQxg3kVw,621
|
|
|
69
69
|
trilogy/parsing/config.py,sha256=Z-DaefdKhPDmSXLgg5V4pebhSB0h590vI0_VtHnlukI,111
|
|
70
70
|
trilogy/parsing/exceptions.py,sha256=92E5i2frv5hj9wxObJZsZqj5T6bglvPzvdvco_vW1Zk,38
|
|
71
71
|
trilogy/parsing/helpers.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
72
|
-
trilogy/parsing/parse_engine.py,sha256=
|
|
72
|
+
trilogy/parsing/parse_engine.py,sha256=TD7dr9f4ffRcNB0BpzgaACqc-gD3Hy4_pOyLA7rmK7A,62563
|
|
73
73
|
trilogy/parsing/render.py,sha256=Gy_6wVYPwYLf35Iota08sbqveuWILtUhI8MYStcvtJM,12174
|
|
74
74
|
trilogy/parsing/trilogy.lark,sha256=kj1DXkqRFAb20PXN4gGDtXtQI61nUv1U8nfPWSWCr1Y,11407
|
|
75
75
|
trilogy/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
76
76
|
trilogy/scripts/trilogy.py,sha256=PHxvv6f2ODv0esyyhWxlARgra8dVhqQhYl0lTrSyVNo,3729
|
|
77
|
-
pytrilogy-0.0.2.
|
|
78
|
-
pytrilogy-0.0.2.
|
|
79
|
-
pytrilogy-0.0.2.
|
|
80
|
-
pytrilogy-0.0.2.
|
|
81
|
-
pytrilogy-0.0.2.
|
|
82
|
-
pytrilogy-0.0.2.
|
|
77
|
+
pytrilogy-0.0.2.10.dist-info/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
|
|
78
|
+
pytrilogy-0.0.2.10.dist-info/METADATA,sha256=sH_c8ZeuuG6nuSMIrKQvhLoHi67-4qWu3DZ5KM27FJQ,7907
|
|
79
|
+
pytrilogy-0.0.2.10.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
|
80
|
+
pytrilogy-0.0.2.10.dist-info/entry_points.txt,sha256=0petKryjvvtEfTlbZC1AuMFumH_WQ9v8A19LvoS6G6c,54
|
|
81
|
+
pytrilogy-0.0.2.10.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
|
|
82
|
+
pytrilogy-0.0.2.10.dist-info/RECORD,,
|
trilogy/__init__.py
CHANGED
trilogy/constants.py
CHANGED
trilogy/core/models.py
CHANGED
|
@@ -70,7 +70,7 @@ from trilogy.utility import unique
|
|
|
70
70
|
from collections import UserList, UserDict
|
|
71
71
|
from functools import cached_property
|
|
72
72
|
from abc import ABC
|
|
73
|
-
|
|
73
|
+
from collections import defaultdict
|
|
74
74
|
|
|
75
75
|
LOGGER_PREFIX = "[MODELS]"
|
|
76
76
|
|
|
@@ -2027,7 +2027,7 @@ class Datasource(Namespaced, BaseModel):
|
|
|
2027
2027
|
return self.__repr__()
|
|
2028
2028
|
|
|
2029
2029
|
def __hash__(self):
|
|
2030
|
-
return
|
|
2030
|
+
return self.full_name.__hash__()
|
|
2031
2031
|
|
|
2032
2032
|
def with_namespace(self, namespace: str):
|
|
2033
2033
|
new_namespace = (
|
|
@@ -2212,9 +2212,9 @@ class BaseJoin(BaseModel):
|
|
|
2212
2212
|
class QueryDatasource(BaseModel):
|
|
2213
2213
|
input_concepts: List[Concept]
|
|
2214
2214
|
output_concepts: List[Concept]
|
|
2215
|
+
datasources: List[Union[Datasource, "QueryDatasource"]]
|
|
2215
2216
|
source_map: Dict[str, Set[Union[Datasource, "QueryDatasource", "UnnestJoin"]]]
|
|
2216
2217
|
|
|
2217
|
-
datasources: List[Union[Datasource, "QueryDatasource"]]
|
|
2218
2218
|
grain: Grain
|
|
2219
2219
|
joins: List[BaseJoin | UnnestJoin]
|
|
2220
2220
|
limit: Optional[int] = None
|
|
@@ -2266,7 +2266,7 @@ class QueryDatasource(BaseModel):
|
|
|
2266
2266
|
|
|
2267
2267
|
@field_validator("source_map")
|
|
2268
2268
|
@classmethod
|
|
2269
|
-
def validate_source_map(cls, v, info: ValidationInfo):
|
|
2269
|
+
def validate_source_map(cls, v: dict, info: ValidationInfo):
|
|
2270
2270
|
values = info.data
|
|
2271
2271
|
for key in ("input_concepts", "output_concepts"):
|
|
2272
2272
|
if not values.get(key):
|
|
@@ -2344,11 +2344,23 @@ class QueryDatasource(BaseModel):
|
|
|
2344
2344
|
)
|
|
2345
2345
|
|
|
2346
2346
|
merged_datasources = {}
|
|
2347
|
+
|
|
2347
2348
|
for ds in [*self.datasources, *other.datasources]:
|
|
2348
2349
|
if ds.full_name in merged_datasources:
|
|
2349
2350
|
merged_datasources[ds.full_name] = merged_datasources[ds.full_name] + ds
|
|
2350
2351
|
else:
|
|
2351
2352
|
merged_datasources[ds.full_name] = ds
|
|
2353
|
+
|
|
2354
|
+
final_source_map = defaultdict(set)
|
|
2355
|
+
for key in self.source_map:
|
|
2356
|
+
final_source_map[key] = self.source_map[key].union(
|
|
2357
|
+
other.source_map.get(key, set())
|
|
2358
|
+
)
|
|
2359
|
+
for key in other.source_map:
|
|
2360
|
+
if key not in final_source_map:
|
|
2361
|
+
final_source_map[key] = other.source_map[key]
|
|
2362
|
+
for k, v in final_source_map.items():
|
|
2363
|
+
final_source_map[k] = set(merged_datasources[x.full_name] for x in list(v))
|
|
2352
2364
|
qds = QueryDatasource(
|
|
2353
2365
|
input_concepts=unique(
|
|
2354
2366
|
self.input_concepts + other.input_concepts, "address"
|
|
@@ -2356,7 +2368,7 @@ class QueryDatasource(BaseModel):
|
|
|
2356
2368
|
output_concepts=unique(
|
|
2357
2369
|
self.output_concepts + other.output_concepts, "address"
|
|
2358
2370
|
),
|
|
2359
|
-
source_map=
|
|
2371
|
+
source_map=final_source_map,
|
|
2360
2372
|
datasources=list(merged_datasources.values()),
|
|
2361
2373
|
grain=self.grain,
|
|
2362
2374
|
joins=unique(self.joins + other.joins, "unique_id"),
|
|
@@ -17,6 +17,7 @@ from trilogy.core.processing.node_generators.common import (
|
|
|
17
17
|
from trilogy.constants import logger
|
|
18
18
|
from trilogy.core.processing.utility import padding, unique
|
|
19
19
|
from trilogy.core.processing.node_generators.common import concept_to_relevant_joins
|
|
20
|
+
from trilogy.core.processing.utility import is_scalar_condition
|
|
20
21
|
|
|
21
22
|
LOGGER_PREFIX = "[GEN_FILTER_NODE]"
|
|
22
23
|
|
|
@@ -78,16 +79,20 @@ def gen_filter_node(
|
|
|
78
79
|
return None
|
|
79
80
|
|
|
80
81
|
optimized_pushdown = False
|
|
81
|
-
if not
|
|
82
|
+
if not is_scalar_condition(where.conditional):
|
|
83
|
+
optimized_pushdown = False
|
|
84
|
+
elif not local_optional:
|
|
82
85
|
optimized_pushdown = True
|
|
83
86
|
elif conditions and conditions == where:
|
|
84
87
|
logger.info(
|
|
85
88
|
f"{padding(depth)}{LOGGER_PREFIX} query conditions are the same as filter conditions, can optimize across all concepts"
|
|
86
89
|
)
|
|
87
90
|
optimized_pushdown = True
|
|
88
|
-
|
|
89
91
|
if optimized_pushdown:
|
|
90
92
|
if isinstance(row_parent, SelectNode):
|
|
93
|
+
logger.info(
|
|
94
|
+
f"{padding(depth)}{LOGGER_PREFIX} nesting select node in strategy node"
|
|
95
|
+
)
|
|
91
96
|
parent = StrategyNode(
|
|
92
97
|
input_concepts=row_parent.output_concepts,
|
|
93
98
|
output_concepts=[concept] + row_parent.output_concepts,
|
|
@@ -130,7 +130,7 @@ class GroupNode(StrategyNode):
|
|
|
130
130
|
if self.conditions
|
|
131
131
|
else self.output_concepts
|
|
132
132
|
),
|
|
133
|
-
inherited_inputs=self.input_concepts,
|
|
133
|
+
inherited_inputs=self.input_concepts + self.existence_concepts,
|
|
134
134
|
),
|
|
135
135
|
joins=[],
|
|
136
136
|
grain=grain,
|
|
@@ -139,10 +139,6 @@ class GroupNode(StrategyNode):
|
|
|
139
139
|
)
|
|
140
140
|
# if there is a condition on a group node and it's not scalar
|
|
141
141
|
# inject an additional CTE
|
|
142
|
-
if self.conditions:
|
|
143
|
-
logger.info("CONDITIONS")
|
|
144
|
-
logger.info(str(self.conditions))
|
|
145
|
-
logger.info(is_scalar_condition(self.conditions))
|
|
146
142
|
if self.conditions and not is_scalar_condition(self.conditions):
|
|
147
143
|
base.condition = None
|
|
148
144
|
base.output_concepts = self.output_concepts + self.conditions.row_arguments
|
|
@@ -355,27 +355,40 @@ def is_scalar_condition(
|
|
|
355
355
|
| MagicConstants
|
|
356
356
|
| DataType
|
|
357
357
|
),
|
|
358
|
+
materialized: set[str] | None = None,
|
|
358
359
|
) -> bool:
|
|
359
360
|
if isinstance(element, Parenthetical):
|
|
360
|
-
return is_scalar_condition(element.content)
|
|
361
|
+
return is_scalar_condition(element.content, materialized)
|
|
361
362
|
elif isinstance(element, SubselectComparison):
|
|
362
363
|
return True
|
|
363
364
|
elif isinstance(element, Comparison):
|
|
364
|
-
return is_scalar_condition(element.left) and is_scalar_condition(
|
|
365
|
+
return is_scalar_condition(element.left, materialized) and is_scalar_condition(
|
|
366
|
+
element.right, materialized
|
|
367
|
+
)
|
|
365
368
|
elif isinstance(element, Function):
|
|
366
369
|
if element.operator in FunctionClass.AGGREGATE_FUNCTIONS.value:
|
|
367
370
|
return False
|
|
371
|
+
elif isinstance(element, Concept):
|
|
372
|
+
if materialized and element.address in materialized:
|
|
373
|
+
return True
|
|
374
|
+
if element.lineage and isinstance(element.lineage, AggregateWrapper):
|
|
375
|
+
return is_scalar_condition(element.lineage, materialized)
|
|
376
|
+
return True
|
|
368
377
|
elif isinstance(element, AggregateWrapper):
|
|
369
|
-
return is_scalar_condition(element.function)
|
|
378
|
+
return is_scalar_condition(element.function, materialized)
|
|
370
379
|
elif isinstance(element, Conditional):
|
|
371
|
-
return is_scalar_condition(element.left) and is_scalar_condition(
|
|
380
|
+
return is_scalar_condition(element.left, materialized) and is_scalar_condition(
|
|
381
|
+
element.right, materialized
|
|
382
|
+
)
|
|
372
383
|
return True
|
|
373
384
|
|
|
374
385
|
|
|
375
386
|
def decompose_condition(
|
|
376
|
-
conditional: Conditional,
|
|
387
|
+
conditional: Conditional | Comparison | Parenthetical,
|
|
377
388
|
) -> list[SubselectComparison | Comparison | Conditional | Parenthetical]:
|
|
378
389
|
chunks: list[SubselectComparison | Comparison | Conditional | Parenthetical] = []
|
|
390
|
+
if not isinstance(conditional, Conditional):
|
|
391
|
+
return [conditional]
|
|
379
392
|
if conditional.operator == BooleanOperator.AND:
|
|
380
393
|
if not (
|
|
381
394
|
isinstance(
|
trilogy/core/query_processor.py
CHANGED
|
@@ -261,7 +261,7 @@ def datasource_to_ctes(
|
|
|
261
261
|
|
|
262
262
|
human_id = generate_cte_name(query_datasource.full_name, name_map)
|
|
263
263
|
logger.info(
|
|
264
|
-
f"Finished building source map for {human_id} with {len(parents)} parents, have {source_map}, query_datasource had non-empty keys {[k for k, v in query_datasource.source_map.items() if v]} "
|
|
264
|
+
f"Finished building source map for {human_id} with {len(parents)} parents, have {source_map}, query_datasource had non-empty keys {[k for k, v in query_datasource.source_map.items() if v]} and existence had non-empty keys {[k for k, v in query_datasource.existence_source_map.items() if v]} "
|
|
265
265
|
)
|
|
266
266
|
final_joins = [
|
|
267
267
|
x
|
trilogy/dialect/base.py
CHANGED
|
@@ -2,7 +2,7 @@ from typing import List, Union, Optional, Dict, Any, Sequence, Callable
|
|
|
2
2
|
|
|
3
3
|
from jinja2 import Template
|
|
4
4
|
|
|
5
|
-
from trilogy.core.processing.utility import is_scalar_condition
|
|
5
|
+
from trilogy.core.processing.utility import is_scalar_condition, decompose_condition
|
|
6
6
|
from trilogy.constants import CONFIG, logger, MagicConstants
|
|
7
7
|
from trilogy.core.internal import DEFAULT_CONCEPTS
|
|
8
8
|
from trilogy.core.enums import (
|
|
@@ -538,6 +538,20 @@ class BaseDialect:
|
|
|
538
538
|
final_joins = []
|
|
539
539
|
else:
|
|
540
540
|
final_joins = cte.joins or []
|
|
541
|
+
where: Conditional | Parenthetical | Comparison | None = None
|
|
542
|
+
having: Conditional | Parenthetical | Comparison | None = None
|
|
543
|
+
materialized = {x for x, v in cte.source_map.items() if v}
|
|
544
|
+
if cte.condition:
|
|
545
|
+
if is_scalar_condition(cte.condition, materialized=materialized):
|
|
546
|
+
where = cte.condition
|
|
547
|
+
else:
|
|
548
|
+
components = decompose_condition(cte.condition)
|
|
549
|
+
for x in components:
|
|
550
|
+
if is_scalar_condition(x, materialized=materialized):
|
|
551
|
+
where = where + x if where else x
|
|
552
|
+
else:
|
|
553
|
+
having = having + x if having else x
|
|
554
|
+
|
|
541
555
|
return CompiledCTE(
|
|
542
556
|
name=cte.name,
|
|
543
557
|
statement=self.SQL_TEMPLATE.render(
|
|
@@ -561,16 +575,8 @@ class BaseDialect:
|
|
|
561
575
|
]
|
|
562
576
|
if j
|
|
563
577
|
],
|
|
564
|
-
where=(
|
|
565
|
-
|
|
566
|
-
if cte.condition and is_scalar_condition(cte.condition)
|
|
567
|
-
else None
|
|
568
|
-
),
|
|
569
|
-
having=(
|
|
570
|
-
self.render_expr(cte.condition, cte)
|
|
571
|
-
if cte.condition and not is_scalar_condition(cte.condition)
|
|
572
|
-
else None
|
|
573
|
-
),
|
|
578
|
+
where=(self.render_expr(where, cte) if where else None),
|
|
579
|
+
having=(self.render_expr(having, cte) if having else None),
|
|
574
580
|
order_by=(
|
|
575
581
|
[self.render_order_item(i, cte) for i in cte.order_by.items]
|
|
576
582
|
if cte.order_by
|
trilogy/dialect/duckdb.py
CHANGED
|
@@ -36,7 +36,7 @@ FUNCTION_MAP = {
|
|
|
36
36
|
# we may return a static value
|
|
37
37
|
FUNCTION_GRAIN_MATCH_MAP = {
|
|
38
38
|
**FUNCTION_MAP,
|
|
39
|
-
FunctionType.COUNT: lambda args: "
|
|
39
|
+
FunctionType.COUNT: lambda args: f"{args[0]}",
|
|
40
40
|
FunctionType.SUM: lambda args: f"{args[0]}",
|
|
41
41
|
FunctionType.AVG: lambda args: f"{args[0]}",
|
|
42
42
|
}
|
trilogy/parsing/parse_engine.py
CHANGED
|
@@ -1116,7 +1116,25 @@ class ParseToObjects(Transformer):
|
|
|
1116
1116
|
def comparison(self, args) -> Comparison:
|
|
1117
1117
|
if args[1] == ComparisonOperator.IN:
|
|
1118
1118
|
raise SyntaxError
|
|
1119
|
-
|
|
1119
|
+
if isinstance(args[0], AggregateWrapper):
|
|
1120
|
+
left = arbitrary_to_concept(
|
|
1121
|
+
args[0],
|
|
1122
|
+
namespace=self.environment.namespace,
|
|
1123
|
+
name=f"{VIRTUAL_CONCEPT_PREFIX}_{string_to_hash(str(args[0]))}",
|
|
1124
|
+
)
|
|
1125
|
+
self.environment.add_concept(left)
|
|
1126
|
+
else:
|
|
1127
|
+
left = args[0]
|
|
1128
|
+
if isinstance(args[2], AggregateWrapper):
|
|
1129
|
+
right = arbitrary_to_concept(
|
|
1130
|
+
args[2],
|
|
1131
|
+
namespace=self.environment.namespace,
|
|
1132
|
+
name=f"{VIRTUAL_CONCEPT_PREFIX}_{string_to_hash(str(args[2]))}",
|
|
1133
|
+
)
|
|
1134
|
+
self.environment.add_concept(right)
|
|
1135
|
+
else:
|
|
1136
|
+
right = args[2]
|
|
1137
|
+
return Comparison(left=left, right=right, operator=args[1])
|
|
1120
1138
|
|
|
1121
1139
|
def between_comparison(self, args) -> Conditional:
|
|
1122
1140
|
left_bound = args[1]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|