[jOOQ/jOOQ#15732] Auto-create a sequence to implement an identity

This commit is contained in:
Lukas Eder 2024-03-28 09:26:49 +01:00
parent 0566aa624d
commit 4f3b66750c
4 changed files with 35 additions and 13 deletions

View File

@ -1327,7 +1327,7 @@ implements
if (part instanceof Field<?> f) {
ctx.sql(' ');
toSQLDDLTypeDeclarationForAddition(ctx, f.getDataType());
toSQLDDLTypeDeclarationForAddition(ctx, table, f.getDataType());
CreateTableImpl.acceptColumnComment(ctx, f);
}
}
@ -1355,7 +1355,7 @@ implements
ctx.qualify(false, c -> c.visit(Tools.uncollate(addColumn))).sql(' ');
toSQLDDLTypeDeclarationForAddition(ctx, addColumnType);
toSQLDDLTypeDeclarationForAddition(ctx, table, addColumnType);
CreateTableImpl.acceptColumnComment(ctx, addColumn);
@ -1502,7 +1502,7 @@ implements
ctx.sql(' ');
toSQLDDLTypeDeclaration(ctx, alterColumnType);
toSQLDDLTypeDeclarationIdentityBeforeNull(ctx, alterColumnType);
toSQLDDLTypeDeclarationIdentityBeforeNull(ctx, table, alterColumnType);
// [#3805] Some databases cannot change the type and the NOT NULL constraint in a single statement
if (!NO_SUPPORT_ALTER_TYPE_AND_NULL.contains(ctx.dialect())) {
@ -1518,7 +1518,7 @@ implements
}
}
toSQLDDLTypeDeclarationIdentityAfterNull(ctx, alterColumnType);
toSQLDDLTypeDeclarationIdentityAfterNull(ctx, table, alterColumnType);
}
else if (alterColumnDefault != null) {
ctx.start(ALTER_TABLE_ALTER_DEFAULT);

View File

@ -356,6 +356,7 @@ implements
static final Set<SQLDialect> REQUIRE_EXECUTE_IMMEDIATE = SQLDialect.supportedBy(FIREBIRD);
static final Set<SQLDialect> NO_SUPPORT_NULLABLE_PRIMARY_KEY = SQLDialect.supportedBy(CLICKHOUSE, MARIADB, MYSQL);
static final Set<SQLDialect> REQUIRE_NON_PK_COLUMNS = SQLDialect.supportedBy(IGNITE);
static final Set<SQLDialect> CREATE_SEQUENCE_FOR_IDENTITY = SQLDialect.supportedBy(DUCKDB);
@ -441,6 +442,11 @@ implements
private final void accept1(Context<?> ctx) {
ctx.start(Clause.CREATE_TABLE);
if (CREATE_SEQUENCE_FOR_IDENTITY.contains(ctx.family())
&& anyMatch(tableElements, e -> e instanceof Field && ((Field<?>) e).getDataType().identity())
)
prependSQL(ctx, createSequenceIfNotExists(identitySequence(table)));
if (select != null) {
@ -522,7 +528,7 @@ implements
if (select == null) {
ctx.sql(' ');
Tools.toSQLDDLTypeDeclarationForAddition(ctx, type);
Tools.toSQLDDLTypeDeclarationForAddition(ctx, table, type);
acceptColumnComment(ctx, field);
}
@ -610,7 +616,7 @@ implements
if (select == null) {
ctx.sql(' ');
Tools.toSQLDDLTypeDeclarationForAddition(ctx, INTEGER);
Tools.toSQLDDLTypeDeclarationForAddition(ctx, table, INTEGER);
}
}
}

View File

@ -211,7 +211,7 @@ implements
return CustomField.of(f.getUnqualifiedName(), f.getDataType(), c -> {
c.visit(f.getUnqualifiedName());
c.sql(' ');
Tools.toSQLDDLTypeDeclarationForAddition(c, f.getDataType());
Tools.toSQLDDLTypeDeclarationForAddition(c, null, f.getDataType());
});
}

View File

@ -334,6 +334,7 @@ import org.jooq.Schema;
import org.jooq.Scope;
import org.jooq.Select;
import org.jooq.SelectFieldOrAsterisk;
import org.jooq.Sequence;
import org.jooq.SortField;
import org.jooq.Source;
import org.jooq.Table;
@ -5763,7 +5764,7 @@ final class Tools {
});
}
static final void toSQLDDLTypeDeclarationForAddition(Context<?> ctx, DataType<?> type) {
static final void toSQLDDLTypeDeclarationForAddition(Context<?> ctx, Table<?> table, DataType<?> type) {
boolean qualify = ctx.qualify();
toSQLDDLTypeDeclaration(ctx, type);
@ -5771,7 +5772,7 @@ final class Tools {
// have qualified field references elsewhere, e.g. in computed
// column declarations.
ctx.qualify(false);
toSQLDDLTypeDeclarationIdentityBeforeNull(ctx, type);
toSQLDDLTypeDeclarationIdentityBeforeNull(ctx, table, type);
@ -5792,7 +5793,7 @@ final class Tools {
if (!DEFAULT_BEFORE_NULL.contains(ctx.dialect()))
toSQLDDLTypeDeclarationDefault(ctx, type);
toSQLDDLTypeDeclarationIdentityAfterNull(ctx, type);
toSQLDDLTypeDeclarationIdentityAfterNull(ctx, table, type);
@ -5858,14 +5859,28 @@ final class Tools {
}
}
private static final Set<SQLDialect> REQUIRE_IDENTITY_AFTER_NULL = SQLDialect.supportedBy(H2, MARIADB, MYSQL);
static final Sequence<?> identitySequence(Table<?> table) {
if (table == null)
return DSL.sequence("id");
Name n = table.getQualifiedName();
if (n.qualified())
n = n.qualifier().append(n.last() + "_seq");
else
n = name(n.last() + "_seq");
return DSL.sequence(n);
}
private static final Set<SQLDialect> REQUIRE_IDENTITY_AFTER_NULL = SQLDialect.supportedBy(DUCKDB, H2, MARIADB, MYSQL);
private static final Set<SQLDialect> SUPPORT_PG_IDENTITY = SQLDialect.supportedBy(POSTGRES);
/**
* If a type is an identity type, some dialects require the relevant
* keywords before the [ NOT ] NULL constraint.
*/
static final void toSQLDDLTypeDeclarationIdentityBeforeNull(Context<?> ctx, DataType<?> type) {
static final void toSQLDDLTypeDeclarationIdentityBeforeNull(Context<?> ctx, Table<?> table, DataType<?> type) {
if (REQUIRE_IDENTITY_AFTER_NULL.contains(ctx.dialect()))
return;
@ -5902,7 +5917,7 @@ final class Tools {
* 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) {
static final void toSQLDDLTypeDeclarationIdentityAfterNull(Context<?> ctx, Table<?> table, DataType<?> type) {
if (!REQUIRE_IDENTITY_AFTER_NULL.contains(ctx.dialect()))
return;
@ -5922,6 +5937,7 @@ final class Tools {
case MARIADB:
case MYSQL: ctx.sql(' ').visit(K_AUTO_INCREMENT); break;
case DUCKDB: ctx.sql(' ').visit(K_DEFAULT).sql(' ').visit(identitySequence(table).nextval()); break;
}
}
}