pytrilogy 0.0.3.71__py3-none-any.whl → 0.0.3.72__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.71
3
+ Version: 0.0.3.72
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.71.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
- trilogy/__init__.py,sha256=M3ozbgvpiJ9h44b-oCogBhygSVgnDOV37ejNFOYUV5w,303
1
+ pytrilogy-0.0.3.72.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
+ trilogy/__init__.py,sha256=nTClKJQdHtjmdR7uHkenK_MjPmcfU2r_PQcI3PwQuNQ,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
@@ -11,12 +11,12 @@ 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
13
  trilogy/core/constants.py,sha256=nizWYDCJQ1bigQMtkNIEMNTcN0NoEAXiIHLzpelxQ24,201
14
- trilogy/core/enums.py,sha256=2sgoVzHQpscIx_WUqJMH0oGxtcg41gN0l1qkRjzK2iI,7803
14
+ trilogy/core/enums.py,sha256=fog9j6YU22LXuoArKsNJn-UFIEAVk06LI_-Zdg2UDv0,7841
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
18
18
  trilogy/core/exceptions.py,sha256=jYEduuMehcMkmCpf-OC_taELPZm7qNfeSNzIWkDYScs,707
19
- trilogy/core/functions.py,sha256=R8_aOe2mNRgOLmsnI9pG_GOU3I7kFPTnXQzplN2d7Dw,29343
19
+ trilogy/core/functions.py,sha256=xT4DR6IRTt3N6TZ_LEcSV2nvLUWFGfajd5vQZd2Pw7k,29512
20
20
  trilogy/core/graph_models.py,sha256=BYhJzHKSgnZHVLJs1CfsgrxTPHqKqPNeA64RlozGY0A,3498
21
21
  trilogy/core/internal.py,sha256=iicDBlC6nM8d7e7jqzf_ZOmpUsW8yrr2AA8AqEiLx-s,1577
22
22
  trilogy/core/optimization.py,sha256=ojpn-p79lr03SSVQbbw74iPCyoYpDYBmj1dbZ3oXCjI,8860
@@ -24,7 +24,7 @@ trilogy/core/query_processor.py,sha256=5aFgv-2LVM1Uku9cR_tFuTRDwyLnxc95bCMAHeFy2
24
24
  trilogy/core/utility.py,sha256=3VC13uSQWcZNghgt7Ot0ZTeEmNqs__cx122abVq9qhM,410
25
25
  trilogy/core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
26
  trilogy/core/models/author.py,sha256=Wz_6yEZS5EyXJ5wHHl-C44ikFka5XftBYOjNRK98Hfw,77790
27
- trilogy/core/models/build.py,sha256=BNHzfqD5NWCKHntvnswvDrtCD1JFgvPedx23cPq942U,65405
27
+ trilogy/core/models/build.py,sha256=59KmJDY1lzJMXuAZjxvT7K5IhIga9k2xwhzQBbx5zyo,65688
28
28
  trilogy/core/models/build_environment.py,sha256=s_C9xAHuD3yZ26T15pWVBvoqvlp2LdZ8yjsv2_HdXLk,5363
29
29
  trilogy/core/models/core.py,sha256=EMAuWTngoNVGCdfNrAY7_k6g528iodNQLwPRVip-8DA,10980
30
30
  trilogy/core/models/datasource.py,sha256=wogTevZ-9CyUW2a8gjzqMCieircxi-J5lkI7EOAZnck,9596
@@ -57,7 +57,7 @@ trilogy/core/processing/node_generators/select_node.py,sha256=Ta1G39V94gjX_AgyZD
57
57
  trilogy/core/processing/node_generators/synonym_node.py,sha256=AnAsa_Wj50NJ_IK0HSgab_7klYmKVrv0WI1uUe-GvEY,3766
58
58
  trilogy/core/processing/node_generators/union_node.py,sha256=VNo6Oey4p8etU9xrOh2oTT2lIOTvY6PULUPRvVa2uxU,2877
59
59
  trilogy/core/processing/node_generators/unnest_node.py,sha256=ueOQtoTf2iJHO09RzWHDFQ5iKZq2fVhGf2KAF2U2kU8,2677
60
- trilogy/core/processing/node_generators/window_node.py,sha256=GP3Hvkbb0TDA6ef7W7bmvQEHVH-NRIfBT_0W4fcH3g4,6529
60
+ trilogy/core/processing/node_generators/window_node.py,sha256=8ZULQZW05nKlGQ1yRQF7XsiD5-AtRlqpkPYjZ1pq7Ak,6631
61
61
  trilogy/core/processing/node_generators/select_helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
62
  trilogy/core/processing/node_generators/select_helpers/datasource_injection.py,sha256=mKCDHxr2eyrdozXEHq_HvuwtBgnb9JPlImJIx6JGX34,7834
63
63
  trilogy/core/processing/nodes/__init__.py,sha256=zTge1EzwzEydlcMliIFO_TT7h7lS8l37lyZuQDir1h0,5487
@@ -76,7 +76,7 @@ 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=YC8GROz9iwRFrUuLdYdzJNKXOliYecmfEqXJtTQGRVE,45187
79
+ trilogy/dialect/base.py,sha256=5FI4_XDdSavdHeC3VhSI8xrvQagFyRRq6Ttsh70ajo4,45241
80
80
  trilogy/dialect/bigquery.py,sha256=e19dGcarapgA0x5_Xmq2StyHzuDWPOOPaR4elkWXwug,4203
81
81
  trilogy/dialect/common.py,sha256=hhzuMTFW9QQIP7TKLT9BlJy6lw2R03a68jKQ-7t4-2c,6070
82
82
  trilogy/dialect/config.py,sha256=olnyeVU5W5T6b9-dMeNAnvxuPlyc2uefb7FRME094Ec,3834
@@ -93,11 +93,11 @@ trilogy/hooks/graph_hook.py,sha256=5BfR7Dt0bgEsCLgwjowgCsVkboGYfVJGOz8g9mqpnos,4
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=_5UEnLtu40VQ8gb6wg3GtSrxf6IONhEOntmdsm0X4lU,30961
96
+ trilogy/parsing/common.py,sha256=yV1AckK0h8u1OFeGQBTMu-wuW5m63c5CcZuPicsTH_w,30660
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
100
- trilogy/parsing/parse_engine.py,sha256=vYhGmSJXi5TcLvt2mujISucQc35j4kHa78hj5ip9gGQ,72564
100
+ trilogy/parsing/parse_engine.py,sha256=YFIWTkWrUJ8l-KoCVwPs1hodj3BhqX-DHbBXWQN5akc,72776
101
101
  trilogy/parsing/render.py,sha256=gGCFj2ue0UoaU2MR6qHGMAHXkYRMkTmHjnBowdcgFMY,19603
102
102
  trilogy/parsing/trilogy.lark,sha256=1RIqA7zrGuqDJYSv9yHGSw0vdIfGOLPOnc4hSBRSTVU,14346
103
103
  trilogy/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -107,11 +107,11 @@ trilogy/std/date.preql,sha256=HWZm4t4HWyxr5geWRsY05RnHBVDMci8z8YA2cu0-OOw,188
107
107
  trilogy/std/display.preql,sha256=nm7lox87Xf6lBvXCVCS6x2HskguMKzndEBucJ5pktzk,175
108
108
  trilogy/std/geography.preql,sha256=qLnHmDU5EnvjTbfqZF-NEclSYM5_e9rZra7QjV01rZ4,582
109
109
  trilogy/std/money.preql,sha256=XWwvAV3WxBsHX9zfptoYRnBigcfYwrYtBHXTME0xJuQ,2082
110
- trilogy/std/net.preql,sha256=-bMV6dyofskl4Kvows-iQ4JCxjVUwsZOeWCy8JO5Ftw,135
110
+ trilogy/std/net.preql,sha256=7l7MqIjs6TDCpO6dBAoNJU81Ex255jZRK36kBgE1GDs,158
111
111
  trilogy/std/ranking.preql,sha256=LDoZrYyz4g3xsII9XwXfmstZD-_92i1Eox1UqkBIfi8,83
112
112
  trilogy/std/report.preql,sha256=LbV-XlHdfw0jgnQ8pV7acG95xrd1-p65fVpiIc-S7W4,202
113
- pytrilogy-0.0.3.71.dist-info/METADATA,sha256=fjanpiqcWQJVfNIXoj2k04p5-0miJb_Rcxc0lZM7moo,9734
114
- pytrilogy-0.0.3.71.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
115
- pytrilogy-0.0.3.71.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
116
- pytrilogy-0.0.3.71.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
117
- pytrilogy-0.0.3.71.dist-info/RECORD,,
113
+ pytrilogy-0.0.3.72.dist-info/METADATA,sha256=FuNovLn_nPyODANKBbc681JtNz4gBoUVY9udJ7n7A3k,9734
114
+ pytrilogy-0.0.3.72.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
115
+ pytrilogy-0.0.3.72.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
116
+ pytrilogy-0.0.3.72.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
117
+ pytrilogy-0.0.3.72.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.71"
7
+ __version__ = "0.0.3.72"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
trilogy/core/enums.py CHANGED
@@ -134,6 +134,7 @@ class FunctionType(Enum):
134
134
  CAST = "cast"
135
135
  CONCAT = "concat"
136
136
  CONSTANT = "constant"
137
+ TYPED_CONSTANT = "typed_constant"
137
138
  COALESCE = "coalesce"
138
139
  IS_NULL = "isnull"
139
140
  NULLIF = "nullif"
trilogy/core/functions.py CHANGED
@@ -704,6 +704,11 @@ FUNCTION_REGISTRY: dict[FunctionType, FunctionConfig] = {
704
704
  output_purpose=Purpose.CONSTANT,
705
705
  arg_count=1,
706
706
  ),
707
+ FunctionType.TYPED_CONSTANT: FunctionConfig(
708
+ output_purpose=Purpose.CONSTANT,
709
+ output_type_function=get_cast_output_type,
710
+ arg_count=2,
711
+ ),
707
712
  FunctionType.IS_NULL: FunctionConfig(
708
713
  output_purpose=Purpose.PROPERTY,
709
714
  output_type=DataType.BOOL,
@@ -1486,6 +1486,17 @@ def get_canonical_pseudonyms(environment: Environment) -> dict[str, set[str]]:
1486
1486
  return roots
1487
1487
 
1488
1488
 
1489
+ def requires_concept_nesting(
1490
+ expr,
1491
+ ) -> AggregateWrapper | WindowItem | FilterItem | Function | None:
1492
+ if isinstance(expr, (AggregateWrapper, WindowItem, FilterItem)):
1493
+ return expr
1494
+ if isinstance(expr, Function) and expr.operator == FunctionType.GROUP:
1495
+ # group by requires nesting
1496
+ return expr
1497
+ return None
1498
+
1499
+
1489
1500
  class Factory:
1490
1501
 
1491
1502
  def __init__(
@@ -1509,11 +1520,12 @@ class Factory:
1509
1520
  | WindowItem
1510
1521
  | FilterItem
1511
1522
  | Function
1512
- | ListWrapper[Any]
1513
- | MapWrapper[Any, Any]
1523
+ | ListWrapper
1524
+ | MapWrapper
1514
1525
  | int
1515
1526
  | float
1516
1527
  | str
1528
+ | date
1517
1529
  ),
1518
1530
  ) -> tuple[Concept, BuildConcept]:
1519
1531
  from trilogy.parsing.common import arbitrary_to_concept
@@ -1572,7 +1584,8 @@ class Factory:
1572
1584
 
1573
1585
  raw_args: list[Concept | FuncArgs] = []
1574
1586
  for arg in base.arguments:
1575
- # to do proper discovery, we need to inject virtual intermediate ocncepts
1587
+ # to do proper discovery, we need to inject virtual intermediate concepts
1588
+ # we don't use requires_concept_nesting here by design
1576
1589
  if isinstance(arg, (AggregateWrapper, FilterItem, WindowItem)):
1577
1590
  narg, _ = self.instantiate_concept(arg)
1578
1591
  raw_args.append(narg)
@@ -1640,11 +1653,10 @@ class Factory:
1640
1653
  def _(self, base: CaseWhen) -> BuildCaseWhen:
1641
1654
 
1642
1655
  comparison = base.comparison
1643
- if isinstance(comparison, (AggregateWrapper, FilterItem, WindowItem)):
1644
- comparison, _ = self.instantiate_concept(comparison)
1645
1656
  expr: Concept | FuncArgs = base.expr
1646
- if isinstance(expr, (AggregateWrapper, FilterItem, WindowItem)):
1647
- expr, _ = self.instantiate_concept(expr)
1657
+ validation = requires_concept_nesting(expr)
1658
+ if validation:
1659
+ expr, _ = self.instantiate_concept(validation)
1648
1660
  return BuildCaseWhen.model_construct(
1649
1661
  comparison=self.build(comparison),
1650
1662
  expr=self.build(expr),
@@ -1653,8 +1665,9 @@ class Factory:
1653
1665
  @build.register
1654
1666
  def _(self, base: CaseElse) -> BuildCaseElse:
1655
1667
  expr: Concept | FuncArgs = base.expr
1656
- if isinstance(expr, (AggregateWrapper, FilterItem, WindowItem)):
1657
- expr, _ = self.instantiate_concept(expr)
1668
+ validation = requires_concept_nesting(expr)
1669
+ if validation:
1670
+ expr, _ = self.instantiate_concept(validation)
1658
1671
  return BuildCaseElse.model_construct(expr=self.build(expr))
1659
1672
 
1660
1673
  @build.register
@@ -1753,10 +1766,9 @@ class Factory:
1753
1766
  def _(self, base: OrderItem) -> BuildOrderItem:
1754
1767
 
1755
1768
  bexpr: Any
1756
- if isinstance(base.expr, (AggregateWrapper, WindowItem, FilterItem)) or (
1757
- isinstance(base.expr, Function) and base.expr.operator == FunctionType.GROUP
1758
- ):
1759
- bexpr, _ = self.instantiate_concept(base.expr)
1769
+ validation = requires_concept_nesting(base.expr)
1770
+ if validation:
1771
+ bexpr, _ = self.instantiate_concept(validation)
1760
1772
  else:
1761
1773
  bexpr = base.expr
1762
1774
  return BuildOrderItem.model_construct(
@@ -1781,8 +1793,9 @@ class Factory:
1781
1793
  def _(self, base: WindowItem) -> BuildWindowItem:
1782
1794
 
1783
1795
  content: Concept | FuncArgs = base.content
1784
- if isinstance(content, (AggregateWrapper, FilterItem, WindowItem)):
1785
- content, _ = self.instantiate_concept(content)
1796
+ validation = requires_concept_nesting(base.content)
1797
+ if validation:
1798
+ content, _ = self.instantiate_concept(validation)
1786
1799
  final_by = []
1787
1800
  for x in base.order_by:
1788
1801
  if (
@@ -1811,6 +1824,7 @@ class Factory:
1811
1824
  @build.register
1812
1825
  def _(self, base: SubselectComparison) -> BuildSubselectComparison:
1813
1826
  right: Any = base.right
1827
+ # this has specialized logic - include all Functions
1814
1828
  if isinstance(base.right, (AggregateWrapper, WindowItem, FilterItem, Function)):
1815
1829
  right_c, _ = self.instantiate_concept(base.right)
1816
1830
  right = right_c
@@ -1824,12 +1838,14 @@ class Factory:
1824
1838
  def _(self, base: Comparison) -> BuildComparison:
1825
1839
 
1826
1840
  left = base.left
1827
- if isinstance(left, (AggregateWrapper, WindowItem, FilterItem)):
1828
- left_c, _ = self.instantiate_concept(left)
1841
+ validation = requires_concept_nesting(base.left)
1842
+ if validation:
1843
+ left_c, _ = self.instantiate_concept(validation)
1829
1844
  left = left_c # type: ignore
1830
1845
  right = base.right
1831
- if isinstance(right, (AggregateWrapper, WindowItem, FilterItem)):
1832
- right_c, _ = self.instantiate_concept(right)
1846
+ validation = requires_concept_nesting(base.right)
1847
+ if validation:
1848
+ right_c, _ = self.instantiate_concept(validation)
1833
1849
  right = right_c # type: ignore
1834
1850
  return BuildComparison.model_construct(
1835
1851
  left=self.handle_constant(self.build(left)),
@@ -39,6 +39,7 @@ def resolve_window_parent_concepts(
39
39
  base += item.concept_arguments
40
40
  if concept.grain:
41
41
  for gitem in concept.grain.components:
42
+ logger.info(f"{LOGGER_PREFIX} appending grain item {gitem} to base")
42
43
  base.append(environment.concepts[gitem])
43
44
  return concept.lineage.content, unique(base, "address")
44
45
 
@@ -55,7 +56,7 @@ def gen_window_node(
55
56
  ) -> StrategyNode | None:
56
57
  base, parent_concepts = resolve_window_parent_concepts(concept, environment)
57
58
  logger.info(
58
- f"{padding(depth)}{LOGGER_PREFIX} generating window node for {concept} with parents {parent_concepts} and optional {local_optional}"
59
+ f"{padding(depth)}{LOGGER_PREFIX} generating window node for {concept} with parents {[x.address for x in parent_concepts]} and optional {local_optional}"
59
60
  )
60
61
  equivalent_optional = [
61
62
  x
trilogy/dialect/base.py CHANGED
@@ -163,6 +163,7 @@ FUNCTION_MAP = {
163
163
  FunctionType.ALIAS: lambda x: f"{x[0]}",
164
164
  FunctionType.GROUP: lambda x: f"{x[0]}",
165
165
  FunctionType.CONSTANT: lambda x: f"{x[0]}",
166
+ FunctionType.TYPED_CONSTANT: lambda x: f"{x[0]}",
166
167
  FunctionType.COALESCE: lambda x: f"coalesce({','.join(x)})",
167
168
  FunctionType.NULLIF: lambda x: f"nullif({x[0]},{x[1]})",
168
169
  FunctionType.CAST: lambda x: f"cast({x[0]} as {x[1]})",
trilogy/parsing/common.py CHANGED
@@ -173,7 +173,9 @@ def concept_list_to_keys(
173
173
 
174
174
 
175
175
  def constant_to_concept(
176
- parent: ListWrapper | TupleWrapper | MapWrapper | int | float | str,
176
+ parent: (
177
+ ListWrapper | TupleWrapper | MapWrapper | int | float | str | date | datetime
178
+ ),
177
179
  name: str,
178
180
  namespace: str,
179
181
  metadata: Metadata | None = None,
@@ -368,9 +370,9 @@ def _get_relevant_parent_concepts(arg) -> tuple[list[ConceptRef], bool]:
368
370
  return get_concept_arguments(arg), False
369
371
 
370
372
 
371
- def get_relevant_parent_concepts(arg):
372
- results = _get_relevant_parent_concepts(arg)
373
- return results
373
+ def get_relevant_parent_concepts(arg) -> tuple[list[ConceptRef], bool]:
374
+ concepts, status = _get_relevant_parent_concepts(arg)
375
+ return unique(concepts, "address"), status
374
376
 
375
377
 
376
378
  def group_function_to_concept(
@@ -626,20 +628,11 @@ def window_item_to_concept(
626
628
 
627
629
  # when including the order by in discovery grain
628
630
  if parent.order_by:
631
+
629
632
  grain_components = parent.over + [bcontent.output]
630
633
  for item in parent.order_by:
631
- # confirm that it's not just an aggregate at the grain of the stuff we're already keying of of
632
- # in which case we can ignore contributions
633
- if (
634
- isinstance(item.expr, AggregateWrapper)
635
- and set([x.address for x in item.expr.by]) == keys
636
- ):
637
- continue
638
- elif isinstance(item.expr, AggregateWrapper):
639
-
640
- grain_components += item.expr.by
641
- else:
642
- grain_components += item.concept_arguments
634
+ relevant, _ = get_relevant_parent_concepts(item.expr)
635
+ grain_components += relevant
643
636
  else:
644
637
  grain_components = parent.over + [bcontent.output]
645
638
 
@@ -842,6 +835,7 @@ def arbitrary_to_concept(
842
835
  | int
843
836
  | float
844
837
  | str
838
+ | date
845
839
  ),
846
840
  environment: Environment,
847
841
  namespace: str | None = None,
@@ -640,6 +640,7 @@ class ParseToObjects(Transformer):
640
640
 
641
641
  @v_args(meta=True)
642
642
  def concept_derivation(self, meta: Meta, args) -> ConceptDerivationStatement:
643
+
643
644
  if len(args) > 3:
644
645
  metadata = args[3]
645
646
  else:
@@ -733,6 +734,7 @@ class ParseToObjects(Transformer):
733
734
 
734
735
  @v_args(meta=True)
735
736
  def constant_derivation(self, meta: Meta, args) -> Concept:
737
+
736
738
  if len(args) > 3:
737
739
  metadata = args[3]
738
740
  else:
@@ -1405,6 +1407,7 @@ class ParseToObjects(Transformer):
1405
1407
  def string_lit(self, args) -> str:
1406
1408
  if not args:
1407
1409
  return ""
1410
+
1408
1411
  return args[0]
1409
1412
 
1410
1413
  @v_args(meta=True)
@@ -1890,7 +1893,9 @@ class ParseToObjects(Transformer):
1890
1893
 
1891
1894
  def internal_fcast(self, meta, args) -> Function:
1892
1895
  args = process_function_args(args, meta=meta, environment=self.environment)
1896
+
1893
1897
  if isinstance(args[0], str):
1898
+
1894
1899
  processed: date | datetime | int | float | bool | str
1895
1900
  if args[1] == DataType.DATE:
1896
1901
  processed = date.fromisoformat(args[0])
@@ -1908,6 +1913,10 @@ class ParseToObjects(Transformer):
1908
1913
  processed = args[0]
1909
1914
  else:
1910
1915
  raise SyntaxError(f"Invalid cast type {args[1]}")
1916
+ if isinstance(args[1], TraitDataType):
1917
+ return self.function_factory.create_function(
1918
+ [processed, args[1]], FunctionType.TYPED_CONSTANT, meta
1919
+ )
1911
1920
  return self.function_factory.create_function(
1912
1921
  [processed], FunctionType.CONSTANT, meta
1913
1922
  )
trilogy/std/net.preql CHANGED
@@ -5,4 +5,5 @@ type domain string;
5
5
  type ip_net_mask string;
6
6
  type ipv6_address string;
7
7
  type ipv4_address string;
8
- type suffix string;
8
+ type suffix string;
9
+ type url_image string;