pytrilogy 0.0.2.29__tar.gz → 0.0.2.31__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.

Files changed (108) hide show
  1. {pytrilogy-0.0.2.29/pytrilogy.egg-info → pytrilogy-0.0.2.31}/PKG-INFO +1 -1
  2. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31/pytrilogy.egg-info}/PKG-INFO +1 -1
  3. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_functions.py +21 -0
  4. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/__init__.py +1 -1
  5. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/parsing/parse_engine.py +18 -10
  6. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/parsing/render.py +19 -1
  7. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/LICENSE.md +0 -0
  8. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/README.md +0 -0
  9. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/pyproject.toml +0 -0
  10. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/pytrilogy.egg-info/SOURCES.txt +0 -0
  11. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/pytrilogy.egg-info/dependency_links.txt +0 -0
  12. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/pytrilogy.egg-info/entry_points.txt +0 -0
  13. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/pytrilogy.egg-info/requires.txt +0 -0
  14. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/pytrilogy.egg-info/top_level.txt +0 -0
  15. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/setup.cfg +0 -0
  16. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/setup.py +0 -0
  17. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_datatypes.py +0 -0
  18. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_declarations.py +0 -0
  19. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_derived_concepts.py +0 -0
  20. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_discovery_nodes.py +0 -0
  21. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_environment.py +0 -0
  22. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_executor.py +0 -0
  23. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_imports.py +0 -0
  24. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_metadata.py +0 -0
  25. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_models.py +0 -0
  26. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_multi_join_assignments.py +0 -0
  27. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_parsing.py +0 -0
  28. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_partial_handling.py +0 -0
  29. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_query_processing.py +0 -0
  30. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_select.py +0 -0
  31. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_show.py +0 -0
  32. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_statements.py +0 -0
  33. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_undefined_concept.py +0 -0
  34. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/tests/test_where_clause.py +0 -0
  35. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/compiler.py +0 -0
  36. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/constants.py +0 -0
  37. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/__init__.py +0 -0
  38. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/constants.py +0 -0
  39. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/enums.py +0 -0
  40. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/env_processor.py +0 -0
  41. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/environment_helpers.py +0 -0
  42. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/ergonomics.py +0 -0
  43. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/exceptions.py +0 -0
  44. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/functions.py +0 -0
  45. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/graph_models.py +0 -0
  46. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/internal.py +0 -0
  47. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/models.py +0 -0
  48. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/optimization.py +0 -0
  49. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/optimizations/__init__.py +0 -0
  50. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/optimizations/base_optimization.py +0 -0
  51. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/optimizations/inline_constant.py +0 -0
  52. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/optimizations/inline_datasource.py +0 -0
  53. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
  54. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/__init__.py +0 -0
  55. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/concept_strategies_v3.py +0 -0
  56. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/graph_utils.py +0 -0
  57. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/node_generators/__init__.py +0 -0
  58. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/node_generators/basic_node.py +0 -0
  59. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/node_generators/common.py +0 -0
  60. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/node_generators/filter_node.py +0 -0
  61. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/node_generators/group_node.py +0 -0
  62. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/node_generators/group_to_node.py +0 -0
  63. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/node_generators/multiselect_node.py +0 -0
  64. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/node_generators/node_merge_node.py +0 -0
  65. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/node_generators/rowset_node.py +0 -0
  66. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/node_generators/select_merge_node.py +0 -0
  67. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/node_generators/select_node.py +0 -0
  68. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/node_generators/unnest_node.py +0 -0
  69. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/node_generators/window_node.py +0 -0
  70. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/nodes/__init__.py +0 -0
  71. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/nodes/base_node.py +0 -0
  72. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/nodes/filter_node.py +0 -0
  73. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/nodes/group_node.py +0 -0
  74. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/nodes/merge_node.py +0 -0
  75. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
  76. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/nodes/unnest_node.py +0 -0
  77. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/nodes/window_node.py +0 -0
  78. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/processing/utility.py +0 -0
  79. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/core/query_processor.py +0 -0
  80. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/dialect/__init__.py +0 -0
  81. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/dialect/base.py +0 -0
  82. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/dialect/bigquery.py +0 -0
  83. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/dialect/common.py +0 -0
  84. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/dialect/config.py +0 -0
  85. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/dialect/duckdb.py +0 -0
  86. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/dialect/enums.py +0 -0
  87. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/dialect/postgres.py +0 -0
  88. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/dialect/presto.py +0 -0
  89. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/dialect/snowflake.py +0 -0
  90. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/dialect/sql_server.py +0 -0
  91. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/engine.py +0 -0
  92. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/executor.py +0 -0
  93. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/hooks/__init__.py +0 -0
  94. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/hooks/base_hook.py +0 -0
  95. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/hooks/graph_hook.py +0 -0
  96. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/hooks/query_debugger.py +0 -0
  97. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/metadata/__init__.py +0 -0
  98. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/parser.py +0 -0
  99. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/parsing/__init__.py +0 -0
  100. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/parsing/common.py +0 -0
  101. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/parsing/config.py +0 -0
  102. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/parsing/exceptions.py +0 -0
  103. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/parsing/helpers.py +0 -0
  104. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/parsing/trilogy.lark +0 -0
  105. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/py.typed +0 -0
  106. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/scripts/__init__.py +0 -0
  107. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/scripts/trilogy.py +0 -0
  108. {pytrilogy-0.0.2.29 → pytrilogy-0.0.2.31}/trilogy/utility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pytrilogy
3
- Version: 0.0.2.29
3
+ Version: 0.0.2.31
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pytrilogy
3
- Version: 0.0.2.29
3
+ Version: 0.0.2.31
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -212,6 +212,27 @@ def test_case_function(test_environment):
212
212
  assert test_environment.concepts["test_upper_case"].datatype == DataType.BOOL
213
213
 
214
214
 
215
+ def test_case_like_function(test_environment):
216
+ declarations = """
217
+ property test_like <- CASE WHEN category_name like '%abc%' then True else False END;
218
+ select
219
+ category_name,
220
+ test_like
221
+ ;"""
222
+ env, parsed = parse(declarations, environment=test_environment)
223
+ assert (
224
+ test_environment.concepts["category_name"]
225
+ in test_environment.concepts["test_like"].lineage.concept_arguments
226
+ )
227
+ select: SelectStatement = parsed[-1]
228
+ for dialect in TEST_DIALECTS:
229
+ compiled = dialect.compile_statement(process_query(test_environment, select))
230
+ assert "CASE" in compiled
231
+ assert "ELSE" in compiled
232
+ assert "END" in compiled
233
+ assert test_environment.concepts["test_like"].datatype == DataType.BOOL
234
+
235
+
215
236
  def test_split_and_index_function(test_environment):
216
237
  declarations = """
217
238
  constant test_string <- 'abc_def';
@@ -4,6 +4,6 @@ from trilogy.executor import Executor
4
4
  from trilogy.parser import parse
5
5
  from trilogy.constants import CONFIG
6
6
 
7
- __version__ = "0.0.2.29"
7
+ __version__ = "0.0.2.31"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
@@ -162,6 +162,21 @@ def parse_concept_reference(
162
162
  return lookup, namespace, name, parent
163
163
 
164
164
 
165
+ def expr_to_boolean(
166
+ root,
167
+ ) -> Union[Comparison, Conditional, SubselectComparison, Parenthetical]:
168
+ if not isinstance(root, (Comparison, Conditional, Parenthetical)):
169
+ if arg_to_datatype(root) == DataType.BOOL:
170
+ root = Comparison(left=root, right=True, operator=ComparisonOperator.EQ)
171
+ else:
172
+ root = Comparison(
173
+ left=root,
174
+ right=MagicConstants.NULL,
175
+ operator=ComparisonOperator.IS_NOT,
176
+ )
177
+ return root
178
+
179
+
165
180
  def unwrap_transformation(
166
181
  input: Union[
167
182
  FilterItem,
@@ -1022,15 +1037,7 @@ class ParseToObjects(Transformer):
1022
1037
 
1023
1038
  def where(self, args):
1024
1039
  root = args[0]
1025
- if not isinstance(root, (Comparison, Conditional, Parenthetical)):
1026
- if arg_to_datatype(root) == DataType.BOOL:
1027
- root = Comparison(left=root, right=True, operator=ComparisonOperator.EQ)
1028
- else:
1029
- root = Comparison(
1030
- left=root,
1031
- right=MagicConstants.NULL,
1032
- operator=ComparisonOperator.IS_NOT,
1033
- )
1040
+ root = expr_to_boolean(root)
1034
1041
  return WhereClause(conditional=root)
1035
1042
 
1036
1043
  def having(self, args):
@@ -1838,7 +1845,8 @@ class ParseToObjects(Transformer):
1838
1845
  @v_args(meta=True)
1839
1846
  def fcase_when(self, meta, args) -> CaseWhen:
1840
1847
  args = process_function_args(args, meta=meta, environment=self.environment)
1841
- return CaseWhen(comparison=args[0], expr=args[1])
1848
+ root = expr_to_boolean(args[0])
1849
+ return CaseWhen(comparison=root, expr=args[1])
1842
1850
 
1843
1851
  @v_args(meta=True)
1844
1852
  def fcase_else(self, meta, args) -> CaseElse:
@@ -386,13 +386,31 @@ class Renderer:
386
386
 
387
387
  @to_string.register
388
388
  def _(self, arg: "Function"):
389
- inputs = ",".join(self.to_string(c) for c in arg.arguments)
389
+ args = [self.to_string(c) for c in arg.arguments]
390
+
391
+ if arg.operator == FunctionType.SUBTRACT:
392
+ return f"{args[0]} - {args[1]}"
393
+ if arg.operator == FunctionType.ADD:
394
+ return f"{args[0]} + {args[1]}"
395
+ if arg.operator == FunctionType.MULTIPLY:
396
+ return f"{args[0]} * {args[1]}"
397
+ if arg.operator == FunctionType.DIVIDE:
398
+ return f"{args[0]} / {args[1]}"
399
+ if arg.operator == FunctionType.MOD:
400
+ return f"{args[0]} % {args[1]}"
401
+
402
+ inputs = ",".join(args)
403
+
390
404
  if arg.operator == FunctionType.CONSTANT:
391
405
  return f"{inputs}"
392
406
  if arg.operator == FunctionType.CAST:
393
407
  return f"CAST({self.to_string(arg.arguments[0])} AS {self.to_string(arg.arguments[1])})"
394
408
  if arg.operator == FunctionType.INDEX_ACCESS:
395
409
  return f"{self.to_string(arg.arguments[0])}[{self.to_string(arg.arguments[1])}]"
410
+
411
+ if arg.operator == FunctionType.CASE:
412
+ inputs = "\n".join(args)
413
+ return f"CASE {inputs}\nEND"
396
414
  return f"{arg.operator.value}({inputs})"
397
415
 
398
416
  @to_string.register
File without changes
File without changes
File without changes
File without changes