vtlengine 1.0__py3-none-any.whl → 1.0.1__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 vtlengine might be problematic. Click here for more details.
- vtlengine/API/_InternalApi.py +153 -100
- vtlengine/API/__init__.py +109 -67
- vtlengine/AST/ASTConstructor.py +188 -98
- vtlengine/AST/ASTConstructorModules/Expr.py +306 -200
- vtlengine/AST/ASTConstructorModules/ExprComponents.py +172 -102
- vtlengine/AST/ASTConstructorModules/Terminals.py +158 -95
- vtlengine/AST/ASTEncoders.py +1 -1
- vtlengine/AST/ASTTemplate.py +8 -9
- vtlengine/AST/ASTVisitor.py +8 -12
- vtlengine/AST/DAG/__init__.py +43 -35
- vtlengine/AST/DAG/_words.py +4 -4
- vtlengine/AST/Grammar/lexer.py +732 -142
- vtlengine/AST/Grammar/parser.py +2188 -826
- vtlengine/AST/Grammar/tokens.py +128 -128
- vtlengine/AST/VtlVisitor.py +7 -4
- vtlengine/AST/__init__.py +22 -11
- vtlengine/DataTypes/NumericTypesHandling.py +5 -4
- vtlengine/DataTypes/TimeHandling.py +194 -301
- vtlengine/DataTypes/__init__.py +304 -218
- vtlengine/Exceptions/__init__.py +52 -27
- vtlengine/Exceptions/messages.py +134 -62
- vtlengine/Interpreter/__init__.py +781 -487
- vtlengine/Model/__init__.py +165 -121
- vtlengine/Operators/Aggregation.py +156 -95
- vtlengine/Operators/Analytic.py +115 -59
- vtlengine/Operators/Assignment.py +7 -4
- vtlengine/Operators/Boolean.py +27 -32
- vtlengine/Operators/CastOperator.py +177 -131
- vtlengine/Operators/Clause.py +137 -99
- vtlengine/Operators/Comparison.py +148 -117
- vtlengine/Operators/Conditional.py +149 -98
- vtlengine/Operators/General.py +68 -47
- vtlengine/Operators/HROperators.py +91 -72
- vtlengine/Operators/Join.py +217 -118
- vtlengine/Operators/Numeric.py +89 -44
- vtlengine/Operators/RoleSetter.py +16 -15
- vtlengine/Operators/Set.py +61 -36
- vtlengine/Operators/String.py +213 -139
- vtlengine/Operators/Time.py +334 -216
- vtlengine/Operators/Validation.py +117 -76
- vtlengine/Operators/__init__.py +340 -213
- vtlengine/Utils/__init__.py +195 -40
- vtlengine/__init__.py +1 -1
- vtlengine/files/output/__init__.py +15 -6
- vtlengine/files/output/_time_period_representation.py +10 -9
- vtlengine/files/parser/__init__.py +77 -52
- vtlengine/files/parser/_rfc_dialect.py +6 -5
- vtlengine/files/parser/_time_checking.py +46 -37
- vtlengine-1.0.1.dist-info/METADATA +236 -0
- vtlengine-1.0.1.dist-info/RECORD +58 -0
- {vtlengine-1.0.dist-info → vtlengine-1.0.1.dist-info}/WHEEL +1 -1
- vtlengine-1.0.dist-info/METADATA +0 -104
- vtlengine-1.0.dist-info/RECORD +0 -58
- {vtlengine-1.0.dist-info → vtlengine-1.0.1.dist-info}/LICENSE.md +0 -0
|
@@ -3,12 +3,29 @@ from copy import copy
|
|
|
3
3
|
|
|
4
4
|
from antlr4.tree.Tree import TerminalNodeImpl
|
|
5
5
|
|
|
6
|
-
from vtlengine.AST import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
from vtlengine.AST import (
|
|
7
|
+
If,
|
|
8
|
+
BinOp,
|
|
9
|
+
RenameNode,
|
|
10
|
+
UDOCall,
|
|
11
|
+
UnaryOp,
|
|
12
|
+
JoinOp,
|
|
13
|
+
Identifier,
|
|
14
|
+
ParamOp,
|
|
15
|
+
EvalOp,
|
|
16
|
+
ParamConstant,
|
|
17
|
+
MulOp,
|
|
18
|
+
RegularAggregation,
|
|
19
|
+
Assignment,
|
|
20
|
+
Aggregation,
|
|
21
|
+
ID,
|
|
22
|
+
TimeAggregation,
|
|
23
|
+
Constant,
|
|
24
|
+
Validation,
|
|
25
|
+
Analytic,
|
|
26
|
+
Windowing,
|
|
27
|
+
VarID,
|
|
28
|
+
)
|
|
12
29
|
from vtlengine.AST.ASTConstructorModules.ExprComponents import ExprComp
|
|
13
30
|
from vtlengine.AST.ASTConstructorModules.Terminals import Terminals
|
|
14
31
|
from vtlengine.AST.ASTDataExchange import de_ruleset_elements
|
|
@@ -23,27 +40,27 @@ class Expr(VtlVisitor):
|
|
|
23
40
|
"""______________________________________________________________________________________
|
|
24
41
|
|
|
25
42
|
|
|
26
|
-
|
|
43
|
+
Expr Definition.
|
|
27
44
|
|
|
28
|
-
|
|
45
|
+
_______________________________________________________________________________________"""
|
|
29
46
|
|
|
30
47
|
def visitExpr(self, ctx: Parser.ExprContext):
|
|
31
48
|
"""
|
|
32
49
|
expr:
|
|
33
|
-
LPAREN expr RPAREN # parenthesisExpr
|
|
34
|
-
| functions # functionsExpression
|
|
35
|
-
| dataset=expr QLPAREN clause=datasetClause QRPAREN # clauseExpr
|
|
36
|
-
| expr MEMBERSHIP simpleComponentId # membershipExpr
|
|
37
|
-
| op=(PLUS|MINUS|NOT) right=expr # unaryExpr
|
|
38
|
-
| left=expr op=(MUL|DIV) right=expr # arithmeticExpr
|
|
39
|
-
| left=expr op=(PLUS|MINUS|CONCAT) right=expr # arithmeticExprOrConcat
|
|
40
|
-
| left=expr op=comparisonOperand right=expr # comparisonExpr
|
|
41
|
-
| left=expr op=(IN|NOT_IN)(lists|valueDomainID) # inNotInExpr
|
|
42
|
-
| left=expr op=AND right=expr # booleanExpr
|
|
43
|
-
| left=expr op=(OR|XOR) right=expr # booleanExpr
|
|
44
|
-
| IF conditionalExpr=expr THEN thenExpr=expr ELSE elseExpr=expr # ifExpr
|
|
45
|
-
| constant # constantExpr
|
|
46
|
-
| varID # varIdExpr
|
|
50
|
+
LPAREN expr RPAREN # parenthesisExpr # noqa E501
|
|
51
|
+
| functions # functionsExpression # noqa E501
|
|
52
|
+
| dataset=expr QLPAREN clause=datasetClause QRPAREN # clauseExpr # noqa E501
|
|
53
|
+
| expr MEMBERSHIP simpleComponentId # membershipExpr # noqa E501
|
|
54
|
+
| op=(PLUS|MINUS|NOT) right=expr # unaryExpr # noqa E501
|
|
55
|
+
| left=expr op=(MUL|DIV) right=expr # arithmeticExpr # noqa E501
|
|
56
|
+
| left=expr op=(PLUS|MINUS|CONCAT) right=expr # arithmeticExprOrConcat # noqa E501
|
|
57
|
+
| left=expr op=comparisonOperand right=expr # comparisonExpr # noqa E501
|
|
58
|
+
| left=expr op=(IN|NOT_IN)(lists|valueDomainID) # inNotInExpr # noqa E501
|
|
59
|
+
| left=expr op=AND right=expr # booleanExpr # noqa E501
|
|
60
|
+
| left=expr op=(OR|XOR) right=expr # booleanExpr # noqa E501
|
|
61
|
+
| IF conditionalExpr=expr THEN thenExpr=expr ELSE elseExpr=expr # ifExpr # noqa E501
|
|
62
|
+
| constant # constantExpr # noqa E501
|
|
63
|
+
| varID # varIdExpr # noqa E501
|
|
47
64
|
;
|
|
48
65
|
"""
|
|
49
66
|
ctx_list = list(ctx.getChildren())
|
|
@@ -163,15 +180,19 @@ class Expr(VtlVisitor):
|
|
|
163
180
|
def visitMembershipExpr(self, ctx: Parser.MembershipExprContext):
|
|
164
181
|
ctx_list = list(ctx.getChildren())
|
|
165
182
|
c = ctx_list[0]
|
|
166
|
-
membership = [
|
|
167
|
-
|
|
183
|
+
membership = [
|
|
184
|
+
componentID
|
|
185
|
+
for componentID in ctx_list
|
|
186
|
+
if isinstance(componentID, Parser.SimpleComponentIdContext)
|
|
187
|
+
]
|
|
168
188
|
|
|
169
189
|
previous_node = self.visitExpr(c)
|
|
170
190
|
|
|
171
191
|
# It is only possible to put a membership at the end so go the last one.
|
|
172
192
|
if len(membership) != 0:
|
|
173
|
-
previous_node = BinOp(
|
|
174
|
-
|
|
193
|
+
previous_node = BinOp(
|
|
194
|
+
previous_node, "#", Terminals().visitSimpleComponentId(membership[0])
|
|
195
|
+
)
|
|
175
196
|
|
|
176
197
|
return previous_node
|
|
177
198
|
|
|
@@ -254,7 +275,7 @@ class Expr(VtlVisitor):
|
|
|
254
275
|
|
|
255
276
|
"""
|
|
256
277
|
-----------------------------------
|
|
257
|
-
Join Functions
|
|
278
|
+
Join Functions
|
|
258
279
|
-----------------------------------
|
|
259
280
|
"""
|
|
260
281
|
|
|
@@ -265,7 +286,7 @@ class Expr(VtlVisitor):
|
|
|
265
286
|
|
|
266
287
|
op_node = ctx_list[0].getSymbol().text
|
|
267
288
|
|
|
268
|
-
if op_node in [
|
|
289
|
+
if op_node in ["inner_join", "left_join"]:
|
|
269
290
|
clause_node, using_node = self.visitJoinClause(ctx_list[2])
|
|
270
291
|
else:
|
|
271
292
|
clause_node = self.visitJoinClauseWithoutUsing(ctx_list[2])
|
|
@@ -297,7 +318,7 @@ class Expr(VtlVisitor):
|
|
|
297
318
|
return left_node
|
|
298
319
|
|
|
299
320
|
intop_node = ctx_list[1].getSymbol().text
|
|
300
|
-
right_node = Identifier(Terminals().visitAlias(ctx_list[2]),
|
|
321
|
+
right_node = Identifier(Terminals().visitAlias(ctx_list[2]), "DatasetID")
|
|
301
322
|
return BinOp(left_node, intop_node, right_node)
|
|
302
323
|
|
|
303
324
|
def visitJoinClause(self, ctx: Parser.JoinClauseContext):
|
|
@@ -311,8 +332,9 @@ class Expr(VtlVisitor):
|
|
|
311
332
|
using = None
|
|
312
333
|
|
|
313
334
|
items = [item for item in ctx_list if isinstance(item, Parser.JoinClauseItemContext)]
|
|
314
|
-
components = [
|
|
315
|
-
|
|
335
|
+
components = [
|
|
336
|
+
component for component in ctx_list if isinstance(component, Parser.ComponentIDContext)
|
|
337
|
+
]
|
|
316
338
|
|
|
317
339
|
for item in items:
|
|
318
340
|
clause_nodes.append(self.visitJoinClauseItem(item))
|
|
@@ -326,7 +348,7 @@ class Expr(VtlVisitor):
|
|
|
326
348
|
|
|
327
349
|
def visitJoinClauseWithoutUsing(self, ctx: Parser.JoinClauseWithoutUsingContext):
|
|
328
350
|
"""
|
|
329
|
-
joinClause: joinClauseItem (COMMA joinClauseItem)* (USING componentID (COMMA componentID)*)? ;
|
|
351
|
+
joinClause: joinClauseItem (COMMA joinClauseItem)* (USING componentID (COMMA componentID)*)? ; # noqa E501
|
|
330
352
|
"""
|
|
331
353
|
ctx_list = list(ctx.getChildren())
|
|
332
354
|
|
|
@@ -341,7 +363,7 @@ class Expr(VtlVisitor):
|
|
|
341
363
|
|
|
342
364
|
def visitJoinBody(self, ctx: Parser.JoinBodyContext):
|
|
343
365
|
"""
|
|
344
|
-
joinBody: filterClause? (calcClause|joinApplyClause|aggrClause)? (keepOrDropClause)? renameClause?
|
|
366
|
+
joinBody: filterClause? (calcClause|joinApplyClause|aggrClause)? (keepOrDropClause)? renameClause? # noqa E501
|
|
345
367
|
"""
|
|
346
368
|
ctx_list = list(ctx.getChildren())
|
|
347
369
|
|
|
@@ -378,7 +400,7 @@ class Expr(VtlVisitor):
|
|
|
378
400
|
|
|
379
401
|
"""
|
|
380
402
|
-----------------------------------
|
|
381
|
-
Generic Functions
|
|
403
|
+
Generic Functions
|
|
382
404
|
-----------------------------------
|
|
383
405
|
"""
|
|
384
406
|
|
|
@@ -400,46 +422,65 @@ class Expr(VtlVisitor):
|
|
|
400
422
|
c = ctx_list[0]
|
|
401
423
|
|
|
402
424
|
op = Terminals().visitOperatorID(c)
|
|
403
|
-
param_nodes = [
|
|
404
|
-
|
|
425
|
+
param_nodes = [
|
|
426
|
+
self.visitParameter(element)
|
|
427
|
+
for element in ctx_list
|
|
428
|
+
if isinstance(element, Parser.ParameterContext)
|
|
429
|
+
]
|
|
405
430
|
|
|
406
431
|
return UDOCall(op=op, params=param_nodes)
|
|
407
432
|
|
|
408
433
|
def visitEvalAtom(self, ctx: Parser.EvalAtomContext):
|
|
409
434
|
"""
|
|
410
|
-
|
|
435
|
+
| EVAL LPAREN routineName LPAREN (varID|scalarItem)? (COMMA (varID|scalarItem))* RPAREN (LANGUAGE STRING_CONSTANT)? (RETURNS evalDatasetType)? RPAREN # noqa E501 # evalAtom
|
|
411
436
|
"""
|
|
412
437
|
ctx_list = list(ctx.getChildren())
|
|
413
438
|
|
|
414
439
|
routine_name = Terminals().visitRoutineName(ctx_list[2])
|
|
415
440
|
|
|
416
441
|
# Think of a way to maintain the order, for now its not necessary.
|
|
417
|
-
var_ids_nodes = [
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
442
|
+
var_ids_nodes = [
|
|
443
|
+
Terminals().visitVarID(varID)
|
|
444
|
+
for varID in ctx_list
|
|
445
|
+
if isinstance(varID, Parser.VarIDContext)
|
|
446
|
+
]
|
|
447
|
+
constant_nodes = [
|
|
448
|
+
Terminals().visitScalarItem(scalar)
|
|
449
|
+
for scalar in ctx_list
|
|
450
|
+
if isinstance(scalar, Parser.ScalarItemContext)
|
|
451
|
+
]
|
|
421
452
|
children_nodes = var_ids_nodes + constant_nodes
|
|
422
453
|
|
|
423
454
|
# Reference manual says it is mandatory.
|
|
424
|
-
language_name = [
|
|
425
|
-
|
|
426
|
-
|
|
455
|
+
language_name = [
|
|
456
|
+
language
|
|
457
|
+
for language in ctx_list
|
|
458
|
+
if isinstance(language, TerminalNodeImpl)
|
|
459
|
+
and language.getSymbol().type == Parser.STRING_CONSTANT
|
|
460
|
+
]
|
|
427
461
|
if len(language_name) == 0:
|
|
428
462
|
# AST_ASTCONSTRUCTOR.12
|
|
429
|
-
raise SemanticError("1-4-2-1", option=
|
|
463
|
+
raise SemanticError("1-4-2-1", option="language")
|
|
430
464
|
# Reference manual says it is mandatory.
|
|
431
|
-
output_node = [
|
|
432
|
-
|
|
465
|
+
output_node = [
|
|
466
|
+
Terminals().visitEvalDatasetType(output)
|
|
467
|
+
for output in ctx_list
|
|
468
|
+
if isinstance(output, Parser.EvalDatasetTypeContext)
|
|
469
|
+
]
|
|
433
470
|
if len(output_node) == 0:
|
|
434
471
|
# AST_ASTCONSTRUCTOR.13
|
|
435
|
-
raise SemanticError("1-4-2-1", option=
|
|
472
|
+
raise SemanticError("1-4-2-1", option="output")
|
|
436
473
|
|
|
437
|
-
return EvalOp(
|
|
438
|
-
|
|
474
|
+
return EvalOp(
|
|
475
|
+
name=routine_name,
|
|
476
|
+
operands=children_nodes,
|
|
477
|
+
output=output_node[0],
|
|
478
|
+
language=language_name[0].getSymbol().text,
|
|
479
|
+
)
|
|
439
480
|
|
|
440
481
|
def visitCastExprDataset(self, ctx: Parser.CastExprDatasetContext):
|
|
441
482
|
"""
|
|
442
|
-
|
|
483
|
+
| CAST LPAREN expr COMMA (basicScalarType|valueDomainName) (COMMA STRING_CONSTANT)? RPAREN # noqa E501 # castExprDataset
|
|
443
484
|
"""
|
|
444
485
|
ctx_list = list(ctx.getChildren())
|
|
445
486
|
c = ctx_list[0]
|
|
@@ -447,19 +488,28 @@ class Expr(VtlVisitor):
|
|
|
447
488
|
token = c.getSymbol()
|
|
448
489
|
|
|
449
490
|
op = token.text
|
|
450
|
-
expr_node = [
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
491
|
+
expr_node = [
|
|
492
|
+
self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
|
|
493
|
+
]
|
|
494
|
+
basic_scalar_type = [
|
|
495
|
+
Terminals().visitBasicScalarType(type_)
|
|
496
|
+
for type_ in ctx_list
|
|
497
|
+
if isinstance(type_, Parser.BasicScalarTypeContext)
|
|
498
|
+
]
|
|
499
|
+
|
|
500
|
+
[
|
|
501
|
+
Terminals().visitValueDomainName(valueD)
|
|
502
|
+
for valueD in ctx_list
|
|
503
|
+
if isinstance(valueD, Parser.ValueDomainNameContext)
|
|
504
|
+
]
|
|
457
505
|
|
|
458
506
|
if len(ctx_list) > 6:
|
|
459
|
-
param_node = [
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
507
|
+
param_node = [
|
|
508
|
+
ParamConstant("PARAM_CAST", str_.symbol.text.strip('"'))
|
|
509
|
+
for str_ in ctx_list
|
|
510
|
+
if isinstance(str_, TerminalNodeImpl)
|
|
511
|
+
and str_.getSymbol().type == Parser.STRING_CONSTANT
|
|
512
|
+
]
|
|
463
513
|
else:
|
|
464
514
|
param_node = []
|
|
465
515
|
|
|
@@ -479,13 +529,13 @@ class Expr(VtlVisitor):
|
|
|
479
529
|
if isinstance(c, Parser.ExprContext):
|
|
480
530
|
return self.visitExpr(c)
|
|
481
531
|
elif isinstance(c, TerminalNodeImpl):
|
|
482
|
-
return ID(
|
|
532
|
+
return ID("OPTIONAL", c.getSymbol().text)
|
|
483
533
|
else:
|
|
484
534
|
raise NotImplementedError
|
|
485
535
|
|
|
486
536
|
"""
|
|
487
537
|
-----------------------------------
|
|
488
|
-
String Functions
|
|
538
|
+
String Functions
|
|
489
539
|
-----------------------------------
|
|
490
540
|
"""
|
|
491
541
|
|
|
@@ -536,10 +586,14 @@ class Expr(VtlVisitor):
|
|
|
536
586
|
c = ctx_list[0]
|
|
537
587
|
|
|
538
588
|
token = c.getSymbol()
|
|
539
|
-
expressions = [
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
589
|
+
expressions = [
|
|
590
|
+
self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
|
|
591
|
+
]
|
|
592
|
+
params = [
|
|
593
|
+
self.visitOptionalExpr(param)
|
|
594
|
+
for param in ctx_list
|
|
595
|
+
if isinstance(param, Parser.OptionalExprContext)
|
|
596
|
+
]
|
|
543
597
|
|
|
544
598
|
op_node = token.text
|
|
545
599
|
|
|
@@ -553,10 +607,14 @@ class Expr(VtlVisitor):
|
|
|
553
607
|
c = ctx_list[0]
|
|
554
608
|
|
|
555
609
|
token = c.getSymbol()
|
|
556
|
-
expressions = [
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
610
|
+
expressions = [
|
|
611
|
+
self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
|
|
612
|
+
]
|
|
613
|
+
params = [
|
|
614
|
+
self.visitOptionalExpr(param)
|
|
615
|
+
for param in ctx_list
|
|
616
|
+
if isinstance(param, Parser.OptionalExprContext)
|
|
617
|
+
]
|
|
560
618
|
|
|
561
619
|
op_node = token.text
|
|
562
620
|
|
|
@@ -567,7 +625,7 @@ class Expr(VtlVisitor):
|
|
|
567
625
|
|
|
568
626
|
"""
|
|
569
627
|
-----------------------------------
|
|
570
|
-
Numeric Functions
|
|
628
|
+
Numeric Functions
|
|
571
629
|
-----------------------------------
|
|
572
630
|
"""
|
|
573
631
|
|
|
@@ -624,7 +682,7 @@ class Expr(VtlVisitor):
|
|
|
624
682
|
|
|
625
683
|
"""
|
|
626
684
|
-----------------------------------
|
|
627
|
-
Comparison Functions
|
|
685
|
+
Comparison Functions
|
|
628
686
|
-----------------------------------
|
|
629
687
|
"""
|
|
630
688
|
|
|
@@ -678,16 +736,20 @@ class Expr(VtlVisitor):
|
|
|
678
736
|
token = ctx_list[0].getSymbol()
|
|
679
737
|
op = token.text
|
|
680
738
|
|
|
681
|
-
operand_nodes = [
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
739
|
+
operand_nodes = [
|
|
740
|
+
self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
|
|
741
|
+
]
|
|
742
|
+
retain_nodes = [
|
|
743
|
+
Terminals().visitRetainType(retain)
|
|
744
|
+
for retain in ctx_list
|
|
745
|
+
if isinstance(retain, Parser.RetainTypeContext)
|
|
746
|
+
]
|
|
685
747
|
|
|
686
748
|
return MulOp(op=op, children=operand_nodes + retain_nodes)
|
|
687
749
|
|
|
688
750
|
"""
|
|
689
751
|
-----------------------------------
|
|
690
|
-
Time Functions
|
|
752
|
+
Time Functions
|
|
691
753
|
-----------------------------------
|
|
692
754
|
"""
|
|
693
755
|
|
|
@@ -715,8 +777,11 @@ class Expr(VtlVisitor):
|
|
|
715
777
|
c = ctx_list[0]
|
|
716
778
|
|
|
717
779
|
op = c.getSymbol().text
|
|
718
|
-
operand_node = [
|
|
719
|
-
|
|
780
|
+
operand_node = [
|
|
781
|
+
self.visitExpr(operand)
|
|
782
|
+
for operand in ctx_list
|
|
783
|
+
if isinstance(operand, Parser.ExprContext)
|
|
784
|
+
]
|
|
720
785
|
|
|
721
786
|
if len(operand_node) == 0:
|
|
722
787
|
# AST_ASTCONSTRUCTOR.15
|
|
@@ -733,7 +798,7 @@ class Expr(VtlVisitor):
|
|
|
733
798
|
|
|
734
799
|
op = c.getSymbol().text
|
|
735
800
|
left_node = self.visitExpr(ctx_list[2])
|
|
736
|
-
right_node = Constant(
|
|
801
|
+
right_node = Constant("INTEGER_CONSTANT", Terminals().visitSignedInteger(ctx_list[4]))
|
|
737
802
|
|
|
738
803
|
return BinOp(left=left_node, op=op, right=right_node)
|
|
739
804
|
|
|
@@ -748,7 +813,7 @@ class Expr(VtlVisitor):
|
|
|
748
813
|
children_node = [self.visitExpr(ctx_list[2])]
|
|
749
814
|
|
|
750
815
|
if len(ctx_list) > 4:
|
|
751
|
-
param_constant_node = [ParamConstant(
|
|
816
|
+
param_constant_node = [ParamConstant("PARAM_TIMESERIES", ctx_list[4].getSymbol().text)]
|
|
752
817
|
else:
|
|
753
818
|
param_constant_node = []
|
|
754
819
|
|
|
@@ -756,7 +821,7 @@ class Expr(VtlVisitor):
|
|
|
756
821
|
|
|
757
822
|
def visitTimeAggAtom(self, ctx: Parser.TimeAggAtomContext):
|
|
758
823
|
"""
|
|
759
|
-
TIME_AGG LPAREN periodIndTo=STRING_CONSTANT (COMMA periodIndFrom=(STRING_CONSTANT| OPTIONAL ))? (COMMA op=optionalExpr)? (COMMA (FIRST|LAST))? RPAREN # timeAggAtom
|
|
824
|
+
TIME_AGG LPAREN periodIndTo=STRING_CONSTANT (COMMA periodIndFrom=(STRING_CONSTANT| OPTIONAL ))? (COMMA op=optionalExpr)? (COMMA (FIRST|LAST))? RPAREN # timeAggAtom # noqa E501
|
|
760
825
|
"""
|
|
761
826
|
ctx_list = list(ctx.getChildren())
|
|
762
827
|
c = ctx_list[0]
|
|
@@ -768,9 +833,12 @@ class Expr(VtlVisitor):
|
|
|
768
833
|
if ctx.periodIndFrom is not None and ctx.periodIndFrom.type != Parser.OPTIONAL:
|
|
769
834
|
period_from = str(ctx.periodIndFrom.text)[1:-1]
|
|
770
835
|
|
|
771
|
-
conf = [
|
|
772
|
-
|
|
773
|
-
|
|
836
|
+
conf = [
|
|
837
|
+
str_.getSymbol().text
|
|
838
|
+
for str_ in ctx_list
|
|
839
|
+
if isinstance(str_, TerminalNodeImpl)
|
|
840
|
+
and str_.getSymbol().type in [Parser.FIRST, Parser.LAST]
|
|
841
|
+
]
|
|
774
842
|
|
|
775
843
|
if len(conf) == 0:
|
|
776
844
|
conf = None
|
|
@@ -789,8 +857,9 @@ class Expr(VtlVisitor):
|
|
|
789
857
|
if operand_node is None:
|
|
790
858
|
# AST_ASTCONSTRUCTOR.17
|
|
791
859
|
raise Exception("Optional as expression node is not allowed in Time Aggregation")
|
|
792
|
-
return TimeAggregation(
|
|
793
|
-
|
|
860
|
+
return TimeAggregation(
|
|
861
|
+
op=op, operand=operand_node, period_to=period_to, period_from=period_from, conf=conf
|
|
862
|
+
)
|
|
794
863
|
|
|
795
864
|
def visitFlowAtom(self, ctx: Parser.FlowAtomContext):
|
|
796
865
|
ctx_list = list(ctx.getChildren())
|
|
@@ -805,7 +874,7 @@ class Expr(VtlVisitor):
|
|
|
805
874
|
|
|
806
875
|
"""
|
|
807
876
|
-----------------------------------
|
|
808
|
-
Conditional Functions
|
|
877
|
+
Conditional Functions
|
|
809
878
|
-----------------------------------
|
|
810
879
|
"""
|
|
811
880
|
|
|
@@ -828,15 +897,15 @@ class Expr(VtlVisitor):
|
|
|
828
897
|
|
|
829
898
|
"""
|
|
830
899
|
-----------------------------------
|
|
831
|
-
Set Functions
|
|
900
|
+
Set Functions
|
|
832
901
|
-----------------------------------
|
|
833
902
|
"""
|
|
834
903
|
|
|
835
904
|
def visitSetFunctions(self, ctx: Parser.SetFunctionsContext):
|
|
836
905
|
"""
|
|
837
|
-
setExpr: UNION LPAREN left=expr (COMMA expr)+ RPAREN # unionAtom
|
|
838
|
-
| INTERSECT LPAREN left=expr (COMMA expr)+ RPAREN # intersectAtom
|
|
839
|
-
| op=(SETDIFF|SYMDIFF) LPAREN left=expr COMMA right=expr RPAREN # setOrSYmDiffAtom
|
|
906
|
+
setExpr: UNION LPAREN left=expr (COMMA expr)+ RPAREN # unionAtom # noqa E501
|
|
907
|
+
| INTERSECT LPAREN left=expr (COMMA expr)+ RPAREN # intersectAtom # noqa E501
|
|
908
|
+
| op=(SETDIFF|SYMDIFF) LPAREN left=expr COMMA right=expr RPAREN # setOrSYmDiffAtom # noqa E501
|
|
840
909
|
"""
|
|
841
910
|
if isinstance(ctx, Parser.UnionAtomContext):
|
|
842
911
|
return self.visitUnionAtom(ctx)
|
|
@@ -849,41 +918,44 @@ class Expr(VtlVisitor):
|
|
|
849
918
|
|
|
850
919
|
def visitUnionAtom(self, ctx: Parser.UnionAtomContext):
|
|
851
920
|
ctx_list = list(ctx.getChildren())
|
|
852
|
-
exprs_nodes = [
|
|
853
|
-
|
|
921
|
+
exprs_nodes = [
|
|
922
|
+
self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
|
|
923
|
+
]
|
|
854
924
|
|
|
855
925
|
return MulOp(ctx_list[0].getSymbol().text, exprs_nodes)
|
|
856
926
|
|
|
857
927
|
def visitIntersectAtom(self, ctx: Parser.IntersectAtomContext):
|
|
858
928
|
ctx_list = list(ctx.getChildren())
|
|
859
|
-
exprs_nodes = [
|
|
860
|
-
|
|
929
|
+
exprs_nodes = [
|
|
930
|
+
self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
|
|
931
|
+
]
|
|
861
932
|
|
|
862
933
|
return MulOp(op=ctx_list[0].getSymbol().text, children=exprs_nodes)
|
|
863
934
|
|
|
864
935
|
def visitSetOrSYmDiffAtom(self, ctx: Parser.SetOrSYmDiffAtomContext):
|
|
865
936
|
ctx_list = list(ctx.getChildren())
|
|
866
|
-
exprs_nodes = [
|
|
867
|
-
|
|
937
|
+
exprs_nodes = [
|
|
938
|
+
self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
|
|
939
|
+
]
|
|
868
940
|
|
|
869
941
|
return MulOp(op=ctx_list[0].getSymbol().text, children=exprs_nodes)
|
|
870
942
|
|
|
871
943
|
"""
|
|
872
944
|
-----------------------------------
|
|
873
|
-
Hierarchy Functions
|
|
945
|
+
Hierarchy Functions
|
|
874
946
|
-----------------------------------
|
|
875
947
|
"""
|
|
876
948
|
|
|
877
949
|
def visitHierarchyFunctions(self, ctx: Parser.HierarchyFunctionsContext):
|
|
878
950
|
"""
|
|
879
|
-
|
|
951
|
+
HIERARCHY LPAREN op=expr COMMA hrName=IDENTIFIER (conditionClause)? (RULE ruleComponent=componentID)? (validationMode)? (inputModeHierarchy)? outputModeHierarchy? RPAREN # noqa E501
|
|
880
952
|
"""
|
|
881
953
|
ctx_list = list(ctx.getChildren())
|
|
882
954
|
c = ctx_list[0]
|
|
883
955
|
|
|
884
956
|
op = c.getSymbol().text
|
|
885
957
|
dataset_node = self.visitExpr(ctx_list[2])
|
|
886
|
-
rule_name_node = Identifier(value=ctx_list[4].getSymbol().text, kind=
|
|
958
|
+
rule_name_node = Identifier(value=ctx_list[4].getSymbol().text, kind="RuleID")
|
|
887
959
|
|
|
888
960
|
conditions = []
|
|
889
961
|
modes = "non_null"
|
|
@@ -910,9 +982,9 @@ class Expr(VtlVisitor):
|
|
|
910
982
|
raise NotImplementedError("Dataset Priority input mode on HR is not implemented")
|
|
911
983
|
param_constant_node = []
|
|
912
984
|
|
|
913
|
-
param_constant_node.append(ParamConstant(
|
|
914
|
-
param_constant_node.append(ParamConstant(
|
|
915
|
-
param_constant_node.append(ParamConstant(
|
|
985
|
+
param_constant_node.append(ParamConstant("PARAM_MODE", modes))
|
|
986
|
+
param_constant_node.append(ParamConstant("PARAM_INPUT", inputs))
|
|
987
|
+
param_constant_node.append(ParamConstant("PARAM_OUTPUT", retains))
|
|
916
988
|
|
|
917
989
|
if not rule_comp:
|
|
918
990
|
if isinstance(de_ruleset_elements[rule_name_node.value], list):
|
|
@@ -921,16 +993,19 @@ class Expr(VtlVisitor):
|
|
|
921
993
|
rule_element = de_ruleset_elements[rule_name_node.value]
|
|
922
994
|
if rule_element.kind == "DatasetID":
|
|
923
995
|
check_hierarchy_rule = rule_element.value
|
|
924
|
-
rule_comp = Identifier(check_hierarchy_rule,
|
|
996
|
+
rule_comp = Identifier(check_hierarchy_rule, "ComponentID")
|
|
925
997
|
else: # ValuedomainID
|
|
926
998
|
raise SemanticError("1-1-10-4", op=op)
|
|
927
999
|
|
|
928
|
-
return ParamOp(
|
|
929
|
-
|
|
1000
|
+
return ParamOp(
|
|
1001
|
+
op=op,
|
|
1002
|
+
children=[dataset_node, rule_comp, rule_name_node, *conditions],
|
|
1003
|
+
params=param_constant_node,
|
|
1004
|
+
)
|
|
930
1005
|
|
|
931
1006
|
"""
|
|
932
1007
|
-----------------------------------
|
|
933
|
-
Validation Functions
|
|
1008
|
+
Validation Functions
|
|
934
1009
|
-----------------------------------
|
|
935
1010
|
"""
|
|
936
1011
|
|
|
@@ -944,7 +1019,7 @@ class Expr(VtlVisitor):
|
|
|
944
1019
|
|
|
945
1020
|
def visitValidateDPruleset(self, ctx: Parser.ValidateDPrulesetContext):
|
|
946
1021
|
"""
|
|
947
|
-
|
|
1022
|
+
validationDatapoint: CHECK_DATAPOINT '(' expr ',' IDENTIFIER (COMPONENTS componentID (',' componentID)*)? (INVALID|ALL_MEASURES|ALL)? ')' ; # noqa E501
|
|
948
1023
|
"""
|
|
949
1024
|
ctx_list = list(ctx.getChildren())
|
|
950
1025
|
c = ctx_list[0]
|
|
@@ -954,8 +1029,11 @@ class Expr(VtlVisitor):
|
|
|
954
1029
|
operand_node = self.visitExpr(ctx_list[2])
|
|
955
1030
|
rule_name = ctx_list[4].getSymbol().text
|
|
956
1031
|
|
|
957
|
-
components = [
|
|
958
|
-
|
|
1032
|
+
components = [
|
|
1033
|
+
Terminals().visitComponentID(comp)
|
|
1034
|
+
for comp in ctx_list
|
|
1035
|
+
if isinstance(comp, Parser.ComponentIDContext)
|
|
1036
|
+
]
|
|
959
1037
|
aux_components = []
|
|
960
1038
|
for x in components:
|
|
961
1039
|
if isinstance(x, BinOp):
|
|
@@ -966,18 +1044,17 @@ class Expr(VtlVisitor):
|
|
|
966
1044
|
components = aux_components
|
|
967
1045
|
|
|
968
1046
|
# Default value for output is invalid.
|
|
969
|
-
output =
|
|
1047
|
+
output = "invalid"
|
|
970
1048
|
|
|
971
1049
|
if isinstance(ctx_list[-2], Parser.ValidationOutputContext):
|
|
972
1050
|
output = Terminals().visitValidationOutput(ctx_list[-2])
|
|
973
1051
|
|
|
974
|
-
return ParamOp(op=op, children=[operand_node, rule_name, *components],
|
|
975
|
-
params=[output])
|
|
1052
|
+
return ParamOp(op=op, children=[operand_node, rule_name, *components], params=[output])
|
|
976
1053
|
|
|
977
1054
|
# TODO Not fully implemented only basic usage available.
|
|
978
1055
|
def visitValidateHRruleset(self, ctx: Parser.ValidateHRrulesetContext):
|
|
979
1056
|
"""
|
|
980
|
-
|
|
1057
|
+
CHECK_HIERARCHY LPAREN op=expr COMMA hrName=IDENTIFIER conditionClause? (RULE componentID)? validationMode? inputMode? validationOutput? RPAREN # noqa E501 # validateHRruleset
|
|
981
1058
|
"""
|
|
982
1059
|
|
|
983
1060
|
ctx_list = list(ctx.getChildren())
|
|
@@ -986,13 +1063,13 @@ class Expr(VtlVisitor):
|
|
|
986
1063
|
op = c.getSymbol().text
|
|
987
1064
|
|
|
988
1065
|
dataset_node = self.visitExpr(ctx_list[2])
|
|
989
|
-
rule_name_node = Identifier(value=ctx_list[4].getSymbol().text, kind=
|
|
1066
|
+
rule_name_node = Identifier(value=ctx_list[4].getSymbol().text, kind="RuleID")
|
|
990
1067
|
|
|
991
1068
|
conditions = []
|
|
992
1069
|
# Default values
|
|
993
|
-
modes =
|
|
994
|
-
inputs =
|
|
995
|
-
retains =
|
|
1070
|
+
modes = "non_null"
|
|
1071
|
+
inputs = "dataset"
|
|
1072
|
+
retains = "invalid"
|
|
996
1073
|
rule_comp = None
|
|
997
1074
|
for c in ctx_list:
|
|
998
1075
|
if isinstance(c, Parser.ConditionClauseContext):
|
|
@@ -1015,9 +1092,9 @@ class Expr(VtlVisitor):
|
|
|
1015
1092
|
if inputs == DATASET_PRIORITY:
|
|
1016
1093
|
raise NotImplementedError("Dataset Priority input mode on HR is not implemented")
|
|
1017
1094
|
|
|
1018
|
-
param_constant_node.append(ParamConstant(
|
|
1019
|
-
param_constant_node.append(ParamConstant(
|
|
1020
|
-
param_constant_node.append(ParamConstant(
|
|
1095
|
+
param_constant_node.append(ParamConstant("PARAM_MODE", modes))
|
|
1096
|
+
param_constant_node.append(ParamConstant("PARAM_INPUT", inputs))
|
|
1097
|
+
param_constant_node.append(ParamConstant("PARAM_OUTPUT", retains))
|
|
1021
1098
|
|
|
1022
1099
|
if not rule_comp:
|
|
1023
1100
|
if isinstance(de_ruleset_elements[rule_name_node.value], list):
|
|
@@ -1027,16 +1104,19 @@ class Expr(VtlVisitor):
|
|
|
1027
1104
|
|
|
1028
1105
|
if rule_element.kind == "DatasetID":
|
|
1029
1106
|
check_hierarchy_rule = rule_element.value
|
|
1030
|
-
rule_comp = Identifier(check_hierarchy_rule,
|
|
1107
|
+
rule_comp = Identifier(check_hierarchy_rule, "ComponentID")
|
|
1031
1108
|
else: # ValuedomainID
|
|
1032
1109
|
raise SemanticError("1-1-10-4", op=op)
|
|
1033
1110
|
|
|
1034
|
-
return ParamOp(
|
|
1035
|
-
|
|
1111
|
+
return ParamOp(
|
|
1112
|
+
op=op,
|
|
1113
|
+
children=[dataset_node, rule_comp, rule_name_node, *conditions],
|
|
1114
|
+
params=param_constant_node,
|
|
1115
|
+
)
|
|
1036
1116
|
|
|
1037
1117
|
def visitValidationSimple(self, ctx: Parser.ValidationSimpleContext):
|
|
1038
1118
|
"""
|
|
1039
|
-
|
|
1119
|
+
| CHECK LPAREN op=expr (codeErr=erCode)? (levelCode=erLevel)? imbalanceExpr? output=(INVALID|ALL)? RPAREN # noqa E501 # validationSimple
|
|
1040
1120
|
"""
|
|
1041
1121
|
ctx_list = list(ctx.getChildren())
|
|
1042
1122
|
c = ctx_list[0]
|
|
@@ -1060,13 +1140,16 @@ class Expr(VtlVisitor):
|
|
|
1060
1140
|
if invalid is None:
|
|
1061
1141
|
invalid_value = False
|
|
1062
1142
|
else:
|
|
1063
|
-
invalid_value = True if invalid.getSymbol().text ==
|
|
1143
|
+
invalid_value = True if invalid.getSymbol().text == "invalid" else False
|
|
1064
1144
|
|
|
1065
|
-
return Validation(
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1145
|
+
return Validation(
|
|
1146
|
+
op=token.text,
|
|
1147
|
+
validation=validation_node,
|
|
1148
|
+
error_code=error_code,
|
|
1149
|
+
error_level=error_level,
|
|
1150
|
+
imbalance=inbalance_node,
|
|
1151
|
+
invalid=invalid_value,
|
|
1152
|
+
)
|
|
1070
1153
|
|
|
1071
1154
|
def visitImbalanceExpr(self, ctx: Parser.ImbalanceExprContext):
|
|
1072
1155
|
ctx_list = list(ctx.getChildren())
|
|
@@ -1074,7 +1157,7 @@ class Expr(VtlVisitor):
|
|
|
1074
1157
|
|
|
1075
1158
|
"""
|
|
1076
1159
|
-----------------------------------
|
|
1077
|
-
Aggregate Functions
|
|
1160
|
+
Aggregate Functions
|
|
1078
1161
|
-----------------------------------
|
|
1079
1162
|
"""
|
|
1080
1163
|
|
|
@@ -1101,7 +1184,7 @@ class Expr(VtlVisitor):
|
|
|
1101
1184
|
|
|
1102
1185
|
def visitAggrDataset(self, ctx: Parser.AggrDatasetContext):
|
|
1103
1186
|
ctx_list = list(ctx.getChildren())
|
|
1104
|
-
c = ctx_list[0]
|
|
1187
|
+
# c = ctx_list[0]
|
|
1105
1188
|
|
|
1106
1189
|
grouping_op = None
|
|
1107
1190
|
group_node = None
|
|
@@ -1117,19 +1200,24 @@ class Expr(VtlVisitor):
|
|
|
1117
1200
|
grouping_op, group_node = self.visitGroupingClause(groups[0])
|
|
1118
1201
|
if len(haves) != 0:
|
|
1119
1202
|
have_node, expr = self.visitHavingClause(haves[0])
|
|
1120
|
-
setattr(have_node,
|
|
1203
|
+
setattr(have_node, "expr", expr)
|
|
1121
1204
|
|
|
1122
|
-
return Aggregation(
|
|
1123
|
-
|
|
1205
|
+
return Aggregation(
|
|
1206
|
+
op=op_node,
|
|
1207
|
+
operand=operand,
|
|
1208
|
+
grouping_op=grouping_op,
|
|
1209
|
+
grouping=group_node,
|
|
1210
|
+
having_clause=have_node,
|
|
1211
|
+
)
|
|
1124
1212
|
|
|
1125
1213
|
"""
|
|
1126
1214
|
-----------------------------------
|
|
1127
|
-
Analytic Functions
|
|
1215
|
+
Analytic Functions
|
|
1128
1216
|
-----------------------------------
|
|
1129
1217
|
"""
|
|
1130
1218
|
|
|
1131
1219
|
def visitAnalyticFunctions(self, ctx: Parser.AnalyticFunctionsContext):
|
|
1132
|
-
ctx_list = list(ctx.getChildren())
|
|
1220
|
+
# ctx_list = list(ctx.getChildren())
|
|
1133
1221
|
|
|
1134
1222
|
if isinstance(ctx, Parser.AnSimpleFunctionContext):
|
|
1135
1223
|
return self.visitAnSimpleFunction(ctx)
|
|
@@ -1165,15 +1253,12 @@ class Expr(VtlVisitor):
|
|
|
1165
1253
|
|
|
1166
1254
|
if window is None:
|
|
1167
1255
|
window = Windowing(
|
|
1168
|
-
type_=
|
|
1169
|
-
start=-1,
|
|
1170
|
-
stop=0,
|
|
1171
|
-
start_mode='preceding',
|
|
1172
|
-
stop_mode='current'
|
|
1256
|
+
type_="data", start=-1, stop=0, start_mode="preceding", stop_mode="current"
|
|
1173
1257
|
)
|
|
1174
1258
|
|
|
1175
|
-
return Analytic(
|
|
1176
|
-
|
|
1259
|
+
return Analytic(
|
|
1260
|
+
op=op_node, operand=operand, partition_by=partition_by, order_by=order_by, window=window
|
|
1261
|
+
)
|
|
1177
1262
|
|
|
1178
1263
|
def visitLagOrLeadAn(self, ctx: Parser.LagOrLeadAnContext):
|
|
1179
1264
|
ctx_list = list(ctx.getChildren())
|
|
@@ -1192,8 +1277,9 @@ class Expr(VtlVisitor):
|
|
|
1192
1277
|
elif isinstance(c, Parser.OrderByClauseContext):
|
|
1193
1278
|
order_by = Terminals().visitOrderByClause(c)
|
|
1194
1279
|
continue
|
|
1195
|
-
elif isinstance(c, Parser.SignedIntegerContext) or isinstance(
|
|
1196
|
-
|
|
1280
|
+
elif isinstance(c, Parser.SignedIntegerContext) or isinstance(
|
|
1281
|
+
c, Parser.ScalarItemContext
|
|
1282
|
+
):
|
|
1197
1283
|
if params is None:
|
|
1198
1284
|
params = []
|
|
1199
1285
|
if isinstance(c, Parser.SignedIntegerContext):
|
|
@@ -1206,13 +1292,14 @@ class Expr(VtlVisitor):
|
|
|
1206
1292
|
# AST_ASTCONSTRUCTOR.16
|
|
1207
1293
|
raise Exception(f"{op_node} requires an offset parameter.")
|
|
1208
1294
|
|
|
1209
|
-
return Analytic(
|
|
1210
|
-
|
|
1295
|
+
return Analytic(
|
|
1296
|
+
op=op_node, operand=operand, partition_by=partition_by, order_by=order_by, params=params
|
|
1297
|
+
)
|
|
1211
1298
|
|
|
1212
1299
|
def visitRatioToReportAn(self, ctx: Parser.RatioToReportAnContext):
|
|
1213
1300
|
ctx_list = list(ctx.getChildren())
|
|
1214
1301
|
|
|
1215
|
-
params = None
|
|
1302
|
+
# params = None
|
|
1216
1303
|
order_by = None
|
|
1217
1304
|
|
|
1218
1305
|
op_node = ctx_list[0].getSymbol().text
|
|
@@ -1276,7 +1363,7 @@ class Expr(VtlVisitor):
|
|
|
1276
1363
|
|
|
1277
1364
|
"""
|
|
1278
1365
|
-----------------------------------
|
|
1279
|
-
Rename Clause
|
|
1366
|
+
Rename Clause
|
|
1280
1367
|
-----------------------------------
|
|
1281
1368
|
"""
|
|
1282
1369
|
|
|
@@ -1286,8 +1373,11 @@ class Expr(VtlVisitor):
|
|
|
1286
1373
|
"""
|
|
1287
1374
|
ctx_list = list(ctx.getChildren())
|
|
1288
1375
|
|
|
1289
|
-
renames = [
|
|
1290
|
-
|
|
1376
|
+
renames = [
|
|
1377
|
+
ctx_child
|
|
1378
|
+
for ctx_child in ctx_list
|
|
1379
|
+
if isinstance(ctx_child, Parser.RenameClauseItemContext)
|
|
1380
|
+
]
|
|
1291
1381
|
rename_nodes = []
|
|
1292
1382
|
|
|
1293
1383
|
for ctx_rename in renames:
|
|
@@ -1297,13 +1387,13 @@ class Expr(VtlVisitor):
|
|
|
1297
1387
|
|
|
1298
1388
|
def visitRenameClauseItem(self, ctx: Parser.RenameClauseItemContext):
|
|
1299
1389
|
"""
|
|
1300
|
-
|
|
1390
|
+
renameClauseItem: fromName=componentID TO toName=componentID;
|
|
1301
1391
|
"""
|
|
1302
1392
|
ctx_list = list(ctx.getChildren())
|
|
1303
1393
|
|
|
1304
1394
|
left_node = Terminals().visitComponentID(ctx_list[0])
|
|
1305
1395
|
if isinstance(left_node, BinOp):
|
|
1306
|
-
left_node = f
|
|
1396
|
+
left_node = f"{left_node.left.value}{left_node.op}{left_node.right.value}"
|
|
1307
1397
|
else:
|
|
1308
1398
|
left_node = left_node.value
|
|
1309
1399
|
|
|
@@ -1313,7 +1403,7 @@ class Expr(VtlVisitor):
|
|
|
1313
1403
|
|
|
1314
1404
|
"""
|
|
1315
1405
|
-----------------------------------
|
|
1316
|
-
Aggregate Clause
|
|
1406
|
+
Aggregate Clause
|
|
1317
1407
|
-----------------------------------
|
|
1318
1408
|
"""
|
|
1319
1409
|
|
|
@@ -1325,8 +1415,11 @@ class Expr(VtlVisitor):
|
|
|
1325
1415
|
|
|
1326
1416
|
aggregates_nodes = []
|
|
1327
1417
|
|
|
1328
|
-
aggregates = [
|
|
1329
|
-
|
|
1418
|
+
aggregates = [
|
|
1419
|
+
aggregate
|
|
1420
|
+
for aggregate in ctx_list
|
|
1421
|
+
if isinstance(aggregate, Parser.AggrFunctionClauseContext)
|
|
1422
|
+
]
|
|
1330
1423
|
|
|
1331
1424
|
for agg in aggregates:
|
|
1332
1425
|
aggregates_nodes.append(self.visitAggrFunctionClause(agg))
|
|
@@ -1348,11 +1441,11 @@ class Expr(VtlVisitor):
|
|
|
1348
1441
|
role = Role.MEASURE
|
|
1349
1442
|
|
|
1350
1443
|
left_node = Terminals().visitSimpleComponentId(ctx_list[base_index])
|
|
1351
|
-
op_node =
|
|
1444
|
+
op_node = ":="
|
|
1352
1445
|
right_node = ExprComp().visitAggregateFunctionsComponents(ctx_list[base_index + 2])
|
|
1353
1446
|
# Encoding the role information inside the Assignment for easiness and simplicity.
|
|
1354
1447
|
# Cannot find another way with less lines of code
|
|
1355
|
-
setattr(left_node,
|
|
1448
|
+
setattr(left_node, "role", role)
|
|
1356
1449
|
|
|
1357
1450
|
return Assignment(left_node, op_node, right_node)
|
|
1358
1451
|
|
|
@@ -1379,21 +1472,25 @@ class Expr(VtlVisitor):
|
|
|
1379
1472
|
grouping_op, group_node = self.visitGroupingClause(groups[0])
|
|
1380
1473
|
if len(haves) > 0:
|
|
1381
1474
|
have_node, expr = self.visitHavingClause(haves[0])
|
|
1382
|
-
setattr(have_node,
|
|
1475
|
+
setattr(have_node, "expr", expr)
|
|
1383
1476
|
for element in aggregate_nodes:
|
|
1384
|
-
element.right = Aggregation(
|
|
1385
|
-
|
|
1386
|
-
|
|
1477
|
+
element.right = Aggregation(
|
|
1478
|
+
op=element.right.op,
|
|
1479
|
+
operand=element.right.operand,
|
|
1480
|
+
grouping_op=grouping_op,
|
|
1481
|
+
grouping=group_node,
|
|
1482
|
+
having_clause=have_node,
|
|
1483
|
+
)
|
|
1387
1484
|
children.append(copy(element))
|
|
1388
1485
|
|
|
1389
1486
|
return RegularAggregation(op=op_node, children=children)
|
|
1390
1487
|
|
|
1391
1488
|
def visitGroupingClause(self, ctx: Parser.GroupingClauseContext):
|
|
1392
1489
|
"""
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1490
|
+
groupingClause:
|
|
1491
|
+
GROUP op=(BY | EXCEPT) componentID (COMMA componentID)* # groupByOrExcept
|
|
1492
|
+
| GROUP ALL exprComponent # groupAll
|
|
1493
|
+
;
|
|
1397
1494
|
"""
|
|
1398
1495
|
if isinstance(ctx, Parser.GroupByOrExceptContext):
|
|
1399
1496
|
return self.visitGroupByOrExcept(ctx)
|
|
@@ -1410,24 +1507,24 @@ class Expr(VtlVisitor):
|
|
|
1410
1507
|
op_node = ctx_list[0].getSymbol().text
|
|
1411
1508
|
|
|
1412
1509
|
text = ctx_list[1].start.source[1].strdata
|
|
1413
|
-
expr = re.split(
|
|
1414
|
-
expr =
|
|
1510
|
+
expr = re.split("having", text)[1]
|
|
1511
|
+
expr = "having " + expr[:-2].strip()
|
|
1415
1512
|
|
|
1416
|
-
if
|
|
1417
|
-
index = expr.index(
|
|
1513
|
+
if "]" in expr:
|
|
1514
|
+
index = expr.index("]")
|
|
1418
1515
|
expr = expr[:index]
|
|
1419
|
-
if
|
|
1420
|
-
index = expr.index(
|
|
1516
|
+
if "end" in expr:
|
|
1517
|
+
index = expr.index("end")
|
|
1421
1518
|
expr = expr[:index]
|
|
1422
|
-
if expr.count(
|
|
1423
|
-
index = expr.rindex(
|
|
1519
|
+
if expr.count(")") > expr.count("("):
|
|
1520
|
+
index = expr.rindex(")")
|
|
1424
1521
|
expr = expr[:index]
|
|
1425
1522
|
|
|
1426
|
-
if
|
|
1427
|
-
expr = expr.replace(
|
|
1428
|
-
expr = expr.replace(
|
|
1429
|
-
if
|
|
1430
|
-
expr = expr.replace(
|
|
1523
|
+
if "{" in expr or "}" in expr:
|
|
1524
|
+
expr = expr.replace("{", "(")
|
|
1525
|
+
expr = expr.replace("}", ")")
|
|
1526
|
+
if "not_in" in expr:
|
|
1527
|
+
expr = expr.replace("not_in", "not in")
|
|
1431
1528
|
if '"' in expr:
|
|
1432
1529
|
expr = expr.replace('"', "'")
|
|
1433
1530
|
|
|
@@ -1448,10 +1545,13 @@ class Expr(VtlVisitor):
|
|
|
1448
1545
|
token_left = ctx_list[0].getSymbol().text
|
|
1449
1546
|
token_right = ctx_list[1].getSymbol().text
|
|
1450
1547
|
|
|
1451
|
-
op_node = token_left +
|
|
1548
|
+
op_node = token_left + " " + token_right
|
|
1452
1549
|
|
|
1453
|
-
children_nodes = [
|
|
1454
|
-
|
|
1550
|
+
children_nodes = [
|
|
1551
|
+
Terminals().visitComponentID(identifier)
|
|
1552
|
+
for identifier in ctx_list
|
|
1553
|
+
if isinstance(identifier, Parser.ComponentIDContext)
|
|
1554
|
+
]
|
|
1455
1555
|
|
|
1456
1556
|
return op_node, children_nodes
|
|
1457
1557
|
|
|
@@ -1461,7 +1561,7 @@ class Expr(VtlVisitor):
|
|
|
1461
1561
|
token_left = ctx_list[0].getSymbol().text
|
|
1462
1562
|
token_right = ctx_list[1].getSymbol().text
|
|
1463
1563
|
|
|
1464
|
-
op_node = token_left +
|
|
1564
|
+
op_node = token_left + " " + token_right
|
|
1465
1565
|
|
|
1466
1566
|
children_nodes = [ExprComp().visitExprComponent(ctx_list[2])]
|
|
1467
1567
|
|
|
@@ -1469,7 +1569,7 @@ class Expr(VtlVisitor):
|
|
|
1469
1569
|
|
|
1470
1570
|
"""
|
|
1471
1571
|
-----------------------------------
|
|
1472
|
-
Filter Clause
|
|
1572
|
+
Filter Clause
|
|
1473
1573
|
-----------------------------------
|
|
1474
1574
|
"""
|
|
1475
1575
|
|
|
@@ -1489,7 +1589,7 @@ class Expr(VtlVisitor):
|
|
|
1489
1589
|
|
|
1490
1590
|
"""
|
|
1491
1591
|
-----------------------------------
|
|
1492
|
-
Calc Clause
|
|
1592
|
+
Calc Clause
|
|
1493
1593
|
-----------------------------------
|
|
1494
1594
|
"""
|
|
1495
1595
|
|
|
@@ -1500,8 +1600,11 @@ class Expr(VtlVisitor):
|
|
|
1500
1600
|
ctx_list = list(ctx.getChildren())
|
|
1501
1601
|
c = ctx_list[0]
|
|
1502
1602
|
|
|
1503
|
-
calcClauseItems = [
|
|
1504
|
-
|
|
1603
|
+
calcClauseItems = [
|
|
1604
|
+
calcClauseItem
|
|
1605
|
+
for calcClauseItem in ctx_list
|
|
1606
|
+
if isinstance(calcClauseItem, Parser.CalcClauseItemContext)
|
|
1607
|
+
]
|
|
1505
1608
|
calcClauseItems_nodes = []
|
|
1506
1609
|
|
|
1507
1610
|
op_node = c.getSymbol().text
|
|
@@ -1522,7 +1625,7 @@ class Expr(VtlVisitor):
|
|
|
1522
1625
|
role = Terminals().visitComponentRole(c)
|
|
1523
1626
|
|
|
1524
1627
|
left_node = Terminals().visitComponentID(ctx_list[1])
|
|
1525
|
-
op_node =
|
|
1628
|
+
op_node = ":="
|
|
1526
1629
|
right_node = ExprComp().visitExprComponent(ctx_list[3])
|
|
1527
1630
|
operand_node = Assignment(left_node, op_node, right_node)
|
|
1528
1631
|
if role is None:
|
|
@@ -1530,7 +1633,7 @@ class Expr(VtlVisitor):
|
|
|
1530
1633
|
return UnaryOp(role.value.lower(), operand_node)
|
|
1531
1634
|
else:
|
|
1532
1635
|
left_node = Terminals().visitSimpleComponentId(c)
|
|
1533
|
-
op_node =
|
|
1636
|
+
op_node = ":="
|
|
1534
1637
|
right_node = ExprComp().visitExprComponent(ctx_list[2])
|
|
1535
1638
|
|
|
1536
1639
|
operand_node = Assignment(left_node, op_node, right_node)
|
|
@@ -1555,7 +1658,7 @@ class Expr(VtlVisitor):
|
|
|
1555
1658
|
|
|
1556
1659
|
"""
|
|
1557
1660
|
-----------------------------------
|
|
1558
|
-
Pivot/Unpivot Clause
|
|
1661
|
+
Pivot/Unpivot Clause
|
|
1559
1662
|
-----------------------------------
|
|
1560
1663
|
"""
|
|
1561
1664
|
|
|
@@ -1576,19 +1679,22 @@ class Expr(VtlVisitor):
|
|
|
1576
1679
|
|
|
1577
1680
|
"""
|
|
1578
1681
|
-----------------------------------
|
|
1579
|
-
Subspace Clause
|
|
1682
|
+
Subspace Clause
|
|
1580
1683
|
-----------------------------------
|
|
1581
1684
|
"""
|
|
1582
1685
|
|
|
1583
1686
|
def visitSubspaceClause(self, ctx: Parser.SubspaceClauseContext):
|
|
1584
1687
|
"""
|
|
1585
|
-
subspaceClause: SUBSPACE subspaceClauseItem (COMMA subspaceClauseItem)*;
|
|
1688
|
+
subspaceClause: SUBSPACE subspaceClauseItem (COMMA subspaceClauseItem)*;"""
|
|
1586
1689
|
ctx_list = list(ctx.getChildren())
|
|
1587
1690
|
c = ctx_list[0]
|
|
1588
1691
|
|
|
1589
1692
|
subspace_nodes = []
|
|
1590
|
-
subspaces = [
|
|
1591
|
-
|
|
1693
|
+
subspaces = [
|
|
1694
|
+
subspace
|
|
1695
|
+
for subspace in ctx_list
|
|
1696
|
+
if isinstance(subspace, Parser.SubspaceClauseItemContext)
|
|
1697
|
+
]
|
|
1592
1698
|
|
|
1593
1699
|
for subspace in subspaces:
|
|
1594
1700
|
subspace_nodes.append(self.visitSubspaceClauseItem(subspace))
|
|
@@ -1618,4 +1724,4 @@ class Expr(VtlVisitor):
|
|
|
1618
1724
|
elif isinstance(c, TerminalNodeImpl):
|
|
1619
1725
|
token = c.getSymbol()
|
|
1620
1726
|
opt = token.text
|
|
1621
|
-
return ID(
|
|
1727
|
+
return ID("OPTIONAL", opt)
|