[#7171] [#7347] Support parsing KEY/INDEX specifications in MySQL CREATE TABLE statements

This commit is contained in:
lukaseder 2018-03-29 14:46:47 +02:00
parent 51a146375c
commit a7e429de44
3 changed files with 66 additions and 20 deletions

View File

@ -417,16 +417,24 @@ final class CreateTableImpl<R extends Record> extends AbstractQuery implements
ctx.end(CREATE_TABLE_CONSTRAINTS);
if (!indexes.isEmpty() && !NO_SUPPORT_INDEXES.contains(ctx.family()))
for (Index index : indexes)
if (!indexes.isEmpty() && !NO_SUPPORT_INDEXES.contains(ctx.family())) {
ctx.qualify(false);
for (Index index : indexes) {
ctx.sql(',')
.formatSeparator()
.visit(K_INDEX).sql(' ').visit(index.getUnqualifiedName())
.sql(" (")
.qualify(false)
.visit(K_INDEX);
if (!"".equals(index.getName()))
ctx.sql(' ').visit(index.getUnqualifiedName());
ctx.sql(" (")
.visit(new SortFieldList(index.getFields()))
.qualify(qualify)
.sql(')');
}
ctx.qualify(qualify);
}
ctx.formatIndentEnd()
.formatNewLine()

View File

@ -60,14 +60,21 @@ public final class Internal {
/**
* Factory method for indexes.
*/
public static Index createIndex(String name, Table<?> table, OrderField<?>[] sortFields, boolean unique) {
return new IndexImpl(DSL.name(name), table, sortFields, null, unique);
public static final Index createIndex(String name, Table<?> table, OrderField<?>[] sortFields, boolean unique) {
return createIndex(DSL.name(name), table, sortFields, unique);
}
/**
* Factory method for indexes.
*/
public static final Index createIndex(Name name, Table<?> table, OrderField<?>[] sortFields, boolean unique) {
return new IndexImpl(name, table, sortFields, null, unique);
}
/**
* Factory method for identities.
*/
public static <R extends Record, T> Identity<R, T> createIdentity(Table<R> table, TableField<R, T> field) {
public static final <R extends Record, T> Identity<R, T> createIdentity(Table<R> table, TableField<R, T> field) {
return new IdentityImpl<R, T>(table, field);
}
@ -77,7 +84,7 @@ public final class Internal {
@SafeVarargs
public static <R extends Record> UniqueKey<R> createUniqueKey(Table<R> table, TableField<R, ?>... fields) {
public static final <R extends Record> UniqueKey<R> createUniqueKey(Table<R> table, TableField<R, ?>... fields) {
return new UniqueKeyImpl<R>(table, fields);
}
@ -87,7 +94,7 @@ public final class Internal {
@SafeVarargs
public static <R extends Record> UniqueKey<R> createUniqueKey(Table<R> table, String name, TableField<R, ?>... fields) {
public static final <R extends Record> UniqueKey<R> createUniqueKey(Table<R> table, String name, TableField<R, ?>... fields) {
return new UniqueKeyImpl<R>(table, name, fields);
}
@ -97,7 +104,7 @@ public final class Internal {
@SafeVarargs
public static <R extends Record, U extends Record> ForeignKey<R, U> createForeignKey(UniqueKey<U> key, Table<R> table, TableField<R, ?>... fields) {
public static final <R extends Record, U extends Record> ForeignKey<R, U> createForeignKey(UniqueKey<U> key, Table<R> table, TableField<R, ?>... fields) {
return createForeignKey(key, table, null, fields);
}
@ -107,7 +114,7 @@ public final class Internal {
@SafeVarargs
public static <R extends Record, U extends Record> ForeignKey<R, U> createForeignKey(UniqueKey<U> key, Table<R> table, String name, TableField<R, ?>... fields) {
public static final <R extends Record, U extends Record> ForeignKey<R, U> createForeignKey(UniqueKey<U> key, Table<R> table, String name, TableField<R, ?>... fields) {
ForeignKey<R, U> result = new ReferenceImpl<R, U>(key, table, name, fields);
if (key instanceof UniqueKeyImpl)

View File

@ -285,6 +285,7 @@ import org.jooq.CreateTableAsStep;
import org.jooq.CreateTableColumnStep;
import org.jooq.CreateTableCommentStep;
import org.jooq.CreateTableConstraintStep;
import org.jooq.CreateTableIndexStep;
import org.jooq.CreateTableStorageStep;
import org.jooq.CreateTableWithDataStep;
import org.jooq.DDLQuery;
@ -311,6 +312,7 @@ import org.jooq.GrantWithGrantOptionStep;
import org.jooq.GroupConcatOrderByStep;
import org.jooq.GroupConcatSeparatorStep;
import org.jooq.GroupField;
import org.jooq.Index;
import org.jooq.Insert;
import org.jooq.InsertOnConflictDoUpdateStep;
import org.jooq.InsertOnConflictWhereStep;
@ -825,7 +827,7 @@ final class ParserImpl implements Parser {
return result;
}
private static void parseLimit(ParserContext ctx, SelectQueryImpl<Record> result, boolean offset) {
private static final void parseLimit(ParserContext ctx, SelectQueryImpl<Record> result, boolean offset) {
boolean offsetStandard = false;
boolean offsetPostgres = false;
@ -2106,11 +2108,27 @@ final class ParserImpl implements Parser {
else {
List<Field<?>> fields = new ArrayList<Field<?>>();
List<Constraint> constraints = new ArrayList<Constraint>();
List<Index> indexes = new ArrayList<Index>();
boolean primary = false;
boolean noConstraint = true;
parse(ctx, '(');
columnLoop:
do {
int position = ctx.position();
// [#7348] Look ahead if the next tokens indicate a MySQL index definition
if (parseKeywordIf(ctx, "KEY") || parseKeywordIf(ctx, "INDEX")) {
if (parseIf(ctx, '(') || parseIdentifierIf(ctx) != null) {
ctx.position(position);
noConstraint = false;
break columnLoop;
}
ctx.position(position);
}
Name fieldName = parseIdentifier(ctx);
DataType<?> type = parseDataType(ctx);
Comment fieldComment = null;
@ -2308,8 +2326,10 @@ final class ParserImpl implements Parser {
constraints.add(parseForeignKeySpecification(ctx, constraint));
else if (parseKeywordIf(ctx, "CHECK"))
constraints.add(parseCheckSpecification(ctx, constraint));
else if (constraint == null && (parseKeywordIf(ctx, "KEY") || parseKeywordIf(ctx, "INDEX")))
indexes.add(parseIndexSpecification(ctx, tableName));
else
throw ctx.expected("CHECK", "FOREIGN KEY", "PRIMARY KEY", "UNIQUE");
throw ctx.expected("CHECK", "CONSTRAINT", "FOREIGN KEY", "INDEX", "KEY", "PRIMARY KEY", "UNIQUE");
}
while (parseIf(ctx, ','));
}
@ -2325,20 +2345,23 @@ final class ParserImpl implements Parser {
CreateTableConstraintStep s3 = constraints.isEmpty()
? s2
: s2.constraints(constraints);
CreateTableCommentStep s4 = s3;
CreateTableIndexStep s4 = indexes.isEmpty()
? s3
: s3.indexes(indexes);
CreateTableCommentStep s5 = s4;
if (temporary && parseKeywordIf(ctx, "ON COMMIT")) {
if (parseKeywordIf(ctx, "DELETE ROWS"))
s4 = s3.onCommitDeleteRows();
s5 = s4.onCommitDeleteRows();
else if (parseKeywordIf(ctx, "DROP"))
s4 = s3.onCommitDrop();
s5 = s4.onCommitDrop();
else if (parseKeywordIf(ctx, "PRESERVE ROWS"))
s4 = s3.onCommitPreserveRows();
s5 = s4.onCommitPreserveRows();
else
throw ctx.unsupportedClause();
}
storageStep = commentStep = s4;
storageStep = commentStep = s5;
}
List<SQL> storage = new ArrayList<SQL>();
@ -2477,6 +2500,14 @@ final class ParserImpl implements Parser {
return storageStep;
}
private static final Index parseIndexSpecification(ParserContext ctx, Table<?> table) {
Name name = parseIdentifierIf(ctx);
parse(ctx, '(');
SortField<?>[] fields = parseSortSpecification(ctx).toArray(EMPTY_SORTFIELD);
parse(ctx, ')');
return Internal.createIndex(name == null ? DSL.name("") : name, table, fields, false);
}
private static final Constraint parsePrimaryKeySpecification(ParserContext ctx, ConstraintTypeStep constraint) {
parse(ctx, '(');
Field<?>[] fieldNames = parseFieldNames(ctx).toArray(EMPTY_FIELD);