pytrilogy 0.0.3.46__tar.gz → 0.0.3.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.3.46/pytrilogy.egg-info → pytrilogy-0.0.3.48}/PKG-INFO +12 -15
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/README.md +11 -14
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48/pytrilogy.egg-info}/PKG-INFO +12 -15
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/pytrilogy.egg-info/SOURCES.txt +0 -1
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_functions.py +3 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_parsing_failures.py +2 -2
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/__init__.py +1 -1
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/environment_helpers.py +2 -27
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/models/author.py +4 -1
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/models/build.py +60 -34
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/models/execute.py +2 -1
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/optimization.py +0 -3
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/optimizations/__init__.py +0 -2
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/group_node.py +4 -1
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/nodes/__init__.py +2 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/query_processor.py +28 -14
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/statements/author.py +21 -9
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/dialect/base.py +22 -4
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/dialect/common.py +25 -14
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/executor.py +3 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/parsing/common.py +73 -16
- pytrilogy-0.0.3.48/trilogy/parsing/exceptions.py +8 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/parsing/parse_engine.py +34 -29
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/parsing/trilogy.lark +1 -4
- pytrilogy-0.0.3.46/trilogy/core/optimizations/inline_constant.py +0 -35
- pytrilogy-0.0.3.46/trilogy/parsing/exceptions.py +0 -2
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/LICENSE.md +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/pyproject.toml +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/pytrilogy.egg-info/dependency_links.txt +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/pytrilogy.egg-info/entry_points.txt +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/pytrilogy.egg-info/requires.txt +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/pytrilogy.egg-info/top_level.txt +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/setup.cfg +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/setup.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_datatypes.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_declarations.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_derived_concepts.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_discovery_nodes.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_enums.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_environment.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_executor.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_failure.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_imports.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_metadata.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_models.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_multi_join_assignments.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_parse_engine.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_parsing.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_partial_handling.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_query_processing.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_query_render.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_select.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_show.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_statements.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_typing.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_undefined_concept.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_user_functions.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/tests/test_where_clause.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/authoring/__init__.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/compiler.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/constants.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/__init__.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/constants.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/enums.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/env_processor.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/ergonomics.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/exceptions.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/functions.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/graph_models.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/internal.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/models/__init__.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/models/build_environment.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/models/core.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/models/datasource.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/models/environment.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/optimizations/base_optimization.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/optimizations/inline_datasource.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/__init__.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/concept_strategies_v3.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/graph_utils.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/__init__.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/basic_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/common.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/filter_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/group_to_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/multiselect_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/node_merge_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/rowset_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/select_helpers/__init__.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/select_merge_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/select_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/synonym_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/union_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/unnest_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/window_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/nodes/base_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/nodes/filter_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/nodes/group_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/nodes/merge_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/nodes/union_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/nodes/unnest_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/nodes/window_node.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/utility.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/statements/__init__.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/statements/build.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/statements/common.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/statements/execute.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/dialect/__init__.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/dialect/bigquery.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/dialect/config.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/dialect/dataframe.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/dialect/duckdb.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/dialect/enums.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/dialect/postgres.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/dialect/presto.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/dialect/snowflake.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/dialect/sql_server.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/engine.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/hooks/__init__.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/hooks/base_hook.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/hooks/graph_hook.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/hooks/query_debugger.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/metadata/__init__.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/parser.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/parsing/__init__.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/parsing/config.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/parsing/helpers.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/parsing/render.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/py.typed +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/render.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/scripts/__init__.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/scripts/trilogy.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/std/__init__.py +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/std/date.preql +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/std/display.preql +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/std/geography.preql +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/std/money.preql +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/std/report.preql +0 -0
- {pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/utility.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pytrilogy
|
|
3
|
-
Version: 0.0.3.
|
|
3
|
+
Version: 0.0.3.48
|
|
4
4
|
Summary: Declarative, typed query language that compiles to SQL.
|
|
5
5
|
Home-page:
|
|
6
6
|
Author:
|
|
@@ -53,7 +53,7 @@ Installation: `pip install pytrilogy`
|
|
|
53
53
|
|
|
54
54
|
You can read more about the project [here](https://trilogydata.dev/) and try out an interactive demo [here](https://trilogydata.dev/demo/).
|
|
55
55
|
|
|
56
|
-
Trilogy:
|
|
56
|
+
Trilogy looks like SQL:
|
|
57
57
|
```sql
|
|
58
58
|
WHERE
|
|
59
59
|
name like '%lvis%'
|
|
@@ -65,7 +65,7 @@ ORDER BY
|
|
|
65
65
|
LIMIT 10;
|
|
66
66
|
```
|
|
67
67
|
## Goals
|
|
68
|
-
|
|
68
|
+
And aims to:
|
|
69
69
|
|
|
70
70
|
Preserve:
|
|
71
71
|
- Correctness
|
|
@@ -85,6 +85,7 @@ Maintain:
|
|
|
85
85
|
Save the following code in a file named `hello.preql`
|
|
86
86
|
|
|
87
87
|
```python
|
|
88
|
+
# semantic model is abstract from data
|
|
88
89
|
key sentence_id int;
|
|
89
90
|
property sentence_id.word_one string; # comments after a definition
|
|
90
91
|
property sentence_id.word_two string; # are syntactic sugar for adding
|
|
@@ -92,7 +93,8 @@ property sentence_id.word_three string; # a description to it
|
|
|
92
93
|
|
|
93
94
|
# comments in other places are just comments
|
|
94
95
|
|
|
95
|
-
# define our
|
|
96
|
+
# define our datasource to bind the model to data
|
|
97
|
+
# testing using query fixtures is a common pattern
|
|
96
98
|
datasource word_one(
|
|
97
99
|
sentence: sentence_id,
|
|
98
100
|
word:word_one
|
|
@@ -126,25 +128,20 @@ union all
|
|
|
126
128
|
select 2 as sentence, '!'
|
|
127
129
|
''';
|
|
128
130
|
|
|
131
|
+
def concat_with_space(x,y) -> x || ' ' || y;
|
|
132
|
+
|
|
129
133
|
# an actual select statement
|
|
130
134
|
# joins are automatically resolved between the 3 sources
|
|
131
135
|
with sentences as
|
|
132
|
-
select sentence_id, word_one
|
|
136
|
+
select sentence_id, @concat_with_space(word_one, word_two) || word_three as text;
|
|
133
137
|
|
|
134
|
-
SELECT
|
|
135
|
-
--sentences.sentence_id,
|
|
136
|
-
sentences.text
|
|
137
138
|
WHERE
|
|
138
|
-
sentences.sentence_id
|
|
139
|
-
;
|
|
140
|
-
|
|
139
|
+
sentences.sentence_id in (1,2)
|
|
141
140
|
SELECT
|
|
142
|
-
--sentences.sentence_id,
|
|
143
141
|
sentences.text
|
|
144
|
-
WHERE
|
|
145
|
-
sentences.sentence_id = 2
|
|
146
142
|
;
|
|
147
|
-
|
|
143
|
+
|
|
144
|
+
|
|
148
145
|
|
|
149
146
|
```
|
|
150
147
|
|
|
@@ -15,7 +15,7 @@ Installation: `pip install pytrilogy`
|
|
|
15
15
|
|
|
16
16
|
You can read more about the project [here](https://trilogydata.dev/) and try out an interactive demo [here](https://trilogydata.dev/demo/).
|
|
17
17
|
|
|
18
|
-
Trilogy:
|
|
18
|
+
Trilogy looks like SQL:
|
|
19
19
|
```sql
|
|
20
20
|
WHERE
|
|
21
21
|
name like '%lvis%'
|
|
@@ -27,7 +27,7 @@ ORDER BY
|
|
|
27
27
|
LIMIT 10;
|
|
28
28
|
```
|
|
29
29
|
## Goals
|
|
30
|
-
|
|
30
|
+
And aims to:
|
|
31
31
|
|
|
32
32
|
Preserve:
|
|
33
33
|
- Correctness
|
|
@@ -47,6 +47,7 @@ Maintain:
|
|
|
47
47
|
Save the following code in a file named `hello.preql`
|
|
48
48
|
|
|
49
49
|
```python
|
|
50
|
+
# semantic model is abstract from data
|
|
50
51
|
key sentence_id int;
|
|
51
52
|
property sentence_id.word_one string; # comments after a definition
|
|
52
53
|
property sentence_id.word_two string; # are syntactic sugar for adding
|
|
@@ -54,7 +55,8 @@ property sentence_id.word_three string; # a description to it
|
|
|
54
55
|
|
|
55
56
|
# comments in other places are just comments
|
|
56
57
|
|
|
57
|
-
# define our
|
|
58
|
+
# define our datasource to bind the model to data
|
|
59
|
+
# testing using query fixtures is a common pattern
|
|
58
60
|
datasource word_one(
|
|
59
61
|
sentence: sentence_id,
|
|
60
62
|
word:word_one
|
|
@@ -88,25 +90,20 @@ union all
|
|
|
88
90
|
select 2 as sentence, '!'
|
|
89
91
|
''';
|
|
90
92
|
|
|
93
|
+
def concat_with_space(x,y) -> x || ' ' || y;
|
|
94
|
+
|
|
91
95
|
# an actual select statement
|
|
92
96
|
# joins are automatically resolved between the 3 sources
|
|
93
97
|
with sentences as
|
|
94
|
-
select sentence_id, word_one
|
|
98
|
+
select sentence_id, @concat_with_space(word_one, word_two) || word_three as text;
|
|
95
99
|
|
|
96
|
-
SELECT
|
|
97
|
-
--sentences.sentence_id,
|
|
98
|
-
sentences.text
|
|
99
100
|
WHERE
|
|
100
|
-
sentences.sentence_id
|
|
101
|
-
;
|
|
102
|
-
|
|
101
|
+
sentences.sentence_id in (1,2)
|
|
103
102
|
SELECT
|
|
104
|
-
--sentences.sentence_id,
|
|
105
103
|
sentences.text
|
|
106
|
-
WHERE
|
|
107
|
-
sentences.sentence_id = 2
|
|
108
104
|
;
|
|
109
|
-
|
|
105
|
+
|
|
106
|
+
|
|
110
107
|
|
|
111
108
|
```
|
|
112
109
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pytrilogy
|
|
3
|
-
Version: 0.0.3.
|
|
3
|
+
Version: 0.0.3.48
|
|
4
4
|
Summary: Declarative, typed query language that compiles to SQL.
|
|
5
5
|
Home-page:
|
|
6
6
|
Author:
|
|
@@ -53,7 +53,7 @@ Installation: `pip install pytrilogy`
|
|
|
53
53
|
|
|
54
54
|
You can read more about the project [here](https://trilogydata.dev/) and try out an interactive demo [here](https://trilogydata.dev/demo/).
|
|
55
55
|
|
|
56
|
-
Trilogy:
|
|
56
|
+
Trilogy looks like SQL:
|
|
57
57
|
```sql
|
|
58
58
|
WHERE
|
|
59
59
|
name like '%lvis%'
|
|
@@ -65,7 +65,7 @@ ORDER BY
|
|
|
65
65
|
LIMIT 10;
|
|
66
66
|
```
|
|
67
67
|
## Goals
|
|
68
|
-
|
|
68
|
+
And aims to:
|
|
69
69
|
|
|
70
70
|
Preserve:
|
|
71
71
|
- Correctness
|
|
@@ -85,6 +85,7 @@ Maintain:
|
|
|
85
85
|
Save the following code in a file named `hello.preql`
|
|
86
86
|
|
|
87
87
|
```python
|
|
88
|
+
# semantic model is abstract from data
|
|
88
89
|
key sentence_id int;
|
|
89
90
|
property sentence_id.word_one string; # comments after a definition
|
|
90
91
|
property sentence_id.word_two string; # are syntactic sugar for adding
|
|
@@ -92,7 +93,8 @@ property sentence_id.word_three string; # a description to it
|
|
|
92
93
|
|
|
93
94
|
# comments in other places are just comments
|
|
94
95
|
|
|
95
|
-
# define our
|
|
96
|
+
# define our datasource to bind the model to data
|
|
97
|
+
# testing using query fixtures is a common pattern
|
|
96
98
|
datasource word_one(
|
|
97
99
|
sentence: sentence_id,
|
|
98
100
|
word:word_one
|
|
@@ -126,25 +128,20 @@ union all
|
|
|
126
128
|
select 2 as sentence, '!'
|
|
127
129
|
''';
|
|
128
130
|
|
|
131
|
+
def concat_with_space(x,y) -> x || ' ' || y;
|
|
132
|
+
|
|
129
133
|
# an actual select statement
|
|
130
134
|
# joins are automatically resolved between the 3 sources
|
|
131
135
|
with sentences as
|
|
132
|
-
select sentence_id, word_one
|
|
136
|
+
select sentence_id, @concat_with_space(word_one, word_two) || word_three as text;
|
|
133
137
|
|
|
134
|
-
SELECT
|
|
135
|
-
--sentences.sentence_id,
|
|
136
|
-
sentences.text
|
|
137
138
|
WHERE
|
|
138
|
-
sentences.sentence_id
|
|
139
|
-
;
|
|
140
|
-
|
|
139
|
+
sentences.sentence_id in (1,2)
|
|
141
140
|
SELECT
|
|
142
|
-
--sentences.sentence_id,
|
|
143
141
|
sentences.text
|
|
144
|
-
WHERE
|
|
145
|
-
sentences.sentence_id = 2
|
|
146
142
|
;
|
|
147
|
-
|
|
143
|
+
|
|
144
|
+
|
|
148
145
|
|
|
149
146
|
```
|
|
150
147
|
|
|
@@ -66,7 +66,6 @@ trilogy/core/models/environment.py
|
|
|
66
66
|
trilogy/core/models/execute.py
|
|
67
67
|
trilogy/core/optimizations/__init__.py
|
|
68
68
|
trilogy/core/optimizations/base_optimization.py
|
|
69
|
-
trilogy/core/optimizations/inline_constant.py
|
|
70
69
|
trilogy/core/optimizations/inline_datasource.py
|
|
71
70
|
trilogy/core/optimizations/predicate_pushdown.py
|
|
72
71
|
trilogy/core/processing/__init__.py
|
|
@@ -123,6 +123,7 @@ def test_date_functions(test_environment):
|
|
|
123
123
|
year(order_timestamp) -> order_year,
|
|
124
124
|
date_trunc(order_timestamp, month) -> order_month_trunc,
|
|
125
125
|
date_add(order_timestamp, month, 1) -> one_month_post_order,
|
|
126
|
+
date_sub(order_timestamp, month, 1) -> one_month_pre_order,
|
|
126
127
|
date_trunc(order_timestamp, day) -> order_day_trunc,
|
|
127
128
|
date_trunc(order_timestamp, year) -> order_year_trunc,
|
|
128
129
|
date_trunc(order_timestamp, hour) -> order_hour_trunc,
|
|
@@ -212,6 +213,7 @@ def test_math_functions(test_environment):
|
|
|
212
213
|
property order_sub <- revenue - 2;
|
|
213
214
|
property order_id.order_nested <- revenue * 2/2;
|
|
214
215
|
property order_id.rounded <- round(revenue + 2.01,2);
|
|
216
|
+
property order_id.rounded_default <- round(revenue + 2.01);
|
|
215
217
|
constant random <- random(1);
|
|
216
218
|
select
|
|
217
219
|
order_id,
|
|
@@ -221,6 +223,7 @@ def test_math_functions(test_environment):
|
|
|
221
223
|
order_sub,
|
|
222
224
|
order_add,
|
|
223
225
|
rounded,
|
|
226
|
+
rounded_default,
|
|
224
227
|
random,
|
|
225
228
|
;"""
|
|
226
229
|
env, parsed = parse(declarations, environment=test_environment)
|
|
@@ -8,7 +8,7 @@ from trilogy.core.models.environment import (
|
|
|
8
8
|
EnvironmentOptions,
|
|
9
9
|
)
|
|
10
10
|
from trilogy.parsing.parse_engine import (
|
|
11
|
-
|
|
11
|
+
NameShadowError,
|
|
12
12
|
parse_text,
|
|
13
13
|
)
|
|
14
14
|
|
|
@@ -77,7 +77,7 @@ SELECT
|
|
|
77
77
|
1+2->scalar
|
|
78
78
|
;
|
|
79
79
|
"""
|
|
80
|
-
with raises(
|
|
80
|
+
with raises(NameShadowError) as e:
|
|
81
81
|
env, parsed = parse_text(
|
|
82
82
|
x, parse_config=Parsing(strict_name_shadow_enforcement=True)
|
|
83
83
|
)
|
|
@@ -6,23 +6,8 @@ from trilogy.core.models.core import DataType, StructType, arg_to_datatype
|
|
|
6
6
|
from trilogy.core.models.environment import Environment
|
|
7
7
|
from trilogy.parsing.common import Meta
|
|
8
8
|
|
|
9
|
-
FUNCTION_DESCRIPTION_MAPS = {
|
|
10
|
-
FunctionType.DATE: "The date part of a timestamp/date. Integer, 0-31 depending on month.",
|
|
11
|
-
FunctionType.MONTH: "The month part of a timestamp/date. Integer, 1-12.",
|
|
12
|
-
FunctionType.YEAR: "The year part of a timestamp/date. Integer.",
|
|
13
|
-
FunctionType.QUARTER: "The quarter part of a timestamp/date. Integer, 1-4.",
|
|
14
|
-
FunctionType.DAY_OF_WEEK: "The day of the week part of a timestamp/date. Integer, 0-6.",
|
|
15
|
-
FunctionType.HOUR: "The hour part of a timestamp. Integer, 0-23.",
|
|
16
|
-
FunctionType.MINUTE: "The minute part of a timestamp. Integer, 0-59.",
|
|
17
|
-
FunctionType.SECOND: "The second part of a timestamp. Integer, 0-59.",
|
|
18
|
-
}
|
|
19
|
-
|
|
20
9
|
|
|
21
10
|
def generate_date_concepts(concept: Concept, environment: Environment):
|
|
22
|
-
if concept.metadata and concept.metadata.description:
|
|
23
|
-
base_description = concept.metadata.description
|
|
24
|
-
else:
|
|
25
|
-
base_description = f"a {concept.address}"
|
|
26
11
|
if concept.metadata and concept.metadata.line_number:
|
|
27
12
|
base_line_number = concept.metadata.line_number
|
|
28
13
|
else:
|
|
@@ -67,7 +52,6 @@ def generate_date_concepts(concept: Concept, environment: Environment):
|
|
|
67
52
|
[concept.address],
|
|
68
53
|
),
|
|
69
54
|
metadata=Metadata(
|
|
70
|
-
description=f"Auto-derived from {base_description}. {FUNCTION_DESCRIPTION_MAPS.get(ftype, ftype.value)}",
|
|
71
55
|
line_number=base_line_number,
|
|
72
56
|
concept_source=ConceptSource.AUTO_DERIVED,
|
|
73
57
|
),
|
|
@@ -95,7 +79,7 @@ def generate_date_concepts(concept: Concept, environment: Environment):
|
|
|
95
79
|
[concept.address],
|
|
96
80
|
),
|
|
97
81
|
metadata=Metadata(
|
|
98
|
-
description=f"Auto-derived from {base_description}. The date truncated to the {grain.value}.",
|
|
82
|
+
# description=f"Auto-derived from {base_description}. The date truncated to the {grain.value}.",
|
|
99
83
|
line_number=base_line_number,
|
|
100
84
|
concept_source=ConceptSource.AUTO_DERIVED,
|
|
101
85
|
),
|
|
@@ -105,10 +89,6 @@ def generate_date_concepts(concept: Concept, environment: Environment):
|
|
|
105
89
|
|
|
106
90
|
|
|
107
91
|
def generate_datetime_concepts(concept: Concept, environment: Environment):
|
|
108
|
-
if concept.metadata and concept.metadata.description:
|
|
109
|
-
base_description = concept.metadata.description
|
|
110
|
-
else:
|
|
111
|
-
base_description = concept.address
|
|
112
92
|
if concept.metadata and concept.metadata.line_number:
|
|
113
93
|
base_line_number = concept.metadata.line_number
|
|
114
94
|
else:
|
|
@@ -146,7 +126,6 @@ def generate_datetime_concepts(concept: Concept, environment: Environment):
|
|
|
146
126
|
[concept.address],
|
|
147
127
|
),
|
|
148
128
|
metadata=Metadata(
|
|
149
|
-
description=f"Auto-derived from {base_description}. {FUNCTION_DESCRIPTION_MAPS.get(ftype, ftype.value)}",
|
|
150
129
|
line_number=base_line_number,
|
|
151
130
|
concept_source=ConceptSource.AUTO_DERIVED,
|
|
152
131
|
),
|
|
@@ -157,10 +136,6 @@ def generate_datetime_concepts(concept: Concept, environment: Environment):
|
|
|
157
136
|
|
|
158
137
|
|
|
159
138
|
def generate_key_concepts(concept: Concept, environment: Environment):
|
|
160
|
-
if concept.metadata and concept.metadata.description:
|
|
161
|
-
base_description = concept.metadata.description
|
|
162
|
-
else:
|
|
163
|
-
base_description = f"a {concept.datatype.value}"
|
|
164
139
|
if concept.metadata and concept.metadata.line_number:
|
|
165
140
|
base_line_number = concept.metadata.line_number
|
|
166
141
|
else:
|
|
@@ -186,7 +161,7 @@ def generate_key_concepts(concept: Concept, environment: Environment):
|
|
|
186
161
|
namespace=concept.namespace,
|
|
187
162
|
keys=set(),
|
|
188
163
|
metadata=Metadata(
|
|
189
|
-
description=f"Auto-derived integer. The {ftype.value} of {concept.address}, {base_description}",
|
|
164
|
+
# description=f"Auto-derived integer. The {ftype.value} of {concept.address}, {base_description}",
|
|
190
165
|
line_number=base_line_number,
|
|
191
166
|
concept_source=ConceptSource.AUTO_DERIVED,
|
|
192
167
|
),
|
|
@@ -445,13 +445,16 @@ class Grain(Namespaced, BaseModel):
|
|
|
445
445
|
concepts: Iterable[Concept | ConceptRef | str],
|
|
446
446
|
environment: Environment | None = None,
|
|
447
447
|
where_clause: WhereClause | None = None,
|
|
448
|
+
local_concepts: dict[str, Concept] | None = None,
|
|
448
449
|
) -> Grain:
|
|
449
450
|
from trilogy.parsing.common import concepts_to_grain_concepts
|
|
450
451
|
|
|
451
452
|
x = Grain.model_construct(
|
|
452
453
|
components={
|
|
453
454
|
c.address
|
|
454
|
-
for c in concepts_to_grain_concepts(
|
|
455
|
+
for c in concepts_to_grain_concepts(
|
|
456
|
+
concepts, environment=environment, local_concepts=local_concepts
|
|
457
|
+
)
|
|
455
458
|
},
|
|
456
459
|
where_clause=where_clause,
|
|
457
460
|
)
|
|
@@ -126,9 +126,14 @@ def concept_is_relevant(
|
|
|
126
126
|
|
|
127
127
|
return False
|
|
128
128
|
if concept.purpose in (Purpose.PROPERTY, Purpose.METRIC) and concept.keys:
|
|
129
|
-
if
|
|
130
|
-
|
|
129
|
+
if all([c in others for c in concept.keys]):
|
|
131
130
|
return False
|
|
131
|
+
if (
|
|
132
|
+
concept.purpose == Purpose.KEY
|
|
133
|
+
and concept.keys
|
|
134
|
+
and all([c in others for c in concept.keys])
|
|
135
|
+
):
|
|
136
|
+
return False
|
|
132
137
|
if concept.purpose in (Purpose.METRIC,):
|
|
133
138
|
if all([c in others for c in concept.grain.components]):
|
|
134
139
|
return False
|
|
@@ -242,6 +247,17 @@ def get_concept_arguments(expr) -> List["BuildConcept"]:
|
|
|
242
247
|
return output
|
|
243
248
|
|
|
244
249
|
|
|
250
|
+
class BuildParamaterizedConceptReference(BaseModel):
|
|
251
|
+
concept: BuildConcept
|
|
252
|
+
|
|
253
|
+
def __str__(self):
|
|
254
|
+
return f":{self.concept.address}"
|
|
255
|
+
|
|
256
|
+
@property
|
|
257
|
+
def safe_address(self) -> str:
|
|
258
|
+
return self.concept.safe_address
|
|
259
|
+
|
|
260
|
+
|
|
245
261
|
class BuildGrain(BaseModel):
|
|
246
262
|
components: set[str] = Field(default_factory=set)
|
|
247
263
|
where_clause: Optional[BuildWhereClause] = None
|
|
@@ -1458,11 +1474,35 @@ class Factory:
|
|
|
1458
1474
|
{} if local_concepts is None else local_concepts
|
|
1459
1475
|
)
|
|
1460
1476
|
|
|
1477
|
+
def instantiate_concept(
|
|
1478
|
+
self,
|
|
1479
|
+
arg: (
|
|
1480
|
+
AggregateWrapper
|
|
1481
|
+
| FunctionCallWrapper
|
|
1482
|
+
| WindowItem
|
|
1483
|
+
| FilterItem
|
|
1484
|
+
| Function
|
|
1485
|
+
| ListWrapper[Any]
|
|
1486
|
+
| MapWrapper[Any, Any]
|
|
1487
|
+
| int
|
|
1488
|
+
| float
|
|
1489
|
+
| str
|
|
1490
|
+
),
|
|
1491
|
+
) -> tuple[Concept, BuildConcept]:
|
|
1492
|
+
from trilogy.parsing.common import arbitrary_to_concept
|
|
1493
|
+
|
|
1494
|
+
new = arbitrary_to_concept(
|
|
1495
|
+
arg,
|
|
1496
|
+
environment=self.environment,
|
|
1497
|
+
)
|
|
1498
|
+
built = self.build(new)
|
|
1499
|
+
self.local_concepts[new.address] = built
|
|
1500
|
+
return new, built
|
|
1501
|
+
|
|
1461
1502
|
@singledispatchmethod
|
|
1462
1503
|
def build(self, base):
|
|
1463
1504
|
raise NotImplementedError("Cannot build {}".format(type(base)))
|
|
1464
1505
|
|
|
1465
|
-
@build.register
|
|
1466
1506
|
@build.register
|
|
1467
1507
|
def _(
|
|
1468
1508
|
self,
|
|
@@ -1496,31 +1536,6 @@ class Factory:
|
|
|
1496
1536
|
):
|
|
1497
1537
|
return base
|
|
1498
1538
|
|
|
1499
|
-
def instantiate_concept(
|
|
1500
|
-
self,
|
|
1501
|
-
arg: (
|
|
1502
|
-
AggregateWrapper
|
|
1503
|
-
| FunctionCallWrapper
|
|
1504
|
-
| WindowItem
|
|
1505
|
-
| FilterItem
|
|
1506
|
-
| Function
|
|
1507
|
-
| ListWrapper[Any]
|
|
1508
|
-
| MapWrapper[Any, Any]
|
|
1509
|
-
| int
|
|
1510
|
-
| float
|
|
1511
|
-
| str
|
|
1512
|
-
),
|
|
1513
|
-
) -> tuple[Concept, BuildConcept]:
|
|
1514
|
-
from trilogy.parsing.common import arbitrary_to_concept
|
|
1515
|
-
|
|
1516
|
-
new = arbitrary_to_concept(
|
|
1517
|
-
arg,
|
|
1518
|
-
environment=self.environment,
|
|
1519
|
-
)
|
|
1520
|
-
built = self.build(new)
|
|
1521
|
-
self.local_concepts[new.address] = built
|
|
1522
|
-
return new, built
|
|
1523
|
-
|
|
1524
1539
|
@build.register
|
|
1525
1540
|
def _(self, base: None) -> None:
|
|
1526
1541
|
return base
|
|
@@ -1574,7 +1589,7 @@ class Factory:
|
|
|
1574
1589
|
|
|
1575
1590
|
new = BuildFunction.model_construct(
|
|
1576
1591
|
operator=base.operator,
|
|
1577
|
-
arguments=[self.build(c) for c in raw_args],
|
|
1592
|
+
arguments=[self.handle_constant(self.build(c)) for c in raw_args],
|
|
1578
1593
|
output_datatype=base.output_datatype,
|
|
1579
1594
|
output_purpose=base.output_purpose,
|
|
1580
1595
|
valid_inputs=base.valid_inputs,
|
|
@@ -1611,6 +1626,8 @@ class Factory:
|
|
|
1611
1626
|
|
|
1612
1627
|
@build.register
|
|
1613
1628
|
def _(self, base: Concept) -> BuildConcept:
|
|
1629
|
+
|
|
1630
|
+
# TODO: if we are using parameters, wrap it in a new model and use that in rendering
|
|
1614
1631
|
if base.address in self.local_concepts:
|
|
1615
1632
|
return self.local_concepts[base.address]
|
|
1616
1633
|
new_lineage, final_grain, _ = base.get_select_grain_and_keys(
|
|
@@ -1626,6 +1643,7 @@ class Factory:
|
|
|
1626
1643
|
derivation, final_grain, build_lineage
|
|
1627
1644
|
)
|
|
1628
1645
|
is_aggregate = Concept.calculate_is_aggregate(build_lineage)
|
|
1646
|
+
|
|
1629
1647
|
rval = BuildConcept.model_construct(
|
|
1630
1648
|
name=base.name,
|
|
1631
1649
|
datatype=base.datatype,
|
|
@@ -1646,7 +1664,6 @@ class Factory:
|
|
|
1646
1664
|
|
|
1647
1665
|
@build.register
|
|
1648
1666
|
def _(self, base: AggregateWrapper) -> BuildAggregateWrapper:
|
|
1649
|
-
|
|
1650
1667
|
if not base.by:
|
|
1651
1668
|
by = [
|
|
1652
1669
|
self.build(self.environment.concepts[c]) for c in self.grain.components
|
|
@@ -1734,8 +1751,8 @@ class Factory:
|
|
|
1734
1751
|
@build.register
|
|
1735
1752
|
def _(self, base: Conditional) -> BuildConditional:
|
|
1736
1753
|
return BuildConditional.model_construct(
|
|
1737
|
-
left=(self.build(base.left)),
|
|
1738
|
-
right=(self.build(base.right)),
|
|
1754
|
+
left=self.handle_constant(self.build(base.left)),
|
|
1755
|
+
right=self.handle_constant(self.build(base.right)),
|
|
1739
1756
|
operator=base.operator,
|
|
1740
1757
|
)
|
|
1741
1758
|
|
|
@@ -1763,8 +1780,8 @@ class Factory:
|
|
|
1763
1780
|
right_c, _ = self.instantiate_concept(right)
|
|
1764
1781
|
right = right_c # type: ignore
|
|
1765
1782
|
return BuildComparison.model_construct(
|
|
1766
|
-
left=(self.build(left)),
|
|
1767
|
-
right=(self.build(right)),
|
|
1783
|
+
left=self.handle_constant(self.build(left)),
|
|
1784
|
+
right=self.handle_constant(self.build(right)),
|
|
1768
1785
|
operator=base.operator,
|
|
1769
1786
|
)
|
|
1770
1787
|
|
|
@@ -2011,3 +2028,12 @@ class Factory:
|
|
|
2011
2028
|
factory.build(base.non_partial_for) if base.non_partial_for else None
|
|
2012
2029
|
),
|
|
2013
2030
|
)
|
|
2031
|
+
|
|
2032
|
+
def handle_constant(self, base):
|
|
2033
|
+
if (
|
|
2034
|
+
isinstance(base, BuildConcept)
|
|
2035
|
+
and isinstance(base.lineage, BuildFunction)
|
|
2036
|
+
and base.lineage.operator == FunctionType.CONSTANT
|
|
2037
|
+
):
|
|
2038
|
+
return BuildParamaterizedConceptReference(concept=base)
|
|
2039
|
+
return base
|
|
@@ -24,6 +24,7 @@ from trilogy.core.models.build import (
|
|
|
24
24
|
BuildFunction,
|
|
25
25
|
BuildGrain,
|
|
26
26
|
BuildOrderBy,
|
|
27
|
+
BuildParamaterizedConceptReference,
|
|
27
28
|
BuildParenthetical,
|
|
28
29
|
BuildRowsetItem,
|
|
29
30
|
LooseBuildConceptList,
|
|
@@ -447,7 +448,7 @@ class CTEConceptPair(ConceptPair):
|
|
|
447
448
|
|
|
448
449
|
|
|
449
450
|
class InstantiatedUnnestJoin(BaseModel):
|
|
450
|
-
|
|
451
|
+
object_to_unnest: BuildConcept | BuildParamaterizedConceptReference | BuildFunction
|
|
451
452
|
alias: str = "unnest"
|
|
452
453
|
|
|
453
454
|
|
|
@@ -5,7 +5,6 @@ from trilogy.core.models.build import (
|
|
|
5
5
|
)
|
|
6
6
|
from trilogy.core.models.execute import CTE, UnionCTE
|
|
7
7
|
from trilogy.core.optimizations import (
|
|
8
|
-
InlineConstant,
|
|
9
8
|
InlineDatasource,
|
|
10
9
|
OptimizationRule,
|
|
11
10
|
PredicatePushdown,
|
|
@@ -206,8 +205,6 @@ def optimize_ctes(
|
|
|
206
205
|
REGISTERED_RULES.append(PredicatePushdown())
|
|
207
206
|
if CONFIG.optimizations.predicate_pushdown:
|
|
208
207
|
REGISTERED_RULES.append(PredicatePushdownRemove())
|
|
209
|
-
if CONFIG.optimizations.constant_inlining:
|
|
210
|
-
REGISTERED_RULES.append(InlineConstant())
|
|
211
208
|
for rule in REGISTERED_RULES:
|
|
212
209
|
loops = 0
|
|
213
210
|
complete = False
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
from .base_optimization import OptimizationRule
|
|
2
|
-
from .inline_constant import InlineConstant
|
|
3
2
|
from .inline_datasource import InlineDatasource
|
|
4
3
|
from .predicate_pushdown import PredicatePushdown, PredicatePushdownRemove
|
|
5
4
|
|
|
6
5
|
__all__ = [
|
|
7
6
|
"OptimizationRule",
|
|
8
|
-
"InlineConstant",
|
|
9
7
|
"InlineDatasource",
|
|
10
8
|
"PredicatePushdown",
|
|
11
9
|
"PredicatePushdownRemove",
|
{pytrilogy-0.0.3.46 → pytrilogy-0.0.3.48}/trilogy/core/processing/node_generators/group_node.py
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import List
|
|
2
2
|
|
|
3
3
|
from trilogy.constants import logger
|
|
4
|
+
from trilogy.core.internal import ALL_ROWS_CONCEPT
|
|
4
5
|
from trilogy.core.models.build import (
|
|
5
6
|
BuildAggregateWrapper,
|
|
6
7
|
BuildConcept,
|
|
@@ -92,7 +93,9 @@ def gen_group_node(
|
|
|
92
93
|
logger.info(
|
|
93
94
|
f"{padding(depth)}{LOGGER_PREFIX} fetching group node parents {LooseBuildConceptList(concepts=parent_concepts)}"
|
|
94
95
|
)
|
|
95
|
-
parent_concepts = unique(
|
|
96
|
+
parent_concepts = unique(
|
|
97
|
+
[x for x in parent_concepts if not x.name == ALL_ROWS_CONCEPT], "address"
|
|
98
|
+
)
|
|
96
99
|
parent = source_concepts(
|
|
97
100
|
mandatory_list=parent_concepts,
|
|
98
101
|
environment=environment,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from pydantic import BaseModel, ConfigDict, Field
|
|
2
2
|
|
|
3
3
|
from trilogy.core.exceptions import UnresolvableQueryException
|
|
4
|
+
from trilogy.core.models.author import Concept
|
|
4
5
|
from trilogy.core.models.build import BuildConcept, BuildWhereClause
|
|
5
6
|
from trilogy.core.models.build_environment import BuildEnvironment
|
|
6
7
|
from trilogy.core.models.environment import Environment
|
|
@@ -17,6 +18,7 @@ from .window_node import WindowNode
|
|
|
17
18
|
|
|
18
19
|
class History(BaseModel):
|
|
19
20
|
base_environment: Environment
|
|
21
|
+
local_base_concepts: dict[str, Concept] = Field(default_factory=dict)
|
|
20
22
|
history: dict[str, StrategyNode | None] = Field(default_factory=dict)
|
|
21
23
|
select_history: dict[str, StrategyNode | None] = Field(default_factory=dict)
|
|
22
24
|
started: dict[str, int] = Field(default_factory=dict)
|