[jOOQ/jOOQ#6492] Add support for computed columns
- Add DataType<T>.generatedAlwaysAs(Field<T>) - Add code generation support for: - H2 - PostgreSQL - Added parser support - Added code generation tests - Added DDL support
This commit is contained in:
parent
b2465ca45b
commit
08be0478da
@ -8489,6 +8489,7 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
baseType
|
||||
) + ".getArrayDataType()";
|
||||
}
|
||||
@ -8504,6 +8505,7 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
type.isNullable(),
|
||||
type.isIdentity(),
|
||||
type.isReadonly(),
|
||||
type.getGeneratedAlwaysAs(),
|
||||
type.getDefaultValue(),
|
||||
type.getQualifiedUserType()
|
||||
);
|
||||
@ -8749,7 +8751,21 @@ 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, boolean r, 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 g,
|
||||
String d,
|
||||
Name u
|
||||
) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (db.getArray(schema, u) != null) {
|
||||
@ -8808,6 +8824,8 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (d != null)
|
||||
dataType = dataType.defaultValue((Field) DSL.field(d, dataType));
|
||||
|
||||
@ -8863,6 +8881,18 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// [#5291] Some dialects report valid SQL expresions (e.g. PostgreSQL), others
|
||||
// report actual values (e.g. MySQL).
|
||||
if (dataType.defaulted()) {
|
||||
|
||||
@ -50,7 +50,6 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
// ...
|
||||
import org.jooq.meta.jaxb.SyntheticReadonlyColumnType;
|
||||
import org.jooq.meta.jaxb.SyntheticReadonlyRowidType;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
import org.jooq.tools.StringUtils;
|
||||
|
||||
@ -115,6 +115,16 @@ public interface DataTypeDefinition {
|
||||
*/
|
||||
boolean isReadonly();
|
||||
|
||||
/**
|
||||
* Whether this data type is computed.
|
||||
*/
|
||||
boolean isComputed();
|
||||
|
||||
/**
|
||||
* The computed column expression.
|
||||
*/
|
||||
String getGeneratedAlwaysAs();
|
||||
|
||||
/**
|
||||
* Whether this data type is an identity.
|
||||
*/
|
||||
|
||||
@ -73,6 +73,7 @@ public class DefaultDataTypeDefinition implements DataTypeDefinition {
|
||||
private final String binding;
|
||||
private final boolean nullable;
|
||||
private boolean readonly;
|
||||
private String generatedAlwaysAs;
|
||||
private boolean identity;
|
||||
private final String defaultValue;
|
||||
private final int length;
|
||||
@ -188,10 +189,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);
|
||||
this(database, schema, typeName, length, precision, scale, nullable, false, null, 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) {
|
||||
public DefaultDataTypeDefinition(Database database, SchemaDefinition schema, String typeName, Number length, Number precision, Number scale, Boolean nullable, boolean readonly, String generatedAlwaysAs, String defaultValue, boolean identity, Name userType, String converter, String binding, String javaType) {
|
||||
this.database = database;
|
||||
this.schema = schema;
|
||||
|
||||
@ -221,6 +222,7 @@ public class DefaultDataTypeDefinition implements DataTypeDefinition {
|
||||
this.scale = scale == null ? 0 : scale.intValue();
|
||||
this.nullable = nullable == null ? true : nullable.booleanValue();
|
||||
this.readonly = readonly;
|
||||
this.generatedAlwaysAs = generatedAlwaysAs;
|
||||
this.defaultValue = defaultValue;
|
||||
this.identity = identity;
|
||||
}
|
||||
@ -254,6 +256,21 @@ public class DefaultDataTypeDefinition implements DataTypeDefinition {
|
||||
return readonly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isComputed() {
|
||||
return getGeneratedAlwaysAs() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getGeneratedAlwaysAs() {
|
||||
return generatedAlwaysAs;
|
||||
}
|
||||
|
||||
public final DefaultDataTypeDefinition generatedAlwaysAs(String g) {
|
||||
this.generatedAlwaysAs = g;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final DefaultDataTypeDefinition identity(boolean i) {
|
||||
this.identity = i;
|
||||
return this;
|
||||
|
||||
@ -109,6 +109,7 @@ public class H2TableDefinition extends AbstractTableDefinition {
|
||||
COLUMNS.NUMERIC_PRECISION.decode(maxP, zero(), COLUMNS.NUMERIC_PRECISION).as(COLUMNS.NUMERIC_PRECISION),
|
||||
COLUMNS.NUMERIC_SCALE.decode(maxS, zero(), COLUMNS.NUMERIC_SCALE).as(COLUMNS.NUMERIC_SCALE),
|
||||
COLUMNS.IS_NULLABLE,
|
||||
COLUMNS.IS_COMPUTED,
|
||||
COLUMNS.COLUMN_DEFAULT,
|
||||
COLUMNS.REMARKS,
|
||||
COLUMNS.SEQUENCE_NAME,
|
||||
@ -132,6 +133,7 @@ public class H2TableDefinition extends AbstractTableDefinition {
|
||||
null != record.get(COLUMNS.SEQUENCE_NAME)
|
||||
|| defaultString(record.get(COLUMNS.COLUMN_DEFAULT)).trim().toLowerCase().startsWith("nextval");
|
||||
|
||||
boolean isComputed = record.get(COLUMNS.IS_COMPUTED, boolean.class);
|
||||
|
||||
// [#7644] H2 puts DATETIME_PRECISION in NUMERIC_SCALE column
|
||||
boolean isTimestamp = record.get(COLUMNS.TYPE_NAME).trim().toLowerCase().startsWith("timestamp");
|
||||
@ -153,9 +155,9 @@ public class H2TableDefinition extends AbstractTableDefinition {
|
||||
? 0
|
||||
: record.get(COLUMNS.NUMERIC_SCALE),
|
||||
record.get(COLUMNS.IS_NULLABLE, boolean.class),
|
||||
isIdentity ? null : record.get(COLUMNS.COLUMN_DEFAULT),
|
||||
isIdentity || isComputed ? null : record.get(COLUMNS.COLUMN_DEFAULT),
|
||||
userType
|
||||
);
|
||||
).generatedAlwaysAs(isComputed ? record.get(COLUMNS.COLUMN_DEFAULT) : null);
|
||||
|
||||
result.add(new DefaultColumnDefinition(
|
||||
getDatabase().getTable(getSchema(), getName()),
|
||||
|
||||
@ -51,7 +51,6 @@ import static org.jooq.meta.postgres.pg_catalog.Tables.PG_ATTRIBUTE;
|
||||
import static org.jooq.meta.postgres.pg_catalog.Tables.PG_CLASS;
|
||||
import static org.jooq.meta.postgres.pg_catalog.Tables.PG_DESCRIPTION;
|
||||
import static org.jooq.meta.postgres.pg_catalog.Tables.PG_NAMESPACE;
|
||||
import static org.jooq.util.postgres.PostgresDSL.oid;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
@ -124,6 +123,7 @@ public class PostgresTableDefinition extends AbstractTableDefinition {
|
||||
COLUMNS.NUMERIC_SCALE,
|
||||
(when(isIdentity, inline("YES"))).as(COLUMNS.IS_IDENTITY),
|
||||
COLUMNS.IS_NULLABLE,
|
||||
COLUMNS.GENERATION_EXPRESSION,
|
||||
(when(isIdentity, inline(null, String.class)).else_(COLUMNS.COLUMN_DEFAULT)).as(COLUMNS.COLUMN_DEFAULT),
|
||||
coalesce(COLUMNS.DOMAIN_SCHEMA, udtSchema).as(COLUMNS.UDT_SCHEMA),
|
||||
coalesce(COLUMNS.DOMAIN_NAME, COLUMNS.UDT_NAME).as(COLUMNS.UDT_NAME),
|
||||
@ -166,7 +166,7 @@ public class PostgresTableDefinition extends AbstractTableDefinition {
|
||||
record.get(COLUMNS.UDT_SCHEMA),
|
||||
record.get(COLUMNS.UDT_NAME)
|
||||
)
|
||||
);
|
||||
).generatedAlwaysAs(record.get(COLUMNS.GENERATION_EXPRESSION));
|
||||
|
||||
ColumnDefinition column = new DefaultColumnDefinition(
|
||||
getDatabase().getTable(getSchema(), getName()),
|
||||
|
||||
@ -443,6 +443,44 @@ public interface DataType<T> extends Named {
|
||||
*/
|
||||
boolean readonly();
|
||||
|
||||
/**
|
||||
* Whether this column is computed.
|
||||
* <p>
|
||||
* This feature is implemented in commercial distributions only.
|
||||
*/
|
||||
boolean computed();
|
||||
|
||||
/**
|
||||
* Set the computed column expression of this data type.
|
||||
* <p>
|
||||
* This implicitly sets {@link #readonly()} to <code>true</code>.
|
||||
* <p>
|
||||
* This feature is implemented in commercial distributions only.
|
||||
*/
|
||||
@NotNull
|
||||
@Support({ POSTGRES })
|
||||
DataType<T> generatedAlwaysAs(T generatedAlwaysAsValue);
|
||||
|
||||
/**
|
||||
* Set the computed column expression of this data type.
|
||||
* <p>
|
||||
* This implicitly sets {@link #readonly()} to <code>true</code>.
|
||||
* <p>
|
||||
* This feature is implemented in commercial distributions only.
|
||||
*/
|
||||
@NotNull
|
||||
@Support({ POSTGRES })
|
||||
DataType<T> generatedAlwaysAs(Field<T> generatedAlwaysAsValue);
|
||||
|
||||
/**
|
||||
* Get the computed column expression of this data type, if any.
|
||||
* <p>
|
||||
* This feature is implemented in commercial distributions only.
|
||||
*/
|
||||
@Nullable
|
||||
@Support({ POSTGRES })
|
||||
Field<T> generatedAlwaysAs();
|
||||
|
||||
/**
|
||||
* Synonym for {@link #nullable(boolean)}, passing <code>true</code> as an
|
||||
* argument.
|
||||
|
||||
@ -145,6 +145,22 @@ implements
|
||||
@Override
|
||||
public abstract DataType<T> readonly(boolean r);
|
||||
|
||||
@Override
|
||||
public final boolean computed() {
|
||||
return generatedAlwaysAs() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> generatedAlwaysAs(T g) {
|
||||
return generatedAlwaysAs(Tools.field(g, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract DataType<T> generatedAlwaysAs(Field<T> generatedAlwaysAsValue);
|
||||
|
||||
@Override
|
||||
public abstract Field<T> generatedAlwaysAs();
|
||||
|
||||
@Override
|
||||
public abstract DataType<T> collation(Collation c);
|
||||
|
||||
|
||||
@ -47,8 +47,6 @@ import org.jooq.Field;
|
||||
import org.jooq.Name;
|
||||
import org.jooq.Nullability;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
@ -67,6 +65,7 @@ abstract class AbstractDataTypeX<T> extends AbstractDataType<T> {
|
||||
Integer newLength,
|
||||
Nullability newNullability,
|
||||
boolean newReadonly,
|
||||
Field<T> newGeneratedAlwaysAs,
|
||||
Collation newCollation,
|
||||
CharacterSet newCharacterSet,
|
||||
boolean newIdentity,
|
||||
@ -75,46 +74,161 @@ abstract class AbstractDataTypeX<T> extends AbstractDataType<T> {
|
||||
|
||||
@Override
|
||||
public final DataType<T> nullability(Nullability n) {
|
||||
return construct(precision0(), scale0(), length0(), n, readonly(), collation(), characterSet(), !n.nullable() && identity(), defaultValue());
|
||||
return construct(
|
||||
precision0(),
|
||||
scale0(),
|
||||
length0(),
|
||||
n,
|
||||
readonly(),
|
||||
generatedAlwaysAs(),
|
||||
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());
|
||||
return construct(
|
||||
precision0(),
|
||||
scale0(),
|
||||
length0(),
|
||||
nullability(),
|
||||
r,
|
||||
generatedAlwaysAs(),
|
||||
collation(),
|
||||
characterSet(),
|
||||
identity(),
|
||||
defaultValue()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> generatedAlwaysAs(Field<T> g) {
|
||||
return construct(
|
||||
precision0(),
|
||||
scale0(),
|
||||
length0(),
|
||||
nullability(),
|
||||
readonly(),
|
||||
g,
|
||||
collation(),
|
||||
characterSet(),
|
||||
identity(),
|
||||
defaultValue()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> collation(Collation c) {
|
||||
return construct(precision0(), scale0(), length0(), nullability(), readonly(), c, characterSet(), identity(), defaultValue());
|
||||
return construct(
|
||||
precision0(),
|
||||
scale0(),
|
||||
length0(),
|
||||
nullability(),
|
||||
readonly(),
|
||||
generatedAlwaysAs(),
|
||||
c,
|
||||
characterSet(),
|
||||
identity(),
|
||||
defaultValue()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> characterSet(CharacterSet c) {
|
||||
return construct(precision0(), scale0(), length0(), nullability(), readonly(), collation(), c, identity(), defaultValue());
|
||||
return construct(
|
||||
precision0(),
|
||||
scale0(),
|
||||
length0(),
|
||||
nullability(),
|
||||
readonly(),
|
||||
generatedAlwaysAs(),
|
||||
collation(),
|
||||
c,
|
||||
identity(),
|
||||
defaultValue()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> identity(boolean i) {
|
||||
return construct(precision0(), scale0(), length0(), i ? NOT_NULL : nullability(), readonly(), collation(), characterSet(), i, defaultValue());
|
||||
return construct(
|
||||
precision0(),
|
||||
scale0(),
|
||||
length0(),
|
||||
i ? NOT_NULL : nullability(),
|
||||
readonly(),
|
||||
generatedAlwaysAs(),
|
||||
collation(),
|
||||
characterSet(),
|
||||
i,
|
||||
defaultValue()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> default_(Field<T> d) {
|
||||
return construct(precision0(), scale0(), length0(), nullability(), readonly(), collation(), characterSet(), identity(), d);
|
||||
return construct(
|
||||
precision0(),
|
||||
scale0(),
|
||||
length0(),
|
||||
nullability(),
|
||||
readonly(),
|
||||
generatedAlwaysAs(),
|
||||
collation(),
|
||||
characterSet(),
|
||||
identity(),
|
||||
d
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
final AbstractDataTypeX<T> precision1(Integer p, Integer s) {
|
||||
return construct(p, s, length0(), nullability(), readonly(), collation(), characterSet(), identity(), defaultValue());
|
||||
return construct(
|
||||
p,
|
||||
s,
|
||||
length0(),
|
||||
nullability(),
|
||||
readonly(),
|
||||
generatedAlwaysAs(),
|
||||
collation(),
|
||||
characterSet(),
|
||||
identity(),
|
||||
defaultValue()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
final AbstractDataTypeX<T> scale1(Integer s) {
|
||||
return construct(precision0(), s, length0(), nullability(), readonly(), collation(), characterSet(), identity(), defaultValue());
|
||||
return construct(
|
||||
precision0(),
|
||||
s,
|
||||
length0(),
|
||||
nullability(),
|
||||
readonly(),
|
||||
generatedAlwaysAs(),
|
||||
collation(),
|
||||
characterSet(),
|
||||
identity(),
|
||||
defaultValue()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
final AbstractDataTypeX<T> length1(Integer l) {
|
||||
return construct(precision0(), scale0(), l, nullability(), readonly(), collation(), characterSet(), identity(), defaultValue());
|
||||
return construct(
|
||||
precision0(),
|
||||
scale0(),
|
||||
l,
|
||||
nullability(),
|
||||
readonly(),
|
||||
generatedAlwaysAs(),
|
||||
collation(),
|
||||
characterSet(),
|
||||
identity(),
|
||||
defaultValue()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,12 +70,13 @@ final class ArrayDataType<T> extends DefaultDataType<T[]> {
|
||||
Integer length,
|
||||
Nullability nullability,
|
||||
boolean readonly,
|
||||
Field<T[]> generatedAlwaysAs,
|
||||
Collation collation,
|
||||
CharacterSet characterSet,
|
||||
boolean identity,
|
||||
Field<T[]> defaultValue
|
||||
) {
|
||||
super(t, precision, scale, length, nullability, readonly, collation, characterSet, identity, defaultValue);
|
||||
super(t, precision, scale, length, nullability, readonly, generatedAlwaysAs, collation, characterSet, identity, defaultValue);
|
||||
|
||||
this.elementType = elementType;
|
||||
}
|
||||
@ -88,6 +89,7 @@ final class ArrayDataType<T> extends DefaultDataType<T[]> {
|
||||
Integer newLength,
|
||||
Nullability newNullability,
|
||||
boolean newReadonly,
|
||||
Field<T[]> newGeneratedAlwaysAs,
|
||||
Collation newCollation,
|
||||
CharacterSet newCharacterSet,
|
||||
boolean newIdentity,
|
||||
@ -101,6 +103,7 @@ final class ArrayDataType<T> extends DefaultDataType<T[]> {
|
||||
newLength,
|
||||
newNullability,
|
||||
newReadonly,
|
||||
newGeneratedAlwaysAs,
|
||||
newCollation,
|
||||
newCharacterSet,
|
||||
newIdentity,
|
||||
|
||||
@ -82,6 +82,7 @@ final class ConvertedDataType<T, U> extends AbstractDataTypeX<U> {
|
||||
Integer newLength,
|
||||
Nullability newNullability,
|
||||
boolean newReadonly,
|
||||
Field<U> newGeneratedAlwaysAs,
|
||||
Collation newCollation,
|
||||
CharacterSet newCharacterSet,
|
||||
boolean newIdentity,
|
||||
@ -93,6 +94,7 @@ final class ConvertedDataType<T, U> extends AbstractDataTypeX<U> {
|
||||
newLength,
|
||||
newNullability,
|
||||
newReadonly,
|
||||
(Field) newGeneratedAlwaysAs,
|
||||
newCollation,
|
||||
newCharacterSet,
|
||||
newIdentity,
|
||||
@ -155,6 +157,11 @@ final class ConvertedDataType<T, U> extends AbstractDataTypeX<U> {
|
||||
return delegate.readonly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<U> generatedAlwaysAs() {
|
||||
return (Field<U>) delegate.generatedAlwaysAs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Collation collation() {
|
||||
return delegate.collation();
|
||||
|
||||
@ -63,13 +63,14 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
|
||||
private final Integer overrideLength;
|
||||
private final Nullability overrideNullability;
|
||||
private final Boolean overrideReadonly;
|
||||
private final Field<T> overrideGeneratedAlwaysAs;
|
||||
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, null);
|
||||
this(type, null, null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
private DataTypeProxy(
|
||||
@ -79,6 +80,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
|
||||
Integer overrideLength,
|
||||
Nullability overrideNullability,
|
||||
Boolean overrideReadonly,
|
||||
Field<T> overrideGeneratedAlwaysAs,
|
||||
Collation overrideCollation,
|
||||
CharacterSet overrideCharacterSet,
|
||||
Boolean overrideIdentity,
|
||||
@ -92,6 +94,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
|
||||
this.overrideLength = overrideLength;
|
||||
this.overrideNullability = overrideNullability;
|
||||
this.overrideReadonly = overrideReadonly;
|
||||
this.overrideGeneratedAlwaysAs = overrideGeneratedAlwaysAs;
|
||||
this.overrideCollation = overrideCollation;
|
||||
this.overrideCharacterSet = overrideCharacterSet;
|
||||
this.overrideIdentity = overrideIdentity;
|
||||
@ -150,6 +153,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
|
||||
overrideLength,
|
||||
n,
|
||||
overrideReadonly,
|
||||
overrideGeneratedAlwaysAs,
|
||||
overrideCollation,
|
||||
overrideCharacterSet,
|
||||
overrideIdentity,
|
||||
@ -171,6 +175,29 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
|
||||
overrideLength,
|
||||
overrideNullability,
|
||||
r,
|
||||
overrideGeneratedAlwaysAs,
|
||||
overrideCollation,
|
||||
overrideCharacterSet,
|
||||
overrideIdentity,
|
||||
overrideDefaultValue
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> generatedAlwaysAs() {
|
||||
return defaultIfNull(overrideGeneratedAlwaysAs, type.generatedAlwaysAs());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> generatedAlwaysAs(Field<T> g) {
|
||||
return new DataTypeProxy<>(
|
||||
this,
|
||||
overridePrecision,
|
||||
overrideScale,
|
||||
overrideLength,
|
||||
overrideNullability,
|
||||
overrideReadonly,
|
||||
g,
|
||||
overrideCollation,
|
||||
overrideCharacterSet,
|
||||
overrideIdentity,
|
||||
@ -192,6 +219,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
|
||||
overrideLength,
|
||||
overrideNullability,
|
||||
overrideReadonly,
|
||||
overrideGeneratedAlwaysAs,
|
||||
c,
|
||||
overrideCharacterSet,
|
||||
overrideIdentity,
|
||||
@ -213,6 +241,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
|
||||
overrideLength,
|
||||
overrideNullability,
|
||||
overrideReadonly,
|
||||
overrideGeneratedAlwaysAs,
|
||||
overrideCollation,
|
||||
c,
|
||||
overrideIdentity,
|
||||
@ -234,6 +263,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
|
||||
overrideLength,
|
||||
overrideNullability,
|
||||
overrideReadonly,
|
||||
overrideGeneratedAlwaysAs,
|
||||
overrideCollation,
|
||||
overrideCharacterSet,
|
||||
i,
|
||||
@ -255,6 +285,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
|
||||
overrideLength,
|
||||
overrideNullability,
|
||||
overrideReadonly,
|
||||
overrideGeneratedAlwaysAs,
|
||||
overrideCollation,
|
||||
overrideCharacterSet,
|
||||
overrideIdentity,
|
||||
@ -306,6 +337,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
|
||||
overrideLength,
|
||||
overrideNullability,
|
||||
overrideReadonly,
|
||||
overrideGeneratedAlwaysAs,
|
||||
overrideCollation,
|
||||
overrideCharacterSet,
|
||||
overrideIdentity,
|
||||
@ -327,6 +359,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
|
||||
overrideLength,
|
||||
overrideNullability,
|
||||
overrideReadonly,
|
||||
overrideGeneratedAlwaysAs,
|
||||
overrideCollation,
|
||||
overrideCharacterSet,
|
||||
overrideIdentity,
|
||||
@ -348,6 +381,7 @@ final class DataTypeProxy<T> extends AbstractDataType<T> {
|
||||
l,
|
||||
overrideNullability,
|
||||
overrideReadonly,
|
||||
overrideGeneratedAlwaysAs,
|
||||
overrideCollation,
|
||||
overrideCharacterSet,
|
||||
overrideIdentity,
|
||||
|
||||
@ -51,9 +51,37 @@ import static org.jooq.impl.CommentImpl.NO_COMMENT;
|
||||
import static org.jooq.impl.DSL.unquotedName;
|
||||
import static org.jooq.impl.DefaultBinding.binding;
|
||||
import static org.jooq.impl.SQLDataType.BIGINT;
|
||||
import static org.jooq.impl.SQLDataType.*;
|
||||
import static org.jooq.impl.SQLDataType.BINARY;
|
||||
import static org.jooq.impl.SQLDataType.BIT;
|
||||
import static org.jooq.impl.SQLDataType.BLOB;
|
||||
import static org.jooq.impl.SQLDataType.BOOLEAN;
|
||||
import static org.jooq.impl.SQLDataType.CHAR;
|
||||
import static org.jooq.impl.SQLDataType.CLOB;
|
||||
import static org.jooq.impl.SQLDataType.DATE;
|
||||
import static org.jooq.impl.SQLDataType.DECIMAL;
|
||||
import static org.jooq.impl.SQLDataType.DOUBLE;
|
||||
import static org.jooq.impl.SQLDataType.FLOAT;
|
||||
import static org.jooq.impl.SQLDataType.INTEGER;
|
||||
import static org.jooq.impl.SQLDataType.LONGNVARCHAR;
|
||||
import static org.jooq.impl.SQLDataType.LONGVARBINARY;
|
||||
import static org.jooq.impl.SQLDataType.LONGVARCHAR;
|
||||
import static org.jooq.impl.SQLDataType.NCHAR;
|
||||
import static org.jooq.impl.SQLDataType.NCLOB;
|
||||
import static org.jooq.impl.SQLDataType.NUMERIC;
|
||||
import static org.jooq.impl.SQLDataType.NVARCHAR;
|
||||
import static org.jooq.impl.SQLDataType.OTHER;
|
||||
import static org.jooq.impl.SQLDataType.REAL;
|
||||
import static org.jooq.impl.SQLDataType.RECORD;
|
||||
import static org.jooq.impl.SQLDataType.RESULT;
|
||||
import static org.jooq.impl.SQLDataType.SMALLINT;
|
||||
import static org.jooq.impl.SQLDataType.TIME;
|
||||
import static org.jooq.impl.SQLDataType.TIMESTAMP;
|
||||
import static org.jooq.impl.SQLDataType.TIMESTAMPWITHTIMEZONE;
|
||||
import static org.jooq.impl.SQLDataType.TIMEWITHTIMEZONE;
|
||||
import static org.jooq.impl.SQLDataType.TINYINT;
|
||||
import static org.jooq.impl.SQLDataType.VARBINARY;
|
||||
import static org.jooq.impl.SQLDataType.VARCHAR;
|
||||
import static org.jooq.impl.SQLDataType.XML;
|
||||
import static org.jooq.tools.reflect.Reflect.wrapper;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@ -221,6 +249,7 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
|
||||
|
||||
private final Nullability nullability;
|
||||
private final boolean readonly;
|
||||
private final Field<T> generatedAlwaysAs;
|
||||
private final Collation collation;
|
||||
private final CharacterSet characterSet;
|
||||
private final boolean identity;
|
||||
@ -290,10 +319,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, false, null, null, false, defaultValue);
|
||||
this(dialect, sqlDataType, type, binding, qualifiedTypeName, typeName, castTypeName, precision, scale, length, nullability, false, null, 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, 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, Field<T> generatedAlwaysAs, Collation collation, CharacterSet characterSet, boolean identity, Field<T> defaultValue) {
|
||||
super(qualifiedTypeName, NO_COMMENT);
|
||||
|
||||
// Initialise final instance members
|
||||
@ -313,6 +342,7 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
|
||||
|
||||
this.nullability = nullability;
|
||||
this.readonly = readonly;
|
||||
this.generatedAlwaysAs = generatedAlwaysAs;
|
||||
this.collation = collation;
|
||||
this.characterSet = characterSet;
|
||||
this.identity = identity;
|
||||
@ -353,12 +383,25 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
|
||||
Integer newLength,
|
||||
Nullability newNullability,
|
||||
boolean newReadonly,
|
||||
Field<T> newGeneratedAlwaysAs,
|
||||
Collation newCollation,
|
||||
CharacterSet newCharacterSet,
|
||||
boolean newIdentity,
|
||||
Field<T> newDefaultValue
|
||||
) {
|
||||
return new DefaultDataType<>(this, newPrecision, newScale, newLength, newNullability, newReadonly, newCollation, newCharacterSet, newIdentity, newDefaultValue);
|
||||
return new DefaultDataType<>(
|
||||
this,
|
||||
newPrecision,
|
||||
newScale,
|
||||
newLength,
|
||||
newNullability,
|
||||
newReadonly,
|
||||
newGeneratedAlwaysAs,
|
||||
newCollation,
|
||||
newCharacterSet,
|
||||
newIdentity,
|
||||
newDefaultValue
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -371,6 +414,7 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
|
||||
Integer length,
|
||||
Nullability nullability,
|
||||
boolean readonly,
|
||||
Field<T> generatedAlwaysAs,
|
||||
Collation collation,
|
||||
CharacterSet characterSet,
|
||||
boolean identity,
|
||||
@ -389,6 +433,7 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
|
||||
|
||||
this.nullability = nullability;
|
||||
this.readonly = readonly;
|
||||
this.generatedAlwaysAs = generatedAlwaysAs;
|
||||
this.collation = collation;
|
||||
this.characterSet = characterSet;
|
||||
this.identity = identity;
|
||||
@ -428,6 +473,11 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
|
||||
return readonly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> generatedAlwaysAs() {
|
||||
return generatedAlwaysAs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Collation collation() {
|
||||
return collation;
|
||||
@ -484,7 +534,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, readonly, collation, characterSet, identity, defaultValue);
|
||||
return dataType.construct(precision, scale, length, nullability, readonly, generatedAlwaysAs, collation, characterSet, identity, defaultValue);
|
||||
}
|
||||
|
||||
// If this is already the dialect's specific data type, return this
|
||||
|
||||
@ -65,6 +65,7 @@ final class DomainDataType<T> extends DefaultDataType<T> {
|
||||
baseType.lengthDefined() ? baseType.length() : null,
|
||||
baseType.nullability(),
|
||||
baseType.readonly(),
|
||||
baseType.generatedAlwaysAs(),
|
||||
null, // TODO: Collation
|
||||
null, // TODO: CharacterSet (?)
|
||||
false,
|
||||
|
||||
@ -60,6 +60,7 @@ final class Keywords {
|
||||
static final Keyword K_ALTER_INDEX = keyword("alter index");
|
||||
static final Keyword K_ALTER_SCHEMA = keyword("alter schema");
|
||||
static final Keyword K_ALTER_TABLE = keyword("alter table");
|
||||
static final Keyword K_ALWAYS = keyword("always");
|
||||
static final Keyword K_AND = keyword("and");
|
||||
static final Keyword K_ARRAY = keyword("array");
|
||||
static final Keyword K_AS = keyword("as");
|
||||
@ -184,7 +185,7 @@ final class Keywords {
|
||||
static final Keyword K_FOR_PORTION_OF = keyword("for portion of");
|
||||
static final Keyword K_FROM = keyword("from");
|
||||
static final Keyword K_FUNCTION = keyword("function");
|
||||
static final Keyword K_GENERATED_BY_DEFAULT_AS_IDENTITY = keyword("generated by default as identity");
|
||||
static final Keyword K_GENERATED = keyword("generated");
|
||||
static final Keyword K_GLOBAL_TEMPORARY = keyword("global temporary");
|
||||
static final Keyword K_GOTO = keyword("goto");
|
||||
static final Keyword K_GRANT = keyword("grant");
|
||||
|
||||
@ -85,12 +85,13 @@ final class MultisetDataType<R extends Record> extends DefaultDataType<Result<R>
|
||||
Integer length,
|
||||
Nullability nullability,
|
||||
boolean readonly,
|
||||
Field<Result<R>> generatedAlwaysAs,
|
||||
Collation collation,
|
||||
CharacterSet characterSet,
|
||||
boolean identity,
|
||||
Field<Result<R>> defaultValue
|
||||
) {
|
||||
super(t, precision, scale, length, nullability, readonly, collation, characterSet, identity, defaultValue);
|
||||
super(t, precision, scale, length, nullability, readonly, generatedAlwaysAs, collation, characterSet, identity, defaultValue);
|
||||
|
||||
this.row = row;
|
||||
this.recordType = recordType;
|
||||
@ -104,6 +105,7 @@ final class MultisetDataType<R extends Record> extends DefaultDataType<Result<R>
|
||||
Integer newLength,
|
||||
Nullability newNullability,
|
||||
boolean newReadonly,
|
||||
Field<Result<R>> newGeneratedAlwaysAs,
|
||||
Collation newCollation,
|
||||
CharacterSet newCharacterSet,
|
||||
boolean newIdentity,
|
||||
@ -118,6 +120,7 @@ final class MultisetDataType<R extends Record> extends DefaultDataType<Result<R>
|
||||
newLength,
|
||||
newNullability,
|
||||
newReadonly,
|
||||
newGeneratedAlwaysAs,
|
||||
newCollation,
|
||||
newCharacterSet,
|
||||
newIdentity,
|
||||
|
||||
@ -4225,6 +4225,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
|
||||
List<Index> indexes = new ArrayList<>();
|
||||
boolean primary = false;
|
||||
boolean identity = false;
|
||||
boolean computed = false;
|
||||
boolean readonly = false;
|
||||
|
||||
// Three valued boolean:
|
||||
@ -4308,11 +4309,13 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
|
||||
constraints,
|
||||
primary,
|
||||
identity,
|
||||
computed,
|
||||
readonly
|
||||
);
|
||||
|
||||
primary = inlineConstraints.primary;
|
||||
identity = inlineConstraints.identity;
|
||||
computed = inlineConstraints.computed;
|
||||
|
||||
if (ctas)
|
||||
fields.add(field(fieldName));
|
||||
@ -4520,7 +4523,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
|
||||
return storageStep;
|
||||
}
|
||||
|
||||
private static final /* record */ class ParseInlineConstraints { private final DataType<?> type; private final Comment fieldComment; private final boolean primary; private final boolean identity; private final boolean readonly; public ParseInlineConstraints(DataType<?> type, Comment fieldComment, boolean primary, boolean identity, boolean readonly) { this.type = type; this.fieldComment = fieldComment; this.primary = primary; this.identity = identity; this.readonly = readonly; } public DataType<?> type() { return type; } public Comment fieldComment() { return fieldComment; } public boolean primary() { return primary; } public boolean identity() { return identity; } public boolean readonly() { return readonly; } @Override public boolean equals(Object o) { if (!(o instanceof ParseInlineConstraints)) return false; ParseInlineConstraints other = (ParseInlineConstraints) o; if (!java.util.Objects.equals(this.type, other.type)) return false; if (!java.util.Objects.equals(this.fieldComment, other.fieldComment)) return false; if (!java.util.Objects.equals(this.primary, other.primary)) return false; if (!java.util.Objects.equals(this.identity, other.identity)) return false; if (!java.util.Objects.equals(this.readonly, other.readonly)) return false; return true; } @Override public int hashCode() { return java.util.Objects.hash(this.type, this.fieldComment, this.primary, this.identity, this.readonly); } @Override public String toString() { return new StringBuilder("ParseInlineConstraints[").append("type=").append(this.type).append(", fieldComment=").append(this.fieldComment).append(", primary=").append(this.primary).append(", identity=").append(this.identity).append(", readonly=").append(this.readonly).append("]").toString(); } }
|
||||
private static final /* record */ class ParseInlineConstraints { private final DataType<?> type; private final Comment fieldComment; private final boolean primary; private final boolean identity; private final boolean computed; private final boolean readonly; public ParseInlineConstraints(DataType<?> type, Comment fieldComment, boolean primary, boolean identity, boolean computed, boolean readonly) { this.type = type; this.fieldComment = fieldComment; this.primary = primary; this.identity = identity; this.computed = computed; this.readonly = readonly; } public DataType<?> type() { return type; } public Comment fieldComment() { return fieldComment; } public boolean primary() { return primary; } public boolean identity() { return identity; } public boolean computed() { return computed; } public boolean readonly() { return readonly; } @Override public boolean equals(Object o) { if (!(o instanceof ParseInlineConstraints)) return false; ParseInlineConstraints other = (ParseInlineConstraints) o; if (!java.util.Objects.equals(this.type, other.type)) return false; if (!java.util.Objects.equals(this.fieldComment, other.fieldComment)) return false; if (!java.util.Objects.equals(this.primary, other.primary)) return false; if (!java.util.Objects.equals(this.identity, other.identity)) return false; if (!java.util.Objects.equals(this.computed, other.computed)) return false; if (!java.util.Objects.equals(this.readonly, other.readonly)) return false; return true; } @Override public int hashCode() { return java.util.Objects.hash(this.type, this.fieldComment, this.primary, this.identity, this.computed, this.readonly); } @Override public String toString() { return new StringBuilder("ParseInlineConstraints[").append("type=").append(this.type).append(", fieldComment=").append(this.fieldComment).append(", primary=").append(this.primary).append(", identity=").append(this.identity).append(", computed=").append(this.computed).append(", readonly=").append(this.readonly).append("]").toString(); } }
|
||||
|
||||
private final ParseInlineConstraints parseInlineConstraints(
|
||||
Name fieldName,
|
||||
@ -4528,6 +4531,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
|
||||
List<? super Constraint> constraints,
|
||||
boolean primary,
|
||||
boolean identity,
|
||||
boolean computed,
|
||||
boolean readonly
|
||||
) {
|
||||
boolean nullable = false;
|
||||
@ -4538,6 +4542,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
|
||||
Comment fieldComment = null;
|
||||
|
||||
identity |= type.identity();
|
||||
computed |= type.computed();
|
||||
readonly |= type.readonly();
|
||||
|
||||
for (;;) {
|
||||
@ -4595,65 +4600,36 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (!identity && parseKeywordIf("GENERATED")) {
|
||||
if (!parseKeywordIf("ALWAYS")) {
|
||||
else if (!computed && parseKeywordIf("AS") && requireProEdition()) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
else if (!identity && !computed && parseKeywordIf("GENERATED")) {
|
||||
boolean always;
|
||||
if (!(always = parseKeywordIf("ALWAYS"))) {
|
||||
parseKeyword("BY DEFAULT");
|
||||
|
||||
// TODO: Ignored keyword from Oracle
|
||||
parseKeywordIf("ON NULL");
|
||||
}
|
||||
|
||||
parseKeyword("AS IDENTITY");
|
||||
if (always ? parseKeywordIf("AS IDENTITY") : parseKeyword("AS IDENTITY")) {
|
||||
parseIdentityOptionIf();
|
||||
type = type.identity(true);
|
||||
identity = true;
|
||||
}
|
||||
else if (parseKeyword("AS") && requireProEdition()) {
|
||||
|
||||
// TODO: Ignored identity options from Oracle
|
||||
if (parseIf('(')) {
|
||||
boolean identityOption = false;
|
||||
|
||||
for (;;) {
|
||||
if (identityOption)
|
||||
parseIf(',');
|
||||
|
||||
if (parseKeywordIf("START WITH")) {
|
||||
if (!parseKeywordIf("LIMIT VALUE"))
|
||||
parseUnsignedIntegerOrBindVariable();
|
||||
identityOption = true;
|
||||
continue;
|
||||
}
|
||||
else if (parseKeywordIf("INCREMENT BY")
|
||||
|| parseKeywordIf("MAXVALUE")
|
||||
|| parseKeywordIf("MINVALUE")
|
||||
|| parseKeywordIf("CACHE")) {
|
||||
parseUnsignedIntegerOrBindVariable();
|
||||
identityOption = true;
|
||||
continue;
|
||||
}
|
||||
else if (parseKeywordIf("NOMAXVALUE")
|
||||
|| parseKeywordIf("NOMINVALUE")
|
||||
|| parseKeywordIf("CYCLE")
|
||||
|| parseKeywordIf("NOCYCLE")
|
||||
|| parseKeywordIf("NOCACHE")
|
||||
|| parseKeywordIf("ORDER")
|
||||
|| parseKeywordIf("NOORDER")) {
|
||||
identityOption = true;
|
||||
continue;
|
||||
}
|
||||
else if (parseSignedIntegerLiteralIf() != null) {
|
||||
identityOption = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (identityOption)
|
||||
break;
|
||||
else
|
||||
throw unsupportedClause();
|
||||
}
|
||||
|
||||
parse(')');
|
||||
}
|
||||
|
||||
type = type.identity(true);
|
||||
defaultValue = true;
|
||||
identity = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -4749,7 +4725,56 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
|
||||
break;
|
||||
}
|
||||
|
||||
return new ParseInlineConstraints(type, fieldComment, primary, identity, readonly);
|
||||
return new ParseInlineConstraints(type, fieldComment, primary, identity, computed, readonly);
|
||||
}
|
||||
|
||||
private final void parseIdentityOptionIf() {
|
||||
|
||||
// TODO: Ignored identity options from Oracle
|
||||
if (parseIf('(')) {
|
||||
boolean identityOption = false;
|
||||
|
||||
for (;;) {
|
||||
if (identityOption)
|
||||
parseIf(',');
|
||||
|
||||
if (parseKeywordIf("START WITH")) {
|
||||
if (!parseKeywordIf("LIMIT VALUE"))
|
||||
parseUnsignedIntegerOrBindVariable();
|
||||
identityOption = true;
|
||||
continue;
|
||||
}
|
||||
else if (parseKeywordIf("INCREMENT BY")
|
||||
|| parseKeywordIf("MAXVALUE")
|
||||
|| parseKeywordIf("MINVALUE")
|
||||
|| parseKeywordIf("CACHE")) {
|
||||
parseUnsignedIntegerOrBindVariable();
|
||||
identityOption = true;
|
||||
continue;
|
||||
}
|
||||
else if (parseKeywordIf("NOMAXVALUE")
|
||||
|| parseKeywordIf("NOMINVALUE")
|
||||
|| parseKeywordIf("CYCLE")
|
||||
|| parseKeywordIf("NOCYCLE")
|
||||
|| parseKeywordIf("NOCACHE")
|
||||
|| parseKeywordIf("ORDER")
|
||||
|| parseKeywordIf("NOORDER")) {
|
||||
identityOption = true;
|
||||
continue;
|
||||
}
|
||||
else if (parseSignedIntegerLiteralIf() != null) {
|
||||
identityOption = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (identityOption)
|
||||
break;
|
||||
else
|
||||
throw unsupportedClause();
|
||||
}
|
||||
|
||||
parse(')');
|
||||
}
|
||||
}
|
||||
|
||||
private final boolean parseSerialIf() {
|
||||
@ -5227,7 +5252,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
|
||||
DataType type = parseDataType();
|
||||
int p = list == null ? -1 : list.size();
|
||||
|
||||
ParseInlineConstraints inline = parseInlineConstraints(fieldName, type, list, false, false, false);
|
||||
ParseInlineConstraints inline = parseInlineConstraints(fieldName, type, list, false, false, false, false);
|
||||
Field<?> result = field(fieldName, inline.type, inline.fieldComment);
|
||||
|
||||
if (list != null)
|
||||
|
||||
@ -86,12 +86,13 @@ final class RecordDataType<R extends Record> extends DefaultDataType<R> {
|
||||
Integer length,
|
||||
Nullability nullability,
|
||||
boolean readonly,
|
||||
Field<R> generatedAlwaysAs,
|
||||
Collation collation,
|
||||
CharacterSet characterSet,
|
||||
boolean identity,
|
||||
Field<R> defaultValue
|
||||
) {
|
||||
super(t, precision, scale, length, nullability, readonly, collation, characterSet, identity, defaultValue);
|
||||
super(t, precision, scale, length, nullability, readonly, generatedAlwaysAs, collation, characterSet, identity, defaultValue);
|
||||
|
||||
this.row = row;
|
||||
}
|
||||
@ -104,6 +105,7 @@ final class RecordDataType<R extends Record> extends DefaultDataType<R> {
|
||||
Integer newLength,
|
||||
Nullability newNullability,
|
||||
boolean newReadonly,
|
||||
Field<R> newGeneratedAlwaysAs,
|
||||
Collation newCollation,
|
||||
CharacterSet newCharacterSet,
|
||||
boolean newIdentity,
|
||||
@ -117,6 +119,7 @@ final class RecordDataType<R extends Record> extends DefaultDataType<R> {
|
||||
newLength,
|
||||
newNullability,
|
||||
newReadonly,
|
||||
newGeneratedAlwaysAs,
|
||||
newCollation,
|
||||
newCharacterSet,
|
||||
newIdentity,
|
||||
|
||||
@ -53,7 +53,7 @@ import static java.util.stream.Collectors.joining;
|
||||
import static org.jooq.SQLDialect.DERBY;
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.FIREBIRD;
|
||||
import static org.jooq.SQLDialect.HSQLDB;
|
||||
import static org.jooq.SQLDialect.*;
|
||||
// ...
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.MARIADB;
|
||||
@ -120,6 +120,7 @@ import static org.jooq.impl.Identifiers.QUOTES;
|
||||
import static org.jooq.impl.Identifiers.QUOTE_END_DELIMITER;
|
||||
import static org.jooq.impl.Identifiers.QUOTE_END_DELIMITER_ESCAPED;
|
||||
import static org.jooq.impl.Identifiers.QUOTE_START_DELIMITER;
|
||||
import static org.jooq.impl.Keywords.K_ALWAYS;
|
||||
import static org.jooq.impl.Keywords.K_AS;
|
||||
import static org.jooq.impl.Keywords.K_ATOMIC;
|
||||
import static org.jooq.impl.Keywords.K_AUTOINCREMENT;
|
||||
@ -127,6 +128,7 @@ import static org.jooq.impl.Keywords.K_AUTO_INCREMENT;
|
||||
import static org.jooq.impl.Keywords.K_BEGIN;
|
||||
import static org.jooq.impl.Keywords.K_BEGIN_CATCH;
|
||||
import static org.jooq.impl.Keywords.K_BEGIN_TRY;
|
||||
import static org.jooq.impl.Keywords.K_BY;
|
||||
import static org.jooq.impl.Keywords.K_CHARACTER_SET;
|
||||
import static org.jooq.impl.Keywords.K_COLLATE;
|
||||
import static org.jooq.impl.Keywords.K_DECLARE;
|
||||
@ -145,7 +147,7 @@ import static org.jooq.impl.Keywords.K_EXEC;
|
||||
import static org.jooq.impl.Keywords.K_EXECUTE_BLOCK;
|
||||
import static org.jooq.impl.Keywords.K_EXECUTE_IMMEDIATE;
|
||||
import static org.jooq.impl.Keywords.K_EXECUTE_STATEMENT;
|
||||
import static org.jooq.impl.Keywords.K_GENERATED_BY_DEFAULT_AS_IDENTITY;
|
||||
import static org.jooq.impl.Keywords.K_GENERATED;
|
||||
import static org.jooq.impl.Keywords.K_IDENTITY;
|
||||
import static org.jooq.impl.Keywords.K_IF;
|
||||
import static org.jooq.impl.Keywords.K_INT;
|
||||
@ -158,7 +160,6 @@ import static org.jooq.impl.Keywords.K_PRIMARY_KEY;
|
||||
import static org.jooq.impl.Keywords.K_RAISE;
|
||||
import static org.jooq.impl.Keywords.K_RAISERROR;
|
||||
import static org.jooq.impl.Keywords.K_SERIAL;
|
||||
import static org.jooq.impl.Keywords.K_SERIAL2;
|
||||
import static org.jooq.impl.Keywords.K_SERIAL4;
|
||||
import static org.jooq.impl.Keywords.K_SERIAL8;
|
||||
import static org.jooq.impl.Keywords.K_SQLSTATE;
|
||||
@ -5096,6 +5097,9 @@ final class Tools {
|
||||
* keywords before the [ NOT ] NULL constraint.
|
||||
*/
|
||||
static final void toSQLDDLTypeDeclarationIdentityBeforeNull(Context<?> ctx, DataType<?> type) {
|
||||
if (REQUIRE_IDENTITY_AFTER_NULL.contains(ctx.dialect()))
|
||||
return;
|
||||
|
||||
if (type.identity()) {
|
||||
switch (ctx.family()) {
|
||||
|
||||
@ -5109,7 +5113,7 @@ final class Tools {
|
||||
|
||||
case CUBRID: ctx.sql(' ').visit(K_AUTO_INCREMENT); break;
|
||||
|
||||
case HSQLDB: ctx.sql(' ').visit(K_GENERATED_BY_DEFAULT_AS_IDENTITY).sql('(').visit(K_START_WITH).sql(" 1)"); break;
|
||||
case HSQLDB: ctx.sql(' ').visit(K_GENERATED).sql(' ').visit(K_BY).sql(' ').visit(K_DEFAULT).sql(' ').visit(K_AS).sql(' ').visit(K_IDENTITY).sql('(').visit(K_START_WITH).sql(" 1)"); break;
|
||||
case SQLITE: ctx.sql(' ').visit(K_PRIMARY_KEY).sql(' ').visit(K_AUTOINCREMENT); break;
|
||||
case POSTGRES:
|
||||
switch (ctx.dialect()) {
|
||||
@ -5119,23 +5123,38 @@ final class Tools {
|
||||
|
||||
|
||||
case POSTGRES:
|
||||
ctx.sql(' ').visit(K_GENERATED_BY_DEFAULT_AS_IDENTITY); break;
|
||||
ctx.sql(' ').visit(K_GENERATED).sql(' ').visit(K_BY).sql(' ').visit(K_DEFAULT).sql(' ').visit(K_AS).sql(' ').visit(K_IDENTITY); break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case DERBY:
|
||||
case FIREBIRD:
|
||||
case YUGABYTE: ctx.sql(' ').visit(K_GENERATED_BY_DEFAULT_AS_IDENTITY); break;
|
||||
case YUGABYTE: ctx.sql(' ').visit(K_GENERATED).sql(' ').visit(K_BY).sql(' ').visit(K_DEFAULT).sql(' ').visit(K_AS).sql(' ').visit(K_IDENTITY); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static final Set<SQLDialect> REQUIRE_IDENTITY_AFTER_NULL = SQLDialect.supportedBy(H2, MARIADB, MYSQL);
|
||||
|
||||
/**
|
||||
* If a type is an identity type, some dialects require the relevant
|
||||
* keywords after the [ NOT ] NULL constraint.
|
||||
*/
|
||||
static final void toSQLDDLTypeDeclarationIdentityAfterNull(Context<?> ctx, DataType<?> type) {
|
||||
if (!REQUIRE_IDENTITY_AFTER_NULL.contains(ctx.dialect()))
|
||||
return;
|
||||
|
||||
if (type.identity()) {
|
||||
|
||||
// [#5062] H2's (and others') AUTO_INCREMENT flag is syntactically located *after* NULL flags.
|
||||
@ -5143,7 +5162,7 @@ final class Tools {
|
||||
|
||||
|
||||
|
||||
case H2: ctx.sql(' ').visit(K_GENERATED_BY_DEFAULT_AS_IDENTITY); break;
|
||||
case H2: ctx.sql(' ').visit(K_GENERATED).sql(' ').visit(K_BY).sql(' ').visit(K_DEFAULT).sql(' ').visit(K_AS).sql(' ').visit(K_IDENTITY); break;
|
||||
|
||||
|
||||
|
||||
@ -5154,6 +5173,20 @@ final class Tools {
|
||||
case MYSQL: ctx.sql(' ').visit(K_AUTO_INCREMENT); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static final void toSQLDDLTypeDeclarationDefault(Context<?> ctx, DataType<?> type) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user