From 9de6ba83debf519c5a6a92ebfcb202df920f5cac Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 29 Oct 2021 16:24:01 +0200 Subject: [PATCH] [jOOQ/jOOQ#9864] Add support for readonly columns - Added synthetic readonly column codegen config - Added code generation logic - Added DataTypeDefinition.readonly() - Added DataType.readonly() --- .../java/org/jooq/codegen/JavaGenerator.java | 17 ++++-- .../java/org/jooq/meta/AbstractDatabase.java | 24 +++++++++ .../org/jooq/meta/DataTypeDefinition.java | 5 ++ .../src/main/java/org/jooq/meta/Database.java | 16 ++++++ .../jooq/meta/DefaultColumnDefinition.java | 54 ++++++++++++++++--- .../jooq/meta/DefaultDataTypeDefinition.java | 26 +++++++-- .../org/jooq/meta/jaxb/ObjectFactory.java | 8 +++ .../jooq/meta/jaxb/SyntheticObjectsType.java | 46 ++++++++++++++++ .../resources/xsd/jooq-codegen-3.16.0.xsd | 23 ++++++++ jOOQ/src/main/java/org/jooq/DataType.java | 19 +++++++ .../java/org/jooq/impl/AbstractDataType.java | 15 +++++- .../java/org/jooq/impl/AbstractDataTypeX.java | 24 ++++++--- .../java/org/jooq/impl/ArrayDataType.java | 8 +-- .../java/org/jooq/impl/ConvertedDataType.java | 7 +++ .../java/org/jooq/impl/DataTypeProxy.java | 40 +++++++++++++- .../java/org/jooq/impl/DefaultDataType.java | 18 +++++-- .../java/org/jooq/impl/DomainDataType.java | 1 + .../java/org/jooq/impl/MultisetDataType.java | 8 +-- .../java/org/jooq/impl/RecordDataType.java | 8 +-- 19 files changed, 327 insertions(+), 40 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 b746f625dd..39a0410e32 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java +++ b/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java @@ -8426,6 +8426,7 @@ public class JavaGenerator extends AbstractGenerator { type.getLength(), true, false, + false, null, baseType ) + ".getArrayDataType()"; @@ -8441,6 +8442,7 @@ public class JavaGenerator extends AbstractGenerator { type.getLength(), type.isNullable(), type.isIdentity(), + type.isReadonly(), type.getDefaultValue(), type.getQualifiedUserType() ); @@ -8686,7 +8688,7 @@ public class JavaGenerator extends AbstractGenerator { return type; } - protected String getTypeReference(Database db, SchemaDefinition schema, JavaWriter out, String t, int p, int s, int l, boolean n, boolean i, String d, Name u) { + protected String getTypeReference(Database db, SchemaDefinition schema, JavaWriter out, String t, int p, int s, int l, boolean n, boolean i, boolean r, String d, Name u) { StringBuilder sb = new StringBuilder(); if (db.getArray(schema, u) != null) { @@ -8739,9 +8741,11 @@ public class JavaGenerator extends AbstractGenerator { sb.append("\")"); } - dataType = dataType - .nullable(n) - .identity(i); + dataType = dataType.nullable(n).identity(i); + + + + if (d != null) dataType = dataType.defaultValue((Field) DSL.field(d, dataType)); @@ -8793,6 +8797,11 @@ public class JavaGenerator extends AbstractGenerator { if (dataType.identity()) sb.append(".identity(true)"); + + + + + // [#5291] Some dialects report valid SQL expresions (e.g. PostgreSQL), others // report actual values (e.g. MySQL). if (dataType.defaulted()) { diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java index f84c806031..c1d9cc5f8b 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java @@ -126,6 +126,7 @@ import org.jooq.meta.jaxb.SyntheticForeignKeyType; import org.jooq.meta.jaxb.SyntheticIdentityType; import org.jooq.meta.jaxb.SyntheticObjectsType; import org.jooq.meta.jaxb.SyntheticPrimaryKeyType; +import org.jooq.meta.jaxb.SyntheticReadonlyColumnType; import org.jooq.meta.jaxb.SyntheticUniqueKeyType; import org.jooq.meta.jaxb.SyntheticViewType; // ... @@ -204,6 +205,8 @@ public abstract class AbstractDatabase implements Database { private Set unusedEmbeddables = new HashSet<>(); private List configuredComments = new ArrayList<>(); private Set unusedComments = new HashSet<>(); + private List configuredSyntheticReadonlyColumns = new ArrayList<>(); + private Set unusedSyntheticReadonlyColumns = new HashSet<>(); private List configuredSyntheticIdentities = new ArrayList<>(); private Set unusedSyntheticIdentities = new HashSet<>(); private List configuredSyntheticPrimaryKeys = new ArrayList<>(); @@ -2816,6 +2819,7 @@ public abstract class AbstractDatabase implements Database { // configured things programmatically, so we must not set the // list but append it. + getConfiguredSyntheticReadonlyColumns().addAll(configuredSyntheticObjects.getReadonlyColumns()); getConfiguredSyntheticIdentities().addAll(configuredSyntheticObjects.getIdentities()); getConfiguredSyntheticPrimaryKeys().addAll(configuredSyntheticObjects.getPrimaryKeys()); getConfiguredSyntheticUniqueKeys().addAll(configuredSyntheticObjects.getUniqueKeys()); @@ -2833,6 +2837,8 @@ public abstract class AbstractDatabase implements Database { + if (!configuredSyntheticObjects.getReadonlyColumns().isEmpty()) + log.info("Commercial feature", "Synthetic read only columns are a commercial only feature. Please upgrade to the jOOQ Professional Edition"); if (!configuredSyntheticObjects.getUniqueKeys().isEmpty()) log.info("Commercial feature", "Synthetic unique keys are a commercial only feature. Please upgrade to the jOOQ Professional Edition"); if (!configuredSyntheticObjects.getForeignKeys().isEmpty()) @@ -2840,6 +2846,14 @@ public abstract class AbstractDatabase implements Database { } } + @Override + public List getConfiguredSyntheticReadonlyColumns() { + if (configuredSyntheticReadonlyColumns == null) + configuredSyntheticReadonlyColumns = new ArrayList<>(); + + return configuredSyntheticReadonlyColumns; + } + @Override public List getConfiguredSyntheticIdentities() { if (configuredSyntheticIdentities == null) @@ -2880,6 +2894,11 @@ public abstract class AbstractDatabase implements Database { return configuredSyntheticViews; } + @Override + public void markUsed(SyntheticReadonlyColumnType readonlyColumn) { + unusedSyntheticReadonlyColumns.remove(readonlyColumn); + } + @Override public void markUsed(SyntheticIdentityType identity) { unusedSyntheticIdentities.remove(identity); @@ -2905,6 +2924,11 @@ public abstract class AbstractDatabase implements Database { unusedSyntheticViews.remove(view); } + @Override + public List getUnusedSyntheticReadonlyColumns() { + return new ArrayList<>(unusedSyntheticReadonlyColumns); + } + @Override public List getUnusedSyntheticIdentities() { return new ArrayList<>(unusedSyntheticIdentities); diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/DataTypeDefinition.java b/jOOQ-meta/src/main/java/org/jooq/meta/DataTypeDefinition.java index 0dd41e74f9..5d51d6b72b 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/DataTypeDefinition.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/DataTypeDefinition.java @@ -110,6 +110,11 @@ public interface DataTypeDefinition { */ boolean isNullable(); + /** + * Whether this data type is readonly. + */ + boolean isReadonly(); + /** * Whether this data type is an identity. */ diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/Database.java b/jOOQ-meta/src/main/java/org/jooq/meta/Database.java index b7bc29b73d..e00f3587cf 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/Database.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/Database.java @@ -62,6 +62,7 @@ import org.jooq.meta.jaxb.SyntheticForeignKeyType; import org.jooq.meta.jaxb.SyntheticIdentityType; import org.jooq.meta.jaxb.SyntheticObjectsType; import org.jooq.meta.jaxb.SyntheticPrimaryKeyType; +import org.jooq.meta.jaxb.SyntheticReadonlyColumnType; import org.jooq.meta.jaxb.SyntheticUniqueKeyType; import org.jooq.meta.jaxb.SyntheticViewType; @@ -1080,6 +1081,11 @@ public interface Database extends AutoCloseable { */ void setConfiguredSyntheticObjects(SyntheticObjectsType configuredSyntheticObjects); + /** + * Get the configured synthetic readonly columns. + */ + List getConfiguredSyntheticReadonlyColumns(); + /** * Get the configured synthetic identities. */ @@ -1105,6 +1111,16 @@ public interface Database extends AutoCloseable { */ List getConfiguredSyntheticViews(); + /** + * Mark a synthetic readonly column as used. + */ + void markUsed(SyntheticReadonlyColumnType readonlyColumn); + + /** + * Retrieve the not-yet used synthetic readonly columns. + */ + List getUnusedSyntheticReadonlyColumns(); + /** * Mark a synthetic identity as used. */ diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/DefaultColumnDefinition.java b/jOOQ-meta/src/main/java/org/jooq/meta/DefaultColumnDefinition.java index b15ebdf33d..d51bdc0259 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/DefaultColumnDefinition.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/DefaultColumnDefinition.java @@ -44,6 +44,7 @@ import java.util.ArrayList; import java.util.List; import org.jooq.meta.jaxb.SyntheticIdentityType; +import org.jooq.meta.jaxb.SyntheticReadonlyColumnType; import org.jooq.tools.JooqLogger; /** @@ -57,20 +58,41 @@ public class DefaultColumnDefinition private static final JooqLogger log = JooqLogger.getLogger(DefaultColumnDefinition.class); private final int position; - private final boolean isIdentity; + private final boolean identity; + private final boolean readonly; private transient List replacedByEmbeddables; - public DefaultColumnDefinition(TableDefinition table, String name, int position, DataTypeDefinition type, - boolean isIdentity, String comment) { + public DefaultColumnDefinition( + TableDefinition table, + String name, + int position, + DataTypeDefinition type, + boolean identity, + String comment + ) { + this(table, name, position, type, identity, false, comment); + } + public DefaultColumnDefinition( + TableDefinition table, + String name, + int position, + DataTypeDefinition type, + boolean identity, + boolean readonly, + String comment + ) { super(table, name, position, type, comment); this.position = position; - this.isIdentity = isIdentity || isSyntheticIdentity(this); + this.identity = identity || isSyntheticIdentity(this); + this.readonly = readonly || isSyntheticReadonlyColumn(this); // [#6222] Copy the column's identity flag to the data type definition - if (type instanceof DefaultDataTypeDefinition) - ((DefaultDataTypeDefinition) type).identity(this.isIdentity); + if (type instanceof DefaultDataTypeDefinition) { DefaultDataTypeDefinition dd = (DefaultDataTypeDefinition) type; + dd.identity(this.identity); + dd.readonly(this.readonly); + } } @SuppressWarnings("unused") @@ -87,6 +109,24 @@ public class DefaultColumnDefinition } } + return false; + } + + private static boolean isSyntheticReadonlyColumn(DefaultColumnDefinition column) { + + + + + + + + + + + + + + return false; } @@ -117,7 +157,7 @@ public class DefaultColumnDefinition @Override public final boolean isIdentity() { - return isIdentity; + return identity; } diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/DefaultDataTypeDefinition.java b/jOOQ-meta/src/main/java/org/jooq/meta/DefaultDataTypeDefinition.java index 2f22c32abe..569ba139dd 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/DefaultDataTypeDefinition.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/DefaultDataTypeDefinition.java @@ -72,7 +72,8 @@ public class DefaultDataTypeDefinition implements DataTypeDefinition { private final String converter; private final String binding; private final boolean nullable; - private boolean isIdentity; + private boolean readonly; + private boolean identity; private final String defaultValue; private final int length; private final int precision; @@ -187,6 +188,10 @@ public class DefaultDataTypeDefinition implements DataTypeDefinition { } public DefaultDataTypeDefinition(Database database, SchemaDefinition schema, String typeName, Number length, Number precision, Number scale, Boolean nullable, String defaultValue, boolean isIdentity, Name userType, String converter, String binding, String javaType) { + this(database, schema, typeName, length, precision, scale, nullable, false, defaultValue, isIdentity, userType, converter, binding, javaType); + } + + public DefaultDataTypeDefinition(Database database, SchemaDefinition schema, String typeName, Number length, Number precision, Number scale, Boolean nullable, boolean readonly, String defaultValue, boolean identity, Name userType, String converter, String binding, String javaType) { this.database = database; this.schema = schema; @@ -215,8 +220,9 @@ public class DefaultDataTypeDefinition implements DataTypeDefinition { this.precision = precision == null ? 0 : precision.intValue(); this.scale = scale == null ? 0 : scale.intValue(); this.nullable = nullable == null ? true : nullable.booleanValue(); + this.readonly = readonly; this.defaultValue = defaultValue; - this.isIdentity = isIdentity; + this.identity = identity; } @Override @@ -238,14 +244,24 @@ public class DefaultDataTypeDefinition implements DataTypeDefinition { return nullable; } - public final DefaultDataTypeDefinition identity(boolean identity) { - this.isIdentity = identity; + public final DefaultDataTypeDefinition readonly(boolean r) { + this.readonly = r; + return this; + } + + @Override + public final boolean isReadonly() { + return readonly; + } + + public final DefaultDataTypeDefinition identity(boolean i) { + this.identity = i; return this; } @Override public final boolean isIdentity() { - return isIdentity; + return identity; } @Override diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ObjectFactory.java b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ObjectFactory.java index 19faa2ab38..690da15347 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ObjectFactory.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ObjectFactory.java @@ -173,6 +173,14 @@ public class ObjectFactory { return new SyntheticObjectsType(); } + /** + * Create an instance of {@link SyntheticReadonlyColumnType } + * + */ + public SyntheticReadonlyColumnType createSyntheticReadonlyColumnType() { + return new SyntheticReadonlyColumnType(); + } + /** * Create an instance of {@link SyntheticIdentityType } * diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/SyntheticObjectsType.java b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/SyntheticObjectsType.java index 07583bc798..b01b494c12 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/SyntheticObjectsType.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/SyntheticObjectsType.java @@ -31,6 +31,9 @@ public class SyntheticObjectsType implements Serializable, XMLAppendable { private final static long serialVersionUID = 31600L; + @XmlElementWrapper(name = "readonlyColumns") + @XmlElement(name = "readonlyColumn") + protected List readonlyColumns; @XmlElementWrapper(name = "identities") @XmlElement(name = "identity") protected List identities; @@ -47,6 +50,17 @@ public class SyntheticObjectsType implements Serializable, XMLAppendable @XmlElement(name = "view") protected List views; + public List getReadonlyColumns() { + if (readonlyColumns == null) { + readonlyColumns = new ArrayList(); + } + return readonlyColumns; + } + + public void setReadonlyColumns(List readonlyColumns) { + this.readonlyColumns = readonlyColumns; + } + public List getIdentities() { if (identities == null) { identities = new ArrayList(); @@ -102,6 +116,27 @@ public class SyntheticObjectsType implements Serializable, XMLAppendable this.views = views; } + public SyntheticObjectsType withReadonlyColumns(SyntheticReadonlyColumnType... values) { + if (values!= null) { + for (SyntheticReadonlyColumnType value: values) { + getReadonlyColumns().add(value); + } + } + return this; + } + + public SyntheticObjectsType withReadonlyColumns(Collection values) { + if (values!= null) { + getReadonlyColumns().addAll(values); + } + return this; + } + + public SyntheticObjectsType withReadonlyColumns(List readonlyColumns) { + setReadonlyColumns(readonlyColumns); + return this; + } + public SyntheticObjectsType withIdentities(SyntheticIdentityType... values) { if (values!= null) { for (SyntheticIdentityType value: values) { @@ -209,6 +244,7 @@ public class SyntheticObjectsType implements Serializable, XMLAppendable @Override public final void appendTo(XMLBuilder builder) { + builder.append("readonlyColumns", "readonlyColumn", readonlyColumns); builder.append("identities", "identity", identities); builder.append("primaryKeys", "primaryKey", primaryKeys); builder.append("uniqueKeys", "uniqueKey", uniqueKeys); @@ -235,6 +271,15 @@ public class SyntheticObjectsType implements Serializable, XMLAppendable return false; } SyntheticObjectsType other = ((SyntheticObjectsType) that); + if (readonlyColumns == null) { + if (other.readonlyColumns!= null) { + return false; + } + } else { + if (!readonlyColumns.equals(other.readonlyColumns)) { + return false; + } + } if (identities == null) { if (other.identities!= null) { return false; @@ -287,6 +332,7 @@ public class SyntheticObjectsType implements Serializable, XMLAppendable public int hashCode() { final int prime = 31; int result = 1; + result = ((prime*result)+((readonlyColumns == null)? 0 :readonlyColumns.hashCode())); result = ((prime*result)+((identities == null)? 0 :identities.hashCode())); result = ((prime*result)+((primaryKeys == null)? 0 :primaryKeys.hashCode())); result = ((prime*result)+((uniqueKeys == null)? 0 :uniqueKeys.hashCode())); diff --git a/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.16.0.xsd b/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.16.0.xsd index 69c9390f85..6a5e060c50 100644 --- a/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.16.0.xsd +++ b/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.16.0.xsd @@ -976,6 +976,10 @@ This feature is available in the commercial distribution only.]]>< + + + + @@ -1002,6 +1006,25 @@ This feature is available in the commercial distribution only.]]>< + + + + + + + + + + + + + + + + + + + diff --git a/jOOQ/src/main/java/org/jooq/DataType.java b/jOOQ/src/main/java/org/jooq/DataType.java index 1ef759cb70..79c4808810 100644 --- a/jOOQ/src/main/java/org/jooq/DataType.java +++ b/jOOQ/src/main/java/org/jooq/DataType.java @@ -424,6 +424,25 @@ public interface DataType extends Named { */ boolean nullable(); + /** + * Return a new data type like this, with a new readonly attribute. + *

+ * This feature is implemented in commercial distributions only. + * + * @param readonly The new readonly attribute value. + * @return The new data type + */ + @NotNull + @Support + DataType readonly(boolean readonly); + + /** + * Get the readonly attribute of this data type. + *

+ * This feature is implemented in commercial distributions only. + */ + boolean readonly(); + /** * Synonym for {@link #nullable(boolean)}, passing true as an * argument. diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java index 7eb28503c3..56303a2031 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java @@ -102,7 +102,14 @@ import org.jooq.types.UNumber; * @author Lukas Eder */ @SuppressWarnings({ "rawtypes", "unchecked" }) -abstract class AbstractDataType extends AbstractNamed implements DataType, UEmpty { +abstract class AbstractDataType +extends + AbstractNamed +implements + DataType, + UEmpty +{ + static final Set NO_SUPPORT_TIMESTAMP_PRECISION = SQLDialect.supportedBy(DERBY, FIREBIRD); AbstractDataType(Name name, Comment comment) { @@ -132,6 +139,12 @@ abstract class AbstractDataType extends AbstractNamed implements DataType, return nullable(false); } + @Override + public abstract boolean readonly(); + + @Override + public abstract DataType readonly(boolean r); + @Override public abstract DataType collation(Collation c); diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDataTypeX.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDataTypeX.java index f6a5c1a141..64a4eb19fe 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDataTypeX.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDataTypeX.java @@ -47,6 +47,8 @@ import org.jooq.Field; import org.jooq.Name; import org.jooq.Nullability; +import org.jetbrains.annotations.NotNull; + /** * @author Lukas Eder */ @@ -64,6 +66,7 @@ abstract class AbstractDataTypeX extends AbstractDataType { Integer newScale, Integer newLength, Nullability newNullability, + boolean newReadonly, Collation newCollation, CharacterSet newCharacterSet, boolean newIdentity, @@ -72,41 +75,46 @@ abstract class AbstractDataTypeX extends AbstractDataType { @Override public final DataType nullability(Nullability n) { - return construct(precision0(), scale0(), length0(), n, collation(), characterSet(), !n.nullable() && identity(), defaultValue()); + return construct(precision0(), scale0(), length0(), n, readonly(), collation(), characterSet(), !n.nullable() && identity(), defaultValue()); + } + + @Override + public final DataType readonly(boolean r) { + return construct(precision0(), scale0(), length0(), nullability(), r, collation(), characterSet(), identity(), defaultValue()); } @Override public final DataType collation(Collation c) { - return construct(precision0(), scale0(), length0(), nullability(), c, characterSet(), identity(), defaultValue()); + return construct(precision0(), scale0(), length0(), nullability(), readonly(), c, characterSet(), identity(), defaultValue()); } @Override public final DataType characterSet(CharacterSet c) { - return construct(precision0(), scale0(), length0(), nullability(), collation(), c, identity(), defaultValue()); + return construct(precision0(), scale0(), length0(), nullability(), readonly(), collation(), c, identity(), defaultValue()); } @Override public final DataType identity(boolean i) { - return construct(precision0(), scale0(), length0(), i ? NOT_NULL : nullability(), collation(), characterSet(), i, defaultValue()); + return construct(precision0(), scale0(), length0(), i ? NOT_NULL : nullability(), readonly(), collation(), characterSet(), i, defaultValue()); } @Override public final DataType default_(Field d) { - return construct(precision0(), scale0(), length0(), nullability(), collation(), characterSet(), identity(), d); + return construct(precision0(), scale0(), length0(), nullability(), readonly(), collation(), characterSet(), identity(), d); } @Override final AbstractDataTypeX precision1(Integer p, Integer s) { - return construct(p, s, length0(), nullability(), collation(), characterSet(), identity(), defaultValue()); + return construct(p, s, length0(), nullability(), readonly(), collation(), characterSet(), identity(), defaultValue()); } @Override final AbstractDataTypeX scale1(Integer s) { - return construct(precision0(), s, length0(), nullability(), collation(), characterSet(), identity(), defaultValue()); + return construct(precision0(), s, length0(), nullability(), readonly(), collation(), characterSet(), identity(), defaultValue()); } @Override final AbstractDataTypeX length1(Integer l) { - return construct(precision0(), scale0(), l, nullability(), collation(), characterSet(), identity(), defaultValue()); + return construct(precision0(), scale0(), l, nullability(), readonly(), collation(), characterSet(), identity(), defaultValue()); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/ArrayDataType.java b/jOOQ/src/main/java/org/jooq/impl/ArrayDataType.java index ed68a6e90e..f080d60437 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ArrayDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/ArrayDataType.java @@ -69,12 +69,13 @@ final class ArrayDataType extends DefaultDataType { Integer scale, Integer length, Nullability nullability, + boolean readonly, Collation collation, CharacterSet characterSet, boolean identity, Field defaultValue ) { - super(t, precision, scale, length, nullability, collation, characterSet, identity, defaultValue); + super(t, precision, scale, length, nullability, readonly, collation, characterSet, identity, defaultValue); this.elementType = elementType; } @@ -85,8 +86,8 @@ final class ArrayDataType extends DefaultDataType { Integer newPrecision, Integer newScale, Integer newLength, - Nullability - newNullability, + Nullability newNullability, + boolean newReadonly, Collation newCollation, CharacterSet newCharacterSet, boolean newIdentity, @@ -99,6 +100,7 @@ final class ArrayDataType extends DefaultDataType { newScale, newLength, newNullability, + newReadonly, newCollation, newCharacterSet, newIdentity, diff --git a/jOOQ/src/main/java/org/jooq/impl/ConvertedDataType.java b/jOOQ/src/main/java/org/jooq/impl/ConvertedDataType.java index 603e81408b..d9ce963f18 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ConvertedDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/ConvertedDataType.java @@ -81,6 +81,7 @@ final class ConvertedDataType extends AbstractDataTypeX { Integer newScale, Integer newLength, Nullability newNullability, + boolean newReadonly, Collation newCollation, CharacterSet newCharacterSet, boolean newIdentity, @@ -91,6 +92,7 @@ final class ConvertedDataType extends AbstractDataTypeX { newScale, newLength, newNullability, + newReadonly, newCollation, newCharacterSet, newIdentity, @@ -148,6 +150,11 @@ final class ConvertedDataType extends AbstractDataTypeX { return delegate.nullability(); } + @Override + public final boolean readonly() { + return delegate.readonly(); + } + @Override public final Collation collation() { return delegate.collation(); diff --git a/jOOQ/src/main/java/org/jooq/impl/DataTypeProxy.java b/jOOQ/src/main/java/org/jooq/impl/DataTypeProxy.java index 60b6c6f7a0..09bd8c2e80 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DataTypeProxy.java +++ b/jOOQ/src/main/java/org/jooq/impl/DataTypeProxy.java @@ -48,7 +48,6 @@ import org.jooq.Field; import org.jooq.Name; import org.jooq.Nullability; import org.jooq.SQLDialect; -import org.jooq.tools.StringUtils; /** * A mutable proxy for a temporary {@link DataType}, which can be replaced by a @@ -57,18 +56,20 @@ import org.jooq.tools.StringUtils; * @author Lukas Eder */ final class DataTypeProxy extends AbstractDataType { + private AbstractDataType type; private final Integer overridePrecision; private final Integer overrideScale; private final Integer overrideLength; private final Nullability overrideNullability; + private final Boolean overrideReadonly; private final Collation overrideCollation; private final CharacterSet overrideCharacterSet; private final Boolean overrideIdentity; private final Field overrideDefaultValue; DataTypeProxy(AbstractDataType type) { - this(type, null, null, null, null, null, null, null, null); + this(type, null, null, null, null, null, null, null, null, null); } private DataTypeProxy( @@ -77,6 +78,7 @@ final class DataTypeProxy extends AbstractDataType { Integer overrideScale, Integer overrideLength, Nullability overrideNullability, + Boolean overrideReadonly, Collation overrideCollation, CharacterSet overrideCharacterSet, Boolean overrideIdentity, @@ -89,6 +91,7 @@ final class DataTypeProxy extends AbstractDataType { this.overrideScale = overrideScale; this.overrideLength = overrideLength; this.overrideNullability = overrideNullability; + this.overrideReadonly = overrideReadonly; this.overrideCollation = overrideCollation; this.overrideCharacterSet = overrideCharacterSet; this.overrideIdentity = overrideIdentity; @@ -146,6 +149,7 @@ final class DataTypeProxy extends AbstractDataType { overrideScale, overrideLength, n, + overrideReadonly, overrideCollation, overrideCharacterSet, overrideIdentity, @@ -153,6 +157,31 @@ final class DataTypeProxy extends AbstractDataType { ); } + + + + + + + + + + + + + + + + + + + + + + + + + @Override public final Collation collation() { return defaultIfNull(overrideCollation, type.collation()); @@ -166,6 +195,7 @@ final class DataTypeProxy extends AbstractDataType { overrideScale, overrideLength, overrideNullability, + overrideReadonly, c, overrideCharacterSet, overrideIdentity, @@ -186,6 +216,7 @@ final class DataTypeProxy extends AbstractDataType { overrideScale, overrideLength, overrideNullability, + overrideReadonly, overrideCollation, c, overrideIdentity, @@ -206,6 +237,7 @@ final class DataTypeProxy extends AbstractDataType { overrideScale, overrideLength, overrideNullability, + overrideReadonly, overrideCollation, overrideCharacterSet, i, @@ -226,6 +258,7 @@ final class DataTypeProxy extends AbstractDataType { overrideScale, overrideLength, overrideNullability, + overrideReadonly, overrideCollation, overrideCharacterSet, overrideIdentity, @@ -276,6 +309,7 @@ final class DataTypeProxy extends AbstractDataType { s, overrideLength, overrideNullability, + overrideReadonly, overrideCollation, overrideCharacterSet, overrideIdentity, @@ -296,6 +330,7 @@ final class DataTypeProxy extends AbstractDataType { s, overrideLength, overrideNullability, + overrideReadonly, overrideCollation, overrideCharacterSet, overrideIdentity, @@ -316,6 +351,7 @@ final class DataTypeProxy extends AbstractDataType { overrideScale, l, overrideNullability, + overrideReadonly, overrideCollation, overrideCharacterSet, overrideIdentity, diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java b/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java index 4b15239155..6167acf07a 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java @@ -220,6 +220,7 @@ public class DefaultDataType extends AbstractDataTypeX { private final String typeName; private final Nullability nullability; + private final boolean readonly; private final Collation collation; private final CharacterSet characterSet; private final boolean identity; @@ -289,10 +290,10 @@ public class DefaultDataType extends AbstractDataTypeX { } DefaultDataType(SQLDialect dialect, DataType sqlDataType, Class type, Binding binding, Name qualifiedTypeName, String typeName, String castTypeName, Integer precision, Integer scale, Integer length, Nullability nullability, Field defaultValue) { - this(dialect, sqlDataType, type, binding, qualifiedTypeName, typeName, castTypeName, precision, scale, length, nullability, null, null, false, defaultValue); + this(dialect, sqlDataType, type, binding, qualifiedTypeName, typeName, castTypeName, precision, scale, length, nullability, false, null, null, false, defaultValue); } - DefaultDataType(SQLDialect dialect, DataType sqlDataType, Class type, Binding binding, Name qualifiedTypeName, String typeName, String castTypeName, Integer precision, Integer scale, Integer length, Nullability nullability, Collation collation, CharacterSet characterSet, boolean identity, Field defaultValue) { + DefaultDataType(SQLDialect dialect, DataType sqlDataType, Class type, Binding binding, Name qualifiedTypeName, String typeName, String castTypeName, Integer precision, Integer scale, Integer length, Nullability nullability, boolean readonly, Collation collation, CharacterSet characterSet, boolean identity, Field defaultValue) { super(qualifiedTypeName, NO_COMMENT); // Initialise final instance members @@ -311,6 +312,7 @@ public class DefaultDataType extends AbstractDataTypeX { this.castTypeSuffix = split.length > 1 ? split[1] : ""; this.nullability = nullability; + this.readonly = readonly; this.collation = collation; this.characterSet = characterSet; this.identity = identity; @@ -350,12 +352,13 @@ public class DefaultDataType extends AbstractDataTypeX { Integer newScale, Integer newLength, Nullability newNullability, + boolean newReadonly, Collation newCollation, CharacterSet newCharacterSet, boolean newIdentity, Field newDefaultValue ) { - return new DefaultDataType<>(this, newPrecision, newScale, newLength, newNullability, newCollation, newCharacterSet, newIdentity, newDefaultValue); + return new DefaultDataType<>(this, newPrecision, newScale, newLength, newNullability, newReadonly, newCollation, newCharacterSet, newIdentity, newDefaultValue); } /** @@ -367,6 +370,7 @@ public class DefaultDataType extends AbstractDataTypeX { Integer scale, Integer length, Nullability nullability, + boolean readonly, Collation collation, CharacterSet characterSet, boolean identity, @@ -384,6 +388,7 @@ public class DefaultDataType extends AbstractDataTypeX { this.castTypeSuffix = t.castTypeSuffix0(); this.nullability = nullability; + this.readonly = readonly; this.collation = collation; this.characterSet = characterSet; this.identity = identity; @@ -418,6 +423,11 @@ public class DefaultDataType extends AbstractDataTypeX { return nullability; } + @Override + public final boolean readonly() { + return readonly; + } + @Override public final Collation collation() { return collation; @@ -474,7 +484,7 @@ public class DefaultDataType extends AbstractDataTypeX { // ... and then, set them back to the original value // [#2710] TODO: Remove this logic along with cached data types - return dataType.construct(precision, scale, length, nullability, collation, characterSet, identity, defaultValue); + return dataType.construct(precision, scale, length, nullability, readonly, collation, characterSet, identity, defaultValue); } // If this is already the dialect's specific data type, return this diff --git a/jOOQ/src/main/java/org/jooq/impl/DomainDataType.java b/jOOQ/src/main/java/org/jooq/impl/DomainDataType.java index 7740edd9a7..057dc63879 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DomainDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/DomainDataType.java @@ -64,6 +64,7 @@ final class DomainDataType extends DefaultDataType { baseType.scaleDefined() ? baseType.scale() : null, baseType.lengthDefined() ? baseType.length() : null, baseType.nullability(), + baseType.readonly(), null, // TODO: Collation null, // TODO: CharacterSet (?) false, diff --git a/jOOQ/src/main/java/org/jooq/impl/MultisetDataType.java b/jOOQ/src/main/java/org/jooq/impl/MultisetDataType.java index ddec58ef86..a8d9930559 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MultisetDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/MultisetDataType.java @@ -84,12 +84,13 @@ final class MultisetDataType extends DefaultDataType Integer scale, Integer length, Nullability nullability, + boolean readonly, Collation collation, CharacterSet characterSet, boolean identity, Field> defaultValue ) { - super(t, precision, scale, length, nullability, collation, characterSet, identity, defaultValue); + super(t, precision, scale, length, nullability, readonly, collation, characterSet, identity, defaultValue); this.row = row; this.recordType = recordType; @@ -101,8 +102,8 @@ final class MultisetDataType extends DefaultDataType Integer newPrecision, Integer newScale, Integer newLength, - Nullability - newNullability, + Nullability newNullability, + boolean newReadonly, Collation newCollation, CharacterSet newCharacterSet, boolean newIdentity, @@ -116,6 +117,7 @@ final class MultisetDataType extends DefaultDataType newScale, newLength, newNullability, + newReadonly, newCollation, newCharacterSet, newIdentity, diff --git a/jOOQ/src/main/java/org/jooq/impl/RecordDataType.java b/jOOQ/src/main/java/org/jooq/impl/RecordDataType.java index ed0e9185c6..7279d81d99 100644 --- a/jOOQ/src/main/java/org/jooq/impl/RecordDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/RecordDataType.java @@ -85,12 +85,13 @@ final class RecordDataType extends DefaultDataType { Integer scale, Integer length, Nullability nullability, + boolean readonly, Collation collation, CharacterSet characterSet, boolean identity, Field defaultValue ) { - super(t, precision, scale, length, nullability, collation, characterSet, identity, defaultValue); + super(t, precision, scale, length, nullability, readonly, collation, characterSet, identity, defaultValue); this.row = row; } @@ -101,8 +102,8 @@ final class RecordDataType extends DefaultDataType { Integer newPrecision, Integer newScale, Integer newLength, - Nullability - newNullability, + Nullability newNullability, + boolean newReadonly, Collation newCollation, CharacterSet newCharacterSet, boolean newIdentity, @@ -115,6 +116,7 @@ final class RecordDataType extends DefaultDataType { newScale, newLength, newNullability, + newReadonly, newCollation, newCharacterSet, newIdentity,