pytrilogy 0.0.3.44__py3-none-any.whl → 0.0.3.46__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.44.dist-info → pytrilogy-0.0.3.46.dist-info}/METADATA +1 -1
- {pytrilogy-0.0.3.44.dist-info → pytrilogy-0.0.3.46.dist-info}/RECORD +11 -11
- {pytrilogy-0.0.3.44.dist-info → pytrilogy-0.0.3.46.dist-info}/WHEEL +1 -1
- trilogy/__init__.py +1 -1
- trilogy/core/models/author.py +1 -1
- trilogy/core/processing/concept_strategies_v3.py +2 -0
- trilogy/core/processing/node_generators/filter_node.py +31 -16
- trilogy/core/processing/nodes/__init__.py +23 -19
- {pytrilogy-0.0.3.44.dist-info → pytrilogy-0.0.3.46.dist-info}/entry_points.txt +0 -0
- {pytrilogy-0.0.3.44.dist-info → pytrilogy-0.0.3.46.dist-info}/licenses/LICENSE.md +0 -0
- {pytrilogy-0.0.3.44.dist-info → pytrilogy-0.0.3.46.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.46.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
|
|
2
|
+
trilogy/__init__.py,sha256=YyUmUiX_R4JnFfmRIfKopul0PlCDdGcFxMRUxiSPkp0,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
|
|
@@ -22,7 +22,7 @@ trilogy/core/internal.py,sha256=iicDBlC6nM8d7e7jqzf_ZOmpUsW8yrr2AA8AqEiLx-s,1577
|
|
|
22
22
|
trilogy/core/optimization.py,sha256=aihzx4-2-mSjx5td1TDTYGvc7e9Zvy-_xEyhPqLS-Ig,8314
|
|
23
23
|
trilogy/core/query_processor.py,sha256=Vl-u0F0rbqI2liv82yJgiZCB255Kx_KiuzZVHL6aeTM,19459
|
|
24
24
|
trilogy/core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
|
-
trilogy/core/models/author.py,sha256=
|
|
25
|
+
trilogy/core/models/author.py,sha256=b5GQc79w-gFQfZhgBdHeRCJAtCYr4j_da6k3Dkx4YAA,76863
|
|
26
26
|
trilogy/core/models/build.py,sha256=EsI7BLmFXdxj1an3NnKR_Qm79tcjlFKjmLjmt3_v2eA,61829
|
|
27
27
|
trilogy/core/models/build_environment.py,sha256=s_C9xAHuD3yZ26T15pWVBvoqvlp2LdZ8yjsv2_HdXLk,5363
|
|
28
28
|
trilogy/core/models/core.py,sha256=wx6hJcFECMG-Ij972ADNkr-3nFXkYESr82ObPiC46_U,10875
|
|
@@ -35,13 +35,13 @@ trilogy/core/optimizations/inline_constant.py,sha256=lvNTIXaLNkw3HseJyXyDNk5R52d
|
|
|
35
35
|
trilogy/core/optimizations/inline_datasource.py,sha256=AHuTGh2x0GQ8usOe0NiFncfTFQ_KogdgDl4uucmhIbI,4241
|
|
36
36
|
trilogy/core/optimizations/predicate_pushdown.py,sha256=g4AYE8Aw_iMlAh68TjNXGP754NTurrDduFECkUjoBnc,9399
|
|
37
37
|
trilogy/core/processing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
-
trilogy/core/processing/concept_strategies_v3.py,sha256=
|
|
38
|
+
trilogy/core/processing/concept_strategies_v3.py,sha256=tgLNXlwObWhcQmBGz8xpN4p-mFZ9Hl74VplQqDm86us,44105
|
|
39
39
|
trilogy/core/processing/graph_utils.py,sha256=8QUVrkE9j-9C1AyrCb1nQEh8daCe0u1HuXl-Te85lag,1205
|
|
40
40
|
trilogy/core/processing/utility.py,sha256=rfzdgl-vWkCyhLzXNNuWgPLK59eiYypQb6TdZKymUqk,21469
|
|
41
41
|
trilogy/core/processing/node_generators/__init__.py,sha256=o8rOFHPSo-s_59hREwXMW6gjUJCsiXumdbJNozHUf-Y,800
|
|
42
42
|
trilogy/core/processing/node_generators/basic_node.py,sha256=UVsXMn6jTjm_ofVFt218jAS11s4RV4zD781vP4im-GI,3371
|
|
43
43
|
trilogy/core/processing/node_generators/common.py,sha256=nVeH_AdO58ygtNSO0wNgMR7_h2D0dFSGM_rh1fJd4Yc,9468
|
|
44
|
-
trilogy/core/processing/node_generators/filter_node.py,sha256=
|
|
44
|
+
trilogy/core/processing/node_generators/filter_node.py,sha256=JymSKzA-9oQAZ3ZtJRK9c3w5FXs8MjJBGWU9TYUqx4E,9099
|
|
45
45
|
trilogy/core/processing/node_generators/group_node.py,sha256=kO-ersxIL04rZwX5-vFIFQQnp357PFo_7ZKXoGq3wyc,5989
|
|
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
|
|
@@ -55,7 +55,7 @@ trilogy/core/processing/node_generators/unnest_node.py,sha256=cOEKnMRzXUW3bwmiOl
|
|
|
55
55
|
trilogy/core/processing/node_generators/window_node.py,sha256=RUHgpYovQObFod1xRIMWtDzMcxwlm4-1Fdrf_Cuw5W4,6346
|
|
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=
|
|
58
|
+
trilogy/core/processing/nodes/__init__.py,sha256=MfookoG73Z9p7kYFDh033uZJpP4exqkwdKtheDRepAw,5893
|
|
59
59
|
trilogy/core/processing/nodes/base_node.py,sha256=FHrY8GsTKPuMJklOjILbhGqCt5s1nmlj62Z-molARDA,16835
|
|
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
|
|
@@ -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.46.dist-info/METADATA,sha256=1cBYEU3n78eaoNyqLsOS-eP_WylqceEDeFoktS7JzO0,9100
|
|
106
|
+
pytrilogy-0.0.3.46.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
107
|
+
pytrilogy-0.0.3.46.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
|
|
108
|
+
pytrilogy-0.0.3.46.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
|
|
109
|
+
pytrilogy-0.0.3.46.dist-info/RECORD,,
|
trilogy/__init__.py
CHANGED
trilogy/core/models/author.py
CHANGED
|
@@ -1906,7 +1906,7 @@ class AggregateWrapper(Mergeable, DataTyped, ConceptArgs, Namespaced, BaseModel)
|
|
|
1906
1906
|
|
|
1907
1907
|
|
|
1908
1908
|
class FilterItem(DataTyped, Namespaced, ConceptArgs, BaseModel):
|
|
1909
|
-
content:
|
|
1909
|
+
content: FuncArgs
|
|
1910
1910
|
where: "WhereClause"
|
|
1911
1911
|
|
|
1912
1912
|
@field_validator("content", mode="before")
|
|
@@ -748,6 +748,7 @@ def search_concepts(
|
|
|
748
748
|
accept_partial: bool = False,
|
|
749
749
|
conditions: BuildWhereClause | None = None,
|
|
750
750
|
) -> StrategyNode | None:
|
|
751
|
+
logger.error(f"starting search for {mandatory_list}")
|
|
751
752
|
hist = history.get_history(
|
|
752
753
|
search=mandatory_list, accept_partial=accept_partial, conditions=conditions
|
|
753
754
|
)
|
|
@@ -1094,6 +1095,7 @@ def _search_concepts(
|
|
|
1094
1095
|
logger.error(
|
|
1095
1096
|
f"{depth_to_prefix(depth)}{LOGGER_PREFIX} Could not resolve concepts {[c.address for c in mandatory_list]}, network outcome was {complete}, missing {all_mandatory - found},"
|
|
1096
1097
|
)
|
|
1098
|
+
|
|
1097
1099
|
return None
|
|
1098
1100
|
|
|
1099
1101
|
|
|
@@ -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,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from pydantic import BaseModel, ConfigDict, Field
|
|
2
2
|
|
|
3
|
+
from trilogy.core.exceptions import UnresolvableQueryException
|
|
3
4
|
from trilogy.core.models.build import BuildConcept, BuildWhereClause
|
|
4
5
|
from trilogy.core.models.build_environment import BuildEnvironment
|
|
5
6
|
from trilogy.core.models.environment import Environment
|
|
@@ -18,7 +19,7 @@ class History(BaseModel):
|
|
|
18
19
|
base_environment: Environment
|
|
19
20
|
history: dict[str, StrategyNode | None] = Field(default_factory=dict)
|
|
20
21
|
select_history: dict[str, StrategyNode | None] = Field(default_factory=dict)
|
|
21
|
-
started:
|
|
22
|
+
started: dict[str, int] = Field(default_factory=dict)
|
|
22
23
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
23
24
|
|
|
24
25
|
def _concepts_to_lookup(
|
|
@@ -27,13 +28,10 @@ class History(BaseModel):
|
|
|
27
28
|
accept_partial: bool,
|
|
28
29
|
conditions: BuildWhereClause | None = None,
|
|
29
30
|
) -> str:
|
|
31
|
+
base = sorted([c.address for c in search])
|
|
30
32
|
if conditions:
|
|
31
|
-
return (
|
|
32
|
-
|
|
33
|
-
+ str(accept_partial)
|
|
34
|
-
+ str(conditions)
|
|
35
|
-
)
|
|
36
|
-
return "-".join([c.address for c in search]) + str(accept_partial)
|
|
33
|
+
return "-".join(base) + str(accept_partial) + str(conditions)
|
|
34
|
+
return "-".join(base) + str(accept_partial)
|
|
37
35
|
|
|
38
36
|
def search_to_history(
|
|
39
37
|
self,
|
|
@@ -80,13 +78,19 @@ class History(BaseModel):
|
|
|
80
78
|
accept_partial: bool = False,
|
|
81
79
|
conditions: BuildWhereClause | None = None,
|
|
82
80
|
):
|
|
83
|
-
self.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
conditions=conditions,
|
|
88
|
-
)
|
|
81
|
+
key = self._concepts_to_lookup(
|
|
82
|
+
search,
|
|
83
|
+
accept_partial=accept_partial,
|
|
84
|
+
conditions=conditions,
|
|
89
85
|
)
|
|
86
|
+
if key in self.started:
|
|
87
|
+
self.started[key] += 1
|
|
88
|
+
else:
|
|
89
|
+
self.started[key] = 1
|
|
90
|
+
if self.started[key] > 5:
|
|
91
|
+
raise UnresolvableQueryException(
|
|
92
|
+
f"Was unable to resolve datasources to serve this query from model; unresolvable set was {search}. You may be querying unrelated concepts."
|
|
93
|
+
)
|
|
90
94
|
|
|
91
95
|
def log_end(
|
|
92
96
|
self,
|
|
@@ -94,13 +98,13 @@ class History(BaseModel):
|
|
|
94
98
|
accept_partial: bool = False,
|
|
95
99
|
conditions: BuildWhereClause | None = None,
|
|
96
100
|
):
|
|
97
|
-
self.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
conditions=conditions,
|
|
102
|
-
)
|
|
101
|
+
key = self._concepts_to_lookup(
|
|
102
|
+
search,
|
|
103
|
+
accept_partial=accept_partial,
|
|
104
|
+
conditions=conditions,
|
|
103
105
|
)
|
|
106
|
+
if key in self.started:
|
|
107
|
+
del self.started[key]
|
|
104
108
|
|
|
105
109
|
def check_started(
|
|
106
110
|
self,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|