pytrilogy 0.0.2.11__py3-none-any.whl → 0.0.2.13__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.

Files changed (31) hide show
  1. {pytrilogy-0.0.2.11.dist-info → pytrilogy-0.0.2.13.dist-info}/METADATA +1 -1
  2. {pytrilogy-0.0.2.11.dist-info → pytrilogy-0.0.2.13.dist-info}/RECORD +31 -31
  3. {pytrilogy-0.0.2.11.dist-info → pytrilogy-0.0.2.13.dist-info}/WHEEL +1 -1
  4. trilogy/__init__.py +1 -1
  5. trilogy/constants.py +5 -0
  6. trilogy/core/enums.py +3 -1
  7. trilogy/core/environment_helpers.py +44 -6
  8. trilogy/core/models.py +51 -27
  9. trilogy/core/optimization.py +31 -3
  10. trilogy/core/optimizations/__init__.py +2 -1
  11. trilogy/core/optimizations/predicate_pushdown.py +60 -42
  12. trilogy/core/processing/concept_strategies_v3.py +6 -4
  13. trilogy/core/processing/node_generators/basic_node.py +22 -9
  14. trilogy/core/processing/node_generators/common.py +13 -23
  15. trilogy/core/processing/node_generators/node_merge_node.py +22 -1
  16. trilogy/core/processing/node_generators/unnest_node.py +10 -3
  17. trilogy/core/processing/nodes/base_node.py +18 -11
  18. trilogy/core/processing/nodes/group_node.py +0 -1
  19. trilogy/core/processing/nodes/merge_node.py +12 -5
  20. trilogy/core/processing/nodes/unnest_node.py +13 -9
  21. trilogy/core/processing/utility.py +3 -1
  22. trilogy/core/query_processor.py +14 -12
  23. trilogy/dialect/base.py +95 -52
  24. trilogy/dialect/common.py +3 -3
  25. trilogy/executor.py +8 -2
  26. trilogy/parsing/common.py +73 -2
  27. trilogy/parsing/parse_engine.py +88 -132
  28. trilogy/parsing/trilogy.lark +3 -3
  29. {pytrilogy-0.0.2.11.dist-info → pytrilogy-0.0.2.13.dist-info}/LICENSE.md +0 -0
  30. {pytrilogy-0.0.2.11.dist-info → pytrilogy-0.0.2.13.dist-info}/entry_points.txt +0 -0
  31. {pytrilogy-0.0.2.11.dist-info → pytrilogy-0.0.2.13.dist-info}/top_level.txt +0 -0
@@ -16,7 +16,6 @@ from trilogy.core.internal import INTERNAL_NAMESPACE, ALL_ROWS_CONCEPT
16
16
  from trilogy.constants import (
17
17
  DEFAULT_NAMESPACE,
18
18
  NULL_VALUE,
19
- VIRTUAL_CONCEPT_PREFIX,
20
19
  MagicConstants,
21
20
  )
22
21
  from trilogy.core.enums import (
@@ -24,7 +23,6 @@ from trilogy.core.enums import (
24
23
  ComparisonOperator,
25
24
  FunctionType,
26
25
  InfiniteFunctionArgs,
27
- FunctionClass,
28
26
  Modifier,
29
27
  Ordering,
30
28
  Purpose,
@@ -104,14 +102,12 @@ from trilogy.core.models import (
104
102
  ConceptDeclarationStatement,
105
103
  ConceptDerivation,
106
104
  RowsetDerivationStatement,
107
- LooseConceptList,
108
105
  list_to_wrapper,
109
106
  dict_to_map_wrapper,
110
107
  NumericType,
111
108
  HavingClause,
112
109
  )
113
110
  from trilogy.parsing.exceptions import ParseError
114
- from trilogy.utility import string_to_hash
115
111
  from trilogy.parsing.common import (
116
112
  agg_wrapper_to_concept,
117
113
  window_item_to_concept,
@@ -119,6 +115,7 @@ from trilogy.parsing.common import (
119
115
  filter_item_to_concept,
120
116
  constant_to_concept,
121
117
  arbitrary_to_concept,
118
+ process_function_args,
122
119
  )
123
120
 
124
121
  CONSTANT_TYPES = (int, float, str, bool, list, ListWrapper, MapWrapper)
@@ -230,50 +227,6 @@ class ParseToObjects(Transformer):
230
227
  self.environment.concepts.undefined = {}
231
228
  return reparsed
232
229
 
233
- def process_function_args(
234
- self, args, meta: Meta, concept_arguments: Optional[LooseConceptList] = None
235
- ):
236
- final: List[Concept | Function] = []
237
- for arg in args:
238
- # if a function has an anonymous function argument
239
- # create an implicit concept
240
- while isinstance(arg, Parenthetical):
241
- arg = arg.content
242
- if isinstance(arg, Function):
243
- # if it's not an aggregate function, we can skip the virtual concepts
244
- # to simplify anonymous function handling
245
- if arg.operator not in FunctionClass.AGGREGATE_FUNCTIONS.value:
246
- final.append(arg)
247
- continue
248
- id_hash = string_to_hash(str(arg))
249
- concept = function_to_concept(
250
- arg,
251
- name=f"{VIRTUAL_CONCEPT_PREFIX}_{id_hash}",
252
- namespace=self.environment.namespace,
253
- )
254
- # to satisfy mypy, concept will always have metadata
255
- if concept.metadata:
256
- concept.metadata.line_number = meta.line
257
- self.environment.add_concept(concept, meta=meta)
258
- final.append(concept)
259
- elif isinstance(
260
- arg, (FilterItem, WindowItem, AggregateWrapper, ListWrapper, MapWrapper)
261
- ):
262
- id_hash = string_to_hash(str(arg))
263
- concept = arbitrary_to_concept(
264
- arg,
265
- name=f"{VIRTUAL_CONCEPT_PREFIX}_{id_hash}",
266
- namespace=self.environment.namespace,
267
- )
268
- if concept.metadata:
269
- concept.metadata.line_number = meta.line
270
- self.environment.add_concept(concept, meta=meta)
271
- final.append(concept)
272
-
273
- else:
274
- final.append(arg)
275
- return final
276
-
277
230
  def start(self, args):
278
231
  return args
279
232
 
@@ -319,17 +272,18 @@ class ParseToObjects(Transformer):
319
272
  @v_args(meta=True)
320
273
  def struct_type(self, meta: Meta, args) -> StructType:
321
274
  final: list[
322
- DataType | MapType | ListType | StructType | NumericType | Concept
275
+ DataType | MapType | ListType | NumericType | StructType | Concept
323
276
  ] = []
324
277
  for arg in args:
325
- if not isinstance(arg, (DataType, ListType, StructType)):
326
- new = self.environment.concepts.__getitem__( # type: ignore
327
- key=arg, line_no=meta.line
328
- )
329
- final.append(new)
330
- else:
331
- final.append(arg)
332
- return StructType(fields=final)
278
+ new = self.environment.concepts.__getitem__( # type: ignore
279
+ key=arg, line_no=meta.line
280
+ )
281
+ final.append(new)
282
+
283
+ return StructType(
284
+ fields=final,
285
+ fields_map={x.name: x for x in final if isinstance(x, Concept)},
286
+ )
333
287
 
334
288
  def list_type(self, args) -> ListType:
335
289
  return ListType(type=args[0])
@@ -520,18 +474,6 @@ class ParseToObjects(Transformer):
520
474
  if concept.metadata:
521
475
  concept.metadata.line_number = meta.line
522
476
  self.environment.add_concept(concept, meta=meta)
523
- assert isinstance(concept.datatype, StructType)
524
- for key, value in concept.datatype.fields_map.items():
525
- args = self.process_function_args([concept, key], meta=meta)
526
- self.environment.add_concept(
527
- Concept(
528
- name=key,
529
- datatype=arg_to_datatype(value),
530
- purpose=Purpose.PROPERTY,
531
- namespace=self.environment.namespace + "." + name,
532
- lineage=AttrAccess(args),
533
- )
534
- )
535
477
  return ConceptDerivation(concept=concept)
536
478
  elif (
537
479
  isinstance(source_value, Function)
@@ -795,8 +737,8 @@ class ParseToObjects(Transformer):
795
737
  x = arbitrary_to_concept(
796
738
  x,
797
739
  namespace=namespace,
798
- name=f"{VIRTUAL_CONCEPT_PREFIX}_{string_to_hash(str(x))}",
799
740
  )
741
+ self.environment.add_concept(x)
800
742
  return x
801
743
 
802
744
  return [
@@ -837,6 +779,11 @@ class ParseToObjects(Transformer):
837
779
  def rawsql_statement(self, meta: Meta, args) -> RawSQLStatement:
838
780
  return RawSQLStatement(meta=Metadata(line_number=meta.line), text=args[0])
839
781
 
782
+ def resolve_import_address(self, address) -> str:
783
+ with open(address, "r", encoding="utf-8") as f:
784
+ text = f.read()
785
+ return text
786
+
840
787
  def import_statement(self, args: list[str]) -> ImportStatement:
841
788
  alias = args[-1]
842
789
  path = args[0].split(".")
@@ -846,8 +793,7 @@ class ParseToObjects(Transformer):
846
793
  nparser = self.parsed[target]
847
794
  else:
848
795
  try:
849
- with open(target, "r", encoding="utf-8") as f:
850
- text = f.read()
796
+ text = self.resolve_import_address(target)
851
797
  nparser = ParseToObjects(
852
798
  visit_tokens=True,
853
799
  text=text,
@@ -1001,6 +947,12 @@ class ParseToObjects(Transformer):
1001
947
  )
1002
948
  self.environment.add_concept(new_concept, meta=meta)
1003
949
  item.content.output = new_concept
950
+ elif isinstance(item.content, Concept):
951
+ # Sometimes cached values here don't have the latest info
952
+ # bug we can't just use environment, as it might not have the right grain.
953
+ item.content = self.environment.concepts[
954
+ item.content.address
955
+ ].with_grain(item.content.grain)
1004
956
  # TODO: revisit if we can push down every filter
1005
957
  # else:
1006
958
  # item.content = (
@@ -1143,7 +1095,6 @@ class ParseToObjects(Transformer):
1143
1095
  left = arbitrary_to_concept(
1144
1096
  args[0],
1145
1097
  namespace=self.environment.namespace,
1146
- name=f"{VIRTUAL_CONCEPT_PREFIX}_{string_to_hash(str(args[0]))}",
1147
1098
  )
1148
1099
  self.environment.add_concept(left)
1149
1100
  else:
@@ -1152,7 +1103,6 @@ class ParseToObjects(Transformer):
1152
1103
  right = arbitrary_to_concept(
1153
1104
  args[2],
1154
1105
  namespace=self.environment.namespace,
1155
- name=f"{VIRTUAL_CONCEPT_PREFIX}_{string_to_hash(str(args[2]))}",
1156
1106
  )
1157
1107
  self.environment.add_concept(right)
1158
1108
  else:
@@ -1187,7 +1137,6 @@ class ParseToObjects(Transformer):
1187
1137
  right = arbitrary_to_concept(
1188
1138
  right,
1189
1139
  namespace=self.environment.namespace,
1190
- name=f"{VIRTUAL_CONCEPT_PREFIX}_{string_to_hash(str(right))}",
1191
1140
  )
1192
1141
  self.environment.add_concept(right, meta=meta)
1193
1142
  return SubselectComparison(
@@ -1236,8 +1185,9 @@ class ParseToObjects(Transformer):
1236
1185
  def window_item_order(self, args):
1237
1186
  return WindowItemOrder(contents=args[0])
1238
1187
 
1239
- def window_item(self, args) -> WindowItem:
1240
- type = args[0]
1188
+ @v_args(meta=True)
1189
+ def window_item(self, meta, args) -> WindowItem:
1190
+ type: WindowType = args[0]
1241
1191
  order_by = []
1242
1192
  over = []
1243
1193
  index = None
@@ -1253,6 +1203,14 @@ class ParseToObjects(Transformer):
1253
1203
  concept = self.environment.concepts[item]
1254
1204
  elif isinstance(item, Concept):
1255
1205
  concept = item
1206
+ elif isinstance(item, WindowType):
1207
+ type = item
1208
+ else:
1209
+ concept = arbitrary_to_concept(
1210
+ item,
1211
+ namespace=self.environment.namespace,
1212
+ )
1213
+ self.environment.add_concept(concept, meta=meta)
1256
1214
  assert concept
1257
1215
  return WindowItem(
1258
1216
  type=type, content=concept, over=over, order_by=order_by, index=index
@@ -1291,57 +1249,58 @@ class ParseToObjects(Transformer):
1291
1249
 
1292
1250
  @v_args(meta=True)
1293
1251
  def index_access(self, meta, args):
1294
- args = self.process_function_args(args, meta=meta)
1252
+ args = process_function_args(args, meta=meta, environment=self.environment)
1295
1253
  if args[0].datatype == DataType.MAP or isinstance(args[0].datatype, MapType):
1296
1254
  return MapAccess(args)
1297
1255
  return IndexAccess(args)
1298
1256
 
1299
1257
  @v_args(meta=True)
1300
1258
  def map_key_access(self, meta, args):
1301
- args = self.process_function_args(args, meta=meta)
1259
+ args = process_function_args(args, meta=meta, environment=self.environment)
1302
1260
  return MapAccess(args)
1303
1261
 
1304
1262
  @v_args(meta=True)
1305
1263
  def attr_access(self, meta, args):
1306
- args = self.process_function_args(args, meta=meta)
1264
+ args = process_function_args(args, meta=meta, environment=self.environment)
1307
1265
  return AttrAccess(args)
1308
1266
 
1309
1267
  @v_args(meta=True)
1310
1268
  def fcoalesce(self, meta, args):
1311
- args = self.process_function_args(args, meta=meta)
1269
+ args = process_function_args(args, meta=meta, environment=self.environment)
1312
1270
  return Coalesce(args)
1313
1271
 
1314
1272
  @v_args(meta=True)
1315
1273
  def unnest(self, meta, args):
1316
- args = self.process_function_args(args, meta=meta)
1274
+ args = process_function_args(args, meta=meta, environment=self.environment)
1317
1275
  return Unnest(args)
1318
1276
 
1319
1277
  @v_args(meta=True)
1320
1278
  def count(self, meta, args):
1321
- args = self.process_function_args(args, meta=meta)
1279
+ args = process_function_args(args, meta=meta, environment=self.environment)
1322
1280
  return Count(args)
1323
1281
 
1324
1282
  @v_args(meta=True)
1325
1283
  def fgroup(self, meta, args):
1326
1284
  if len(args) == 2:
1327
- args = self.process_function_args([args[0]] + args[1], meta=meta)
1285
+ fargs = [args[0]] + args[1]
1328
1286
  else:
1329
- args = self.process_function_args([args[0]], meta=meta)
1287
+ fargs = [args[0]]
1288
+ args = process_function_args(fargs, meta=meta, environment=self.environment)
1330
1289
  return Group(args)
1331
1290
 
1332
1291
  @v_args(meta=True)
1333
1292
  def fabs(self, meta, args):
1334
- args = self.process_function_args(args, meta=meta)
1293
+ args = process_function_args(args, meta=meta, environment=self.environment)
1335
1294
  return Abs(args)
1336
1295
 
1337
1296
  @v_args(meta=True)
1338
1297
  def count_distinct(self, meta, args):
1339
- args = self.process_function_args(args, meta=meta)
1298
+ args = process_function_args(args, meta=meta, environment=self.environment)
1340
1299
  return CountDistinct(args)
1341
1300
 
1342
1301
  @v_args(meta=True)
1343
1302
  def sum(self, meta, args):
1344
- args = self.process_function_args(args, meta=meta)
1303
+ args = process_function_args(args, meta=meta, environment=self.environment)
1345
1304
  return Function(
1346
1305
  operator=FunctionType.SUM,
1347
1306
  arguments=args,
@@ -1352,7 +1311,7 @@ class ParseToObjects(Transformer):
1352
1311
 
1353
1312
  @v_args(meta=True)
1354
1313
  def avg(self, meta, args):
1355
- args = self.process_function_args(args, meta=meta)
1314
+ args = process_function_args(args, meta=meta, environment=self.environment)
1356
1315
  arg = args[0]
1357
1316
 
1358
1317
  return Function(
@@ -1366,17 +1325,17 @@ class ParseToObjects(Transformer):
1366
1325
 
1367
1326
  @v_args(meta=True)
1368
1327
  def max(self, meta, args):
1369
- args = self.process_function_args(args, meta=meta)
1328
+ args = process_function_args(args, meta=meta, environment=self.environment)
1370
1329
  return Max(args)
1371
1330
 
1372
1331
  @v_args(meta=True)
1373
1332
  def min(self, meta, args):
1374
- args = self.process_function_args(args, meta=meta)
1333
+ args = process_function_args(args, meta=meta, environment=self.environment)
1375
1334
  return Min(args)
1376
1335
 
1377
1336
  @v_args(meta=True)
1378
1337
  def len(self, meta, args):
1379
- args = self.process_function_args(args, meta=meta)
1338
+ args = process_function_args(args, meta=meta, environment=self.environment)
1380
1339
  return Function(
1381
1340
  operator=FunctionType.LENGTH,
1382
1341
  arguments=args,
@@ -1388,12 +1347,12 @@ class ParseToObjects(Transformer):
1388
1347
 
1389
1348
  @v_args(meta=True)
1390
1349
  def fsplit(self, meta, args):
1391
- args = self.process_function_args(args, meta=meta)
1350
+ args = process_function_args(args, meta=meta, environment=self.environment)
1392
1351
  return Split(args)
1393
1352
 
1394
1353
  @v_args(meta=True)
1395
1354
  def concat(self, meta, args):
1396
- args = self.process_function_args(args, meta=meta)
1355
+ args = process_function_args(args, meta=meta, environment=self.environment)
1397
1356
  return Function(
1398
1357
  operator=FunctionType.CONCAT,
1399
1358
  arguments=args,
@@ -1406,7 +1365,7 @@ class ParseToObjects(Transformer):
1406
1365
 
1407
1366
  @v_args(meta=True)
1408
1367
  def like(self, meta, args):
1409
- args = self.process_function_args(args, meta=meta)
1368
+ args = process_function_args(args, meta=meta, environment=self.environment)
1410
1369
  return Function(
1411
1370
  operator=FunctionType.LIKE,
1412
1371
  arguments=args,
@@ -1418,7 +1377,7 @@ class ParseToObjects(Transformer):
1418
1377
 
1419
1378
  @v_args(meta=True)
1420
1379
  def alt_like(self, meta, args):
1421
- args = self.process_function_args(args, meta=meta)
1380
+ args = process_function_args(args, meta=meta, environment=self.environment)
1422
1381
  return Function(
1423
1382
  operator=FunctionType.LIKE,
1424
1383
  arguments=args,
@@ -1430,7 +1389,7 @@ class ParseToObjects(Transformer):
1430
1389
 
1431
1390
  @v_args(meta=True)
1432
1391
  def ilike(self, meta, args):
1433
- args = self.process_function_args(args, meta=meta)
1392
+ args = process_function_args(args, meta=meta, environment=self.environment)
1434
1393
  return Function(
1435
1394
  operator=FunctionType.ILIKE,
1436
1395
  arguments=args,
@@ -1442,7 +1401,7 @@ class ParseToObjects(Transformer):
1442
1401
 
1443
1402
  @v_args(meta=True)
1444
1403
  def upper(self, meta, args):
1445
- args = self.process_function_args(args, meta=meta)
1404
+ args = process_function_args(args, meta=meta, environment=self.environment)
1446
1405
  return Function(
1447
1406
  operator=FunctionType.UPPER,
1448
1407
  arguments=args,
@@ -1454,15 +1413,12 @@ class ParseToObjects(Transformer):
1454
1413
 
1455
1414
  @v_args(meta=True)
1456
1415
  def fstrpos(self, meta, args):
1457
- args = self.process_function_args(args, meta=meta)
1416
+ args = process_function_args(args, meta=meta, environment=self.environment)
1458
1417
  return StrPos(args)
1459
1418
 
1460
1419
  @v_args(meta=True)
1461
1420
  def fsubstring(self, meta, args):
1462
- args = self.process_function_args(
1463
- args,
1464
- meta=meta,
1465
- )
1421
+ args = process_function_args(args, meta=meta, environment=self.environment)
1466
1422
  return SubString(args)
1467
1423
 
1468
1424
  def logical_operator(self, args):
@@ -1470,7 +1426,7 @@ class ParseToObjects(Transformer):
1470
1426
 
1471
1427
  @v_args(meta=True)
1472
1428
  def lower(self, meta, args):
1473
- args = self.process_function_args(args, meta=meta)
1429
+ args = process_function_args(args, meta=meta, environment=self.environment)
1474
1430
  return Function(
1475
1431
  operator=FunctionType.LOWER,
1476
1432
  arguments=args,
@@ -1483,7 +1439,7 @@ class ParseToObjects(Transformer):
1483
1439
  # date functions
1484
1440
  @v_args(meta=True)
1485
1441
  def fdate(self, meta, args):
1486
- args = self.process_function_args(args, meta=meta)
1442
+ args = process_function_args(args, meta=meta, environment=self.environment)
1487
1443
  return Function(
1488
1444
  operator=FunctionType.DATE,
1489
1445
  arguments=args,
@@ -1503,7 +1459,7 @@ class ParseToObjects(Transformer):
1503
1459
 
1504
1460
  @v_args(meta=True)
1505
1461
  def fdate_trunc(self, meta, args):
1506
- args = self.process_function_args(args, meta=meta)
1462
+ args = process_function_args(args, meta=meta, environment=self.environment)
1507
1463
  return Function(
1508
1464
  operator=FunctionType.DATE_TRUNCATE,
1509
1465
  arguments=args,
@@ -1523,7 +1479,7 @@ class ParseToObjects(Transformer):
1523
1479
 
1524
1480
  @v_args(meta=True)
1525
1481
  def fdate_part(self, meta, args):
1526
- args = self.process_function_args(args, meta=meta)
1482
+ args = process_function_args(args, meta=meta, environment=self.environment)
1527
1483
  return Function(
1528
1484
  operator=FunctionType.DATE_PART,
1529
1485
  arguments=args,
@@ -1543,7 +1499,7 @@ class ParseToObjects(Transformer):
1543
1499
 
1544
1500
  @v_args(meta=True)
1545
1501
  def fdate_add(self, meta, args):
1546
- args = self.process_function_args(args, meta=meta)
1502
+ args = process_function_args(args, meta=meta, environment=self.environment)
1547
1503
  return Function(
1548
1504
  operator=FunctionType.DATE_ADD,
1549
1505
  arguments=args,
@@ -1564,7 +1520,7 @@ class ParseToObjects(Transformer):
1564
1520
 
1565
1521
  @v_args(meta=True)
1566
1522
  def fdate_diff(self, meta, args):
1567
- args = self.process_function_args(args, meta=meta)
1523
+ args = process_function_args(args, meta=meta, environment=self.environment)
1568
1524
  purpose = function_args_to_output_purpose(args)
1569
1525
  return Function(
1570
1526
  operator=FunctionType.DATE_DIFF,
@@ -1589,7 +1545,7 @@ class ParseToObjects(Transformer):
1589
1545
 
1590
1546
  @v_args(meta=True)
1591
1547
  def fdatetime(self, meta, args):
1592
- args = self.process_function_args(args, meta=meta)
1548
+ args = process_function_args(args, meta=meta, environment=self.environment)
1593
1549
  return Function(
1594
1550
  operator=FunctionType.DATETIME,
1595
1551
  arguments=args,
@@ -1606,7 +1562,7 @@ class ParseToObjects(Transformer):
1606
1562
 
1607
1563
  @v_args(meta=True)
1608
1564
  def ftimestamp(self, meta, args):
1609
- args = self.process_function_args(args, meta=meta)
1565
+ args = process_function_args(args, meta=meta, environment=self.environment)
1610
1566
  return Function(
1611
1567
  operator=FunctionType.TIMESTAMP,
1612
1568
  arguments=args,
@@ -1618,7 +1574,7 @@ class ParseToObjects(Transformer):
1618
1574
 
1619
1575
  @v_args(meta=True)
1620
1576
  def fsecond(self, meta, args):
1621
- args = self.process_function_args(args, meta=meta)
1577
+ args = process_function_args(args, meta=meta, environment=self.environment)
1622
1578
  return Function(
1623
1579
  operator=FunctionType.SECOND,
1624
1580
  arguments=args,
@@ -1630,7 +1586,7 @@ class ParseToObjects(Transformer):
1630
1586
 
1631
1587
  @v_args(meta=True)
1632
1588
  def fminute(self, meta, args):
1633
- args = self.process_function_args(args, meta=meta)
1589
+ args = process_function_args(args, meta=meta, environment=self.environment)
1634
1590
  return Function(
1635
1591
  operator=FunctionType.MINUTE,
1636
1592
  arguments=args,
@@ -1642,7 +1598,7 @@ class ParseToObjects(Transformer):
1642
1598
 
1643
1599
  @v_args(meta=True)
1644
1600
  def fhour(self, meta, args):
1645
- args = self.process_function_args(args, meta=meta)
1601
+ args = process_function_args(args, meta=meta, environment=self.environment)
1646
1602
  return Function(
1647
1603
  operator=FunctionType.HOUR,
1648
1604
  arguments=args,
@@ -1654,7 +1610,7 @@ class ParseToObjects(Transformer):
1654
1610
 
1655
1611
  @v_args(meta=True)
1656
1612
  def fday(self, meta, args):
1657
- args = self.process_function_args(args, meta=meta)
1613
+ args = process_function_args(args, meta=meta, environment=self.environment)
1658
1614
  return Function(
1659
1615
  operator=FunctionType.DAY,
1660
1616
  arguments=args,
@@ -1666,7 +1622,7 @@ class ParseToObjects(Transformer):
1666
1622
 
1667
1623
  @v_args(meta=True)
1668
1624
  def fday_of_week(self, meta, args):
1669
- args = self.process_function_args(args, meta=meta)
1625
+ args = process_function_args(args, meta=meta, environment=self.environment)
1670
1626
  return Function(
1671
1627
  operator=FunctionType.DAY_OF_WEEK,
1672
1628
  arguments=args,
@@ -1678,7 +1634,7 @@ class ParseToObjects(Transformer):
1678
1634
 
1679
1635
  @v_args(meta=True)
1680
1636
  def fweek(self, meta, args):
1681
- args = self.process_function_args(args, meta=meta)
1637
+ args = process_function_args(args, meta=meta, environment=self.environment)
1682
1638
  return Function(
1683
1639
  operator=FunctionType.WEEK,
1684
1640
  arguments=args,
@@ -1690,7 +1646,7 @@ class ParseToObjects(Transformer):
1690
1646
 
1691
1647
  @v_args(meta=True)
1692
1648
  def fmonth(self, meta, args):
1693
- args = self.process_function_args(args, meta=meta)
1649
+ args = process_function_args(args, meta=meta, environment=self.environment)
1694
1650
  return Function(
1695
1651
  operator=FunctionType.MONTH,
1696
1652
  arguments=args,
@@ -1702,7 +1658,7 @@ class ParseToObjects(Transformer):
1702
1658
 
1703
1659
  @v_args(meta=True)
1704
1660
  def fquarter(self, meta, args):
1705
- args = self.process_function_args(args, meta=meta)
1661
+ args = process_function_args(args, meta=meta, environment=self.environment)
1706
1662
  return Function(
1707
1663
  operator=FunctionType.QUARTER,
1708
1664
  arguments=args,
@@ -1714,7 +1670,7 @@ class ParseToObjects(Transformer):
1714
1670
 
1715
1671
  @v_args(meta=True)
1716
1672
  def fyear(self, meta, args):
1717
- args = self.process_function_args(args, meta=meta)
1673
+ args = process_function_args(args, meta=meta, environment=self.environment)
1718
1674
  return Function(
1719
1675
  operator=FunctionType.YEAR,
1720
1676
  arguments=args,
@@ -1727,7 +1683,7 @@ class ParseToObjects(Transformer):
1727
1683
  # utility functions
1728
1684
  @v_args(meta=True)
1729
1685
  def fcast(self, meta, args) -> Function:
1730
- args = self.process_function_args(args, meta=meta)
1686
+ args = process_function_args(args, meta=meta, environment=self.environment)
1731
1687
  output_datatype = args[1]
1732
1688
  return Function(
1733
1689
  operator=FunctionType.CAST,
@@ -1748,7 +1704,7 @@ class ParseToObjects(Transformer):
1748
1704
  # math functions
1749
1705
  @v_args(meta=True)
1750
1706
  def fadd(self, meta, args) -> Function:
1751
- args = self.process_function_args(args, meta=meta)
1707
+ args = process_function_args(args, meta=meta, environment=self.environment)
1752
1708
  output_datatype = arg_to_datatype(args[0])
1753
1709
  # TODO: check for valid transforms?
1754
1710
  return Function(
@@ -1762,7 +1718,7 @@ class ParseToObjects(Transformer):
1762
1718
 
1763
1719
  @v_args(meta=True)
1764
1720
  def fsub(self, meta, args) -> Function:
1765
- args = self.process_function_args(args, meta=meta)
1721
+ args = process_function_args(args, meta=meta, environment=self.environment)
1766
1722
  output_datatype = arg_to_datatype(args[0])
1767
1723
  return Function(
1768
1724
  operator=FunctionType.SUBTRACT,
@@ -1775,7 +1731,7 @@ class ParseToObjects(Transformer):
1775
1731
 
1776
1732
  @v_args(meta=True)
1777
1733
  def fmul(self, meta, args) -> Function:
1778
- args = self.process_function_args(args, meta=meta)
1734
+ args = process_function_args(args, meta=meta, environment=self.environment)
1779
1735
  output_datatype = arg_to_datatype(args[0])
1780
1736
  return Function(
1781
1737
  operator=FunctionType.MULTIPLY,
@@ -1789,7 +1745,7 @@ class ParseToObjects(Transformer):
1789
1745
  @v_args(meta=True)
1790
1746
  def fdiv(self, meta: Meta, args):
1791
1747
  output_datatype = arg_to_datatype(args[0])
1792
- args = self.process_function_args(args, meta=meta)
1748
+ args = process_function_args(args, meta=meta, environment=self.environment)
1793
1749
  return Function(
1794
1750
  operator=FunctionType.DIVIDE,
1795
1751
  arguments=args,
@@ -1802,7 +1758,7 @@ class ParseToObjects(Transformer):
1802
1758
  @v_args(meta=True)
1803
1759
  def fmod(self, meta: Meta, args):
1804
1760
  output_datatype = arg_to_datatype(args[0])
1805
- args = self.process_function_args(args, meta=meta)
1761
+ args = process_function_args(args, meta=meta, environment=self.environment)
1806
1762
  return Function(
1807
1763
  operator=FunctionType.MOD,
1808
1764
  arguments=args,
@@ -1817,7 +1773,7 @@ class ParseToObjects(Transformer):
1817
1773
 
1818
1774
  @v_args(meta=True)
1819
1775
  def fround(self, meta, args) -> Function:
1820
- args = self.process_function_args(args, meta=meta)
1776
+ args = process_function_args(args, meta=meta, environment=self.environment)
1821
1777
  output_datatype = arg_to_datatype(args[0])
1822
1778
  return Function(
1823
1779
  operator=FunctionType.ROUND,
@@ -1851,27 +1807,27 @@ class ParseToObjects(Transformer):
1851
1807
 
1852
1808
  @v_args(meta=True)
1853
1809
  def fcase_when(self, meta, args) -> CaseWhen:
1854
- args = self.process_function_args(args, meta=meta)
1810
+ args = process_function_args(args, meta=meta, environment=self.environment)
1855
1811
  return CaseWhen(comparison=args[0], expr=args[1])
1856
1812
 
1857
1813
  @v_args(meta=True)
1858
1814
  def fcase_else(self, meta, args) -> CaseElse:
1859
- args = self.process_function_args(args, meta=meta)
1815
+ args = process_function_args(args, meta=meta, environment=self.environment)
1860
1816
  return CaseElse(expr=args[0])
1861
1817
 
1862
1818
  @v_args(meta=True)
1863
1819
  def fcurrent_date(self, meta, args):
1864
- args = self.process_function_args(args, meta=meta)
1820
+ args = process_function_args(args, meta=meta, environment=self.environment)
1865
1821
  return CurrentDate([])
1866
1822
 
1867
1823
  @v_args(meta=True)
1868
1824
  def fcurrent_datetime(self, meta, args):
1869
- args = self.process_function_args(args, meta=meta)
1825
+ args = process_function_args(args, meta=meta, environment=self.environment)
1870
1826
  return CurrentDatetime([])
1871
1827
 
1872
1828
  @v_args(meta=True)
1873
1829
  def fnot(self, meta, args):
1874
- args = self.process_function_args(args, meta=meta)
1830
+ args = process_function_args(args, meta=meta, environment=self.environment)
1875
1831
  return IsNull(args)
1876
1832
 
1877
1833
 
@@ -90,9 +90,9 @@
90
90
 
91
91
 
92
92
  // rank/lag/lead
93
- WINDOW_TYPE: ("row_number"i|"rank"i|"lag"i|"lead"i | "sum"i) /[\s]+/
93
+ WINDOW_TYPE: ("row_number"i|"rank"i|"lag"i|"lead"i | "sum"i | "avg"i | "max"i | "min"i ) /[\s]+/
94
94
 
95
- window_item: WINDOW_TYPE int_lit? concept_lit window_item_over? window_item_order?
95
+ window_item: WINDOW_TYPE int_lit? expr window_item_over? window_item_order?
96
96
 
97
97
  window_item_over: ("OVER"i over_list)
98
98
 
@@ -296,7 +296,7 @@
296
296
 
297
297
  MODIFIER: "Optional"i | "Partial"i | "Nullable"i
298
298
 
299
- SHORTHAND_MODIFIER: "~"
299
+ SHORTHAND_MODIFIER: "~" | "?"
300
300
 
301
301
  struct_type: "struct"i "<" ((data_type | IDENTIFIER) ",")* (data_type | IDENTIFIER) ","? ">"
302
302