pytrilogy 0.0.3.53__py3-none-any.whl → 0.0.3.54__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.3.53.dist-info → pytrilogy-0.0.3.54.dist-info}/METADATA +1 -1
- {pytrilogy-0.0.3.53.dist-info → pytrilogy-0.0.3.54.dist-info}/RECORD +12 -12
- {pytrilogy-0.0.3.53.dist-info → pytrilogy-0.0.3.54.dist-info}/WHEEL +1 -1
- trilogy/__init__.py +1 -1
- trilogy/core/optimization.py +26 -9
- trilogy/core/processing/node_generators/rowset_node.py +1 -3
- trilogy/core/processing/node_generators/window_node.py +13 -4
- trilogy/core/processing/nodes/__init__.py +2 -1
- trilogy/core/processing/nodes/base_node.py +32 -2
- {pytrilogy-0.0.3.53.dist-info → pytrilogy-0.0.3.54.dist-info}/entry_points.txt +0 -0
- {pytrilogy-0.0.3.53.dist-info → pytrilogy-0.0.3.54.dist-info}/licenses/LICENSE.md +0 -0
- {pytrilogy-0.0.3.53.dist-info → pytrilogy-0.0.3.54.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
pytrilogy-0.0.3.
|
|
2
|
-
trilogy/__init__.py,sha256=
|
|
1
|
+
pytrilogy-0.0.3.54.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
|
|
2
|
+
trilogy/__init__.py,sha256=Wz4e3LWZ4MWyBm3EuLrz5-n5-yyu96rHR7k-4JPA4RE,303
|
|
3
3
|
trilogy/compiler.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
trilogy/constants.py,sha256=5eQxk1A0pv-TQk3CCvgZCFA9_K-6nxrOm7E5Lxd7KIY,1652
|
|
5
5
|
trilogy/engine.py,sha256=OK2RuqCIUId6yZ5hfF8J1nxGP0AJqHRZiafcowmW0xc,1728
|
|
@@ -19,7 +19,7 @@ trilogy/core/exceptions.py,sha256=JPYyBcit3T_pRtlHdtKSeVJkIyWUTozW2aaut25A2xI,67
|
|
|
19
19
|
trilogy/core/functions.py,sha256=IvqHyuO__o6Th8tkDWjb9cDxQDly6l3ZEfJ9y8YrTRU,29227
|
|
20
20
|
trilogy/core/graph_models.py,sha256=z17EoO8oky2QOuO6E2aMWoVNKEVJFhLdsQZOhC4fNLU,2079
|
|
21
21
|
trilogy/core/internal.py,sha256=iicDBlC6nM8d7e7jqzf_ZOmpUsW8yrr2AA8AqEiLx-s,1577
|
|
22
|
-
trilogy/core/optimization.py,sha256=
|
|
22
|
+
trilogy/core/optimization.py,sha256=ClDPMuuLBjuZCHdRGsuNhKNNTkbev1I22SbnLMzHT60,8839
|
|
23
23
|
trilogy/core/query_processor.py,sha256=NNzYPKN5HzivQFXugSbJC_MaupkwOYii7A_vnXuBIK4,20063
|
|
24
24
|
trilogy/core/utility.py,sha256=3VC13uSQWcZNghgt7Ot0ZTeEmNqs__cx122abVq9qhM,410
|
|
25
25
|
trilogy/core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -46,17 +46,17 @@ trilogy/core/processing/node_generators/group_node.py,sha256=nIfiMrJQEksUfqAeeA3
|
|
|
46
46
|
trilogy/core/processing/node_generators/group_to_node.py,sha256=jKcNCDOY6fNblrdZwaRU0sbUSr9H0moQbAxrGgX6iGA,3832
|
|
47
47
|
trilogy/core/processing/node_generators/multiselect_node.py,sha256=GWV5yLmKTe1yyPhN60RG1Rnrn4ktfn9lYYXi_FVU4UI,7061
|
|
48
48
|
trilogy/core/processing/node_generators/node_merge_node.py,sha256=sv55oynfqgpHEpo1OEtVDri-5fywzPhDlR85qaWikvY,16195
|
|
49
|
-
trilogy/core/processing/node_generators/rowset_node.py,sha256=
|
|
49
|
+
trilogy/core/processing/node_generators/rowset_node.py,sha256=2BiSsegbRF9csJ_Xl8P_CxIm4dAAb7dF29u6v_Odr-A,6709
|
|
50
50
|
trilogy/core/processing/node_generators/select_merge_node.py,sha256=lxXhMhDKGbu67QFNbbAT-BO8gbWppIvjn_hAXpLEPe0,19953
|
|
51
51
|
trilogy/core/processing/node_generators/select_node.py,sha256=Y-zO0AFkTrpi2LyebjpyHU7WWANr7nKZSS9rY7DH4Wo,1888
|
|
52
52
|
trilogy/core/processing/node_generators/synonym_node.py,sha256=9LHK2XHDjbyTLjmDQieskG8fqbiSpRnFOkfrutDnOTE,2258
|
|
53
53
|
trilogy/core/processing/node_generators/union_node.py,sha256=VNo6Oey4p8etU9xrOh2oTT2lIOTvY6PULUPRvVa2uxU,2877
|
|
54
54
|
trilogy/core/processing/node_generators/unnest_node.py,sha256=cOEKnMRzXUW3bwmiOlgn3E1-B38osng0dh2pDykwITY,2410
|
|
55
|
-
trilogy/core/processing/node_generators/window_node.py,sha256=
|
|
55
|
+
trilogy/core/processing/node_generators/window_node.py,sha256=GP3Hvkbb0TDA6ef7W7bmvQEHVH-NRIfBT_0W4fcH3g4,6529
|
|
56
56
|
trilogy/core/processing/node_generators/select_helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
57
57
|
trilogy/core/processing/node_generators/select_helpers/datasource_injection.py,sha256=GMW07bb6hXurhF0hZLYoMAKSIS65tat5hwBjvqqPeSA,6516
|
|
58
|
-
trilogy/core/processing/nodes/__init__.py,sha256=
|
|
59
|
-
trilogy/core/processing/nodes/base_node.py,sha256=
|
|
58
|
+
trilogy/core/processing/nodes/__init__.py,sha256=oHDknqAZFm6KSDDbzJXj8HDGDh-dn-YjHDGqiXc8Psw,6054
|
|
59
|
+
trilogy/core/processing/nodes/base_node.py,sha256=IdKR2yaQGY1iRgKXgxF1UtlyuJEmPXWRh0rGFXv7Z_U,18111
|
|
60
60
|
trilogy/core/processing/nodes/filter_node.py,sha256=5VtRfKbCORx0dV-vQfgy3gOEkmmscL9f31ExvlODwvY,2461
|
|
61
61
|
trilogy/core/processing/nodes/group_node.py,sha256=MUvcOg9U5J6TnWBel8eht9PdI9BfAKjUxmfjP_ZXx9o,10484
|
|
62
62
|
trilogy/core/processing/nodes/merge_node.py,sha256=02oWRca0ba41U6PSAB14jwnWWxoyrvxRPLwkli259SY,15865
|
|
@@ -102,8 +102,8 @@ trilogy/std/display.preql,sha256=2BbhvqR4rcltyAbOXAUo7SZ_yGFYZgFnurglHMbjW2g,40
|
|
|
102
102
|
trilogy/std/geography.preql,sha256=-fqAGnBL6tR-UtT8DbSek3iMFg66ECR_B_41pODxv-k,504
|
|
103
103
|
trilogy/std/money.preql,sha256=ZHW-csTX-kYbOLmKSO-TcGGgQ-_DMrUXy0BjfuJSFxM,80
|
|
104
104
|
trilogy/std/report.preql,sha256=LbV-XlHdfw0jgnQ8pV7acG95xrd1-p65fVpiIc-S7W4,202
|
|
105
|
-
pytrilogy-0.0.3.
|
|
106
|
-
pytrilogy-0.0.3.
|
|
107
|
-
pytrilogy-0.0.3.
|
|
108
|
-
pytrilogy-0.0.3.
|
|
109
|
-
pytrilogy-0.0.3.
|
|
105
|
+
pytrilogy-0.0.3.54.dist-info/METADATA,sha256=_Bv_Q8dZSrH750iNkW7KtpUP1vSAwZRnBzsG8KDXdXE,9095
|
|
106
|
+
pytrilogy-0.0.3.54.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
|
|
107
|
+
pytrilogy-0.0.3.54.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
|
|
108
|
+
pytrilogy-0.0.3.54.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
|
|
109
|
+
pytrilogy-0.0.3.54.dist-info/RECORD,,
|
trilogy/__init__.py
CHANGED
trilogy/core/optimization.py
CHANGED
|
@@ -120,6 +120,13 @@ def gen_inverse_map(input: list[CTE | UnionCTE]) -> dict[str, list[CTE | UnionCT
|
|
|
120
120
|
return inverse_map
|
|
121
121
|
|
|
122
122
|
|
|
123
|
+
SENSITIVE_DERIVATIONS = [
|
|
124
|
+
Derivation.UNNEST,
|
|
125
|
+
Derivation.WINDOW,
|
|
126
|
+
# Derivation.AGGREGATE,
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
|
|
123
130
|
def is_direct_return_eligible(cte: CTE | UnionCTE) -> CTE | UnionCTE | None:
|
|
124
131
|
# if isinstance(select, (PersistStatement, MultiSelectStatement)):
|
|
125
132
|
# return False
|
|
@@ -151,21 +158,31 @@ def is_direct_return_eligible(cte: CTE | UnionCTE) -> CTE | UnionCTE | None:
|
|
|
151
158
|
]
|
|
152
159
|
condition_arguments = cte.condition.row_arguments if cte.condition else []
|
|
153
160
|
for x in derived_concepts:
|
|
154
|
-
if x.derivation
|
|
155
|
-
return None
|
|
156
|
-
if x.derivation == Derivation.UNNEST:
|
|
157
|
-
return None
|
|
158
|
-
if x.derivation == Derivation.AGGREGATE:
|
|
161
|
+
if x.derivation in SENSITIVE_DERIVATIONS:
|
|
159
162
|
return None
|
|
160
163
|
for x in parent_derived_concepts:
|
|
161
164
|
if x.address not in condition_arguments:
|
|
162
165
|
continue
|
|
163
|
-
if x.derivation
|
|
164
|
-
return None
|
|
165
|
-
if x.derivation == Derivation.WINDOW:
|
|
166
|
+
if x.derivation in SENSITIVE_DERIVATIONS:
|
|
166
167
|
return None
|
|
168
|
+
for x in condition_arguments:
|
|
169
|
+
# if it's derived in the parent
|
|
170
|
+
if x.address in parent_derived_concepts:
|
|
171
|
+
if x.derivation in SENSITIVE_DERIVATIONS:
|
|
172
|
+
return None
|
|
173
|
+
# this maybe needs to be recursive if we flatten a ton of derivation
|
|
174
|
+
# into one CTE
|
|
175
|
+
if not x.lineage:
|
|
176
|
+
continue
|
|
177
|
+
for z in x.lineage.concept_arguments:
|
|
178
|
+
# if it was preexisting in the parent, it's safe
|
|
179
|
+
if z.address in direct_parent.source.input_concepts:
|
|
180
|
+
continue
|
|
181
|
+
# otherwise if it's dangerous, play it safe.
|
|
182
|
+
if z.derivation in SENSITIVE_DERIVATIONS:
|
|
183
|
+
return None
|
|
167
184
|
logger.info(
|
|
168
|
-
f"[Optimization][EarlyReturn] Removing redundant output CTE with derived_concepts {[x.address for x in derived_concepts]}"
|
|
185
|
+
f"[Optimization][EarlyReturn] Removing redundant output CTE {cte.name} with derived_concepts {[x.address for x in derived_concepts]}"
|
|
169
186
|
)
|
|
170
187
|
return direct_parent
|
|
171
188
|
|
|
@@ -95,9 +95,7 @@ def gen_rowset_node(
|
|
|
95
95
|
f"{padding(depth)}{LOGGER_PREFIX} hiding {final_hidden} local optional {local_optional}"
|
|
96
96
|
)
|
|
97
97
|
node.hide_output_concepts(final_hidden)
|
|
98
|
-
|
|
99
|
-
# assume grain to be output of select
|
|
100
|
-
# but don't include anything hidden(the non-rowset concepts)
|
|
98
|
+
|
|
101
99
|
node.grain = BuildGrain.from_concepts(
|
|
102
100
|
[
|
|
103
101
|
x
|
|
@@ -11,7 +11,12 @@ from trilogy.core.models.build_environment import BuildEnvironment
|
|
|
11
11
|
from trilogy.core.processing.node_generators.common import (
|
|
12
12
|
gen_enrichment_node,
|
|
13
13
|
)
|
|
14
|
-
from trilogy.core.processing.nodes import
|
|
14
|
+
from trilogy.core.processing.nodes import (
|
|
15
|
+
History,
|
|
16
|
+
StrategyNode,
|
|
17
|
+
WhereSafetyNode,
|
|
18
|
+
WindowNode,
|
|
19
|
+
)
|
|
15
20
|
from trilogy.core.processing.utility import create_log_lambda, padding
|
|
16
21
|
from trilogy.utility import unique
|
|
17
22
|
|
|
@@ -71,10 +76,13 @@ def gen_window_node(
|
|
|
71
76
|
if equivalent_optional:
|
|
72
77
|
for x in equivalent_optional:
|
|
73
78
|
assert isinstance(x.lineage, WINDOW_TYPES)
|
|
79
|
+
base, parents = resolve_window_parent_concepts(x, environment)
|
|
74
80
|
logger.info(
|
|
75
|
-
f"{padding(depth)}{LOGGER_PREFIX} found equivalent optional {x} with parents {
|
|
81
|
+
f"{padding(depth)}{LOGGER_PREFIX} found equivalent optional {x} with parents {parents}"
|
|
76
82
|
)
|
|
77
83
|
additional_outputs.append(x)
|
|
84
|
+
# also append the base concept it's being grouped over
|
|
85
|
+
targets.append(base)
|
|
78
86
|
|
|
79
87
|
grain_equivalents = [
|
|
80
88
|
x
|
|
@@ -85,7 +93,8 @@ def gen_window_node(
|
|
|
85
93
|
]
|
|
86
94
|
|
|
87
95
|
for x in grain_equivalents:
|
|
88
|
-
|
|
96
|
+
if x.address in additional_outputs:
|
|
97
|
+
continue
|
|
89
98
|
targets.append(x)
|
|
90
99
|
|
|
91
100
|
# finally, the ones we'll need to enrich
|
|
@@ -134,7 +143,7 @@ def gen_window_node(
|
|
|
134
143
|
_window_node.rebuild_cache()
|
|
135
144
|
_window_node.resolve()
|
|
136
145
|
|
|
137
|
-
window_node =
|
|
146
|
+
window_node = WhereSafetyNode(
|
|
138
147
|
input_concepts=[concept] + additional_outputs + parent_concepts + targets,
|
|
139
148
|
output_concepts=[concept] + additional_outputs + parent_concepts + targets,
|
|
140
149
|
environment=environment,
|
|
@@ -6,7 +6,7 @@ from trilogy.core.models.build import BuildConcept, BuildWhereClause
|
|
|
6
6
|
from trilogy.core.models.build_environment import BuildEnvironment
|
|
7
7
|
from trilogy.core.models.environment import Environment
|
|
8
8
|
|
|
9
|
-
from .base_node import NodeJoin, StrategyNode
|
|
9
|
+
from .base_node import NodeJoin, StrategyNode, WhereSafetyNode
|
|
10
10
|
from .filter_node import FilterNode
|
|
11
11
|
from .group_node import GroupNode
|
|
12
12
|
from .merge_node import MergeNode
|
|
@@ -193,4 +193,5 @@ __all__ = [
|
|
|
193
193
|
"UnnestNode",
|
|
194
194
|
"UnionNode",
|
|
195
195
|
"History",
|
|
196
|
+
"WhereSafetyNode",
|
|
196
197
|
]
|
|
@@ -291,9 +291,14 @@ class StrategyNode:
|
|
|
291
291
|
def add_output_concept(self, concept: BuildConcept, rebuild: bool = True):
|
|
292
292
|
return self.add_output_concepts([concept], rebuild)
|
|
293
293
|
|
|
294
|
-
def hide_output_concepts(
|
|
294
|
+
def hide_output_concepts(
|
|
295
|
+
self, concepts: List[BuildConcept] | list[str] | set[str], rebuild: bool = True
|
|
296
|
+
):
|
|
295
297
|
for x in concepts:
|
|
296
|
-
|
|
298
|
+
if isinstance(x, BuildConcept):
|
|
299
|
+
self.hidden_concepts.add(x.address)
|
|
300
|
+
else:
|
|
301
|
+
self.hidden_concepts.add(x)
|
|
297
302
|
if rebuild:
|
|
298
303
|
self.rebuild_cache()
|
|
299
304
|
return self
|
|
@@ -471,3 +476,28 @@ class NodeJoin:
|
|
|
471
476
|
f" {self.right_node} on"
|
|
472
477
|
f" {','.join([str(k) for k in self.concepts])}"
|
|
473
478
|
)
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
class WhereSafetyNode(StrategyNode):
|
|
482
|
+
"""Specialized node to be used to pad certain
|
|
483
|
+
select outputs that can't be immediately used in a where
|
|
484
|
+
clause; eg window functions. Will remove itself if not required."""
|
|
485
|
+
|
|
486
|
+
def resolve(self) -> QueryDatasource:
|
|
487
|
+
if not self.conditions and len(self.parents) == 1:
|
|
488
|
+
parent = self.parents[0]
|
|
489
|
+
parent = parent.copy()
|
|
490
|
+
# avoid performance hit by not rebuilding until end
|
|
491
|
+
parent.set_output_concepts(self.output_concepts, rebuild=False)
|
|
492
|
+
parent.hide_output_concepts(self.hidden_concepts, rebuild=False)
|
|
493
|
+
|
|
494
|
+
# these conditions
|
|
495
|
+
if self.preexisting_conditions:
|
|
496
|
+
parent.set_preexisting_conditions(self.preexisting_conditions)
|
|
497
|
+
# TODO: add a helper for this
|
|
498
|
+
parent.ordering = self.ordering
|
|
499
|
+
|
|
500
|
+
# actually build the node
|
|
501
|
+
parent.rebuild_cache()
|
|
502
|
+
return parent.resolve()
|
|
503
|
+
return super().resolve()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|