Skip to content

Commit 011dc74

Browse files
committed
Rename Changes
1 parent 269f3c9 commit 011dc74

File tree

1 file changed

+85
-5
lines changed

1 file changed

+85
-5
lines changed

vtl-engine/src/main/java/fr/insee/vtl/engine/visitors/ClauseVisitor.java

Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -290,18 +290,98 @@ public DatasetExpression visitFilterClause(VtlParser.FilterClauseContext ctx) {
290290

291291
@Override
292292
public DatasetExpression visitRenameClause(VtlParser.RenameClauseContext ctx) {
293+
294+
// Dataset structure in order + lookup maps
295+
final List<Dataset.Component> componentsInOrder =
296+
new ArrayList<>(datasetExpression.getDataStructure().values());
297+
final Set<String> availableColumns =
298+
componentsInOrder.stream()
299+
.map(Dataset.Component::getName)
300+
.collect(Collectors.toCollection(LinkedHashSet::new));
301+
302+
// Map for detailed error reporting (includes role/type if available)
303+
final Map<String, Dataset.Component> byName =
304+
componentsInOrder.stream()
305+
.collect(
306+
Collectors.toMap(
307+
Dataset.Component::getName, c -> c, (a, b) -> a, LinkedHashMap::new));
308+
309+
// Parse the RENAME clause and validate
293310
Map<String, String> fromTo = new LinkedHashMap<>();
294-
Set<String> renamed = new HashSet<>();
311+
Set<String> toSeen = new LinkedHashSet<>();
312+
Set<String> fromSeen = new LinkedHashSet<>();
313+
295314
for (VtlParser.RenameClauseItemContext renameCtx : ctx.renameClauseItem()) {
296-
var toNameString = getName(renameCtx.toName);
297-
var fromNameString = getName(renameCtx.fromName);
298-
if (!renamed.add(toNameString)) {
315+
final String toNameString = getName(renameCtx.toName);
316+
final String fromNameString = getName(renameCtx.fromName);
317+
318+
// Validate: no duplicate "from" names inside the clause
319+
if (!fromSeen.add(fromNameString)) {
299320
throw new VtlRuntimeException(
300321
new InvalidArgumentException(
301-
"duplicate column: %s".formatted(toNameString), fromContext(renameCtx)));
322+
String.format("Error: duplicate source name in RENAME clause: '%s", fromNameString),
323+
fromContext(ctx)));
302324
}
325+
326+
// Validate: "from" must exist in dataset
327+
if (!availableColumns.contains(fromNameString)) {
328+
Dataset.Component comp = byName.get(fromNameString);
329+
String meta =
330+
(comp != null)
331+
? String.format(
332+
" (role=%s, type=%s)",
333+
comp.getRole(), comp.getType() != null ? comp.getType() : "n/a")
334+
: "";
335+
throw new VtlRuntimeException(
336+
new InvalidArgumentException(
337+
String.format(
338+
"Error: source column to rename not found: '%s'%s", fromNameString, meta),
339+
fromContext(ctx)));
340+
}
341+
342+
// Validate: no duplicate "to" names inside the clause
343+
if (!toSeen.add(toNameString)) {
344+
throw new VtlRuntimeException(
345+
new InvalidArgumentException(
346+
String.format(
347+
"Error: duplicate output column name in RENAME clause: '%s.", fromNameString),
348+
fromContext(ctx)));
349+
}
350+
303351
fromTo.put(fromNameString, toNameString);
304352
}
353+
354+
// Validate collisions with untouched dataset columns ("Untouched" = columns that are not
355+
// being renamed)
356+
final Set<String> untouched =
357+
availableColumns.stream()
358+
.filter(c -> !fromTo.containsKey(c))
359+
.collect(Collectors.toCollection(LinkedHashSet::new));
360+
361+
for (Map.Entry<String, String> e : fromTo.entrySet()) {
362+
final String from = e.getKey();
363+
final String to = e.getValue();
364+
365+
// If target already exists as untouched, it would cause a collision
366+
if (untouched.contains(to)) {
367+
Dataset.Component comp = byName.get(to);
368+
String meta =
369+
(comp != null)
370+
? String.format(
371+
" (role=%s, type=%s)",
372+
comp.getRole(), comp.getType() != null ? comp.getType() : "n/a")
373+
: "";
374+
375+
throw new VtlRuntimeException(
376+
new InvalidArgumentException(
377+
String.format(
378+
"Error: target name '%s'%s already exists in dataset and is not being renamed.",
379+
to, meta),
380+
fromContext(ctx)));
381+
}
382+
}
383+
384+
// Execute rename in processing engine
305385
return processingEngine.executeRename(datasetExpression, fromTo);
306386
}
307387

0 commit comments

Comments
 (0)