pytrilogy 0.0.2.46__py3-none-any.whl → 0.0.2.48__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.46.dist-info → pytrilogy-0.0.2.48.dist-info}/METADATA +1 -1
- pytrilogy-0.0.2.48.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 +448 -394
- 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 +40 -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 +9 -8
- 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 +17 -13
- trilogy/core/processing/nodes/filter_node.py +3 -4
- trilogy/core/processing/nodes/group_node.py +8 -10
- trilogy/core/processing/nodes/merge_node.py +11 -11
- trilogy/core/processing/nodes/select_node_v2.py +8 -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 +37 -40
- trilogy/core/query_processor.py +68 -44
- 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 +124 -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.46.dist-info/RECORD +0 -83
- {pytrilogy-0.0.2.46.dist-info → pytrilogy-0.0.2.48.dist-info}/LICENSE.md +0 -0
- {pytrilogy-0.0.2.46.dist-info → pytrilogy-0.0.2.48.dist-info}/WHEEL +0 -0
- {pytrilogy-0.0.2.46.dist-info → pytrilogy-0.0.2.48.dist-info}/entry_points.txt +0 -0
- {pytrilogy-0.0.2.46.dist-info → pytrilogy-0.0.2.48.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:
|
|
@@ -604,7 +606,6 @@ class ParseToObjects(Transformer):
|
|
|
604
606
|
|
|
605
607
|
@v_args(meta=True)
|
|
606
608
|
def concept(self, meta: Meta, args) -> ConceptDeclarationStatement:
|
|
607
|
-
|
|
608
609
|
if isinstance(args[0], Concept):
|
|
609
610
|
concept: Concept = args[0]
|
|
610
611
|
else:
|
|
@@ -680,7 +681,6 @@ class ParseToObjects(Transformer):
|
|
|
680
681
|
|
|
681
682
|
@v_args(meta=True)
|
|
682
683
|
def select_transform(self, meta: Meta, args) -> ConceptTransform:
|
|
683
|
-
|
|
684
684
|
output: str = args[1]
|
|
685
685
|
transformation = unwrap_transformation(args[0])
|
|
686
686
|
lookup, namespace, output, parent = parse_concept_reference(
|
|
@@ -712,7 +712,6 @@ class ParseToObjects(Transformer):
|
|
|
712
712
|
else:
|
|
713
713
|
raise SyntaxError("Invalid transformation")
|
|
714
714
|
|
|
715
|
-
self.environment.add_concept(concept, meta=meta)
|
|
716
715
|
return ConceptTransform(function=transformation, output=concept)
|
|
717
716
|
|
|
718
717
|
@v_args(meta=True)
|
|
@@ -761,7 +760,6 @@ class ParseToObjects(Transformer):
|
|
|
761
760
|
return Ordering(base)
|
|
762
761
|
|
|
763
762
|
def order_list(self, args):
|
|
764
|
-
|
|
765
763
|
def handle_order_item(x, namespace: str):
|
|
766
764
|
if not isinstance(x, Concept):
|
|
767
765
|
x = arbitrary_to_concept(
|
|
@@ -843,7 +841,6 @@ class ParseToObjects(Transformer):
|
|
|
843
841
|
|
|
844
842
|
@v_args(meta=True)
|
|
845
843
|
def copy_statement(self, meta: Meta, args) -> CopyStatement:
|
|
846
|
-
|
|
847
844
|
return CopyStatement(
|
|
848
845
|
target=args[1],
|
|
849
846
|
target_type=args[0],
|
|
@@ -959,7 +956,7 @@ class ParseToObjects(Transformer):
|
|
|
959
956
|
|
|
960
957
|
@v_args(meta=True)
|
|
961
958
|
def multi_select_statement(self, meta: Meta, args) -> MultiSelectStatement:
|
|
962
|
-
selects = []
|
|
959
|
+
selects: list[SelectStatement] = []
|
|
963
960
|
align: AlignClause | None = None
|
|
964
961
|
limit: int | None = None
|
|
965
962
|
order_by: OrderBy | None = None
|
|
@@ -978,6 +975,10 @@ class ParseToObjects(Transformer):
|
|
|
978
975
|
|
|
979
976
|
assert align
|
|
980
977
|
assert align is not None
|
|
978
|
+
base_local: EnvironmentConceptDict = selects[0].local_concepts
|
|
979
|
+
for select in selects[1:]:
|
|
980
|
+
for k, v in select.local_concepts.items():
|
|
981
|
+
base_local[k] = v
|
|
981
982
|
multi = MultiSelectStatement(
|
|
982
983
|
selects=selects,
|
|
983
984
|
align=align,
|
|
@@ -986,6 +987,7 @@ class ParseToObjects(Transformer):
|
|
|
986
987
|
order_by=order_by,
|
|
987
988
|
limit=limit,
|
|
988
989
|
meta=Metadata(line_number=meta.line),
|
|
990
|
+
local_concepts=base_local,
|
|
989
991
|
)
|
|
990
992
|
for concept in multi.derived_concepts:
|
|
991
993
|
self.environment.add_concept(concept, meta=meta)
|
|
@@ -1019,34 +1021,55 @@ class ParseToObjects(Transformer):
|
|
|
1019
1021
|
order_by=order_by,
|
|
1020
1022
|
meta=Metadata(line_number=meta.line),
|
|
1021
1023
|
)
|
|
1022
|
-
for
|
|
1023
|
-
#
|
|
1024
|
-
#
|
|
1025
|
-
#
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1024
|
+
for parse_pass in [1, 2]:
|
|
1025
|
+
# the first pass will result in all concepts being defined
|
|
1026
|
+
# the second will get grains appropriately
|
|
1027
|
+
# 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
|
|
1028
|
+
# until after the first pass, and so don't know the grain of a
|
|
1029
|
+
nselect = []
|
|
1030
|
+
for item in select_items:
|
|
1031
|
+
# we don't know the grain of an aggregate at assignment time
|
|
1032
|
+
# so rebuild at this point in the tree
|
|
1033
|
+
# TODO: simplify
|
|
1034
|
+
if isinstance(item.content, ConceptTransform):
|
|
1035
|
+
new_concept = item.content.output.with_select_context(
|
|
1036
|
+
output.local_concepts,
|
|
1037
|
+
output.grain,
|
|
1038
|
+
environment=self.environment,
|
|
1039
|
+
)
|
|
1040
|
+
output.local_concepts[new_concept.address] = new_concept
|
|
1041
|
+
item.content.output = new_concept
|
|
1042
|
+
if parse_pass == 2 and CONFIG.select_as_definition:
|
|
1043
|
+
self.environment.add_concept(new_concept)
|
|
1044
|
+
elif isinstance(item.content, UndefinedConcept):
|
|
1045
|
+
self.environment.concepts.raise_undefined(
|
|
1046
|
+
item.content.address,
|
|
1047
|
+
line_no=item.content.metadata.line_number,
|
|
1048
|
+
file=self.token_address,
|
|
1049
|
+
)
|
|
1050
|
+
elif isinstance(item.content, Concept):
|
|
1051
|
+
# Sometimes cached values here don't have the latest info
|
|
1052
|
+
# but we can't just use environment, as it might not have the right grain.
|
|
1053
|
+
item.content = item.content.with_select_context(
|
|
1054
|
+
output.local_concepts,
|
|
1055
|
+
output.grain,
|
|
1056
|
+
environment=self.environment,
|
|
1057
|
+
)
|
|
1058
|
+
output.local_concepts[item.content.address] = item.content
|
|
1059
|
+
nselect.append(item)
|
|
1040
1060
|
if order_by:
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1061
|
+
output.order_by = order_by.with_select_context(
|
|
1062
|
+
local_concepts=output.local_concepts,
|
|
1063
|
+
grain=output.grain,
|
|
1064
|
+
environment=self.environment,
|
|
1065
|
+
)
|
|
1066
|
+
if output.having_clause:
|
|
1067
|
+
output.having_clause = output.having_clause.with_select_context(
|
|
1068
|
+
local_concepts=output.local_concepts,
|
|
1069
|
+
grain=output.grain,
|
|
1070
|
+
environment=self.environment,
|
|
1071
|
+
)
|
|
1072
|
+
output.validate_syntax(self.environment)
|
|
1050
1073
|
return output
|
|
1051
1074
|
|
|
1052
1075
|
@v_args(meta=True)
|
|
@@ -1126,7 +1149,6 @@ class ParseToObjects(Transformer):
|
|
|
1126
1149
|
return args[0]
|
|
1127
1150
|
|
|
1128
1151
|
def struct_lit(self, args):
|
|
1129
|
-
|
|
1130
1152
|
zipped = dict(zip(args[::2], args[1::2]))
|
|
1131
1153
|
types = [arg_to_datatype(x) for x in args[1::2]]
|
|
1132
1154
|
return Function(
|
|
@@ -1422,10 +1444,23 @@ class ParseToObjects(Transformer):
|
|
|
1422
1444
|
output_datatype=DataType.STRING,
|
|
1423
1445
|
output_purpose=Purpose.PROPERTY,
|
|
1424
1446
|
valid_inputs={DataType.STRING},
|
|
1425
|
-
arg_count
|
|
1447
|
+
arg_count=-1,
|
|
1426
1448
|
# output_grain=args[0].grain,
|
|
1427
1449
|
)
|
|
1428
1450
|
|
|
1451
|
+
@v_args(meta=True)
|
|
1452
|
+
def union(self, meta, args):
|
|
1453
|
+
args = process_function_args(args, meta=meta, environment=self.environment)
|
|
1454
|
+
output_datatype = merge_datatypes([arg_to_datatype(x) for x in args])
|
|
1455
|
+
return Function(
|
|
1456
|
+
operator=FunctionType.UNION,
|
|
1457
|
+
arguments=args,
|
|
1458
|
+
output_datatype=output_datatype,
|
|
1459
|
+
output_purpose=Purpose.KEY,
|
|
1460
|
+
valid_inputs={*DataType},
|
|
1461
|
+
arg_count=-1,
|
|
1462
|
+
)
|
|
1463
|
+
|
|
1429
1464
|
@v_args(meta=True)
|
|
1430
1465
|
def like(self, meta, args):
|
|
1431
1466
|
args = process_function_args(args, meta=meta, environment=self.environment)
|
|
@@ -1945,6 +1980,7 @@ def parse_text(text: str, environment: Optional[Environment] = None) -> Tuple[
|
|
|
1945
1980
|
# this will reset fail on missing
|
|
1946
1981
|
pass_two = parser.hydrate_missing()
|
|
1947
1982
|
output = [v for v in pass_two if v]
|
|
1983
|
+
environment.concepts.fail_on_missing = True
|
|
1948
1984
|
except VisitError as e:
|
|
1949
1985
|
unpack_visit_error(e)
|
|
1950
1986
|
# 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=q-cYTIW_OeTndnX4REcP9y6FQJIbng3ilR-7zaKPUyc,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=WxmOgW0cTUgcBVu_gLPUwA9j3KWYPH5FsxKzBSJukEg,164085
|
|
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.46.dist-info/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
|
|
79
|
-
pytrilogy-0.0.2.46.dist-info/METADATA,sha256=L7_5Dv6L1KqiOvLlUnSRzmGZajKdmZ3p_TMYt2Y5iq8,8426
|
|
80
|
-
pytrilogy-0.0.2.46.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
81
|
-
pytrilogy-0.0.2.46.dist-info/entry_points.txt,sha256=0petKryjvvtEfTlbZC1AuMFumH_WQ9v8A19LvoS6G6c,54
|
|
82
|
-
pytrilogy-0.0.2.46.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
|
|
83
|
-
pytrilogy-0.0.2.46.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|