pytrilogy 0.0.2.5__tar.gz → 0.0.2.6__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 (105) hide show
  1. {pytrilogy-0.0.2.5/pytrilogy.egg-info → pytrilogy-0.0.2.6}/PKG-INFO +1 -1
  2. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6/pytrilogy.egg-info}/PKG-INFO +1 -1
  3. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_parsing.py +45 -1
  4. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/__init__.py +1 -1
  5. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/enums.py +1 -0
  6. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/models.py +11 -0
  7. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/dialect/base.py +5 -3
  8. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/dialect/common.py +2 -1
  9. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/dialect/presto.py +2 -1
  10. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/parsing/parse_engine.py +6 -3
  11. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/parsing/trilogy.lark +3 -2
  12. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/LICENSE.md +0 -0
  13. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/README.md +0 -0
  14. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/pyproject.toml +0 -0
  15. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/pytrilogy.egg-info/SOURCES.txt +0 -0
  16. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/pytrilogy.egg-info/dependency_links.txt +0 -0
  17. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/pytrilogy.egg-info/entry_points.txt +0 -0
  18. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/pytrilogy.egg-info/requires.txt +0 -0
  19. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/pytrilogy.egg-info/top_level.txt +0 -0
  20. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/setup.cfg +0 -0
  21. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/setup.py +0 -0
  22. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_datatypes.py +0 -0
  23. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_declarations.py +0 -0
  24. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_derived_concepts.py +0 -0
  25. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_discovery_nodes.py +0 -0
  26. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_environment.py +0 -0
  27. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_functions.py +0 -0
  28. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_imports.py +0 -0
  29. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_metadata.py +0 -0
  30. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_models.py +0 -0
  31. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_multi_join_assignments.py +0 -0
  32. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_partial_handling.py +0 -0
  33. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_query_processing.py +0 -0
  34. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_select.py +0 -0
  35. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_statements.py +0 -0
  36. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_undefined_concept.py +0 -0
  37. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/tests/test_where_clause.py +0 -0
  38. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/compiler.py +0 -0
  39. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/constants.py +0 -0
  40. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/__init__.py +0 -0
  41. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/constants.py +0 -0
  42. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/env_processor.py +0 -0
  43. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/environment_helpers.py +0 -0
  44. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/ergonomics.py +0 -0
  45. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/exceptions.py +0 -0
  46. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/functions.py +0 -0
  47. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/graph_models.py +0 -0
  48. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/internal.py +0 -0
  49. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/optimization.py +0 -0
  50. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/optimizations/__init__.py +0 -0
  51. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/optimizations/base_optimization.py +0 -0
  52. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/optimizations/inline_constant.py +0 -0
  53. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/optimizations/inline_datasource.py +0 -0
  54. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
  55. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/__init__.py +0 -0
  56. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/concept_strategies_v3.py +0 -0
  57. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/graph_utils.py +0 -0
  58. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/node_generators/__init__.py +0 -0
  59. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/node_generators/basic_node.py +0 -0
  60. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/node_generators/common.py +0 -0
  61. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/node_generators/filter_node.py +0 -0
  62. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/node_generators/group_node.py +0 -0
  63. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/node_generators/group_to_node.py +0 -0
  64. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/node_generators/multiselect_node.py +0 -0
  65. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/node_generators/node_merge_node.py +0 -0
  66. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/node_generators/rowset_node.py +0 -0
  67. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/node_generators/select_node.py +0 -0
  68. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/node_generators/unnest_node.py +0 -0
  69. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/node_generators/window_node.py +0 -0
  70. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/nodes/__init__.py +0 -0
  71. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/nodes/base_node.py +0 -0
  72. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/nodes/filter_node.py +0 -0
  73. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/nodes/group_node.py +0 -0
  74. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/nodes/merge_node.py +0 -0
  75. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
  76. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/nodes/unnest_node.py +0 -0
  77. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/nodes/window_node.py +0 -0
  78. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/processing/utility.py +0 -0
  79. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/core/query_processor.py +0 -0
  80. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/dialect/__init__.py +0 -0
  81. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/dialect/bigquery.py +0 -0
  82. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/dialect/config.py +0 -0
  83. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/dialect/duckdb.py +0 -0
  84. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/dialect/enums.py +0 -0
  85. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/dialect/postgres.py +0 -0
  86. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/dialect/snowflake.py +0 -0
  87. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/dialect/sql_server.py +0 -0
  88. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/engine.py +0 -0
  89. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/executor.py +0 -0
  90. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/hooks/__init__.py +0 -0
  91. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/hooks/base_hook.py +0 -0
  92. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/hooks/graph_hook.py +0 -0
  93. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/hooks/query_debugger.py +0 -0
  94. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/metadata/__init__.py +0 -0
  95. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/parser.py +0 -0
  96. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/parsing/__init__.py +0 -0
  97. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/parsing/common.py +0 -0
  98. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/parsing/config.py +0 -0
  99. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/parsing/exceptions.py +0 -0
  100. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/parsing/helpers.py +0 -0
  101. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/parsing/render.py +0 -0
  102. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/py.typed +0 -0
  103. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/scripts/__init__.py +0 -0
  104. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/scripts/trilogy.py +0 -0
  105. {pytrilogy-0.0.2.5 → pytrilogy-0.0.2.6}/trilogy/utility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pytrilogy
3
- Version: 0.0.2.5
3
+ Version: 0.0.2.6
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.5
3
+ Version: 0.0.2.6
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -160,7 +160,8 @@ address `preqldata.analytics_411641820.events_*`
160
160
  ;"""
161
161
  )
162
162
  query = parsed[-1]
163
- assert query.address.location == "`preqldata.analytics_411641820.events_*`"
163
+ assert query.address.quoted is True
164
+ assert query.address.location == "preqldata.analytics_411641820.events_*"
164
165
 
165
166
 
166
167
  def test_purpose_and_keys():
@@ -448,3 +449,46 @@ select
448
449
  {"a": 1, "b": 2, "c": 3},
449
450
  1,
450
451
  )
452
+
453
+
454
+ def test_datasource_colon():
455
+
456
+ text = """
457
+ key x int;
458
+ key y int;
459
+
460
+ datasource test (
461
+ x:x,
462
+ y:y)
463
+ grain(x)
464
+ address `abc:def`
465
+ ;
466
+
467
+
468
+ select x;
469
+ """
470
+ env, parsed = parse_text(text)
471
+
472
+ results = Dialects.DUCK_DB.default_executor().generate_sql(text)[0]
473
+
474
+ assert '"abc:def" as test' in results
475
+
476
+ text = """
477
+ key x int;
478
+ key y int;
479
+
480
+ datasource test (
481
+ x:x,
482
+ y:y)
483
+ grain(x)
484
+ address abcdef
485
+ ;
486
+
487
+
488
+ select x;
489
+ """
490
+ env, parsed = parse_text(text)
491
+
492
+ results = Dialects.DUCK_DB.default_executor().generate_sql(text)[0]
493
+
494
+ assert "abcdef as test" in results, results
@@ -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.5"
7
+ __version__ = "0.0.2.6"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
@@ -7,6 +7,7 @@ class UnnestMode(Enum):
7
7
  DIRECT = "direct"
8
8
  CROSS_APPLY = "cross_apply"
9
9
  CROSS_JOIN = "cross_join"
10
+ CROSS_JOIN_ALIAS = "cross_join_alias"
10
11
 
11
12
 
12
13
  class ConceptSource(Enum):
@@ -1817,6 +1817,7 @@ class MultiSelectStatement(SelectTypeMixin, Mergeable, Namespaced, BaseModel):
1817
1817
  class Address(BaseModel):
1818
1818
  location: str
1819
1819
  is_query: bool = False
1820
+ quoted: bool = False
1820
1821
 
1821
1822
 
1822
1823
  class Query(BaseModel):
@@ -2579,6 +2580,16 @@ class CTE(BaseModel):
2579
2580
  return self.relevant_base_ctes[0].name
2580
2581
  return self.source.name
2581
2582
 
2583
+ @property
2584
+ def quote_address(self) -> bool:
2585
+ if self.is_root_datasource:
2586
+ candidate = self.source.datasources[0]
2587
+ if isinstance(candidate, Datasource) and isinstance(
2588
+ candidate.address, Address
2589
+ ):
2590
+ return candidate.address.quoted
2591
+ return False
2592
+
2582
2593
  @property
2583
2594
  def base_alias(self) -> str:
2584
2595
  if self.base_alias_override:
@@ -499,10 +499,12 @@ class BaseDialect:
499
499
  for c in cte.output_columns
500
500
  if c.address not in [y.address for y in cte.hidden_concepts]
501
501
  ]
502
- if cte.base_name == cte.base_alias:
503
- source = cte.base_name
502
+ if cte.quote_address:
503
+ source = f"{self.QUOTE_CHARACTER}{cte.base_name}{self.QUOTE_CHARACTER}"
504
504
  else:
505
- source = f"{cte.base_name} as {cte.base_alias}"
505
+ source = cte.base_name
506
+ if cte.base_name != cte.base_alias:
507
+ source = f"{source} as {cte.base_alias}"
506
508
  return CompiledCTE(
507
509
  name=cte.name,
508
510
  statement=self.SQL_TEMPLATE.render(
@@ -26,7 +26,8 @@ def render_join(
26
26
  raise ValueError("must provide a cte to build an unnest joins")
27
27
  if unnest_mode == UnnestMode.CROSS_JOIN:
28
28
  return f"CROSS JOIN {render_func(join.concept, cte, False)} as {quote_character}{join.concept.safe_address}{quote_character}"
29
-
29
+ if unnest_mode == UnnestMode.CROSS_JOIN_ALIAS:
30
+ return f"CROSS JOIN {render_func(join.concept, cte, False)} as array_unnest ({quote_character}{join.concept.safe_address}{quote_character})"
30
31
  return f"FULL JOIN {render_func(join.concept, cte, False)} as unnest_wrapper({quote_character}{join.concept.safe_address}{quote_character})"
31
32
  left_name = join.left_name
32
33
  right_name = join.right_name
@@ -5,7 +5,7 @@ from jinja2 import Template
5
5
  from trilogy.core.enums import FunctionType, WindowType
6
6
  from trilogy.dialect.base import BaseDialect
7
7
  from trilogy.core.models import DataType
8
-
8
+ from trilogy.core.enums import UnnestMode
9
9
 
10
10
  WINDOW_FUNCTION_MAP: Mapping[WindowType, Callable[[Any, Any, Any], str]] = {}
11
11
 
@@ -86,6 +86,7 @@ class PrestoDialect(BaseDialect):
86
86
  QUOTE_CHARACTER = '"'
87
87
  SQL_TEMPLATE = SQL_TEMPLATE
88
88
  DATATYPE_MAP = {**BaseDialect.DATATYPE_MAP, DataType.NUMERIC: "DECIMAL"}
89
+ UNNEST_MODE = UnnestMode.CROSS_JOIN
89
90
 
90
91
 
91
92
  class TrinoDialect(PrestoDialect):
@@ -297,8 +297,11 @@ class ParseToObjects(Transformer):
297
297
  def concept_lit(self, args) -> Concept:
298
298
  return self.environment.concepts.__getitem__(args[0])
299
299
 
300
- def ADDRESS(self, args) -> str:
301
- return args.value
300
+ def ADDRESS(self, args) -> Address:
301
+ return Address(location=args.value, quoted=False)
302
+
303
+ def QUOTED_ADDRESS(self, args) -> Address:
304
+ return Address(location=args.value[1:-1], quoted=True)
302
305
 
303
306
  def STRING_CHARS(self, args) -> str:
304
307
  return args.value
@@ -1010,7 +1013,7 @@ class ParseToObjects(Transformer):
1010
1013
 
1011
1014
  @v_args(meta=True)
1012
1015
  def address(self, meta: Meta, args):
1013
- return Address(location=args[0])
1016
+ return args[0]
1014
1017
 
1015
1018
  @v_args(meta=True)
1016
1019
  def query(self, meta: Meta, args):
@@ -39,7 +39,7 @@
39
39
 
40
40
  grain_clause: "grain" "(" column_list ")"
41
41
 
42
- address: "address" ADDRESS
42
+ address: "address" (QUOTED_ADDRESS | ADDRESS)
43
43
 
44
44
  query: "query" MULTILINE_STRING
45
45
 
@@ -258,7 +258,8 @@
258
258
  // base language constructs
259
259
  concept_lit: IDENTIFIER
260
260
  IDENTIFIER: /[a-zA-Z\_][a-zA-Z0-9\_\-\.\-]*/
261
- ADDRESS: IDENTIFIER | /`[a-zA-Z\_][a-zA-Z0-9\_\-\.\-\*]*`/
261
+ QUOTED_ADDRESS: /`[a-zA-Z\_][a-zA-Z0-9\_\-\.\-\*\:]*`/
262
+ ADDRESS: IDENTIFIER
262
263
 
263
264
  MULTILINE_STRING: /\'{3}(.*?)\'{3}/s
264
265
 
File without changes
File without changes
File without changes
File without changes
File without changes