Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
4eebc10
Fixed bolean casting to str
mla2001 Mar 18, 2026
0d10e92
Fixed trunc to 0 not setting the type to integer
mla2001 Mar 18, 2026
5b26080
Fixed duckdb RM value domains loading
mla2001 Mar 18, 2026
c08468d
Fixed linting errors
mla2001 Mar 18, 2026
39d6d54
Minor fix
mla2001 Mar 18, 2026
0942fb0
Deactivated some measure form scalars tests until nullability over sc…
mla2001 Mar 19, 2026
1ede4e3
tests are now skipped instead of deactivated
mla2001 Mar 19, 2026
3b446b2
Fixed some time operators null handling
mla2001 Mar 19, 2026
6264479
Minor fix
mla2001 Mar 19, 2026
79c1bd9
Fixed membership column alignment
mla2001 Mar 19, 2026
8e11441
Minor fix
mla2001 Mar 19, 2026
e46b296
Fixed attributes handler
mla2001 Mar 19, 2026
19e49b2
Fixed group by/except cols alignment
mla2001 Mar 19, 2026
50b3d4a
Fixed empty count transpiling
mla2001 Mar 19, 2026
93f6408
Fixed linting errors
mla2001 Mar 19, 2026
d9638d1
Fixed some duckdb transpiler references
mla2001 Mar 19, 2026
e50202f
Added duration mapping
mla2001 Mar 19, 2026
fa5317e
Merge remote-tracking branch 'origin/main' into cr-607
mla2001 Mar 20, 2026
71f0016
Ensure presence of the time identifier in time_agg ops
mla2001 Mar 20, 2026
fe465b0
Minor fix
mla2001 Mar 20, 2026
f889649
Minor fix
mla2001 Mar 20, 2026
23568c1
Fixed linting errors
mla2001 Mar 20, 2026
9ae6978
Skipped case sesitive test
mla2001 Mar 20, 2026
fe7c2dd
Fixed int_var like columns missing on nested aggregations
mla2001 Mar 20, 2026
3d0c762
Merge remote-tracking branch 'origin/duckdb/main' into cr-607
mla2001 Mar 20, 2026
e05a089
Fixed duckdb RM tests
mla2001 Mar 20, 2026
34ddd1b
Merge remote-tracking branch 'origin/duckdb/main' into cr-607
mla2001 Mar 20, 2026
ad5280a
Fixed DataLoad tests
mla2001 Mar 23, 2026
b48561d
Merge remote-tracking branch 'origin/duckdb/main' into cr-607
mla2001 Mar 23, 2026
cd98e42
Fixed scalars saving when output_folder is provided
mla2001 Mar 23, 2026
1c8bd13
Fixed some duration ops
mla2001 Mar 23, 2026
14c8077
Fixed Date format with hh:mm:ss handling
mla2001 Mar 23, 2026
f5191f8
Fixed dateAdd not returning Date comps
mla2001 Mar 23, 2026
9ccd003
Fixed outdated ruff linting errors
mla2001 Mar 23, 2026
243d143
Fixed random tests
mla2001 Mar 23, 2026
46adef2
Fixed Decimals config
mla2001 Mar 24, 2026
3743c89
Fixed duckdb transpiler date related tests
mla2001 Mar 24, 2026
5176f38
Updated decimal config
mla2001 Mar 24, 2026
be81af6
Minor fix
mla2001 Mar 24, 2026
48ea3c5
Fixed dataload data_type key error
mla2001 Mar 24, 2026
79a63a6
Updated invalid decimal config error message
mla2001 Mar 24, 2026
921db34
Fixed invalid env var Exception
mla2001 Mar 24, 2026
1c96bf8
Minor fix
mla2001 Mar 24, 2026
ae66b66
Fixed duration comparation
mla2001 Mar 24, 2026
abe66c7
Updated date handling: DATE SQL type if all inputs are date like form…
mla2001 Mar 25, 2026
87c8eb2
Fixed some dataload tests
mla2001 Mar 26, 2026
6b4c84d
Fixed linting errors
mla2001 Mar 26, 2026
5a032da
Fixed some type handling errors
mla2001 Mar 26, 2026
5eb761c
Enhance error handling and type validation in DuckDB transpiler
mla2001 Mar 27, 2026
5123ea0
Fixed most semantic tests
mla2001 Mar 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 3 additions & 9 deletions src/vtlengine/API/_InternalApi.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,9 @@ def _extract_data_type(component: Dict[str, Any]) -> Tuple[str, Any]:
Raises:
InputValidationException: If the data type key or value is invalid
"""
if "type" in component:
key = "type"
value = component["type"]
else:
key = "data_type"
value = component["data_type"]

check_key(key, _SCALAR_TYPE_KEYS, value)
return key, SCALAR_TYPES[value]
key = "type" if "type" in component else "data_type"
check_key(key, _SCALAR_TYPE_KEYS, component[key])
return key, SCALAR_TYPES[component[key]]


def _load_dataset_from_structure(
Expand Down
97 changes: 78 additions & 19 deletions src/vtlengine/AST/ASTConstructorModules/Expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ def visitExpr(self, ctx: Parser.ExprContext):
condition = self.visitExpr(ctx_list[i + 1])
thenOp = self.visitExpr(ctx_list[i + 3])
case_obj = CaseObj(
condition=condition, thenOp=thenOp, **extract_token_info(ctx_list[i + 1])
condition=condition,
thenOp=thenOp,
**extract_token_info(ctx_list[i + 1]),
)
cases.append(case_obj)

Expand Down Expand Up @@ -572,7 +574,10 @@ def visitCastExprDataset(self, ctx: Parser.CastExprDatasetContext):
children_nodes = expr_node + basic_scalar_type

return ParamOp(
op=op, children=children_nodes, params=param_node, **extract_token_info(ctx)
op=op,
children=children_nodes,
params=param_node,
**extract_token_info(ctx),
)

else:
Expand All @@ -587,7 +592,9 @@ def visitParameter(self, ctx: Parser.ParameterContext):
return self.visitExpr(c)
elif isinstance(c, TerminalNodeImpl):
return ID(
type_="OPTIONAL", value=c.getSymbol().text, **extract_token_info(c.getSymbol())
type_="OPTIONAL",
value=c.getSymbol().text,
**extract_token_info(c.getSymbol()),
)
else:
raise NotImplementedError
Expand Down Expand Up @@ -639,7 +646,10 @@ def visitSubstrAtom(self, ctx: Parser.SubstrAtomContext):
params_nodes.append(self.visitOptionalExpr(param))

return ParamOp(
op=op_node, children=children_nodes, params=params_nodes, **extract_token_info(ctx)
op=op_node,
children=children_nodes,
params=params_nodes,
**extract_token_info(ctx),
)

def visitReplaceAtom(self, ctx: Parser.ReplaceAtomContext):
Expand All @@ -662,7 +672,10 @@ def visitReplaceAtom(self, ctx: Parser.ReplaceAtomContext):
params_nodes = [expressions[1]] + params

return ParamOp(
op=op_node, children=children_nodes, params=params_nodes, **extract_token_info(ctx)
op=op_node,
children=children_nodes,
params=params_nodes,
**extract_token_info(ctx),
)

def visitInstrAtom(self, ctx: Parser.InstrAtomContext):
Expand All @@ -685,7 +698,10 @@ def visitInstrAtom(self, ctx: Parser.InstrAtomContext):
params_nodes = [expressions[1]] + params

return ParamOp(
op=op_node, children=children_nodes, params=params_nodes, **extract_token_info(ctx)
op=op_node,
children=children_nodes,
params=params_nodes,
**extract_token_info(ctx),
)

"""
Expand Down Expand Up @@ -733,7 +749,10 @@ def visitUnaryWithOptionalNumeric(self, ctx: Parser.UnaryWithOptionalNumericCont
params_nodes.append(self.visitOptionalExpr(param))

return ParamOp(
op=op_node, children=children_nodes, params=params_nodes, **extract_token_info(ctx)
op=op_node,
children=children_nodes,
params=params_nodes,
**extract_token_info(ctx),
)

def visitBinaryNumeric(self, ctx: Parser.BinaryNumericContext):
Expand Down Expand Up @@ -911,7 +930,10 @@ def visitFillTimeAtom(self, ctx: Parser.FillTimeAtomContext):
param_constant_node = []

return ParamOp(
op=op, children=children_node, params=param_constant_node, **extract_token_info(ctx)
op=op,
children=children_node,
params=param_constant_node,
**extract_token_info(ctx),
)

def visitTimeAggAtom(self, ctx: Parser.TimeAggAtomContext):
Expand Down Expand Up @@ -996,7 +1018,10 @@ def visitTimeAddAtom(self, ctx: Parser.TimeShiftAtomContext):
param_constant_node.append(self.visitExpr(ctx_list[6]))

return ParamOp(
op=op, children=children_node, params=param_constant_node, **extract_token_info(ctx)
op=op,
children=children_node,
params=param_constant_node,
**extract_token_info(ctx),
)

"""
Expand Down Expand Up @@ -1050,7 +1075,9 @@ def visitUnionAtom(self, ctx: Parser.UnionAtomContext):
]

return MulOp(
op=ctx_list[0].getSymbol().text, children=exprs_nodes, **extract_token_info(ctx)
op=ctx_list[0].getSymbol().text,
children=exprs_nodes,
**extract_token_info(ctx),
)

def visitIntersectAtom(self, ctx: Parser.IntersectAtomContext):
Expand All @@ -1060,7 +1087,9 @@ def visitIntersectAtom(self, ctx: Parser.IntersectAtomContext):
]

return MulOp(
op=ctx_list[0].getSymbol().text, children=exprs_nodes, **extract_token_info(ctx)
op=ctx_list[0].getSymbol().text,
children=exprs_nodes,
**extract_token_info(ctx),
)

def visitSetOrSYmDiffAtom(self, ctx: Parser.SetOrSYmDiffAtomContext):
Expand All @@ -1070,7 +1099,9 @@ def visitSetOrSYmDiffAtom(self, ctx: Parser.SetOrSYmDiffAtomContext):
]

return MulOp(
op=ctx_list[0].getSymbol().text, children=exprs_nodes, **extract_token_info(ctx)
op=ctx_list[0].getSymbol().text,
children=exprs_nodes,
**extract_token_info(ctx),
)

"""
Expand Down Expand Up @@ -1124,7 +1155,9 @@ def visitHierarchyFunctions(self, ctx: Parser.HierarchyFunctionsContext):
if rule_element.kind == "DatasetID":
check_hierarchy_rule = rule_element.value
rule_comp = Identifier(
value=check_hierarchy_rule, kind="ComponentID", **extract_token_info(ctx)
value=check_hierarchy_rule,
kind="ComponentID",
**extract_token_info(ctx),
)
else: # ValuedomainID
raise SemanticError("1-1-10-4", op=op)
Expand Down Expand Up @@ -1546,7 +1579,9 @@ def visitRenameClause(self, ctx: Parser.RenameClauseContext):
rename_nodes.append(self.visitRenameClauseItem(ctx_rename))

return RegularAggregation(
op=ctx_list[0].getSymbol().text, children=rename_nodes, **extract_token_info(ctx)
op=ctx_list[0].getSymbol().text,
children=rename_nodes,
**extract_token_info(ctx),
)

def visitRenameClauseItem(self, ctx: Parser.RenameClauseItemContext):
Expand Down Expand Up @@ -1771,14 +1806,34 @@ def visitGroupAll(self, ctx: Parser.GroupAllContext):

# Check if TIME_AGG is present (more than just GROUP ALL)
if len(ctx_list) > 2:
period_to, conf = self._extract_time_agg_tokens(ctx_list)
period_to = None
period_from = None
operand_node = None
conf = None

for child in ctx_list:
if isinstance(child, TerminalNodeImpl):
token = child.getSymbol()
if token.type == Parser.STRING_CONSTANT:
if period_to is None:
period_to = token.text[1:-1]
else:
period_from = token.text[1:-1]
elif token.type in [Parser.FIRST, Parser.LAST]:
conf = token.text
elif isinstance(child, Parser.OptionalExprContext):
operand_node = self.visitOptionalExpr(child)
if isinstance(operand_node, ID):
operand_node = None
elif isinstance(operand_node, Identifier):
operand_node = VarID(value=operand_node.value, **extract_token_info(child))

children_nodes = [
TimeAggregation(
op="time_agg",
operand=None,
operand=operand_node,
period_to=period_to,
period_from=None,
period_from=period_from,
conf=conf,
**extract_token_info(ctx),
)
Expand Down Expand Up @@ -1853,7 +1908,9 @@ def visitCalcClauseItem(self, ctx: Parser.CalcClauseItemContext):
)
if role is None:
return UnaryOp(
op=Role.MEASURE.value.lower(), operand=operand_node, **extract_token_info(c)
op=Role.MEASURE.value.lower(),
operand=operand_node,
**extract_token_info(c),
)
return UnaryOp(op=role.value.lower(), operand=operand_node, **extract_token_info(c))
else:
Expand All @@ -1865,7 +1922,9 @@ def visitCalcClauseItem(self, ctx: Parser.CalcClauseItemContext):
left=left_node, op=op_node, right=right_node, **extract_token_info(ctx)
)
return UnaryOp(
op=Role.MEASURE.value.lower(), operand=operand_node, **extract_token_info(ctx)
op=Role.MEASURE.value.lower(),
operand=operand_node,
**extract_token_info(ctx),
)

def visitKeepOrDropClause(self, ctx: Parser.KeepOrDropClauseContext):
Expand Down
42 changes: 33 additions & 9 deletions src/vtlengine/AST/Grammar/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3292,7 +3292,8 @@ def exprComponent(self, _p: int = 0):
la_ = self._interp.adaptivePredict(self._input, 10, self._ctx)
if la_ == 1:
localctx = Parser.ArithmeticExprCompContext(
self, Parser.ExprComponentContext(self, _parentctx, _parentState)
self,
Parser.ExprComponentContext(self, _parentctx, _parentState),
)
localctx.left = _prevctx
self.pushNewRecursionContext(localctx, _startState, self.RULE_exprComponent)
Expand All @@ -3315,7 +3316,8 @@ def exprComponent(self, _p: int = 0):

elif la_ == 2:
localctx = Parser.ArithmeticExprOrConcatCompContext(
self, Parser.ExprComponentContext(self, _parentctx, _parentState)
self,
Parser.ExprComponentContext(self, _parentctx, _parentState),
)
localctx.left = _prevctx
self.pushNewRecursionContext(localctx, _startState, self.RULE_exprComponent)
Expand All @@ -3338,7 +3340,8 @@ def exprComponent(self, _p: int = 0):

elif la_ == 3:
localctx = Parser.ComparisonExprCompContext(
self, Parser.ExprComponentContext(self, _parentctx, _parentState)
self,
Parser.ExprComponentContext(self, _parentctx, _parentState),
)
localctx.left = _prevctx
self.pushNewRecursionContext(localctx, _startState, self.RULE_exprComponent)
Expand All @@ -3355,7 +3358,8 @@ def exprComponent(self, _p: int = 0):

elif la_ == 4:
localctx = Parser.BooleanExprCompContext(
self, Parser.ExprComponentContext(self, _parentctx, _parentState)
self,
Parser.ExprComponentContext(self, _parentctx, _parentState),
)
localctx.left = _prevctx
self.pushNewRecursionContext(localctx, _startState, self.RULE_exprComponent)
Expand All @@ -3372,7 +3376,8 @@ def exprComponent(self, _p: int = 0):

elif la_ == 5:
localctx = Parser.BooleanExprCompContext(
self, Parser.ExprComponentContext(self, _parentctx, _parentState)
self,
Parser.ExprComponentContext(self, _parentctx, _parentState),
)
localctx.left = _prevctx
self.pushNewRecursionContext(localctx, _startState, self.RULE_exprComponent)
Expand All @@ -3395,7 +3400,8 @@ def exprComponent(self, _p: int = 0):

elif la_ == 6:
localctx = Parser.InNotInExprCompContext(
self, Parser.ExprComponentContext(self, _parentctx, _parentState)
self,
Parser.ExprComponentContext(self, _parentctx, _parentState),
)
localctx.left = _prevctx
self.pushNewRecursionContext(localctx, _startState, self.RULE_exprComponent)
Expand Down Expand Up @@ -6893,7 +6899,14 @@ def numericOperators(self):
self.state = 780
self._errHandler.sync(self)
token = self._input.LA(1)
if token in [Parser.ABS, Parser.LN, Parser.EXP, Parser.CEIL, Parser.FLOOR, Parser.SQRT]:
if token in [
Parser.ABS,
Parser.LN,
Parser.EXP,
Parser.CEIL,
Parser.FLOOR,
Parser.SQRT,
]:
localctx = Parser.UnaryNumericContext(self, localctx)
self.enterOuterAlt(localctx, 1)
self.state = 759
Expand Down Expand Up @@ -7138,7 +7151,14 @@ def numericOperatorsComponent(self):
self.state = 803
self._errHandler.sync(self)
token = self._input.LA(1)
if token in [Parser.ABS, Parser.LN, Parser.EXP, Parser.CEIL, Parser.FLOOR, Parser.SQRT]:
if token in [
Parser.ABS,
Parser.LN,
Parser.EXP,
Parser.CEIL,
Parser.FLOOR,
Parser.SQRT,
]:
localctx = Parser.UnaryNumericComponentContext(self, localctx)
self.enterOuterAlt(localctx, 1)
self.state = 782
Expand Down Expand Up @@ -13121,7 +13141,11 @@ def rulesetType(self):
self.state = 1542
self.match(Parser.RULESET)
pass
elif token in [Parser.DATAPOINT, Parser.DATAPOINT_ON_VD, Parser.DATAPOINT_ON_VAR]:
elif token in [
Parser.DATAPOINT,
Parser.DATAPOINT_ON_VD,
Parser.DATAPOINT_ON_VAR,
]:
self.enterOuterAlt(localctx, 2)
self.state = 1543
self.dpRuleset()
Expand Down
8 changes: 8 additions & 0 deletions src/vtlengine/Exceptions/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,14 @@
"description": "Raised when URL datapoints are provided but data_structures is not a "
"file path or URL for fetching the SDMX structure definition.",
},
# Env var errors
"0-4-1-1": {
"message": "Invalid value for {env_var}: {value}. "
"Expected an integer between {min_value} and {max_value}, "
"or {disable_value} to disable.",
"description": "Raised when the provided time period output format "
"is not one of the supported representations.",
},
# ------------Operators-------------
# General Semantic errors
"1-1-1-1": {
Expand Down
3 changes: 1 addition & 2 deletions src/vtlengine/Interpreter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -855,8 +855,7 @@ def visit_VarID(self, node: AST.VarID) -> Any: # noqa: C901
return copy(self.scalars[node.value])
if (
self.is_from_join
and node.value
not in self.regular_aggregation_dataset.get_components_names()
and node.value not in self.regular_aggregation_dataset.get_components_names()
):
is_partial_present = 0
found_comp = None
Expand Down
4 changes: 2 additions & 2 deletions src/vtlengine/Operators/Numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,9 +469,9 @@ class Random(Parameterized):
def validate(cls, seed: Any, index: Any = None) -> Any:
if index.data_type != Integer:
index.data_type = binary_implicit_promotion(index.data_type, Integer)
if index.value < 0:
if index.value is not None and index.value < 0:
raise SemanticError("2-1-15-2", op=cls.op, value=index)
if index.value > 10000:
if index.value is not None and index.value > 10000:
warnings.warn(
"Random: The value of 'index' is very big. This can affect performance.",
UserWarning,
Expand Down
Loading