pytrilogy 0.0.2.46__tar.gz → 0.0.2.48__tar.gz
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/pytrilogy.egg-info → pytrilogy-0.0.2.48}/PKG-INFO +1 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/pyproject.toml +1 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48/pytrilogy.egg-info}/PKG-INFO +1 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/pytrilogy.egg-info/SOURCES.txt +2 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_derived_concepts.py +1 -4
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_discovery_nodes.py +2 -2
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_enums.py +1 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_environment.py +19 -3
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_executor.py +2 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_functions.py +6 -5
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_imports.py +2 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_metadata.py +2 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_models.py +16 -15
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_multi_join_assignments.py +1 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_parse_engine.py +6 -4
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_parsing.py +15 -20
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_partial_handling.py +8 -10
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_query_processing.py +2 -2
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_select.py +33 -4
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_statements.py +3 -2
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_undefined_concept.py +1 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_where_clause.py +2 -2
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/__init__.py +2 -2
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/constants.py +4 -2
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/enums.py +7 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/env_processor.py +1 -2
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/environment_helpers.py +5 -5
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/functions.py +11 -10
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/internal.py +2 -3
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/models.py +448 -394
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/optimization.py +37 -21
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/optimizations/base_optimization.py +6 -6
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/optimizations/inline_constant.py +7 -4
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/optimizations/inline_datasource.py +14 -5
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/optimizations/predicate_pushdown.py +20 -10
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/concept_strategies_v3.py +40 -24
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/graph_utils.py +2 -3
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/node_generators/__init__.py +7 -5
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/node_generators/basic_node.py +4 -4
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/node_generators/common.py +10 -11
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/node_generators/filter_node.py +7 -9
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/node_generators/group_node.py +10 -11
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/node_generators/multiselect_node.py +10 -12
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/node_generators/node_merge_node.py +7 -9
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/node_generators/rowset_node.py +9 -8
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/node_generators/select_merge_node.py +11 -10
- pytrilogy-0.0.2.48/trilogy/core/processing/node_generators/union_node.py +75 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/node_generators/unnest_node.py +2 -3
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/node_generators/window_node.py +3 -4
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/nodes/__init__.py +9 -5
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/nodes/base_node.py +17 -13
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/nodes/filter_node.py +3 -4
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/nodes/group_node.py +8 -10
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/nodes/merge_node.py +11 -11
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/nodes/select_node_v2.py +8 -9
- pytrilogy-0.0.2.48/trilogy/core/processing/nodes/union_node.py +50 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/nodes/unnest_node.py +2 -3
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/nodes/window_node.py +2 -3
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/utility.py +37 -40
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/query_processor.py +68 -44
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/dialect/base.py +95 -53
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/dialect/bigquery.py +2 -3
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/dialect/common.py +5 -4
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/dialect/config.py +0 -2
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/dialect/duckdb.py +2 -2
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/dialect/enums.py +5 -5
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/dialect/postgres.py +2 -2
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/dialect/presto.py +3 -4
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/dialect/snowflake.py +2 -2
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/dialect/sql_server.py +3 -4
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/engine.py +2 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/executor.py +43 -30
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/hooks/base_hook.py +5 -4
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/hooks/graph_hook.py +2 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/hooks/query_debugger.py +18 -8
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/parsing/common.py +15 -20
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/parsing/parse_engine.py +124 -88
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/parsing/render.py +32 -35
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/parsing/trilogy.lark +8 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/scripts/trilogy.py +6 -4
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/utility.py +1 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/LICENSE.md +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/README.md +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/pytrilogy.egg-info/dependency_links.txt +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/pytrilogy.egg-info/entry_points.txt +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/pytrilogy.egg-info/requires.txt +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/pytrilogy.egg-info/top_level.txt +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/setup.cfg +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/setup.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_datatypes.py +1 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_declarations.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/tests/test_show.py +1 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/compiler.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/__init__.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/constants.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/ergonomics.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/exceptions.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/graph_models.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/optimizations/__init__.py +1 -1
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/__init__.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/node_generators/group_to_node.py +5 -5
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/core/processing/node_generators/select_node.py +5 -5
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/dialect/__init__.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/hooks/__init__.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/metadata/__init__.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/parser.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/parsing/__init__.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/parsing/config.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/parsing/exceptions.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/parsing/helpers.py +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/py.typed +0 -0
- {pytrilogy-0.0.2.46 → pytrilogy-0.0.2.48}/trilogy/scripts/__init__.py +0 -0
|
@@ -70,6 +70,7 @@ trilogy/core/processing/node_generators/node_merge_node.py
|
|
|
70
70
|
trilogy/core/processing/node_generators/rowset_node.py
|
|
71
71
|
trilogy/core/processing/node_generators/select_merge_node.py
|
|
72
72
|
trilogy/core/processing/node_generators/select_node.py
|
|
73
|
+
trilogy/core/processing/node_generators/union_node.py
|
|
73
74
|
trilogy/core/processing/node_generators/unnest_node.py
|
|
74
75
|
trilogy/core/processing/node_generators/window_node.py
|
|
75
76
|
trilogy/core/processing/nodes/__init__.py
|
|
@@ -78,6 +79,7 @@ trilogy/core/processing/nodes/filter_node.py
|
|
|
78
79
|
trilogy/core/processing/nodes/group_node.py
|
|
79
80
|
trilogy/core/processing/nodes/merge_node.py
|
|
80
81
|
trilogy/core/processing/nodes/select_node_v2.py
|
|
82
|
+
trilogy/core/processing/nodes/union_node.py
|
|
81
83
|
trilogy/core/processing/nodes/unnest_node.py
|
|
82
84
|
trilogy/core/processing/nodes/window_node.py
|
|
83
85
|
trilogy/dialect/__init__.py
|
|
@@ -33,9 +33,7 @@ def test_filtering_where_on_derived_aggregate(test_environment):
|
|
|
33
33
|
)
|
|
34
34
|
except Exception as e:
|
|
35
35
|
exception = True
|
|
36
|
-
assert str(e)
|
|
37
|
-
"Cannot reference an aggregate derived in the select (local.filtered_cst) in the same statement where clause"
|
|
38
|
-
)
|
|
36
|
+
assert "Undefined concept: local.filtered_cst" in str(e)
|
|
39
37
|
assert exception, "should have an exception"
|
|
40
38
|
|
|
41
39
|
|
|
@@ -68,7 +66,6 @@ def test_filtering_having_on_unincluded_value(test_environment):
|
|
|
68
66
|
|
|
69
67
|
|
|
70
68
|
def test_filtering_valid(test_environment):
|
|
71
|
-
|
|
72
69
|
env, _ = parse(
|
|
73
70
|
"""key x int;
|
|
74
71
|
property x.cost float;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
from trilogy.core.constants import ALL_ROWS_CONCEPT, INTERNAL_NAMESPACE
|
|
2
|
+
from trilogy.core.models import Environment, Grain
|
|
1
3
|
from trilogy.core.processing.concept_strategies_v3 import (
|
|
2
4
|
GroupNode,
|
|
3
5
|
search_concepts,
|
|
4
6
|
)
|
|
5
7
|
from trilogy.core.processing.node_generators import gen_group_node
|
|
6
|
-
from trilogy.core.models import Environment, Grain
|
|
7
|
-
from trilogy.core.constants import INTERNAL_NAMESPACE, ALL_ROWS_CONCEPT
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def test_group_node(test_environment, test_environment_graph):
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
from trilogy.core.models import Environment
|
|
2
1
|
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from trilogy import Dialects
|
|
3
4
|
from trilogy.core.enums import Modifier
|
|
4
5
|
from trilogy.core.exceptions import UndefinedConceptException
|
|
6
|
+
from trilogy.core.models import Environment
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
def test_environment_serialization(test_environment: Environment):
|
|
@@ -18,14 +20,12 @@ def test_environment_serialization(test_environment: Environment):
|
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
def test_environment_from_path():
|
|
21
|
-
|
|
22
23
|
env = Environment.from_file(Path(__file__).parent / "test_env.preql")
|
|
23
24
|
|
|
24
25
|
assert "local.id" in env.concepts
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
def test_environment_invalid():
|
|
28
|
-
|
|
29
29
|
env = Environment()
|
|
30
30
|
env.concepts.fail_on_missing = False
|
|
31
31
|
x = env.concepts["abc"]
|
|
@@ -85,3 +85,19 @@ key order_id int;
|
|
|
85
85
|
assert x.modifiers == [Modifier.PARTIAL]
|
|
86
86
|
found = True
|
|
87
87
|
assert found
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def test_environment_select_promotion():
|
|
91
|
+
x = Dialects.DUCK_DB.default_executor()
|
|
92
|
+
|
|
93
|
+
results = x.execute_query(
|
|
94
|
+
"""
|
|
95
|
+
const x <- 6;
|
|
96
|
+
|
|
97
|
+
select x+2 as y;
|
|
98
|
+
|
|
99
|
+
select y;
|
|
100
|
+
"""
|
|
101
|
+
).fetchall()
|
|
102
|
+
|
|
103
|
+
assert results[0].y == 8
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
# from trilogy.compiler import compile
|
|
2
|
+
from logging import INFO
|
|
3
|
+
|
|
2
4
|
from pytest import raises
|
|
3
5
|
|
|
6
|
+
from trilogy.constants import logger
|
|
7
|
+
from trilogy.core.enums import Purpose, PurposeLineage
|
|
4
8
|
from trilogy.core.exceptions import InvalidSyntaxException
|
|
5
|
-
from trilogy.core.models import DataType,
|
|
9
|
+
from trilogy.core.models import DataType, Environment, ListType, SelectStatement
|
|
6
10
|
from trilogy.core.query_processor import process_query
|
|
7
11
|
from trilogy.dialect.base import BaseDialect
|
|
8
12
|
from trilogy.dialect.bigquery import BigqueryDialect
|
|
9
13
|
from trilogy.dialect.duckdb import DuckDBDialect
|
|
10
|
-
from trilogy.dialect.sql_server import SqlServerDialect
|
|
11
14
|
from trilogy.dialect.snowflake import SnowflakeDialect
|
|
15
|
+
from trilogy.dialect.sql_server import SqlServerDialect
|
|
12
16
|
from trilogy.parser import parse
|
|
13
|
-
from logging import INFO
|
|
14
|
-
from trilogy.constants import logger
|
|
15
|
-
from trilogy.core.enums import PurposeLineage, Purpose
|
|
16
17
|
|
|
17
18
|
logger.setLevel(INFO)
|
|
18
19
|
|
|
@@ -1,25 +1,26 @@
|
|
|
1
|
-
from
|
|
1
|
+
from copy import deepcopy
|
|
2
|
+
|
|
3
|
+
from trilogy import parse
|
|
4
|
+
from trilogy.core.enums import BooleanOperator, ComparisonOperator, JoinType, Purpose
|
|
2
5
|
from trilogy.core.models import (
|
|
3
6
|
CTE,
|
|
4
|
-
Grain,
|
|
5
|
-
QueryDatasource,
|
|
6
|
-
Conditional,
|
|
7
|
-
SelectStatement,
|
|
8
|
-
Environment,
|
|
9
7
|
Address,
|
|
10
|
-
|
|
8
|
+
AggregateWrapper,
|
|
11
9
|
BaseJoin,
|
|
12
10
|
Comparison,
|
|
13
|
-
Join,
|
|
14
|
-
CTEConceptPair,
|
|
15
11
|
Concept,
|
|
16
|
-
|
|
12
|
+
Conditional,
|
|
13
|
+
CTEConceptPair,
|
|
14
|
+
DataType,
|
|
15
|
+
Environment,
|
|
16
|
+
Grain,
|
|
17
|
+
Join,
|
|
18
|
+
QueryDatasource,
|
|
17
19
|
RowsetItem,
|
|
20
|
+
SelectStatement,
|
|
18
21
|
TupleWrapper,
|
|
19
|
-
|
|
22
|
+
UndefinedConcept,
|
|
20
23
|
)
|
|
21
|
-
from trilogy import parse
|
|
22
|
-
from copy import deepcopy
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
def test_cte_merge(test_environment, test_environment_graph):
|
|
@@ -162,9 +163,9 @@ def test_undefined(test_environment: Environment):
|
|
|
162
163
|
environment=test_environment.concepts,
|
|
163
164
|
)
|
|
164
165
|
|
|
165
|
-
y = x.with_select_context(Grain(components=[test_environment.concepts["order_id"]]))
|
|
166
|
+
# y = x.with_select_context({}, Grain(components=[test_environment.concepts["order_id"]]), test_environment)
|
|
166
167
|
|
|
167
|
-
assert y.grain == Grain(components=[test_environment.concepts["order_id"]])
|
|
168
|
+
# assert y.grain == Grain(components=[test_environment.concepts["order_id"]])
|
|
168
169
|
|
|
169
170
|
z = x.with_default_grain()
|
|
170
171
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
from
|
|
1
|
+
from pytest import raises
|
|
2
|
+
|
|
2
3
|
from trilogy import Environment
|
|
3
4
|
from trilogy.core.exceptions import UndefinedConceptException
|
|
4
|
-
from
|
|
5
|
+
from trilogy.parsing.parse_engine import PARSER, ParseToObjects, unpack_visit_error
|
|
5
6
|
|
|
6
7
|
TEXT = """
|
|
7
8
|
const a <- 1;
|
|
@@ -18,10 +19,11 @@ def test_parser():
|
|
|
18
19
|
x = ParseToObjects(environment=env)
|
|
19
20
|
x.environment.concepts.fail_on_missing = False
|
|
20
21
|
x.set_text(TEXT)
|
|
21
|
-
|
|
22
|
-
x.transform(tokens)
|
|
22
|
+
|
|
23
23
|
failed = False
|
|
24
24
|
try:
|
|
25
|
+
tokens = PARSER.parse(TEXT)
|
|
26
|
+
x.transform(tokens)
|
|
25
27
|
x.hydrate_missing()
|
|
26
28
|
except Exception as e:
|
|
27
29
|
failed = True
|
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
from trilogy
|
|
1
|
+
from trilogy import Dialects
|
|
2
|
+
from trilogy.constants import MagicConstants
|
|
3
|
+
from trilogy.core.enums import BooleanOperator, ComparisonOperator, Purpose
|
|
4
|
+
from trilogy.core.functions import argument_to_purpose, function_args_to_output_purpose
|
|
2
5
|
from trilogy.core.models import (
|
|
6
|
+
Comparison,
|
|
7
|
+
Datasource,
|
|
3
8
|
DataType,
|
|
9
|
+
Environment,
|
|
4
10
|
ProcessedQuery,
|
|
5
|
-
ShowStatement,
|
|
6
11
|
SelectStatement,
|
|
7
|
-
|
|
8
|
-
Comparison,
|
|
12
|
+
ShowStatement,
|
|
9
13
|
TupleWrapper,
|
|
10
|
-
Datasource,
|
|
11
14
|
)
|
|
12
|
-
from trilogy.
|
|
15
|
+
from trilogy.dialect.base import BaseDialect
|
|
13
16
|
from trilogy.parsing.parse_engine import (
|
|
14
17
|
arg_to_datatype,
|
|
15
18
|
parse_text,
|
|
16
19
|
)
|
|
17
|
-
from trilogy.constants import MagicConstants
|
|
18
|
-
from trilogy.dialect.base import BaseDialect
|
|
19
|
-
from trilogy.core.enums import BooleanOperator
|
|
20
|
-
from trilogy import Dialects
|
|
21
20
|
|
|
22
21
|
|
|
23
22
|
def test_in():
|
|
@@ -178,7 +177,9 @@ select
|
|
|
178
177
|
"""
|
|
179
178
|
)
|
|
180
179
|
|
|
181
|
-
for name in [
|
|
180
|
+
for name in [
|
|
181
|
+
"name_alphabetical",
|
|
182
|
+
]:
|
|
182
183
|
assert f"local.{name}" in env.concepts
|
|
183
184
|
assert env.concepts[name].purpose == Purpose.PROPERTY
|
|
184
185
|
assert env.concepts[name].keys == (env.concepts["id"],)
|
|
@@ -206,7 +207,6 @@ select
|
|
|
206
207
|
|
|
207
208
|
|
|
208
209
|
def test_output_purpose():
|
|
209
|
-
|
|
210
210
|
env, parsed = parse_text(
|
|
211
211
|
"""key id int;
|
|
212
212
|
property id.name string;
|
|
@@ -219,8 +219,10 @@ rowset test<- select
|
|
|
219
219
|
row_number id order by name asc -> name_alphabetical_2
|
|
220
220
|
;
|
|
221
221
|
|
|
222
|
+
auto test_name_count <- count(test.name);
|
|
223
|
+
|
|
222
224
|
select
|
|
223
|
-
|
|
225
|
+
test_name_count;
|
|
224
226
|
"""
|
|
225
227
|
)
|
|
226
228
|
# assert output_purpose == Purpose.METRIC
|
|
@@ -274,7 +276,6 @@ def test_the_comments():
|
|
|
274
276
|
|
|
275
277
|
|
|
276
278
|
def test_purpose_nesting():
|
|
277
|
-
|
|
278
279
|
env, parsed = parse_text(
|
|
279
280
|
"""key year int;
|
|
280
281
|
"""
|
|
@@ -434,7 +435,6 @@ const labels <- '';
|
|
|
434
435
|
|
|
435
436
|
|
|
436
437
|
def test_struct_attr_access():
|
|
437
|
-
|
|
438
438
|
text = """
|
|
439
439
|
const labels <- struct(a=1, b=2, c=3);
|
|
440
440
|
|
|
@@ -459,7 +459,6 @@ select
|
|
|
459
459
|
|
|
460
460
|
|
|
461
461
|
def test_datasource_colon():
|
|
462
|
-
|
|
463
462
|
text = """
|
|
464
463
|
key x int;
|
|
465
464
|
key y int;
|
|
@@ -502,7 +501,6 @@ select x;
|
|
|
502
501
|
|
|
503
502
|
|
|
504
503
|
def test_datasource_where_equivalent():
|
|
505
|
-
|
|
506
504
|
text = """
|
|
507
505
|
key x int;
|
|
508
506
|
key y int;
|
|
@@ -524,7 +522,6 @@ address `abc:def`
|
|
|
524
522
|
|
|
525
523
|
|
|
526
524
|
def test_datasource_quoted():
|
|
527
|
-
|
|
528
525
|
text = """
|
|
529
526
|
key x int;
|
|
530
527
|
key y int;
|
|
@@ -546,7 +543,6 @@ address `abc:def`
|
|
|
546
543
|
|
|
547
544
|
|
|
548
545
|
def test_datasource_from_persist():
|
|
549
|
-
|
|
550
546
|
text = """
|
|
551
547
|
key x int;
|
|
552
548
|
key y int;
|
|
@@ -575,7 +571,6 @@ where y>10;
|
|
|
575
571
|
|
|
576
572
|
|
|
577
573
|
def test_filter_concise():
|
|
578
|
-
|
|
579
574
|
text = """
|
|
580
575
|
key x int;
|
|
581
576
|
key y int;
|
|
@@ -1,23 +1,21 @@
|
|
|
1
|
-
from trilogy import Executor, Dialects
|
|
2
|
-
|
|
3
1
|
# from trilogy.core.models import Environment
|
|
4
2
|
from sqlalchemy import create_engine
|
|
3
|
+
|
|
4
|
+
from trilogy import Dialects, Executor
|
|
5
|
+
from trilogy.core.enums import Purpose
|
|
5
6
|
from trilogy.core.models import (
|
|
6
|
-
DataType,
|
|
7
|
-
Datasource,
|
|
8
|
-
Concept,
|
|
9
7
|
ColumnAssignment,
|
|
8
|
+
Concept,
|
|
9
|
+
Datasource,
|
|
10
|
+
DataType,
|
|
10
11
|
Environment,
|
|
11
12
|
)
|
|
12
|
-
from trilogy.core.enums import Purpose
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
from trilogy.core.query_processor import generate_graph
|
|
16
|
-
from trilogy.core.processing.nodes import MergeNode
|
|
17
13
|
from trilogy.core.processing.concept_strategies_v3 import search_concepts
|
|
18
14
|
from trilogy.core.processing.node_generators import (
|
|
19
15
|
gen_filter_node,
|
|
20
16
|
)
|
|
17
|
+
from trilogy.core.processing.nodes import MergeNode
|
|
18
|
+
from trilogy.core.query_processor import generate_graph
|
|
21
19
|
from trilogy.hooks.query_debugger import DebuggingHook
|
|
22
20
|
|
|
23
21
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
from trilogy.core.models import
|
|
1
|
+
from trilogy.core.models import Environment, Grain, QueryDatasource, SelectStatement
|
|
2
2
|
from trilogy.core.processing.concept_strategies_v3 import search_concepts
|
|
3
|
-
from trilogy.core.query_processor import
|
|
3
|
+
from trilogy.core.query_processor import get_query_datasources, process_query
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def test_direct_select(test_environment, test_environment_graph):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# from trilogy.compiler import compile
|
|
2
|
-
from trilogy
|
|
3
|
-
from trilogy.core.models import SelectStatement
|
|
2
|
+
from trilogy import Dialects
|
|
3
|
+
from trilogy.core.models import Grain, SelectStatement
|
|
4
4
|
from trilogy.core.query_processor import process_query
|
|
5
5
|
from trilogy.dialect.bigquery import BigqueryDialect
|
|
6
6
|
from trilogy.parser import parse
|
|
@@ -32,6 +32,7 @@ datasource users (
|
|
|
32
32
|
address `bigquery-public-data.stackoverflow.users`
|
|
33
33
|
;
|
|
34
34
|
|
|
35
|
+
auto post_count <- count(post_id);
|
|
35
36
|
|
|
36
37
|
"""
|
|
37
38
|
env, parsed = parse(declarations)
|
|
@@ -40,7 +41,7 @@ datasource users (
|
|
|
40
41
|
# a comment
|
|
41
42
|
user_id,
|
|
42
43
|
about_me,
|
|
43
|
-
|
|
44
|
+
post_count
|
|
44
45
|
;"""
|
|
45
46
|
env, parse_one = parse(q1, environment=env)
|
|
46
47
|
|
|
@@ -54,7 +55,10 @@ datasource users (
|
|
|
54
55
|
env, parse_two = parse(q2, environment=env)
|
|
55
56
|
|
|
56
57
|
select: SelectStatement = parse_two[-1]
|
|
57
|
-
assert
|
|
58
|
+
assert (
|
|
59
|
+
select.grain.components
|
|
60
|
+
== Grain(components=[env.concepts["about_me"]]).components
|
|
61
|
+
)
|
|
58
62
|
|
|
59
63
|
|
|
60
64
|
def test_double_aggregate():
|
|
@@ -147,3 +151,28 @@ def test_having_without_select():
|
|
|
147
151
|
assert "that is not in the select projection in the HAVING clause" in str(e)
|
|
148
152
|
failed = True
|
|
149
153
|
assert failed
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def test_local_select_concepts():
|
|
157
|
+
q1 = """
|
|
158
|
+
|
|
159
|
+
key id int;
|
|
160
|
+
datasource local (
|
|
161
|
+
|
|
162
|
+
id: id
|
|
163
|
+
)
|
|
164
|
+
grain (id)
|
|
165
|
+
query '''
|
|
166
|
+
|
|
167
|
+
SELECT 1 as id
|
|
168
|
+
''';
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
select id + 2 as three;
|
|
172
|
+
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
env, parsed = parse(q1)
|
|
176
|
+
|
|
177
|
+
result = Dialects.DUCK_DB.default_executor(environment=env).execute_text(q1)[-1]
|
|
178
|
+
assert result.fetchone().three == 3
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from trilogy.core.enums import Purpose
|
|
2
2
|
from trilogy.core.exceptions import UndefinedConceptException
|
|
3
|
-
from trilogy.core.models import DataType, EnvironmentConceptDict
|
|
3
|
+
from trilogy.core.models import Concept, DataType, EnvironmentConceptDict
|
|
4
4
|
from trilogy.parser import parse
|
|
5
5
|
|
|
6
6
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# from trilogy.compiler import compile
|
|
2
|
-
from trilogy.core.models import
|
|
2
|
+
from trilogy.core.models import Grain, Parenthetical, SelectStatement
|
|
3
|
+
from trilogy.core.processing.utility import is_scalar_condition
|
|
3
4
|
from trilogy.core.query_processor import process_query
|
|
4
5
|
from trilogy.dialect.base import BaseDialect
|
|
5
6
|
from trilogy.parser import parse
|
|
6
|
-
from trilogy.core.processing.utility import is_scalar_condition
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def test_select_where(test_environment):
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
from trilogy.constants import CONFIG
|
|
1
2
|
from trilogy.core.models import Environment
|
|
2
3
|
from trilogy.dialect.enums import Dialects
|
|
3
4
|
from trilogy.executor import Executor
|
|
4
5
|
from trilogy.parser import parse
|
|
5
|
-
from trilogy.constants import CONFIG
|
|
6
6
|
|
|
7
|
-
__version__ = "0.0.2.
|
|
7
|
+
__version__ = "0.0.2.48"
|
|
8
8
|
|
|
9
9
|
__all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import random
|
|
2
2
|
from dataclasses import dataclass, field
|
|
3
3
|
from enum import Enum
|
|
4
|
-
import
|
|
4
|
+
from logging import getLogger
|
|
5
5
|
|
|
6
6
|
logger = getLogger("trilogy")
|
|
7
7
|
|
|
@@ -44,6 +44,7 @@ class Rendering:
|
|
|
44
44
|
"""Control how the SQL is rendered"""
|
|
45
45
|
|
|
46
46
|
parameters: bool = True
|
|
47
|
+
concise: bool = False
|
|
47
48
|
|
|
48
49
|
|
|
49
50
|
# TODO: support loading from environments
|
|
@@ -56,6 +57,7 @@ class Config:
|
|
|
56
57
|
comments: Comments = field(default_factory=Comments)
|
|
57
58
|
optimizations: Optimizations = field(default_factory=Optimizations)
|
|
58
59
|
rendering: Rendering = field(default_factory=Rendering)
|
|
60
|
+
select_as_definition: bool = True
|
|
59
61
|
|
|
60
62
|
@property
|
|
61
63
|
def show_comments(self) -> bool:
|
|
@@ -29,6 +29,7 @@ class Purpose(Enum):
|
|
|
29
29
|
METRIC = "metric"
|
|
30
30
|
ROWSET = "rowset"
|
|
31
31
|
AUTO = "auto"
|
|
32
|
+
UNKNOWN = "unknown"
|
|
32
33
|
|
|
33
34
|
@classmethod
|
|
34
35
|
def _missing_(cls, value):
|
|
@@ -44,6 +45,7 @@ class PurposeLineage(Enum):
|
|
|
44
45
|
FILTER = "filter"
|
|
45
46
|
CONSTANT = "constant"
|
|
46
47
|
UNNEST = "unnest"
|
|
48
|
+
UNION = "union"
|
|
47
49
|
ROOT = "root"
|
|
48
50
|
ROWSET = "rowset"
|
|
49
51
|
MULTISELECT = "multiselect"
|
|
@@ -113,6 +115,9 @@ class FunctionType(Enum):
|
|
|
113
115
|
|
|
114
116
|
# structural
|
|
115
117
|
UNNEST = "unnest"
|
|
118
|
+
|
|
119
|
+
UNION = "union"
|
|
120
|
+
|
|
116
121
|
ALIAS = "alias"
|
|
117
122
|
|
|
118
123
|
# Generic
|
|
@@ -133,6 +138,7 @@ class FunctionType(Enum):
|
|
|
133
138
|
|
|
134
139
|
# TEXT AND MAYBE MORE
|
|
135
140
|
SPLIT = "split"
|
|
141
|
+
LENGTH = "len"
|
|
136
142
|
|
|
137
143
|
# Math
|
|
138
144
|
DIVIDE = "divide"
|
|
@@ -154,7 +160,6 @@ class FunctionType(Enum):
|
|
|
154
160
|
MAX = "max"
|
|
155
161
|
MIN = "min"
|
|
156
162
|
AVG = "avg"
|
|
157
|
-
LENGTH = "len"
|
|
158
163
|
|
|
159
164
|
# String
|
|
160
165
|
LIKE = "like"
|
|
@@ -299,6 +304,7 @@ class SourceType(Enum):
|
|
|
299
304
|
ROWSET = "rowset"
|
|
300
305
|
MERGE = "merge"
|
|
301
306
|
BASIC = "basic"
|
|
307
|
+
UNION = "union"
|
|
302
308
|
|
|
303
309
|
|
|
304
310
|
class ShowCategory(Enum):
|
|
@@ -3,7 +3,7 @@ from trilogy.core.graph_models import (
|
|
|
3
3
|
concept_to_node,
|
|
4
4
|
datasource_to_node,
|
|
5
5
|
)
|
|
6
|
-
from trilogy.core.models import
|
|
6
|
+
from trilogy.core.models import Concept, Datasource, Environment
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def add_concept(
|
|
@@ -68,7 +68,6 @@ def generate_adhoc_graph(
|
|
|
68
68
|
def generate_graph(
|
|
69
69
|
environment: Environment,
|
|
70
70
|
) -> ReferenceGraph:
|
|
71
|
-
|
|
72
71
|
return generate_adhoc_graph(
|
|
73
72
|
list(environment.concepts.values())
|
|
74
73
|
+ list(environment.alias_origin_lookup.values()),
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
+
from trilogy.constants import DEFAULT_NAMESPACE
|
|
2
|
+
from trilogy.core.enums import ConceptSource, FunctionType, Purpose
|
|
3
|
+
from trilogy.core.functions import AttrAccess
|
|
1
4
|
from trilogy.core.models import (
|
|
2
|
-
DataType,
|
|
3
5
|
Concept,
|
|
6
|
+
DataType,
|
|
4
7
|
Environment,
|
|
5
8
|
Function,
|
|
6
9
|
Metadata,
|
|
7
10
|
StructType,
|
|
8
11
|
)
|
|
9
|
-
from trilogy.
|
|
10
|
-
from trilogy.core.enums import Purpose, FunctionType, ConceptSource
|
|
11
|
-
from trilogy.constants import DEFAULT_NAMESPACE
|
|
12
|
-
from trilogy.parsing.common import process_function_args, arg_to_datatype, Meta
|
|
12
|
+
from trilogy.parsing.common import Meta, arg_to_datatype, process_function_args
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def generate_date_concepts(concept: Concept, environment: Environment):
|