diff --git a/vtl-engine/src/main/java/fr/insee/vtl/engine/visitors/ClauseVisitor.java b/vtl-engine/src/main/java/fr/insee/vtl/engine/visitors/ClauseVisitor.java index fefde8900..b31063046 100644 --- a/vtl-engine/src/main/java/fr/insee/vtl/engine/visitors/ClauseVisitor.java +++ b/vtl-engine/src/main/java/fr/insee/vtl/engine/visitors/ClauseVisitor.java @@ -106,83 +106,294 @@ private static AggregationExpression convertToAggregation( @Override public DatasetExpression visitKeepOrDropClause(VtlParser.KeepOrDropClauseContext ctx) { - // Normalize to keep operation. - var keep = ctx.op.getType() == VtlParser.KEEP; - var names = ctx.componentID().stream().map(ClauseVisitor::getName).collect(Collectors.toSet()); - List columnNames = - datasetExpression.getDataStructure().values().stream() - .map(Dataset.Component::getName) - .filter(name -> keep == names.contains(name)) - .collect(Collectors.toList()); - return processingEngine.executeProject(datasetExpression, columnNames); + // The type of the op can either be KEEP or DROP. + final boolean keep = ctx.op.getType() == VtlParser.KEEP; + + // Columns explicitly requested in the KEEP/DROP clause + final List columnNames = + ctx.componentID().stream().map(ClauseVisitor::getName).toList(); + + // All available dataset components + final List inputColumnDataTypes = + new ArrayList<>(datasetExpression.getDataStructure().values()); + final List inputColumns = + inputColumnDataTypes.stream().map(Dataset.Component::getName).toList(); + + // Dataset identifiers (role = IDENTIFIER) + final Map identifiers = + inputColumnDataTypes.stream() + .filter(c -> c.getRole() == Dataset.Role.IDENTIFIER) + .collect( + Collectors.toMap( + Dataset.Component::getName, c -> c, (a, b) -> a, LinkedHashMap::new)); + + // Evaluate that all requested columns must exist in the dataset or raise an error + for (String requested : columnNames) { + if (!inputColumns.contains(requested)) { + throw new VtlRuntimeException( + new InvalidArgumentException( +// TODO: use actual column context. + String.format("'%s' not found in dataset.", requested), fromContext(ctx))); + } + } + + // VTL specification: identifiers must not appear explicitly in KEEP + final Set forbidden = + columnNames.stream() + .filter(identifiers::containsKey) + .collect(Collectors.toCollection(LinkedHashSet::new)); + + if (!forbidden.isEmpty()) { + StringBuilder details = new StringBuilder(); + for (String id : forbidden) { + Dataset.Component comp = identifiers.get(id); + details.append( + String.format( + "%s(role=%s, type=%s) ", + id, comp.getRole(), comp.getType() != null ? comp.getType() : "n/a")); + } + throw new VtlRuntimeException( + new InvalidArgumentException( + String.format( + "identifiers %s must not be explicitly listed in KEEP/DROP. Details: %s", + forbidden, details.toString().trim()), +// TODO: use actual column context. + fromContext(ctx))); + } + + // Build result set: + // + KEEP: identifiers + requested columns + // + DROP: (all columns - requested) + identifiers + final Set resultSet = new LinkedHashSet<>(); + resultSet.addAll(identifiers.keySet()); + if (keep) { + resultSet.addAll(columnNames); + } else { + for (String col : inputColumns) { + if (!columnNames.contains(col)) { + resultSet.add(col); + } + } + } + + // Retrieve the output column names (identifiers + requested) + final List outputColumns = + inputColumns.stream().filter(resultSet::contains).collect(Collectors.toList()); + return processingEngine.executeProject(datasetExpression, outputColumns); } @Override public DatasetExpression visitCalcClause(VtlParser.CalcClauseContext ctx) { - var expressions = new LinkedHashMap(); - var expressionStrings = new LinkedHashMap(); - var roles = new LinkedHashMap(); - var currentDatasetExpression = datasetExpression; - // TODO: Refactor so we call the executeCalc for each CalcClauseItemContext the same way we call - // the - // analytics functions. + // Dataset structure (ordered) and quick lookups + final List componentsInOrder = + new ArrayList<>(datasetExpression.getDataStructure().values()); + + final Map byName = + componentsInOrder.stream() + .collect( + Collectors.toMap( + Dataset.Component::getName, c -> c, (a, b) -> a, LinkedHashMap::new)); + + // Accumulators for non-analytic calc items + final LinkedHashMap expressions = new LinkedHashMap<>(); + final LinkedHashMap expressionStrings = new LinkedHashMap<>(); + final LinkedHashMap roles = new LinkedHashMap<>(); + + // Tracks duplicates in the same clause (target names) + final Set targetsSeen = new LinkedHashSet<>(); + + // We need a rolling dataset expression to chain analytics items + DatasetExpression currentDatasetExpression = datasetExpression; + + // TODO: Refactor so we call executeCalc per CalcClauseItemContext (as analytics do). for (VtlParser.CalcClauseItemContext calcCtx : ctx.calcClauseItem()) { - var columnName = getName(calcCtx.componentID()); - var columnRole = - calcCtx.componentRole() == null + + // ---- Resolve target name and desired role ---- + final String columnName = getName(calcCtx.componentID()); + final Dataset.Role columnRole = + (calcCtx.componentRole() == null) ? Dataset.Role.MEASURE : Dataset.Role.valueOf(calcCtx.componentRole().getText().toUpperCase()); - if ((calcCtx.expr() instanceof VtlParser.FunctionsExpressionContext) - && ((VtlParser.FunctionsExpressionContext) calcCtx.expr()).functions() - instanceof VtlParser.AnalyticFunctionsContext) { - AnalyticsVisitor analyticsVisitor = + // If the target already exists in the dataset, check its role + final Dataset.Component existing = byName.get(columnName); + if (existing != null) { + // Explicitly block overwriting identifiers (already handled above if role==IDENTIFIER). + if (existing.getRole() == Dataset.Role.IDENTIFIER) { + final String meta = + String.format( + "(role=%s, type=%s)", + existing.getRole(), existing.getType() != null ? existing.getType() : "n/a"); + throw new VtlRuntimeException( + new InvalidArgumentException( +// TODO: see if other cases are the same error (already defined in assignment for example). + String.format("CALC cannot overwrite IDENTIFIER '%s' %s.", columnName, meta), + fromContext(ctx))); + } + } + + // ---- Dispatch: analytics vs. regular calc ---- + final boolean isAnalytic = + (calcCtx.expr() instanceof VtlParser.FunctionsExpressionContext) + && ((VtlParser.FunctionsExpressionContext) calcCtx.expr()).functions() + instanceof VtlParser.AnalyticFunctionsContext; + + if (isAnalytic) { + // Analytics are executed immediately and update the rolling dataset expression + final AnalyticsVisitor analyticsVisitor = new AnalyticsVisitor(processingEngine, currentDatasetExpression, columnName); - VtlParser.FunctionsExpressionContext functionExprCtx = + final VtlParser.FunctionsExpressionContext functionExprCtx = (VtlParser.FunctionsExpressionContext) calcCtx.expr(); - VtlParser.AnalyticFunctionsContext anFuncCtx = + final VtlParser.AnalyticFunctionsContext anFuncCtx = (VtlParser.AnalyticFunctionsContext) functionExprCtx.functions(); + currentDatasetExpression = analyticsVisitor.visit(anFuncCtx); } else { - ResolvableExpression calc = componentExpressionVisitor.visit(calcCtx); + // Regular calc expression – build resolvable expression and capture its source text + final ResolvableExpression calc = componentExpressionVisitor.visit(calcCtx); + + final String exprSource = getSource(calcCtx.expr()); + if (exprSource == null || exprSource.isEmpty()) { + throw new VtlRuntimeException( + new InvalidArgumentException( + String.format( + "empty or unavailable source expression for '%s' in CALC.", columnName), + fromContext(ctx))); + } + // Store in insertion order (deterministic column creation) expressions.put(columnName, calc); - expressionStrings.put(columnName, getSource(calcCtx.expr())); + expressionStrings.put(columnName, exprSource); roles.put(columnName, columnRole); } } + // ---- Consistency checks before execution ---- + if (!(expressions.keySet().equals(expressionStrings.keySet()) + && expressions.keySet().equals(roles.keySet()))) { + throw new VtlRuntimeException( + new InvalidArgumentException( + "internal CALC maps out of sync (expressions/expressionStrings/roles)", + fromContext(ctx))); + } + + // ---- Execute the batch calc if any non-analytic expressions were collected ---- if (!expressionStrings.isEmpty()) { currentDatasetExpression = processingEngine.executeCalc( currentDatasetExpression, expressions, roles, expressionStrings); } - return currentDatasetExpression; } @Override public DatasetExpression visitFilterClause(VtlParser.FilterClauseContext ctx) { + + // Error reporting context + final int line = ctx.getStart().getLine(); + final int charPosition = ctx.getStart().getCharPositionInLine(); + final String statement = ctx.getText(); + ResolvableExpression filter = componentExpressionVisitor.visit(ctx.expr()); return processingEngine.executeFilter(datasetExpression, filter, getSource(ctx.expr())); } @Override public DatasetExpression visitRenameClause(VtlParser.RenameClauseContext ctx) { + + // Dataset structure in order + lookup maps + final List componentsInOrder = + new ArrayList<>(datasetExpression.getDataStructure().values()); + final Set availableColumns = + componentsInOrder.stream() + .map(Dataset.Component::getName) + .collect(Collectors.toCollection(LinkedHashSet::new)); + + // Map for detailed error reporting (includes role/type if available) + final Map byName = + componentsInOrder.stream() + .collect( + Collectors.toMap( + Dataset.Component::getName, c -> c, (a, b) -> a, LinkedHashMap::new)); + + // Parse the RENAME clause and validate Map fromTo = new LinkedHashMap<>(); - Set renamed = new HashSet<>(); + Set toSeen = new LinkedHashSet<>(); + Set fromSeen = new LinkedHashSet<>(); + for (VtlParser.RenameClauseItemContext renameCtx : ctx.renameClauseItem()) { - var toNameString = getName(renameCtx.toName); - var fromNameString = getName(renameCtx.fromName); - if (!renamed.add(toNameString)) { + final String toNameString = getName(renameCtx.toName); + final String fromNameString = getName(renameCtx.fromName); + + // Validate: no duplicate "from" names inside the clause + if (!fromSeen.add(fromNameString)) { throw new VtlRuntimeException( new InvalidArgumentException( - "duplicate column: %s".formatted(toNameString), fromContext(renameCtx))); + String.format("Error: duplicate source name in RENAME clause: '%s", fromNameString), + fromContext(ctx))); } + + // Validate: "from" must exist in dataset + if (!availableColumns.contains(fromNameString)) { + Dataset.Component comp = byName.get(fromNameString); + String meta = + (comp != null) + ? String.format( + " (role=%s, type=%s)", + comp.getRole(), comp.getType() != null ? comp.getType() : "n/a") + : ""; + throw new VtlRuntimeException( + new InvalidArgumentException( + String.format( + "Error: source column to rename not found: '%s'%s", fromNameString, meta), + fromContext(ctx))); + } + + // Validate: no duplicate "to" names inside the clause + if (!toSeen.add(toNameString)) { + throw new VtlRuntimeException( + new InvalidArgumentException( + String.format( + "Error: duplicate output column name in RENAME clause: '%s.", fromNameString), + fromContext(ctx))); + } + fromTo.put(fromNameString, toNameString); } + + // Validate collisions with untouched dataset columns ("Untouched" = columns that are not + // being renamed) + final Set untouched = + availableColumns.stream() + .filter(c -> !fromTo.containsKey(c)) + .collect(Collectors.toCollection(LinkedHashSet::new)); + + for (Map.Entry e : fromTo.entrySet()) { + final String from = e.getKey(); + final String to = e.getValue(); + + // If target already exists as untouched, it would cause a collision + if (untouched.contains(to)) { + Dataset.Component comp = byName.get(to); + String meta = + (comp != null) + ? String.format( + " (role=%s, type=%s)", + comp.getRole(), comp.getType() != null ? comp.getType() : "n/a") + : ""; + + throw new VtlRuntimeException( + new InvalidArgumentException( + String.format( + "Error: target name '%s'%s already exists in dataset and is not being renamed.", + to, meta), + fromContext(ctx))); + } + } + + // Execute rename in processing engine return processingEngine.executeRename(datasetExpression, fromTo); } diff --git a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/ClauseVisitorTest.java b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/ClauseVisitorTest.java index 5c25d981b..a4127d2bd 100644 --- a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/ClauseVisitorTest.java +++ b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/ClauseVisitorTest.java @@ -1,6 +1,5 @@ package fr.insee.vtl.engine.visitors; -import static fr.insee.vtl.engine.VtlScriptEngineTest.atPosition; import static fr.insee.vtl.model.Dataset.Role; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -86,8 +85,9 @@ public void testManyCalc() throws ScriptException { Map.of("name", "Franck", "weight", 9L, "wisdom", 24L)); } + /** CALC: measures/attributes are allowed and should be created as requested. */ @Test - public void testCalcRoleModifier() throws ScriptException { + public void testCalcRoleModifier_measuresAndAttributesOk() throws ScriptException { InMemoryDataset dataset = new InMemoryDataset( List.of( @@ -125,8 +125,9 @@ public void testCalcRoleModifier() throws ScriptException { assertThat(unitComponent.getRole()).isEqualTo(Role.ATTRIBUTE); } + /** RENAME: duplicate "to" name inside the clause must raise a detailed script error. */ @Test - public void testRenameClause() throws ScriptException { + public void testRenameClause_duplicateToNameShouldFail() { InMemoryDataset dataset = new InMemoryDataset( List.of( @@ -136,23 +137,67 @@ public void testRenameClause() throws ScriptException { Map.of("name", String.class, "age", Long.class, "weight", Long.class), Map.of("name", Role.IDENTIFIER, "age", Role.MEASURE, "weight", Role.MEASURE)); - ScriptContext context = engine.getContext(); - context.setAttribute("ds", dataset, ScriptContext.ENGINE_SCOPE); + engine.getContext().setAttribute("ds1", dataset, ScriptContext.ENGINE_SCOPE); - engine.eval("ds1 := ds[rename age to weight, weight to age, name to pseudo];"); + assertThatThrownBy( + () -> engine.eval("ds := ds1[rename age to weight, weight to age, name to age];")) + .isInstanceOf(VtlScriptException.class) + .hasMessageContaining("duplicate output column name in RENAME clause"); + } - assertThat(engine.getContext().getAttribute("ds1")).isInstanceOf(Dataset.class); - assertThat(((Dataset) engine.getContext().getAttribute("ds1")).getDataAsMap()) - .containsExactlyInAnyOrder( - Map.of("pseudo", "Hadrien", "weight", 10L, "age", 11L), - Map.of("pseudo", "Nico", "weight", 11L, "age", 10L), - Map.of("pseudo", "Franck", "weight", 12L, "age", 9L)); + /** RENAME: duplicate "from" name inside the clause must raise a detailed script error. */ + @Test + public void testRenameClause_duplicateFromNameShouldFail() { + InMemoryDataset dataset = + new InMemoryDataset( + List.of( + Map.of("name", "Hadrien", "age", 10L, "weight", 11L), + Map.of("name", "Nico", "age", 11L, "weight", 10L)), + Map.of("name", String.class, "age", Long.class, "weight", Long.class), + Map.of("name", Role.IDENTIFIER, "age", Role.MEASURE, "weight", Role.MEASURE)); - assertThatThrownBy( - () -> engine.eval("ds2 := ds[rename age to weight, weight to age, name to age];")) + engine.getContext().setAttribute("ds1", dataset, ScriptContext.ENGINE_SCOPE); + + assertThatThrownBy(() -> engine.eval("ds := ds1[rename age to weight, age to weight2];")) + .isInstanceOf(VtlScriptException.class) + .hasMessageContaining("duplicate source name in RENAME clause"); + } + + /** RENAME: "from" column must exist in dataset. */ + @Test + public void testRenameClause_fromColumnNotFoundShouldFail() { + InMemoryDataset dataset = + new InMemoryDataset( + List.of(Map.of("name", "Hadrien", "age", 10L, "weight", 11L)), + Map.of("name", String.class, "age", Long.class, "weight", Long.class), + Map.of("name", Role.IDENTIFIER, "age", Role.MEASURE, "weight", Role.MEASURE)); + + engine.getContext().setAttribute("ds1", dataset, ScriptContext.ENGINE_SCOPE); + + assertThatThrownBy(() -> engine.eval("ds := ds1[rename unknown to something];")) + .isInstanceOf(VtlScriptException.class) + .hasMessageContaining("source column to rename not found: 'unknown'"); + } + + /** + * RENAME: target collides with an untouched existing column -> must error with details + * (role/type). + */ + @Test + public void testRenameClause_targetCollidesWithUntouchedShouldFail() { + InMemoryDataset dataset = + new InMemoryDataset( + List.of(Map.of("name", "Hadrien", "age", 10L, "weight", 11L)), + Map.of("name", String.class, "age", Long.class, "weight", Long.class), + Map.of("name", Role.IDENTIFIER, "age", Role.MEASURE, "weight", Role.MEASURE)); + + engine.getContext().setAttribute("ds1", dataset, ScriptContext.ENGINE_SCOPE); + + assertThatThrownBy(() -> engine.eval("ds := ds1[rename name to age];")) .isInstanceOf(VtlScriptException.class) - .hasMessage("duplicate column: age") - .is(atPosition(0, 47, 58)); + .hasMessageContaining("target name 'age'") // main message + .hasMessageContaining("already exists in dataset and is not being renamed") + .hasMessageContaining("(role=MEASURE, type=class java.lang.Long)"); } @Test @@ -194,7 +239,8 @@ public void testKeepDropClause() throws ScriptException { ScriptContext context = engine.getContext(); context.setAttribute("ds1", dataset, ScriptContext.ENGINE_SCOPE); - engine.eval("ds2 := ds1[keep name, age];"); + // KEEP: identifiers must not be listed explicitly; they are implicitly preserved. + engine.eval("ds2 := ds1[keep age];"); assertThat(engine.getContext().getAttribute("ds2")).isInstanceOf(Dataset.class); assertThat(((Dataset) engine.getContext().getAttribute("ds2")).getDataAsMap()) @@ -213,6 +259,26 @@ public void testKeepDropClause() throws ScriptException { Map.of("name", "Franck", "age", 12L)); } + /** KEEP/DROP: listing identifiers explicitly must raise a script error. */ + @Test + public void testKeepDropClause_identifierExplicitShouldFail() { + InMemoryDataset dataset = + new InMemoryDataset( + List.of( + Map.of("name", "Hadrien", "age", 10L, "weight", 11L), + Map.of("name", "Nico", "age", 11L, "weight", 10L), + Map.of("name", "Franck", "age", 12L, "weight", 9L)), + Map.of("name", String.class, "age", Long.class, "weight", Long.class), + Map.of("name", Role.IDENTIFIER, "age", Role.MEASURE, "weight", Role.MEASURE)); + + ScriptContext context = engine.getContext(); + context.setAttribute("ds1", dataset, ScriptContext.ENGINE_SCOPE); + + assertThatThrownBy(() -> engine.eval("ds := ds1[keep name, age];")) + .isInstanceOf(VtlScriptException.class) + .hasMessageContaining("identifiers [name] must not be explicitly listed in KEEP/DROP"); + } + @Test public void testAggregateType() { InMemoryDataset dataset = diff --git a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ArithmeticExprOrConcatTest.java b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ArithmeticExprOrConcatTest.java index 3d61e46ba..d3cb18544 100644 --- a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ArithmeticExprOrConcatTest.java +++ b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ArithmeticExprOrConcatTest.java @@ -52,7 +52,7 @@ public void testPlus() throws ScriptException { assertThat(context.getAttribute("plus2")).isEqualTo(5.0); context.setAttribute("ds1", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := ds1[keep id, long1, long2] + ds1[keep id, long1, long2];"); + Object res = engine.eval("res := ds1[keep long1, long2] + ds1[keep long1, long2];"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Toto", "long1", 60L, "long2", 600L), @@ -75,7 +75,7 @@ public void testMinus() throws ScriptException { context.setAttribute("ds1", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); context.setAttribute("ds2", DatasetSamples.ds2, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := ds2[keep id, long1] - ds1[keep id, long1] + 1;"); + Object res = engine.eval("res := ds2[keep long1] - ds1[keep long1] + 1;"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Hadrien", "long1", 141L), @@ -92,7 +92,7 @@ public void testConcat() throws ScriptException { context.setAttribute("ds1", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); context.setAttribute("ds2", DatasetSamples.ds2, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := ds2[keep id, string1] || \" \" || ds1[keep id, string1];"); + Object res = engine.eval("res := ds2[keep string1] || \" \" || ds1[keep string1];"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Hadrien", "string1", "hadrien hadrien"), diff --git a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ArithmeticExprTest.java b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ArithmeticExprTest.java index c5822ea0f..353838880 100644 --- a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ArithmeticExprTest.java +++ b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ArithmeticExprTest.java @@ -64,8 +64,7 @@ public void testArithmeticExpr() throws ScriptException { context.setAttribute("ds1", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); context.setAttribute("ds2", DatasetSamples.ds2, ScriptContext.ENGINE_SCOPE); - Object res = - engine.eval("res := round(ds1[keep id, long1, double1] * ds2[keep id, long1, double1]);"); + Object res = engine.eval("res := round(ds1[keep long1, double1] * ds2[keep long1, double1]);"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Hadrien", "long1", 1500.0, "double1", 1.0), @@ -83,8 +82,7 @@ public void testArithmeticExpr() throws ScriptException { engine.eval("div4 := 3.0 / 1.5;"); assertThat(context.getAttribute("div4")).isEqualTo(2.0); - res = - engine.eval("res2 := round(ds1[keep id, long1, double1] / ds2[keep id, long1, double1]);"); + res = engine.eval("res2 := round(ds1[keep long1, double1] / ds2[keep long1, double1]);"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Hadrien", "long1", 0.0, "double1", 1.0), diff --git a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/BooleanExprTest.java b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/BooleanExprTest.java index 7e7216f6d..d9ba19e7d 100644 --- a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/BooleanExprTest.java +++ b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/BooleanExprTest.java @@ -100,8 +100,8 @@ public void testOnDatasets() throws ScriptException { context.setAttribute("ds_1", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); context.setAttribute("ds_2", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); engine.eval( - "ds1 := ds_1[keep id, bool2][rename bool2 to bool1]; " - + "ds2 := ds_2[keep id, bool1]; " + "ds1 := ds_1[keep bool2][rename bool2 to bool1]; " + + "ds2 := ds_2[keep bool1]; " + "andDs := ds1 and ds2; " + "orDs := ds1 or ds2; " + "xorDs := ds1 xor ds2; "); diff --git a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ComparisonExprTest.java b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ComparisonExprTest.java index 70921ac91..297becc48 100644 --- a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ComparisonExprTest.java +++ b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ComparisonExprTest.java @@ -73,7 +73,7 @@ public void testComparisonExpr() throws ScriptException { context.setAttribute("ds1", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); context.setAttribute("ds2", DatasetSamples.ds2, ScriptContext.ENGINE_SCOPE); - engine.eval("equal := ds1[keep id, long1] = ds2[keep id, long1];"); + engine.eval("equal := ds1[keep long1] = ds2[keep long1];"); var equal = engine.getContext().getAttribute("equal"); assertThat(((Dataset) equal).getDataAsMap()) .containsExactlyInAnyOrder( @@ -90,7 +90,7 @@ public void testComparisonExpr() throws ScriptException { assertThat((Boolean) context.getAttribute("long1")).isTrue(); engine.eval("mix1 := 6 <> (3*20.0);"); assertThat((Boolean) context.getAttribute("mix1")).isTrue(); - engine.eval("notEqual := ds1[keep id, long1] <> ds2[keep id, long1];"); + engine.eval("notEqual := ds1[keep long1] <> ds2[keep long1];"); var notEqual = engine.getContext().getAttribute("notEqual"); assertThat(((Dataset) notEqual).getDataAsMap()) .containsExactlyInAnyOrder( @@ -106,7 +106,7 @@ public void testComparisonExpr() throws ScriptException { assertThat((Boolean) context.getAttribute("lt1")).isFalse(); engine.eval("mix2 := 6 < 6.1;"); assertThat((Boolean) context.getAttribute("mix2")).isTrue(); - engine.eval("lt2 := ds1[keep id, long1] < ds2[keep id, long1];"); + engine.eval("lt2 := ds1[keep long1] < ds2[keep long1];"); var lt = engine.getContext().getAttribute("lt2"); assertThat(((Dataset) lt).getDataAsMap()) .containsExactlyInAnyOrder( @@ -122,7 +122,7 @@ public void testComparisonExpr() throws ScriptException { assertThat((Boolean) context.getAttribute("mt1")).isTrue(); engine.eval("mix4 := 6 > 6.1;"); assertThat((Boolean) context.getAttribute("mix4")).isFalse(); - engine.eval("mt2 := ds1[keep id, long1] > ds2[keep id, long1];"); + engine.eval("mt2 := ds1[keep long1] > ds2[keep long1];"); var mt = engine.getContext().getAttribute("mt2"); assertThat(((Dataset) mt).getDataAsMap()) .containsExactlyInAnyOrder( @@ -139,7 +139,7 @@ public void testComparisonExpr() throws ScriptException { engine.eval("mix5 := 6 <= 6.1;"); assertThat((Boolean) context.getAttribute("mix5")).isTrue(); - engine.eval("le2 := ds1[keep id, long1] <= ds2[keep id, long1];"); + engine.eval("le2 := ds1[keep long1] <= ds2[keep long1];"); var le = engine.getContext().getAttribute("le2"); assertThat(((Dataset) le).getDataAsMap()) .containsExactlyInAnyOrder( @@ -156,7 +156,7 @@ public void testComparisonExpr() throws ScriptException { engine.eval("mix6 := 6 >= 6.1;"); assertThat((Boolean) context.getAttribute("mix6")).isFalse(); - engine.eval("me2 := ds1[keep id, long1] >= ds2[keep id, long1];"); + engine.eval("me2 := ds1[keep long1] >= ds2[keep long1];"); var me = engine.getContext().getAttribute("me2"); assertThat(((Dataset) me).getDataAsMap()) .containsExactlyInAnyOrder( @@ -198,7 +198,7 @@ public void testInNotIn() throws ScriptException { assertThat((Boolean) engine.getContext().getAttribute("res4")).isTrue(); engine.getContext().setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - engine.eval("me := ds[keep id, long1, string1] in {\"toto\", \"franck\"};"); + engine.eval("me := ds[keep long1, string1] in {\"toto\", \"franck\"};"); var in = engine.getContext().getAttribute("me"); assertThat(((Dataset) in).getDataAsMap()) .containsExactlyInAnyOrder( diff --git a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ConditionalExprTest.java b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ConditionalExprTest.java index 2994c97c7..5ce05c628 100644 --- a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ConditionalExprTest.java +++ b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/ConditionalExprTest.java @@ -46,8 +46,8 @@ public void testIfExpr() throws ScriptException { engine.getContext().setAttribute("ds_1", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); engine.getContext().setAttribute("ds_2", DatasetSamples.ds2, ScriptContext.ENGINE_SCOPE); engine.eval( - "ds1 := ds_1[keep id, long1][rename long1 to bool_var]; " - + "ds2 := ds_2[keep id, long1][rename long1 to bool_var]; " + "ds1 := ds_1[keep long1][rename long1 to bool_var]; " + + "ds2 := ds_2[keep long1][rename long1 to bool_var]; " + "res := if ds1 > ds2 then ds1 else ds2;"); var res = engine.getContext().getAttribute("res"); assertThat(((Dataset) res).getDataAsMap()) @@ -73,7 +73,7 @@ public void testCaseExpr() throws ScriptException { engine.getContext().setAttribute("ds_1", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); engine.getContext().setAttribute("ds_2", DatasetSamples.ds2, ScriptContext.ENGINE_SCOPE); engine.eval( - "ds1 := ds_1[keep id, long1]; " + "ds1 := ds_1[keep long1]; " + "res <- ds1[calc c := case when long1 > 30 then \"ok\" else \"ko\"][drop long1];"); Object res = engine.getContext().getAttribute("res"); assertThat(((Dataset) res).getDataAsMap()) @@ -84,7 +84,7 @@ public void testCaseExpr() throws ScriptException { Map.of("id", "Franck", "c", "ok")); assertThat(((Dataset) res).getDataStructure().get("c").getType()).isEqualTo(String.class); engine.eval( - "ds2 := ds_1[keep id, long1]; " + "ds2 := ds_1[keep long1]; " + "res2 <- ds2[calc c := case when long1 > 30 then 1 else 0][drop long1];"); Object res2 = engine.getContext().getAttribute("res2"); assertThat(((Dataset) res2).getDataAsMap()) @@ -95,8 +95,8 @@ public void testCaseExpr() throws ScriptException { Map.of("id", "Franck", "c", 1L)); assertThat(((Dataset) res2).getDataStructure().get("c").getType()).isEqualTo(Long.class); engine.eval( - "ds3 := ds_1[keep id, long1][rename long1 to bool_var];" - + "ds4 := ds_2[keep id, long1][rename long1 to bool_var]; " + "ds3 := ds_1[keep long1][rename long1 to bool_var];" + + "ds4 := ds_2[keep long1][rename long1 to bool_var]; " + "res_ds <- case when ds3 < 30 then ds3 else ds4;"); Object res_ds = engine.getContext().getAttribute("res_ds"); assertThat(((Dataset) res_ds).getDataAsMap()) @@ -115,7 +115,7 @@ public void testNvlExpr() throws ScriptException { assertThat(context.getAttribute("s2")).isEqualTo("default"); engine.getContext().setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - engine.eval("res := nvl(ds[keep id, long1], 0);"); + engine.eval("res := nvl(ds[keep long1], 0);"); var res = engine.getContext().getAttribute("res"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( @@ -142,7 +142,7 @@ public void testNvlImplicitCast() throws ScriptException { assertThat(context.getAttribute("s2")).isEqualTo(1.1D); engine.getContext().setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - engine.eval("res := nvl(ds[keep id, long1], 0.1);"); + engine.eval("res := nvl(ds[keep long1], 0.1);"); var res = engine.getContext().getAttribute("res"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( diff --git a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/UnaryExprTest.java b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/UnaryExprTest.java index 45ef35973..bbe9aea24 100644 --- a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/UnaryExprTest.java +++ b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/UnaryExprTest.java @@ -44,7 +44,7 @@ public void testUnaryExpr() throws ScriptException { assertThat(context.getAttribute("plus1")).isEqualTo(1.5D); context.setAttribute("ds2", DatasetSamples.ds2, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res1 := + ds2[keep id, long1, double1];"); + Object res = engine.eval("res1 := + ds2[keep long1, double1];"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Hadrien", "long1", 150L, "double1", 1.1D), @@ -57,7 +57,7 @@ public void testUnaryExpr() throws ScriptException { engine.eval("plus3 := - 1.5;"); assertThat(context.getAttribute("plus3")).isEqualTo(-1.5D); - res = engine.eval("res2 := - ds2[keep id, long1, double1];"); + res = engine.eval("res2 := - ds2[keep long1, double1];"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Hadrien", "long1", -150L, "double1", -1.1D), diff --git a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/ComparisonFunctionsTest.java b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/ComparisonFunctionsTest.java index 9e307d085..e19a3d273 100644 --- a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/ComparisonFunctionsTest.java +++ b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/ComparisonFunctionsTest.java @@ -50,7 +50,7 @@ public void testBetweenAtom() throws ScriptException { assertThat((Boolean) context.getAttribute("b2")).isFalse(); context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := between(ds[keep id, long1, double2], 5, 15);"); + Object res = engine.eval("res := between(ds[keep long1, double2], 5, 15);"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Toto", "long1", false, "double2", false), @@ -80,8 +80,7 @@ public void testCharsetMatchAtom() throws ScriptException { assertThat((Boolean) context.getAttribute("t3")).isFalse(); context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - Object res = - engine.eval("res := match_characters(ds[keep id, string1, string2], \"(.*)o(.*)\");"); + Object res = engine.eval("res := match_characters(ds[keep string1, string2], \"(.*)o(.*)\");"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Toto", "string1", true, "string2", false), @@ -114,7 +113,7 @@ public void testIsNullAtom() throws ScriptException { assertThat((Boolean) context.getAttribute("n1")).isFalse(); context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := isnull(ds[keep id, string1, bool1]);"); + Object res = engine.eval("res := isnull(ds[keep string1, bool1]);"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Toto", "string1", false, "bool1", false), diff --git a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/DistanceFunctionsTest.java b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/DistanceFunctionsTest.java index f83d6837f..787e230b0 100644 --- a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/DistanceFunctionsTest.java +++ b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/DistanceFunctionsTest.java @@ -43,7 +43,7 @@ public void testLevenshteinAtom() throws ScriptException { context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); Object res = engine.eval( - "res := levenshtein(ds[keep id, string1], ds[keep id, string2][rename string2 to string1])[rename string1 to lev];"); + "res := levenshtein(ds[keep string1], ds[keep string2][rename string2 to string1])[rename string1 to lev];"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Toto", "lev", 3L), diff --git a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/JoinFunctionsTest.java b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/JoinFunctionsTest.java index e79293263..f18c03612 100644 --- a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/JoinFunctionsTest.java +++ b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/JoinFunctionsTest.java @@ -137,7 +137,8 @@ public void testLeftJoinWithDifferentIdentifiers() throws ScriptException { result2 := left_join(ds_1_1, ds_2 using Id_2);\ """)) .isInstanceOf(InvalidArgumentException.class) - .hasMessage("using component Id_2 has to be an identifier"); + .hasMessage( + "CALC cannot overwrite IDENTIFIER 'Id_2' (role=IDENTIFIER, type=class java.lang.Long)."); } @Test @@ -230,9 +231,8 @@ public void testLeftJoinMixedStructure() throws ScriptException { engine.getContext().setAttribute("ds1", dataset1, ScriptContext.ENGINE_SCOPE); engine.getContext().setAttribute("ds2", dataset2, ScriptContext.ENGINE_SCOPE); - engine.eval( - "unionData := union(ds1[keep id, measure1, measure2], ds2[keep id, measure1, measure2]);"); - engine.eval("ds1_keep := ds1[keep id, color];"); + engine.eval("unionData := union(ds1[keep measure1, measure2], ds2[keep measure1, measure2]);"); + engine.eval("ds1_keep := ds1[keep color];"); engine.eval("joinData := left_join(unionData, ds1_keep);"); Dataset joinData = (Dataset) engine.getBindings(ScriptContext.ENGINE_SCOPE).get("joinData"); @@ -260,7 +260,7 @@ public void testInnerJoin() throws ScriptException { engine.getContext().setAttribute("ds_1", ds1, ScriptContext.ENGINE_SCOPE); engine.getContext().setAttribute("ds_2", ds2, ScriptContext.ENGINE_SCOPE); - engine.eval("result1 := inner_join(ds_1[keep id1, id2, m1] as ds1, ds_2 as ds2);"); + engine.eval("result1 := inner_join(ds_1[keep m1] as ds1, ds_2 as ds2);"); var result = (Dataset) engine.getContext().getAttribute("result1"); assertThat(result.getColumnNames()).containsExactlyInAnyOrder("id1", "id2", "m1", "m2"); diff --git a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/NumericFunctionsTest.java b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/NumericFunctionsTest.java index d26b9617a..558e1f720 100644 --- a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/NumericFunctionsTest.java +++ b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/NumericFunctionsTest.java @@ -85,7 +85,7 @@ public void testCeil() throws ScriptException { assertThat(context.getAttribute("d")).isEqualTo(0L); context.setAttribute("ds", DatasetSamples.ds2, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := ceil(ds[keep id, long1, double1]);"); + Object res = engine.eval("res := ceil(ds[keep long1, double1]);"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Hadrien", "long1", 150L, "double1", 2L), @@ -112,7 +112,7 @@ public void testFloor() throws ScriptException { assertThat(context.getAttribute("d")).isEqualTo(-1L); context.setAttribute("ds", DatasetSamples.ds2, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := floor(ds[keep id, double1]);"); + Object res = engine.eval("res := floor(ds[keep double1]);"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Hadrien", "double1", 1L), @@ -135,7 +135,7 @@ public void testAbs() throws ScriptException { assertThat(context.getAttribute("b")).isEqualTo(5.5D); context.setAttribute("ds", DatasetSamples.ds2, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := abs(ds[keep id, double1]);"); + Object res = engine.eval("res := abs(ds[keep double1]);"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Hadrien", "double1", 1.1D), @@ -164,7 +164,7 @@ public void testExp() throws ScriptException { assertThat(((Double) context.getAttribute("d"))) .isCloseTo(0.367D, Percentage.withPercentage(1)); context.setAttribute("ds", DatasetSamples.ds2, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := floor(exp(ds[keep id, double1, long1]));"); + Object res = engine.eval("res := floor(exp(ds[keep double1, long1]));"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Hadrien", "double1", 3L, "long1", 9223372036854775807L), @@ -192,7 +192,7 @@ public void testLn() throws ScriptException { .isCloseTo(-0.69D, Percentage.withPercentage(1)); context.setAttribute("ds", DatasetSamples.ds2, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := floor(ln(abs(ds[keep id, double1])));"); + Object res = engine.eval("res := floor(ln(abs(ds[keep double1])));"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Hadrien", "double1", 0L), @@ -221,7 +221,7 @@ public void testRound() throws ScriptException { assertThat(context.getAttribute("e")).isEqualTo(12350D); context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := round(ds[keep id, long1, double2], 1);"); + Object res = engine.eval("res := round(ds[keep long1, double2], 1);"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Toto", "long1", 30.0D, "double2", 1.2D), @@ -258,7 +258,7 @@ public void testTrunc() throws ScriptException { assertThat(context.getAttribute("e")).isEqualTo(12340D); context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := trunc(ds[keep id, long1, double2], 1);"); + Object res = engine.eval("res := trunc(ds[keep long1, double2], 1);"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Toto", "long1", 30.0D, "double2", 1.2D), @@ -289,7 +289,7 @@ public void testSqrt() throws ScriptException { assertThat(context.getAttribute("c")).isEqualTo(0D); context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := round(sqrt(ds[keep id, long1, double2]));"); + Object res = engine.eval("res := round(sqrt(ds[keep long1, double2]));"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Toto", "long1", 5.0D, "double2", 1D), @@ -321,7 +321,7 @@ public void testMod() throws ScriptException { assertThat(context.getAttribute("d")).isEqualTo(9D); context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := trunc(mod(ds[keep id, long1, double2], 2), 1);"); + Object res = engine.eval("res := trunc(mod(ds[keep long1, double2], 2), 1);"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Toto", "long1", 0.0D, "double2", 1.2D), @@ -353,7 +353,7 @@ public void testPower() throws ScriptException { assertThat(context.getAttribute("e")).isEqualTo(-125D); context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := trunc(power(ds[keep id, long1, double2], 2), 1);"); + Object res = engine.eval("res := trunc(power(ds[keep long1, double2], 2), 1);"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Toto", "long1", 900.0D, "double2", 1.4D), @@ -383,7 +383,7 @@ public void testRandom() throws ScriptException { assertThat((Double) context.getAttribute("a")).isCloseTo(0.72D, Percentage.withPercentage(0.2)); context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := trunc(random(ds[keep id, long1], 200), 1);"); + Object res = engine.eval("res := trunc(random(ds[keep long1], 200), 1);"); assertThat(((Dataset) res).getDataStructure().get("long1").getType()).isEqualTo(Double.class); assertThatThrownBy( @@ -410,7 +410,7 @@ public void testLog() throws ScriptException { .isCloseTo(3.01D, Percentage.withPercentage(0.01)); context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := trunc(log(ds[keep id, long1, double2], 2), 1);"); + Object res = engine.eval("res := trunc(log(ds[keep long1, double2], 2), 1);"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Toto", "long1", 4.9D, "double2", 0.2D), diff --git a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/StringFunctionsTest.java b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/StringFunctionsTest.java index d291258b9..516a48c45 100644 --- a/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/StringFunctionsTest.java +++ b/vtl-engine/src/test/java/fr/insee/vtl/engine/visitors/expression/functions/StringFunctionsTest.java @@ -86,12 +86,12 @@ public void testUnaryStringFunction() throws ScriptException { context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); engine.eval( - "dsTrim := trim(ds[keep id, string1]); " - + "dsLTrim := ltrim(ds[keep id, string1]); " - + "dsRTrim := rtrim(ds[keep id, string1]); " - + "dsUpper := upper(ds[keep id, string1]); " - + "dsLower := lower(ds[keep id, string1]); " - + "dsLen := length(ds[keep id, string1]);"); + "dsTrim := trim(ds[keep string1]); " + + "dsLTrim := ltrim(ds[keep string1]); " + + "dsRTrim := rtrim(ds[keep string1]); " + + "dsUpper := upper(ds[keep string1]); " + + "dsLower := lower(ds[keep string1]); " + + "dsLen := length(ds[keep string1]);"); assertThat(((Dataset) context.getAttribute("dsTrim")).getDataAsMap().get(0)) .isEqualTo(Map.of("id", "Toto", "string1", "toto")); assertThat(((Dataset) context.getAttribute("dsLTrim")).getDataAsMap().get(0)) @@ -127,7 +127,7 @@ public void testSubstrAtom() throws ScriptException { assertThat(context.getAttribute("s5")).isEqualTo(""); context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := substr(ds[keep id, string1, string2], 2, 4);"); + Object res = engine.eval("res := substr(ds[keep string1, string2], 2, 4);"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Toto", "string1", "oto", "string2", ""), @@ -146,7 +146,7 @@ public void testReplaceAtom() throws ScriptException { assertThat(context.getAttribute("r2")).isEqualTo("de"); context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := replace(ds[keep id, string1, string2], \"o\", \"O\");"); + Object res = engine.eval("res := replace(ds[keep string1, string2], \"o\", \"O\");"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Toto", "string1", "tOtO", "string2", "t"), @@ -182,7 +182,7 @@ public void testInstrAtom() throws ScriptException { assertThat(context.getAttribute("i4")).isEqualTo(0L); context.setAttribute("ds", DatasetSamples.ds1, ScriptContext.ENGINE_SCOPE); - Object res = engine.eval("res := instr(ds[keep id, string1, string2], \"o\", 0, 2);"); + Object res = engine.eval("res := instr(ds[keep string1, string2], \"o\", 0, 2);"); assertThat(((Dataset) res).getDataAsMap()) .containsExactlyInAnyOrder( Map.of("id", "Toto", "string1", 4L, "string2", 0L),