pytrilogy 0.0.3.60__py3-none-any.whl → 0.0.3.61__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.60.dist-info → pytrilogy-0.0.3.61.dist-info}/METADATA +1 -1
- {pytrilogy-0.0.3.60.dist-info → pytrilogy-0.0.3.61.dist-info}/RECORD +21 -21
- trilogy/__init__.py +1 -1
- trilogy/core/enums.py +1 -0
- trilogy/core/models/build.py +1 -1
- trilogy/core/models/core.py +5 -1
- trilogy/core/models/environment.py +3 -1
- trilogy/core/optimization.py +1 -1
- trilogy/core/processing/node_generators/basic_node.py +12 -1
- trilogy/core/processing/node_generators/synonym_node.py +0 -1
- trilogy/core/processing/node_generators/unnest_node.py +1 -1
- trilogy/dialect/base.py +7 -5
- trilogy/dialect/common.py +3 -1
- trilogy/dialect/presto.py +8 -2
- trilogy/parsing/parse_engine.py +34 -6
- trilogy/parsing/render.py +12 -0
- trilogy/parsing/trilogy.lark +2 -2
- {pytrilogy-0.0.3.60.dist-info → pytrilogy-0.0.3.61.dist-info}/WHEEL +0 -0
- {pytrilogy-0.0.3.60.dist-info → pytrilogy-0.0.3.61.dist-info}/entry_points.txt +0 -0
- {pytrilogy-0.0.3.60.dist-info → pytrilogy-0.0.3.61.dist-info}/licenses/LICENSE.md +0 -0
- {pytrilogy-0.0.3.60.dist-info → pytrilogy-0.0.3.61.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.61.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
|
|
2
|
+
trilogy/__init__.py,sha256=6pE1HEb6lBSW2ODExpQU2E4nDuvhlPqat8goqgVFph4,303
|
|
3
3
|
trilogy/compiler.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
trilogy/constants.py,sha256=lv_aJWP6dn6e2aF4BAE72jbnNtceFddfqtiDSsvzno0,1692
|
|
5
5
|
trilogy/engine.py,sha256=OK2RuqCIUId6yZ5hfF8J1nxGP0AJqHRZiafcowmW0xc,1728
|
|
@@ -11,7 +11,7 @@ trilogy/utility.py,sha256=euQccZLKoYBz0LNg5tzLlvv2YHvXh9HArnYp1V3uXsM,763
|
|
|
11
11
|
trilogy/authoring/__init__.py,sha256=h-Ag7vT76tsjib9BfjOgI-yVpuJDgpn2TSps-ibRAj8,2593
|
|
12
12
|
trilogy/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
trilogy/core/constants.py,sha256=nizWYDCJQ1bigQMtkNIEMNTcN0NoEAXiIHLzpelxQ24,201
|
|
14
|
-
trilogy/core/enums.py,sha256=
|
|
14
|
+
trilogy/core/enums.py,sha256=2sgoVzHQpscIx_WUqJMH0oGxtcg41gN0l1qkRjzK2iI,7803
|
|
15
15
|
trilogy/core/env_processor.py,sha256=pFsxnluKIusGKx1z7tTnfsd_xZcPy9pZDungkjkyvI0,3170
|
|
16
16
|
trilogy/core/environment_helpers.py,sha256=VvPIiFemqaLLpIpLIqprfu63K7muZ1YzNg7UZIUph8w,8267
|
|
17
17
|
trilogy/core/ergonomics.py,sha256=e-7gE29vPLFdg0_A1smQ7eOrUwKl5VYdxRSTddHweRA,1631
|
|
@@ -19,16 +19,16 @@ trilogy/core/exceptions.py,sha256=JPYyBcit3T_pRtlHdtKSeVJkIyWUTozW2aaut25A2xI,67
|
|
|
19
19
|
trilogy/core/functions.py,sha256=poVfAwet1xdxTkC7WL38UmGRDpUVO9iSMNWSagl9_r4,29302
|
|
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=ojpn-p79lr03SSVQbbw74iPCyoYpDYBmj1dbZ3oXCjI,8860
|
|
23
23
|
trilogy/core/query_processor.py,sha256=QiE_w5HgheT4GLZFnaLssJ4plf4voK0TeTd6N3jhR6A,20188
|
|
24
24
|
trilogy/core/utility.py,sha256=3VC13uSQWcZNghgt7Ot0ZTeEmNqs__cx122abVq9qhM,410
|
|
25
25
|
trilogy/core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
26
|
trilogy/core/models/author.py,sha256=8XbIsQr6cQrgo9uzee5qRoYiMdEG7yKF4FiiWImW7U0,77490
|
|
27
|
-
trilogy/core/models/build.py,sha256=
|
|
27
|
+
trilogy/core/models/build.py,sha256=VAJpmk3GQCeJHpgjbFYHDXnFZlSD89sb0RvtIsZ58JE,63129
|
|
28
28
|
trilogy/core/models/build_environment.py,sha256=s_C9xAHuD3yZ26T15pWVBvoqvlp2LdZ8yjsv2_HdXLk,5363
|
|
29
|
-
trilogy/core/models/core.py,sha256=
|
|
29
|
+
trilogy/core/models/core.py,sha256=EMAuWTngoNVGCdfNrAY7_k6g528iodNQLwPRVip-8DA,10980
|
|
30
30
|
trilogy/core/models/datasource.py,sha256=6RjJUd2u4nYmEwFBpJlM9LbHVYDv8iHJxqiBMZqUrwI,9422
|
|
31
|
-
trilogy/core/models/environment.py,sha256=
|
|
31
|
+
trilogy/core/models/environment.py,sha256=tM8SwH9r1ZSc-F0Enod7r1NuqzGpQfLcPxnrtK5Hqpk,27398
|
|
32
32
|
trilogy/core/models/execute.py,sha256=hOilC-lka4W-C8Pakb0Vd1-T0oskeWdC8Ls0bm8_388,43109
|
|
33
33
|
trilogy/core/optimizations/__init__.py,sha256=YH2-mGXZnVDnBcWVi8vTbrdw7Qs5TivG4h38rH3js_I,290
|
|
34
34
|
trilogy/core/optimizations/base_optimization.py,sha256=gzDOKImoFn36k7XBD3ysEYDnbnb6vdVIztUfFQZsGnM,513
|
|
@@ -43,7 +43,7 @@ trilogy/core/processing/discovery_validation.py,sha256=Ek9jviFgimLMUMYLXBChUQmOD
|
|
|
43
43
|
trilogy/core/processing/graph_utils.py,sha256=8QUVrkE9j-9C1AyrCb1nQEh8daCe0u1HuXl-Te85lag,1205
|
|
44
44
|
trilogy/core/processing/utility.py,sha256=mrfR9pgek-xjxoDQSlvPqOW9dpmREjgzqn4AGoqpGeM,22774
|
|
45
45
|
trilogy/core/processing/node_generators/__init__.py,sha256=w8TQQgNhyAra6JQHdg1_Ags4BGyxjXYruu6UeC5yOkI,873
|
|
46
|
-
trilogy/core/processing/node_generators/basic_node.py,sha256=
|
|
46
|
+
trilogy/core/processing/node_generators/basic_node.py,sha256=8NtHZ99mJhJwDIib3xlcrn7oWmE42HHKuBpnwXIzpyo,4861
|
|
47
47
|
trilogy/core/processing/node_generators/common.py,sha256=PdysdroW9DUADP7f5Wv_GKPUyCTROZV1g3L45fawxi8,9443
|
|
48
48
|
trilogy/core/processing/node_generators/filter_node.py,sha256=0hdfiS2I-Jvr6P-il3jnAJK-g-DMG7_cFbZGCnLnJAo,10032
|
|
49
49
|
trilogy/core/processing/node_generators/group_node.py,sha256=nIfiMrJQEksUfqAeeA3X5PS1343y4lmPTipYuCa-rvs,6141
|
|
@@ -54,9 +54,9 @@ trilogy/core/processing/node_generators/recursive_node.py,sha256=l5zdh0dURKwmAy8
|
|
|
54
54
|
trilogy/core/processing/node_generators/rowset_node.py,sha256=2BiSsegbRF9csJ_Xl8P_CxIm4dAAb7dF29u6v_Odr-A,6709
|
|
55
55
|
trilogy/core/processing/node_generators/select_merge_node.py,sha256=lxXhMhDKGbu67QFNbbAT-BO8gbWppIvjn_hAXpLEPe0,19953
|
|
56
56
|
trilogy/core/processing/node_generators/select_node.py,sha256=3dvw0d53eUtCRCUPN6J48I3qBEX1Wha7saQ_ndPu6_I,1777
|
|
57
|
-
trilogy/core/processing/node_generators/synonym_node.py,sha256=
|
|
57
|
+
trilogy/core/processing/node_generators/synonym_node.py,sha256=BNfdwTunCerIzm7YLISI_XcfxxUzWLrZrRvZvayScSk,2257
|
|
58
58
|
trilogy/core/processing/node_generators/union_node.py,sha256=VNo6Oey4p8etU9xrOh2oTT2lIOTvY6PULUPRvVa2uxU,2877
|
|
59
|
-
trilogy/core/processing/node_generators/unnest_node.py,sha256=
|
|
59
|
+
trilogy/core/processing/node_generators/unnest_node.py,sha256=ueOQtoTf2iJHO09RzWHDFQ5iKZq2fVhGf2KAF2U2kU8,2677
|
|
60
60
|
trilogy/core/processing/node_generators/window_node.py,sha256=GP3Hvkbb0TDA6ef7W7bmvQEHVH-NRIfBT_0W4fcH3g4,6529
|
|
61
61
|
trilogy/core/processing/node_generators/select_helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
62
62
|
trilogy/core/processing/node_generators/select_helpers/datasource_injection.py,sha256=GMW07bb6hXurhF0hZLYoMAKSIS65tat5hwBjvqqPeSA,6516
|
|
@@ -76,15 +76,15 @@ trilogy/core/statements/build.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
|
|
|
76
76
|
trilogy/core/statements/common.py,sha256=KxEmz2ySySyZ6CTPzn0fJl5NX2KOk1RPyuUSwWhnK1g,759
|
|
77
77
|
trilogy/core/statements/execute.py,sha256=rqfuoMuXPcH7L7TmE1dSiZ_K_A1ohB8whVMfGimZBOk,1294
|
|
78
78
|
trilogy/dialect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
79
|
-
trilogy/dialect/base.py,sha256=
|
|
79
|
+
trilogy/dialect/base.py,sha256=CVOkIm3pwcuWlPGRqiimXjoKfns-2dAYlGsMCHGuzY4,43036
|
|
80
80
|
trilogy/dialect/bigquery.py,sha256=6ghCqy-k7UioIJc1EEQ7gRo_PHaO8Vm7yYbiQ-kgpzs,3629
|
|
81
|
-
trilogy/dialect/common.py,sha256=
|
|
81
|
+
trilogy/dialect/common.py,sha256=hhzuMTFW9QQIP7TKLT9BlJy6lw2R03a68jKQ-7t4-2c,6070
|
|
82
82
|
trilogy/dialect/config.py,sha256=olnyeVU5W5T6b9-dMeNAnvxuPlyc2uefb7FRME094Ec,3834
|
|
83
83
|
trilogy/dialect/dataframe.py,sha256=RUbNgReEa9g3pL6H7fP9lPTrAij5pkqedpZ99D8_5AE,1522
|
|
84
84
|
trilogy/dialect/duckdb.py,sha256=C5TovwacDXo9YDpMTpPxkH7D0AxQERa7JL1RUkDGVng,3898
|
|
85
85
|
trilogy/dialect/enums.py,sha256=FRNYQ5-w-B6-X0yXKNU5g9GowsMlERFogTC5u2nxL_s,4740
|
|
86
86
|
trilogy/dialect/postgres.py,sha256=VH4EB4myjIeZTHeFU6vK00GxY9c53rCBjg2mLbdaCEE,3254
|
|
87
|
-
trilogy/dialect/presto.py,sha256=
|
|
87
|
+
trilogy/dialect/presto.py,sha256=Wd0yHq3EOSfCOy7lWPfCr13JHO3olsm8qUXgml-oTm0,3529
|
|
88
88
|
trilogy/dialect/snowflake.py,sha256=LQIcHuyuGZXbxrv6sH17aLXLzw7yFVuRoE9M4doNk5k,3187
|
|
89
89
|
trilogy/dialect/sql_server.py,sha256=z2Vg7Qvw83rbGiEFIvHHLqVWJTWiz2xs76kpQj4HdTU,3131
|
|
90
90
|
trilogy/hooks/__init__.py,sha256=T3SF3phuUDPLXKGRVE_Lf9mzuwoXWyaLolncR_1kY30,144
|
|
@@ -97,9 +97,9 @@ trilogy/parsing/common.py,sha256=OOAssbo6Yp3L4u2OSGUYIuC_iAG_843vLpUtLkk1ub8,299
|
|
|
97
97
|
trilogy/parsing/config.py,sha256=Z-DaefdKhPDmSXLgg5V4pebhSB0h590vI0_VtHnlukI,111
|
|
98
98
|
trilogy/parsing/exceptions.py,sha256=Xwwsv2C9kSNv2q-HrrKC1f60JNHShXcCMzstTSEbiCw,154
|
|
99
99
|
trilogy/parsing/helpers.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
100
|
-
trilogy/parsing/parse_engine.py,sha256=
|
|
101
|
-
trilogy/parsing/render.py,sha256=
|
|
102
|
-
trilogy/parsing/trilogy.lark,sha256=
|
|
100
|
+
trilogy/parsing/parse_engine.py,sha256=O7aM5nZ4SjKlqO2x8XWefI1BMCW06jYYLhABU4k1HCI,72430
|
|
101
|
+
trilogy/parsing/render.py,sha256=xUhG0gw4atYFO79kKL_U5UkHMma-oorN5vjPJ5zTBdU,19383
|
|
102
|
+
trilogy/parsing/trilogy.lark,sha256=x9D1BXtE1E9Kxatx5Kt7xCaid8zgedabwca_B7j7L7o,14331
|
|
103
103
|
trilogy/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
104
104
|
trilogy/scripts/trilogy.py,sha256=1L0XrH4mVHRt1C9T1HnaDv2_kYEfbWTb5_-cBBke79w,3774
|
|
105
105
|
trilogy/std/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -110,8 +110,8 @@ trilogy/std/money.preql,sha256=XWwvAV3WxBsHX9zfptoYRnBigcfYwrYtBHXTME0xJuQ,2082
|
|
|
110
110
|
trilogy/std/net.preql,sha256=-bMV6dyofskl4Kvows-iQ4JCxjVUwsZOeWCy8JO5Ftw,135
|
|
111
111
|
trilogy/std/ranking.preql,sha256=LDoZrYyz4g3xsII9XwXfmstZD-_92i1Eox1UqkBIfi8,83
|
|
112
112
|
trilogy/std/report.preql,sha256=LbV-XlHdfw0jgnQ8pV7acG95xrd1-p65fVpiIc-S7W4,202
|
|
113
|
-
pytrilogy-0.0.3.
|
|
114
|
-
pytrilogy-0.0.3.
|
|
115
|
-
pytrilogy-0.0.3.
|
|
116
|
-
pytrilogy-0.0.3.
|
|
117
|
-
pytrilogy-0.0.3.
|
|
113
|
+
pytrilogy-0.0.3.61.dist-info/METADATA,sha256=rXq2NHO2bCO_JhPw5mu8Xj2lEOHcnX73fENl0m7-P2s,9095
|
|
114
|
+
pytrilogy-0.0.3.61.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
115
|
+
pytrilogy-0.0.3.61.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
|
|
116
|
+
pytrilogy-0.0.3.61.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
|
|
117
|
+
pytrilogy-0.0.3.61.dist-info/RECORD,,
|
trilogy/__init__.py
CHANGED
trilogy/core/enums.py
CHANGED
trilogy/core/models/build.py
CHANGED
|
@@ -131,7 +131,7 @@ def concept_is_relevant(
|
|
|
131
131
|
if (
|
|
132
132
|
concept.purpose == Purpose.KEY
|
|
133
133
|
and concept.keys
|
|
134
|
-
and all([c in others for c in concept.keys])
|
|
134
|
+
and all([c in others and c != concept.address for c in concept.keys])
|
|
135
135
|
):
|
|
136
136
|
return False
|
|
137
137
|
if concept.purpose in (Purpose.METRIC,):
|
trilogy/core/models/core.py
CHANGED
|
@@ -175,13 +175,17 @@ class ListType(BaseModel):
|
|
|
175
175
|
|
|
176
176
|
|
|
177
177
|
class MapType(BaseModel):
|
|
178
|
-
key_type:
|
|
178
|
+
key_type: TYPEDEF_TYPES
|
|
179
179
|
value_type: TYPEDEF_TYPES
|
|
180
180
|
|
|
181
181
|
@field_validator("value_type", mode="plain")
|
|
182
182
|
def validate_type(cls, v):
|
|
183
183
|
return v
|
|
184
184
|
|
|
185
|
+
@field_validator("key_type", mode="plain")
|
|
186
|
+
def validate_key_type(cls, v):
|
|
187
|
+
return v
|
|
188
|
+
|
|
185
189
|
@property
|
|
186
190
|
def data_type(self):
|
|
187
191
|
return DataType.MAP
|
|
@@ -58,7 +58,9 @@ if TYPE_CHECKING:
|
|
|
58
58
|
class Import:
|
|
59
59
|
alias: str
|
|
60
60
|
path: Path
|
|
61
|
-
input_path:
|
|
61
|
+
input_path: Path | None = (
|
|
62
|
+
None # filepath where the text came from (path is the import path, but may be resolved from a dictionary for some resolvers)
|
|
63
|
+
)
|
|
62
64
|
|
|
63
65
|
|
|
64
66
|
class BaseImportResolver(BaseModel):
|
trilogy/core/optimization.py
CHANGED
|
@@ -21,6 +21,8 @@ def is_equivalent_basic_function_lineage(
|
|
|
21
21
|
y.lineage, BuildFunction
|
|
22
22
|
):
|
|
23
23
|
return False
|
|
24
|
+
if x.lineage.operator == y.lineage.operator == FunctionType.ATTR_ACCESS:
|
|
25
|
+
return x.lineage.concept_arguments == y.lineage.concept_arguments
|
|
24
26
|
if x.lineage.operator == y.lineage.operator:
|
|
25
27
|
return True
|
|
26
28
|
if (
|
|
@@ -55,9 +57,14 @@ def gen_basic_node(
|
|
|
55
57
|
f"{depth_prefix}{LOGGER_PREFIX} checking for synonyms for attribute access"
|
|
56
58
|
)
|
|
57
59
|
for x in local_optional:
|
|
60
|
+
found = False
|
|
58
61
|
for z in x.pseudonyms:
|
|
62
|
+
# gate to ensure we don't match to multiple synonyms
|
|
63
|
+
if found:
|
|
64
|
+
continue
|
|
59
65
|
s_concept = environment.alias_origin_lookup[z]
|
|
60
66
|
if is_equivalent_basic_function_lineage(concept, s_concept):
|
|
67
|
+
found = True
|
|
61
68
|
synonyms.append(s_concept)
|
|
62
69
|
ignored_optional.add(x.address)
|
|
63
70
|
equivalent_optional = [
|
|
@@ -72,7 +79,11 @@ def gen_basic_node(
|
|
|
72
79
|
f"{depth_prefix}{LOGGER_PREFIX} basic node for {concept} has equivalent optional {[x.address for x in equivalent_optional]}"
|
|
73
80
|
)
|
|
74
81
|
for eo in equivalent_optional:
|
|
75
|
-
|
|
82
|
+
new_parents = resolve_function_parent_concepts(eo, environment=environment)
|
|
83
|
+
logger.info(
|
|
84
|
+
f"{depth_prefix}{LOGGER_PREFIX} equivalent optional {eo.address} has parents {[x.address for x in new_parents]}"
|
|
85
|
+
)
|
|
86
|
+
parent_concepts += new_parents
|
|
76
87
|
non_equivalent_optional = [
|
|
77
88
|
x
|
|
78
89
|
for x in local_optional
|
|
@@ -31,7 +31,7 @@ def gen_unnest_node(
|
|
|
31
31
|
]
|
|
32
32
|
all_parents = arguments + non_equivalent_optional
|
|
33
33
|
logger.info(
|
|
34
|
-
f"{depth_prefix}{LOGGER_PREFIX} unnest node for {concept} with lineage {concept.lineage} has parents {all_parents} and equivalent optional {equivalent_optional}"
|
|
34
|
+
f"{depth_prefix}{LOGGER_PREFIX} unnest node for {concept} with lineage {concept.lineage} has parents + optional {all_parents} and equivalent optional {equivalent_optional}"
|
|
35
35
|
)
|
|
36
36
|
if arguments or local_optional:
|
|
37
37
|
parent = source_concepts(
|
trilogy/dialect/base.py
CHANGED
|
@@ -757,7 +757,7 @@ class BaseDialect:
|
|
|
757
757
|
f"{self.QUOTE_CHARACTER}{c.safe_address}{self.QUOTE_CHARACTER}"
|
|
758
758
|
for c in cte.join_derived_concepts
|
|
759
759
|
]
|
|
760
|
-
elif self.UNNEST_MODE
|
|
760
|
+
elif self.UNNEST_MODE in (UnnestMode.CROSS_JOIN_UNNEST, UnnestMode.PRESTO):
|
|
761
761
|
select_columns = [
|
|
762
762
|
self.render_concept_sql(c, cte)
|
|
763
763
|
for c in cte.output_columns
|
|
@@ -787,12 +787,14 @@ class BaseDialect:
|
|
|
787
787
|
):
|
|
788
788
|
|
|
789
789
|
source = f"{render_unnest(self.UNNEST_MODE, self.QUOTE_CHARACTER, cte.join_derived_concepts[0], self.render_expr, cte)}"
|
|
790
|
-
elif (
|
|
791
|
-
|
|
792
|
-
and self.UNNEST_MODE == UnnestMode.CROSS_JOIN_UNNEST
|
|
790
|
+
elif cte.join_derived_concepts and self.UNNEST_MODE in (
|
|
791
|
+
UnnestMode.CROSS_JOIN_UNNEST,
|
|
793
792
|
):
|
|
794
793
|
source = f"{self.render_expr(cte.join_derived_concepts[0], cte)} as {self.QUOTE_CHARACTER}{UNNEST_NAME}{self.QUOTE_CHARACTER}"
|
|
795
|
-
|
|
794
|
+
elif cte.join_derived_concepts and self.UNNEST_MODE in (
|
|
795
|
+
UnnestMode.PRESTO,
|
|
796
|
+
):
|
|
797
|
+
source = f"{self.render_expr(cte.join_derived_concepts[0], cte)} as t({self.QUOTE_CHARACTER}{UNNEST_NAME}{self.QUOTE_CHARACTER})"
|
|
796
798
|
elif (
|
|
797
799
|
cte.join_derived_concepts
|
|
798
800
|
and self.UNNEST_MODE == UnnestMode.SNOWFLAKE
|
trilogy/dialect/common.py
CHANGED
|
@@ -35,7 +35,6 @@ def render_unnest(
|
|
|
35
35
|
cte: CTE,
|
|
36
36
|
):
|
|
37
37
|
if not isinstance(concept, (BuildConcept, BuildParamaterizedConceptReference)):
|
|
38
|
-
print(type(concept))
|
|
39
38
|
address = UNNEST_NAME
|
|
40
39
|
else:
|
|
41
40
|
address = concept.safe_address
|
|
@@ -43,6 +42,8 @@ def render_unnest(
|
|
|
43
42
|
return f"{render_func(concept, cte)} as {quote_character}{address}{quote_character}"
|
|
44
43
|
elif unnest_mode == UnnestMode.CROSS_JOIN_UNNEST:
|
|
45
44
|
return f"unnest({render_func(concept, cte)}) as {quote_character}{address}{quote_character}"
|
|
45
|
+
elif unnest_mode == UnnestMode.PRESTO:
|
|
46
|
+
return f"unnest({render_func(concept, cte)}) as t({quote_character}{UNNEST_NAME}{quote_character})"
|
|
46
47
|
elif unnest_mode == UnnestMode.CROSS_JOIN_ALIAS:
|
|
47
48
|
return f"{render_func(concept, cte)} as unnest_wrapper ({quote_character}{address}{quote_character})"
|
|
48
49
|
elif unnest_mode == UnnestMode.SNOWFLAKE:
|
|
@@ -103,6 +104,7 @@ def render_join(
|
|
|
103
104
|
UnnestMode.CROSS_JOIN,
|
|
104
105
|
UnnestMode.CROSS_JOIN_UNNEST,
|
|
105
106
|
UnnestMode.CROSS_JOIN_ALIAS,
|
|
107
|
+
UnnestMode.PRESTO,
|
|
106
108
|
):
|
|
107
109
|
return f"CROSS JOIN {render_unnest(unnest_mode, quote_character, join.object_to_unnest, render_expr_func, cte)}"
|
|
108
110
|
if unnest_mode == UnnestMode.SNOWFLAKE:
|
trilogy/dialect/presto.py
CHANGED
|
@@ -33,6 +33,8 @@ FUNCTION_MAP = {
|
|
|
33
33
|
FunctionType.CURRENT_DATE: lambda x: "CURRENT_DATE",
|
|
34
34
|
FunctionType.CURRENT_DATETIME: lambda x: "CURRENT_TIMESTAMP",
|
|
35
35
|
FunctionType.ARRAY: lambda x: f"ARRAY[{', '.join(x)}]",
|
|
36
|
+
# regex
|
|
37
|
+
FunctionType.REGEXP_CONTAINS: lambda x: f"REGEXP_LIKE({x[0]}, {x[1]})",
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
FUNCTION_GRAIN_MATCH_MAP = {
|
|
@@ -85,8 +87,12 @@ class PrestoDialect(BaseDialect):
|
|
|
85
87
|
}
|
|
86
88
|
QUOTE_CHARACTER = '"'
|
|
87
89
|
SQL_TEMPLATE = SQL_TEMPLATE
|
|
88
|
-
DATATYPE_MAP = {
|
|
89
|
-
|
|
90
|
+
DATATYPE_MAP = {
|
|
91
|
+
**BaseDialect.DATATYPE_MAP,
|
|
92
|
+
DataType.NUMERIC: "DECIMAL",
|
|
93
|
+
DataType.STRING: "VARCHAR",
|
|
94
|
+
}
|
|
95
|
+
UNNEST_MODE = UnnestMode.PRESTO
|
|
90
96
|
|
|
91
97
|
|
|
92
98
|
class TrinoDialect(PrestoDialect):
|
trilogy/parsing/parse_engine.py
CHANGED
|
@@ -460,13 +460,22 @@ class ParseToObjects(Transformer):
|
|
|
460
460
|
)
|
|
461
461
|
|
|
462
462
|
def list_type(self, args) -> ListType:
|
|
463
|
-
|
|
463
|
+
content = args[0]
|
|
464
|
+
if isinstance(content, str):
|
|
465
|
+
content = self.environment.concepts[content]
|
|
466
|
+
return ListType(type=content)
|
|
464
467
|
|
|
465
468
|
def numeric_type(self, args) -> NumericType:
|
|
466
469
|
return NumericType(precision=args[0], scale=args[1])
|
|
467
470
|
|
|
468
471
|
def map_type(self, args) -> MapType:
|
|
469
|
-
|
|
472
|
+
key = args[0]
|
|
473
|
+
value = args[1]
|
|
474
|
+
if isinstance(key, str):
|
|
475
|
+
key = self.environment.concepts[key]
|
|
476
|
+
elif isinstance(value, str):
|
|
477
|
+
value = self.environment.concepts[value]
|
|
478
|
+
return MapType(key_type=key, value_type=value)
|
|
470
479
|
|
|
471
480
|
@v_args(meta=True)
|
|
472
481
|
def data_type(
|
|
@@ -842,6 +851,17 @@ class ParseToObjects(Transformer):
|
|
|
842
851
|
continue
|
|
843
852
|
|
|
844
853
|
key_inputs = grain.components
|
|
854
|
+
eligible = True
|
|
855
|
+
for key in key_inputs:
|
|
856
|
+
# never overwrite a key with a dependency on a property
|
|
857
|
+
# for example - binding a datasource with a grain of <x>.fun should
|
|
858
|
+
# never override the grain of x to <fun>
|
|
859
|
+
if column.concept.address in (
|
|
860
|
+
self.environment.concepts[key].keys or set()
|
|
861
|
+
):
|
|
862
|
+
eligible = False
|
|
863
|
+
if not eligible:
|
|
864
|
+
continue
|
|
845
865
|
keys = [self.environment.concepts[grain] for grain in key_inputs]
|
|
846
866
|
# target_c.purpose = Purpose.PROPERTY
|
|
847
867
|
target_c.keys = set([x.address for x in keys])
|
|
@@ -1030,6 +1050,9 @@ class ParseToObjects(Transformer):
|
|
|
1030
1050
|
|
|
1031
1051
|
def import_statement(self, args: list[str]) -> ImportStatement:
|
|
1032
1052
|
start = datetime.now()
|
|
1053
|
+
is_file_resolver = isinstance(
|
|
1054
|
+
self.environment.config.import_resolver, FileSystemImportResolver
|
|
1055
|
+
)
|
|
1033
1056
|
if len(args) == 2:
|
|
1034
1057
|
alias = args[-1]
|
|
1035
1058
|
cache_key = args[-1]
|
|
@@ -1043,9 +1066,7 @@ class ParseToObjects(Transformer):
|
|
|
1043
1066
|
is_stdlib = True
|
|
1044
1067
|
target = join(STDLIB_ROOT, *path) + ".preql"
|
|
1045
1068
|
token_lookup: Path | str = Path(target)
|
|
1046
|
-
elif
|
|
1047
|
-
self.environment.config.import_resolver, FileSystemImportResolver
|
|
1048
|
-
):
|
|
1069
|
+
elif is_file_resolver:
|
|
1049
1070
|
target = join(self.environment.working_path, *path) + ".preql"
|
|
1050
1071
|
# tokens + text are cached by path
|
|
1051
1072
|
token_lookup = Path(target)
|
|
@@ -1125,7 +1146,13 @@ class ParseToObjects(Transformer):
|
|
|
1125
1146
|
imps = ImportStatement(alias=alias, input_path=input_path, path=parsed_path)
|
|
1126
1147
|
|
|
1127
1148
|
self.environment.add_import(
|
|
1128
|
-
alias,
|
|
1149
|
+
alias,
|
|
1150
|
+
new_env,
|
|
1151
|
+
Import(
|
|
1152
|
+
alias=alias,
|
|
1153
|
+
path=parsed_path,
|
|
1154
|
+
input_path=Path(target) if is_file_resolver else None,
|
|
1155
|
+
),
|
|
1129
1156
|
)
|
|
1130
1157
|
end = datetime.now()
|
|
1131
1158
|
perf_logger.debug(
|
|
@@ -1677,6 +1704,7 @@ class ParseToObjects(Transformer):
|
|
|
1677
1704
|
|
|
1678
1705
|
@v_args(meta=True)
|
|
1679
1706
|
def unnest(self, meta, args):
|
|
1707
|
+
|
|
1680
1708
|
return self.function_factory.create_function(args, FunctionType.UNNEST, meta)
|
|
1681
1709
|
|
|
1682
1710
|
@v_args(meta=True)
|
trilogy/parsing/render.py
CHANGED
|
@@ -31,6 +31,7 @@ from trilogy.core.models.core import (
|
|
|
31
31
|
DataType,
|
|
32
32
|
ListType,
|
|
33
33
|
ListWrapper,
|
|
34
|
+
MapWrapper,
|
|
34
35
|
NumericType,
|
|
35
36
|
TraitDataType,
|
|
36
37
|
TupleWrapper,
|
|
@@ -250,6 +251,17 @@ class Renderer:
|
|
|
250
251
|
def _(self, arg: TupleWrapper):
|
|
251
252
|
return "(" + ", ".join([self.to_string(x) for x in arg]) + ")"
|
|
252
253
|
|
|
254
|
+
@to_string.register
|
|
255
|
+
def _(self, arg: MapWrapper):
|
|
256
|
+
def process_key_value(key, value):
|
|
257
|
+
return f"{self.to_string(key)}: {self.to_string(value)}"
|
|
258
|
+
|
|
259
|
+
return (
|
|
260
|
+
"{"
|
|
261
|
+
+ ", ".join([process_key_value(key, value) for key, value in arg.items()])
|
|
262
|
+
+ "}"
|
|
263
|
+
)
|
|
264
|
+
|
|
253
265
|
@to_string.register
|
|
254
266
|
def _(self, arg: DatePart):
|
|
255
267
|
return arg.value
|
trilogy/parsing/trilogy.lark
CHANGED
|
@@ -402,11 +402,11 @@
|
|
|
402
402
|
|
|
403
403
|
struct_type: "struct"i "<" ((data_type | IDENTIFIER) ",")* (data_type | IDENTIFIER) ","? ">"
|
|
404
404
|
|
|
405
|
-
list_type: ("list"i
|
|
405
|
+
list_type: ("list"i | "array"i) "<" (data_type | IDENTIFIER) ">"
|
|
406
406
|
|
|
407
407
|
numeric_type: "numeric"i "(" int_lit "," int_lit ")"
|
|
408
408
|
|
|
409
|
-
map_type: "map"i "<" data_type "," data_type ">"
|
|
409
|
+
map_type: "map"i "<" (data_type | IDENTIFIER) "," (data_type | IDENTIFIER) ">"
|
|
410
410
|
|
|
411
411
|
!data_type: ("string"i | "number"i | "numeric"i | "map"i | "list"i | "array"i | "any"i | "int"i | "bigint"i | "date"i | "datetime"i | "timestamp"i | "float"i | "bool"i | numeric_type | map_type | struct_type | list_type) ("::" IDENTIFIER)?
|
|
412
412
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|