pytrilogy 0.0.1.103__py3-none-any.whl → 0.0.1.105__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.1.103.dist-info → pytrilogy-0.0.1.105.dist-info}/METADATA +1 -1
- {pytrilogy-0.0.1.103.dist-info → pytrilogy-0.0.1.105.dist-info}/RECORD +18 -18
- {pytrilogy-0.0.1.103.dist-info → pytrilogy-0.0.1.105.dist-info}/WHEEL +1 -1
- trilogy/__init__.py +1 -1
- trilogy/core/models.py +176 -45
- trilogy/core/processing/concept_strategies_v3.py +6 -3
- trilogy/core/processing/node_generators/common.py +19 -7
- trilogy/core/processing/node_generators/filter_node.py +39 -10
- trilogy/core/processing/node_generators/merge_node.py +11 -1
- trilogy/core/processing/node_generators/select_node.py +275 -53
- trilogy/core/processing/nodes/__init__.py +54 -1
- trilogy/dialect/base.py +12 -3
- trilogy/parsing/common.py +30 -0
- trilogy/parsing/parse_engine.py +65 -94
- trilogy/parsing/render.py +0 -122
- {pytrilogy-0.0.1.103.dist-info → pytrilogy-0.0.1.105.dist-info}/LICENSE.md +0 -0
- {pytrilogy-0.0.1.103.dist-info → pytrilogy-0.0.1.105.dist-info}/entry_points.txt +0 -0
- {pytrilogy-0.0.1.103.dist-info → pytrilogy-0.0.1.105.dist-info}/top_level.txt +0 -0
trilogy/parsing/parse_engine.py
CHANGED
|
@@ -9,6 +9,7 @@ from lark.exceptions import (
|
|
|
9
9
|
UnexpectedToken,
|
|
10
10
|
VisitError,
|
|
11
11
|
)
|
|
12
|
+
from pathlib import Path
|
|
12
13
|
from lark.tree import Meta
|
|
13
14
|
from pydantic import ValidationError
|
|
14
15
|
from trilogy.core.internal import INTERNAL_NAMESPACE, ALL_ROWS_CONCEPT
|
|
@@ -16,6 +17,7 @@ from trilogy.constants import (
|
|
|
16
17
|
DEFAULT_NAMESPACE,
|
|
17
18
|
NULL_VALUE,
|
|
18
19
|
VIRTUAL_CONCEPT_PREFIX,
|
|
20
|
+
MagicConstants,
|
|
19
21
|
)
|
|
20
22
|
from trilogy.core.enums import (
|
|
21
23
|
BooleanOperator,
|
|
@@ -61,6 +63,7 @@ from trilogy.core.models import (
|
|
|
61
63
|
ColumnAssignment,
|
|
62
64
|
Comment,
|
|
63
65
|
Comparison,
|
|
66
|
+
SubselectComparison,
|
|
64
67
|
Concept,
|
|
65
68
|
ConceptTransform,
|
|
66
69
|
Conditional,
|
|
@@ -107,6 +110,7 @@ from trilogy.parsing.common import (
|
|
|
107
110
|
function_to_concept,
|
|
108
111
|
filter_item_to_concept,
|
|
109
112
|
constant_to_concept,
|
|
113
|
+
arbitrary_to_concept,
|
|
110
114
|
)
|
|
111
115
|
|
|
112
116
|
CONSTANT_TYPES = (int, float, str, bool, ListWrapper)
|
|
@@ -186,9 +190,9 @@ grammar = r"""
|
|
|
186
190
|
|
|
187
191
|
// FUNCTION blocks
|
|
188
192
|
function: raw_function
|
|
189
|
-
function_binding_item: IDENTIFIER data_type
|
|
193
|
+
function_binding_item: IDENTIFIER ":" data_type
|
|
190
194
|
function_binding_list: (function_binding_item ",")* function_binding_item ","?
|
|
191
|
-
raw_function: "
|
|
195
|
+
raw_function: "bind" "sql" IDENTIFIER "(" function_binding_list ")" "-" ">" data_type "as"i MULTILINE_STRING
|
|
192
196
|
|
|
193
197
|
|
|
194
198
|
// user_id where state = Mexico
|
|
@@ -245,7 +249,9 @@ grammar = r"""
|
|
|
245
249
|
|
|
246
250
|
COMPARISON_OPERATOR: (/is[\s]+not/ | "is" |"=" | ">" | "<" | ">=" | "<=" | "!=" )
|
|
247
251
|
|
|
248
|
-
comparison: (expr COMPARISON_OPERATOR expr) | (expr array_comparison expr_tuple)
|
|
252
|
+
comparison: (expr COMPARISON_OPERATOR expr) | (expr array_comparison expr_tuple)
|
|
253
|
+
|
|
254
|
+
subselect_comparison: expr array_comparison expr
|
|
249
255
|
|
|
250
256
|
expr_tuple: "(" (expr ",")* expr ","? ")"
|
|
251
257
|
|
|
@@ -257,7 +263,7 @@ grammar = r"""
|
|
|
257
263
|
|
|
258
264
|
parenthetical: "(" (conditional | expr) ")"
|
|
259
265
|
|
|
260
|
-
expr: window_item | filter_item | comparison | fgroup | aggregate_functions | unnest | _string_functions | _math_functions | _generic_functions | _constant_functions| _date_functions | literal | expr_reference | index_access | attr_access | parenthetical
|
|
266
|
+
expr: window_item | filter_item | comparison | subselect_comparison | fgroup | aggregate_functions | unnest | _string_functions | _math_functions | _generic_functions | _constant_functions| _date_functions | literal | expr_reference | index_access | attr_access | parenthetical
|
|
261
267
|
|
|
262
268
|
// functions
|
|
263
269
|
|
|
@@ -466,25 +472,34 @@ class ParseToObjects(Transformer):
|
|
|
466
472
|
text,
|
|
467
473
|
environment: Environment,
|
|
468
474
|
parse_address: str | None = None,
|
|
469
|
-
parsed: dict | None = None,
|
|
475
|
+
parsed: dict[str, "ParseToObjects"] | None = None,
|
|
470
476
|
):
|
|
471
477
|
Transformer.__init__(self, visit_tokens)
|
|
472
478
|
self.text = text
|
|
473
479
|
self.environment: Environment = environment
|
|
474
|
-
self.imported: set[str] = set()
|
|
475
480
|
self.parse_address = parse_address or "root"
|
|
476
481
|
self.parsed: dict[str, ParseToObjects] = parsed if parsed else {}
|
|
477
482
|
# we do a second pass to pick up circular dependencies
|
|
478
483
|
# after initial parsing
|
|
479
484
|
self.pass_count = 1
|
|
485
|
+
self._results_stash = None
|
|
486
|
+
|
|
487
|
+
def transform(self, tree):
|
|
488
|
+
results = super().transform(tree)
|
|
489
|
+
self._results_stash = results
|
|
490
|
+
self.environment._parse_count += 1
|
|
491
|
+
return results
|
|
480
492
|
|
|
481
493
|
def hydrate_missing(self):
|
|
482
494
|
self.pass_count = 2
|
|
483
495
|
for k, v in self.parsed.items():
|
|
496
|
+
|
|
484
497
|
if v.pass_count == 2:
|
|
485
498
|
continue
|
|
486
499
|
v.hydrate_missing()
|
|
487
500
|
self.environment.concepts.fail_on_missing = True
|
|
501
|
+
# if not self.environment.concepts.undefined:
|
|
502
|
+
# return self._results_stash
|
|
488
503
|
reparsed = self.transform(PARSER.parse(self.text))
|
|
489
504
|
self.environment.concepts.undefined = {}
|
|
490
505
|
return reparsed
|
|
@@ -515,43 +530,11 @@ class ParseToObjects(Transformer):
|
|
|
515
530
|
concept.metadata.line_number = meta.line
|
|
516
531
|
self.environment.add_concept(concept, meta=meta)
|
|
517
532
|
final.append(concept)
|
|
518
|
-
elif isinstance(
|
|
533
|
+
elif isinstance(
|
|
534
|
+
arg, (FilterItem, WindowItem, AggregateWrapper, ListWrapper)
|
|
535
|
+
):
|
|
519
536
|
id_hash = string_to_hash(str(arg))
|
|
520
|
-
concept =
|
|
521
|
-
arg,
|
|
522
|
-
name=f"{VIRTUAL_CONCEPT_PREFIX}_{id_hash}",
|
|
523
|
-
namespace=self.environment.namespace,
|
|
524
|
-
)
|
|
525
|
-
if concept.metadata:
|
|
526
|
-
concept.metadata.line_number = meta.line
|
|
527
|
-
self.environment.add_concept(concept, meta=meta)
|
|
528
|
-
final.append(concept)
|
|
529
|
-
elif isinstance(arg, WindowItem):
|
|
530
|
-
id_hash = string_to_hash(str(arg))
|
|
531
|
-
concept = window_item_to_concept(
|
|
532
|
-
arg,
|
|
533
|
-
namespace=self.environment.namespace,
|
|
534
|
-
name=f"{VIRTUAL_CONCEPT_PREFIX}_{id_hash}",
|
|
535
|
-
)
|
|
536
|
-
if concept.metadata:
|
|
537
|
-
concept.metadata.line_number = meta.line
|
|
538
|
-
self.environment.add_concept(concept, meta=meta)
|
|
539
|
-
final.append(concept)
|
|
540
|
-
elif isinstance(arg, AggregateWrapper):
|
|
541
|
-
id_hash = string_to_hash(str(arg))
|
|
542
|
-
concept = agg_wrapper_to_concept(
|
|
543
|
-
arg,
|
|
544
|
-
namespace=self.environment.namespace,
|
|
545
|
-
name=f"{VIRTUAL_CONCEPT_PREFIX}_{id_hash}",
|
|
546
|
-
)
|
|
547
|
-
if concept.metadata:
|
|
548
|
-
concept.metadata.line_number = meta.line
|
|
549
|
-
self.environment.add_concept(concept, meta=meta)
|
|
550
|
-
final.append(concept)
|
|
551
|
-
# we don't need virtual types for most constants
|
|
552
|
-
elif isinstance(arg, (ListWrapper)):
|
|
553
|
-
id_hash = string_to_hash(str(arg))
|
|
554
|
-
concept = constant_to_concept(
|
|
537
|
+
concept = arbitrary_to_concept(
|
|
555
538
|
arg,
|
|
556
539
|
name=f"{VIRTUAL_CONCEPT_PREFIX}_{id_hash}",
|
|
557
540
|
namespace=self.environment.namespace,
|
|
@@ -560,6 +543,7 @@ class ParseToObjects(Transformer):
|
|
|
560
543
|
concept.metadata.line_number = meta.line
|
|
561
544
|
self.environment.add_concept(concept, meta=meta)
|
|
562
545
|
final.append(concept)
|
|
546
|
+
|
|
563
547
|
else:
|
|
564
548
|
final.append(arg)
|
|
565
549
|
return final
|
|
@@ -763,8 +747,10 @@ class ParseToObjects(Transformer):
|
|
|
763
747
|
while isinstance(source_value, Parenthetical):
|
|
764
748
|
source_value = source_value.content
|
|
765
749
|
|
|
766
|
-
if isinstance(
|
|
767
|
-
|
|
750
|
+
if isinstance(
|
|
751
|
+
source_value, (FilterItem, WindowItem, AggregateWrapper, Function)
|
|
752
|
+
):
|
|
753
|
+
concept = arbitrary_to_concept(
|
|
768
754
|
source_value,
|
|
769
755
|
name=name,
|
|
770
756
|
namespace=namespace,
|
|
@@ -772,31 +758,6 @@ class ParseToObjects(Transformer):
|
|
|
772
758
|
metadata=metadata,
|
|
773
759
|
)
|
|
774
760
|
|
|
775
|
-
if concept.metadata:
|
|
776
|
-
concept.metadata.line_number = meta.line
|
|
777
|
-
self.environment.add_concept(concept, meta=meta)
|
|
778
|
-
return ConceptDerivation(concept=concept)
|
|
779
|
-
elif isinstance(source_value, WindowItem):
|
|
780
|
-
|
|
781
|
-
concept = window_item_to_concept(
|
|
782
|
-
source_value,
|
|
783
|
-
name=name,
|
|
784
|
-
namespace=namespace,
|
|
785
|
-
purpose=purpose,
|
|
786
|
-
metadata=metadata,
|
|
787
|
-
)
|
|
788
|
-
if concept.metadata:
|
|
789
|
-
concept.metadata.line_number = meta.line
|
|
790
|
-
self.environment.add_concept(concept, meta=meta)
|
|
791
|
-
return ConceptDerivation(concept=concept)
|
|
792
|
-
elif isinstance(source_value, AggregateWrapper):
|
|
793
|
-
concept = agg_wrapper_to_concept(
|
|
794
|
-
source_value,
|
|
795
|
-
namespace=namespace,
|
|
796
|
-
name=name,
|
|
797
|
-
metadata=metadata,
|
|
798
|
-
purpose=purpose,
|
|
799
|
-
)
|
|
800
761
|
if concept.metadata:
|
|
801
762
|
concept.metadata.line_number = meta.line
|
|
802
763
|
self.environment.add_concept(concept, meta=meta)
|
|
@@ -814,19 +775,6 @@ class ParseToObjects(Transformer):
|
|
|
814
775
|
self.environment.add_concept(concept, meta=meta)
|
|
815
776
|
return ConceptDerivation(concept=concept)
|
|
816
777
|
|
|
817
|
-
elif isinstance(source_value, Function):
|
|
818
|
-
function: Function = source_value
|
|
819
|
-
|
|
820
|
-
concept = function_to_concept(
|
|
821
|
-
function,
|
|
822
|
-
name=name,
|
|
823
|
-
namespace=namespace,
|
|
824
|
-
)
|
|
825
|
-
if concept.metadata:
|
|
826
|
-
concept.metadata.line_number = meta.line
|
|
827
|
-
self.environment.add_concept(concept, meta=meta)
|
|
828
|
-
return ConceptDerivation(concept=concept)
|
|
829
|
-
|
|
830
778
|
raise SyntaxError(
|
|
831
779
|
f"Received invalid type {type(args[2])} {args[2]} as input to select"
|
|
832
780
|
" transform"
|
|
@@ -932,7 +880,7 @@ class ParseToObjects(Transformer):
|
|
|
932
880
|
)
|
|
933
881
|
for column in columns:
|
|
934
882
|
column.concept = column.concept.with_grain(datasource.grain)
|
|
935
|
-
self.environment.
|
|
883
|
+
self.environment.add_datasource(datasource, meta=meta)
|
|
936
884
|
return datasource
|
|
937
885
|
|
|
938
886
|
@v_args(meta=True)
|
|
@@ -1046,12 +994,11 @@ class ParseToObjects(Transformer):
|
|
|
1046
994
|
self.environment.add_concept(new, meta=meta)
|
|
1047
995
|
return merge
|
|
1048
996
|
|
|
1049
|
-
def import_statement(self, args: list[str]):
|
|
997
|
+
def import_statement(self, args: list[str]) -> ImportStatement:
|
|
1050
998
|
alias = args[-1]
|
|
1051
999
|
path = args[0].split(".")
|
|
1052
1000
|
|
|
1053
1001
|
target = join(self.environment.working_path, *path) + ".preql"
|
|
1054
|
-
self.imported.add(target)
|
|
1055
1002
|
if target in self.parsed:
|
|
1056
1003
|
nparser = self.parsed[target]
|
|
1057
1004
|
else:
|
|
@@ -1070,21 +1017,23 @@ class ParseToObjects(Transformer):
|
|
|
1070
1017
|
)
|
|
1071
1018
|
nparser.transform(PARSER.parse(text))
|
|
1072
1019
|
self.parsed[target] = nparser
|
|
1020
|
+
# add the parsed objects of the import in
|
|
1021
|
+
self.parsed = {**self.parsed, **nparser.parsed}
|
|
1073
1022
|
except Exception as e:
|
|
1074
1023
|
raise ImportError(
|
|
1075
1024
|
f"Unable to import file {dirname(target)}, parsing error: {e}"
|
|
1076
1025
|
)
|
|
1077
1026
|
|
|
1078
|
-
for
|
|
1079
|
-
# self.environment.concepts[f"{alias}.{key}"] = concept.with_namespace(new_namespace)
|
|
1027
|
+
for _, concept in nparser.environment.concepts.items():
|
|
1080
1028
|
self.environment.add_concept(concept.with_namespace(alias))
|
|
1081
1029
|
|
|
1082
|
-
for
|
|
1030
|
+
for _, datasource in nparser.environment.datasources.items():
|
|
1083
1031
|
self.environment.add_datasource(datasource.with_namespace(alias))
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1032
|
+
imps = ImportStatement(
|
|
1033
|
+
alias=alias, path=Path(args[0]), environment=nparser.environment
|
|
1034
|
+
)
|
|
1035
|
+
self.environment.imports[alias] = imps
|
|
1036
|
+
return imps
|
|
1088
1037
|
|
|
1089
1038
|
@v_args(meta=True)
|
|
1090
1039
|
def show_category(self, meta: Meta, args) -> ShowCategory:
|
|
@@ -1208,7 +1157,14 @@ class ParseToObjects(Transformer):
|
|
|
1208
1157
|
def where(self, args):
|
|
1209
1158
|
root = args[0]
|
|
1210
1159
|
if not isinstance(root, (Comparison, Conditional, Parenthetical)):
|
|
1211
|
-
|
|
1160
|
+
if arg_to_datatype(root) == DataType.BOOL:
|
|
1161
|
+
root = Comparison(left=root, right=True, operator=ComparisonOperator.EQ)
|
|
1162
|
+
else:
|
|
1163
|
+
root = Comparison(
|
|
1164
|
+
left=root,
|
|
1165
|
+
right=MagicConstants.NULL,
|
|
1166
|
+
operator=ComparisonOperator.IS_NOT,
|
|
1167
|
+
)
|
|
1212
1168
|
return WhereClause(conditional=root)
|
|
1213
1169
|
|
|
1214
1170
|
@v_args(meta=True)
|
|
@@ -1221,7 +1177,6 @@ class ParseToObjects(Transformer):
|
|
|
1221
1177
|
|
|
1222
1178
|
@v_args(meta=True)
|
|
1223
1179
|
def raw_function(self, meta: Meta, args) -> Function:
|
|
1224
|
-
print(args)
|
|
1225
1180
|
identity = args[0]
|
|
1226
1181
|
fargs = args[1]
|
|
1227
1182
|
output = args[2]
|
|
@@ -1262,6 +1217,22 @@ class ParseToObjects(Transformer):
|
|
|
1262
1217
|
def comparison(self, args) -> Comparison:
|
|
1263
1218
|
return Comparison(left=args[0], right=args[2], operator=args[1])
|
|
1264
1219
|
|
|
1220
|
+
@v_args(meta=True)
|
|
1221
|
+
def subselect_comparison(self, meta: Meta, args) -> SubselectComparison:
|
|
1222
|
+
right = args[2]
|
|
1223
|
+
if not isinstance(right, Concept):
|
|
1224
|
+
right = arbitrary_to_concept(
|
|
1225
|
+
right,
|
|
1226
|
+
namespace=self.environment.namespace,
|
|
1227
|
+
name=f"{VIRTUAL_CONCEPT_PREFIX}_{string_to_hash(str(right))}",
|
|
1228
|
+
)
|
|
1229
|
+
self.environment.add_concept(right)
|
|
1230
|
+
return SubselectComparison(
|
|
1231
|
+
left=args[0],
|
|
1232
|
+
right=right,
|
|
1233
|
+
operator=args[1],
|
|
1234
|
+
)
|
|
1235
|
+
|
|
1265
1236
|
def expr_tuple(self, args):
|
|
1266
1237
|
return Parenthetical(content=args)
|
|
1267
1238
|
|
trilogy/parsing/render.py
CHANGED
|
@@ -298,128 +298,6 @@ class Renderer:
|
|
|
298
298
|
def _(self, arg: "FilterItem"):
|
|
299
299
|
return f"filter {self.to_string(arg.content)} where {self.to_string(arg.where)}"
|
|
300
300
|
|
|
301
|
-
@to_string.register
|
|
302
|
-
def _(self, arg: "WindowItem"):
|
|
303
|
-
over = ",".join(self.to_string(c) for c in arg.over)
|
|
304
|
-
order = ",".join(self.to_string(c) for c in arg.order_by)
|
|
305
|
-
if over:
|
|
306
|
-
return (
|
|
307
|
-
f"{arg.type.value} {self.to_string(arg.content)} by {order} OVER {over}"
|
|
308
|
-
)
|
|
309
|
-
return f"{arg.type.value} {self.to_string(arg.content)} by {order}"
|
|
310
|
-
|
|
311
|
-
@to_string.register
|
|
312
|
-
def _(self, arg: "FilterItem"):
|
|
313
|
-
return f"filter {self.to_string(arg.content)} where {self.to_string(arg.where)}"
|
|
314
|
-
|
|
315
|
-
@to_string.register
|
|
316
|
-
def _(self, arg: "ImportStatement"):
|
|
317
|
-
return f"import {arg.path} as {arg.alias};"
|
|
318
|
-
|
|
319
|
-
@to_string.register
|
|
320
|
-
def _(self, arg: "WindowItem"):
|
|
321
|
-
over = ",".join(self.to_string(c) for c in arg.over)
|
|
322
|
-
order = ",".join(self.to_string(c) for c in arg.order_by)
|
|
323
|
-
if over:
|
|
324
|
-
return (
|
|
325
|
-
f"{arg.type.value} {self.to_string(arg.content)} by {order} OVER {over}"
|
|
326
|
-
)
|
|
327
|
-
return f"{arg.type.value} {self.to_string(arg.content)} by {order}"
|
|
328
|
-
|
|
329
|
-
@to_string.register
|
|
330
|
-
def _(self, arg: "FilterItem"):
|
|
331
|
-
return f"filter {self.to_string(arg.content)} where {self.to_string(arg.where)}"
|
|
332
|
-
|
|
333
|
-
@to_string.register
|
|
334
|
-
def _(self, arg: "ImportStatement"):
|
|
335
|
-
return f"import {arg.path} as {arg.alias};"
|
|
336
|
-
|
|
337
|
-
@to_string.register
|
|
338
|
-
def _(self, arg: "WindowItem"):
|
|
339
|
-
over = ",".join(self.to_string(c) for c in arg.over)
|
|
340
|
-
order = ",".join(self.to_string(c) for c in arg.order_by)
|
|
341
|
-
if over:
|
|
342
|
-
return (
|
|
343
|
-
f"{arg.type.value} {self.to_string(arg.content)} by {order} OVER {over}"
|
|
344
|
-
)
|
|
345
|
-
return f"{arg.type.value} {self.to_string(arg.content)} by {order}"
|
|
346
|
-
|
|
347
|
-
@to_string.register
|
|
348
|
-
def _(self, arg: "FilterItem"):
|
|
349
|
-
return f"filter {self.to_string(arg.content)} where {self.to_string(arg.where)}"
|
|
350
|
-
|
|
351
|
-
@to_string.register
|
|
352
|
-
def _(self, arg: "ImportStatement"):
|
|
353
|
-
return f"import {arg.path} as {arg.alias};"
|
|
354
|
-
|
|
355
|
-
@to_string.register
|
|
356
|
-
def _(self, arg: "WindowItem"):
|
|
357
|
-
over = ",".join(self.to_string(c) for c in arg.over)
|
|
358
|
-
order = ",".join(self.to_string(c) for c in arg.order_by)
|
|
359
|
-
if over:
|
|
360
|
-
return (
|
|
361
|
-
f"{arg.type.value} {self.to_string(arg.content)} by {order} OVER {over}"
|
|
362
|
-
)
|
|
363
|
-
return f"{arg.type.value} {self.to_string(arg.content)} by {order}"
|
|
364
|
-
|
|
365
|
-
@to_string.register
|
|
366
|
-
def _(self, arg: "FilterItem"):
|
|
367
|
-
return f"filter {self.to_string(arg.content)} where {self.to_string(arg.where)}"
|
|
368
|
-
|
|
369
|
-
@to_string.register
|
|
370
|
-
def _(self, arg: "ImportStatement"):
|
|
371
|
-
return f"import {arg.path} as {arg.alias};"
|
|
372
|
-
|
|
373
|
-
@to_string.register
|
|
374
|
-
def _(self, arg: "WindowItem"):
|
|
375
|
-
over = ",".join(self.to_string(c) for c in arg.over)
|
|
376
|
-
order = ",".join(self.to_string(c) for c in arg.order_by)
|
|
377
|
-
if over:
|
|
378
|
-
return (
|
|
379
|
-
f"{arg.type.value} {self.to_string(arg.content)} by {order} OVER {over}"
|
|
380
|
-
)
|
|
381
|
-
return f"{arg.type.value} {self.to_string(arg.content)} by {order}"
|
|
382
|
-
|
|
383
|
-
@to_string.register
|
|
384
|
-
def _(self, arg: "FilterItem"):
|
|
385
|
-
return f"filter {self.to_string(arg.content)} where {self.to_string(arg.where)}"
|
|
386
|
-
|
|
387
|
-
@to_string.register
|
|
388
|
-
def _(self, arg: "ImportStatement"):
|
|
389
|
-
return f"import {arg.path} as {arg.alias};"
|
|
390
|
-
|
|
391
|
-
@to_string.register
|
|
392
|
-
def _(self, arg: "WindowItem"):
|
|
393
|
-
over = ",".join(self.to_string(c) for c in arg.over)
|
|
394
|
-
order = ",".join(self.to_string(c) for c in arg.order_by)
|
|
395
|
-
if over:
|
|
396
|
-
return (
|
|
397
|
-
f"{arg.type.value} {self.to_string(arg.content)} by {order} OVER {over}"
|
|
398
|
-
)
|
|
399
|
-
return f"{arg.type.value} {self.to_string(arg.content)} by {order}"
|
|
400
|
-
|
|
401
|
-
@to_string.register
|
|
402
|
-
def _(self, arg: "FilterItem"):
|
|
403
|
-
return f"filter {self.to_string(arg.content)} where {self.to_string(arg.where)}"
|
|
404
|
-
|
|
405
|
-
@to_string.register
|
|
406
|
-
def _(self, arg: "ImportStatement"):
|
|
407
|
-
return f"import {arg.path} as {arg.alias};"
|
|
408
|
-
|
|
409
|
-
@to_string.register
|
|
410
|
-
def _(self, arg: "WindowItem"):
|
|
411
|
-
over = ",".join(self.to_string(c) for c in arg.over)
|
|
412
|
-
order = ",".join(self.to_string(c) for c in arg.order_by)
|
|
413
|
-
if over:
|
|
414
|
-
return (
|
|
415
|
-
f"{arg.type.value} {self.to_string(arg.content)} by {order} OVER {over}"
|
|
416
|
-
)
|
|
417
|
-
return f"{arg.type.value} {self.to_string(arg.content)} by {order}"
|
|
418
|
-
|
|
419
|
-
@to_string.register
|
|
420
|
-
def _(self, arg: "FilterItem"):
|
|
421
|
-
return f"filter {self.to_string(arg.content)} where {self.to_string(arg.where)}"
|
|
422
|
-
|
|
423
301
|
@to_string.register
|
|
424
302
|
def _(self, arg: "ImportStatement"):
|
|
425
303
|
return f"import {arg.path} as {arg.alias};"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|