From d8b72f2ada442cb815e371c0451b5f5b75b3362f Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 3 Dec 2019 16:53:25 +0100 Subject: [PATCH] [jOOQ/jOOQ#8528] Support FIRST / BEFORE / AFTER with multi column ADD --- .../java/org/jooq/impl/DDLInterpreter.java | 82 ++++++++++++++++--- jOOQ/src/main/java/org/jooq/impl/Tools.java | 36 +++++--- 2 files changed, 96 insertions(+), 22 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/DDLInterpreter.java b/jOOQ/src/main/java/org/jooq/impl/DDLInterpreter.java index 3b54769273..0256d36d4a 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DDLInterpreter.java +++ b/jOOQ/src/main/java/org/jooq/impl/DDLInterpreter.java @@ -46,6 +46,7 @@ import static org.jooq.impl.DSL.unquotedName; import static org.jooq.impl.SQLDataType.BIGINT; import static org.jooq.impl.Tools.EMPTY_FIELD; import static org.jooq.impl.Tools.intersect; +import static org.jooq.impl.Tools.reverseIterable; import java.util.ArrayList; import java.util.Arrays; @@ -414,15 +415,31 @@ final class DDLInterpreter { else if (fc instanceof Constraint && !fc.getUnqualifiedName().empty() && existing.constraint((Constraint) fc) != null) throw constraintAlreadyExists((Constraint) fc); - for (FieldOrConstraint fc : query.$add()) - if (fc instanceof Field) + if (query.$addFirst()) { + for (Field f : assertFields(query, reverseIterable(query.$add()))) + addField(existing, 0, (UnqualifiedName) f.getUnqualifiedName(), ((Field) f).getDataType()); + } + else if (query.$addBefore() != null) { + int index = indexOrFail(existing, query.$addBefore()); - // TODO: FIRST, BEFORE, AFTER - existing.fields.add(new MutableField((UnqualifiedName) fc.getUnqualifiedName(), existing, ((Field) fc).getDataType())); - else if (fc instanceof Constraint) - addConstraint(query, (ConstraintImpl) fc, schema, existing); - else - throw unsupportedQuery(query); + for (Field f : assertFields(query, reverseIterable(query.$add()))) + addField(existing, index, (UnqualifiedName) f.getUnqualifiedName(), ((Field) f).getDataType()); + } + else if (query.$addAfter() != null) { + int index = indexOrFail(existing, query.$addAfter()) + 1; + + for (Field f : assertFields(query, reverseIterable(query.$add()))) + addField(existing, index, (UnqualifiedName) f.getUnqualifiedName(), ((Field) f).getDataType()); + } + else { + for (FieldOrConstraint fc : query.$add()) + if (fc instanceof Field) + addField(existing, Integer.MAX_VALUE, (UnqualifiedName) fc.getUnqualifiedName(), ((Field) fc).getDataType()); + else if (fc instanceof Constraint) + addConstraint(query, (ConstraintImpl) fc, schema, existing); + else + throw unsupportedQuery(query); + } } else if (query.$addColumn() != null) { if (existing.field(query.$addColumn()) != null) @@ -431,14 +448,17 @@ final class DDLInterpreter { else return; + UnqualifiedName name = (UnqualifiedName) query.$addColumn().getUnqualifiedName(); + DataType dataType = query.$addColumnType(); + if (query.$addFirst()) - existing.fields.add(0, new MutableField((UnqualifiedName) query.$addColumn().getUnqualifiedName(), existing, query.$addColumnType())); + addField(existing, 0, name, dataType); else if (query.$addBefore() != null) - existing.fields.add(indexOrFail(existing, query.$addBefore()), new MutableField((UnqualifiedName) query.$addColumn().getUnqualifiedName(), existing, query.$addColumnType())); + addField(existing, indexOrFail(existing, query.$addBefore()), name, dataType); else if (query.$addAfter() != null) - existing.fields.add(indexOrFail(existing, query.$addAfter()) + 1, new MutableField((UnqualifiedName) query.$addColumn().getUnqualifiedName(), existing, query.$addColumnType())); + addField(existing, indexOrFail(existing, query.$addAfter()) + 1, name, dataType); else - existing.fields.add(new MutableField((UnqualifiedName) query.$addColumn().getUnqualifiedName(), existing, query.$addColumnType())); + addField(existing, Integer.MAX_VALUE, name, dataType); } else if (query.$addConstraint() != null) { addConstraint(query, (ConstraintImpl) query.$addConstraint(), schema, existing); @@ -553,6 +573,44 @@ final class DDLInterpreter { throw unsupportedQuery(query); } + private final Iterable> assertFields(final Query query, final Iterable fields) { + return new Iterable>() { + @Override + public Iterator> iterator() { + return new Iterator>() { + Iterator it = fields.iterator(); + + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public Field next() { + FieldOrConstraint next = it.next(); + + if (next instanceof Field) + return (Field) next; + else + throw unsupportedQuery(query); + } + + @Override + public void remove() { + it.remove(); + } + }; + } + }; + } + + private final void addField(MutableTable existing, int index, UnqualifiedName name, DataType dataType) { + if (index == Integer.MAX_VALUE) + existing.fields.add( new MutableField(name, existing, dataType)); + else + existing.fields.add(index, new MutableField(name, existing, dataType)); + } + private final void addConstraint(Query query, ConstraintImpl impl, MutableSchema schema, MutableTable existing) { if (!impl.getUnqualifiedName().empty() && existing.constraint(impl) != null) throw constraintAlreadyExists(impl); diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 1605b63c03..400a31a4a0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -188,6 +188,7 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.ListIterator; import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; @@ -214,6 +215,7 @@ import org.jooq.CommonTableExpression; import org.jooq.Condition; import org.jooq.Configuration; import org.jooq.Context; +import org.jooq.Converter; import org.jooq.Cursor; import org.jooq.DSLContext; import org.jooq.DataType; @@ -1921,12 +1923,7 @@ final class Tools { @SafeVarargs static final Iterable reverseIterable(final T... array) { - return new Iterable() { - @Override - public Iterator iterator() { - return reverseIterator(array); - } - }; + return reverseIterable(Arrays.asList(array)); } /** @@ -1936,22 +1933,41 @@ final class Tools { @SafeVarargs static final Iterator reverseIterator(final T... array) { + return reverseIterator(Arrays.asList(array)); + } + + /** + * Reverse iterate over a list. + */ + static final Iterable reverseIterable(final List list) { + return new Iterable() { + @Override + public Iterator iterator() { + return reverseIterator(list); + } + }; + } + + /** + * Reverse iterate over a list. + */ + static final Iterator reverseIterator(final List list) { return new Iterator() { - int index = array.length; + ListIterator li = list.listIterator(list.size()); @Override public boolean hasNext() { - return index > 0; + return li.hasPrevious(); } @Override public T next() { - return array[--index]; + return li.previous(); } @Override public void remove() { - throw new UnsupportedOperationException("remove"); + li.remove(); } }; }