From 5b881d717c6730a61821622fed0b4db8f671ec57 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 22 Jun 2020 11:03:00 +0200 Subject: [PATCH] [jOOQ/jOOQ#10175] Add support for CARDINALITY() function --- .../main/java/org/jooq/impl/Cardinality.java | 78 +++++++++++++++++++ jOOQ/src/main/java/org/jooq/impl/DSL.java | 9 +++ jOOQ/src/main/java/org/jooq/impl/Names.java | 2 + .../main/java/org/jooq/impl/ParserImpl.java | 19 ++++- 4 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 jOOQ/src/main/java/org/jooq/impl/Cardinality.java diff --git a/jOOQ/src/main/java/org/jooq/impl/Cardinality.java b/jOOQ/src/main/java/org/jooq/impl/Cardinality.java new file mode 100644 index 0000000000..ce3cfc52ab --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/Cardinality.java @@ -0,0 +1,78 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.impl; + +import static org.jooq.impl.Names.N_ARRAY_LENGTH; +import static org.jooq.impl.Names.N_CARDINALITY; +import static org.jooq.impl.SQLDataType.INTEGER; + +import org.jooq.Context; +import org.jooq.Field; + +/** + * @author Lukas Eder + */ +final class Cardinality extends AbstractField { + + /** + * Generated UID + */ + private static final long serialVersionUID = 2503480426872240632L; + private final Field arg; + + Cardinality(Field arg) { + super(N_CARDINALITY, INTEGER); + + this.arg = arg; + } + + @Override + public final void accept(Context ctx) { + switch (ctx.family()) { + + + + + + + default: + ctx.visit(N_CARDINALITY).sql('(').visit(arg).sql(')'); + break; + } + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java index b4286ad70e..3f27467bd7 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DSL.java +++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java @@ -21117,6 +21117,15 @@ public class DSL { return new Array<>(fields); } + /** + * Calculate the cardinality of an array field. + */ + @NotNull + @Support({ H2, HSQLDB, POSTGRES }) + public static Field cardinality(Field field) { + return new Cardinality(field); + } + /** * Get the max value over a field: max(field). */ diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index 7437036cf0..f604b69a57 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Names.java +++ b/jOOQ/src/main/java/org/jooq/impl/Names.java @@ -59,6 +59,7 @@ final class Names { static final Name N_AGE = unquotedName("age"); static final Name N_ARRAY = unquotedName("array"); static final Name N_ARRAY_AGG = unquotedName("array_agg"); + static final Name N_ARRAY_LENGTH = unquotedName("array_length"); static final Name N_ASC = unquotedName("asc"); static final Name N_ASCII = unquotedName("ascii"); static final Name N_ASCII_VAL = unquotedName("ascii_val"); @@ -68,6 +69,7 @@ final class Names { static final Name N_BIT_COUNT = unquotedName("bit_count"); static final Name N_BOOL_AND = unquotedName("bool_and"); static final Name N_BOOL_OR = unquotedName("bool_or"); + static final Name N_CARDINALITY = unquotedName("cardinality"); static final Name N_CASE = unquotedName("case"); static final Name N_CAST = unquotedName("cast"); static final Name N_CEIL = unquotedName("ceil"); diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index e17ce9c0eb..18cf2c43ed 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -77,6 +77,7 @@ import static org.jooq.impl.DSL.bitOr; import static org.jooq.impl.DSL.bitXNor; import static org.jooq.impl.DSL.bitXor; import static org.jooq.impl.DSL.boolOr; +import static org.jooq.impl.DSL.cardinality; import static org.jooq.impl.DSL.cast; import static org.jooq.impl.DSL.catalog; import static org.jooq.impl.DSL.ceil; @@ -6481,6 +6482,7 @@ final class ParserImpl implements Parser { private static final FieldOrRow parseTerm(ParserContext ctx, Type type) { FieldOrRow field; + Field arg; Object value; switch (ctx.characterUpper()) { @@ -6551,6 +6553,8 @@ final class ParserImpl implements Parser { return field; else if ((field = parseFieldCharLengthIf(ctx)) != null) return field; + else if ((field = parseFieldCardinalityIf(ctx)) != null) + return field; else if (parseFunctionNameIf(ctx, "CEILING") || parseFunctionNameIf(ctx, "CEIL")) return ceil((Field) parseFieldNumericOpParenthesised(ctx)); else if (parseFunctionNameIf(ctx, "COSH")) @@ -7715,6 +7719,17 @@ final class ParserImpl implements Parser { return jsonEntry(key, value); } + private static final Field parseFieldCardinalityIf(ParserContext ctx) { + if (parseKeywordIf(ctx, "CARDINALITY")) { + parse(ctx, '('); + Field f = (Field) parseField(ctx, A); + parse(ctx, ')'); + return cardinality(f); + } + + return null; + } + private static final Field parseArrayValueConstructorIf(ParserContext ctx) { if (parseKeywordIf(ctx, "ARRAY")) { parse(ctx, '['); @@ -11690,8 +11705,8 @@ final class ParserImpl implements Parser { return true; } - private static final boolean parseFunctionNameIf(ParserContext ctx, String string) { - return peekKeyword(ctx, string, true, false, true); + private static final boolean parseFunctionNameIf(ParserContext ctx, String name) { + return peekKeyword(ctx, name, true, false, true); } private static final boolean parseOperator(ParserContext ctx, String operator) {