pytrilogy 0.0.3.86__tar.gz → 0.0.3.89__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.86/pytrilogy.egg-info → pytrilogy-0.0.3.89}/PKG-INFO +1 -1
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89/pytrilogy.egg-info}/PKG-INFO +1 -1
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/__init__.py +1 -1
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/enums.py +9 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/functions.py +33 -2
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/models/author.py +41 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/models/build.py +5 -2
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/models/core.py +33 -3
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/models/execute.py +5 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/dialect/base.py +33 -14
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/dialect/presto.py +2 -1
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/parsing/parse_engine.py +37 -7
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/parsing/trilogy.lark +13 -4
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/LICENSE.md +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/README.md +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/pyproject.toml +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/pytrilogy.egg-info/SOURCES.txt +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/pytrilogy.egg-info/dependency_links.txt +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/pytrilogy.egg-info/entry_points.txt +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/pytrilogy.egg-info/requires.txt +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/pytrilogy.egg-info/top_level.txt +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/setup.cfg +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/setup.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_datatypes.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_declarations.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_derived_concepts.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_discovery_nodes.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_enums.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_environment.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_execute_models.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_executor.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_failure.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_functions.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_imports.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_metadata.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_models.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_multi_join_assignments.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_parse_engine.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_parsing.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_parsing_failures.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_partial_handling.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_query_processing.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_query_render.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_select.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_show.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_statements.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_typing.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_undefined_concept.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_user_functions.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/tests/test_where_clause.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/authoring/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/compiler.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/constants.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/constants.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/env_processor.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/environment_helpers.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/ergonomics.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/exceptions.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/graph_models.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/internal.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/models/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/models/build_environment.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/models/datasource.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/models/environment.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/optimization.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/optimizations/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/optimizations/base_optimization.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/optimizations/inline_datasource.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/concept_strategies_v3.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/discovery_loop.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/discovery_node_factory.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/discovery_utility.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/discovery_validation.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/graph_utils.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/basic_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/common.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/constant_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/filter_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/group_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/group_to_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/multiselect_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/node_merge_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/recursive_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/rowset_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/select_helpers/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/select_merge_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/select_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/synonym_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/union_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/unnest_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/window_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/nodes/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/nodes/base_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/nodes/filter_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/nodes/group_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/nodes/merge_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/nodes/recursive_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/nodes/union_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/nodes/unnest_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/nodes/window_node.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/utility.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/query_processor.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/statements/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/statements/author.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/statements/build.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/statements/common.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/statements/execute.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/utility.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/dialect/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/dialect/bigquery.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/dialect/common.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/dialect/config.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/dialect/dataframe.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/dialect/duckdb.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/dialect/enums.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/dialect/postgres.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/dialect/snowflake.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/dialect/sql_server.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/engine.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/executor.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/hooks/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/hooks/base_hook.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/hooks/graph_hook.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/hooks/query_debugger.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/metadata/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/parser.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/parsing/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/parsing/common.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/parsing/config.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/parsing/exceptions.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/parsing/helpers.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/parsing/render.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/py.typed +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/render.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/scripts/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/scripts/trilogy.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/std/__init__.py +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/std/date.preql +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/std/display.preql +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/std/geography.preql +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/std/money.preql +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/std/net.preql +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/std/ranking.preql +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/std/report.preql +0 -0
- {pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/utility.py +0 -0
|
@@ -13,6 +13,11 @@ class UnnestMode(Enum):
|
|
|
13
13
|
SNOWFLAKE = "snowflake"
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
class GroupMode(Enum):
|
|
17
|
+
AUTO = "auto"
|
|
18
|
+
BY_INDEX = "by_index"
|
|
19
|
+
|
|
20
|
+
|
|
16
21
|
class ConceptSource(Enum):
|
|
17
22
|
MANUAL = "manual"
|
|
18
23
|
CTE = "cte"
|
|
@@ -156,6 +161,10 @@ class FunctionType(Enum):
|
|
|
156
161
|
ARRAY_TRANSFORM = "array_transform"
|
|
157
162
|
ARRAY_TO_STRING = "array_to_string"
|
|
158
163
|
|
|
164
|
+
# MAP
|
|
165
|
+
MAP_KEYS = "map_keys"
|
|
166
|
+
MAP_VALUES = "map_values"
|
|
167
|
+
|
|
159
168
|
# TEXT AND MAYBE MORE
|
|
160
169
|
SPLIT = "split"
|
|
161
170
|
LENGTH = "len"
|
|
@@ -70,7 +70,7 @@ def get_coalesce_output_type(args: list[Any]) -> CONCRETE_TYPES:
|
|
|
70
70
|
|
|
71
71
|
|
|
72
72
|
def get_transform_output_type(args: list[Any]) -> CONCRETE_TYPES:
|
|
73
|
-
return arg_to_datatype(args[2])
|
|
73
|
+
return ArrayType(type=arg_to_datatype(args[2]))
|
|
74
74
|
|
|
75
75
|
|
|
76
76
|
def get_index_output_type(
|
|
@@ -92,7 +92,7 @@ def get_attr_datatype(
|
|
|
92
92
|
lookup = args[1]
|
|
93
93
|
datatype = arg_to_datatype(arg)
|
|
94
94
|
if isinstance(datatype, StructType):
|
|
95
|
-
return
|
|
95
|
+
return datatype.field_types[lookup]
|
|
96
96
|
return datatype
|
|
97
97
|
|
|
98
98
|
|
|
@@ -178,6 +178,20 @@ def get_date_trunc_output(
|
|
|
178
178
|
raise InvalidSyntaxException(f"Date truncation not supported for {target}")
|
|
179
179
|
|
|
180
180
|
|
|
181
|
+
def get_map_key_type(arg):
|
|
182
|
+
arg_datatype = arg_to_datatype(arg)
|
|
183
|
+
if isinstance(arg_datatype, MapType):
|
|
184
|
+
return ArrayType(type=arg_datatype.key_data_type)
|
|
185
|
+
return ArrayType(type=DataType.STRING)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def get_map_value_type(arg):
|
|
189
|
+
arg_datatype = arg_to_datatype(arg)
|
|
190
|
+
if isinstance(arg_datatype, MapType):
|
|
191
|
+
return ArrayType(type=arg_datatype.value_data_type)
|
|
192
|
+
return ArrayType(type=DataType.STRING)
|
|
193
|
+
|
|
194
|
+
|
|
181
195
|
FUNCTION_REGISTRY: dict[FunctionType, FunctionConfig] = {
|
|
182
196
|
FunctionType.ALIAS: FunctionConfig(
|
|
183
197
|
arg_count=1,
|
|
@@ -254,6 +268,22 @@ FUNCTION_REGISTRY: dict[FunctionType, FunctionConfig] = {
|
|
|
254
268
|
output_type_function=get_index_output_type,
|
|
255
269
|
arg_count=2,
|
|
256
270
|
),
|
|
271
|
+
FunctionType.MAP_KEYS: FunctionConfig(
|
|
272
|
+
valid_inputs={
|
|
273
|
+
DataType.MAP,
|
|
274
|
+
},
|
|
275
|
+
output_purpose=Purpose.PROPERTY,
|
|
276
|
+
output_type_function=lambda args: get_map_key_type(args[0]),
|
|
277
|
+
arg_count=1,
|
|
278
|
+
),
|
|
279
|
+
FunctionType.MAP_VALUES: FunctionConfig(
|
|
280
|
+
valid_inputs={
|
|
281
|
+
DataType.MAP,
|
|
282
|
+
},
|
|
283
|
+
output_purpose=Purpose.PROPERTY,
|
|
284
|
+
output_type_function=lambda args: get_map_value_type(args[0]),
|
|
285
|
+
arg_count=1,
|
|
286
|
+
),
|
|
257
287
|
FunctionType.ARRAY_DISTINCT: FunctionConfig(
|
|
258
288
|
valid_inputs={
|
|
259
289
|
DataType.ARRAY,
|
|
@@ -905,6 +935,7 @@ class FunctionFactory:
|
|
|
905
935
|
output_purpose = Purpose.METRIC
|
|
906
936
|
else:
|
|
907
937
|
output_purpose = Purpose.PROPERTY
|
|
938
|
+
|
|
908
939
|
return Function(
|
|
909
940
|
operator=operator,
|
|
910
941
|
arguments=full_args, # type: ignore
|
|
@@ -164,6 +164,26 @@ class ConceptRef(Addressable, Namespaced, DataTyped, Mergeable, BaseModel):
|
|
|
164
164
|
def with_reference_replacement(self, source: str, target: Expr | ArgBinding):
|
|
165
165
|
if self.address == source:
|
|
166
166
|
return target
|
|
167
|
+
|
|
168
|
+
# a reference might be to an attribute of a struct that is bound late
|
|
169
|
+
# if the replacement is a parent in the access path; replace reference
|
|
170
|
+
# with an attribute access call
|
|
171
|
+
candidates = [f"local.{self.address}", self.address]
|
|
172
|
+
for candidate in candidates:
|
|
173
|
+
if not candidate.startswith(f"{source}."):
|
|
174
|
+
continue
|
|
175
|
+
attribute = self.address.rsplit(".", 1)[1]
|
|
176
|
+
dtype = arg_to_datatype(target)
|
|
177
|
+
if not isinstance(dtype, StructType):
|
|
178
|
+
continue
|
|
179
|
+
output_type = dtype.field_types.get(attribute, DataType.UNKNOWN)
|
|
180
|
+
return Function(
|
|
181
|
+
arguments=[target, self.address.rsplit(".", 1)[1]],
|
|
182
|
+
operator=FunctionType.ATTR_ACCESS,
|
|
183
|
+
arg_count=2,
|
|
184
|
+
output_datatype=output_type,
|
|
185
|
+
output_purpose=Purpose.PROPERTY,
|
|
186
|
+
)
|
|
167
187
|
return self
|
|
168
188
|
|
|
169
189
|
|
|
@@ -1622,6 +1642,9 @@ class Function(DataTyped, ConceptArgs, Mergeable, Namespaced, BaseModel):
|
|
|
1622
1642
|
] = None
|
|
1623
1643
|
arguments: Sequence[FuncArgs]
|
|
1624
1644
|
|
|
1645
|
+
class Config:
|
|
1646
|
+
frozen = True
|
|
1647
|
+
|
|
1625
1648
|
def __repr__(self):
|
|
1626
1649
|
return f'{self.operator.value}({",".join([str(a) for a in self.arguments])})'
|
|
1627
1650
|
|
|
@@ -1632,6 +1655,16 @@ class Function(DataTyped, ConceptArgs, Mergeable, Namespaced, BaseModel):
|
|
|
1632
1655
|
def datatype(self):
|
|
1633
1656
|
return self.output_datatype
|
|
1634
1657
|
|
|
1658
|
+
@field_validator("output_datatype")
|
|
1659
|
+
@classmethod
|
|
1660
|
+
def parse_output_datatype(cls, v, info: ValidationInfo):
|
|
1661
|
+
values = info.data
|
|
1662
|
+
if values.get("operator") == FunctionType.ATTR_ACCESS:
|
|
1663
|
+
print(v)
|
|
1664
|
+
if isinstance(v, StructType):
|
|
1665
|
+
raise SyntaxError
|
|
1666
|
+
return v
|
|
1667
|
+
|
|
1635
1668
|
@field_validator("arguments", mode="before")
|
|
1636
1669
|
@classmethod
|
|
1637
1670
|
def parse_arguments(cls, v, info: ValidationInfo):
|
|
@@ -1730,8 +1763,16 @@ class Function(DataTyped, ConceptArgs, Mergeable, Namespaced, BaseModel):
|
|
|
1730
1763
|
]
|
|
1731
1764
|
if self.output_datatype == DataType.UNKNOWN:
|
|
1732
1765
|
new_output = merge_datatypes([arg_to_datatype(x) for x in nargs])
|
|
1766
|
+
|
|
1767
|
+
if self.operator == FunctionType.ATTR_ACCESS:
|
|
1768
|
+
if isinstance(new_output, StructType):
|
|
1769
|
+
new_output = new_output.field_types[str(nargs[1])]
|
|
1733
1770
|
else:
|
|
1734
1771
|
new_output = self.output_datatype
|
|
1772
|
+
# this is not ideal - see hacky logic for datatypes above
|
|
1773
|
+
# we need to figure out how to patch properly
|
|
1774
|
+
# should use function factory, but does not have environment access
|
|
1775
|
+
# probably move all datatype resolution to build?
|
|
1735
1776
|
return Function.model_construct(
|
|
1736
1777
|
operator=self.operator,
|
|
1737
1778
|
arguments=nargs,
|
|
@@ -1649,8 +1649,11 @@ class Factory:
|
|
|
1649
1649
|
full = self.local_concepts[base.address]
|
|
1650
1650
|
if isinstance(full, BuildConcept):
|
|
1651
1651
|
return full
|
|
1652
|
-
|
|
1653
|
-
|
|
1652
|
+
if base.address in self.environment.concepts:
|
|
1653
|
+
raw = self.environment.concepts[base.address]
|
|
1654
|
+
return self.build(raw)
|
|
1655
|
+
# this will error by design - TODO - more helpful message?
|
|
1656
|
+
return self.build(self.environment.concepts[base.address])
|
|
1654
1657
|
|
|
1655
1658
|
@build.register
|
|
1656
1659
|
def _(self, base: CaseWhen) -> BuildCaseWhen:
|
|
@@ -27,7 +27,7 @@ from pydantic_core import core_schema
|
|
|
27
27
|
from trilogy.constants import (
|
|
28
28
|
MagicConstants,
|
|
29
29
|
)
|
|
30
|
-
from trilogy.core.enums import Ordering
|
|
30
|
+
from trilogy.core.enums import Modifier, Ordering
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
class DataTyped(ABC):
|
|
@@ -211,9 +211,19 @@ class MapType(BaseModel):
|
|
|
211
211
|
return self.key_type
|
|
212
212
|
|
|
213
213
|
|
|
214
|
+
class StructComponent(BaseModel):
|
|
215
|
+
name: str
|
|
216
|
+
type: TYPEDEF_TYPES
|
|
217
|
+
modifiers: list[Modifier] = []
|
|
218
|
+
|
|
219
|
+
@field_validator("type", mode="plain")
|
|
220
|
+
def validate_Type(cls, v):
|
|
221
|
+
return v
|
|
222
|
+
|
|
223
|
+
|
|
214
224
|
class StructType(BaseModel):
|
|
215
|
-
fields: Sequence[TYPEDEF_TYPES]
|
|
216
|
-
fields_map: Dict[str, DataTyped | int | float | str]
|
|
225
|
+
fields: Sequence[StructComponent | TYPEDEF_TYPES]
|
|
226
|
+
fields_map: Dict[str, DataTyped | int | float | str | StructComponent]
|
|
217
227
|
|
|
218
228
|
@field_validator("fields", mode="plain")
|
|
219
229
|
def validate_type(cls, v):
|
|
@@ -234,6 +244,22 @@ class StructType(BaseModel):
|
|
|
234
244
|
def value(self):
|
|
235
245
|
return self.data_type.value
|
|
236
246
|
|
|
247
|
+
@property
|
|
248
|
+
def field_types(self) -> Dict[str, CONCRETE_TYPES]:
|
|
249
|
+
out: Dict[str, CONCRETE_TYPES] = {}
|
|
250
|
+
keys = list(self.fields_map.keys())
|
|
251
|
+
for idx, field in enumerate(self.fields):
|
|
252
|
+
if isinstance(field, StructComponent):
|
|
253
|
+
out[field.name] = arg_to_datatype(field.type)
|
|
254
|
+
elif isinstance(field, DataTyped):
|
|
255
|
+
out[keys[idx]] = field.output_datatype
|
|
256
|
+
else:
|
|
257
|
+
out[keys[idx]] = field
|
|
258
|
+
return out
|
|
259
|
+
|
|
260
|
+
def __hash__(self):
|
|
261
|
+
return hash(str(self))
|
|
262
|
+
|
|
237
263
|
|
|
238
264
|
class ListWrapper(Generic[VT], UserList):
|
|
239
265
|
"""Used to distinguish parsed list objects from other lists"""
|
|
@@ -401,6 +427,8 @@ def arg_to_datatype(arg) -> CONCRETE_TYPES:
|
|
|
401
427
|
return DataType.STRING
|
|
402
428
|
elif isinstance(arg, float):
|
|
403
429
|
return DataType.FLOAT
|
|
430
|
+
elif isinstance(arg, DataType):
|
|
431
|
+
return arg
|
|
404
432
|
elif isinstance(arg, NumericType):
|
|
405
433
|
return arg
|
|
406
434
|
elif isinstance(arg, TraitDataType):
|
|
@@ -420,6 +448,8 @@ def arg_to_datatype(arg) -> CONCRETE_TYPES:
|
|
|
420
448
|
return DataType.DATETIME
|
|
421
449
|
elif isinstance(arg, date):
|
|
422
450
|
return DataType.DATE
|
|
451
|
+
elif isinstance(arg, StructComponent):
|
|
452
|
+
return arg_to_datatype(arg.type)
|
|
423
453
|
else:
|
|
424
454
|
raise ValueError(
|
|
425
455
|
f"Cannot parse arg datatype for arg of raw type {type(arg)} value {arg}"
|
|
@@ -1076,6 +1076,11 @@ class UnionCTE(BaseModel):
|
|
|
1076
1076
|
def group_to_grain(self) -> bool:
|
|
1077
1077
|
return False
|
|
1078
1078
|
|
|
1079
|
+
@property
|
|
1080
|
+
def group_concepts(self) -> List[BuildConcept]:
|
|
1081
|
+
# unions should always be on unique sets
|
|
1082
|
+
return []
|
|
1083
|
+
|
|
1079
1084
|
def __add__(self, other):
|
|
1080
1085
|
if not isinstance(other, UnionCTE) or not other.name == self.name:
|
|
1081
1086
|
raise SyntaxError("Cannot merge union CTEs")
|
|
@@ -15,6 +15,7 @@ from trilogy.core.enums import (
|
|
|
15
15
|
ComparisonOperator,
|
|
16
16
|
DatePart,
|
|
17
17
|
FunctionType,
|
|
18
|
+
GroupMode,
|
|
18
19
|
Ordering,
|
|
19
20
|
ShowCategory,
|
|
20
21
|
UnnestMode,
|
|
@@ -186,6 +187,9 @@ FUNCTION_MAP = {
|
|
|
186
187
|
FunctionType.ARRAY: lambda x: f"[{', '.join(x)}]",
|
|
187
188
|
FunctionType.DATE_LITERAL: lambda x: f"date '{x}'",
|
|
188
189
|
FunctionType.DATETIME_LITERAL: lambda x: f"datetime '{x}'",
|
|
190
|
+
# MAP
|
|
191
|
+
FunctionType.MAP_KEYS: lambda x: f"map_keys({x[0]})",
|
|
192
|
+
FunctionType.MAP_VALUES: lambda x: f"map_values({x[0]})",
|
|
189
193
|
# ARRAY
|
|
190
194
|
FunctionType.ARRAY_SUM: lambda x: f"array_sum({x[0]})",
|
|
191
195
|
FunctionType.ARRAY_DISTINCT: lambda x: f"array_distinct({x[0]})",
|
|
@@ -338,6 +342,7 @@ class BaseDialect:
|
|
|
338
342
|
DATATYPE_MAP = DATATYPE_MAP
|
|
339
343
|
COMPLEX_DATATYPE_MAP = COMPLEX_DATATYPE_MAP
|
|
340
344
|
UNNEST_MODE = UnnestMode.CROSS_APPLY
|
|
345
|
+
GROUP_MODE = GroupMode.AUTO
|
|
341
346
|
|
|
342
347
|
def __init__(self, rendering: Rendering | None = None):
|
|
343
348
|
self.rendering = rendering or CONFIG.rendering
|
|
@@ -775,6 +780,33 @@ class BaseDialect:
|
|
|
775
780
|
else:
|
|
776
781
|
raise ValueError(f"Unable to render type {type(e)} {e}")
|
|
777
782
|
|
|
783
|
+
def render_cte_group_by(
|
|
784
|
+
self, cte: CTE | UnionCTE, select_columns
|
|
785
|
+
) -> Optional[list[str]]:
|
|
786
|
+
|
|
787
|
+
if not cte.group_to_grain:
|
|
788
|
+
return None
|
|
789
|
+
base = set(
|
|
790
|
+
[self.render_concept_sql(c, cte, alias=False) for c in cte.group_concepts]
|
|
791
|
+
)
|
|
792
|
+
if self.GROUP_MODE == GroupMode.AUTO:
|
|
793
|
+
return sorted(list(base))
|
|
794
|
+
|
|
795
|
+
else:
|
|
796
|
+
# find the index of each column in the select columns
|
|
797
|
+
final = []
|
|
798
|
+
found = []
|
|
799
|
+
for idx, c in enumerate(select_columns):
|
|
800
|
+
pre_alias = c.split(" as ")[0]
|
|
801
|
+
if pre_alias in base:
|
|
802
|
+
final.append(str(idx + 1))
|
|
803
|
+
found.append(pre_alias)
|
|
804
|
+
if not all(c in found for c in base):
|
|
805
|
+
raise ValueError(
|
|
806
|
+
f"Group by columns {base} not found in select columns {select_columns}"
|
|
807
|
+
)
|
|
808
|
+
return final
|
|
809
|
+
|
|
778
810
|
def render_cte(self, cte: CTE | UnionCTE, auto_sort: bool = True) -> CompiledCTE:
|
|
779
811
|
if isinstance(cte, UnionCTE):
|
|
780
812
|
base_statement = f"\n{cte.operator}\n".join(
|
|
@@ -926,20 +958,7 @@ class BaseDialect:
|
|
|
926
958
|
if cte.order_by
|
|
927
959
|
else None
|
|
928
960
|
),
|
|
929
|
-
group_by=(
|
|
930
|
-
sorted(
|
|
931
|
-
list(
|
|
932
|
-
set(
|
|
933
|
-
[
|
|
934
|
-
self.render_concept_sql(c, cte, alias=False)
|
|
935
|
-
for c in cte.group_concepts
|
|
936
|
-
]
|
|
937
|
-
)
|
|
938
|
-
)
|
|
939
|
-
)
|
|
940
|
-
if cte.group_to_grain
|
|
941
|
-
else None
|
|
942
|
-
),
|
|
961
|
+
group_by=self.render_cte_group_by(cte, select_columns),
|
|
943
962
|
),
|
|
944
963
|
)
|
|
945
964
|
|
|
@@ -2,7 +2,7 @@ from typing import Any, Callable, Mapping
|
|
|
2
2
|
|
|
3
3
|
from jinja2 import Template
|
|
4
4
|
|
|
5
|
-
from trilogy.core.enums import FunctionType, UnnestMode, WindowType
|
|
5
|
+
from trilogy.core.enums import FunctionType, GroupMode, UnnestMode, WindowType
|
|
6
6
|
from trilogy.core.models.core import DataType
|
|
7
7
|
from trilogy.dialect.base import BaseDialect
|
|
8
8
|
|
|
@@ -94,6 +94,7 @@ class PrestoDialect(BaseDialect):
|
|
|
94
94
|
DataType.STRING: "VARCHAR",
|
|
95
95
|
}
|
|
96
96
|
UNNEST_MODE = UnnestMode.PRESTO
|
|
97
|
+
GROUP_MODE = GroupMode.BY_INDEX
|
|
97
98
|
|
|
98
99
|
|
|
99
100
|
class TrinoDialect(PrestoDialect):
|
|
@@ -89,6 +89,7 @@ from trilogy.core.models.core import (
|
|
|
89
89
|
MapType,
|
|
90
90
|
MapWrapper,
|
|
91
91
|
NumericType,
|
|
92
|
+
StructComponent,
|
|
92
93
|
StructType,
|
|
93
94
|
TraitDataType,
|
|
94
95
|
TupleWrapper,
|
|
@@ -443,20 +444,39 @@ class ParseToObjects(Transformer):
|
|
|
443
444
|
def MINUS(self, args) -> str:
|
|
444
445
|
return "-"
|
|
445
446
|
|
|
447
|
+
@v_args(meta=True)
|
|
448
|
+
def struct_component(self, meta: Meta, args) -> StructComponent:
|
|
449
|
+
modifiers = []
|
|
450
|
+
for arg in args:
|
|
451
|
+
if isinstance(arg, Modifier):
|
|
452
|
+
modifiers.append(arg)
|
|
453
|
+
return StructComponent(name=args[0], type=args[1], modifiers=modifiers)
|
|
454
|
+
|
|
446
455
|
@v_args(meta=True)
|
|
447
456
|
def struct_type(self, meta: Meta, args) -> StructType:
|
|
448
457
|
final: list[
|
|
449
|
-
DataType
|
|
458
|
+
DataType
|
|
459
|
+
| MapType
|
|
460
|
+
| ArrayType
|
|
461
|
+
| NumericType
|
|
462
|
+
| StructType
|
|
463
|
+
| StructComponent
|
|
464
|
+
| Concept
|
|
450
465
|
] = []
|
|
451
466
|
for arg in args:
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
467
|
+
if isinstance(arg, StructComponent):
|
|
468
|
+
final.append(arg)
|
|
469
|
+
else:
|
|
470
|
+
new = self.environment.concepts.__getitem__( # type: ignore
|
|
471
|
+
key=arg, line_no=meta.line
|
|
472
|
+
)
|
|
473
|
+
final.append(new)
|
|
456
474
|
|
|
457
475
|
return StructType(
|
|
458
476
|
fields=final,
|
|
459
|
-
fields_map={
|
|
477
|
+
fields_map={
|
|
478
|
+
x.name: x for x in final if isinstance(x, (Concept, StructComponent))
|
|
479
|
+
},
|
|
460
480
|
)
|
|
461
481
|
|
|
462
482
|
def list_type(self, args) -> ArrayType:
|
|
@@ -681,6 +701,7 @@ class ParseToObjects(Transformer):
|
|
|
681
701
|
environment=self.environment,
|
|
682
702
|
metadata=metadata,
|
|
683
703
|
)
|
|
704
|
+
|
|
684
705
|
# let constant purposes exist to support round-tripping
|
|
685
706
|
# as a build concept may end up with a constant based on constant inlining happening recursively
|
|
686
707
|
if purpose == Purpose.KEY and concept.purpose != Purpose.KEY:
|
|
@@ -902,7 +923,6 @@ class ParseToObjects(Transformer):
|
|
|
902
923
|
name=output,
|
|
903
924
|
metadata=metadata,
|
|
904
925
|
)
|
|
905
|
-
|
|
906
926
|
return ConceptTransform(function=transformation, output=concept)
|
|
907
927
|
|
|
908
928
|
@v_args(meta=True)
|
|
@@ -2026,6 +2046,16 @@ class ParseToObjects(Transformer):
|
|
|
2026
2046
|
def fbool(self, meta, args):
|
|
2027
2047
|
return self.function_factory.create_function(args, FunctionType.BOOL, meta)
|
|
2028
2048
|
|
|
2049
|
+
@v_args(meta=True)
|
|
2050
|
+
def fmap_keys(self, meta, args):
|
|
2051
|
+
return self.function_factory.create_function(args, FunctionType.MAP_KEYS, meta)
|
|
2052
|
+
|
|
2053
|
+
@v_args(meta=True)
|
|
2054
|
+
def fmap_values(self, meta, args):
|
|
2055
|
+
return self.function_factory.create_function(
|
|
2056
|
+
args, FunctionType.MAP_VALUES, meta
|
|
2057
|
+
)
|
|
2058
|
+
|
|
2029
2059
|
@v_args(meta=True)
|
|
2030
2060
|
def farray_sum(self, meta, args):
|
|
2031
2061
|
return self.function_factory.create_function(args, FunctionType.ARRAY_SUM, meta)
|
|
@@ -181,7 +181,8 @@
|
|
|
181
181
|
//indexing into an expression is a function
|
|
182
182
|
index_access: atom "[" int_lit "]"
|
|
183
183
|
map_key_access: atom "[" string_lit "]"
|
|
184
|
-
|
|
184
|
+
_ATTR_ACCESS.1 : "getattr("i
|
|
185
|
+
attr_access: ( _ATTR_ACCESS atom "," string_lit ")") | (atom "." string_lit)
|
|
185
186
|
|
|
186
187
|
?expr: comparison_root | between_root
|
|
187
188
|
|
|
@@ -309,6 +310,14 @@
|
|
|
309
310
|
farray_transform: _ARRAY_TRANSFORM expr "," transform_lambda ")"
|
|
310
311
|
|
|
311
312
|
_array_functions: farray_sum | farray_distinct | farray_sort | farray_transform | farray_to_string
|
|
313
|
+
|
|
314
|
+
//map_functions
|
|
315
|
+
_MAP_KEYS.1: "map_keys("i
|
|
316
|
+
fmap_keys: _MAP_KEYS expr ")"
|
|
317
|
+
_MAP_VALUES.1: "map_values("i
|
|
318
|
+
fmap_values: _MAP_VALUES expr ")"
|
|
319
|
+
|
|
320
|
+
_map_functions: fmap_keys | fmap_values
|
|
312
321
|
|
|
313
322
|
// special aggregate
|
|
314
323
|
_GROUP.1: "group("i
|
|
@@ -380,7 +389,7 @@
|
|
|
380
389
|
|
|
381
390
|
_date_functions: fdate | fdate_add | fdate_sub | fdate_diff | fdatetime | ftimestamp | fsecond | fminute | fhour | fday | fday_of_week | fweek | fmonth | fquarter | fyear | fdate_part | fdate_trunc
|
|
382
391
|
|
|
383
|
-
_static_functions: _string_functions | _math_functions | _array_functions
|
|
392
|
+
_static_functions: _string_functions | _math_functions | _array_functions | _map_functions
|
|
384
393
|
|
|
385
394
|
custom_function: "@" IDENTIFIER "(" (expr ",")* expr ")"
|
|
386
395
|
|
|
@@ -424,8 +433,8 @@
|
|
|
424
433
|
MODIFIER: /OPTIONAL|PARTIAL|NULLABLE/i
|
|
425
434
|
|
|
426
435
|
SHORTHAND_MODIFIER: /~|\?/
|
|
427
|
-
|
|
428
|
-
struct_type: "struct"i "<" ((
|
|
436
|
+
struct_component: IDENTIFIER ":" data_type concept_nullable_modifier? metadata?
|
|
437
|
+
struct_type: "struct"i "<" ((struct_component | IDENTIFIER) ",")* (struct_component | IDENTIFIER) ","? ">"
|
|
429
438
|
|
|
430
439
|
list_type: ("list"i | "array"i) "<" (data_type | IDENTIFIER) ">"
|
|
431
440
|
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/__init__.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/basic_node.py
RENAMED
|
File without changes
|
|
File without changes
|
{pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/constant_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/filter_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/group_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/group_to_node.py
RENAMED
|
File without changes
|
|
File without changes
|
{pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/node_merge_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/recursive_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/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.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/select_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/synonym_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/union_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/trilogy/core/processing/node_generators/unnest_node.py
RENAMED
|
File without changes
|
{pytrilogy-0.0.3.86 → pytrilogy-0.0.3.89}/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
|
|
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
|