[jOOQ/jOOQ#9879] Added more generics to Generator and GeneratorContext

In order to implement pure functions of type Generator, we must make the GeneratorContext::table available to Generator implementations, including the usual type safety that allows for binding to the generated table type, which gives access to columns. This prevents having to capture this from the Generator, which isn't too clean (though it's still possible for those people who don't care)
This commit is contained in:
Lukas Eder 2022-04-19 10:26:45 +02:00
parent 4717560baa
commit 153762132f
15 changed files with 57 additions and 33 deletions

View File

@ -607,7 +607,7 @@ public interface DataType<T> extends Named {
* This feature is implemented in commercial distributions only.
*/
@NotNull
DataType<T> generatedAlwaysAs(Generator<T> generatedAlwaysAsValue);
DataType<T> generatedAlwaysAs(Generator<?, ?, T> generatedAlwaysAsValue);
/**
* Get the computed column expression of this data type, if any.
@ -630,7 +630,7 @@ public interface DataType<T> extends Named {
* This feature is implemented in commercial distributions only.
*/
@Nullable
Generator<T> generatedAlwaysAsGenerator();
Generator<?, ?, T> generatedAlwaysAsGenerator();
/**
* Set the {@link #generationOption()} of the computed column expression to

View File

@ -50,7 +50,7 @@ import java.util.function.Function;
* @author Lukas Eder
*/
@FunctionalInterface
public interface Generator<T> extends Function<GeneratorContext<T>, Field<T>>, Serializable {
public interface Generator<R extends Record, X extends Table<R>, T> extends Function<GeneratorContext<R, X, T>, Field<T>>, Serializable {
/**
* Whether this generator supports a given statement type.

View File

@ -37,7 +37,6 @@
*/
package org.jooq;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@ -49,7 +48,14 @@ import org.jetbrains.annotations.Nullable;
*
* @author Lukas Eder
*/
public interface GeneratorContext<T> extends Scope {
public interface GeneratorContext<R extends Record, X extends Table<R>, T> extends Scope {
/**
* The target table whose contents are being generated, or <code>null</code>
* when the table is unknown / not applicable.
*/
@Nullable
X table();
/**
* The target field whose contents are being generated, or <code>null</code>

View File

@ -103,6 +103,7 @@ import org.jooq.Result;
import org.jooq.Row;
import org.jooq.SQLDialect;
import org.jooq.Schema;
import org.jooq.Table;
import org.jooq.XML;
import org.jooq.impl.QOM.GenerationLocation;
import org.jooq.impl.QOM.GenerationOption;
@ -203,20 +204,20 @@ implements
@Override
public final DataType<T> generatedAlwaysAs(Field<T> generatedAlwaysAsValue) {
return generatedAlwaysAs(ctx -> generatedAlwaysAsValue);
return generatedAlwaysAs((Generator<Record, Table<Record>, T>) t -> generatedAlwaysAsValue);
}
@Override
public abstract DataType<T> generatedAlwaysAs(Generator<T> generatedAlwaysAsValue);
public abstract DataType<T> generatedAlwaysAs(Generator<?, ?, T> generatedAlwaysAsValue);
@Override
public final Field<T> generatedAlwaysAs() {
Generator<T> s = generatedAlwaysAsGenerator();
return s == null ? null : s.apply(new DefaultGeneratorContext(CONFIG, null, null));
Generator<?, ?, T> s = generatedAlwaysAsGenerator();
return s == null ? null : s.apply(new DefaultGeneratorContext(CONFIG, null, null, null));
}
@Override
public abstract Generator<T> generatedAlwaysAsGenerator();
public abstract Generator<?, ?, T> generatedAlwaysAsGenerator();
@Override
public final DataType<T> stored() {

View File

@ -73,7 +73,7 @@ abstract class AbstractDataTypeX<T> extends AbstractDataType<T> {
Integer newLength,
Nullability newNullability,
boolean newReadonly,
Generator<T> newGeneratedAlwaysAs,
Generator<?, ?, T> newGeneratedAlwaysAs,
GenerationOption newGenerationOption,
GenerationLocation newGenerationLocation,
Collation newCollation,
@ -124,7 +124,7 @@ abstract class AbstractDataTypeX<T> extends AbstractDataType<T> {
private static final JooqLogger logGeneratedAlwaysAs = JooqLogger.getLogger(AbstractDataTypeX.class, "generateAlwaysAs", 1);
@Override
public final DataType<T> generatedAlwaysAs(Generator<T> g) {
public final DataType<T> generatedAlwaysAs(Generator<?, ?, T> g) {
if (g != null && !CONFIG.commercial())
logGeneratedAlwaysAs.info("Computed columns", "Computed columns are a commercial only jOOQ feature. If you wish to profit from this feature, please upgrade to the jOOQ Professional Edition");

View File

@ -796,7 +796,7 @@ abstract class AbstractTable<R extends Record> extends AbstractNamed implements
* @param type The data type of the field
*/
@SuppressWarnings("unchecked")
protected static final <R extends Record, T, X, U> TableField<R, U> createField(Name name, DataType<T> type, Table<R> table, String comment, Converter<X, U> converter, Binding<T, X> binding, Generator<U> generator) {
protected static final <R extends Record, TR extends Table<R>, T, X, U> TableField<R, U> createField(Name name, DataType<T> type, TR table, String comment, Converter<X, U> converter, Binding<T, X> binding, Generator<R, TR, U> generator) {
Binding<T, U> actualBinding = DefaultBinding.newBinding(converter, type, binding);
DataType<U> actualType =
converter == null && binding == null

View File

@ -76,7 +76,7 @@ final class ArrayDataType<T> extends DefaultDataType<T[]> {
Integer length,
Nullability nullability,
boolean readonly,
Generator<T[]> generatedAlwaysAs,
Generator<?, ?, T[]> generatedAlwaysAs,
GenerationOption generationOption,
GenerationLocation generationLocation,
Collation collation,
@ -97,7 +97,7 @@ final class ArrayDataType<T> extends DefaultDataType<T[]> {
Integer newLength,
Nullability newNullability,
boolean newReadonly,
Generator<T[]> newGeneratedAlwaysAs,
Generator<?, ?, T[]> newGeneratedAlwaysAs,
GenerationOption newGenerationOption,
GenerationLocation newGenerationLocation,
Collation newCollation,

View File

@ -93,6 +93,8 @@ package org.jooq.impl;

View File

@ -88,7 +88,7 @@ final class ConvertedDataType<T, U> extends AbstractDataTypeX<U> {
Integer newLength,
Nullability newNullability,
boolean newReadonly,
Generator<U> newGeneratedAlwaysAs,
Generator<?, ?, U> newGeneratedAlwaysAs,
GenerationOption newGenerationOption,
GenerationLocation newGenerationLocation,
Collation newCollation,
@ -210,8 +210,8 @@ final class ConvertedDataType<T, U> extends AbstractDataTypeX<U> {
}
@Override
public final Generator<U> generatedAlwaysAsGenerator() {
return (Generator<U>) delegate.generatedAlwaysAsGenerator();
public final Generator<?, ?, U> generatedAlwaysAsGenerator() {
return (Generator<?, ?, U>) delegate.generatedAlwaysAsGenerator();
}
@Override

View File

@ -66,7 +66,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
private final Integer overrideLength;
private final Nullability overrideNullability;
private final Boolean overrideReadonly;
private final Generator<T> overrideGeneratedAlwaysAs;
private final Generator<?, ?, T> overrideGeneratedAlwaysAs;
private final GenerationOption overrideGenerationOption;
private final GenerationLocation overrideGenerationLocation;
private final Collation overrideCollation;
@ -86,7 +86,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
Integer overrideLength,
Nullability overrideNullability,
Boolean overrideReadonly,
Generator<T> overrideGeneratedAlwaysAs,
Generator<?, ?, T> overrideGeneratedAlwaysAs,
GenerationOption overrideGenerationOption,
GenerationLocation overrideGenerationLocation,
Collation overrideCollation,
@ -198,12 +198,12 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
}
@Override
public final Generator<T> generatedAlwaysAsGenerator() {
public final Generator<?, ?, T> generatedAlwaysAsGenerator() {
return defaultIfNull(overrideGeneratedAlwaysAs, type.generatedAlwaysAsGenerator());
}
@Override
public final DataType<T> generatedAlwaysAs(Generator<T> g) {
public final DataType<T> generatedAlwaysAs(Generator<?, ?, T> g) {
return new DataTypeProxy<>(
this,
overridePrecision,

View File

@ -259,7 +259,7 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
private final Nullability nullability;
private final boolean readonly;
private final Generator<T> generatedAlwaysAs;
private final Generator<?, ?, T> generatedAlwaysAs;
private final GenerationOption generationOption;
private final GenerationLocation generationLocation;
private final Collation collation;
@ -334,7 +334,7 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
this(dialect, sqlDataType, type, binding, qualifiedTypeName, typeName, castTypeName, precision, scale, length, nullability, false, null, GenerationOption.DEFAULT, GenerationLocation.SERVER, null, null, false, defaultValue);
}
DefaultDataType(SQLDialect dialect, DataType<T> sqlDataType, Class<T> type, Binding<?, T> binding, Name qualifiedTypeName, String typeName, String castTypeName, Integer precision, Integer scale, Integer length, Nullability nullability, boolean readonly, Generator<T> generatedAlwaysAs, GenerationOption generationOption, GenerationLocation generationLocation, Collation collation, CharacterSet characterSet, boolean identity, Field<T> defaultValue) {
DefaultDataType(SQLDialect dialect, DataType<T> sqlDataType, Class<T> type, Binding<?, T> binding, Name qualifiedTypeName, String typeName, String castTypeName, Integer precision, Integer scale, Integer length, Nullability nullability, boolean readonly, Generator<?, ?, T> generatedAlwaysAs, GenerationOption generationOption, GenerationLocation generationLocation, Collation collation, CharacterSet characterSet, boolean identity, Field<T> defaultValue) {
super(qualifiedTypeName, NO_COMMENT);
// Initialise final instance members
@ -401,7 +401,7 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
Integer newLength,
Nullability newNullability,
boolean newReadonly,
Generator<T> newGeneratedAlwaysAs,
Generator<?, ?, T> newGeneratedAlwaysAs,
GenerationOption newGenerationOption,
GenerationLocation newGenerationLocation,
Collation newCollation,
@ -436,7 +436,7 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
Integer length,
Nullability nullability,
boolean readonly,
Generator<T> generatedAlwaysAs,
Generator<?, ?, T> generatedAlwaysAs,
GenerationOption generationOption,
GenerationLocation generationLocation,
Collation collation,
@ -500,7 +500,7 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
}
@Override
public final Generator<T> generatedAlwaysAsGenerator() {
public final Generator<?, ?, T> generatedAlwaysAsGenerator() {
return generatedAlwaysAs;
}

View File

@ -41,22 +41,31 @@ import org.jooq.Configuration;
import org.jooq.Field;
import org.jooq.GeneratorContext;
import org.jooq.GeneratorStatementType;
import org.jooq.Record;
import org.jooq.Table;
/**
* @author Lukas Eder
*/
final class DefaultGeneratorContext<T> extends AbstractScope implements GeneratorContext<T> {
final class DefaultGeneratorContext<R extends Record, X extends Table<R>, T> extends AbstractScope implements GeneratorContext<R, X, T> {
final X table;
final Field<T> field;
final GeneratorStatementType statementType;
DefaultGeneratorContext(Configuration configuration, Field<T> field, GeneratorStatementType statementType) {
DefaultGeneratorContext(Configuration configuration, X table, Field<T> field, GeneratorStatementType statementType) {
super(configuration);
this.table = table;
this.field = field;
this.statementType = statementType;
}
@Override
public final X table() {
return table;
}
@Override
public final Field<T> field() {
return field;

View File

@ -88,6 +88,7 @@ import org.jooq.RenderContext.CastMode;
import org.jooq.SQLDialect;
import org.jooq.Select;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.conf.WriteIfReadonly;
import org.jooq.exception.DataTypeException;
import org.jooq.impl.AbstractStoreQuery.UnknownField;
@ -299,6 +300,11 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple

View File

@ -88,7 +88,7 @@ final class MultisetDataType<R extends Record> extends DefaultDataType<Result<R>
Integer length,
Nullability nullability,
boolean readonly,
Generator<Result<R>> generatedAlwaysAs,
Generator<?, ?, Result<R>> generatedAlwaysAs,
GenerationOption generationOption,
GenerationLocation generationLocation,
Collation collation,
@ -110,7 +110,7 @@ final class MultisetDataType<R extends Record> extends DefaultDataType<Result<R>
Integer newLength,
Nullability newNullability,
boolean newReadonly,
Generator<Result<R>> newGeneratedAlwaysAs,
Generator<?, ?, Result<R>> newGeneratedAlwaysAs,
GenerationOption newGenerationOption,
GenerationLocation newGenerationLocation,
Collation newCollation,

View File

@ -89,7 +89,7 @@ final class RecordDataType<R extends Record> extends DefaultDataType<R> {
Integer length,
Nullability nullability,
boolean readonly,
Generator<R> generatedAlwaysAs,
Generator<?, ?, R> generatedAlwaysAs,
GenerationOption generationOption,
GenerationLocation generationLocation,
Collation collation,
@ -110,7 +110,7 @@ final class RecordDataType<R extends Record> extends DefaultDataType<R> {
Integer newLength,
Nullability newNullability,
boolean newReadonly,
Generator<R> newGeneratedAlwaysAs,
Generator<?, ?, R> newGeneratedAlwaysAs,
GenerationOption newGenerationOption,
GenerationLocation newGenerationLocation,
Collation newCollation,