pytrilogy 0.0.3.57__py3-none-any.whl → 0.0.3.60__py3-none-any.whl

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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytrilogy
3
- Version: 0.0.3.57
3
+ Version: 0.0.3.60
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -1,5 +1,5 @@
1
- pytrilogy-0.0.3.57.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
- trilogy/__init__.py,sha256=JPKu2C5PxT7TYswlIkOCzUXcjNHQ8puwzu6tF26QzWc,303
1
+ pytrilogy-0.0.3.60.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
+ trilogy/__init__.py,sha256=8jDnsd42NfWTeVpYr5aVIC5F7YtNxUA3qJ-UpkKPzbU,303
3
3
  trilogy/compiler.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  trilogy/constants.py,sha256=lv_aJWP6dn6e2aF4BAE72jbnNtceFddfqtiDSsvzno0,1692
5
5
  trilogy/engine.py,sha256=OK2RuqCIUId6yZ5hfF8J1nxGP0AJqHRZiafcowmW0xc,1728
@@ -10,8 +10,8 @@ trilogy/render.py,sha256=qQWwduymauOlB517UtM-VGbVe8Cswa4UJub5aGbSO6c,1512
10
10
  trilogy/utility.py,sha256=euQccZLKoYBz0LNg5tzLlvv2YHvXh9HArnYp1V3uXsM,763
11
11
  trilogy/authoring/__init__.py,sha256=h-Ag7vT76tsjib9BfjOgI-yVpuJDgpn2TSps-ibRAj8,2593
12
12
  trilogy/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- trilogy/core/constants.py,sha256=7XaCpZn5mQmjTobbeBn56SzPWq9eMNDfzfsRU-fP0VE,171
14
- trilogy/core/enums.py,sha256=9thKx6u-Z3vzT3iGBBUtHsHCXaU-8L4IaqGJp1G7It0,7737
13
+ trilogy/core/constants.py,sha256=nizWYDCJQ1bigQMtkNIEMNTcN0NoEAXiIHLzpelxQ24,201
14
+ trilogy/core/enums.py,sha256=z2mljNfhosnap4Nesx-mVOzM4UAPYU0R-Gy-HQVqcBI,7781
15
15
  trilogy/core/env_processor.py,sha256=pFsxnluKIusGKx1z7tTnfsd_xZcPy9pZDungkjkyvI0,3170
16
16
  trilogy/core/environment_helpers.py,sha256=VvPIiFemqaLLpIpLIqprfu63K7muZ1YzNg7UZIUph8w,8267
17
17
  trilogy/core/ergonomics.py,sha256=e-7gE29vPLFdg0_A1smQ7eOrUwKl5VYdxRSTddHweRA,1631
@@ -37,7 +37,7 @@ trilogy/core/optimizations/predicate_pushdown.py,sha256=g4AYE8Aw_iMlAh68TjNXGP75
37
37
  trilogy/core/processing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  trilogy/core/processing/concept_strategies_v3.py,sha256=KHpSQyG5Ubb5H1dmzpDWI2ypJL_rxeS3zc3sjaeCq_s,21997
39
39
  trilogy/core/processing/discovery_loop.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
- trilogy/core/processing/discovery_node_factory.py,sha256=eC9AkPq9Phe3iY9qIstb98BqAPqKJ8RejsjqUYJMixQ,14890
40
+ trilogy/core/processing/discovery_node_factory.py,sha256=LFGHUznUz_kszcs8QywZ0pNaejbRoNVHv81gX6Mqm2Y,14909
41
41
  trilogy/core/processing/discovery_utility.py,sha256=hF3aUbRHHZFeFT5aBjE6TuSeU60I90gzmj512QXG_t8,4856
42
42
  trilogy/core/processing/discovery_validation.py,sha256=Ek9jviFgimLMUMYLXBChUQmOD94ihhwQ3NDVe6RTdWg,4930
43
43
  trilogy/core/processing/graph_utils.py,sha256=8QUVrkE9j-9C1AyrCb1nQEh8daCe0u1HuXl-Te85lag,1205
@@ -49,7 +49,7 @@ trilogy/core/processing/node_generators/filter_node.py,sha256=0hdfiS2I-Jvr6P-il3
49
49
  trilogy/core/processing/node_generators/group_node.py,sha256=nIfiMrJQEksUfqAeeA3X5PS1343y4lmPTipYuCa-rvs,6141
50
50
  trilogy/core/processing/node_generators/group_to_node.py,sha256=jKcNCDOY6fNblrdZwaRU0sbUSr9H0moQbAxrGgX6iGA,3832
51
51
  trilogy/core/processing/node_generators/multiselect_node.py,sha256=GWV5yLmKTe1yyPhN60RG1Rnrn4ktfn9lYYXi_FVU4UI,7061
52
- trilogy/core/processing/node_generators/node_merge_node.py,sha256=kTyvSIDFFGnulh3SeXHar3oCZK2DOpymXIZbCWZFxI0,16220
52
+ trilogy/core/processing/node_generators/node_merge_node.py,sha256=1vUmNE0qQQ1MYAvC6TO2dNsudIUytj9ZVcW4w1IGHXY,16734
53
53
  trilogy/core/processing/node_generators/recursive_node.py,sha256=l5zdh0dURKwmAy8kK4OpMtZfyUEQRk6N-PwSWIyBpSM,2468
54
54
  trilogy/core/processing/node_generators/rowset_node.py,sha256=2BiSsegbRF9csJ_Xl8P_CxIm4dAAb7dF29u6v_Odr-A,6709
55
55
  trilogy/core/processing/node_generators/select_merge_node.py,sha256=lxXhMhDKGbu67QFNbbAT-BO8gbWppIvjn_hAXpLEPe0,19953
@@ -76,9 +76,9 @@ trilogy/core/statements/build.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
76
76
  trilogy/core/statements/common.py,sha256=KxEmz2ySySyZ6CTPzn0fJl5NX2KOk1RPyuUSwWhnK1g,759
77
77
  trilogy/core/statements/execute.py,sha256=rqfuoMuXPcH7L7TmE1dSiZ_K_A1ohB8whVMfGimZBOk,1294
78
78
  trilogy/dialect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
79
- trilogy/dialect/base.py,sha256=Ts5rRMNyc9S2GJqrDIUImAZ41vYYfhcA9blEAsBlWhU,41840
80
- trilogy/dialect/bigquery.py,sha256=4u4SuQ67_Zwyu0czyQnBMDUVlegqir0SA30iEbZEAwU,3575
81
- trilogy/dialect/common.py,sha256=IhW0v5zATvZ2K0vr4Ab4TWpYMKKkGangSpIyqaPYEkw,5762
79
+ trilogy/dialect/base.py,sha256=V9003GLDMf1fg-EhphlxKov84f1LKqhyYfnqujXblPg,42754
80
+ trilogy/dialect/bigquery.py,sha256=6ghCqy-k7UioIJc1EEQ7gRo_PHaO8Vm7yYbiQ-kgpzs,3629
81
+ trilogy/dialect/common.py,sha256=61yWE0K6M-Hfc934HkdHakIdLAUNB5kPSAQcTeAo3sU,5917
82
82
  trilogy/dialect/config.py,sha256=olnyeVU5W5T6b9-dMeNAnvxuPlyc2uefb7FRME094Ec,3834
83
83
  trilogy/dialect/dataframe.py,sha256=RUbNgReEa9g3pL6H7fP9lPTrAij5pkqedpZ99D8_5AE,1522
84
84
  trilogy/dialect/duckdb.py,sha256=C5TovwacDXo9YDpMTpPxkH7D0AxQERa7JL1RUkDGVng,3898
@@ -93,7 +93,7 @@ trilogy/hooks/graph_hook.py,sha256=c-vC-IXoJ_jDmKQjxQyIxyXPOuUcLIURB573gCsAfzQ,2
93
93
  trilogy/hooks/query_debugger.py,sha256=1npRjww94sPV5RRBBlLqMJRaFkH9vhEY6o828MeoEcw,5583
94
94
  trilogy/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
95
95
  trilogy/parsing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
96
- trilogy/parsing/common.py,sha256=kjA0-14mgrr1smOjt01h0nk6iatLj9tXXC8cMsir084,29782
96
+ trilogy/parsing/common.py,sha256=OOAssbo6Yp3L4u2OSGUYIuC_iAG_843vLpUtLkk1ub8,29960
97
97
  trilogy/parsing/config.py,sha256=Z-DaefdKhPDmSXLgg5V4pebhSB0h590vI0_VtHnlukI,111
98
98
  trilogy/parsing/exceptions.py,sha256=Xwwsv2C9kSNv2q-HrrKC1f60JNHShXcCMzstTSEbiCw,154
99
99
  trilogy/parsing/helpers.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
@@ -103,14 +103,15 @@ trilogy/parsing/trilogy.lark,sha256=CK7Hqqr9W6FYb1BRWd9k3B6SzhJ8GgK4lu4hALxn_kw,
103
103
  trilogy/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
104
104
  trilogy/scripts/trilogy.py,sha256=1L0XrH4mVHRt1C9T1HnaDv2_kYEfbWTb5_-cBBke79w,3774
105
105
  trilogy/std/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
106
- trilogy/std/date.preql,sha256=Ki4M-dG2xUIT_U16kOBXdaZb62S3P7iDrMBY93I4I3Q,132
106
+ trilogy/std/date.preql,sha256=HWZm4t4HWyxr5geWRsY05RnHBVDMci8z8YA2cu0-OOw,188
107
107
  trilogy/std/display.preql,sha256=2BbhvqR4rcltyAbOXAUo7SZ_yGFYZgFnurglHMbjW2g,40
108
108
  trilogy/std/geography.preql,sha256=qLnHmDU5EnvjTbfqZF-NEclSYM5_e9rZra7QjV01rZ4,582
109
109
  trilogy/std/money.preql,sha256=XWwvAV3WxBsHX9zfptoYRnBigcfYwrYtBHXTME0xJuQ,2082
110
110
  trilogy/std/net.preql,sha256=-bMV6dyofskl4Kvows-iQ4JCxjVUwsZOeWCy8JO5Ftw,135
111
+ trilogy/std/ranking.preql,sha256=LDoZrYyz4g3xsII9XwXfmstZD-_92i1Eox1UqkBIfi8,83
111
112
  trilogy/std/report.preql,sha256=LbV-XlHdfw0jgnQ8pV7acG95xrd1-p65fVpiIc-S7W4,202
112
- pytrilogy-0.0.3.57.dist-info/METADATA,sha256=eEwXdnEJXGts7_XfpLnH-bw-Ee8zvPrFxklMcCfRLC4,9095
113
- pytrilogy-0.0.3.57.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
114
- pytrilogy-0.0.3.57.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
115
- pytrilogy-0.0.3.57.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
116
- pytrilogy-0.0.3.57.dist-info/RECORD,,
113
+ pytrilogy-0.0.3.60.dist-info/METADATA,sha256=n3i-LaY9KCLDvVzwfo7Z1xuUqYRPZR3LMXmOGFwBeGU,9095
114
+ pytrilogy-0.0.3.60.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
115
+ pytrilogy-0.0.3.60.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
116
+ pytrilogy-0.0.3.60.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
117
+ pytrilogy-0.0.3.60.dist-info/RECORD,,
trilogy/__init__.py CHANGED
@@ -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.57"
7
+ __version__ = "0.0.3.60"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
trilogy/core/constants.py CHANGED
@@ -2,3 +2,4 @@ CONSTANT_DATASET: str = "preql_internal_constant_dataset"
2
2
  ALL_ROWS_CONCEPT = "all_rows"
3
3
  INTERNAL_NAMESPACE = "__preql_internal"
4
4
  PERSISTED_CONCEPT_PREFIX = "__pre_persist"
5
+ UNNEST_NAME = "_unnest_alias"
trilogy/core/enums.py CHANGED
@@ -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_UNNEST = "cross_join_unnest"
10
11
  CROSS_JOIN_ALIAS = "cross_join_alias"
11
12
  SNOWFLAKE = "snowflake"
12
13
 
@@ -373,7 +373,7 @@ class RootNodeHandler:
373
373
  ) -> Optional[StrategyNode]:
374
374
  logger.info(
375
375
  f"{depth_to_prefix(self.ctx.depth)}{LOGGER_PREFIX} "
376
- f"Could not resolve root concepts, checking for synonyms"
376
+ f"Could not resolve root concepts, checking for synonyms for {root_targets}"
377
377
  )
378
378
 
379
379
  if not self.ctx.history.check_started(
@@ -88,7 +88,10 @@ def determine_induced_minimal_nodes(
88
88
  for node in G.nodes:
89
89
  if concepts.get(node):
90
90
  lookup: BuildConcept = concepts[node]
91
- if lookup.derivation in (Derivation.CONSTANT,):
91
+ # inclusion of aggregates can create ambiguous node relation chains
92
+ # there may be a better way to handle this
93
+ # can be revisited if we need to connect a derived synonym based on an aggregate
94
+ if lookup.derivation in (Derivation.CONSTANT, Derivation.AGGREGATE):
92
95
  nodes_to_remove.append(node)
93
96
  # purge a node if we're already looking for all it's parents
94
97
  if filter_downstream and lookup.derivation not in (Derivation.ROOT,):
@@ -112,6 +115,7 @@ def determine_induced_minimal_nodes(
112
115
  return None
113
116
  H.remove_nodes_from(list(x for x in H.nodes if x not in paths))
114
117
  sG: nx.Graph = ax.steinertree.steiner_tree(H, nodelist).copy()
118
+ logger.debug("Steiner tree found for nodes %s", nodelist)
115
119
  final: nx.DiGraph = nx.subgraph(G, sG.nodes).copy()
116
120
 
117
121
  for edge in G.edges:
@@ -228,11 +232,14 @@ def resolve_weak_components(
228
232
  # to ensure there are not ambiguous discovery paths
229
233
  # (if we did not care about raising ambiguity errors, we could just use the first one)
230
234
  count = 0
231
- node_list = [
232
- concept_to_node(c.with_default_grain())
233
- for c in all_concepts
234
- if "__preql_internal" not in c.address
235
- ]
235
+ node_list = sorted(
236
+ [
237
+ concept_to_node(c.with_default_grain())
238
+ for c in all_concepts
239
+ if "__preql_internal" not in c.address
240
+ ]
241
+ )
242
+ logger.debug(f"Resolving weak components for {node_list} in {search_graph.nodes}")
236
243
  synonyms: set[str] = set()
237
244
  for x in all_concepts:
238
245
  synonyms = synonyms.union(x.pseudonyms)
@@ -354,7 +361,7 @@ def subgraphs_to_merge_node(
354
361
  parents.append(parent)
355
362
  input_c = []
356
363
  for x in parents:
357
- for y in x.output_concepts:
364
+ for y in x.usable_outputs:
358
365
  input_c.append(y)
359
366
  if len(parents) == 1 and enable_early_exit:
360
367
  logger.info(
@@ -392,6 +399,7 @@ def gen_merge_node(
392
399
  )
393
400
  else:
394
401
  all_search_concepts = all_concepts
402
+ all_search_concepts = sorted(all_search_concepts, key=lambda x: x.address)
395
403
  for filter_downstream in [True, False]:
396
404
  weak_resolve = resolve_weak_components(
397
405
  all_search_concepts,
trilogy/dialect/base.py CHANGED
@@ -10,6 +10,7 @@ from trilogy.constants import (
10
10
  Rendering,
11
11
  logger,
12
12
  )
13
+ from trilogy.core.constants import UNNEST_NAME
13
14
  from trilogy.core.enums import (
14
15
  DatePart,
15
16
  FunctionType,
@@ -756,6 +757,16 @@ class BaseDialect:
756
757
  f"{self.QUOTE_CHARACTER}{c.safe_address}{self.QUOTE_CHARACTER}"
757
758
  for c in cte.join_derived_concepts
758
759
  ]
760
+ elif self.UNNEST_MODE == UnnestMode.CROSS_JOIN_UNNEST:
761
+ select_columns = [
762
+ self.render_concept_sql(c, cte)
763
+ for c in cte.output_columns
764
+ if c.address not in [y.address for y in cte.join_derived_concepts]
765
+ and c.address not in cte.hidden_concepts
766
+ ] + [
767
+ f"{UNNEST_NAME} as {self.QUOTE_CHARACTER}{c.safe_address}{self.QUOTE_CHARACTER}"
768
+ for c in cte.join_derived_concepts
769
+ ]
759
770
  else:
760
771
  # otherwse, assume we are unnesting directly in the select
761
772
  select_columns = [
@@ -770,11 +781,18 @@ class BaseDialect:
770
781
  if len(cte.joins) > 0:
771
782
  if cte.join_derived_concepts and self.UNNEST_MODE in (
772
783
  UnnestMode.CROSS_JOIN_ALIAS,
784
+ # UnnestMode.CROSS_JOIN_UNNEST,
773
785
  UnnestMode.CROSS_JOIN,
774
786
  UnnestMode.CROSS_APPLY,
775
787
  ):
776
788
 
777
789
  source = f"{render_unnest(self.UNNEST_MODE, self.QUOTE_CHARACTER, cte.join_derived_concepts[0], self.render_expr, cte)}"
790
+ elif (
791
+ cte.join_derived_concepts
792
+ and self.UNNEST_MODE == UnnestMode.CROSS_JOIN_UNNEST
793
+ ):
794
+ source = f"{self.render_expr(cte.join_derived_concepts[0], cte)} as {self.QUOTE_CHARACTER}{UNNEST_NAME}{self.QUOTE_CHARACTER}"
795
+
778
796
  elif (
779
797
  cte.join_derived_concepts
780
798
  and self.UNNEST_MODE == UnnestMode.SNOWFLAKE
@@ -22,7 +22,7 @@ FUNCTION_MAP = {
22
22
  FunctionType.MINUTE: lambda x: f"EXTRACT(MINUTE from {x[0]})",
23
23
  FunctionType.SECOND: lambda x: f"EXTRACT(SECOND from {x[0]})",
24
24
  FunctionType.HOUR: lambda x: f"EXTRACT(HOUR from {x[0]})",
25
- FunctionType.DAY_OF_WEEK: lambda x: f"EXTRACT(DAYOFWEEK from {x[0]})",
25
+ FunctionType.DAY_OF_WEEK: lambda x: f"EXTRACT(DAYOFWEEK from {x[0]})-1", # BigQuery's DAYOFWEEK returns 1 for Sunday
26
26
  FunctionType.DAY: lambda x: f"EXTRACT(DAY from {x[0]})",
27
27
  FunctionType.YEAR: lambda x: f"EXTRACT(YEAR from {x[0]})",
28
28
  FunctionType.MONTH: lambda x: f"EXTRACT(MONTH from {x[0]})",
@@ -97,5 +97,5 @@ class BigqueryDialect(BaseDialect):
97
97
  }
98
98
  QUOTE_CHARACTER = "`"
99
99
  SQL_TEMPLATE = BQ_SQL_TEMPLATE
100
- UNNEST_MODE = UnnestMode.CROSS_JOIN
100
+ UNNEST_MODE = UnnestMode.CROSS_JOIN_UNNEST
101
101
  DATATYPE_MAP = DATATYPE_MAP
trilogy/dialect/common.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from typing import Callable
2
2
 
3
+ from trilogy.core.constants import UNNEST_NAME
3
4
  from trilogy.core.enums import Modifier, UnnestMode
4
5
  from trilogy.core.models.build import (
5
6
  BuildComparison,
@@ -34,11 +35,14 @@ def render_unnest(
34
35
  cte: CTE,
35
36
  ):
36
37
  if not isinstance(concept, (BuildConcept, BuildParamaterizedConceptReference)):
37
- address = "anon_function"
38
+ print(type(concept))
39
+ address = UNNEST_NAME
38
40
  else:
39
41
  address = concept.safe_address
40
42
  if unnest_mode == UnnestMode.CROSS_JOIN:
41
43
  return f"{render_func(concept, cte)} as {quote_character}{address}{quote_character}"
44
+ elif unnest_mode == UnnestMode.CROSS_JOIN_UNNEST:
45
+ return f"unnest({render_func(concept, cte)}) as {quote_character}{address}{quote_character}"
42
46
  elif unnest_mode == UnnestMode.CROSS_JOIN_ALIAS:
43
47
  return f"{render_func(concept, cte)} as unnest_wrapper ({quote_character}{address}{quote_character})"
44
48
  elif unnest_mode == UnnestMode.SNOWFLAKE:
@@ -95,9 +99,11 @@ def render_join(
95
99
  return None
96
100
  if not cte:
97
101
  raise ValueError("must provide a cte to build an unnest joins")
98
- if unnest_mode == UnnestMode.CROSS_JOIN:
99
- return f"CROSS JOIN {render_unnest(unnest_mode, quote_character, join.object_to_unnest, render_expr_func, cte)}"
100
- if unnest_mode == UnnestMode.CROSS_JOIN_ALIAS:
102
+ if unnest_mode in (
103
+ UnnestMode.CROSS_JOIN,
104
+ UnnestMode.CROSS_JOIN_UNNEST,
105
+ UnnestMode.CROSS_JOIN_ALIAS,
106
+ ):
101
107
  return f"CROSS JOIN {render_unnest(unnest_mode, quote_character, join.object_to_unnest, render_expr_func, cte)}"
102
108
  if unnest_mode == UnnestMode.SNOWFLAKE:
103
109
  return f"LEFT JOIN LATERAL {render_unnest(unnest_mode, quote_character, join.object_to_unnest, render_expr_func, cte)}"
trilogy/parsing/common.py CHANGED
@@ -38,6 +38,7 @@ from trilogy.core.models.author import (
38
38
  Parenthetical,
39
39
  RowsetItem,
40
40
  RowsetLineage,
41
+ TraitDataType,
41
42
  UndefinedConcept,
42
43
  WhereClause,
43
44
  WindowItem,
@@ -608,6 +609,9 @@ def window_item_to_concept(
608
609
  and set([x.address for x in item.expr.by]) == keys
609
610
  ):
610
611
  continue
612
+ elif isinstance(item.expr, AggregateWrapper):
613
+
614
+ grain_components += item.expr.by
611
615
  else:
612
616
  grain_components += item.concept_arguments
613
617
  else:
@@ -617,19 +621,20 @@ def window_item_to_concept(
617
621
  modifiers = get_upstream_modifiers(bcontent.concept_arguments, environment)
618
622
  datatype = parent.content.datatype
619
623
  if parent.type in (
620
- WindowType.RANK,
624
+ # WindowType.RANK,
621
625
  WindowType.ROW_NUMBER,
622
626
  WindowType.COUNT,
623
627
  WindowType.COUNT_DISTINCT,
624
628
  ):
625
629
  datatype = DataType.INTEGER
630
+ if parent.type == WindowType.RANK:
631
+ datatype = TraitDataType(type=DataType.INTEGER, traits=["rank"])
626
632
  return Concept(
627
633
  name=name,
628
634
  datatype=datatype,
629
635
  purpose=local_purpose,
630
636
  lineage=parent,
631
637
  metadata=fmetadata,
632
- # filters are implicitly at the grain of the base item
633
638
  grain=final_grain,
634
639
  namespace=namespace,
635
640
  keys=keys,
trilogy/std/date.preql CHANGED
@@ -2,9 +2,12 @@
2
2
 
3
3
  type year int;
4
4
  type month int;
5
+ type month_name string;
5
6
  type week int;
6
7
  type day int;
7
8
  type hour int;
8
9
  type minute int;
9
10
  type second int;
10
- type day_of_week int;
11
+ type day_of_week int;
12
+ type day_of_week_name string;
13
+
@@ -0,0 +1,6 @@
1
+
2
+ type rank int;
3
+ type score int;
4
+ type position int;
5
+ type index int;
6
+ type grade int;