From d57dcdbb85cc9bef60e8b563235ef4ad9723ae2d Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Wed, 21 Aug 2024 14:18:18 +0200 Subject: [PATCH] [jOOQ/jOOQ#17099] [jOOQ/jOOQ#17117] Code generation escaping issues This includes: - [jOOQ/jOOQ#17099] KotlinGenerator contains incomplete list of Kotlin forbidden identifier characters - [jOOQ/jOOQ#17117] Bad code generated for enum values containing backslash character --- .../java/org/jooq/codegen/GenerationUtil.java | 34 +++++++++++++------ .../java/org/jooq/codegen/JavaGenerator.java | 6 ++-- .../java/org/jooq/impl/InsertQueryImpl.java | 2 +- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/jOOQ-codegen/src/main/java/org/jooq/codegen/GenerationUtil.java b/jOOQ-codegen/src/main/java/org/jooq/codegen/GenerationUtil.java index 47f5dc8e0b..4b30f1b544 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/codegen/GenerationUtil.java +++ b/jOOQ-codegen/src/main/java/org/jooq/codegen/GenerationUtil.java @@ -358,19 +358,31 @@ class GenerationUtil { * Check if a character can be used in a kotlin identifier. *

* See https://kotlinlang.org/spec/syntax-and-grammar.html#grammar-rule-QuotedSymbol + * "https://kotlinlang.org/docs/reference/grammar.html#Identifier">https://kotlinlang.org/docs/reference/grammar.html#Identifier */ private static boolean isKotlinIdentifierPart(char c) { - return c != '\r' - && c != '\n' - && c != '`' - && c != '(' - && c != ')' - && c != '{' - && c != '}' - && c != '[' - && c != ']' - && c != '.'; + switch (c) { + case '\r': + case '\n': + case '`': + case '.': + case ';': + case ':': + case '\\': + case '/': + case '[': + case ']': + // [#17099] These used to be listed, but aren't actually forbidden: + // case '(': + // case ')': + // case '{': + // case '}': + case '<': + case '>': + return false; + default: + return true; + } } /** diff --git a/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java b/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java index 2a0c515e7c..709ce90652 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java +++ b/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java @@ -4158,7 +4158,7 @@ public class JavaGenerator extends AbstractGenerator { out.println("def valueOf(s: %s): %s = s match {", String.class, className); for (int i = 0; i < identifiers.size(); i++) { - out.println("case \"%s\" => %s", literals.get(i), identifiers.get(i)); + out.println("case \"%s\" => %s", escapeString(literals.get(i)), identifiers.get(i)); } out.println("case _ => throw new %s()", IllegalArgumentException.class); out.println("}"); @@ -4199,7 +4199,7 @@ public class JavaGenerator extends AbstractGenerator { out.println("%senum class %s(@get:JvmName(\"literal\") public val literal: String)[[before= : ][%s]] {", visibility(), className, interfaces); for (int i = 0; i < literals.size(); i++) - out.println("%s(\"%s\")%s", identifiers.get(i), literals.get(i), (i == literals.size() - 1) ? ";" : ","); + out.println("%s(\"%s\")%s", identifiers.get(i), escapeString(literals.get(i)), (i == literals.size() - 1) ? ";" : ","); out.println("%soverride fun getCatalog(): %s? = %s", visibilityPublic(), Catalog.class, noCatalog ? "null" : "schema.catalog"); @@ -4222,7 +4222,7 @@ public class JavaGenerator extends AbstractGenerator { for (int i = 0; i < literals.size(); i++) { out.println(); - out.println("%s(\"%s\")%s", identifiers.get(i), literals.get(i), (i == literals.size() - 1) ? ";" : ","); + out.println("%s(\"%s\")%s", identifiers.get(i), escapeString(literals.get(i)), (i == literals.size() - 1) ? ";" : ","); } out.println(); diff --git a/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java index f001bbcbca..bfebfe837d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/InsertQueryImpl.java @@ -1176,7 +1176,7 @@ implements Condition and = null; for (Field field : fields) { - Field f = (Field) field; + Field f = (Field) orElse(table().field(field), () -> field); Condition other = matchByConflictingKey(ctx, f, s.field(f)); and = (and == null) ? other : and.and(other); }