[jOOQ/jOOQ#10576] Compilation error when 2 Oracle packages both contain the same record type name

This commit is contained in:
Lukas Eder 2020-09-02 16:10:08 +02:00
parent c02b69eb2d
commit 387912cbd1
9 changed files with 143 additions and 91 deletions

View File

@ -68,8 +68,8 @@ public abstract class AbstractGeneratorStrategy implements GeneratorStrategy {
// -------------------------------------------------------------------------
@Override
public final String getGlobalReferencesFileName(SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
return getGlobalReferencesJavaClassName(containingSchema, objectType) + ".java";
public final String getGlobalReferencesFileName(Definition container, Class<? extends Definition> objectType) {
return getGlobalReferencesJavaClassName(container, objectType) + ".java";
}
@Override
@ -90,10 +90,10 @@ public abstract class AbstractGeneratorStrategy implements GeneratorStrategy {
}
@Override
public final File getGlobalReferencesFile(SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
public final File getGlobalReferencesFile(Definition container, Class<? extends Definition> objectType) {
String dir = getTargetDirectory();
String pkg = getGlobalReferencesJavaPackageName(containingSchema, objectType).replaceAll("\\.", "/");
return new File(dir + "/" + pkg, getGlobalReferencesFileName(containingSchema, objectType));
String pkg = getGlobalReferencesJavaPackageName(container, objectType).replaceAll("\\.", "/");
return new File(dir + "/" + pkg, getGlobalReferencesFileName(container, objectType));
}
@Override
@ -204,8 +204,8 @@ public abstract class AbstractGeneratorStrategy implements GeneratorStrategy {
}
@Override
public final String getGlobalReferencesFullJavaClassName(SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
return getGlobalReferencesJavaPackageName(containingSchema, objectType) + "." + getGlobalReferencesJavaClassName(containingSchema, objectType);
public final String getGlobalReferencesFullJavaClassName(Definition container, Class<? extends Definition> objectType) {
return getGlobalReferencesJavaPackageName(container, objectType) + "." + getGlobalReferencesJavaClassName(container, objectType);
}
@Override

View File

@ -48,6 +48,7 @@ import static org.jooq.SQLDialect.MYSQL;
import static org.jooq.SQLDialect.POSTGRES;
// ...
// ...
import static org.jooq.codegen.AbstractGenerator.Language.KOTLIN;
import java.util.ArrayList;
import java.util.List;
@ -160,7 +161,7 @@ public class DefaultGeneratorStrategy extends AbstractGeneratorStrategy {
// -------------------------------------------------------------------------
@Override
public String getGlobalReferencesFileHeader(SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
public String getGlobalReferencesFileHeader(Definition container, Class<? extends Definition> objectType) {
return "This file is generated by jOOQ.";
}
@ -268,7 +269,7 @@ public class DefaultGeneratorStrategy extends AbstractGeneratorStrategy {
}
@Override
public String getGlobalReferencesJavaClassExtends(SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
public String getGlobalReferencesJavaClassExtends(Definition container, Class<? extends Definition> objectType) {
return null;
}
@ -278,7 +279,7 @@ public class DefaultGeneratorStrategy extends AbstractGeneratorStrategy {
}
@Override
public List<String> getGlobalReferencesJavaClassImplements(SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
public List<String> getGlobalReferencesJavaClassImplements(Definition container, Class<? extends Definition> objectType) {
return new ArrayList<>();
}
@ -288,7 +289,7 @@ public class DefaultGeneratorStrategy extends AbstractGeneratorStrategy {
}
@Override
public String getGlobalReferencesJavaClassName(SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
public String getGlobalReferencesJavaClassName(Definition container, Class<? extends Definition> objectType) {
if (ArrayDefinition.class.isAssignableFrom(objectType))
return "Arrays";
else if (ConstraintDefinition.class.isAssignableFrom(objectType))
@ -336,27 +337,25 @@ public class DefaultGeneratorStrategy extends AbstractGeneratorStrategy {
}
@Override
public String getGlobalReferencesJavaPackageName(SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
String packageName = getJavaPackageName(containingSchema);
public String getGlobalReferencesJavaPackageName(Definition container, Class<? extends Definition> objectType) {
String packageName = getJavaPackageName(container);
switch (targetLanguage) {
case KOTLIN: {
String className = getGlobalReferencesJavaClassName(containingSchema, objectType).toLowerCase(targetLocale);
if (container instanceof PackageDefinition)
packageName = packageName + "." + getJavaIdentifier(container).toLowerCase(targetLocale);
// Repeat the package name for global references to prevent collisions
if (TableDefinition.class.isAssignableFrom(objectType))
return packageName + "." + className + ".references";
else if (RoutineDefinition.class.isAssignableFrom(objectType))
return packageName + "." + className + ".references";
else
return packageName + "." + className;
}
if (targetLanguage == KOTLIN) {
String className = getGlobalReferencesJavaClassName(container, objectType).toLowerCase(targetLocale);
case JAVA:
case SCALA:
default:
return packageName;
// Repeat the package name for global references to prevent collisions
if (TableDefinition.class.isAssignableFrom(objectType))
packageName = packageName + "." + className + ".references";
else if (RoutineDefinition.class.isAssignableFrom(objectType))
packageName = packageName + "." + className + ".references";
else
packageName = packageName + "." + className;
}
return packageName;
}
@Override
@ -382,9 +381,10 @@ public class DefaultGeneratorStrategy extends AbstractGeneratorStrategy {
if (!(definition instanceof SchemaDefinition)) {
// Some definitions have their dedicated subpackages, e.g. "tables", "routines"
if (!StringUtils.isBlank(getSubPackage(definition))) {
String subPackage = getSubPackage(definition);
if (!StringUtils.isBlank(subPackage)) {
sb.append(".");
sb.append(getSubPackage(definition));
sb.append(subPackage);
}
// Record are yet in another subpackage

View File

@ -50,7 +50,6 @@ import org.jooq.meta.DomainDefinition;
import org.jooq.meta.EnumDefinition;
import org.jooq.meta.ParameterDefinition;
import org.jooq.meta.RoutineDefinition;
import org.jooq.meta.SchemaDefinition;
import org.jooq.meta.TableDefinition;
import org.jooq.meta.UDTDefinition;
@ -246,7 +245,7 @@ public interface GeneratorStrategy {
* <code>null</code> or an empty string, then no super class is
* extended.
*/
String getGlobalReferencesJavaClassExtends(SchemaDefinition containingSchema, Class<? extends Definition> objectType);
String getGlobalReferencesJavaClassExtends(Definition container, Class<? extends Definition> objectType);
/**
* This is the same as calling
@ -273,7 +272,7 @@ public interface GeneratorStrategy {
* returns <code>null</code> or an empty list, then no interfaces
* are implemented.
*/
List<String> getGlobalReferencesJavaClassImplements(SchemaDefinition containingSchema, Class<? extends Definition> objectType);
List<String> getGlobalReferencesJavaClassImplements(Definition container, Class<? extends Definition> objectType);
/**
* This is the same as calling
@ -298,7 +297,7 @@ public interface GeneratorStrategy {
* @return The Java class name of the global references class for a given
* definition type, e.g. [MyTableSuffix]
*/
String getGlobalReferencesJavaClassName(SchemaDefinition containingSchema, Class<? extends Definition> objectType);
String getGlobalReferencesJavaClassName(Definition container, Class<? extends Definition> objectType);
/**
* This is the same as calling
@ -318,7 +317,7 @@ public interface GeneratorStrategy {
* @return The Java package name of the global references class for a given
* definition type, e.g. [org.jooq.generated]
*/
String getGlobalReferencesJavaPackageName(SchemaDefinition containingSchema, Class<? extends Definition> objectType);
String getGlobalReferencesJavaPackageName(Definition container, Class<? extends Definition> objectType);
/**
* This is the same as calling
@ -369,7 +368,7 @@ public interface GeneratorStrategy {
* @return The full Java class name of the global references class for a
* given definition type, e.g. [org.jooq.generated.MyTable]
*/
String getGlobalReferencesFullJavaClassName(SchemaDefinition containingSchema, Class<? extends Definition> objectType);
String getGlobalReferencesFullJavaClassName(Definition container, Class<? extends Definition> objectType);
/**
* @return The full Java class name representing this object, e.g.
@ -390,7 +389,7 @@ public interface GeneratorStrategy {
* @return The Java class file name of the global references class for a
* given definition type, e.g. [MyTable.java]
*/
String getGlobalReferencesFileName(SchemaDefinition containingSchema, Class<? extends Definition> objectType);
String getGlobalReferencesFileName(Definition container, Class<? extends Definition> objectType);
/**
* @return The Java class file name representing this object, e.g.
@ -414,7 +413,7 @@ public interface GeneratorStrategy {
* @return The Java class file name of the global references class for a
* given definition type, e.g. [C:\org\jooq\generated\MyTable.java]
*/
File getGlobalReferencesFile(SchemaDefinition containingSchema, Class<? extends Definition> objectType);
File getGlobalReferencesFile(Definition container, Class<? extends Definition> objectType);
/**
* @return The Java class file name representing this object, e.g.
@ -440,7 +439,7 @@ public interface GeneratorStrategy {
* This file is generated by jOOQ.
* </pre></code>
*/
String getGlobalReferencesFileHeader(SchemaDefinition containingSchema, Class<? extends Definition> objectType);
String getGlobalReferencesFileHeader(Definition container, Class<? extends Definition> objectType);
/**
* @return The Java class file header, e.g. <code><pre>

View File

@ -150,8 +150,8 @@ class GeneratorStrategyWrapper extends AbstractGeneratorStrategy {
}
@Override
public String getGlobalReferencesFileHeader(SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
return delegate.getGlobalReferencesFileHeader(containingSchema, objectType);
public String getGlobalReferencesFileHeader(Definition container, Class<? extends Definition> objectType) {
return delegate.getGlobalReferencesFileHeader(container, objectType);
}
@Override
@ -325,8 +325,8 @@ class GeneratorStrategyWrapper extends AbstractGeneratorStrategy {
}
@Override
public String getGlobalReferencesJavaClassExtends(SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
return delegate.getGlobalReferencesJavaClassExtends(containingSchema, objectType);
public String getGlobalReferencesJavaClassExtends(Definition container, Class<? extends Definition> objectType) {
return delegate.getGlobalReferencesJavaClassExtends(container, objectType);
}
@Override
@ -337,8 +337,8 @@ class GeneratorStrategyWrapper extends AbstractGeneratorStrategy {
}
@Override
public List<String> getGlobalReferencesJavaClassImplements(SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
return delegate.getGlobalReferencesJavaClassImplements(containingSchema, objectType);
public List<String> getGlobalReferencesJavaClassImplements(Definition container, Class<? extends Definition> objectType) {
return delegate.getGlobalReferencesJavaClassImplements(container, objectType);
}
@Override
@ -364,8 +364,8 @@ class GeneratorStrategyWrapper extends AbstractGeneratorStrategy {
}
@Override
public String getGlobalReferencesJavaClassName(SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
return fixJavaClassName(delegate.getGlobalReferencesJavaClassName(containingSchema, objectType));
public String getGlobalReferencesJavaClassName(Definition container, Class<? extends Definition> objectType) {
return fixJavaClassName(delegate.getGlobalReferencesJavaClassName(container, objectType));
}
@Override
@ -394,8 +394,8 @@ class GeneratorStrategyWrapper extends AbstractGeneratorStrategy {
}
@Override
public String getGlobalReferencesJavaPackageName(SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
return fixJavaPackageName(delegate.getGlobalReferencesJavaPackageName(containingSchema, objectType));
public String getGlobalReferencesJavaPackageName(Definition container, Class<? extends Definition> objectType) {
return fixJavaPackageName(delegate.getGlobalReferencesJavaPackageName(container, objectType));
}
@Override

View File

@ -775,8 +775,6 @@ public class JavaGenerator extends AbstractGenerator {
@ -2609,7 +2607,8 @@ public class JavaGenerator extends AbstractGenerator {
for (UDTDefinition udt : database.getUDTs(schema)) {
try {
generateUDT(schema, udt);
} catch (Exception e) {
}
catch (Exception e) {
log.error("Error while generating udt " + udt, e);
}
}
@ -2798,7 +2797,8 @@ public class JavaGenerator extends AbstractGenerator {
for (UDTDefinition udt : database.getUDTs(schema)) {
try {
generateUDTInterface(udt);
} catch (Exception e) {
}
catch (Exception e) {
log.error("Error while generating UDT interface " + udt, e);
}
}
@ -2831,7 +2831,8 @@ public class JavaGenerator extends AbstractGenerator {
for (UDTDefinition udt : database.getUDTs(schema)) {
try {
generateUDTRecord(udt);
} catch (Exception e) {
}
catch (Exception e) {
log.error("Error while generating UDT record " + udt, e);
}
}
@ -2864,7 +2865,8 @@ public class JavaGenerator extends AbstractGenerator {
for (RoutineDefinition routine : udt.getRoutines()) {
try {
generateRoutine(schema, routine);
} catch (Exception e) {
}
catch (Exception e) {
log.error("Error while generating member routines " + routine, e);
}
}
@ -2880,17 +2882,18 @@ public class JavaGenerator extends AbstractGenerator {
/**
* Generating central static udt access
*/
protected void generateUDTReferences(SchemaDefinition schema) {
log.info("Generating UDT references");
JavaWriter out = newJavaWriter(getStrategy().getGlobalReferencesFile(schema, UDTDefinition.class));
printGlobalReferencesPackage(out, schema, UDTDefinition.class);
protected void generateUDTReferences(Definition schemaOrPackage) {
String logSuffix = schemaOrPackage instanceof SchemaDefinition ? "" : (" for package " + schemaOrPackage.getOutputName());
log.info("Generating UDT references" + logSuffix);
JavaWriter out = newJavaWriter(getStrategy().getGlobalReferencesFile(schemaOrPackage, UDTDefinition.class));
printGlobalReferencesPackage(out, schemaOrPackage, UDTDefinition.class);
if (!kotlin) {
printClassJavadoc(out, "Convenience access to all UDTs in " + schemaNameOrDefault(schema) + ".");
printClassAnnotations(out, schema, Mode.DEFAULT);
printClassJavadoc(out, "Convenience access to all UDTs in " + schemaNameOrDefault(schemaOrPackage) + ".");
printClassAnnotations(out, schemaOrPackage, Mode.DEFAULT);
}
final String referencesClassName = getStrategy().getGlobalReferencesJavaClassName(schema, UDTDefinition.class);
final String referencesClassName = getStrategy().getGlobalReferencesJavaClassName(schemaOrPackage, UDTDefinition.class);
if (scala)
out.println("object %s {", referencesClassName);
@ -2898,33 +2901,54 @@ public class JavaGenerator extends AbstractGenerator {
else
out.println("public class %s {", referencesClassName);
for (UDTDefinition udt : database.getUDTs(schema)) {
List<UDTDefinition> udts = new ArrayList<>();
if (schemaOrPackage instanceof SchemaDefinition) {
for (UDTDefinition udt : database.getUDTs((SchemaDefinition) schemaOrPackage))
if (udt.getPackage() == null)
udts.add(udt);
}
else
udts.addAll(database.getUDTs((PackageDefinition) schemaOrPackage));
for (UDTDefinition udt : udts) {
final String className = out.ref(getStrategy().getFullJavaClassName(udt));
final String id = getStrategy().getJavaIdentifier(udt);
final String fullId = getStrategy().getFullJavaIdentifier(udt);
out.javadoc("The type <code>%s</code>", udt.getQualifiedOutputName());
if (scala)
if (scala || kotlin)
out.println("val %s = %s", id, fullId);
else
out.println("public static final %s %s = %s;", className, id, fullId);
}
generateUDTReferencesClassFooter(schema, out);
generateUDTReferencesClassFooter(schemaOrPackage, out);
if (!kotlin)
out.println("}");
closeJavaWriter(out);
watch.splitInfo("UDT references generated");
watch.splitInfo("UDT references generated" + logSuffix);
if (schemaOrPackage instanceof SchemaDefinition)
for (PackageDefinition pkg : database.getPackages((SchemaDefinition) schemaOrPackage))
if (!pkg.getUDTs().isEmpty())
generateUDTReferences(pkg);
}
/**
* Subclasses may override this method to provide UDT references class footer code.
*/
@SuppressWarnings("unused")
protected void generateUDTReferencesClassFooter(SchemaDefinition schema, JavaWriter out) {}
protected void generateUDTReferencesClassFooter(Definition schemaOrPackage, JavaWriter out) {}
/**
* Subclasses may override this method to provide UDT references class footer code.
*/
@SuppressWarnings("unused")
protected void generateUDTReferencesClassFooter(PackageDefinition pkg, JavaWriter out) {}
/**
* Generating central static domain access
@ -3655,7 +3679,7 @@ public class JavaGenerator extends AbstractGenerator {
@SuppressWarnings("unused")
protected void generateTableReferencesClassFooter(SchemaDefinition schema, JavaWriter out) {}
private String schemaNameOrDefault(SchemaDefinition schema) {
private String schemaNameOrDefault(Definition schema) {
return StringUtils.isEmpty(schema.getOutputName()) ? "the default schema" : schema.getOutputName();
}
@ -7697,10 +7721,10 @@ public class JavaGenerator extends AbstractGenerator {
out.println();
}
protected void printGlobalReferencesPackage(JavaWriter out, SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
printGlobalReferencesPackageComment(out, containingSchema, objectType);
protected void printGlobalReferencesPackage(JavaWriter out, Definition container, Class<? extends Definition> objectType) {
printGlobalReferencesPackageComment(out, container, objectType);
out.printPackageSpecification(getStrategy().getGlobalReferencesJavaPackageName(containingSchema, objectType));
out.printPackageSpecification(getStrategy().getGlobalReferencesJavaPackageName(container, objectType));
out.println();
out.printImports();
out.println();
@ -7716,8 +7740,8 @@ public class JavaGenerator extends AbstractGenerator {
}
}
protected void printGlobalReferencesPackageComment(JavaWriter out, SchemaDefinition containingSchema, Class<? extends Definition> objectType) {
String header = getStrategy().getGlobalReferencesFileHeader(containingSchema, objectType);
protected void printGlobalReferencesPackageComment(JavaWriter out, Definition container, Class<? extends Definition> objectType) {
String header = getStrategy().getGlobalReferencesFileHeader(container, objectType);
if (!StringUtils.isBlank(header)) {
out.println("/*");

View File

@ -222,6 +222,7 @@ public abstract class AbstractDatabase implements Database {
private transient Map<SchemaDefinition, List<EnumDefinition>> enumsBySchema;
private transient Map<SchemaDefinition, List<DomainDefinition>> domainsBySchema;
private transient Map<SchemaDefinition, List<UDTDefinition>> udtsBySchema;
private transient Map<PackageDefinition, List<UDTDefinition>> udtsByPackage;
private transient Map<SchemaDefinition, List<ArrayDefinition>> arraysBySchema;
private transient Map<SchemaDefinition, List<RoutineDefinition>> routinesBySchema;
private transient Map<SchemaDefinition, List<PackageDefinition>> packagesBySchema;
@ -2224,7 +2225,8 @@ public abstract class AbstractDatabase implements Database {
return getDefinition(getArrays(schema), name, ignoreCase);
}
private final List<UDTDefinition> getAllUDTs(SchemaDefinition schema) {
@Override
public final List<UDTDefinition> getUDTs() {
if (udts == null) {
udts = new ArrayList<>();
@ -2243,25 +2245,15 @@ public abstract class AbstractDatabase implements Database {
log.info("UDTs excluded");
}
if (udtsBySchema == null)
udtsBySchema = new LinkedHashMap<>();
return filterSchema(udts, schema, udtsBySchema);
}
private final List<UDTDefinition> ifInPackage(List<UDTDefinition> allUDTs, boolean expected) {
List<UDTDefinition> result = new ArrayList<>();
for (UDTDefinition u : allUDTs)
if ((u.getPackage() != null) == expected)
result.add(u);
return result;
return udts;
}
@Override
public final List<UDTDefinition> getUDTs(SchemaDefinition schema) {
return getAllUDTs(schema);
if (udtsBySchema == null)
udtsBySchema = new LinkedHashMap<>();
return filterSchema(getUDTs(), schema, udtsBySchema);
}
@Override
@ -2286,7 +2278,10 @@ public abstract class AbstractDatabase implements Database {
@Override
public final List<UDTDefinition> getUDTs(PackageDefinition pkg) {
return ifInPackage(getAllUDTs(pkg.getSchema()), true);
if (udtsByPackage == null)
udtsByPackage = new LinkedHashMap<>();
return filterPackage(getUDTs(), pkg, udtsByPackage);
}
@Override
@ -2465,7 +2460,29 @@ public abstract class AbstractDatabase implements Database {
List<T> result = new ArrayList<>();
for (T definition : definitions)
if (definition.getSchema().equals(schema))
if (definition.getSchema() != null && definition.getSchema().equals(schema))
result.add(definition);
return result;
}
protected final <T extends Definition> List<T> filterPackage(List<T> definitions, PackageDefinition pkg, Map<PackageDefinition, List<T>> cache) {
List<T> result = cache.get(pkg);
if (result == null)
cache.put(pkg, result = filterPackage(definitions, pkg));
return result;
}
protected final <T extends Definition> List<T> filterPackage(List<T> definitions, PackageDefinition pkg) {
if (pkg == null)
return definitions;
List<T> result = new ArrayList<>();
for (T definition : definitions)
if (definition.getPackage() != null && definition.getPackage().equals(pkg))
result.add(definition);
return result;

View File

@ -113,6 +113,7 @@ public abstract class AbstractDefinition implements Definition {
return result;
}
@Override
public final PackageDefinition getPackage() {
return pkg;
}

View File

@ -249,6 +249,11 @@ public interface Database extends AutoCloseable {
*/
DomainDefinition getDomain(SchemaDefinition schema, Name name, boolean ignoreCase);
/**
* The UDTs defined in this database.
*/
List<UDTDefinition> getUDTs();
/**
* The UDTs defined in this database.
*/

View File

@ -66,6 +66,12 @@ public interface Definition {
*/
SchemaDefinition getSchema();
/**
* @return The package of this object or <code>null</code> if this object is
* not contained in a package.
*/
PackageDefinition getPackage();
/**
* @return The name of this object, e.g. [my_table]. This corresponds to
* {@link #getInputName()}