[jOOQ/jOOQ#9864] Add support for readonly columns

- Added synthetic readonly column codegen config
- Added code generation logic
- Added DataTypeDefinition.readonly()
- Added DataType.readonly()
This commit is contained in:
Lukas Eder 2021-10-29 16:24:01 +02:00
parent 0c7c6c16dc
commit 9de6ba83de
19 changed files with 327 additions and 40 deletions

View File

@ -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()) {

View File

@ -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<EmbeddableDefinitionType> unusedEmbeddables = new HashSet<>();
private List<CommentType> configuredComments = new ArrayList<>();
private Set<CommentType> unusedComments = new HashSet<>();
private List<SyntheticReadonlyColumnType> configuredSyntheticReadonlyColumns = new ArrayList<>();
private Set<SyntheticReadonlyColumnType> unusedSyntheticReadonlyColumns = new HashSet<>();
private List<SyntheticIdentityType> configuredSyntheticIdentities = new ArrayList<>();
private Set<SyntheticIdentityType> unusedSyntheticIdentities = new HashSet<>();
private List<SyntheticPrimaryKeyType> 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<SyntheticReadonlyColumnType> getConfiguredSyntheticReadonlyColumns() {
if (configuredSyntheticReadonlyColumns == null)
configuredSyntheticReadonlyColumns = new ArrayList<>();
return configuredSyntheticReadonlyColumns;
}
@Override
public List<SyntheticIdentityType> 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<SyntheticReadonlyColumnType> getUnusedSyntheticReadonlyColumns() {
return new ArrayList<>(unusedSyntheticReadonlyColumns);
}
@Override
public List<SyntheticIdentityType> getUnusedSyntheticIdentities() {
return new ArrayList<>(unusedSyntheticIdentities);

View File

@ -110,6 +110,11 @@ public interface DataTypeDefinition {
*/
boolean isNullable();
/**
* Whether this data type is readonly.
*/
boolean isReadonly();
/**
* Whether this data type is an identity.
*/

View File

@ -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<SyntheticReadonlyColumnType> getConfiguredSyntheticReadonlyColumns();
/**
* Get the configured synthetic identities.
*/
@ -1105,6 +1111,16 @@ public interface Database extends AutoCloseable {
*/
List<SyntheticViewType> getConfiguredSyntheticViews();
/**
* Mark a synthetic readonly column as used.
*/
void markUsed(SyntheticReadonlyColumnType readonlyColumn);
/**
* Retrieve the not-yet used synthetic readonly columns.
*/
List<SyntheticReadonlyColumnType> getUnusedSyntheticReadonlyColumns();
/**
* Mark a synthetic identity as used.
*/

View File

@ -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<EmbeddableDefinition> 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;
}

View File

@ -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

View File

@ -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 }
*

View File

@ -31,6 +31,9 @@ public class SyntheticObjectsType implements Serializable, XMLAppendable
{
private final static long serialVersionUID = 31600L;
@XmlElementWrapper(name = "readonlyColumns")
@XmlElement(name = "readonlyColumn")
protected List<SyntheticReadonlyColumnType> readonlyColumns;
@XmlElementWrapper(name = "identities")
@XmlElement(name = "identity")
protected List<SyntheticIdentityType> identities;
@ -47,6 +50,17 @@ public class SyntheticObjectsType implements Serializable, XMLAppendable
@XmlElement(name = "view")
protected List<SyntheticViewType> views;
public List<SyntheticReadonlyColumnType> getReadonlyColumns() {
if (readonlyColumns == null) {
readonlyColumns = new ArrayList<SyntheticReadonlyColumnType>();
}
return readonlyColumns;
}
public void setReadonlyColumns(List<SyntheticReadonlyColumnType> readonlyColumns) {
this.readonlyColumns = readonlyColumns;
}
public List<SyntheticIdentityType> getIdentities() {
if (identities == null) {
identities = new ArrayList<SyntheticIdentityType>();
@ -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<SyntheticReadonlyColumnType> values) {
if (values!= null) {
getReadonlyColumns().addAll(values);
}
return this;
}
public SyntheticObjectsType withReadonlyColumns(List<SyntheticReadonlyColumnType> 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()));

View File

@ -976,6 +976,10 @@ This feature is available in the commercial distribution only.]]></jxb:javadoc><
<complexType name="SyntheticObjectsType">
<annotation><appinfo><jxb:class><jxb:javadoc><![CDATA[Synthetic objects configuration.]]></jxb:javadoc></jxb:class></appinfo></annotation>
<all>
<element name="readonlyColumns" type="tns:SyntheticReadonlyColumnsType" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Synthetic read only columns configuration]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="identities" type="tns:SyntheticIdentitiesType" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Synthetic identity configuration]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
@ -1002,6 +1006,25 @@ This feature is available in the commercial distribution only.]]></jxb:javadoc><
</all>
</complexType>
<complexType name="SyntheticReadonlyColumnsType">
<sequence>
<element name="readonlyColumn" type="tns:SyntheticReadonlyColumnType" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
</complexType>
<complexType name="SyntheticReadonlyColumnType">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Synthetic readonly column configuration]]></jxb:javadoc></jxb:property></appinfo></annotation>
<all>
<element name="tables" type="string" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[A regular expression matching all tables on which to apply this synthetic readonly column.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="fields" type="string" minOccurs="1" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[A regular expression matching all fields on which to apply this synthetic readonly column.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
</all>
</complexType>
<complexType name="SyntheticIdentitiesType">
<sequence>
<element name="identity" type="tns:SyntheticIdentityType" minOccurs="1" maxOccurs="unbounded"/>

View File

@ -424,6 +424,25 @@ public interface DataType<T> extends Named {
*/
boolean nullable();
/**
* Return a new data type like this, with a new readonly attribute.
* <p>
* This feature is implemented in commercial distributions only.
*
* @param readonly The new readonly attribute value.
* @return The new data type
*/
@NotNull
@Support
DataType<T> readonly(boolean readonly);
/**
* Get the readonly attribute of this data type.
* <p>
* This feature is implemented in commercial distributions only.
*/
boolean readonly();
/**
* Synonym for {@link #nullable(boolean)}, passing <code>true</code> as an
* argument.

View File

@ -102,7 +102,14 @@ import org.jooq.types.UNumber;
* @author Lukas Eder
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
abstract class AbstractDataType<T> extends AbstractNamed implements DataType<T>, UEmpty {
abstract class AbstractDataType<T>
extends
AbstractNamed
implements
DataType<T>,
UEmpty
{
static final Set<SQLDialect> NO_SUPPORT_TIMESTAMP_PRECISION = SQLDialect.supportedBy(DERBY, FIREBIRD);
AbstractDataType(Name name, Comment comment) {
@ -132,6 +139,12 @@ abstract class AbstractDataType<T> extends AbstractNamed implements DataType<T>,
return nullable(false);
}
@Override
public abstract boolean readonly();
@Override
public abstract DataType<T> readonly(boolean r);
@Override
public abstract DataType<T> collation(Collation c);

View File

@ -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<T> extends AbstractDataType<T> {
Integer newScale,
Integer newLength,
Nullability newNullability,
boolean newReadonly,
Collation newCollation,
CharacterSet newCharacterSet,
boolean newIdentity,
@ -72,41 +75,46 @@ abstract class AbstractDataTypeX<T> extends AbstractDataType<T> {
@Override
public final DataType<T> 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<T> readonly(boolean r) {
return construct(precision0(), scale0(), length0(), nullability(), r, collation(), characterSet(), identity(), defaultValue());
}
@Override
public final DataType<T> 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<T> 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<T> 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<T> default_(Field<T> 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<T> 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<T> 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<T> length1(Integer l) {
return construct(precision0(), scale0(), l, nullability(), collation(), characterSet(), identity(), defaultValue());
return construct(precision0(), scale0(), l, nullability(), readonly(), collation(), characterSet(), identity(), defaultValue());
}
}

View File

@ -69,12 +69,13 @@ final class ArrayDataType<T> extends DefaultDataType<T[]> {
Integer scale,
Integer length,
Nullability nullability,
boolean readonly,
Collation collation,
CharacterSet characterSet,
boolean identity,
Field<T[]> 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<T> extends DefaultDataType<T[]> {
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<T> extends DefaultDataType<T[]> {
newScale,
newLength,
newNullability,
newReadonly,
newCollation,
newCharacterSet,
newIdentity,

View File

@ -81,6 +81,7 @@ final class ConvertedDataType<T, U> extends AbstractDataTypeX<U> {
Integer newScale,
Integer newLength,
Nullability newNullability,
boolean newReadonly,
Collation newCollation,
CharacterSet newCharacterSet,
boolean newIdentity,
@ -91,6 +92,7 @@ final class ConvertedDataType<T, U> extends AbstractDataTypeX<U> {
newScale,
newLength,
newNullability,
newReadonly,
newCollation,
newCharacterSet,
newIdentity,
@ -148,6 +150,11 @@ final class ConvertedDataType<T, U> extends AbstractDataTypeX<U> {
return delegate.nullability();
}
@Override
public final boolean readonly() {
return delegate.readonly();
}
@Override
public final Collation collation() {
return delegate.collation();

View File

@ -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<T> extends AbstractDataType<T> {
private AbstractDataType<T> 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<T> overrideDefaultValue;
DataTypeProxy(AbstractDataType<T> 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<T> extends AbstractDataType<T> {
Integer overrideScale,
Integer overrideLength,
Nullability overrideNullability,
Boolean overrideReadonly,
Collation overrideCollation,
CharacterSet overrideCharacterSet,
Boolean overrideIdentity,
@ -89,6 +91,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
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<T> extends AbstractDataType<T> {
overrideScale,
overrideLength,
n,
overrideReadonly,
overrideCollation,
overrideCharacterSet,
overrideIdentity,
@ -153,6 +157,31 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
);
}
@Override
public final Collation collation() {
return defaultIfNull(overrideCollation, type.collation());
@ -166,6 +195,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
overrideScale,
overrideLength,
overrideNullability,
overrideReadonly,
c,
overrideCharacterSet,
overrideIdentity,
@ -186,6 +216,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
overrideScale,
overrideLength,
overrideNullability,
overrideReadonly,
overrideCollation,
c,
overrideIdentity,
@ -206,6 +237,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
overrideScale,
overrideLength,
overrideNullability,
overrideReadonly,
overrideCollation,
overrideCharacterSet,
i,
@ -226,6 +258,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
overrideScale,
overrideLength,
overrideNullability,
overrideReadonly,
overrideCollation,
overrideCharacterSet,
overrideIdentity,
@ -276,6 +309,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
s,
overrideLength,
overrideNullability,
overrideReadonly,
overrideCollation,
overrideCharacterSet,
overrideIdentity,
@ -296,6 +330,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
s,
overrideLength,
overrideNullability,
overrideReadonly,
overrideCollation,
overrideCharacterSet,
overrideIdentity,
@ -316,6 +351,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
overrideScale,
l,
overrideNullability,
overrideReadonly,
overrideCollation,
overrideCharacterSet,
overrideIdentity,

View File

@ -220,6 +220,7 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
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<T> extends AbstractDataTypeX<T> {
}
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, Field<T> 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<T> sqlDataType, Class<T> type, Binding<?, T> binding, Name qualifiedTypeName, String typeName, String castTypeName, Integer precision, Integer scale, Integer length, Nullability nullability, 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, Collation collation, CharacterSet characterSet, boolean identity, Field<T> defaultValue) {
super(qualifiedTypeName, NO_COMMENT);
// Initialise final instance members
@ -311,6 +312,7 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
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<T> extends AbstractDataTypeX<T> {
Integer newScale,
Integer newLength,
Nullability newNullability,
boolean newReadonly,
Collation newCollation,
CharacterSet newCharacterSet,
boolean newIdentity,
Field<T> 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<T> extends AbstractDataTypeX<T> {
Integer scale,
Integer length,
Nullability nullability,
boolean readonly,
Collation collation,
CharacterSet characterSet,
boolean identity,
@ -384,6 +388,7 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
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<T> extends AbstractDataTypeX<T> {
return nullability;
}
@Override
public final boolean readonly() {
return readonly;
}
@Override
public final Collation collation() {
return collation;
@ -474,7 +484,7 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
// ... 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

View File

@ -64,6 +64,7 @@ final class DomainDataType<T> extends DefaultDataType<T> {
baseType.scaleDefined() ? baseType.scale() : null,
baseType.lengthDefined() ? baseType.length() : null,
baseType.nullability(),
baseType.readonly(),
null, // TODO: Collation
null, // TODO: CharacterSet (?)
false,

View File

@ -84,12 +84,13 @@ final class MultisetDataType<R extends Record> extends DefaultDataType<Result<R>
Integer scale,
Integer length,
Nullability nullability,
boolean readonly,
Collation collation,
CharacterSet characterSet,
boolean identity,
Field<Result<R>> 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<R extends Record> extends DefaultDataType<Result<R>
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<R extends Record> extends DefaultDataType<Result<R>
newScale,
newLength,
newNullability,
newReadonly,
newCollation,
newCharacterSet,
newIdentity,

View File

@ -85,12 +85,13 @@ final class RecordDataType<R extends Record> extends DefaultDataType<R> {
Integer scale,
Integer length,
Nullability nullability,
boolean readonly,
Collation collation,
CharacterSet characterSet,
boolean identity,
Field<R> 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<R extends Record> extends DefaultDataType<R> {
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<R extends Record> extends DefaultDataType<R> {
newScale,
newLength,
newNullability,
newReadonly,
newCollation,
newCharacterSet,
newIdentity,