pytrilogy 0.0.2.58__tar.gz → 0.0.3.0__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.58/pytrilogy.egg-info → pytrilogy-0.0.3.0}/PKG-INFO +9 -2
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0/pytrilogy.egg-info}/PKG-INFO +9 -2
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/pytrilogy.egg-info/SOURCES.txt +13 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_datatypes.py +1 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_derived_concepts.py +4 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_discovery_nodes.py +15 -2
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_environment.py +40 -4
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_executor.py +2 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_functions.py +6 -3
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_imports.py +1 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_metadata.py +2 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_models.py +71 -39
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_multi_join_assignments.py +2 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_parse_engine.py +1 -2
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_parsing.py +14 -7
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_partial_handling.py +13 -8
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_query_processing.py +28 -15
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_select.py +40 -9
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_show.py +1 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_statements.py +6 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_undefined_concept.py +3 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_where_clause.py +19 -7
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/__init__.py +2 -2
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/enums.py +1 -7
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/env_processor.py +17 -5
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/environment_helpers.py +11 -25
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/exceptions.py +4 -0
- pytrilogy-0.0.3.0/trilogy/core/functions.py +817 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/graph_models.py +10 -10
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/internal.py +11 -2
- pytrilogy-0.0.3.0/trilogy/core/models/author.py +2110 -0
- pytrilogy-0.0.3.0/trilogy/core/models/build.py +1845 -0
- pytrilogy-0.0.3.0/trilogy/core/models/build_environment.py +151 -0
- pytrilogy-0.0.3.0/trilogy/core/models/core.py +370 -0
- pytrilogy-0.0.3.0/trilogy/core/models/datasource.py +297 -0
- pytrilogy-0.0.3.0/trilogy/core/models/environment.py +696 -0
- pytrilogy-0.0.3.0/trilogy/core/models/execute.py +931 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/optimization.py +14 -16
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/optimizations/base_optimization.py +1 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/optimizations/inline_constant.py +6 -6
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/optimizations/inline_datasource.py +17 -11
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/optimizations/predicate_pushdown.py +17 -16
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/concept_strategies_v3.py +180 -145
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/graph_utils.py +1 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/basic_node.py +19 -18
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/common.py +50 -44
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/filter_node.py +26 -13
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/group_node.py +26 -21
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/group_to_node.py +11 -8
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/multiselect_node.py +60 -43
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/node_merge_node.py +76 -38
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/rowset_node.py +57 -36
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +27 -34
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/select_merge_node.py +161 -64
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/select_node.py +13 -13
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/union_node.py +12 -11
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/unnest_node.py +9 -7
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/window_node.py +19 -16
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/nodes/__init__.py +21 -18
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/nodes/base_node.py +82 -66
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/nodes/filter_node.py +19 -13
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/nodes/group_node.py +50 -35
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/nodes/merge_node.py +45 -36
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/nodes/select_node_v2.py +53 -39
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/nodes/union_node.py +5 -7
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/nodes/unnest_node.py +7 -11
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/nodes/window_node.py +9 -4
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/utility.py +103 -75
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/query_processor.py +65 -47
- pytrilogy-0.0.3.0/trilogy/core/statements/author.py +413 -0
- pytrilogy-0.0.3.0/trilogy/core/statements/common.py +30 -0
- pytrilogy-0.0.3.0/trilogy/core/statements/execute.py +42 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/dialect/base.py +146 -106
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/dialect/common.py +9 -10
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/dialect/duckdb.py +1 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/dialect/enums.py +4 -2
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/dialect/presto.py +1 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/dialect/sql_server.py +1 -1
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/executor.py +44 -32
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/hooks/base_hook.py +6 -4
- pytrilogy-0.0.3.0/trilogy/hooks/query_debugger.py +167 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/parser.py +1 -1
- pytrilogy-0.0.3.0/trilogy/parsing/__init__.py +0 -0
- pytrilogy-0.0.3.0/trilogy/parsing/common.py +618 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/parsing/parse_engine.py +263 -617
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/parsing/render.py +50 -26
- pytrilogy-0.0.3.0/trilogy/py.typed +0 -0
- pytrilogy-0.0.3.0/trilogy/scripts/__init__.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/scripts/trilogy.py +2 -1
- pytrilogy-0.0.2.58/trilogy/core/functions.py +0 -383
- pytrilogy-0.0.2.58/trilogy/core/models.py +0 -4960
- pytrilogy-0.0.2.58/trilogy/hooks/query_debugger.py +0 -150
- pytrilogy-0.0.2.58/trilogy/parsing/common.py +0 -379
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/LICENSE.md +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/README.md +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/pyproject.toml +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/pytrilogy.egg-info/dependency_links.txt +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/pytrilogy.egg-info/entry_points.txt +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/pytrilogy.egg-info/requires.txt +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/pytrilogy.egg-info/top_level.txt +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/setup.cfg +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/setup.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_declarations.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/tests/test_enums.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/compiler.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/constants.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/__init__.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/constants.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/ergonomics.py +0 -0
- {pytrilogy-0.0.2.58/trilogy/core/processing → pytrilogy-0.0.3.0/trilogy/core/models}/__init__.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/optimizations/__init__.py +0 -0
- {pytrilogy-0.0.2.58/trilogy/core/processing/node_generators/select_helpers → pytrilogy-0.0.3.0/trilogy/core/processing}/__init__.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/core/processing/node_generators/__init__.py +0 -0
- {pytrilogy-0.0.2.58/trilogy/dialect → pytrilogy-0.0.3.0/trilogy/core/processing/node_generators/select_helpers}/__init__.py +0 -0
- {pytrilogy-0.0.2.58/trilogy/hooks → pytrilogy-0.0.3.0/trilogy/core/statements}/__init__.py +0 -0
- /pytrilogy-0.0.2.58/trilogy/metadata/__init__.py → /pytrilogy-0.0.3.0/trilogy/core/statements/build.py +0 -0
- {pytrilogy-0.0.2.58/trilogy/parsing → pytrilogy-0.0.3.0/trilogy/dialect}/__init__.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/dialect/bigquery.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/dialect/config.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/dialect/postgres.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/dialect/snowflake.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/engine.py +0 -0
- {pytrilogy-0.0.2.58/trilogy/scripts → pytrilogy-0.0.3.0/trilogy/hooks}/__init__.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/hooks/graph_hook.py +0 -0
- /pytrilogy-0.0.2.58/trilogy/py.typed → /pytrilogy-0.0.3.0/trilogy/metadata/__init__.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/parsing/config.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/parsing/exceptions.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/parsing/helpers.py +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/parsing/trilogy.lark +0 -0
- {pytrilogy-0.0.2.58 → pytrilogy-0.0.3.0}/trilogy/utility.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: pytrilogy
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3.0
|
|
4
4
|
Summary: Declarative, typed query language that compiles to SQL.
|
|
5
5
|
Home-page:
|
|
6
6
|
Author:
|
|
@@ -27,6 +27,13 @@ Provides-Extra: bigquery
|
|
|
27
27
|
Requires-Dist: sqlalchemy-bigquery; extra == "bigquery"
|
|
28
28
|
Provides-Extra: snowflake
|
|
29
29
|
Requires-Dist: snowflake-sqlalchemy; extra == "snowflake"
|
|
30
|
+
Dynamic: author-email
|
|
31
|
+
Dynamic: classifier
|
|
32
|
+
Dynamic: description
|
|
33
|
+
Dynamic: description-content-type
|
|
34
|
+
Dynamic: provides-extra
|
|
35
|
+
Dynamic: requires-dist
|
|
36
|
+
Dynamic: summary
|
|
30
37
|
|
|
31
38
|
## Trilogy
|
|
32
39
|
[](https://trilogydata.dev/)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: pytrilogy
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3.0
|
|
4
4
|
Summary: Declarative, typed query language that compiles to SQL.
|
|
5
5
|
Home-page:
|
|
6
6
|
Author:
|
|
@@ -27,6 +27,13 @@ Provides-Extra: bigquery
|
|
|
27
27
|
Requires-Dist: sqlalchemy-bigquery; extra == "bigquery"
|
|
28
28
|
Provides-Extra: snowflake
|
|
29
29
|
Requires-Dist: snowflake-sqlalchemy; extra == "snowflake"
|
|
30
|
+
Dynamic: author-email
|
|
31
|
+
Dynamic: classifier
|
|
32
|
+
Dynamic: description
|
|
33
|
+
Dynamic: description-content-type
|
|
34
|
+
Dynamic: provides-extra
|
|
35
|
+
Dynamic: requires-dist
|
|
36
|
+
Dynamic: summary
|
|
30
37
|
|
|
31
38
|
## Trilogy
|
|
32
39
|
[](https://trilogydata.dev/)
|
|
@@ -47,9 +47,16 @@ trilogy/core/exceptions.py
|
|
|
47
47
|
trilogy/core/functions.py
|
|
48
48
|
trilogy/core/graph_models.py
|
|
49
49
|
trilogy/core/internal.py
|
|
50
|
-
trilogy/core/models.py
|
|
51
50
|
trilogy/core/optimization.py
|
|
52
51
|
trilogy/core/query_processor.py
|
|
52
|
+
trilogy/core/models/__init__.py
|
|
53
|
+
trilogy/core/models/author.py
|
|
54
|
+
trilogy/core/models/build.py
|
|
55
|
+
trilogy/core/models/build_environment.py
|
|
56
|
+
trilogy/core/models/core.py
|
|
57
|
+
trilogy/core/models/datasource.py
|
|
58
|
+
trilogy/core/models/environment.py
|
|
59
|
+
trilogy/core/models/execute.py
|
|
53
60
|
trilogy/core/optimizations/__init__.py
|
|
54
61
|
trilogy/core/optimizations/base_optimization.py
|
|
55
62
|
trilogy/core/optimizations/inline_constant.py
|
|
@@ -84,6 +91,11 @@ trilogy/core/processing/nodes/select_node_v2.py
|
|
|
84
91
|
trilogy/core/processing/nodes/union_node.py
|
|
85
92
|
trilogy/core/processing/nodes/unnest_node.py
|
|
86
93
|
trilogy/core/processing/nodes/window_node.py
|
|
94
|
+
trilogy/core/statements/__init__.py
|
|
95
|
+
trilogy/core/statements/author.py
|
|
96
|
+
trilogy/core/statements/build.py
|
|
97
|
+
trilogy/core/statements/common.py
|
|
98
|
+
trilogy/core/statements/execute.py
|
|
87
99
|
trilogy/dialect/__init__.py
|
|
88
100
|
trilogy/dialect/base.py
|
|
89
101
|
trilogy/dialect/bigquery.py
|
|
@@ -33,7 +33,10 @@ def test_filtering_where_on_derived_aggregate(test_environment):
|
|
|
33
33
|
)
|
|
34
34
|
except Exception as e:
|
|
35
35
|
exception = True
|
|
36
|
-
assert
|
|
36
|
+
assert (
|
|
37
|
+
"Cannot reference an aggregate derived in the select (local.filtered_cst)"
|
|
38
|
+
in str(e)
|
|
39
|
+
)
|
|
37
40
|
assert exception, "should have an exception"
|
|
38
41
|
|
|
39
42
|
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
from trilogy.core.constants import ALL_ROWS_CONCEPT, INTERNAL_NAMESPACE
|
|
2
|
-
from trilogy.core.models import
|
|
2
|
+
from trilogy.core.models.build import BuildGrain
|
|
3
|
+
from trilogy.core.models.environment import Environment
|
|
3
4
|
from trilogy.core.processing.concept_strategies_v3 import (
|
|
4
5
|
GroupNode,
|
|
6
|
+
History,
|
|
5
7
|
search_concepts,
|
|
6
8
|
)
|
|
7
9
|
from trilogy.core.processing.node_generators import gen_group_node
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
def test_group_node(test_environment, test_environment_graph):
|
|
13
|
+
history = History(base_environment=test_environment)
|
|
14
|
+
test_environment = test_environment.materialize_for_select()
|
|
11
15
|
total_revenue = test_environment.concepts["total_revenue"]
|
|
12
16
|
revenue = test_environment.concepts["revenue"]
|
|
13
17
|
category = test_environment.concepts["category_name"]
|
|
@@ -21,6 +25,7 @@ def test_group_node(test_environment, test_environment_graph):
|
|
|
21
25
|
environment=test_environment,
|
|
22
26
|
g=test_environment_graph,
|
|
23
27
|
depth=0,
|
|
28
|
+
history=history,
|
|
24
29
|
)
|
|
25
30
|
],
|
|
26
31
|
)
|
|
@@ -28,6 +33,8 @@ def test_group_node(test_environment, test_environment_graph):
|
|
|
28
33
|
|
|
29
34
|
|
|
30
35
|
def test_group_node_property(test_environment: Environment, test_environment_graph):
|
|
36
|
+
history = History(base_environment=test_environment)
|
|
37
|
+
test_environment = test_environment.materialize_for_select()
|
|
31
38
|
sum_name_length = test_environment.concepts["category_name_length_sum"]
|
|
32
39
|
|
|
33
40
|
group_node = gen_group_node(
|
|
@@ -36,6 +43,7 @@ def test_group_node_property(test_environment: Environment, test_environment_gra
|
|
|
36
43
|
environment=test_environment,
|
|
37
44
|
g=test_environment_graph,
|
|
38
45
|
source_concepts=search_concepts,
|
|
46
|
+
history=history,
|
|
39
47
|
depth=0,
|
|
40
48
|
)
|
|
41
49
|
input_concept_names = {
|
|
@@ -50,15 +58,20 @@ def test_group_node_property(test_environment: Environment, test_environment_gra
|
|
|
50
58
|
|
|
51
59
|
|
|
52
60
|
def test_group_node_property_all(test_environment: Environment, test_environment_graph):
|
|
61
|
+
history = History(base_environment=test_environment)
|
|
62
|
+
test_environment = test_environment.materialize_for_select()
|
|
53
63
|
sum_name_length = test_environment.concepts["category_name_length_sum"]
|
|
54
64
|
all_rows = test_environment.concepts[f"{INTERNAL_NAMESPACE}.{ALL_ROWS_CONCEPT}"]
|
|
55
|
-
sum_name_length_all_rows = sum_name_length.with_grain(
|
|
65
|
+
sum_name_length_all_rows = sum_name_length.with_grain(
|
|
66
|
+
BuildGrain(components=[all_rows])
|
|
67
|
+
)
|
|
56
68
|
group_node = gen_group_node(
|
|
57
69
|
sum_name_length_all_rows,
|
|
58
70
|
local_optional=[],
|
|
59
71
|
environment=test_environment,
|
|
60
72
|
g=test_environment_graph,
|
|
61
73
|
source_concepts=search_concepts,
|
|
74
|
+
history=history,
|
|
62
75
|
depth=0,
|
|
63
76
|
)
|
|
64
77
|
input_concept_names = {
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
|
+
from pytest import raises
|
|
4
|
+
|
|
3
5
|
from trilogy import Dialects
|
|
4
|
-
from trilogy.core.enums import Modifier
|
|
5
|
-
from trilogy.core.exceptions import
|
|
6
|
-
|
|
6
|
+
from trilogy.core.enums import Modifier, Purpose
|
|
7
|
+
from trilogy.core.exceptions import (
|
|
8
|
+
FrozenEnvironmentException,
|
|
9
|
+
UndefinedConceptException,
|
|
10
|
+
)
|
|
11
|
+
from trilogy.core.models.author import Concept
|
|
12
|
+
from trilogy.core.models.core import DataType
|
|
13
|
+
from trilogy.core.models.environment import Environment, LazyEnvironment
|
|
7
14
|
|
|
8
15
|
|
|
9
16
|
def test_environment_serialization(test_environment: Environment):
|
|
10
17
|
|
|
11
18
|
path = test_environment.to_cache()
|
|
12
|
-
print(path)
|
|
13
19
|
test_environment2 = Environment.from_cache(path)
|
|
14
20
|
assert test_environment2
|
|
15
21
|
|
|
@@ -25,6 +31,36 @@ def test_environment_from_path():
|
|
|
25
31
|
assert "local.id" in env.concepts
|
|
26
32
|
|
|
27
33
|
|
|
34
|
+
def test_lazy_environment_from_path():
|
|
35
|
+
env = LazyEnvironment(load_path=Path(__file__).parent / "test_env.preql")
|
|
36
|
+
|
|
37
|
+
assert not env.loaded
|
|
38
|
+
|
|
39
|
+
_ = len(env.concepts)
|
|
40
|
+
|
|
41
|
+
assert env.loaded
|
|
42
|
+
|
|
43
|
+
env2 = Environment.from_file(Path(__file__).parent / "test_env.preql")
|
|
44
|
+
|
|
45
|
+
assert env.concepts == env2.concepts
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_frozen_environment():
|
|
49
|
+
env = Environment.from_file(Path(__file__).parent / "test_env.preql")
|
|
50
|
+
|
|
51
|
+
exec = Dialects.DUCK_DB.default_executor(environment=env)
|
|
52
|
+
|
|
53
|
+
run = exec.execute_query(
|
|
54
|
+
"""select id+5 ->id_plus_5 order by id_plus_5 asc;"""
|
|
55
|
+
).fetchall()
|
|
56
|
+
assert run[0].id_plus_5 == 6
|
|
57
|
+
env.freeze()
|
|
58
|
+
with raises(FrozenEnvironmentException):
|
|
59
|
+
env.add_concept(
|
|
60
|
+
Concept(name="test", datatype=DataType.INTEGER, purpose=Purpose.KEY)
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
28
64
|
def test_environment_invalid():
|
|
29
65
|
env = Environment()
|
|
30
66
|
env.concepts.fail_on_missing = False
|
|
@@ -6,10 +6,12 @@ from pytest import raises
|
|
|
6
6
|
|
|
7
7
|
from trilogy import Dialects
|
|
8
8
|
from trilogy.constants import logger
|
|
9
|
-
from trilogy.core.enums import
|
|
9
|
+
from trilogy.core.enums import Derivation, Purpose
|
|
10
10
|
from trilogy.core.exceptions import InvalidSyntaxException
|
|
11
|
-
from trilogy.core.models import DataType,
|
|
11
|
+
from trilogy.core.models.core import DataType, ListType
|
|
12
|
+
from trilogy.core.models.environment import Environment
|
|
12
13
|
from trilogy.core.query_processor import process_query
|
|
14
|
+
from trilogy.core.statements.author import SelectStatement
|
|
13
15
|
from trilogy.dialect.base import BaseDialect
|
|
14
16
|
from trilogy.dialect.bigquery import BigqueryDialect
|
|
15
17
|
from trilogy.dialect.duckdb import DuckDBDialect
|
|
@@ -107,6 +109,7 @@ def test_date_functions(test_environment):
|
|
|
107
109
|
|
|
108
110
|
select
|
|
109
111
|
order_id,
|
|
112
|
+
order_timestamp,
|
|
110
113
|
date(order_timestamp) -> order_date,
|
|
111
114
|
datetime(order_timestamp) -> order_timestamp_datetime,
|
|
112
115
|
timestamp(order_timestamp) -> order_timestamp_dos,
|
|
@@ -344,4 +347,4 @@ def test_validate_constant_functions():
|
|
|
344
347
|
"""
|
|
345
348
|
)
|
|
346
349
|
assert env.concepts["current_date"].purpose == Purpose.CONSTANT
|
|
347
|
-
assert env.concepts["current_date"].derivation ==
|
|
350
|
+
assert env.concepts["current_date"].derivation == Derivation.CONSTANT
|
|
@@ -1,29 +1,43 @@
|
|
|
1
1
|
from copy import deepcopy
|
|
2
2
|
|
|
3
3
|
from trilogy import parse
|
|
4
|
-
from trilogy.core.enums import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
from trilogy.core.enums import (
|
|
5
|
+
BooleanOperator,
|
|
6
|
+
ComparisonOperator,
|
|
7
|
+
FunctionType,
|
|
8
|
+
JoinType,
|
|
9
|
+
Purpose,
|
|
10
|
+
)
|
|
11
|
+
from trilogy.core.models.author import (
|
|
8
12
|
AggregateWrapper,
|
|
9
|
-
BaseJoin,
|
|
10
13
|
Comparison,
|
|
11
14
|
Concept,
|
|
12
15
|
Conditional,
|
|
13
|
-
|
|
14
|
-
DataType,
|
|
15
|
-
Environment,
|
|
16
|
+
Function,
|
|
16
17
|
Grain,
|
|
17
|
-
|
|
18
|
-
QueryDatasource,
|
|
18
|
+
Parenthetical,
|
|
19
19
|
RowsetItem,
|
|
20
|
-
SelectStatement,
|
|
21
|
-
TupleWrapper,
|
|
22
20
|
UndefinedConcept,
|
|
23
21
|
)
|
|
22
|
+
from trilogy.core.models.build import BuildGrain
|
|
23
|
+
from trilogy.core.models.core import (
|
|
24
|
+
DataType,
|
|
25
|
+
TupleWrapper,
|
|
26
|
+
)
|
|
27
|
+
from trilogy.core.models.datasource import Address
|
|
28
|
+
from trilogy.core.models.environment import Environment
|
|
29
|
+
from trilogy.core.models.execute import (
|
|
30
|
+
CTE,
|
|
31
|
+
BaseJoin,
|
|
32
|
+
CTEConceptPair,
|
|
33
|
+
Join,
|
|
34
|
+
QueryDatasource,
|
|
35
|
+
)
|
|
36
|
+
from trilogy.core.statements.author import SelectStatement
|
|
24
37
|
|
|
25
38
|
|
|
26
39
|
def test_cte_merge(test_environment, test_environment_graph):
|
|
40
|
+
test_environment = test_environment.materialize_for_select()
|
|
27
41
|
datasource = list(test_environment.datasources.values())[0]
|
|
28
42
|
outputs = [c.concept for c in datasource.columns]
|
|
29
43
|
output_map = {
|
|
@@ -35,12 +49,12 @@ def test_cte_merge(test_environment, test_environment_graph):
|
|
|
35
49
|
a = CTE(
|
|
36
50
|
name="test",
|
|
37
51
|
output_columns=[outputs[0]],
|
|
38
|
-
grain=
|
|
52
|
+
grain=BuildGrain(),
|
|
39
53
|
source=QueryDatasource(
|
|
40
54
|
input_concepts=[outputs[0]],
|
|
41
55
|
output_concepts=[outputs[0]],
|
|
42
56
|
datasources=[datasource],
|
|
43
|
-
grain=
|
|
57
|
+
grain=BuildGrain(),
|
|
44
58
|
joins=[],
|
|
45
59
|
source_map={outputs[0].address: {datasource}},
|
|
46
60
|
),
|
|
@@ -49,12 +63,12 @@ def test_cte_merge(test_environment, test_environment_graph):
|
|
|
49
63
|
b = CTE(
|
|
50
64
|
name="testb",
|
|
51
65
|
output_columns=outputs,
|
|
52
|
-
grain=
|
|
66
|
+
grain=BuildGrain(),
|
|
53
67
|
source=QueryDatasource(
|
|
54
68
|
input_concepts=outputs,
|
|
55
69
|
output_concepts=outputs,
|
|
56
70
|
datasources=[datasource],
|
|
57
|
-
grain=
|
|
71
|
+
grain=BuildGrain(),
|
|
58
72
|
joins=[],
|
|
59
73
|
source_map=output_map,
|
|
60
74
|
),
|
|
@@ -151,33 +165,22 @@ def test_select(test_environment: Environment):
|
|
|
151
165
|
selection=[oid, pid, cid, cname], grain=Grain(components=[oid, pid, cid])
|
|
152
166
|
)
|
|
153
167
|
ds = x.to_datasource(
|
|
154
|
-
test_environment.namespace,
|
|
168
|
+
test_environment.namespace,
|
|
169
|
+
"test",
|
|
170
|
+
address=Address(location="test"),
|
|
171
|
+
environment=test_environment,
|
|
155
172
|
)
|
|
156
173
|
|
|
157
174
|
assert ds.grain.components == Grain(components=[oid, pid, cid]).components
|
|
158
175
|
|
|
159
176
|
|
|
160
177
|
def test_undefined(test_environment: Environment):
|
|
161
|
-
|
|
162
|
-
name="test",
|
|
163
|
-
datatype="int",
|
|
164
|
-
purpose=Purpose.CONSTANT,
|
|
165
|
-
grain=Grain(),
|
|
166
|
-
namespace="test",
|
|
167
|
-
environment=test_environment.concepts,
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
# y = x.with_select_context({}, Grain(components=[test_environment.concepts["order_id"]]), test_environment)
|
|
171
|
-
|
|
172
|
-
# assert y.grain == Grain(components=[test_environment.concepts["order_id"]])
|
|
173
|
-
|
|
174
|
-
z = x.with_default_grain()
|
|
175
|
-
|
|
176
|
-
assert z.grain == Grain()
|
|
178
|
+
UndefinedConcept(address="test.test")
|
|
177
179
|
|
|
178
180
|
|
|
179
181
|
def test_base_join(test_environment: Environment):
|
|
180
182
|
exc: SyntaxError | None = None
|
|
183
|
+
test_environment = test_environment.materialize_for_select()
|
|
181
184
|
try:
|
|
182
185
|
BaseJoin(
|
|
183
186
|
left_datasource=test_environment.datasources["revenue"],
|
|
@@ -211,6 +214,7 @@ def test_comparison():
|
|
|
211
214
|
|
|
212
215
|
|
|
213
216
|
def test_join(test_environment: Environment):
|
|
217
|
+
test_environment = test_environment.materialize_for_select()
|
|
214
218
|
datasource = list(test_environment.datasources.values())[0]
|
|
215
219
|
outputs = [c.concept for c in datasource.columns]
|
|
216
220
|
output_map = {
|
|
@@ -222,12 +226,12 @@ def test_join(test_environment: Environment):
|
|
|
222
226
|
a = CTE(
|
|
223
227
|
name="test",
|
|
224
228
|
output_columns=[outputs[0]],
|
|
225
|
-
grain=
|
|
229
|
+
grain=BuildGrain(),
|
|
226
230
|
source=QueryDatasource(
|
|
227
231
|
input_concepts=[outputs[0]],
|
|
228
232
|
output_concepts=[outputs[0]],
|
|
229
233
|
datasources=[datasource],
|
|
230
|
-
grain=
|
|
234
|
+
grain=BuildGrain(),
|
|
231
235
|
joins=[],
|
|
232
236
|
source_map={outputs[0].address: {datasource}},
|
|
233
237
|
),
|
|
@@ -237,12 +241,12 @@ def test_join(test_environment: Environment):
|
|
|
237
241
|
b = CTE(
|
|
238
242
|
name="testb",
|
|
239
243
|
output_columns=outputs,
|
|
240
|
-
grain=
|
|
244
|
+
grain=BuildGrain(),
|
|
241
245
|
source=QueryDatasource(
|
|
242
246
|
input_concepts=outputs,
|
|
243
247
|
output_concepts=outputs,
|
|
244
248
|
datasources=[datasource],
|
|
245
|
-
grain=
|
|
249
|
+
grain=BuildGrain(),
|
|
246
250
|
joins=[],
|
|
247
251
|
source_map=output_map,
|
|
248
252
|
),
|
|
@@ -270,7 +274,6 @@ def test_concept_address_in_check():
|
|
|
270
274
|
datatype="int",
|
|
271
275
|
purpose=Purpose.CONSTANT,
|
|
272
276
|
grain=Grain(),
|
|
273
|
-
environment={},
|
|
274
277
|
)
|
|
275
278
|
assert target.address == "local.test"
|
|
276
279
|
x = [target]
|
|
@@ -304,10 +307,39 @@ select avg_greater_ten;
|
|
|
304
307
|
|
|
305
308
|
lineage = env.concepts["avg_greater_ten"].lineage
|
|
306
309
|
assert isinstance(lineage, AggregateWrapper)
|
|
307
|
-
assert isinstance(
|
|
310
|
+
assert isinstance(
|
|
311
|
+
env.concepts[lineage.function.concept_arguments[0]].lineage, RowsetItem
|
|
312
|
+
)
|
|
308
313
|
|
|
309
314
|
|
|
310
315
|
def test_tuple_clone():
|
|
311
316
|
x = TupleWrapper([1, 2, 3], type=DataType.INTEGER)
|
|
312
317
|
y = deepcopy(x)
|
|
313
318
|
assert y == x
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def test_parenthetical(test_environment: Environment):
|
|
322
|
+
x = Parenthetical(content=TupleWrapper([1, 2, 3], type=DataType.INTEGER))
|
|
323
|
+
|
|
324
|
+
assert x.concept_arguments == []
|
|
325
|
+
|
|
326
|
+
x = Parenthetical(
|
|
327
|
+
content=test_environment.concepts["order_id"], type=DataType.INTEGER
|
|
328
|
+
)
|
|
329
|
+
# return concept if it's a concept
|
|
330
|
+
assert x.concept_arguments == [test_environment.concepts["order_id"]]
|
|
331
|
+
function = Function(
|
|
332
|
+
operator=FunctionType.COUNT,
|
|
333
|
+
output_datatype=DataType.INTEGER,
|
|
334
|
+
output_purpose=Purpose.METRIC,
|
|
335
|
+
arguments=[test_environment.concepts["order_id"]],
|
|
336
|
+
)
|
|
337
|
+
assert function.concept_arguments == [
|
|
338
|
+
test_environment.concepts["order_id"].reference
|
|
339
|
+
]
|
|
340
|
+
x = Parenthetical(content=function)
|
|
341
|
+
# else pass through parent
|
|
342
|
+
assert x.concept_arguments == [test_environment.concepts["order_id"].reference]
|
|
343
|
+
|
|
344
|
+
merged = x + x
|
|
345
|
+
assert isinstance(merged, Conditional)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# from trilogy.compiler import compile
|
|
2
|
-
from trilogy.core.models import Grain
|
|
2
|
+
from trilogy.core.models.author import Grain
|
|
3
3
|
from trilogy.core.query_processor import process_query
|
|
4
|
+
from trilogy.core.statements.author import SelectStatement
|
|
4
5
|
from trilogy.parser import parse
|
|
5
6
|
|
|
6
7
|
TEST_SETUP = r"""
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from pytest import raises
|
|
2
2
|
|
|
3
|
-
from trilogy import Environment
|
|
4
3
|
from trilogy.core.exceptions import UndefinedConceptException
|
|
4
|
+
from trilogy.core.models.environment import Environment
|
|
5
5
|
from trilogy.parsing.parse_engine import PARSER, ParseToObjects, unpack_visit_error
|
|
6
6
|
|
|
7
7
|
TEXT = """
|
|
@@ -17,7 +17,6 @@ select
|
|
|
17
17
|
def test_parser():
|
|
18
18
|
env = Environment()
|
|
19
19
|
x = ParseToObjects(environment=env)
|
|
20
|
-
x.environment.concepts.fail_on_missing = False
|
|
21
20
|
x.set_text(TEXT)
|
|
22
21
|
|
|
23
22
|
failed = False
|
|
@@ -2,16 +2,15 @@ from trilogy import Dialects
|
|
|
2
2
|
from trilogy.constants import MagicConstants
|
|
3
3
|
from trilogy.core.enums import BooleanOperator, ComparisonOperator, Purpose
|
|
4
4
|
from trilogy.core.functions import argument_to_purpose, function_args_to_output_purpose
|
|
5
|
-
from trilogy.core.models import
|
|
6
|
-
|
|
7
|
-
Datasource,
|
|
5
|
+
from trilogy.core.models.author import Comparison
|
|
6
|
+
from trilogy.core.models.core import (
|
|
8
7
|
DataType,
|
|
9
|
-
Environment,
|
|
10
|
-
ProcessedQuery,
|
|
11
|
-
SelectStatement,
|
|
12
|
-
ShowStatement,
|
|
13
8
|
TupleWrapper,
|
|
14
9
|
)
|
|
10
|
+
from trilogy.core.models.datasource import Datasource
|
|
11
|
+
from trilogy.core.models.environment import Environment
|
|
12
|
+
from trilogy.core.statements.author import SelectStatement, ShowStatement
|
|
13
|
+
from trilogy.core.statements.execute import ProcessedQuery
|
|
15
14
|
from trilogy.dialect.base import BaseDialect
|
|
16
15
|
from trilogy.parsing.parse_engine import (
|
|
17
16
|
arg_to_datatype,
|
|
@@ -390,6 +389,14 @@ select composite_id;
|
|
|
390
389
|
"""
|
|
391
390
|
executor.parse_text(test_case)
|
|
392
391
|
|
|
392
|
+
assert (
|
|
393
|
+
"local.composite_id_alt"
|
|
394
|
+
in executor.environment.concepts["local.composite_id"].pseudonyms
|
|
395
|
+
)
|
|
396
|
+
assert (
|
|
397
|
+
"local.composite_id"
|
|
398
|
+
in executor.environment.alias_origin_lookup["local.composite_id_alt"].pseudonyms
|
|
399
|
+
)
|
|
393
400
|
results = executor.execute_text(test_case)[0].fetchall()
|
|
394
401
|
|
|
395
402
|
assert results == [("123-abc",)]
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
# from trilogy.core.models import Environment
|
|
2
1
|
from sqlalchemy import create_engine
|
|
3
2
|
|
|
4
3
|
from trilogy import Dialects, Executor
|
|
5
4
|
from trilogy.core.enums import Purpose
|
|
6
|
-
from trilogy.core.models import
|
|
7
|
-
|
|
8
|
-
Concept,
|
|
9
|
-
Datasource,
|
|
5
|
+
from trilogy.core.models.author import Concept
|
|
6
|
+
from trilogy.core.models.core import (
|
|
10
7
|
DataType,
|
|
11
|
-
Environment,
|
|
12
8
|
)
|
|
13
|
-
from trilogy.core.
|
|
9
|
+
from trilogy.core.models.datasource import ColumnAssignment, Datasource
|
|
10
|
+
from trilogy.core.models.environment import Environment
|
|
11
|
+
from trilogy.core.processing.concept_strategies_v3 import History, search_concepts
|
|
14
12
|
from trilogy.core.processing.node_generators import (
|
|
15
13
|
gen_filter_node,
|
|
16
14
|
)
|
|
@@ -104,12 +102,14 @@ def test_partial_assignment():
|
|
|
104
102
|
|
|
105
103
|
executor = setup_engine()
|
|
106
104
|
env = Environment()
|
|
105
|
+
history = History(base_environment=env)
|
|
107
106
|
setup_titanic(env)
|
|
108
107
|
executor.environment = env
|
|
109
108
|
executor.hooks = [DebuggingHook()]
|
|
110
109
|
test = """property passenger.id.family <- split(passenger.name, ',')[1];
|
|
111
110
|
auto surviving_passenger<- filter passenger.id where passenger.survived =1;"""
|
|
112
111
|
_ = executor.parse_text(test)
|
|
112
|
+
env = env.materialize_for_select()
|
|
113
113
|
family = env.concepts["passenger.family"]
|
|
114
114
|
# id = env.concepts["passenger.id"]
|
|
115
115
|
# survived = env.concepts["passenger.survived"]
|
|
@@ -117,6 +117,7 @@ def test_partial_assignment():
|
|
|
117
117
|
filtered_node = gen_filter_node(
|
|
118
118
|
env.concepts["surviving_passenger"],
|
|
119
119
|
[family],
|
|
120
|
+
history=history,
|
|
120
121
|
environment=env,
|
|
121
122
|
g=g,
|
|
122
123
|
depth=0,
|
|
@@ -132,7 +133,11 @@ def test_partial_assignment():
|
|
|
132
133
|
|
|
133
134
|
# check at the source level
|
|
134
135
|
sourced = search_concepts(
|
|
135
|
-
[family, env.concepts["surviving_passenger"]],
|
|
136
|
+
[family, env.concepts["surviving_passenger"]],
|
|
137
|
+
history=history,
|
|
138
|
+
environment=env,
|
|
139
|
+
g=g,
|
|
140
|
+
depth=0,
|
|
136
141
|
)
|
|
137
142
|
assert isinstance(sourced, MergeNode)
|
|
138
143
|
assert len(sourced.parents) == 2
|