pytrilogy 0.0.2.47__py3-none-any.whl → 0.0.2.49__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.47.dist-info → pytrilogy-0.0.2.49.dist-info}/METADATA +1 -1
- pytrilogy-0.0.2.49.dist-info/RECORD +85 -0
- trilogy/__init__.py +2 -2
- trilogy/constants.py +4 -2
- trilogy/core/enums.py +7 -1
- trilogy/core/env_processor.py +1 -2
- trilogy/core/environment_helpers.py +5 -5
- trilogy/core/functions.py +11 -10
- trilogy/core/internal.py +2 -3
- trilogy/core/models.py +449 -393
- trilogy/core/optimization.py +37 -21
- trilogy/core/optimizations/__init__.py +1 -1
- trilogy/core/optimizations/base_optimization.py +6 -6
- trilogy/core/optimizations/inline_constant.py +7 -4
- trilogy/core/optimizations/inline_datasource.py +14 -5
- trilogy/core/optimizations/predicate_pushdown.py +20 -10
- trilogy/core/processing/concept_strategies_v3.py +43 -24
- trilogy/core/processing/graph_utils.py +2 -3
- trilogy/core/processing/node_generators/__init__.py +7 -5
- trilogy/core/processing/node_generators/basic_node.py +4 -4
- trilogy/core/processing/node_generators/common.py +10 -11
- trilogy/core/processing/node_generators/filter_node.py +7 -9
- trilogy/core/processing/node_generators/group_node.py +10 -11
- trilogy/core/processing/node_generators/group_to_node.py +5 -5
- trilogy/core/processing/node_generators/multiselect_node.py +10 -12
- trilogy/core/processing/node_generators/node_merge_node.py +7 -9
- trilogy/core/processing/node_generators/rowset_node.py +36 -15
- trilogy/core/processing/node_generators/select_merge_node.py +11 -10
- trilogy/core/processing/node_generators/select_node.py +5 -5
- trilogy/core/processing/node_generators/union_node.py +75 -0
- trilogy/core/processing/node_generators/unnest_node.py +2 -3
- trilogy/core/processing/node_generators/window_node.py +3 -4
- trilogy/core/processing/nodes/__init__.py +9 -5
- trilogy/core/processing/nodes/base_node.py +45 -13
- trilogy/core/processing/nodes/filter_node.py +3 -4
- trilogy/core/processing/nodes/group_node.py +17 -13
- trilogy/core/processing/nodes/merge_node.py +14 -12
- trilogy/core/processing/nodes/select_node_v2.py +13 -9
- trilogy/core/processing/nodes/union_node.py +50 -0
- trilogy/core/processing/nodes/unnest_node.py +2 -3
- trilogy/core/processing/nodes/window_node.py +2 -3
- trilogy/core/processing/utility.py +38 -41
- trilogy/core/query_processor.py +71 -51
- trilogy/dialect/base.py +95 -53
- trilogy/dialect/bigquery.py +2 -3
- trilogy/dialect/common.py +5 -4
- trilogy/dialect/config.py +0 -2
- trilogy/dialect/duckdb.py +2 -2
- trilogy/dialect/enums.py +5 -5
- trilogy/dialect/postgres.py +2 -2
- trilogy/dialect/presto.py +3 -4
- trilogy/dialect/snowflake.py +2 -2
- trilogy/dialect/sql_server.py +3 -4
- trilogy/engine.py +2 -1
- trilogy/executor.py +43 -30
- trilogy/hooks/base_hook.py +5 -4
- trilogy/hooks/graph_hook.py +2 -1
- trilogy/hooks/query_debugger.py +18 -8
- trilogy/parsing/common.py +15 -20
- trilogy/parsing/parse_engine.py +125 -88
- trilogy/parsing/render.py +32 -35
- trilogy/parsing/trilogy.lark +8 -1
- trilogy/scripts/trilogy.py +6 -4
- trilogy/utility.py +1 -1
- pytrilogy-0.0.2.47.dist-info/RECORD +0 -83
- {pytrilogy-0.0.2.47.dist-info → pytrilogy-0.0.2.49.dist-info}/LICENSE.md +0 -0
- {pytrilogy-0.0.2.47.dist-info → pytrilogy-0.0.2.49.dist-info}/WHEEL +0 -0
- {pytrilogy-0.0.2.47.dist-info → pytrilogy-0.0.2.49.dist-info}/entry_points.txt +0 -0
- {pytrilogy-0.0.2.47.dist-info → pytrilogy-0.0.2.49.dist-info}/top_level.txt +0 -0
trilogy/parsing/parse_engine.py
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
1
2
|
from os.path import dirname, join
|
|
2
|
-
from
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
from re import IGNORECASE
|
|
4
|
-
from
|
|
5
|
+
from typing import List, Optional, Tuple, Union
|
|
6
|
+
|
|
7
|
+
from lark import Lark, ParseTree, Transformer, Tree, v_args
|
|
5
8
|
from lark.exceptions import (
|
|
6
9
|
UnexpectedCharacters,
|
|
7
10
|
UnexpectedEOF,
|
|
@@ -9,11 +12,11 @@ from lark.exceptions import (
|
|
|
9
12
|
UnexpectedToken,
|
|
10
13
|
VisitError,
|
|
11
14
|
)
|
|
12
|
-
from pathlib import Path
|
|
13
15
|
from lark.tree import Meta
|
|
14
16
|
from pydantic import ValidationError
|
|
15
|
-
|
|
17
|
+
|
|
16
18
|
from trilogy.constants import (
|
|
19
|
+
CONFIG,
|
|
17
20
|
DEFAULT_NAMESPACE,
|
|
18
21
|
NULL_VALUE,
|
|
19
22
|
MagicConstants,
|
|
@@ -21,110 +24,111 @@ from trilogy.constants import (
|
|
|
21
24
|
from trilogy.core.enums import (
|
|
22
25
|
BooleanOperator,
|
|
23
26
|
ComparisonOperator,
|
|
27
|
+
ConceptSource,
|
|
28
|
+
DatePart,
|
|
24
29
|
FunctionType,
|
|
25
30
|
InfiniteFunctionArgs,
|
|
31
|
+
IOType,
|
|
26
32
|
Modifier,
|
|
27
33
|
Ordering,
|
|
28
34
|
Purpose,
|
|
35
|
+
ShowCategory,
|
|
29
36
|
WindowOrder,
|
|
30
37
|
WindowType,
|
|
31
|
-
DatePart,
|
|
32
|
-
ShowCategory,
|
|
33
|
-
IOType,
|
|
34
|
-
ConceptSource,
|
|
35
38
|
)
|
|
36
39
|
from trilogy.core.exceptions import InvalidSyntaxException, UndefinedConceptException
|
|
37
40
|
from trilogy.core.functions import (
|
|
41
|
+
Abs,
|
|
42
|
+
AttrAccess,
|
|
43
|
+
Bool,
|
|
44
|
+
Coalesce,
|
|
38
45
|
Count,
|
|
39
46
|
CountDistinct,
|
|
47
|
+
CurrentDate,
|
|
48
|
+
CurrentDatetime,
|
|
40
49
|
Group,
|
|
50
|
+
IndexAccess,
|
|
51
|
+
IsNull,
|
|
52
|
+
MapAccess,
|
|
41
53
|
Max,
|
|
42
54
|
Min,
|
|
43
55
|
Split,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
AttrAccess,
|
|
47
|
-
Abs,
|
|
56
|
+
StrPos,
|
|
57
|
+
SubString,
|
|
48
58
|
Unnest,
|
|
49
|
-
Coalesce,
|
|
50
59
|
function_args_to_output_purpose,
|
|
51
|
-
CurrentDate,
|
|
52
|
-
CurrentDatetime,
|
|
53
|
-
IsNull,
|
|
54
|
-
Bool,
|
|
55
|
-
SubString,
|
|
56
|
-
StrPos,
|
|
57
60
|
)
|
|
61
|
+
from trilogy.core.internal import ALL_ROWS_CONCEPT, INTERNAL_NAMESPACE
|
|
58
62
|
from trilogy.core.models import (
|
|
59
63
|
Address,
|
|
64
|
+
AggregateWrapper,
|
|
60
65
|
AlignClause,
|
|
61
66
|
AlignItem,
|
|
62
|
-
AggregateWrapper,
|
|
63
67
|
CaseElse,
|
|
64
68
|
CaseWhen,
|
|
65
69
|
ColumnAssignment,
|
|
66
70
|
Comment,
|
|
67
71
|
Comparison,
|
|
68
|
-
SubselectComparison,
|
|
69
72
|
Concept,
|
|
73
|
+
ConceptDeclarationStatement,
|
|
74
|
+
ConceptDerivation,
|
|
70
75
|
ConceptTransform,
|
|
71
76
|
Conditional,
|
|
77
|
+
CopyStatement,
|
|
72
78
|
Datasource,
|
|
73
|
-
|
|
79
|
+
DataType,
|
|
74
80
|
Environment,
|
|
81
|
+
EnvironmentConceptDict,
|
|
75
82
|
FilterItem,
|
|
76
83
|
Function,
|
|
77
84
|
Grain,
|
|
85
|
+
HavingClause,
|
|
78
86
|
ImportStatement,
|
|
79
87
|
Limit,
|
|
88
|
+
ListType,
|
|
89
|
+
ListWrapper,
|
|
90
|
+
MapType,
|
|
91
|
+
MapWrapper,
|
|
92
|
+
MergeStatementV2,
|
|
80
93
|
Metadata,
|
|
81
94
|
MultiSelectStatement,
|
|
95
|
+
NumericType,
|
|
82
96
|
OrderBy,
|
|
83
97
|
OrderItem,
|
|
84
98
|
Parenthetical,
|
|
85
99
|
PersistStatement,
|
|
86
100
|
Query,
|
|
101
|
+
RawColumnExpr,
|
|
87
102
|
RawSQLStatement,
|
|
88
|
-
|
|
89
|
-
SelectStatement,
|
|
103
|
+
RowsetDerivationStatement,
|
|
90
104
|
SelectItem,
|
|
105
|
+
SelectStatement,
|
|
106
|
+
ShowStatement,
|
|
107
|
+
StructType,
|
|
108
|
+
SubselectComparison,
|
|
109
|
+
TupleWrapper,
|
|
110
|
+
UndefinedConcept,
|
|
91
111
|
WhereClause,
|
|
92
112
|
Window,
|
|
93
113
|
WindowItem,
|
|
94
114
|
WindowItemOrder,
|
|
95
115
|
WindowItemOver,
|
|
96
|
-
RawColumnExpr,
|
|
97
116
|
arg_to_datatype,
|
|
98
|
-
|
|
99
|
-
ListWrapper,
|
|
100
|
-
MapWrapper,
|
|
101
|
-
MapType,
|
|
102
|
-
ShowStatement,
|
|
103
|
-
DataType,
|
|
104
|
-
StructType,
|
|
105
|
-
ListType,
|
|
106
|
-
ConceptDeclarationStatement,
|
|
107
|
-
ConceptDerivation,
|
|
108
|
-
RowsetDerivationStatement,
|
|
117
|
+
dict_to_map_wrapper,
|
|
109
118
|
list_to_wrapper,
|
|
119
|
+
merge_datatypes,
|
|
110
120
|
tuple_to_wrapper,
|
|
111
|
-
dict_to_map_wrapper,
|
|
112
|
-
NumericType,
|
|
113
|
-
HavingClause,
|
|
114
|
-
TupleWrapper,
|
|
115
121
|
)
|
|
116
|
-
from trilogy.parsing.exceptions import ParseError
|
|
117
122
|
from trilogy.parsing.common import (
|
|
118
123
|
agg_wrapper_to_concept,
|
|
119
|
-
window_item_to_concept,
|
|
120
|
-
function_to_concept,
|
|
121
|
-
filter_item_to_concept,
|
|
122
|
-
constant_to_concept,
|
|
123
124
|
arbitrary_to_concept,
|
|
125
|
+
constant_to_concept,
|
|
126
|
+
filter_item_to_concept,
|
|
127
|
+
function_to_concept,
|
|
124
128
|
process_function_args,
|
|
129
|
+
window_item_to_concept,
|
|
125
130
|
)
|
|
126
|
-
from
|
|
127
|
-
|
|
131
|
+
from trilogy.parsing.exceptions import ParseError
|
|
128
132
|
|
|
129
133
|
CONSTANT_TYPES = (int, float, str, bool, list, ListWrapper, MapWrapper)
|
|
130
134
|
|
|
@@ -195,7 +199,7 @@ def unwrap_transformation(
|
|
|
195
199
|
str,
|
|
196
200
|
float,
|
|
197
201
|
bool,
|
|
198
|
-
]
|
|
202
|
+
],
|
|
199
203
|
) -> Function | FilterItem | WindowItem | AggregateWrapper:
|
|
200
204
|
if isinstance(input, Function):
|
|
201
205
|
return input
|
|
@@ -264,7 +268,6 @@ class ParseToObjects(Transformer):
|
|
|
264
268
|
if v.pass_count == 2:
|
|
265
269
|
continue
|
|
266
270
|
v.hydrate_missing()
|
|
267
|
-
self.environment.concepts.fail_on_missing = True
|
|
268
271
|
reparsed = self.transform(self.tokens[self.token_address])
|
|
269
272
|
self.environment.concepts.undefined = {}
|
|
270
273
|
return reparsed
|
|
@@ -310,7 +313,8 @@ class ParseToObjects(Transformer):
|
|
|
310
313
|
|
|
311
314
|
@v_args(meta=True)
|
|
312
315
|
def concept_lit(self, meta: Meta, args) -> Concept:
|
|
313
|
-
|
|
316
|
+
address = args[0]
|
|
317
|
+
return self.environment.concepts.__getitem__(address, meta.line)
|
|
314
318
|
|
|
315
319
|
def ADDRESS(self, args) -> Address:
|
|
316
320
|
return Address(location=args.value, quoted=False)
|
|
@@ -429,7 +433,6 @@ class ParseToObjects(Transformer):
|
|
|
429
433
|
|
|
430
434
|
@v_args(meta=True)
|
|
431
435
|
def concept_property_declaration(self, meta: Meta, args) -> Concept:
|
|
432
|
-
|
|
433
436
|
metadata = Metadata()
|
|
434
437
|
modifiers = []
|
|
435
438
|
for arg in args:
|
|
@@ -488,12 +491,11 @@ class ParseToObjects(Transformer):
|
|
|
488
491
|
)
|
|
489
492
|
if concept.metadata:
|
|
490
493
|
concept.metadata.line_number = meta.line
|
|
491
|
-
self.environment.add_concept(concept, meta=meta)
|
|
494
|
+
self.environment.add_concept(concept, meta=meta, force=True)
|
|
492
495
|
return ConceptDeclarationStatement(concept=concept)
|
|
493
496
|
|
|
494
497
|
@v_args(meta=True)
|
|
495
498
|
def concept_derivation(self, meta: Meta, args) -> ConceptDerivation:
|
|
496
|
-
|
|
497
499
|
if len(args) > 3:
|
|
498
500
|
metadata = args[3]
|
|
499
501
|
else:
|
|
@@ -568,6 +570,7 @@ class ParseToObjects(Transformer):
|
|
|
568
570
|
for new_concept in output.derived_concepts:
|
|
569
571
|
if new_concept.metadata:
|
|
570
572
|
new_concept.metadata.line_number = meta.line
|
|
573
|
+
# output.select.local_concepts[new_concept.address] = new_concept
|
|
571
574
|
self.environment.add_concept(new_concept)
|
|
572
575
|
|
|
573
576
|
return output
|
|
@@ -604,7 +607,6 @@ class ParseToObjects(Transformer):
|
|
|
604
607
|
|
|
605
608
|
@v_args(meta=True)
|
|
606
609
|
def concept(self, meta: Meta, args) -> ConceptDeclarationStatement:
|
|
607
|
-
|
|
608
610
|
if isinstance(args[0], Concept):
|
|
609
611
|
concept: Concept = args[0]
|
|
610
612
|
else:
|
|
@@ -680,7 +682,6 @@ class ParseToObjects(Transformer):
|
|
|
680
682
|
|
|
681
683
|
@v_args(meta=True)
|
|
682
684
|
def select_transform(self, meta: Meta, args) -> ConceptTransform:
|
|
683
|
-
|
|
684
685
|
output: str = args[1]
|
|
685
686
|
transformation = unwrap_transformation(args[0])
|
|
686
687
|
lookup, namespace, output, parent = parse_concept_reference(
|
|
@@ -712,7 +713,6 @@ class ParseToObjects(Transformer):
|
|
|
712
713
|
else:
|
|
713
714
|
raise SyntaxError("Invalid transformation")
|
|
714
715
|
|
|
715
|
-
self.environment.add_concept(concept, meta=meta)
|
|
716
716
|
return ConceptTransform(function=transformation, output=concept)
|
|
717
717
|
|
|
718
718
|
@v_args(meta=True)
|
|
@@ -761,7 +761,6 @@ class ParseToObjects(Transformer):
|
|
|
761
761
|
return Ordering(base)
|
|
762
762
|
|
|
763
763
|
def order_list(self, args):
|
|
764
|
-
|
|
765
764
|
def handle_order_item(x, namespace: str):
|
|
766
765
|
if not isinstance(x, Concept):
|
|
767
766
|
x = arbitrary_to_concept(
|
|
@@ -843,7 +842,6 @@ class ParseToObjects(Transformer):
|
|
|
843
842
|
|
|
844
843
|
@v_args(meta=True)
|
|
845
844
|
def copy_statement(self, meta: Meta, args) -> CopyStatement:
|
|
846
|
-
|
|
847
845
|
return CopyStatement(
|
|
848
846
|
target=args[1],
|
|
849
847
|
target_type=args[0],
|
|
@@ -959,7 +957,7 @@ class ParseToObjects(Transformer):
|
|
|
959
957
|
|
|
960
958
|
@v_args(meta=True)
|
|
961
959
|
def multi_select_statement(self, meta: Meta, args) -> MultiSelectStatement:
|
|
962
|
-
selects = []
|
|
960
|
+
selects: list[SelectStatement] = []
|
|
963
961
|
align: AlignClause | None = None
|
|
964
962
|
limit: int | None = None
|
|
965
963
|
order_by: OrderBy | None = None
|
|
@@ -978,6 +976,10 @@ class ParseToObjects(Transformer):
|
|
|
978
976
|
|
|
979
977
|
assert align
|
|
980
978
|
assert align is not None
|
|
979
|
+
base_local: EnvironmentConceptDict = selects[0].local_concepts
|
|
980
|
+
for select in selects[1:]:
|
|
981
|
+
for k, v in select.local_concepts.items():
|
|
982
|
+
base_local[k] = v
|
|
981
983
|
multi = MultiSelectStatement(
|
|
982
984
|
selects=selects,
|
|
983
985
|
align=align,
|
|
@@ -986,6 +988,7 @@ class ParseToObjects(Transformer):
|
|
|
986
988
|
order_by=order_by,
|
|
987
989
|
limit=limit,
|
|
988
990
|
meta=Metadata(line_number=meta.line),
|
|
991
|
+
local_concepts=base_local,
|
|
989
992
|
)
|
|
990
993
|
for concept in multi.derived_concepts:
|
|
991
994
|
self.environment.add_concept(concept, meta=meta)
|
|
@@ -1019,34 +1022,55 @@ class ParseToObjects(Transformer):
|
|
|
1019
1022
|
order_by=order_by,
|
|
1020
1023
|
meta=Metadata(line_number=meta.line),
|
|
1021
1024
|
)
|
|
1022
|
-
for
|
|
1023
|
-
#
|
|
1024
|
-
#
|
|
1025
|
-
#
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1025
|
+
for parse_pass in [1, 2]:
|
|
1026
|
+
# the first pass will result in all concepts being defined
|
|
1027
|
+
# the second will get grains appropriately
|
|
1028
|
+
# eg if someone does sum(x)->a, b+c -> z - we don't know if Z is a key to group by or an aggregate
|
|
1029
|
+
# until after the first pass, and so don't know the grain of a
|
|
1030
|
+
nselect = []
|
|
1031
|
+
for item in select_items:
|
|
1032
|
+
# we don't know the grain of an aggregate at assignment time
|
|
1033
|
+
# so rebuild at this point in the tree
|
|
1034
|
+
# TODO: simplify
|
|
1035
|
+
if isinstance(item.content, ConceptTransform):
|
|
1036
|
+
new_concept = item.content.output.with_select_context(
|
|
1037
|
+
output.local_concepts,
|
|
1038
|
+
output.grain,
|
|
1039
|
+
environment=self.environment,
|
|
1040
|
+
)
|
|
1041
|
+
output.local_concepts[new_concept.address] = new_concept
|
|
1042
|
+
item.content.output = new_concept
|
|
1043
|
+
if parse_pass == 2 and CONFIG.select_as_definition:
|
|
1044
|
+
self.environment.add_concept(new_concept)
|
|
1045
|
+
elif isinstance(item.content, UndefinedConcept):
|
|
1046
|
+
self.environment.concepts.raise_undefined(
|
|
1047
|
+
item.content.address,
|
|
1048
|
+
line_no=item.content.metadata.line_number,
|
|
1049
|
+
file=self.token_address,
|
|
1050
|
+
)
|
|
1051
|
+
elif isinstance(item.content, Concept):
|
|
1052
|
+
# Sometimes cached values here don't have the latest info
|
|
1053
|
+
# but we can't just use environment, as it might not have the right grain.
|
|
1054
|
+
item.content = item.content.with_select_context(
|
|
1055
|
+
output.local_concepts,
|
|
1056
|
+
output.grain,
|
|
1057
|
+
environment=self.environment,
|
|
1058
|
+
)
|
|
1059
|
+
output.local_concepts[item.content.address] = item.content
|
|
1060
|
+
nselect.append(item)
|
|
1040
1061
|
if order_by:
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1062
|
+
output.order_by = order_by.with_select_context(
|
|
1063
|
+
local_concepts=output.local_concepts,
|
|
1064
|
+
grain=output.grain,
|
|
1065
|
+
environment=self.environment,
|
|
1066
|
+
)
|
|
1067
|
+
if output.having_clause:
|
|
1068
|
+
output.having_clause = output.having_clause.with_select_context(
|
|
1069
|
+
local_concepts=output.local_concepts,
|
|
1070
|
+
grain=output.grain,
|
|
1071
|
+
environment=self.environment,
|
|
1072
|
+
)
|
|
1073
|
+
output.validate_syntax(self.environment)
|
|
1050
1074
|
return output
|
|
1051
1075
|
|
|
1052
1076
|
@v_args(meta=True)
|
|
@@ -1126,7 +1150,6 @@ class ParseToObjects(Transformer):
|
|
|
1126
1150
|
return args[0]
|
|
1127
1151
|
|
|
1128
1152
|
def struct_lit(self, args):
|
|
1129
|
-
|
|
1130
1153
|
zipped = dict(zip(args[::2], args[1::2]))
|
|
1131
1154
|
types = [arg_to_datatype(x) for x in args[1::2]]
|
|
1132
1155
|
return Function(
|
|
@@ -1422,10 +1445,23 @@ class ParseToObjects(Transformer):
|
|
|
1422
1445
|
output_datatype=DataType.STRING,
|
|
1423
1446
|
output_purpose=Purpose.PROPERTY,
|
|
1424
1447
|
valid_inputs={DataType.STRING},
|
|
1425
|
-
arg_count
|
|
1448
|
+
arg_count=-1,
|
|
1426
1449
|
# output_grain=args[0].grain,
|
|
1427
1450
|
)
|
|
1428
1451
|
|
|
1452
|
+
@v_args(meta=True)
|
|
1453
|
+
def union(self, meta, args):
|
|
1454
|
+
args = process_function_args(args, meta=meta, environment=self.environment)
|
|
1455
|
+
output_datatype = merge_datatypes([arg_to_datatype(x) for x in args])
|
|
1456
|
+
return Function(
|
|
1457
|
+
operator=FunctionType.UNION,
|
|
1458
|
+
arguments=args,
|
|
1459
|
+
output_datatype=output_datatype,
|
|
1460
|
+
output_purpose=Purpose.KEY,
|
|
1461
|
+
valid_inputs={*DataType},
|
|
1462
|
+
arg_count=-1,
|
|
1463
|
+
)
|
|
1464
|
+
|
|
1429
1465
|
@v_args(meta=True)
|
|
1430
1466
|
def like(self, meta, args):
|
|
1431
1467
|
args = process_function_args(args, meta=meta, environment=self.environment)
|
|
@@ -1945,6 +1981,7 @@ def parse_text(text: str, environment: Optional[Environment] = None) -> Tuple[
|
|
|
1945
1981
|
# this will reset fail on missing
|
|
1946
1982
|
pass_two = parser.hydrate_missing()
|
|
1947
1983
|
output = [v for v in pass_two if v]
|
|
1984
|
+
environment.concepts.fail_on_missing = True
|
|
1948
1985
|
except VisitError as e:
|
|
1949
1986
|
unpack_visit_error(e)
|
|
1950
1987
|
# this will never be reached
|
trilogy/parsing/render.py
CHANGED
|
@@ -1,55 +1,52 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
1
2
|
from functools import singledispatchmethod
|
|
2
3
|
|
|
3
4
|
from jinja2 import Template
|
|
4
5
|
|
|
5
|
-
from trilogy.constants import DEFAULT_NAMESPACE,
|
|
6
|
-
from trilogy.core.enums import
|
|
6
|
+
from trilogy.constants import DEFAULT_NAMESPACE, VIRTUAL_CONCEPT_PREFIX, MagicConstants
|
|
7
|
+
from trilogy.core.enums import ConceptSource, DatePart, FunctionType, Modifier, Purpose
|
|
7
8
|
from trilogy.core.models import (
|
|
8
|
-
DataType,
|
|
9
9
|
Address,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
SelectStatement,
|
|
17
|
-
SelectItem,
|
|
18
|
-
WhereClause,
|
|
19
|
-
Conditional,
|
|
20
|
-
SubselectComparison,
|
|
10
|
+
AggregateWrapper,
|
|
11
|
+
AlignClause,
|
|
12
|
+
AlignItem,
|
|
13
|
+
CaseElse,
|
|
14
|
+
CaseWhen,
|
|
15
|
+
ColumnAssignment,
|
|
21
16
|
Comparison,
|
|
22
|
-
|
|
17
|
+
Concept,
|
|
23
18
|
ConceptDeclarationStatement,
|
|
24
19
|
ConceptDerivation,
|
|
20
|
+
ConceptTransform,
|
|
21
|
+
Conditional,
|
|
22
|
+
CopyStatement,
|
|
25
23
|
Datasource,
|
|
26
|
-
|
|
24
|
+
DataType,
|
|
25
|
+
Environment,
|
|
27
26
|
FilterItem,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
CaseElse,
|
|
31
|
-
CaseWhen,
|
|
27
|
+
Function,
|
|
28
|
+
Grain,
|
|
32
29
|
ImportStatement,
|
|
33
|
-
Parenthetical,
|
|
34
|
-
AggregateWrapper,
|
|
35
|
-
PersistStatement,
|
|
36
|
-
ListWrapper,
|
|
37
30
|
ListType,
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
ListWrapper,
|
|
32
|
+
MergeStatementV2,
|
|
40
33
|
MultiSelectStatement,
|
|
34
|
+
NumericType,
|
|
41
35
|
OrderBy,
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
OrderItem,
|
|
37
|
+
Parenthetical,
|
|
38
|
+
PersistStatement,
|
|
39
|
+
Query,
|
|
40
|
+
RawColumnExpr,
|
|
44
41
|
RawSQLStatement,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
RowsetDerivationStatement,
|
|
43
|
+
SelectItem,
|
|
44
|
+
SelectStatement,
|
|
45
|
+
SubselectComparison,
|
|
46
|
+
TupleWrapper,
|
|
47
|
+
WhereClause,
|
|
48
|
+
WindowItem,
|
|
48
49
|
)
|
|
49
|
-
from trilogy.core.enums import Modifier
|
|
50
|
-
|
|
51
|
-
from collections import defaultdict
|
|
52
|
-
|
|
53
50
|
|
|
54
51
|
QUERY_TEMPLATE = Template(
|
|
55
52
|
"""{% if where %}WHERE
|
trilogy/parsing/trilogy.lark
CHANGED
|
@@ -79,6 +79,8 @@
|
|
|
79
79
|
// raw sql statement
|
|
80
80
|
rawsql_statement: "raw_sql"i "(" MULTILINE_STRING ")"
|
|
81
81
|
|
|
82
|
+
|
|
83
|
+
|
|
82
84
|
// copy statement
|
|
83
85
|
|
|
84
86
|
COPY_TYPE: "csv"i
|
|
@@ -166,12 +168,17 @@
|
|
|
166
168
|
//unnesting is a function
|
|
167
169
|
_UNNEST.1: "UNNEST("i
|
|
168
170
|
unnest: _UNNEST expr ")"
|
|
171
|
+
|
|
172
|
+
// union statement
|
|
173
|
+
_UNION.1: "UNION("i
|
|
174
|
+
union: _UNION (expr ",")* expr ")"
|
|
175
|
+
|
|
169
176
|
//indexing into an expression is a function
|
|
170
177
|
index_access: expr "[" int_lit "]"
|
|
171
178
|
map_key_access: expr "[" string_lit "]"
|
|
172
179
|
attr_access: expr "." string_lit
|
|
173
180
|
|
|
174
|
-
expr: _constant_functions | window_item | filter_item | subselect_comparison | between_comparison | fgroup | aggregate_functions | unnest | _static_functions | literal | concept_lit | index_access | map_key_access | attr_access | parenthetical | expr_tuple | comparison | alt_like
|
|
181
|
+
expr: _constant_functions | window_item | filter_item | subselect_comparison | between_comparison | fgroup | aggregate_functions | unnest | union | _static_functions | literal | concept_lit | index_access | map_key_access | attr_access | parenthetical | expr_tuple | comparison | alt_like
|
|
175
182
|
|
|
176
183
|
// functions
|
|
177
184
|
|
trilogy/scripts/trilogy.py
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
from click import Path, argument, option, group, pass_context, UNPROCESSED
|
|
2
|
-
from trilogy import Executor, Environment, parse
|
|
3
|
-
from trilogy.dialect.enums import Dialects
|
|
4
1
|
from datetime import datetime
|
|
5
2
|
from pathlib import Path as PathlibPath
|
|
3
|
+
|
|
4
|
+
from click import UNPROCESSED, Path, argument, group, option, pass_context
|
|
5
|
+
|
|
6
|
+
from trilogy import Environment, Executor, parse
|
|
7
|
+
from trilogy.constants import DEFAULT_NAMESPACE
|
|
8
|
+
from trilogy.dialect.enums import Dialects
|
|
6
9
|
from trilogy.hooks.query_debugger import DebuggingHook
|
|
7
10
|
from trilogy.parsing.render import Renderer
|
|
8
|
-
from trilogy.constants import DEFAULT_NAMESPACE
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
def print_tabulate(q, tabulate):
|
trilogy/utility.py
CHANGED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
trilogy/__init__.py,sha256=1AtwhSy-U-0z7qVDt7pbGMULzjuha1IHXXyCkuZwRiw,291
|
|
2
|
-
trilogy/compiler.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
trilogy/constants.py,sha256=UPymm94T2c6a55XdDaXw0aleTe1pOJ6lf6gOWLKZyKg,1430
|
|
4
|
-
trilogy/engine.py,sha256=R5ubIxYyrxRExz07aZCUfrTsoXCHQ8DKFTDsobXdWdA,1102
|
|
5
|
-
trilogy/executor.py,sha256=mgWg9VR3V6Uo_sNmHtpAtT2ikYvXXFzo7QTWtbQJig4,15398
|
|
6
|
-
trilogy/parser.py,sha256=UtuqSiGiCjpMAYgo1bvNq-b7NSzCA5hzbUW31RXaMII,281
|
|
7
|
-
trilogy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
trilogy/utility.py,sha256=zM__8r29EsyDW7K9VOHz8yvZC2bXFzh7xKy3cL7GKsk,707
|
|
9
|
-
trilogy/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
trilogy/core/constants.py,sha256=7XaCpZn5mQmjTobbeBn56SzPWq9eMNDfzfsRU-fP0VE,171
|
|
11
|
-
trilogy/core/enums.py,sha256=z-qBLh0YW52tkRtp6VLn6afxLfgI45r7_QfDtGH9CSw,6858
|
|
12
|
-
trilogy/core/env_processor.py,sha256=SHVB3nkidIlFc5dz-sofRMKXx66stpLQNuVdQSjC-So,2586
|
|
13
|
-
trilogy/core/environment_helpers.py,sha256=DIsoo-GcXmXVPB1JbNh8Oku25Nyef9mexPIdy2ur_sk,7159
|
|
14
|
-
trilogy/core/ergonomics.py,sha256=ASLDd0RqKWrZiG3XcKHo8nyTjaB_8xfE9t4NZ1UvGpc,1639
|
|
15
|
-
trilogy/core/exceptions.py,sha256=1c1lQCwSw4_5CQS3q7scOkXU8GQvullJXfPHubprl90,617
|
|
16
|
-
trilogy/core/functions.py,sha256=IhVpt3n6wEanKHnGu3oA2w6-hKIlxWpEyz7fHN66mpo,10720
|
|
17
|
-
trilogy/core/graph_models.py,sha256=mameUTiuCajtihDw_2-W218xyJlvTusOWrEKP1yAWgk,2003
|
|
18
|
-
trilogy/core/internal.py,sha256=jNGFHKENnbMiMCtAgsnLZYVSENDK4b5ALecXFZpTDzQ,1075
|
|
19
|
-
trilogy/core/models.py,sha256=Hk25VWc8mA6eJNozhoNaP3_Rx7ECpCYXXQaanS_pwn4,164150
|
|
20
|
-
trilogy/core/optimization.py,sha256=VFSvJLNoCCOraip-PZUKeE4qrlxtXARjQUzJZiW-yRk,7325
|
|
21
|
-
trilogy/core/query_processor.py,sha256=mbcZlgjChrRjDHkdmMbKe-T70UpbBkJhS09MyU5a6UY,17785
|
|
22
|
-
trilogy/core/optimizations/__init__.py,sha256=bWQecbeiwiDx9LJnLsa7dkWxdbl2wcnkcTN69JyP8iI,356
|
|
23
|
-
trilogy/core/optimizations/base_optimization.py,sha256=tWWT-xnTbnEU-mNi_isMNbywm8B9WTRsNFwGpeh3rqE,468
|
|
24
|
-
trilogy/core/optimizations/inline_constant.py,sha256=kHNyc2UoaPVdYfVAPAFwnWuk4sJ_IF5faRtVcDOrBtw,1110
|
|
25
|
-
trilogy/core/optimizations/inline_datasource.py,sha256=NqUOVl0pOXF1R_roELVW8I0qN7or2wPtAsRmDD9QJso,3658
|
|
26
|
-
trilogy/core/optimizations/predicate_pushdown.py,sha256=oJy09U7lb8FMKexWISjg4Ksyf98Nx22bzIxmm9WuXtk,8899
|
|
27
|
-
trilogy/core/processing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
-
trilogy/core/processing/concept_strategies_v3.py,sha256=Qy3WHiKaF371dDmbA0DWVQqSMKptH_gK714Uc41wbqc,36132
|
|
29
|
-
trilogy/core/processing/graph_utils.py,sha256=aq-kqk4Iado2HywDxWEejWc-7PGO6Oa-ZQLAM6XWPHw,1199
|
|
30
|
-
trilogy/core/processing/utility.py,sha256=_sWLDuV8WAEWdEIcAPM8-FcXgBai30UV12i4O9u5Mpc,18680
|
|
31
|
-
trilogy/core/processing/node_generators/__init__.py,sha256=-mzYkRsaRNa_dfTckYkKVFSR8h8a3ihEiPJDU_tAmDo,672
|
|
32
|
-
trilogy/core/processing/node_generators/basic_node.py,sha256=qsQ8HegQ2qOSpXFleq7yHJ-rYfF6XQGCC7h2pC-t1kQ,2878
|
|
33
|
-
trilogy/core/processing/node_generators/common.py,sha256=eslHTTPFTkmwHwKIuUsbFn54jxj-Avtt-QScqtNwzdg,8945
|
|
34
|
-
trilogy/core/processing/node_generators/filter_node.py,sha256=Vz9Rb67e1dfZgnliekwwLeDPVkthMbdrnrKRdz7J1ik,7654
|
|
35
|
-
trilogy/core/processing/node_generators/group_node.py,sha256=r54IVEhXW-tzod6uEHIQObrxgQt6aNySk5emWkWyqCU,4938
|
|
36
|
-
trilogy/core/processing/node_generators/group_to_node.py,sha256=R9i_wHipxjXJyfYEwfeTw2EPpuanXVA327XyfcP2tBg,2537
|
|
37
|
-
trilogy/core/processing/node_generators/multiselect_node.py,sha256=Prn0tWu6gpxyP1tJywVoMG6YAKB8kVRRpPMYdqnl6SE,6583
|
|
38
|
-
trilogy/core/processing/node_generators/node_merge_node.py,sha256=dIEv5P2MTViAES2MzqJgccYzM3HldjHrQYFwH00cqyc,14003
|
|
39
|
-
trilogy/core/processing/node_generators/rowset_node.py,sha256=KtdN6t2xM8CJxobc4aQX4W8uX98U6IabeuBF_FtBLR4,4583
|
|
40
|
-
trilogy/core/processing/node_generators/select_merge_node.py,sha256=zVPSYzhl-jSMobL7L1JauG03yNMkhKp0-tOVXiuC0Vo,12690
|
|
41
|
-
trilogy/core/processing/node_generators/select_node.py,sha256=xTCWOoucRPBWkTccm5wepidhuZix-wd0YXWyOsy8nLs,1795
|
|
42
|
-
trilogy/core/processing/node_generators/unnest_node.py,sha256=cZ26CN338CBnd6asML1OBUtNcDzmNlFpY0Vnade4yrc,2256
|
|
43
|
-
trilogy/core/processing/node_generators/window_node.py,sha256=Ywb2K0T5Ym_Y4XStzIE2fuWV1fW2dp5eQ2hXVFTLsGM,3511
|
|
44
|
-
trilogy/core/processing/nodes/__init__.py,sha256=qS5EJDRwwIrCEfS7ibCA2ESE0RPzsAIii1UWd_wNsHA,4760
|
|
45
|
-
trilogy/core/processing/nodes/base_node.py,sha256=sc3HrXkWk-xpsAQ7B7ltX1ZejYAkqFiv8Ei8Jg5VGkQ,15579
|
|
46
|
-
trilogy/core/processing/nodes/filter_node.py,sha256=GfZ9eghpFDI-s7iQP2UqTljCmn25LT_T5TAxDlh7PkQ,2343
|
|
47
|
-
trilogy/core/processing/nodes/group_node.py,sha256=PrBHaGq_f8RmokUw9lXLGJ5YbjdP77P7Ag0pgR6e2cU,7293
|
|
48
|
-
trilogy/core/processing/nodes/merge_node.py,sha256=W3eCjmJbs8Wfw7Y5AgIY2pP-ntPCrrMe11UG-QGJvA8,14835
|
|
49
|
-
trilogy/core/processing/nodes/select_node_v2.py,sha256=7WoFxeGEAzhpS4y4Zw2nH2tt7OzdlLfMvDFoLF_vb4Y,8108
|
|
50
|
-
trilogy/core/processing/nodes/unnest_node.py,sha256=mAmFluzm2yeeiQ6NfIB7BU_8atRGh-UJfPf9ROwbhr8,2152
|
|
51
|
-
trilogy/core/processing/nodes/window_node.py,sha256=ro0QfMFi4ZmIn5Q4D0M_vJWfnHH_C0MN7XkVkx8Gygg,1214
|
|
52
|
-
trilogy/dialect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
53
|
-
trilogy/dialect/base.py,sha256=YyJy20CNJfOmuHg-WhYEwIamJzAQxb48_lqghriTm8c,36261
|
|
54
|
-
trilogy/dialect/bigquery.py,sha256=15KJ-cOpBlk9O7FPviPgmg8xIydJeKx7WfmL3SSsPE8,2953
|
|
55
|
-
trilogy/dialect/common.py,sha256=eqJi_Si1iyb2sV0siTf8g8JOHueWu6RkdtQZtutKazk,3826
|
|
56
|
-
trilogy/dialect/config.py,sha256=tLVEMctaTDhUgARKXUNfHUcIolGaALkQ0RavUvXAY4w,2994
|
|
57
|
-
trilogy/dialect/duckdb.py,sha256=_0a5HBU8zRNtZj7YED3ju4fHXRYG9jNeKwnlZwUDvwI,3419
|
|
58
|
-
trilogy/dialect/enums.py,sha256=4NdpsydBpDn6jnh0JzFz5VvQEtnShErWtWHVyT6TNpw,3948
|
|
59
|
-
trilogy/dialect/postgres.py,sha256=ev1RJZsC8BB3vJSxJ4q-TTYqZ4Hk1NXUtuRkLrQEBX0,3254
|
|
60
|
-
trilogy/dialect/presto.py,sha256=2Rs53UfPxKU0rJTcEbiS-Lxm-CDiqUGojh7yRpQgyRE,3416
|
|
61
|
-
trilogy/dialect/snowflake.py,sha256=_Bf4XO7-nImMv9XCSsTfVM3g2f_KHdO17VTa9J-HgSM,2989
|
|
62
|
-
trilogy/dialect/sql_server.py,sha256=owUZbMFrooYIMj1DSLstPWxPO7K7WAUEWNvDKM-DMt0,3118
|
|
63
|
-
trilogy/hooks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
64
|
-
trilogy/hooks/base_hook.py,sha256=Xkb-A2qCHozYjum0A36zOy5PwTVwrP3NLDF0U2GpgHo,1100
|
|
65
|
-
trilogy/hooks/graph_hook.py,sha256=onHvMQPwj_KOS3HOTpRFiy7QLLKAiycq2MzJ_Q0Oh5Y,2467
|
|
66
|
-
trilogy/hooks/query_debugger.py,sha256=787umJjdGA057DCC714dqFstzJRUbwmz3MNr66IdpQI,4404
|
|
67
|
-
trilogy/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
68
|
-
trilogy/parsing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
69
|
-
trilogy/parsing/common.py,sha256=3kly4cH36F_8nwR1evKB5_yk1ezEtwwoeav4PrHUJ6o,10417
|
|
70
|
-
trilogy/parsing/config.py,sha256=Z-DaefdKhPDmSXLgg5V4pebhSB0h590vI0_VtHnlukI,111
|
|
71
|
-
trilogy/parsing/exceptions.py,sha256=92E5i2frv5hj9wxObJZsZqj5T6bglvPzvdvco_vW1Zk,38
|
|
72
|
-
trilogy/parsing/helpers.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
73
|
-
trilogy/parsing/parse_engine.py,sha256=fWE_0n30ecBdlT6OvAZL5DYJRs-q2MiD-m8wqxQ_9XE,65201
|
|
74
|
-
trilogy/parsing/render.py,sha256=-qqpXQg4yHcv284Vosjnsc_vrPveH6oaYbeCd3ZSvs0,15682
|
|
75
|
-
trilogy/parsing/trilogy.lark,sha256=B6NM3-rBHtYB_WSEti0DiS8Z-I8YH3kZU47xNzQvBx4,12389
|
|
76
|
-
trilogy/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
77
|
-
trilogy/scripts/trilogy.py,sha256=PHxvv6f2ODv0esyyhWxlARgra8dVhqQhYl0lTrSyVNo,3729
|
|
78
|
-
pytrilogy-0.0.2.47.dist-info/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
|
|
79
|
-
pytrilogy-0.0.2.47.dist-info/METADATA,sha256=Mb0qndiqtvzvG5pNpM-PE3qSZKQmtKa-Gdsv5CDdOFc,8426
|
|
80
|
-
pytrilogy-0.0.2.47.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
81
|
-
pytrilogy-0.0.2.47.dist-info/entry_points.txt,sha256=0petKryjvvtEfTlbZC1AuMFumH_WQ9v8A19LvoS6G6c,54
|
|
82
|
-
pytrilogy-0.0.2.47.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
|
|
83
|
-
pytrilogy-0.0.2.47.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|