[jOOQ/jOOQ#8474] Add support for CREATE TYPE AS <member list>

This commit is contained in:
Lukas Eder 2023-08-29 13:31:50 +02:00
parent 18f5e7164f
commit 9c1cc75f42
8 changed files with 130 additions and 19 deletions

View File

@ -97,4 +97,18 @@ public interface CreateTypeStep {
@Support({ H2, POSTGRES, YUGABYTEDB })
@NotNull @CheckReturnValue
CreateTypeFinalStep asEnum();
/**
* Add the <code>AS</code> clause to the <code>CREATE TYPE</code> statement.
*/
@Support({ POSTGRES, YUGABYTEDB })
@NotNull @CheckReturnValue
CreateTypeFinalStep as(Field<?>... attributes);
/**
* Add the <code>AS</code> clause to the <code>CREATE TYPE</code> statement.
*/
@Support({ POSTGRES, YUGABYTEDB })
@NotNull @CheckReturnValue
CreateTypeFinalStep as(Collection<? extends Field<?>> attributes);
}

View File

@ -76,6 +76,7 @@ implements
final Type<?> type;
QueryPartListView<? extends Field<String>> values;
QueryPartListView<? extends Field<?>> attributes;
CreateTypeImpl(
Configuration configuration,
@ -84,6 +85,7 @@ implements
this(
configuration,
type,
null,
null
);
}
@ -91,12 +93,14 @@ implements
CreateTypeImpl(
Configuration configuration,
Type<?> type,
Collection<? extends Field<String>> values
Collection<? extends Field<String>> values,
Collection<? extends Field<?>> attributes
) {
super(configuration);
this.type = type;
this.values = new QueryPartList<>(values);
this.attributes = new QueryPartList<>(attributes);
}
// -------------------------------------------------------------------------
@ -124,6 +128,17 @@ implements
return this;
}
@Override
public final CreateTypeImpl as(Field<?>... attributes) {
return as(Arrays.asList(attributes));
}
@Override
public final CreateTypeImpl as(Collection<? extends Field<?>> attributes) {
this.attributes = new QueryPartList<>(attributes);
return this;
}
// -------------------------------------------------------------------------
// XXX: QueryPart API
// -------------------------------------------------------------------------
@ -134,9 +149,32 @@ implements
public final void accept(Context<?> ctx) {
ctx.visit(K_CREATE).sql(' ').visit(K_TYPE).sql(' ')
.visit(type).sql(' ')
.visit(K_AS).sql(' ').visit(K_ENUM).sql(" (")
.visit(values, ParamType.INLINED)
.sql(')');
.visit(K_AS).sql(' ');
if (!values.isEmpty()) {
ctx.visit(K_ENUM).sql(" (")
.visit(values, ParamType.INLINED)
.sql(')');
}
else {
ctx.sql('(').visit(
new QueryPartList<Field<?>>(attributes).map(f -> declare(f)),
ParamType.INLINED
).sql(')');
}
}
private static final <T> Field<T> declare(Field<T> f) {
return CustomField.of(f.getUnqualifiedName(), f.getDataType(), c -> {
c.visit(f.getUnqualifiedName());
c.sql(' ');
Tools.toSQLDDLTypeDeclarationForAddition(c, f.getDataType());
});
}
@ -155,20 +193,32 @@ implements
return QOM.unmodifiable(values);
}
@Override
public final UnmodifiableList<? extends Field<?>> $attributes() {
return QOM.unmodifiable(attributes);
}
@Override
public final QOM.CreateType $type(Type<?> newValue) {
return $constructor().apply(newValue, $values());
return $constructor().apply(newValue, $values(), $attributes());
}
@Override
public final QOM.CreateType $values(Collection<? extends Field<String>> newValue) {
return $constructor().apply($type(), newValue);
return $constructor().apply($type(), newValue, $attributes());
}
public final Function2<? super Type<?>, ? super Collection<? extends Field<String>>, ? extends QOM.CreateType> $constructor() {
return (a1, a2) -> new CreateTypeImpl(configuration(), a1, (Collection<? extends Field<String>>) a2);
@Override
public final QOM.CreateType $attributes(Collection<? extends Field<?>> newValue) {
return $constructor().apply($type(), $values(), newValue);
}
public final Function3<? super Type<?>, ? super Collection<? extends Field<String>>, ? super Collection<? extends Field<?>>, ? extends QOM.CreateType> $constructor() {
return (a1, a2, a3) -> new CreateTypeImpl(configuration(), a1, (Collection<? extends Field<String>>) a2, (Collection<? extends Field<?>>) a3);
}

View File

@ -51,6 +51,7 @@ enum DDLStatementType {
ALTER_SEQUENCE,
ALTER_TABLE,
ALTER_TRIGGER,
ALTER_TYPE,
ALTER_VIEW,
CREATE_DATABASE,
@ -62,6 +63,7 @@ enum DDLStatementType {
CREATE_SEQUENCE,
CREATE_TABLE,
CREATE_TRIGGER,
CREATE_TYPE,
CREATE_VIEW,
DROP_DATABASE,
@ -73,5 +75,6 @@ enum DDLStatementType {
DROP_SEQUENCE,
DROP_TABLE,
DROP_TRIGGER,
DROP_TYPE,
DROP_VIEW,
}

View File

@ -126,11 +126,39 @@ implements
private static final Set<SQLDialect> NO_SUPPORT_IF_EXISTS = SQLDialect.supportedUntil();
@Override
public final void accept(Context<?> ctx) {
accept0(ctx);
}
private final boolean supportsIfExists(Context<?> ctx) {
return !NO_SUPPORT_IF_EXISTS.contains(ctx.dialect());
}
private final void accept0(Context<?> ctx) {
if (ifExists && !supportsIfExists(ctx))
tryCatch(ctx, DDLStatementType.DROP_TYPE, c -> accept1(c));
else
accept1(ctx);
}
private final void accept1(Context<?> ctx) {
ctx.visit(K_DROP).sql(' ').visit(K_TYPE);
if (ifExists)
if (ifExists && supportsIfExists(ctx))
ctx.sql(' ').visit(K_IF_EXISTS);
ctx.sql(' ').visit(types);

View File

@ -288,6 +288,7 @@ final class Keywords {
static final Keyword K_NULLS_LAST = keyword("nulls last");
static final Keyword K_NUMERIC = keyword("numeric");
static final Keyword K_NVARCHAR = keyword("nvarchar");
static final Keyword K_OBJECT = keyword("object");
static final Keyword K_OCCURRENCE = keyword("occurrence");
static final Keyword K_OF = keyword("of");
static final Keyword K_OFFSET = keyword("offset");

View File

@ -5115,18 +5115,28 @@ final class DefaultParseContext extends AbstractScope implements ParseContext {
private final DDLQuery parseCreateType() {
Name name = parseName();
parseKeyword("AS ENUM");
List<String> values;
parse('(');
parseKeyword("AS");
if (!parseIf(')')) {
values = parseList(',', ParseContext::parseStringLiteral);
parse(')');
if (parseKeywordIf("ENUM")) {
List<String> values;
parse('(');
if (!parseIf(')')) {
values = parseList(',', ParseContext::parseStringLiteral);
parse(')');
}
else
values = new ArrayList<>();
return dsl.createType(name).asEnum(values.toArray(EMPTY_STRING));
}
else {
parseKeywordIf("OBJECT");
parse('(');
List<Field<?>> fields = parseList(',', ctx -> DSL.field(parseIdentifier(), parseDataType()));
parse(')');
return dsl.createType(name).as(fields);
}
else
values = new ArrayList<>();
return dsl.createType(name).asEnum(values.toArray(EMPTY_STRING));
}
private final Index parseIndexSpecification(Table<?> table) {

View File

@ -2269,10 +2269,13 @@ public final class QOM {
{
@NotNull Type<?> $type();
@NotNull UnmodifiableList<? extends Field<String>> $values();
@NotNull UnmodifiableList<? extends Field<?>> $attributes();
@CheckReturnValue
@NotNull CreateType $type(Type<?> type);
@CheckReturnValue
@NotNull CreateType $values(Collection<? extends Field<String>> values);
@CheckReturnValue
@NotNull CreateType $attributes(Collection<? extends Field<?>> attributes);
}
/**

View File

@ -5510,6 +5510,8 @@ final class Tools {