[jOOQ/jOOQ#644] Add support for Oracle TYPE .. UNDER type hierarchies
This includes: - [jOOQ/jOOQ#11371] Generate UDT.getSupertype() and UDT.getSubtypes()
This commit is contained in:
parent
fdbeea9977
commit
175380c1dc
@ -603,26 +603,17 @@ public class DefaultGeneratorStrategy extends AbstractGeneratorStrategy {
|
||||
sb.append(subPackage);
|
||||
}
|
||||
|
||||
// Record are yet in another subpackage
|
||||
if (mode == Mode.RECORD) {
|
||||
// Other subpackages
|
||||
if (mode == Mode.RECORD)
|
||||
sb.append(".records");
|
||||
}
|
||||
|
||||
// POJOs too
|
||||
else if (mode == Mode.POJO) {
|
||||
else if (mode == Mode.RECORD_TYPE)
|
||||
sb.append(".recordtypes");
|
||||
else if (mode == Mode.POJO)
|
||||
sb.append(".pojos");
|
||||
}
|
||||
|
||||
// DAOs too
|
||||
else if (mode == Mode.DAO) {
|
||||
else if (mode == Mode.DAO)
|
||||
sb.append(".daos");
|
||||
}
|
||||
|
||||
// Interfaces too
|
||||
else if (mode == Mode.INTERFACE) {
|
||||
else if (mode == Mode.INTERFACE)
|
||||
sb.append(".interfaces");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -679,6 +670,8 @@ public class DefaultGeneratorStrategy extends AbstractGeneratorStrategy {
|
||||
result.append("Dao");
|
||||
else if (mode == Mode.INTERFACE)
|
||||
result.insert(0, "I");
|
||||
else if (mode == Mode.RECORD_TYPE)
|
||||
result.append("RecordType");
|
||||
else if (mode == Mode.PATH)
|
||||
result.append("Path");
|
||||
|
||||
|
||||
@ -616,6 +616,12 @@ public interface GeneratorStrategy {
|
||||
*/
|
||||
RECORD,
|
||||
|
||||
/**
|
||||
* The record type mode. This is used when a {@link UDTDefinition}'s
|
||||
* record type interface is being rendered.
|
||||
*/
|
||||
RECORD_TYPE,
|
||||
|
||||
/**
|
||||
* The pojo mode. This is used when a {@link TableDefinition}'s pojo
|
||||
* class is being rendered
|
||||
|
||||
@ -154,6 +154,7 @@ import org.jooq.TableOptions;
|
||||
// ...
|
||||
import org.jooq.UDT;
|
||||
import org.jooq.UDTField;
|
||||
import org.jooq.UDTRecord;
|
||||
import org.jooq.UniqueKey;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.codegen.GenerationUtil.BaseType;
|
||||
@ -779,6 +780,7 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
|
||||
if (generateUDTs()) {
|
||||
generateUDTRecords(schema);
|
||||
generateUDTRecordTypes(schema);
|
||||
|
||||
if (generatePojos())
|
||||
generateUDTPojos(schema);
|
||||
@ -1712,6 +1714,15 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
if (generateInterfaces())
|
||||
interfaces.add(out.ref(getStrategy().getFullJavaClassName(tableUdtOrEmbeddable, Mode.INTERFACE)));
|
||||
|
||||
if (tableUdtOrEmbeddable instanceof UDTDefinition u) {
|
||||
if (u.getSupertype() != null || !u.getSubtypes().isEmpty()) {
|
||||
interfaces.add(out.ref(getStrategy().getFullJavaClassName(u, Mode.RECORD_TYPE))
|
||||
+ "<"
|
||||
+ className
|
||||
+ ">");
|
||||
}
|
||||
}
|
||||
|
||||
if (scala) {
|
||||
if (tableUdtOrEmbeddable instanceof EmbeddableDefinition)
|
||||
out.println("%sclass %s extends %s[%s](%s.%s.getDataType.getRow)[[before= with ][separator= with ][%s]] {",
|
||||
@ -2169,6 +2180,104 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
out.println("}");
|
||||
}
|
||||
|
||||
protected void generateUDTRecordType(UDTDefinition udt) {
|
||||
JavaWriter out = newJavaWriter(udt, Mode.RECORD_TYPE);
|
||||
log.info("Generating record type", out.file().getName());
|
||||
generateRecordType0(udt, out);
|
||||
closeJavaWriter(out);
|
||||
}
|
||||
|
||||
private final void generateRecordType0(UDTDefinition udt, JavaWriter out) {
|
||||
final String className = getStrategy().getJavaClassName(udt, Mode.RECORD_TYPE);
|
||||
final List<String> interfaces = out.ref(getStrategy().getJavaClassImplements(udt, Mode.RECORD_TYPE));
|
||||
|
||||
interfaces.add(out.ref(UDTRecord.class) + "<R>");
|
||||
|
||||
if (udt.getSupertype() != null)
|
||||
interfaces.add(out.ref(getStrategy().getFullJavaClassName(udt.getSupertype(), Mode.RECORD_TYPE)) + "<R>");
|
||||
|
||||
printPackage(out, udt, Mode.RECORD_TYPE);
|
||||
generateUDTRecordTypeClassJavadoc(udt, out);
|
||||
|
||||
printClassAnnotations(out, udt, Mode.RECORD_TYPE);
|
||||
|
||||
if (scala)
|
||||
out.println("%strait %s[R <: %s[R] ] extends [[%s]] {", visibility(), className, UDTRecord.class, interfaces);
|
||||
else if (kotlin)
|
||||
out.println("%sinterface %s<R : %s<R>> : [[%s]] {", visibility(), className, UDTRecord.class, interfaces);
|
||||
else
|
||||
out.println("%sinterface %s<R extends %s<R>> extends [[%s]] {", visibility(), className, UDTRecord.class, interfaces);
|
||||
|
||||
List<? extends TypedElementDefinition<?>> typedElements = getTypedElements(udt);
|
||||
for (int i = 0; i < typedElements.size(); i++) {
|
||||
TypedElementDefinition<?> column = typedElements.get(i);
|
||||
|
||||
if (!generateImmutableInterfaces())
|
||||
generateUDTRecordTypeSetter(column, i, out);
|
||||
|
||||
generateUDTRecordTypeGetter(column, i, out);
|
||||
}
|
||||
|
||||
generateUDTRecordTypeClassFooter(udt, out);
|
||||
out.println("}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override this method to provide their own record type setters.
|
||||
*/
|
||||
protected void generateUDTRecordTypeSetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
|
||||
generateUDTRecordTypeSetter0(column, index, out);
|
||||
}
|
||||
|
||||
private final void generateUDTRecordTypeSetter0(TypedElementDefinition<?> column, @SuppressWarnings("unused") int index, JavaWriter out) {
|
||||
final String className = getStrategy().getJavaClassName(column.getContainer(), Mode.RECORD_TYPE);
|
||||
final String setterReturnType = generateFluentSetters() ? className : tokenVoid;
|
||||
final String setter = getStrategy().getJavaSetterName(column, Mode.RECORD_TYPE);
|
||||
final String typeFull = getJavaType(column.getType(resolver(out, Mode.RECORD_TYPE)), out, Mode.RECORD_TYPE);
|
||||
final String type = out.ref(typeFull);
|
||||
final String name = column.getQualifiedOutputName();
|
||||
|
||||
if (!kotlin && !printDeprecationIfUnknownType(out, typeFull))
|
||||
out.javadoc("Setter for <code>%s</code>.[[before= ][%s]]", name, list(escapeEntities(comment(column))));
|
||||
|
||||
if (scala)
|
||||
out.println("%sdef %s(value: %s): %s", visibilityPublic(), setter, type, setterReturnType);
|
||||
// The property is already defined in the getter
|
||||
else if (kotlin) {}
|
||||
else
|
||||
out.println("%s%s %s([[before=@][after= ][%s]]%s value);", visibilityPublic(), setterReturnType, setter, list(nullableOrNonnullAnnotation(out, column)), varargsIfArray(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override this method to provide their own record type getters.
|
||||
*/
|
||||
protected void generateUDTRecordTypeGetter(TypedElementDefinition<?> column, int index, JavaWriter out) {
|
||||
generateUDTRecordTypeGetter0(column, index, out);
|
||||
}
|
||||
|
||||
private final void generateUDTRecordTypeGetter0(TypedElementDefinition<?> column, @SuppressWarnings("unused") int index, JavaWriter out) {
|
||||
final String member = getStrategy().getJavaMemberName(column, Mode.RECORD_TYPE);
|
||||
final String getter = getStrategy().getJavaGetterName(column, Mode.RECORD_TYPE);
|
||||
final String typeFull = getJavaType(column.getType(resolver(out, Mode.RECORD_TYPE)), out, Mode.RECORD_TYPE);
|
||||
final String type = out.ref(typeFull);
|
||||
final String name = column.getQualifiedOutputName();
|
||||
|
||||
if (!kotlin && !printDeprecationIfUnknownType(out, typeFull))
|
||||
out.javadoc("Getter for <code>%s</code>.[[before= ][%s]]", name, list(escapeEntities(comment(column))));
|
||||
|
||||
printValidationAnnotation(out, column);
|
||||
printNullableOrNonnullAnnotation(out, column);
|
||||
if (kotlin && !generateImmutableInterfaces())
|
||||
printKotlinSetterAnnotation(out, column, Mode.RECORD_TYPE);
|
||||
|
||||
if (scala)
|
||||
out.println("%sdef %s: %s", visibilityPublic(), scalaWhitespaceSuffix(getter), type);
|
||||
else if (kotlin)
|
||||
out.println("%s%s %s: %s%s", visibilityPublic(), (generateImmutableInterfaces() ? "val" : "var"), member, type, kotlinNullability(out, column, Mode.RECORD_TYPE));
|
||||
else
|
||||
out.println("%s%s %s();", visibilityPublic(), type, getter);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface EmbeddableFilter {
|
||||
void accept(List<Definition> result, Set<EmbeddableDefinition> duplicates, int index, EmbeddableDefinition embeddable);
|
||||
@ -2584,13 +2693,13 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
}
|
||||
|
||||
private String getJavaType(Definition column, JavaWriter out) {
|
||||
return getJavaType(column, out, Mode.RECORD);
|
||||
return getJavaType(column, out, Mode.DEFAULT);
|
||||
}
|
||||
|
||||
private String getJavaType(Definition column, JavaWriter out, Mode mode) {
|
||||
return column instanceof EmbeddableDefinition
|
||||
? getStrategy().getFullJavaClassName(column, mode)
|
||||
: getJavaType(((TypedElementDefinition<?>) column).getType(resolver(out)), out);
|
||||
? getStrategy().getFullJavaClassName(column, mode == Mode.DEFAULT ? Mode.RECORD : mode)
|
||||
: getJavaType(((TypedElementDefinition<?>) column).getType(resolver(out)), out, mode);
|
||||
}
|
||||
|
||||
private String getJavaTypeRef(Definition column, JavaWriter out) {
|
||||
@ -2677,7 +2786,7 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
|
||||
// [#3117] Avoid covariant setters for UDTs when generating interfaces
|
||||
if (generateInterfaces() && !generateImmutableInterfaces() && (isUDT || isArray)) {
|
||||
final String columnTypeFull = getJavaType(column.getType(resolver(out, Mode.RECORD)), out, Mode.RECORD);
|
||||
final String columnTypeFull = getJavaType(column.getType(resolver(out, Mode.DEFAULT)), out, Mode.DEFAULT);
|
||||
final String columnType = out.ref(columnTypeFull);
|
||||
final String columnTypeInterface = out.ref(getJavaType(column.getType(resolver(out, Mode.INTERFACE)), out, Mode.INTERFACE));
|
||||
|
||||
@ -3456,6 +3565,40 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
if (udt.getSupertype() != null) {
|
||||
final String superUdtId = out.ref(getStrategy().getFullJavaIdentifier(udt.getSupertype()), 2);
|
||||
|
||||
// [#644] TODO
|
||||
if (scala) {
|
||||
}
|
||||
// [#644] TODO
|
||||
else if (kotlin) {
|
||||
}
|
||||
else {
|
||||
out.overrideInherit();
|
||||
out.println("%s%s<?> getSupertype() {", visibilityPublic(), UDT.class);
|
||||
out.println("return %s;", superUdtId);
|
||||
out.println("}");
|
||||
}
|
||||
}
|
||||
|
||||
if (!udt.getSubtypes().isEmpty()) {
|
||||
final List<String> subUdtIds = out.ref(getStrategy().getFullJavaIdentifiers(udt.getSubtypes()), 2);
|
||||
|
||||
// [#644] TODO
|
||||
if (scala) {
|
||||
}
|
||||
// [#644] TODO
|
||||
else if (kotlin) {
|
||||
}
|
||||
else {
|
||||
out.overrideInherit();
|
||||
out.println("%s%s<%s<?>> getSubtypes() {", visibilityPublic(), List.class, UDT.class);
|
||||
out.println("return %s.asList([[%s]]);", Arrays.class, subUdtIds);
|
||||
out.println("}");
|
||||
}
|
||||
}
|
||||
|
||||
generateUDTClassFooter(udt, out);
|
||||
out.println("}");
|
||||
closeJavaWriter(out);
|
||||
@ -3708,6 +3851,41 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
printClassJavadoc(out, udt, "The udt <code>" + udt.getQualifiedInputName() + "</code>.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generating UDT record types
|
||||
*/
|
||||
protected void generateUDTRecordTypes(SchemaDefinition schema) {
|
||||
log.info("Generating UDT record types");
|
||||
|
||||
for (UDTDefinition udt : database.getUDTs(schema)) {
|
||||
try {
|
||||
if (udt.getSupertype() != null || !udt.getSubtypes().isEmpty())
|
||||
generateUDTRecordType(udt);
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("Error while generating UDT record types " + udt, e);
|
||||
}
|
||||
}
|
||||
|
||||
watch.splitInfo("UDT record types generated");
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override this method to provide udt record class footer code.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
protected void generateUDTRecordTypeClassFooter(UDTDefinition udt, JavaWriter out) {}
|
||||
|
||||
/**
|
||||
* Subclasses may override this method to provide their own Javadoc.
|
||||
*/
|
||||
protected void generateUDTRecordTypeClassJavadoc(UDTDefinition udt, JavaWriter out) {
|
||||
if (generateCommentsOnUDTs())
|
||||
printClassJavadoc(out, udt);
|
||||
else
|
||||
printClassJavadoc(out, udt, "The udt <code>" + udt.getQualifiedInputName() + "</code>.");
|
||||
}
|
||||
|
||||
protected void generateUDTRoutines(SchemaDefinition schema) {
|
||||
for (UDTDefinition udt : database.getUDTs(schema)) {
|
||||
if (udt.getRoutines().size() > 0) {
|
||||
@ -10702,7 +10880,7 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
}
|
||||
|
||||
protected String getJavaType(DataTypeDefinition type, JavaWriter out) {
|
||||
return getJavaType(type, out, Mode.RECORD);
|
||||
return getJavaType(type, out, Mode.DEFAULT);
|
||||
}
|
||||
|
||||
protected String getJavaType(DataTypeDefinition type, JavaWriter out, Mode udtMode) {
|
||||
@ -10731,7 +10909,7 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
}
|
||||
|
||||
protected String getType(Database db, SchemaDefinition schema, JavaWriter out, String t, int p, int s, Name u, String javaType, String defaultType) {
|
||||
return getType(db, schema, out, t, p, s, u, javaType, defaultType, Mode.RECORD);
|
||||
return getType(db, schema, out, t, p, s, u, javaType, defaultType, Mode.DEFAULT);
|
||||
}
|
||||
|
||||
protected String getType(Database db, SchemaDefinition schema, JavaWriter out, String t, int p, int s, Name u, String javaType, String defaultType, Mode udtMode) {
|
||||
@ -10739,7 +10917,9 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
}
|
||||
|
||||
protected String getType(Database db, SchemaDefinition schema, JavaWriter out, String t, int p, int s, Name u, String javaType, String defaultType, Mode udtMode, XMLTypeDefinition xmlType) {
|
||||
UDTDefinition udt;
|
||||
String type = defaultType;
|
||||
Mode udtDefaultMode = udtMode == Mode.DEFAULT ? Mode.RECORD : udtMode;
|
||||
|
||||
// XML types
|
||||
if (xmlType != null) {
|
||||
@ -10762,7 +10942,7 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
|
||||
// [#10309] TODO: The schema should be taken from baseType, if available. Might be different than the argument schema.
|
||||
// When can this happen?
|
||||
String baseType = getType(db, schema, out, newT, p, s, bt.u(), javaType, defaultType, udtMode);
|
||||
String baseType = getType(db, schema, out, newT, p, s, bt.u(), javaType, defaultType, udtDefaultMode);
|
||||
|
||||
if (scala)
|
||||
type = "scala.Array[" + baseType + "]";
|
||||
@ -10804,14 +10984,17 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
}
|
||||
|
||||
// Check for UDTs
|
||||
else if (db.getUDT(schema, u) != null) {
|
||||
type = getStrategy().getFullJavaClassName(db.getUDT(schema, u), udtMode);
|
||||
else if ((udt = db.getUDT(schema, u)) != null) {
|
||||
if (udt.getSubtypes().isEmpty() || udtMode == Mode.RECORD || udtMode == Mode.POJO || udtMode == Mode.INTERFACE)
|
||||
type = getStrategy().getFullJavaClassName(udt, udtDefaultMode);
|
||||
else
|
||||
type = getStrategy().getFullJavaClassName(udt, Mode.RECORD_TYPE) + "<?>";
|
||||
}
|
||||
|
||||
// [#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) {
|
||||
type = getStrategy().getFullJavaClassName(db.getTable(schema, u), udtMode);
|
||||
type = getStrategy().getFullJavaClassName(db.getTable(schema, u), udtDefaultMode);
|
||||
}
|
||||
|
||||
// Check for custom types
|
||||
|
||||
@ -330,6 +330,7 @@ public abstract class AbstractDatabase implements Database {
|
||||
private transient Map<SchemaDefinition, List<XMLSchemaCollectionDefinition>> xmlSchemaCollectionsBySchema;
|
||||
private transient Map<SchemaDefinition, List<UDTDefinition>> udtsBySchema;
|
||||
private transient Map<PackageDefinition, List<UDTDefinition>> udtsByPackage;
|
||||
private transient Map<UDTDefinition, List<UDTDefinition>> subtypesByUdt;
|
||||
private transient Map<SchemaDefinition, List<ArrayDefinition>> arraysBySchema;
|
||||
private transient Map<SchemaDefinition, List<RoutineDefinition>> routinesBySchema;
|
||||
private transient Map<SchemaDefinition, List<PackageDefinition>> packagesBySchema;
|
||||
@ -3101,6 +3102,14 @@ public abstract class AbstractDatabase implements Database {
|
||||
return filterPackage(getUDTs(), pkg, udtsByPackage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UDTDefinition> getSubtypes(UDTDefinition udt) {
|
||||
if (subtypesByUdt == null)
|
||||
subtypesByUdt = new LinkedHashMap<>();
|
||||
|
||||
return filterSupertype(getUDTs(), udt, subtypesByUdt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Relations getRelations() {
|
||||
if (relations == null) {
|
||||
@ -3304,6 +3313,23 @@ public abstract class AbstractDatabase implements Database {
|
||||
return result;
|
||||
}
|
||||
|
||||
final List<UDTDefinition> filterSupertype(List<UDTDefinition> definitions, UDTDefinition supertype, Map<UDTDefinition, List<UDTDefinition>> cache) {
|
||||
return cache.computeIfAbsent(supertype, u -> filterSupertype(definitions, u));
|
||||
}
|
||||
|
||||
final List<UDTDefinition> filterSupertype(List<UDTDefinition> definitions, UDTDefinition u) {
|
||||
if (u == null)
|
||||
return definitions;
|
||||
|
||||
List<UDTDefinition> result = new ArrayList<>();
|
||||
|
||||
for (UDTDefinition definition : definitions)
|
||||
if (definition.getSupertype() != null && definition.getSupertype().equals(u))
|
||||
result.add(definition);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected final <T extends TableElementDefinition> List<T> filterTable(List<T> definitions, TableDefinition table, Map<TableDefinition, List<T>> cache) {
|
||||
List<T> result = cache.get(table);
|
||||
|
||||
|
||||
@ -53,6 +53,8 @@ implements
|
||||
|
||||
private List<RoutineDefinition> routines;
|
||||
private final boolean synthetic;
|
||||
private SchemaDefinition supertypeSchema;
|
||||
private String supertypeName;
|
||||
|
||||
public AbstractUDTDefinition(SchemaDefinition schema, String name, String comment) {
|
||||
this(schema, null, name, false, comment);
|
||||
@ -63,9 +65,15 @@ implements
|
||||
}
|
||||
|
||||
public AbstractUDTDefinition(SchemaDefinition schema, PackageDefinition pkg, String name, boolean synthetic, String comment) {
|
||||
this(schema, pkg, name, synthetic, comment, null, null);
|
||||
}
|
||||
|
||||
public AbstractUDTDefinition(SchemaDefinition schema, PackageDefinition pkg, String name, boolean synthetic, String comment, SchemaDefinition supertypeSchema, String supertypeName) {
|
||||
super(schema, pkg, name, comment);
|
||||
|
||||
this.synthetic = synthetic;
|
||||
this.supertypeSchema = supertypeSchema;
|
||||
this.supertypeName = supertypeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -107,4 +115,14 @@ implements
|
||||
public boolean isSynthetic() {
|
||||
return synthetic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UDTDefinition getSupertype() {
|
||||
return supertypeSchema == null ? null : getDatabase().getUDT(supertypeSchema, supertypeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UDTDefinition> getSubtypes() {
|
||||
return getDatabase().getSubtypes(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -411,6 +411,11 @@ public interface Database extends AutoCloseable {
|
||||
*/
|
||||
List<UDTDefinition> getUDTs(PackageDefinition pkg);
|
||||
|
||||
/**
|
||||
* Get the subtypes of a UDT, if any.
|
||||
*/
|
||||
List<UDTDefinition> getSubtypes(UDTDefinition udt);
|
||||
|
||||
/**
|
||||
* The Arrays defined in this database.
|
||||
*/
|
||||
|
||||
@ -76,4 +76,14 @@ public interface UDTDefinition extends PackageDefinition {
|
||||
*/
|
||||
@Override
|
||||
boolean isSynthetic();
|
||||
|
||||
/**
|
||||
* The subtypes of this UDT, if any.
|
||||
*/
|
||||
List<UDTDefinition> getSubtypes();
|
||||
|
||||
/**
|
||||
* The supertype of this UDT, if any.
|
||||
*/
|
||||
UDTDefinition getSupertype();
|
||||
}
|
||||
|
||||
@ -37,6 +37,11 @@
|
||||
*/
|
||||
package org.jooq;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* UDT definition.
|
||||
* <p>
|
||||
@ -63,4 +68,23 @@ public interface UDT<R extends UDTRecord<R>> extends RecordQualifier<R> {
|
||||
* </ul>
|
||||
*/
|
||||
boolean isSynthetic();
|
||||
|
||||
/**
|
||||
* Get the supertype of this {@link UDT}, or <code>null</code> if this type
|
||||
* has no supertype.
|
||||
*/
|
||||
@Nullable
|
||||
UDT<?> getSupertype();
|
||||
|
||||
/**
|
||||
* Get the subtypes of this {@link UDT} or an empty list, if there are no
|
||||
* known subtypes.
|
||||
*/
|
||||
@NotNull
|
||||
List<UDT<?>> getSubtypes();
|
||||
|
||||
/**
|
||||
* Check if this type is a supertype or the same type as another {@link UDT} type.
|
||||
*/
|
||||
boolean isAssignableFrom(UDT<?> other);
|
||||
}
|
||||
|
||||
@ -273,11 +273,11 @@ implements
|
||||
* @deprecated - 3.20.0 - [#15723] - Re-generate your code.
|
||||
*/
|
||||
@Deprecated
|
||||
protected AbstractRoutine(String name, Schema schema, DataType<T> type) {
|
||||
protected AbstractRoutine(String name, Schema schema, DataType<? extends T> type) {
|
||||
this(name, schema, (Package) null, type, null, null);
|
||||
}
|
||||
|
||||
protected AbstractRoutine(String name, Schema schema, Comment comment, DataType<T> type) {
|
||||
protected AbstractRoutine(String name, Schema schema, Comment comment, DataType<? extends T> type) {
|
||||
this(name, schema, (Package) null, comment, type, null, null);
|
||||
}
|
||||
|
||||
@ -321,11 +321,11 @@ implements
|
||||
* @deprecated - 3.20.0 - [#15723] - Re-generate your code.
|
||||
*/
|
||||
@Deprecated
|
||||
protected AbstractRoutine(String name, Schema schema, Package pkg, DataType<T> type) {
|
||||
protected AbstractRoutine(String name, Schema schema, Package pkg, DataType<? extends T> type) {
|
||||
this(name, schema, pkg, type, null, null);
|
||||
}
|
||||
|
||||
protected AbstractRoutine(String name, Schema schema, Package pkg, Comment comment, DataType<T> type) {
|
||||
protected AbstractRoutine(String name, Schema schema, Package pkg, Comment comment, DataType<? extends T> type) {
|
||||
this(name, schema, pkg, comment, type, null, null);
|
||||
}
|
||||
|
||||
|
||||
@ -358,7 +358,7 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
static final <T, U> Binding<T, U> binding(DataType<T> dataType, Converter<T, U> converter) {
|
||||
static final <T, U> Binding<T, U> binding(DataType<? extends T> dataType, Converter<T, U> converter) {
|
||||
Class<?> type = converter.fromType();
|
||||
|
||||
// Concrete types
|
||||
@ -550,7 +550,7 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
static final <T, X, U> Binding<T, U> newBinding(final Converter<X, U> converter, final DataType<T> dataType, final Binding<T, X> binding) {
|
||||
static final <T, X, U> Binding<T, U> newBinding(final Converter<X, U> converter, final DataType<? extends T> dataType, final Binding<T, X> binding) {
|
||||
final Binding<T, U> theBinding;
|
||||
|
||||
|
||||
@ -622,7 +622,9 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
try {
|
||||
if (QualifiedRecord.class.isAssignableFrom(type)) {
|
||||
Class<QualifiedRecord<?>> t = (Class<QualifiedRecord<?>>) type;
|
||||
result.put(getMappedUDTName(scope, t), t);
|
||||
|
||||
// [#644] Prevent infinite recursion between fields and subtypes
|
||||
if (result.putIfAbsent(getMappedUDTName(scope, t), t) == null) {
|
||||
|
||||
|
||||
|
||||
@ -635,8 +637,16 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
|
||||
|
||||
|
||||
for (Field<?> field : getRecordQualifier(t).fields())
|
||||
typeMap(field.getType(), scope, result);
|
||||
RecordQualifier<?> q = getRecordQualifier(t);
|
||||
for (Field<?> field : q.fields())
|
||||
typeMap(field.getType(), scope, result);
|
||||
|
||||
// [#644] Put subtypes into the type map as well
|
||||
if (q instanceof UDT<?> u) {
|
||||
for (UDT<?> s : u.getSubtypes())
|
||||
typeMap(s.getRecordType(), scope, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -647,6 +657,7 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MappingException("Error while collecting type map", e);
|
||||
@ -1871,6 +1882,14 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -643,7 +643,7 @@ public final class Internal {
|
||||
* Factory method for parameters.
|
||||
*/
|
||||
@NotNull
|
||||
public static final <T> Parameter<T> createParameter(String name, DataType<T> type, boolean isDefaulted, boolean isUnnamed) {
|
||||
public static final <T> Parameter<T> createParameter(String name, DataType<? extends T> type, boolean isDefaulted, boolean isUnnamed) {
|
||||
return createParameter(name, type, isDefaulted, isUnnamed, null, null);
|
||||
}
|
||||
|
||||
@ -651,7 +651,7 @@ public final class Internal {
|
||||
* Factory method for parameters.
|
||||
*/
|
||||
@NotNull
|
||||
public static final <T, U> Parameter<U> createParameter(String name, DataType<T> type, boolean isDefaulted, boolean isUnnamed, Converter<T, U> converter) {
|
||||
public static final <T, U> Parameter<U> createParameter(String name, DataType<? extends T> type, boolean isDefaulted, boolean isUnnamed, Converter<T, U> converter) {
|
||||
return createParameter(name, type, isDefaulted, isUnnamed, converter, null);
|
||||
}
|
||||
|
||||
@ -659,7 +659,7 @@ public final class Internal {
|
||||
* Factory method for parameters.
|
||||
*/
|
||||
@NotNull
|
||||
public static final <T, U> Parameter<U> createParameter(String name, DataType<T> type, boolean isDefaulted, boolean isUnnamed, Binding<T, U> binding) {
|
||||
public static final <T, U> Parameter<U> createParameter(String name, DataType<? extends T> type, boolean isDefaulted, boolean isUnnamed, Binding<T, U> binding) {
|
||||
return createParameter(name, type, isDefaulted, isUnnamed, null, binding);
|
||||
}
|
||||
|
||||
@ -668,7 +668,7 @@ public final class Internal {
|
||||
*/
|
||||
@NotNull
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final <T, X, U> Parameter<U> createParameter(String name, DataType<T> type, boolean isDefaulted, boolean isUnnamed, Converter<X, U> converter, Binding<T, X> binding) {
|
||||
public static final <T, X, U> Parameter<U> createParameter(String name, DataType<? extends T> type, boolean isDefaulted, boolean isUnnamed, Converter<X, U> converter, Binding<T, X> binding) {
|
||||
final Binding<T, U> actualBinding = DefaultBinding.newBinding(converter, type, binding);
|
||||
final DataType<U> actualType = converter == null && binding == null
|
||||
? (DataType<U>) type
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import org.jooq.ConverterContext;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Row;
|
||||
import org.jooq.SQLDialect;
|
||||
|
||||
@ -37,6 +37,12 @@
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jooq.Binding;
|
||||
import org.jooq.Catalog;
|
||||
import org.jooq.Comment;
|
||||
@ -54,6 +60,7 @@ import org.jooq.UDTField;
|
||||
import org.jooq.UDTRecord;
|
||||
import org.jooq.impl.QOM.UNotYetImplemented;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.ApiStatus.Internal;
|
||||
|
||||
/**
|
||||
@ -163,6 +170,25 @@ implements
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ UDT<?> getSupertype() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ List<UDT<?>> getSubtypes() {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isAssignableFrom(UDT<?> other) {
|
||||
if (equals(other))
|
||||
return true;
|
||||
|
||||
UDT<?> s = other.getSupertype();
|
||||
return s != null ? isAssignableFrom(s) : false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isSQLUsable() {
|
||||
return true ;
|
||||
@ -209,7 +235,7 @@ implements
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected static final <R extends UDTRecord<R>, T> UDTField<R, T> createField(String name, DataType<T> type, UDT<R> udt) {
|
||||
protected static final <R extends UDTRecord<R>, T> UDTField<R, T> createField(String name, DataType<? extends T> type, UDT<R> udt) {
|
||||
return createField(DSL.name(name), type, udt, "", null, null);
|
||||
}
|
||||
|
||||
@ -224,7 +250,7 @@ implements
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected static final <R extends UDTRecord<R>, T> UDTField<R, T> createField(String name, DataType<T> type, UDT<R> udt, String comment) {
|
||||
protected static final <R extends UDTRecord<R>, T> UDTField<R, T> createField(String name, DataType<? extends T> type, UDT<R> udt, String comment) {
|
||||
return createField(DSL.name(name), type, udt, comment, null, null);
|
||||
}
|
||||
|
||||
@ -239,7 +265,7 @@ implements
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected static final <R extends UDTRecord<R>, T, U> UDTField<R, U> createField(String name, DataType<T> type, UDT<R> udt, String comment, Converter<T, U> converter) {
|
||||
protected static final <R extends UDTRecord<R>, T, U> UDTField<R, U> createField(String name, DataType<? extends T> type, UDT<R> udt, String comment, Converter<T, U> converter) {
|
||||
return createField(DSL.name(name), type, udt, comment, converter, null);
|
||||
}
|
||||
|
||||
@ -254,7 +280,7 @@ implements
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected static final <R extends UDTRecord<R>, T, U> UDTField<R, U> createField(String name, DataType<T> type, UDT<R> udt, String comment, Binding<T, U> binding) {
|
||||
protected static final <R extends UDTRecord<R>, T, U> UDTField<R, U> createField(String name, DataType<? extends T> type, UDT<R> udt, String comment, Binding<T, U> binding) {
|
||||
return createField(DSL.name(name), type, udt, comment, null, binding);
|
||||
}
|
||||
|
||||
@ -269,7 +295,7 @@ implements
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected static final <R extends UDTRecord<R>, T, X, U> UDTField<R, U> createField(String name, DataType<T> type, UDT<R> udt, String comment, Converter<X, U> converter, Binding<T, X> binding) {
|
||||
protected static final <R extends UDTRecord<R>, T, X, U> UDTField<R, U> createField(String name, DataType<? extends T> type, UDT<R> udt, String comment, Converter<X, U> converter, Binding<T, X> binding) {
|
||||
return createField(DSL.name(name), type, udt, comment, converter, binding);
|
||||
}
|
||||
|
||||
@ -280,7 +306,7 @@ implements
|
||||
* @param name The name of the field (case-sensitive!)
|
||||
* @param type The data type of the field
|
||||
*/
|
||||
protected static final <R extends UDTRecord<R>, T> UDTField<R, T> createField(Name name, DataType<T> type, UDT<R> udt) {
|
||||
protected static final <R extends UDTRecord<R>, T> UDTField<R, T> createField(Name name, DataType<? extends T> type, UDT<R> udt) {
|
||||
return createField(name, type, udt, "", null, null);
|
||||
}
|
||||
|
||||
@ -291,7 +317,7 @@ implements
|
||||
* @param name The name of the field (case-sensitive!)
|
||||
* @param type The data type of the field
|
||||
*/
|
||||
protected static final <R extends UDTRecord<R>, T> UDTField<R, T> createField(Name name, DataType<T> type, UDT<R> udt, String comment) {
|
||||
protected static final <R extends UDTRecord<R>, T> UDTField<R, T> createField(Name name, DataType<? extends T> type, UDT<R> udt, String comment) {
|
||||
return createField(name, type, udt, comment, null, null);
|
||||
}
|
||||
|
||||
@ -302,7 +328,7 @@ implements
|
||||
* @param name The name of the field (case-sensitive!)
|
||||
* @param type The data type of the field
|
||||
*/
|
||||
protected static final <R extends UDTRecord<R>, T, U> UDTField<R, U> createField(Name name, DataType<T> type, UDT<R> udt, String comment, Converter<T, U> converter) {
|
||||
protected static final <R extends UDTRecord<R>, T, U> UDTField<R, U> createField(Name name, DataType<? extends T> type, UDT<R> udt, String comment, Converter<T, U> converter) {
|
||||
return createField(name, type, udt, comment, converter, null);
|
||||
}
|
||||
|
||||
@ -313,7 +339,7 @@ implements
|
||||
* @param name The name of the field (case-sensitive!)
|
||||
* @param type The data type of the field
|
||||
*/
|
||||
protected static final <R extends UDTRecord<R>, T, U> UDTField<R, U> createField(Name name, DataType<T> type, UDT<R> udt, String comment, Binding<T, U> binding) {
|
||||
protected static final <R extends UDTRecord<R>, T, U> UDTField<R, U> createField(Name name, DataType<? extends T> type, UDT<R> udt, String comment, Binding<T, U> binding) {
|
||||
return createField(name, type, udt, comment, null, binding);
|
||||
}
|
||||
|
||||
@ -325,7 +351,7 @@ implements
|
||||
* @param type The data type of the field
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static final <R extends UDTRecord<R>, T, X, U> UDTField<R, U> createField(Name name, DataType<T> type, UDT<R> udt, String comment, Converter<X, U> converter, Binding<T, X> binding) {
|
||||
protected static final <R extends UDTRecord<R>, T, X, U> UDTField<R, U> createField(Name name, DataType<? extends T> type, UDT<R> udt, String comment, Converter<X, U> converter, Binding<T, X> binding) {
|
||||
final Binding<T, U> actualBinding = DefaultBinding.newBinding(converter, type, binding);
|
||||
final DataType<U> actualType = converter == null && binding == null
|
||||
? (DataType<U>) type
|
||||
|
||||
Loading…
Reference in New Issue
Block a user