From 11ce2ec1cf291f86de3656ea262436dae411ab76 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 9 Dec 2024 19:41:11 +0100 Subject: [PATCH] [jOOQ/jOOQ#14005] Code generator produces wrong ordering of DataType properties for nullable and defaulted array types --- .../java/org/jooq/codegen/JavaGenerator.java | 95 +++++++++++++++---- 1 file changed, 78 insertions(+), 17 deletions(-) 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 2591e4cdc7..3f8397bd23 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java +++ b/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java @@ -11439,24 +11439,43 @@ public class JavaGenerator extends AbstractGenerator { } protected String getJavaTypeReference(Database db, DataTypeDefinition type, JavaWriter out) { - - // [#4388] TODO: Improve array handling if (database.isArrayType(type.getType())) { - DataTypeDefinition base = GenerationUtil.getArrayBaseType(db.getDialect(), type); + DataTypeDefinition t; + DataTypeDefinition base = type; - // [#252] This check prevents StackOverflowError in case of e.g. PostgreSQL ANYARRAY types - if (base != type) - return getJavaTypeReference(db, base, out) + ".array()"; - else - return getJavaTypeReference0(db, type, out) + ".array()"; + do + base = GenerationUtil.getArrayBaseType(db.getDialect(), t = base); + while (base != t); + + return getJavaTypeReference0(db, base, out, arrayAppender(type)); } else - return getJavaTypeReference0(db, type, out); + return getJavaTypeReference0(db, type, out, arrayAppender(type)); } - private String getJavaTypeReference0(Database db, DataTypeDefinition type, JavaWriter out) { - return getTypeReference( + private Consumer arrayAppender(DataTypeDefinition type) { + if (database.isArrayType(type.getType())) { + DataTypeDefinition base = GenerationUtil.getArrayBaseType(database.getDialect(), type); + + // [#252] This check prevents StackOverflowError in case of e.g. PostgreSQL ANYARRAY types + if (base != type) + return sb -> arrayAppender(base).accept(sb.append(".array()")); + else + return sb -> sb.append(".array()"); + } + + else + return sb -> {}; + } + + private String getJavaTypeReference0( + Database db, + DataTypeDefinition type, + JavaWriter out, + Consumer arrayAppender + ) { + return getTypeReference0( db, type.getSchema(), out, @@ -11472,7 +11491,8 @@ public class JavaGenerator extends AbstractGenerator { type.getGenerationOption(), type.getGenerator(), type.getDefaultValue(), - type.getQualifiedUserType() + type.getQualifiedUserType(), + arrayAppender ); } @@ -11839,6 +11859,7 @@ public class JavaGenerator extends AbstractGenerator { } } + @Deprecated protected String getTypeReference( Database db, SchemaDefinition schema, @@ -11856,6 +11877,30 @@ public class JavaGenerator extends AbstractGenerator { String ge, String d, Name u + ) { + return getTypeReference0( + db, schema, out, t, p, s, l, n, i, h, r, g, go, ge, d, u, x -> {} + ); + } + + private String getTypeReference0( + Database db, + SchemaDefinition schema, + JavaWriter out, + String t, + int p, + int s, + int l, + boolean n, + boolean i, + boolean h, + boolean r, + String g, + GenerationOption go, + String ge, + String d, + Name u, + Consumer arrayAppender ) { StringBuilder sb = new StringBuilder(); @@ -11871,18 +11916,23 @@ public class JavaGenerator extends AbstractGenerator { final String sqlDataTypeRef = out.ref(getStrategy().getFullJavaIdentifier(db.getDomain(schema, u)), domainRefSegments()) + ".getDataType()"; sb.append(sqlDataTypeRef); + arrayAppender.accept(sb); appendTypeReferenceNullability(db, out, sb, n); - appendTypeReferenceDefault(db, out, sb, d, sqlDataTypeRef); + appendTypeReferenceDefault(db, out, sb, d, sqlDataTypeRef, arrayAppender); } else if (db.getUDT(schema, u) != null) { sb.append(out.ref(getStrategy().getFullJavaIdentifier(db.getUDT(schema, u)), 2)); + appendGetDataTypeCall(sb); + arrayAppender.accept(sb); } // [#3942] [#7863] Dialects that support tables as UDTs // [#5334] In MySQL, the user type is (ab)used for synthetic enum types. This can lead to accidental matches here else if (SUPPORT_TABLE_AS_UDT.contains(db.getDialect()) && db.getTable(schema, u) != null) { sb.append(out.ref(getStrategy().getFullJavaIdentifier(db.getTable(schema, u)), 2)); + appendGetDataTypeCall(sb); + arrayAppender.accept(sb); } else if (db.getEnum(schema, u) != null) { sb.append(getJavaTypeReference(db, new DefaultDataTypeDefinition( @@ -11894,6 +11944,8 @@ public class JavaGenerator extends AbstractGenerator { sb.append(".asEnumDataType("); sb.append(classOf(out.ref(getStrategy().getFullJavaClassName(db.getEnum(schema, u), Mode.ENUM)))); sb.append(")"); + + arrayAppender.accept(sb); } else { DataType dataType; @@ -11968,6 +12020,7 @@ public class JavaGenerator extends AbstractGenerator { sb.append(sqlDataTypeRef); } + arrayAppender.accept(sb); appendTypeReferenceNullability(db, out, sb, n); if (dataType.identity()) @@ -12001,7 +12054,7 @@ public class JavaGenerator extends AbstractGenerator { // [#5291] Some dialects report valid SQL expresions (e.g. PostgreSQL), others // report actual values (e.g. MySQL). if (dataType.defaulted()) - appendTypeReferenceDefault(db, out, sb, d, sqlDataTypeRef); + appendTypeReferenceDefault(db, out, sb, d, sqlDataTypeRef, arrayAppender); } return sb.toString(); @@ -12023,7 +12076,14 @@ public class JavaGenerator extends AbstractGenerator { private static final Pattern P_TS_EXPRESSION = Pattern.compile("^(?i:current_(date|timestamp).*)$"); - private final void appendTypeReferenceDefault(Database db, JavaWriter out, StringBuilder sb, String d, String sqlDataTypeRef) { + private final void appendTypeReferenceDefault( + Database db, + JavaWriter out, + StringBuilder sb, + String d, + String sqlDataTypeRef, + Consumer arrayAppender + ) { if (d != null) { sb.append(".defaultValue("); @@ -12054,8 +12114,9 @@ public class JavaGenerator extends AbstractGenerator { .append("\")"); sb.append(", ") - .append(sqlDataTypeRef) - .append(")") + .append(sqlDataTypeRef); + arrayAppender.accept(sb); + sb.append(")") .append(kotlin && sqlDataTypeRef.contains(".OTHER") ? " as Any?" : "") .append(")"); }