From 7ee1f5fc005be7034676fdfb0f53b0a610184111 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Wed, 22 Apr 2020 13:54:01 +0200 Subject: [PATCH] [jOOQ/jOOQ#10097] Add support for DB2 CREATE INDEX .. EXCLUDE NULL KEYS clause --- .../java/org/jooq/CreateIndexWhereStep.java | 8 +++ .../java/org/jooq/impl/CreateIndexImpl.java | 54 ++++++++++++++----- .../src/main/java/org/jooq/impl/Keywords.java | 1 + jOOQ/src/main/java/org/jooq/impl/Tools.java | 13 +++++ 4 files changed, 62 insertions(+), 14 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/CreateIndexWhereStep.java b/jOOQ/src/main/java/org/jooq/CreateIndexWhereStep.java index 765d3c8b82..304a5db6e0 100644 --- a/jOOQ/src/main/java/org/jooq/CreateIndexWhereStep.java +++ b/jOOQ/src/main/java/org/jooq/CreateIndexWhereStep.java @@ -37,6 +37,7 @@ */ package org.jooq; +// ... // ... import static org.jooq.SQLDialect.POSTGRES; import static org.jooq.SQLDialect.SQLITE; @@ -159,4 +160,11 @@ public interface CreateIndexWhereStep extends CreateIndexFinalStep { @Support({ POSTGRES, SQLITE }) @PlainSQL CreateIndexFinalStep where(String sql, QueryPart... parts); + + /** + * Add a DB2 style EXCLUDE NULL KEYS clause to create a partial + * index. + */ + @Support({ POSTGRES, SQLITE }) + CreateIndexFinalStep excludeNullKeys(); } diff --git a/jOOQ/src/main/java/org/jooq/impl/CreateIndexImpl.java b/jOOQ/src/main/java/org/jooq/impl/CreateIndexImpl.java index 6117d64d43..ad3781b481 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CreateIndexImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/CreateIndexImpl.java @@ -55,11 +55,15 @@ import static org.jooq.SQLDialect.POSTGRES; // ... // ... import static org.jooq.impl.DSL.name; +import static org.jooq.impl.DSL.row; import static org.jooq.impl.DSL.table; import static org.jooq.impl.Keywords.K_CREATE; +import static org.jooq.impl.Keywords.K_EXCLUDE; import static org.jooq.impl.Keywords.K_IF_NOT_EXISTS; import static org.jooq.impl.Keywords.K_INCLUDE; import static org.jooq.impl.Keywords.K_INDEX; +import static org.jooq.impl.Keywords.K_KEYS; +import static org.jooq.impl.Keywords.K_NULL; import static org.jooq.impl.Keywords.K_ON; import static org.jooq.impl.Keywords.K_STORING; import static org.jooq.impl.Keywords.K_UNIQUE; @@ -69,6 +73,8 @@ import static org.jooq.impl.Tools.EMPTY_NAME; import static org.jooq.impl.Tools.EMPTY_ORDERFIELD; import static org.jooq.impl.Tools.EMPTY_SORTFIELD; import static org.jooq.impl.Tools.EMPTY_STRING; +import static org.jooq.impl.Tools.field; +import static org.jooq.impl.Tools.fields; import java.util.Collection; import java.util.Set; @@ -102,19 +108,20 @@ final class CreateIndexImpl extends AbstractRowCountQuery implements /** * Generated UID */ - private static final long serialVersionUID = 8904572826501186329L; - private static final Clause[] CLAUSES = { CREATE_INDEX }; - private static final Set NO_SUPPORT_IF_NOT_EXISTS = SQLDialect.supportedBy(DERBY, FIREBIRD); - private static final Set SUPPORT_UNNAMED_INDEX = SQLDialect.supportedBy(POSTGRES); - private static final Set SUPPORT_INCLUDE = SQLDialect.supportedBy(POSTGRES); + private static final long serialVersionUID = 8904572826501186329L; + private static final Clause[] CLAUSES = { CREATE_INDEX }; + private static final Set NO_SUPPORT_IF_NOT_EXISTS = SQLDialect.supportedBy(DERBY, FIREBIRD); + private static final Set SUPPORT_UNNAMED_INDEX = SQLDialect.supportedBy(POSTGRES); + private static final Set SUPPORT_INCLUDE = SQLDialect.supportedBy(POSTGRES); - private final Index index; - private final boolean unique; - private final boolean ifNotExists; - private Table table; - private SortField[] sortFields; - private Field[] include; - private Condition where; + private final Index index; + private final boolean unique; + private final boolean ifNotExists; + private Table table; + private SortField[] sortFields; + private Field[] include; + private Condition where; + private boolean excludeNullKeys; CreateIndexImpl(Configuration configuration, Index index, boolean unique, boolean ifNotExists) { super(configuration); @@ -238,6 +245,12 @@ final class CreateIndexImpl extends AbstractRowCountQuery implements return where(DSL.condition(sql, parts)); } + @Override + public final CreateIndexImpl excludeNullKeys() { + excludeNullKeys = true; + return this; + } + // ------------------------------------------------------------------------ // XXX: QueryPart API // ------------------------------------------------------------------------ @@ -328,13 +341,26 @@ final class CreateIndexImpl extends AbstractRowCountQuery implements .sql(')'); } - if (where != null && ctx.configuration().data("org.jooq.ddl.ignore-storage-clauses") == null) + Condition c = where; + + if (excludeNullKeys && c == null) + + + + c = sortFields.length == 1 ? field(sortFields[0]).isNotNull() : row(fields(sortFields)).isNotNull(); + + if (c != null && ctx.configuration().data("org.jooq.ddl.ignore-storage-clauses") == null) ctx.formatSeparator() .visit(K_WHERE) .sql(' ') .qualify(false) - .visit(where) + .visit(c) .qualify(true); + + + + + } private final Name generatedName() { diff --git a/jOOQ/src/main/java/org/jooq/impl/Keywords.java b/jOOQ/src/main/java/org/jooq/impl/Keywords.java index 058fa83707..3a52c7e07c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Keywords.java +++ b/jOOQ/src/main/java/org/jooq/impl/Keywords.java @@ -221,6 +221,7 @@ final class Keywords { static final Keyword K_JSON_OBJECT = keyword("json_object"); static final Keyword K_KEEP = keyword("keep"); static final Keyword K_KEY = keyword("key"); + static final Keyword K_KEYS = keyword("keys"); static final Keyword K_LAST = keyword("last"); static final Keyword K_LATERAL = keyword("lateral"); static final Keyword K_LEADING = keyword("leading"); diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index f4a1deba76..b69dc6e2be 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -5166,6 +5166,19 @@ final class Tools { return DSL.field(DSL.name(name), field.getDataType()); } + static final Field field(SortField sortField) { + return ((SortFieldImpl) sortField).getField(); + } + + static final Field[] fields(SortField[] sortFields) { + Field[] result = new Field[sortFields.length]; + + for (int i = 0; i < result.length; i++) + result[i] = field(sortFields[i]); + + return result; + } + static final Field unalias(Field field) { Field result = aliased(field); return result != null ? result : field;