@@ -279,19 +279,27 @@ public DatasetExpression visitFilterClause(VtlParser.FilterClauseContext ctx) {
279279 public DatasetExpression visitRenameClause (VtlParser .RenameClauseContext ctx ) {
280280
281281 // Dataset structure in order + lookup maps
282- final List <Dataset .Component > componentsInOrder =
283- new ArrayList <>(datasetExpression .getDataStructure ().values ());
284- final Set <String > availableColumns =
285- componentsInOrder .stream ()
286- .map (Dataset .Component ::getName )
287- .collect (Collectors .toCollection (LinkedHashSet ::new ));
282+ //final List<Dataset.Component> componentsInOrder =
283+ // new ArrayList<>(datasetExpression.getDataStructure().values());
284+ // final Set<String> availableColumns =
285+ // componentsInOrder.stream()
286+ // .map(Dataset.Component::getName)
287+ // .collect(Collectors.toCollection(LinkedHashSet::new));
288+
289+ var structure = datasetExpression .getDataStructure ();
288290
289291 // Parse the RENAME clause and validate
290292 Map <String , String > fromTo = new LinkedHashMap <>();
291293 Set <String > toSeen = new LinkedHashSet <>();
292294 Set <String > fromSeen = new LinkedHashSet <>();
293295
296+ Map <String , ParserRuleContext > toCtxMap = new HashMap <>();
297+ Map <String , ParserRuleContext > fromCtxMap = new HashMap <>();
298+
294299 for (VtlParser .RenameClauseItemContext renameCtx : ctx .renameClauseItem ()) {
300+ toCtxMap .put (getName (renameCtx .toName ), renameCtx .toName );
301+ fromCtxMap .put (getName (renameCtx .fromName ), renameCtx .fromName );
302+
295303 final String toNameString = getName (renameCtx .toName );
296304 final String fromNameString = getName (renameCtx .fromName );
297305
@@ -304,7 +312,7 @@ public DatasetExpression visitRenameClause(VtlParser.RenameClauseContext ctx) {
304312 }
305313
306314 // Validate: "from" must exist in dataset
307- if (!availableColumns . contains (fromNameString )) {
315+ if (!structure . containsKey (fromNameString )) {
308316 throw new VtlRuntimeException (
309317 new UndefinedVariableException (toPositioned (renameCtx .fromName ), datasetExpression ));
310318 }
@@ -318,10 +326,10 @@ public DatasetExpression visitRenameClause(VtlParser.RenameClauseContext ctx) {
318326 fromTo .put (fromNameString , toNameString );
319327 }
320328
321- // Validate collisions with untouched dataset columns ("Untouched" = columns that are not
322- // being renamed)
329+ // Check that the renamed columns do not collide with the remaining columns. This
330+ // is done so that swapping variables works: a -> b, b -> a.
323331 final Set <String > untouched =
324- availableColumns .stream ()
332+ structure . keySet () .stream ()
325333 .filter (c -> !fromTo .containsKey (c ))
326334 .collect (Collectors .toCollection (LinkedHashSet ::new ));
327335
@@ -331,20 +339,12 @@ public DatasetExpression visitRenameClause(VtlParser.RenameClauseContext ctx) {
331339
332340 // If target already exists as untouched, it would cause a collision
333341 if (untouched .contains (to )) {
334- Dataset .Component comp = datasetExpression .getDataStructure ().get (to );
335- String meta =
336- (comp != null )
337- ? String .format (
338- " (role=%s, type=%s)" ,
339- comp .getRole (), comp .getType () != null ? comp .getType () : "n/a" )
340- : "" ;
341-
342342 throw new VtlRuntimeException (
343- new InvalidArgumentException (
344- String . format (
345- "Error: target name '%s'%s already exists in dataset and is not being renamed." ,
346- to , meta ),
347- fromContext ( ctx )) );
343+ new AlreadyDefinedException (
344+ toPositioned ( toCtxMap . get ( to )),
345+ datasetExpression
346+ )
347+ );
348348 }
349349 }
350350
0 commit comments