pytrilogy 0.0.3.17__tar.gz → 0.0.3.18__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 (133) hide show
  1. {pytrilogy-0.0.3.17/pytrilogy.egg-info → pytrilogy-0.0.3.18}/PKG-INFO +1 -1
  2. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18/pytrilogy.egg-info}/PKG-INFO +1 -1
  3. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_show.py +3 -3
  4. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/__init__.py +1 -1
  5. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/enums.py +1 -0
  6. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/ergonomics.py +0 -1
  7. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/functions.py +21 -3
  8. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/models/author.py +4 -0
  9. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/models/environment.py +1 -0
  10. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/statements/author.py +5 -0
  11. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/dialect/duckdb.py +2 -1
  12. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/parsing/parse_engine.py +10 -3
  13. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/parsing/trilogy.lark +5 -3
  14. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/LICENSE.md +0 -0
  15. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/README.md +0 -0
  16. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/pyproject.toml +0 -0
  17. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/pytrilogy.egg-info/SOURCES.txt +0 -0
  18. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/pytrilogy.egg-info/dependency_links.txt +0 -0
  19. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/pytrilogy.egg-info/entry_points.txt +0 -0
  20. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/pytrilogy.egg-info/requires.txt +0 -0
  21. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/pytrilogy.egg-info/top_level.txt +0 -0
  22. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/setup.cfg +0 -0
  23. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/setup.py +0 -0
  24. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_datatypes.py +0 -0
  25. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_declarations.py +0 -0
  26. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_derived_concepts.py +0 -0
  27. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_discovery_nodes.py +0 -0
  28. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_enums.py +0 -0
  29. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_environment.py +0 -0
  30. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_executor.py +0 -0
  31. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_functions.py +0 -0
  32. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_imports.py +0 -0
  33. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_metadata.py +0 -0
  34. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_models.py +0 -0
  35. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_multi_join_assignments.py +0 -0
  36. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_parse_engine.py +0 -0
  37. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_parsing.py +0 -0
  38. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_partial_handling.py +0 -0
  39. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_query_processing.py +0 -0
  40. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_query_render.py +0 -0
  41. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_select.py +0 -0
  42. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_statements.py +0 -0
  43. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_typing.py +0 -0
  44. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_undefined_concept.py +0 -0
  45. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_user_functions.py +0 -0
  46. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/tests/test_where_clause.py +0 -0
  47. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/authoring/__init__.py +0 -0
  48. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/compiler.py +0 -0
  49. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/constants.py +0 -0
  50. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/__init__.py +0 -0
  51. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/constants.py +0 -0
  52. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/env_processor.py +0 -0
  53. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/environment_helpers.py +0 -0
  54. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/exceptions.py +0 -0
  55. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/graph_models.py +0 -0
  56. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/internal.py +0 -0
  57. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/models/__init__.py +0 -0
  58. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/models/build.py +0 -0
  59. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/models/build_environment.py +0 -0
  60. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/models/core.py +0 -0
  61. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/models/datasource.py +0 -0
  62. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/models/execute.py +0 -0
  63. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/optimization.py +0 -0
  64. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/optimizations/__init__.py +0 -0
  65. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/optimizations/base_optimization.py +0 -0
  66. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/optimizations/inline_constant.py +0 -0
  67. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/optimizations/inline_datasource.py +0 -0
  68. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
  69. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/__init__.py +0 -0
  70. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/concept_strategies_v3.py +0 -0
  71. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/graph_utils.py +0 -0
  72. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/__init__.py +0 -0
  73. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/basic_node.py +0 -0
  74. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/common.py +0 -0
  75. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/filter_node.py +0 -0
  76. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/group_node.py +0 -0
  77. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/group_to_node.py +0 -0
  78. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/multiselect_node.py +0 -0
  79. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/node_merge_node.py +0 -0
  80. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/rowset_node.py +0 -0
  81. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/select_helpers/__init__.py +0 -0
  82. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +0 -0
  83. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/select_merge_node.py +0 -0
  84. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/select_node.py +0 -0
  85. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/synonym_node.py +0 -0
  86. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/union_node.py +0 -0
  87. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/unnest_node.py +0 -0
  88. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/node_generators/window_node.py +0 -0
  89. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/nodes/__init__.py +0 -0
  90. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/nodes/base_node.py +0 -0
  91. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/nodes/filter_node.py +0 -0
  92. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/nodes/group_node.py +0 -0
  93. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/nodes/merge_node.py +0 -0
  94. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
  95. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/nodes/union_node.py +0 -0
  96. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/nodes/unnest_node.py +0 -0
  97. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/nodes/window_node.py +0 -0
  98. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/processing/utility.py +0 -0
  99. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/query_processor.py +0 -0
  100. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/statements/__init__.py +0 -0
  101. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/statements/build.py +0 -0
  102. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/statements/common.py +0 -0
  103. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/core/statements/execute.py +0 -0
  104. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/dialect/__init__.py +0 -0
  105. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/dialect/base.py +0 -0
  106. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/dialect/bigquery.py +0 -0
  107. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/dialect/common.py +0 -0
  108. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/dialect/config.py +0 -0
  109. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/dialect/dataframe.py +0 -0
  110. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/dialect/enums.py +0 -0
  111. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/dialect/postgres.py +0 -0
  112. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/dialect/presto.py +0 -0
  113. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/dialect/snowflake.py +0 -0
  114. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/dialect/sql_server.py +0 -0
  115. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/engine.py +0 -0
  116. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/executor.py +0 -0
  117. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/hooks/__init__.py +0 -0
  118. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/hooks/base_hook.py +0 -0
  119. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/hooks/graph_hook.py +0 -0
  120. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/hooks/query_debugger.py +0 -0
  121. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/metadata/__init__.py +0 -0
  122. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/parser.py +0 -0
  123. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/parsing/__init__.py +0 -0
  124. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/parsing/common.py +0 -0
  125. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/parsing/config.py +0 -0
  126. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/parsing/exceptions.py +0 -0
  127. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/parsing/helpers.py +0 -0
  128. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/parsing/render.py +0 -0
  129. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/py.typed +0 -0
  130. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/render.py +0 -0
  131. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/scripts/__init__.py +0 -0
  132. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/scripts/trilogy.py +0 -0
  133. {pytrilogy-0.0.3.17 → pytrilogy-0.0.3.18}/trilogy/utility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pytrilogy
3
- Version: 0.0.3.17
3
+ Version: 0.0.3.18
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.2
2
2
  Name: pytrilogy
3
- Version: 0.0.3.17
3
+ Version: 0.0.3.18
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -52,6 +52,6 @@ def test_show_bigquery():
52
52
  .execute_query(select)
53
53
  .fetchall()
54
54
  )
55
- assert "FULL JOIN wakeful on 1=1" in query[0]["__preql_internal_query_text"], query[
56
- 0
57
- ]["__preql_internal_query_text"]
55
+ assert (
56
+ "FULL JOIN cheerful on 1=1" in query[0]["__preql_internal_query_text"]
57
+ ), query[0]["__preql_internal_query_text"]
@@ -4,6 +4,6 @@ from trilogy.dialect.enums import Dialects
4
4
  from trilogy.executor import Executor
5
5
  from trilogy.parser import parse
6
6
 
7
- __version__ = "0.0.3.17"
7
+ __version__ = "0.0.3.18"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
@@ -193,6 +193,7 @@ class FunctionType(Enum):
193
193
  DATE_PART = "date_part"
194
194
  DATE_TRUNCATE = "date_truncate"
195
195
  DATE_ADD = "date_add"
196
+ DATE_SUB = "date_sub"
196
197
  DATE_DIFF = "date_diff"
197
198
 
198
199
  # UNIX
@@ -3,7 +3,6 @@ from trilogy.constants import CONFIG
3
3
  # source: https://github.com/aaronbassett/Pass-phrase
4
4
  CTE_NAMES = """quizzical
5
5
  highfalutin
6
- dynamic
7
6
  wakeful
8
7
  cheerful
9
8
  thoughtful
@@ -145,6 +145,9 @@ def get_date_trunc_output(
145
145
 
146
146
 
147
147
  FUNCTION_REGISTRY: dict[FunctionType, FunctionConfig] = {
148
+ FunctionType.ALIAS: FunctionConfig(
149
+ arg_count=1,
150
+ ),
148
151
  FunctionType.PARENTHETICAL: FunctionConfig(
149
152
  arg_count=1,
150
153
  ),
@@ -375,6 +378,21 @@ FUNCTION_REGISTRY: dict[FunctionType, FunctionConfig] = {
375
378
  output_type=DataType.DATE,
376
379
  arg_count=3,
377
380
  ),
381
+ FunctionType.DATE_SUB: FunctionConfig(
382
+ valid_inputs=[
383
+ {
384
+ DataType.DATE,
385
+ DataType.TIMESTAMP,
386
+ DataType.DATETIME,
387
+ DataType.STRING,
388
+ },
389
+ {DataType.DATE_PART},
390
+ {DataType.INTEGER},
391
+ ],
392
+ output_purpose=Purpose.PROPERTY,
393
+ output_type=DataType.DATE,
394
+ arg_count=3,
395
+ ),
378
396
  FunctionType.DATE_DIFF: FunctionConfig(
379
397
  valid_inputs=[
380
398
  {
@@ -639,8 +657,6 @@ FUNCTION_REGISTRY: dict[FunctionType, FunctionConfig] = {
639
657
 
640
658
  EXCLUDED_FUNCTIONS = {
641
659
  FunctionType.CUSTOM,
642
- FunctionType.ALIAS,
643
- # FunctionType.PARENTHETICAL,
644
660
  # Temporary
645
661
  FunctionType.DATE_LITERAL,
646
662
  FunctionType.DATETIME_LITERAL,
@@ -649,7 +665,9 @@ EXCLUDED_FUNCTIONS = {
649
665
 
650
666
  for k in FunctionType.__members__.values():
651
667
  if k not in FUNCTION_REGISTRY and k not in EXCLUDED_FUNCTIONS:
652
- raise InvalidSyntaxException(f"Function {k} not in registry")
668
+ raise InvalidSyntaxException(
669
+ f"Function enum value {k} not in creation registry"
670
+ )
653
671
 
654
672
 
655
673
  class FunctionFactory:
@@ -793,6 +793,10 @@ class Concept(Addressable, DataTyped, ConceptArgs, Mergeable, Namespaced, BaseMo
793
793
  base = f"{self.address}@{self.grain}"
794
794
  return base
795
795
 
796
+ @property
797
+ def is_internal(self) -> bool:
798
+ return self.namespace.startswith("_") or self.name.startswith("_")
799
+
796
800
  @property
797
801
  def reference(self) -> ConceptRef:
798
802
  return ConceptRef.model_construct(
@@ -58,6 +58,7 @@ if TYPE_CHECKING:
58
58
  class Import:
59
59
  alias: str
60
60
  path: Path
61
+ input_path: str | None = None
61
62
 
62
63
 
63
64
  class BaseImportResolver(BaseModel):
@@ -382,7 +382,12 @@ class MergeStatementV2(HasUUID, BaseModel):
382
382
 
383
383
 
384
384
  class ImportStatement(HasUUID, BaseModel):
385
+ # import abc.def as bar
386
+ # the bit after 'as', eg bar
385
387
  alias: str
388
+ # the bit after import, abc.def
389
+ input_path: str
390
+ # what it actually resolves to, typically a filepath
386
391
  path: Path
387
392
 
388
393
 
@@ -8,6 +8,7 @@ from trilogy.dialect.base import BaseDialect
8
8
 
9
9
  WINDOW_FUNCTION_MAP: Mapping[WindowType, Callable[[Any, Any, Any], str]] = {}
10
10
 
11
+
11
12
  FUNCTION_MAP = {
12
13
  FunctionType.COUNT: lambda args: f"count({args[0]})",
13
14
  FunctionType.SUM: lambda args: f"sum({args[0]})",
@@ -27,7 +28,7 @@ FUNCTION_MAP = {
27
28
  # datetime is aliased
28
29
  FunctionType.CURRENT_DATETIME: lambda x: "cast(get_current_timestamp() as datetime)",
29
30
  FunctionType.DATE_TRUNCATE: lambda x: f"date_trunc('{x[1]}', {x[0]})",
30
- FunctionType.DATE_ADD: lambda x: f"date_add({x[0]}, INTERVAL {x[2]} {x[1]})",
31
+ FunctionType.DATE_ADD: lambda x: f"date_add({x[0]}, {x[2]} * INTERVAL 1 {x[1]})",
31
32
  FunctionType.DATE_PART: lambda x: f"date_part('{x[1]}', {x[0]})",
32
33
  FunctionType.DATE_DIFF: lambda x: f"date_diff('{x[2]}', {x[0]}, {x[1]})",
33
34
  FunctionType.CONCAT: lambda x: f"({' || '.join(x)})",
@@ -951,7 +951,8 @@ class ParseToObjects(Transformer):
951
951
  else:
952
952
  alias = self.environment.namespace
953
953
  cache_key = args[0]
954
- path = args[0].split(".")
954
+ input_path = args[0]
955
+ path = input_path.split(".")
955
956
 
956
957
  if isinstance(
957
958
  self.environment.config.import_resolver, FileSystemImportResolver
@@ -971,7 +972,9 @@ class ParseToObjects(Transformer):
971
972
 
972
973
  # we don't iterate past the max parse depth
973
974
  if len(key_path) > MAX_PARSE_DEPTH:
974
- return ImportStatement(alias=alias, path=Path(target))
975
+ return ImportStatement(
976
+ alias=alias, input_path=input_path, path=Path(target)
977
+ )
975
978
 
976
979
  if token_lookup in self.tokens:
977
980
  raw_tokens = self.tokens[token_lookup]
@@ -1015,7 +1018,7 @@ class ParseToObjects(Transformer):
1015
1018
  ) from e
1016
1019
 
1017
1020
  parsed_path = Path(args[0])
1018
- imps = ImportStatement(alias=alias, path=parsed_path)
1021
+ imps = ImportStatement(alias=alias, input_path=input_path, path=parsed_path)
1019
1022
 
1020
1023
  self.environment.add_import(
1021
1024
  alias, new_env, Import(alias=alias, path=parsed_path)
@@ -1582,6 +1585,10 @@ class ParseToObjects(Transformer):
1582
1585
  def fdate_add(self, meta, args):
1583
1586
  return self.function_factory.create_function(args, FunctionType.DATE_ADD, meta)
1584
1587
 
1588
+ @v_args(meta=True)
1589
+ def fdate_sub(self, meta, args):
1590
+ return self.function_factory.create_function(args, FunctionType.DATE_SUB, meta)
1591
+
1585
1592
  @v_args(meta=True)
1586
1593
  def fdate_diff(self, meta, args):
1587
1594
  return self.function_factory.create_function(args, FunctionType.DATE_DIFF, meta)
@@ -293,11 +293,13 @@
293
293
  _DATE_PART.1: "date_part("i
294
294
  fdate_part: _DATE_PART expr "," DATE_PART ")"
295
295
  _DATE_ADD.1: "date_add("i
296
- fdate_add: _DATE_ADD expr "," DATE_PART "," int_lit ")"
297
- _DATE_DIFF.1: "date_diff("i
296
+ fdate_add: _DATE_ADD expr "," DATE_PART "," expr ")"
297
+ _DATE_SUB.1: "date_sub("i
298
+ fdate_sub: _DATE_SUB expr "," DATE_PART "," expr ")"
299
+ _DATE_DIFF.1: "date_diff("i
298
300
  fdate_diff: _DATE_DIFF expr "," expr "," DATE_PART ")"
299
301
 
300
- _date_functions: fdate | fdate_add | fdate_diff | fdatetime | ftimestamp | fsecond | fminute | fhour | fday | fday_of_week | fweek | fmonth | fquarter | fyear | fdate_part | fdate_trunc
302
+ _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
301
303
 
302
304
  _static_functions: _string_functions | _math_functions | _generic_functions | _date_functions
303
305
 
File without changes
File without changes
File without changes
File without changes