pytrilogy 0.0.3.19__tar.gz → 0.0.3.21__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.19/pytrilogy.egg-info → pytrilogy-0.0.3.21}/PKG-INFO +4 -3
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/README.md +2 -2
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21/pytrilogy.egg-info}/PKG-INFO +4 -3
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_parsing.py +74 -1
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/__init__.py +1 -1
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/constants.py +9 -1
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/enums.py +1 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/models/execute.py +8 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/statements/author.py +2 -2
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/dialect/base.py +13 -3
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/dialect/common.py +11 -1
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/dialect/config.py +10 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/dialect/enums.py +4 -1
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/dialect/snowflake.py +3 -1
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/executor.py +3 -2
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/parsing/parse_engine.py +29 -5
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/render.py +13 -9
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/LICENSE.md +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/pyproject.toml +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/pytrilogy.egg-info/SOURCES.txt +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/pytrilogy.egg-info/dependency_links.txt +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/pytrilogy.egg-info/entry_points.txt +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/pytrilogy.egg-info/requires.txt +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/pytrilogy.egg-info/top_level.txt +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/setup.cfg +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/setup.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_datatypes.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_declarations.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_derived_concepts.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_discovery_nodes.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_enums.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_environment.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_executor.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_functions.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_imports.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_metadata.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_models.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_multi_join_assignments.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_parse_engine.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_partial_handling.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_query_processing.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_query_render.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_select.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_show.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_statements.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_typing.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_undefined_concept.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_user_functions.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/tests/test_where_clause.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/authoring/__init__.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/compiler.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/__init__.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/constants.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/env_processor.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/environment_helpers.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/ergonomics.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/exceptions.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/functions.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/graph_models.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/internal.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/models/__init__.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/models/author.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/models/build.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/models/build_environment.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/models/core.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/models/datasource.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/models/environment.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/optimization.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/optimizations/__init__.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/optimizations/base_optimization.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/optimizations/inline_constant.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/optimizations/inline_datasource.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/__init__.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/concept_strategies_v3.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/graph_utils.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/__init__.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/basic_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/common.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/filter_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/group_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/group_to_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/multiselect_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/node_merge_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/rowset_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/select_helpers/__init__.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/select_merge_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/select_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/synonym_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/union_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/unnest_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/window_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/nodes/__init__.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/nodes/base_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/nodes/filter_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/nodes/group_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/nodes/merge_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/nodes/union_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/nodes/unnest_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/nodes/window_node.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/utility.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/query_processor.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/statements/__init__.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/statements/build.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/statements/common.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/statements/execute.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/dialect/__init__.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/dialect/bigquery.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/dialect/dataframe.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/dialect/duckdb.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/dialect/postgres.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/dialect/presto.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/dialect/sql_server.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/engine.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/hooks/__init__.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/hooks/base_hook.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/hooks/graph_hook.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/hooks/query_debugger.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/metadata/__init__.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/parser.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/parsing/__init__.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/parsing/common.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/parsing/config.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/parsing/exceptions.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/parsing/helpers.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/parsing/render.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/parsing/trilogy.lark +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/py.typed +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/scripts/__init__.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/scripts/trilogy.py +0 -0
- {pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/utility.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: pytrilogy
|
|
3
|
-
Version: 0.0.3.
|
|
3
|
+
Version: 0.0.3.21
|
|
4
4
|
Summary: Declarative, typed query language that compiles to SQL.
|
|
5
5
|
Home-page:
|
|
6
6
|
Author:
|
|
@@ -31,6 +31,7 @@ Dynamic: author-email
|
|
|
31
31
|
Dynamic: classifier
|
|
32
32
|
Dynamic: description
|
|
33
33
|
Dynamic: description-content-type
|
|
34
|
+
Dynamic: license-file
|
|
34
35
|
Dynamic: provides-extra
|
|
35
36
|
Dynamic: requires-dist
|
|
36
37
|
Dynamic: summary
|
|
@@ -44,7 +45,7 @@ pytrilogy is an experimental implementation of the Trilogy language, a higher-le
|
|
|
44
45
|
Trilogy looks like SQL, but simpler. It's a modern SQL refresh targeted at SQL lovers who want more reusability and composability without losing the expressiveness and iterative value of SQL. It compiles to SQL - making it easy to debug or integrate into existing workflows - and can be run against any supported SQL backend.
|
|
45
46
|
|
|
46
47
|
> [!TIP]
|
|
47
|
-
> To get an overview of the language and run interactive examples, head to the [documentation](https://trilogydata.dev/).
|
|
48
|
+
> Try it online in a hosted [open-source studio](https://trilogydata.dev/trilogy-studio-core/). To get an overview of the language and run interactive examples, head to the [documentation](https://trilogydata.dev/).
|
|
48
49
|
|
|
49
50
|
Installation: `pip install pytrilogy`
|
|
50
51
|
|
|
@@ -7,7 +7,7 @@ pytrilogy is an experimental implementation of the Trilogy language, a higher-le
|
|
|
7
7
|
Trilogy looks like SQL, but simpler. It's a modern SQL refresh targeted at SQL lovers who want more reusability and composability without losing the expressiveness and iterative value of SQL. It compiles to SQL - making it easy to debug or integrate into existing workflows - and can be run against any supported SQL backend.
|
|
8
8
|
|
|
9
9
|
> [!TIP]
|
|
10
|
-
> To get an overview of the language and run interactive examples, head to the [documentation](https://trilogydata.dev/).
|
|
10
|
+
> Try it online in a hosted [open-source studio](https://trilogydata.dev/trilogy-studio-core/). To get an overview of the language and run interactive examples, head to the [documentation](https://trilogydata.dev/).
|
|
11
11
|
|
|
12
12
|
Installation: `pip install pytrilogy`
|
|
13
13
|
|
|
@@ -353,4 +353,4 @@ Return generated SQL without executing.
|
|
|
353
353
|
|
|
354
354
|
```sql
|
|
355
355
|
show <select>;
|
|
356
|
-
```
|
|
356
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: pytrilogy
|
|
3
|
-
Version: 0.0.3.
|
|
3
|
+
Version: 0.0.3.21
|
|
4
4
|
Summary: Declarative, typed query language that compiles to SQL.
|
|
5
5
|
Home-page:
|
|
6
6
|
Author:
|
|
@@ -31,6 +31,7 @@ Dynamic: author-email
|
|
|
31
31
|
Dynamic: classifier
|
|
32
32
|
Dynamic: description
|
|
33
33
|
Dynamic: description-content-type
|
|
34
|
+
Dynamic: license-file
|
|
34
35
|
Dynamic: provides-extra
|
|
35
36
|
Dynamic: requires-dist
|
|
36
37
|
Dynamic: summary
|
|
@@ -44,7 +45,7 @@ pytrilogy is an experimental implementation of the Trilogy language, a higher-le
|
|
|
44
45
|
Trilogy looks like SQL, but simpler. It's a modern SQL refresh targeted at SQL lovers who want more reusability and composability without losing the expressiveness and iterative value of SQL. It compiles to SQL - making it easy to debug or integrate into existing workflows - and can be run against any supported SQL backend.
|
|
45
46
|
|
|
46
47
|
> [!TIP]
|
|
47
|
-
> To get an overview of the language and run interactive examples, head to the [documentation](https://trilogydata.dev/).
|
|
48
|
+
> Try it online in a hosted [open-source studio](https://trilogydata.dev/trilogy-studio-core/). To get an overview of the language and run interactive examples, head to the [documentation](https://trilogydata.dev/).
|
|
48
49
|
|
|
49
50
|
Installation: `pip install pytrilogy`
|
|
50
51
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
from pytest import raises
|
|
2
|
+
|
|
1
3
|
from trilogy import Dialects
|
|
2
|
-
from trilogy.constants import MagicConstants
|
|
4
|
+
from trilogy.constants import MagicConstants, Parsing
|
|
3
5
|
from trilogy.core.enums import BooleanOperator, ComparisonOperator, Purpose
|
|
4
6
|
from trilogy.core.functions import argument_to_purpose, function_args_to_output_purpose
|
|
5
7
|
from trilogy.core.models.author import Comparison
|
|
@@ -17,6 +19,7 @@ from trilogy.core.statements.author import SelectStatement, ShowStatement
|
|
|
17
19
|
from trilogy.core.statements.execute import ProcessedQuery
|
|
18
20
|
from trilogy.dialect.base import BaseDialect
|
|
19
21
|
from trilogy.parsing.parse_engine import (
|
|
22
|
+
ParseError,
|
|
20
23
|
arg_to_datatype,
|
|
21
24
|
parse_text,
|
|
22
25
|
)
|
|
@@ -661,3 +664,73 @@ select x % 10 -> x_mod_10;
|
|
|
661
664
|
|
|
662
665
|
"""
|
|
663
666
|
)
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
def test_import_shows_source():
|
|
670
|
+
|
|
671
|
+
env = Environment(
|
|
672
|
+
config=EnvironmentOptions(
|
|
673
|
+
import_resolver=DictImportResolver(
|
|
674
|
+
content={
|
|
675
|
+
"test": """
|
|
676
|
+
import test_dep as test_dep;
|
|
677
|
+
key x int;
|
|
678
|
+
datasource test (
|
|
679
|
+
x: x)
|
|
680
|
+
grain(x)
|
|
681
|
+
query '''
|
|
682
|
+
select 1 as x
|
|
683
|
+
union all
|
|
684
|
+
select 11 as x
|
|
685
|
+
''' TYPO
|
|
686
|
+
""",
|
|
687
|
+
"test_dep": """
|
|
688
|
+
key x int;
|
|
689
|
+
""",
|
|
690
|
+
}
|
|
691
|
+
)
|
|
692
|
+
)
|
|
693
|
+
)
|
|
694
|
+
assert isinstance(env.config.import_resolver, DictImportResolver)
|
|
695
|
+
|
|
696
|
+
with raises(Exception, match="Unable to import 'test', parsing error") as e:
|
|
697
|
+
env.parse(
|
|
698
|
+
"""
|
|
699
|
+
import test;
|
|
700
|
+
|
|
701
|
+
select x % 10 -> x_mod_10;
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
"""
|
|
705
|
+
)
|
|
706
|
+
assert "TYPO" in str(e.value)
|
|
707
|
+
assert 1 == 0
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
def test_concept_shadow_warning():
|
|
711
|
+
x = """
|
|
712
|
+
key scalar int;
|
|
713
|
+
property scalar.int_array list<int>;
|
|
714
|
+
|
|
715
|
+
key split <- unnest(int_array);
|
|
716
|
+
|
|
717
|
+
datasource avalues (
|
|
718
|
+
int_array: int_array,
|
|
719
|
+
scalar: scalar
|
|
720
|
+
)
|
|
721
|
+
grain (scalar)
|
|
722
|
+
query '''(
|
|
723
|
+
select [1,2,3,4] as int_array, 2 as scalar
|
|
724
|
+
union all
|
|
725
|
+
select [5,6,7,8] as int_array, 4 as scalar
|
|
726
|
+
)''';
|
|
727
|
+
|
|
728
|
+
SELECT
|
|
729
|
+
int_array,
|
|
730
|
+
sum(scalar)->scalar
|
|
731
|
+
;
|
|
732
|
+
"""
|
|
733
|
+
with raises(ParseError):
|
|
734
|
+
env, parsed = parse_text(
|
|
735
|
+
x, parse_config=Parsing(strict_name_shadow_enforcement=True)
|
|
736
|
+
)
|
|
@@ -47,6 +47,14 @@ class Rendering:
|
|
|
47
47
|
concise: bool = False
|
|
48
48
|
|
|
49
49
|
|
|
50
|
+
@dataclass
|
|
51
|
+
class Parsing:
|
|
52
|
+
"""Control Parsing"""
|
|
53
|
+
|
|
54
|
+
strict_name_shadow_enforcement: bool = False
|
|
55
|
+
select_as_definition: bool = True
|
|
56
|
+
|
|
57
|
+
|
|
50
58
|
# TODO: support loading from environments
|
|
51
59
|
@dataclass
|
|
52
60
|
class Config:
|
|
@@ -57,7 +65,7 @@ class Config:
|
|
|
57
65
|
comments: Comments = field(default_factory=Comments)
|
|
58
66
|
optimizations: Optimizations = field(default_factory=Optimizations)
|
|
59
67
|
rendering: Rendering = field(default_factory=Rendering)
|
|
60
|
-
|
|
68
|
+
parsing: Parsing = field(default_factory=Parsing)
|
|
61
69
|
|
|
62
70
|
@property
|
|
63
71
|
def show_comments(self) -> bool:
|
|
@@ -59,6 +59,14 @@ class CTE(BaseModel):
|
|
|
59
59
|
base_name_override: Optional[str] = None
|
|
60
60
|
base_alias_override: Optional[str] = None
|
|
61
61
|
|
|
62
|
+
@field_validator("join_derived_concepts")
|
|
63
|
+
def validate_join_derived_concepts(cls, v):
|
|
64
|
+
if len(v) > 1:
|
|
65
|
+
raise NotImplementedError(
|
|
66
|
+
"Multiple join derived concepts not yet supported."
|
|
67
|
+
)
|
|
68
|
+
return unique(v, "address")
|
|
69
|
+
|
|
62
70
|
@property
|
|
63
71
|
def identifier(self):
|
|
64
72
|
return self.name
|
|
@@ -142,7 +142,7 @@ class SelectStatement(HasUUID, SelectTypeMixin, BaseModel):
|
|
|
142
142
|
if isinstance(x.content.output, UndefinedConcept):
|
|
143
143
|
continue
|
|
144
144
|
if (
|
|
145
|
-
CONFIG.select_as_definition
|
|
145
|
+
CONFIG.parsing.select_as_definition
|
|
146
146
|
and not environment.frozen
|
|
147
147
|
and x.concept.address not in environment.concepts
|
|
148
148
|
):
|
|
@@ -156,7 +156,7 @@ class SelectStatement(HasUUID, SelectTypeMixin, BaseModel):
|
|
|
156
156
|
elif isinstance(x.content, ConceptRef):
|
|
157
157
|
output.local_concepts[x.content.address] = environment.concepts[
|
|
158
158
|
x.content.address
|
|
159
|
-
]
|
|
159
|
+
]
|
|
160
160
|
output.validate_syntax(environment)
|
|
161
161
|
return output
|
|
162
162
|
|
|
@@ -3,7 +3,7 @@ from typing import Any, Callable, Dict, List, Optional, Sequence, Union
|
|
|
3
3
|
|
|
4
4
|
from jinja2 import Template
|
|
5
5
|
|
|
6
|
-
from trilogy.constants import CONFIG, MagicConstants, logger
|
|
6
|
+
from trilogy.constants import CONFIG, MagicConstants, Rendering, logger
|
|
7
7
|
from trilogy.core.enums import (
|
|
8
8
|
DatePart,
|
|
9
9
|
FunctionType,
|
|
@@ -283,6 +283,9 @@ class BaseDialect:
|
|
|
283
283
|
DATATYPE_MAP = DATATYPE_MAP
|
|
284
284
|
UNNEST_MODE = UnnestMode.CROSS_APPLY
|
|
285
285
|
|
|
286
|
+
def __init__(self, rendering: Rendering | None = None):
|
|
287
|
+
self.rendering = rendering or CONFIG.rendering
|
|
288
|
+
|
|
286
289
|
def render_order_item(
|
|
287
290
|
self,
|
|
288
291
|
order_item: BuildOrderItem,
|
|
@@ -416,7 +419,7 @@ class BaseDialect:
|
|
|
416
419
|
elif (
|
|
417
420
|
isinstance(c.lineage, FUNCTION_ITEMS)
|
|
418
421
|
and c.lineage.operator == FunctionType.CONSTANT
|
|
419
|
-
and
|
|
422
|
+
and self.rendering.parameters is True
|
|
420
423
|
and c.datatype.data_type != DataType.MAP
|
|
421
424
|
):
|
|
422
425
|
rval = f":{c.safe_address}"
|
|
@@ -633,7 +636,7 @@ class BaseDialect:
|
|
|
633
636
|
if (
|
|
634
637
|
isinstance(e.lineage, FUNCTION_ITEMS)
|
|
635
638
|
and e.lineage.operator == FunctionType.CONSTANT
|
|
636
|
-
and
|
|
639
|
+
and self.rendering.parameters is True
|
|
637
640
|
and e.datatype.data_type != DataType.MAP
|
|
638
641
|
):
|
|
639
642
|
return f":{e.safe_address}"
|
|
@@ -694,6 +697,7 @@ class BaseDialect:
|
|
|
694
697
|
UnnestMode.CROSS_APPLY,
|
|
695
698
|
UnnestMode.CROSS_JOIN,
|
|
696
699
|
UnnestMode.CROSS_JOIN_ALIAS,
|
|
700
|
+
UnnestMode.SNOWFLAKE,
|
|
697
701
|
):
|
|
698
702
|
# for a cross apply, derivation happens in the join
|
|
699
703
|
# so we only use the alias to select
|
|
@@ -723,6 +727,12 @@ class BaseDialect:
|
|
|
723
727
|
UnnestMode.CROSS_JOIN,
|
|
724
728
|
UnnestMode.CROSS_APPLY,
|
|
725
729
|
):
|
|
730
|
+
|
|
731
|
+
source = f"{render_unnest(self.UNNEST_MODE, self.QUOTE_CHARACTER, cte.join_derived_concepts[0], self.render_concept_sql, cte)}"
|
|
732
|
+
elif (
|
|
733
|
+
cte.join_derived_concepts
|
|
734
|
+
and self.UNNEST_MODE == UnnestMode.SNOWFLAKE
|
|
735
|
+
):
|
|
726
736
|
source = f"{render_unnest(self.UNNEST_MODE, self.QUOTE_CHARACTER, cte.join_derived_concepts[0], self.render_concept_sql, cte)}"
|
|
727
737
|
# direct - eg DUCK DB - can be directly selected inline
|
|
728
738
|
elif (
|
|
@@ -25,7 +25,15 @@ def render_unnest(
|
|
|
25
25
|
):
|
|
26
26
|
if unnest_mode == UnnestMode.CROSS_JOIN:
|
|
27
27
|
return f"{render_func(concept, cte, False)} as {quote_character}{concept.safe_address}{quote_character}"
|
|
28
|
-
|
|
28
|
+
elif unnest_mode == UnnestMode.CROSS_JOIN_ALIAS:
|
|
29
|
+
return f"{render_func(concept, cte, False)} as unnest_wrapper ({quote_character}{concept.safe_address}{quote_character})"
|
|
30
|
+
elif unnest_mode == UnnestMode.SNOWFLAKE:
|
|
31
|
+
# if we don't actually have a join, we're directly unnesting a concept, and we can skip the flatten
|
|
32
|
+
if not cte.render_from_clause:
|
|
33
|
+
return f"{render_func(concept, cte, False)} as unnest_wrapper ( unnest1, unnest2, unnest3, unnest4, {quote_character}{cte.join_derived_concepts[0].safe_address}{quote_character})"
|
|
34
|
+
# otherwise, flatten the concept for the join
|
|
35
|
+
return f"flatten({render_func(concept, cte, False)}) as unnest_wrapper ( unnest1, unnest2, unnest3, unnest4, {quote_character}{cte.join_derived_concepts[0].safe_address}{quote_character})"
|
|
36
|
+
return f"{render_func(concept, cte, False)} as {quote_character}{concept.safe_address}{quote_character}"
|
|
29
37
|
|
|
30
38
|
|
|
31
39
|
def render_join_concept(
|
|
@@ -67,6 +75,8 @@ def render_join(
|
|
|
67
75
|
return f"CROSS JOIN {render_unnest(unnest_mode, quote_character, join.concept_to_unnest, render_func, cte)}"
|
|
68
76
|
if unnest_mode == UnnestMode.CROSS_JOIN_ALIAS:
|
|
69
77
|
return f"CROSS JOIN {render_unnest(unnest_mode, quote_character, join.concept_to_unnest, render_func, cte)}"
|
|
78
|
+
if unnest_mode == UnnestMode.SNOWFLAKE:
|
|
79
|
+
return f"LEFT JOIN LATERAL {render_unnest(unnest_mode, quote_character, join.concept_to_unnest, render_func, cte)}"
|
|
70
80
|
return f"FULL JOIN {render_unnest(unnest_mode, quote_character, join.concept_to_unnest, render_func, cte)}"
|
|
71
81
|
# left_name = join.left_name
|
|
72
82
|
right_name = join.right_name
|
|
@@ -76,12 +76,22 @@ class SnowflakeConfig(DialectConfig):
|
|
|
76
76
|
account: str,
|
|
77
77
|
username: str,
|
|
78
78
|
password: str,
|
|
79
|
+
database: str | None = None,
|
|
80
|
+
schema: str | None = None,
|
|
79
81
|
):
|
|
80
82
|
self.account = account
|
|
81
83
|
self.username = username
|
|
82
84
|
self.password = password
|
|
85
|
+
self.database = database
|
|
86
|
+
self.schema = schema
|
|
87
|
+
if self.schema and not self.database:
|
|
88
|
+
raise ValueError("Setting snowflake schema also requires setting database")
|
|
83
89
|
|
|
84
90
|
def connection_string(self) -> str:
|
|
91
|
+
if self.schema:
|
|
92
|
+
return f"snowflake://{self.username}:{self.password}@{self.account}/{self.database}/{self.schema}"
|
|
93
|
+
if self.database:
|
|
94
|
+
return f"snowflake://{self.username}:{self.password}@{self.account}/{self.database}"
|
|
85
95
|
return f"snowflake://{self.username}:{self.password}@{self.account}"
|
|
86
96
|
|
|
87
97
|
|
|
@@ -7,7 +7,7 @@ if TYPE_CHECKING:
|
|
|
7
7
|
from trilogy import Executor
|
|
8
8
|
from trilogy.hooks.base_hook import BaseHook
|
|
9
9
|
|
|
10
|
-
from trilogy.constants import logger
|
|
10
|
+
from trilogy.constants import Rendering, logger
|
|
11
11
|
from trilogy.dialect.config import DialectConfig
|
|
12
12
|
|
|
13
13
|
|
|
@@ -114,6 +114,7 @@ class Dialects(Enum):
|
|
|
114
114
|
environment: Optional["Environment"] = None,
|
|
115
115
|
hooks: List["BaseHook"] | None = None,
|
|
116
116
|
conf: DialectConfig | None = None,
|
|
117
|
+
rendering: Rendering | None = None,
|
|
117
118
|
_engine_factory: Callable | None = None,
|
|
118
119
|
) -> "Executor":
|
|
119
120
|
from trilogy import Executor
|
|
@@ -123,6 +124,7 @@ class Dialects(Enum):
|
|
|
123
124
|
engine=self.default_engine(conf=conf, _engine_factory=_engine_factory),
|
|
124
125
|
environment=environment or Environment(),
|
|
125
126
|
dialect=self,
|
|
127
|
+
rendering=rendering,
|
|
126
128
|
hooks=hooks,
|
|
127
129
|
)
|
|
128
130
|
|
|
@@ -130,5 +132,6 @@ class Dialects(Enum):
|
|
|
130
132
|
engine=self.default_engine(conf=conf),
|
|
131
133
|
environment=environment or Environment(),
|
|
132
134
|
dialect=self,
|
|
135
|
+
rendering=rendering,
|
|
133
136
|
hooks=hooks,
|
|
134
137
|
)
|
|
@@ -30,6 +30,8 @@ FUNCTION_MAP = {
|
|
|
30
30
|
FunctionType.QUARTER: lambda x: f"EXTRACT(QUARTER from {x[0]})",
|
|
31
31
|
# math
|
|
32
32
|
FunctionType.DIVIDE: lambda x: f"DIV0({x[0]},{x[1]})",
|
|
33
|
+
FunctionType.UNNEST: lambda x: f"table(flatten({x[0]}))",
|
|
34
|
+
FunctionType.ARRAY: lambda x: f"ARRAY_CONSTRUCT({', '.join(x)})",
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
FUNCTION_GRAIN_MATCH_MAP = {
|
|
@@ -83,4 +85,4 @@ class SnowflakeDialect(BaseDialect):
|
|
|
83
85
|
}
|
|
84
86
|
QUOTE_CHARACTER = '"'
|
|
85
87
|
SQL_TEMPLATE = BQ_SQL_TEMPLATE
|
|
86
|
-
UNNEST_MODE = UnnestMode.
|
|
88
|
+
UNNEST_MODE = UnnestMode.SNOWFLAKE
|
|
@@ -6,7 +6,7 @@ from typing import Any, Generator, List, Optional, Protocol
|
|
|
6
6
|
from sqlalchemy import text
|
|
7
7
|
from sqlalchemy.engine import CursorResult
|
|
8
8
|
|
|
9
|
-
from trilogy.constants import logger
|
|
9
|
+
from trilogy.constants import Rendering, logger
|
|
10
10
|
from trilogy.core.enums import FunctionType, Granularity, IOType
|
|
11
11
|
from trilogy.core.models.author import Concept, Function
|
|
12
12
|
from trilogy.core.models.build import BuildConcept, BuildFunction
|
|
@@ -75,6 +75,7 @@ class Executor(object):
|
|
|
75
75
|
dialect: Dialects,
|
|
76
76
|
engine: ExecutionEngine,
|
|
77
77
|
environment: Optional[Environment] = None,
|
|
78
|
+
rendering: Rendering | None = None,
|
|
78
79
|
hooks: List[BaseHook] | None = None,
|
|
79
80
|
):
|
|
80
81
|
self.dialect: Dialects = dialect
|
|
@@ -83,7 +84,7 @@ class Executor(object):
|
|
|
83
84
|
self.generator: BaseDialect
|
|
84
85
|
self.logger = logger
|
|
85
86
|
self.hooks = hooks
|
|
86
|
-
self.generator = get_dialect_generator(self.dialect)
|
|
87
|
+
self.generator = get_dialect_generator(self.dialect, rendering)
|
|
87
88
|
self.connection = self.engine.connect()
|
|
88
89
|
# TODO: make generic
|
|
89
90
|
if self.dialect == Dialects.DATAFRAME:
|
|
@@ -18,9 +18,11 @@ from lark.tree import Meta
|
|
|
18
18
|
from pydantic import ValidationError
|
|
19
19
|
|
|
20
20
|
from trilogy.constants import (
|
|
21
|
+
CONFIG,
|
|
21
22
|
DEFAULT_NAMESPACE,
|
|
22
23
|
NULL_VALUE,
|
|
23
24
|
MagicConstants,
|
|
25
|
+
Parsing,
|
|
24
26
|
)
|
|
25
27
|
from trilogy.core.enums import (
|
|
26
28
|
BooleanOperator,
|
|
@@ -282,6 +284,7 @@ class ParseToObjects(Transformer):
|
|
|
282
284
|
text_lookup: dict[Path | str, str] | None = None,
|
|
283
285
|
environment_lookup: dict[str, Environment] | None = None,
|
|
284
286
|
import_keys: list[str] | None = None,
|
|
287
|
+
parse_config: Parsing | None = None,
|
|
285
288
|
):
|
|
286
289
|
Transformer.__init__(self, True)
|
|
287
290
|
self.environment: Environment = environment
|
|
@@ -298,6 +301,7 @@ class ParseToObjects(Transformer):
|
|
|
298
301
|
self.parse_pass = ParsePass.INITIAL
|
|
299
302
|
self.function_factory = FunctionFactory(self.environment)
|
|
300
303
|
self.import_keys: list[str] = import_keys or ["root"]
|
|
304
|
+
self.parse_config: Parsing = parse_config or CONFIG.parsing
|
|
301
305
|
|
|
302
306
|
def set_text(self, text: str):
|
|
303
307
|
self.text_lookup[self.token_address] = text
|
|
@@ -983,7 +987,12 @@ class ParseToObjects(Transformer):
|
|
|
983
987
|
text = self.resolve_import_address(target)
|
|
984
988
|
self.text_lookup[token_lookup] = text
|
|
985
989
|
|
|
986
|
-
|
|
990
|
+
try:
|
|
991
|
+
raw_tokens = PARSER.parse(text)
|
|
992
|
+
except Exception as e:
|
|
993
|
+
raise ImportError(
|
|
994
|
+
f"Unable to import '{target}', parsing error: {e}"
|
|
995
|
+
) from e
|
|
987
996
|
self.tokens[token_lookup] = raw_tokens
|
|
988
997
|
|
|
989
998
|
if cache_lookup in self.parsed:
|
|
@@ -1009,6 +1018,7 @@ class ParseToObjects(Transformer):
|
|
|
1009
1018
|
tokens=self.tokens,
|
|
1010
1019
|
text_lookup=self.text_lookup,
|
|
1011
1020
|
import_keys=self.import_keys + [cache_key],
|
|
1021
|
+
parse_config=self.parse_config,
|
|
1012
1022
|
)
|
|
1013
1023
|
nparser.transform(raw_tokens)
|
|
1014
1024
|
self.parsed[cache_lookup] = nparser
|
|
@@ -1143,8 +1153,8 @@ class ParseToObjects(Transformer):
|
|
|
1143
1153
|
elif isinstance(arg, HavingClause):
|
|
1144
1154
|
having = arg
|
|
1145
1155
|
if not select_items:
|
|
1146
|
-
raise
|
|
1147
|
-
|
|
1156
|
+
raise ParseError("Malformed select, missing select items")
|
|
1157
|
+
pre_keys = set(self.environment.concepts.keys())
|
|
1148
1158
|
base = SelectStatement.from_inputs(
|
|
1149
1159
|
environment=self.environment,
|
|
1150
1160
|
selection=select_items,
|
|
@@ -1154,6 +1164,15 @@ class ParseToObjects(Transformer):
|
|
|
1154
1164
|
limit=limit,
|
|
1155
1165
|
meta=Metadata(line_number=meta.line),
|
|
1156
1166
|
)
|
|
1167
|
+
if (
|
|
1168
|
+
self.parse_pass == ParsePass.INITIAL
|
|
1169
|
+
and self.parse_config.strict_name_shadow_enforcement
|
|
1170
|
+
):
|
|
1171
|
+
intersection = base.locally_derived.intersection(pre_keys)
|
|
1172
|
+
if intersection:
|
|
1173
|
+
raise ParseError(
|
|
1174
|
+
f"Select statement {base} has derived concepts {list(intersection)} that shadow existing environment concepts, which may cause unexpected behavior. Rename these."
|
|
1175
|
+
)
|
|
1157
1176
|
return base
|
|
1158
1177
|
|
|
1159
1178
|
@v_args(meta=True)
|
|
@@ -1735,7 +1754,10 @@ def parse_text_raw(text: str, environment: Optional[Environment] = None):
|
|
|
1735
1754
|
|
|
1736
1755
|
|
|
1737
1756
|
def parse_text(
|
|
1738
|
-
text: str,
|
|
1757
|
+
text: str,
|
|
1758
|
+
environment: Optional[Environment] = None,
|
|
1759
|
+
root: Path | None = None,
|
|
1760
|
+
parse_config: Parsing | None = None,
|
|
1739
1761
|
) -> Tuple[
|
|
1740
1762
|
Environment,
|
|
1741
1763
|
List[
|
|
@@ -1751,7 +1773,9 @@ def parse_text(
|
|
|
1751
1773
|
environment = environment or (
|
|
1752
1774
|
Environment(working_path=root) if root else Environment()
|
|
1753
1775
|
)
|
|
1754
|
-
parser = ParseToObjects(
|
|
1776
|
+
parser = ParseToObjects(
|
|
1777
|
+
environment=environment, import_keys=["root"], parse_config=parse_config
|
|
1778
|
+
)
|
|
1755
1779
|
|
|
1756
1780
|
try:
|
|
1757
1781
|
parser.set_text(text)
|
|
@@ -1,38 +1,42 @@
|
|
|
1
|
+
from trilogy.constants import Rendering
|
|
2
|
+
from trilogy.dialect.base import BaseDialect
|
|
1
3
|
from trilogy.dialect.enums import Dialects
|
|
2
4
|
|
|
3
5
|
|
|
4
|
-
def get_dialect_generator(
|
|
6
|
+
def get_dialect_generator(
|
|
7
|
+
dialect: Dialects, rendering: Rendering | None = None
|
|
8
|
+
) -> BaseDialect:
|
|
5
9
|
if dialect == Dialects.BIGQUERY:
|
|
6
10
|
from trilogy.dialect.bigquery import BigqueryDialect
|
|
7
11
|
|
|
8
|
-
return BigqueryDialect()
|
|
12
|
+
return BigqueryDialect(rendering=rendering)
|
|
9
13
|
elif dialect == Dialects.SQL_SERVER:
|
|
10
14
|
from trilogy.dialect.sql_server import SqlServerDialect
|
|
11
15
|
|
|
12
|
-
return SqlServerDialect()
|
|
16
|
+
return SqlServerDialect(rendering=rendering)
|
|
13
17
|
elif dialect == Dialects.DUCK_DB:
|
|
14
18
|
from trilogy.dialect.duckdb import DuckDBDialect
|
|
15
19
|
|
|
16
|
-
return DuckDBDialect()
|
|
20
|
+
return DuckDBDialect(rendering=rendering)
|
|
17
21
|
elif dialect == Dialects.PRESTO:
|
|
18
22
|
from trilogy.dialect.presto import PrestoDialect
|
|
19
23
|
|
|
20
|
-
return PrestoDialect()
|
|
24
|
+
return PrestoDialect(rendering=rendering)
|
|
21
25
|
elif dialect == Dialects.TRINO:
|
|
22
26
|
from trilogy.dialect.presto import TrinoDialect
|
|
23
27
|
|
|
24
|
-
return TrinoDialect()
|
|
28
|
+
return TrinoDialect(rendering=rendering)
|
|
25
29
|
elif dialect == Dialects.POSTGRES:
|
|
26
30
|
from trilogy.dialect.postgres import PostgresDialect
|
|
27
31
|
|
|
28
|
-
return PostgresDialect()
|
|
32
|
+
return PostgresDialect(rendering=rendering)
|
|
29
33
|
elif dialect == Dialects.SNOWFLAKE:
|
|
30
34
|
from trilogy.dialect.snowflake import SnowflakeDialect
|
|
31
35
|
|
|
32
|
-
return SnowflakeDialect()
|
|
36
|
+
return SnowflakeDialect(rendering=rendering)
|
|
33
37
|
elif dialect == Dialects.DATAFRAME:
|
|
34
38
|
from trilogy.dialect.dataframe import DataframeDialect
|
|
35
39
|
|
|
36
|
-
return DataframeDialect()
|
|
40
|
+
return DataframeDialect(rendering=rendering)
|
|
37
41
|
else:
|
|
38
42
|
raise ValueError(f"Unsupported dialect {dialect}")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/__init__.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/basic_node.py
RENAMED
|
File without changes
|
|
File without changes
|
{pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/filter_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/group_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/group_to_node.py
RENAMED
|
File without changes
|
|
File without changes
|
{pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/node_merge_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/rowset_node.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/select_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/synonym_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/union_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/unnest_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.19 → pytrilogy-0.0.3.21}/trilogy/core/processing/node_generators/window_node.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|