From 77837a966b6950bb3a40845f1d682d408ac65e0f Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Thu, 28 Nov 2024 13:47:40 +0100 Subject: [PATCH] [jOOQ/jOOQ#17686] Add support for PostgreSQL's STRING_TO_ARRAY and ARRAY_TO_STRING functions --- .../java/org/jooq/impl/ArrayToString.java | 207 +++++++++++++++++ jOOQ/src/main/java/org/jooq/impl/DSL.java | 116 ++++++++++ jOOQ/src/main/java/org/jooq/impl/Names.java | 4 +- .../main/java/org/jooq/impl/ParserImpl.java | 4 + jOOQ/src/main/java/org/jooq/impl/QOM.java | 94 ++++++++ .../java/org/jooq/impl/StringToArray.java | 216 ++++++++++++++++++ 6 files changed, 640 insertions(+), 1 deletion(-) create mode 100644 jOOQ/src/main/java/org/jooq/impl/ArrayToString.java create mode 100644 jOOQ/src/main/java/org/jooq/impl/StringToArray.java diff --git a/jOOQ/src/main/java/org/jooq/impl/ArrayToString.java b/jOOQ/src/main/java/org/jooq/impl/ArrayToString.java new file mode 100644 index 0000000000..2173967117 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/ArrayToString.java @@ -0,0 +1,207 @@ +/* + * 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 + * + * https://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 + * Apache-2.0 license and offer limited warranties, support, maintenance, and + * commercial database integrations. + * + * For more information, please visit: https://www.jooq.org/legal/licensing + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.impl; + +import static org.jooq.impl.DSL.*; +import static org.jooq.impl.Internal.*; +import static org.jooq.impl.Keywords.*; +import static org.jooq.impl.Names.*; +import static org.jooq.impl.SQLDataType.*; +import static org.jooq.impl.Tools.*; +import static org.jooq.impl.Tools.BooleanDataKey.*; +import static org.jooq.impl.Tools.ExtendedDataKey.*; +import static org.jooq.impl.Tools.SimpleDataKey.*; +import static org.jooq.SQLDialect.*; + +import org.jooq.*; +import org.jooq.Function1; +import org.jooq.Record; +import org.jooq.conf.ParamType; +import org.jooq.tools.StringUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + + + +/** + * The ARRAY TO STRING statement. + */ +@SuppressWarnings({ "rawtypes", "unchecked", "unused" }) +final class ArrayToString +extends + AbstractField +implements + QOM.ArrayToString +{ + + final Field array; + final Field delimiter; + final Field nullString; + + ArrayToString( + Field array, + Field delimiter + ) { + super( + N_ARRAY_TO_STRING, + allNotNull(VARCHAR, array, delimiter) + ); + + this.array = nullSafeNotNull(array, OTHER.array()); + this.delimiter = nullSafeNotNull(delimiter, VARCHAR); + this.nullString = null; + } + + ArrayToString( + Field array, + Field delimiter, + Field nullString + ) { + super( + N_ARRAY_TO_STRING, + allNotNull(VARCHAR, array, delimiter, nullString) + ); + + this.array = nullSafeNotNull(array, OTHER.array()); + this.delimiter = nullSafeNotNull(delimiter, VARCHAR); + this.nullString = nullSafeNotNull(nullString, VARCHAR); + } + + // ------------------------------------------------------------------------- + // XXX: QueryPart API + // ------------------------------------------------------------------------- + + @Override + final boolean parenthesised(Context ctx) { + return true; + } + + @Override + public final void accept(Context ctx) { + switch (ctx.family()) { + + + + + + + default: + if (nullString != null) + ctx.visit(function(N_ARRAY_TO_STRING, getDataType(), array, delimiter, nullString)); + else + ctx.visit(function(N_ARRAY_TO_STRING, getDataType(), array, delimiter)); + break; + } + } + + + + + + + + + + + + + + + + // ------------------------------------------------------------------------- + // XXX: Query Object Model + // ------------------------------------------------------------------------- + + @Override + public final Field $arg1() { + return array; + } + + @Override + public final Field $arg2() { + return delimiter; + } + + @Override + public final Field $arg3() { + return nullString; + } + + @Override + public final QOM.ArrayToString $arg1(Field newValue) { + return $constructor().apply(newValue, $arg2(), $arg3()); + } + + @Override + public final QOM.ArrayToString $arg2(Field newValue) { + return $constructor().apply($arg1(), newValue, $arg3()); + } + + @Override + public final QOM.ArrayToString $arg3(Field newValue) { + return $constructor().apply($arg1(), $arg2(), newValue); + } + + @Override + public final Function3, ? super Field, ? super Field, ? extends QOM.ArrayToString> $constructor() { + return (a1, a2, a3) -> new ArrayToString<>(a1, a2, a3); + } + + // ------------------------------------------------------------------------- + // XXX: The Object API + // ------------------------------------------------------------------------- + + @Override + public boolean equals(Object that) { + if (that instanceof QOM.ArrayToString o) { + return + StringUtils.equals($array(), o.$array()) && + StringUtils.equals($delimiter(), o.$delimiter()) && + StringUtils.equals($nullString(), o.$nullString()) + ; + } + else + return super.equals(that); + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java index ca69c50eda..4620b419c8 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DSL.java +++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java @@ -23250,6 +23250,64 @@ public class DSL { return new ArrayReplace<>(array, search, replace); } + /** + * The ARRAY_TO_STRING function. + *

+ * Join array elements into a string. + * + * @param array The array whose elements are joined + * @param delimiter The delimiter to place between elements + * @param nullString The NULL encoding + */ + @NotNull + @Support({ POSTGRES, YUGABYTEDB }) + public static Field arrayToString(Object[] array, @Stringly.Param String delimiter, @Stringly.Param String nullString) { + return new ArrayToString<>(Tools.field(array), Tools.field(delimiter), Tools.field(nullString)); + } + + /** + * The ARRAY_TO_STRING function. + *

+ * Join array elements into a string. + * + * @param array The array whose elements are joined + * @param delimiter The delimiter to place between elements + * @param nullString The NULL encoding + */ + @NotNull + @Support({ POSTGRES, YUGABYTEDB }) + public static Field arrayToString(Field array, Field delimiter, Field nullString) { + return new ArrayToString<>(array, delimiter, nullString); + } + + /** + * The ARRAY_TO_STRING function. + *

+ * Join array elements into a string. + * + * @param array The array whose elements are joined + * @param delimiter The delimiter to place between elements + */ + @NotNull + @Support({ POSTGRES, YUGABYTEDB }) + public static Field arrayToString(Object[] array, @Stringly.Param String delimiter) { + return new ArrayToString<>(Tools.field(array), Tools.field(delimiter)); + } + + /** + * The ARRAY_TO_STRING function. + *

+ * Join array elements into a string. + * + * @param array The array whose elements are joined + * @param delimiter The delimiter to place between elements + */ + @NotNull + @Support({ POSTGRES, YUGABYTEDB }) + public static Field arrayToString(Field array, Field delimiter) { + return new ArrayToString<>(array, delimiter); + } + /** * The ARRAY_FILTER function. *

@@ -23530,6 +23588,64 @@ public class DSL { return new ArrayNoneMatch<>(array, predicate); } + /** + * The STRING_TO_ARRAY function. + *

+ * Split a string into array elements. + * + * @param string The string to split + * @param delimiter The delimiter to parse between elements + * @param nullString The NULL encoding + */ + @NotNull + @Support({ POSTGRES, YUGABYTEDB }) + public static Field stringToArray(@Stringly.Param String string, @Stringly.Param String delimiter, @Stringly.Param String nullString) { + return new StringToArray(Tools.field(string), Tools.field(delimiter), Tools.field(nullString)); + } + + /** + * The STRING_TO_ARRAY function. + *

+ * Split a string into array elements. + * + * @param string The string to split + * @param delimiter The delimiter to parse between elements + * @param nullString The NULL encoding + */ + @NotNull + @Support({ POSTGRES, YUGABYTEDB }) + public static Field stringToArray(Field string, Field delimiter, Field nullString) { + return new StringToArray(string, delimiter, nullString); + } + + /** + * The STRING_TO_ARRAY function. + *

+ * Split a string into array elements. + * + * @param string The string to split + * @param delimiter The delimiter to parse between elements + */ + @NotNull + @Support({ POSTGRES, YUGABYTEDB }) + public static Field stringToArray(@Stringly.Param String string, @Stringly.Param String delimiter) { + return new StringToArray(Tools.field(string), Tools.field(delimiter)); + } + + /** + * The STRING_TO_ARRAY function. + *

+ * Split a string into array elements. + * + * @param string The string to split + * @param delimiter The delimiter to parse between elements + */ + @NotNull + @Support({ POSTGRES, YUGABYTEDB }) + public static Field stringToArray(Field string, Field delimiter) { + return new StringToArray(string, delimiter); + } + // ------------------------------------------------------------------------- // Utility functions // ------------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index f9f3593ca5..d9f1cdaa65 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Names.java +++ b/jOOQ/src/main/java/org/jooq/impl/Names.java @@ -262,7 +262,6 @@ final class Names { static final Name N_SEQ8 = systemName("seq8"); static final Name N_SHL = systemName("shl"); static final Name N_SHR = systemName("shr"); - static final Name N_SPLIT = systemName("split"); static final Name N_SQL_TSI_DAY = systemName("sql_tsi_day"); static final Name N_SQL_TSI_FRAC_SECOND = systemName("sql_tsi_frac_second"); static final Name N_SQL_TSI_HOUR = systemName("sql_tsi_hour"); @@ -355,6 +354,7 @@ final class Names { static final Name N_ARRAY_PREPEND = systemName("array_prepend"); static final Name N_ARRAY_REMOVE = systemName("array_remove"); static final Name N_ARRAY_REPLACE = systemName("array_replace"); + static final Name N_ARRAY_TO_STRING = systemName("array_to_string"); static final Name N_ARRAY_TRANSFORM = systemName("array_transform"); static final Name N_ASC = systemName("asc"); static final Name N_ASCII = systemName("ascii"); @@ -593,6 +593,7 @@ final class Names { static final Name N_SIN = systemName("sin"); static final Name N_SINH = systemName("sinh"); static final Name N_SPACE = systemName("space"); + static final Name N_SPLIT = systemName("split"); static final Name N_SPLIT_PART = systemName("split_part"); static final Name N_SQR = systemName("sqr"); static final Name N_SQRT = systemName("sqrt"); @@ -600,6 +601,7 @@ final class Names { static final Name N_STARTS_WITH = systemName("starts_with"); static final Name N_STDDEV_POP = systemName("stddev_pop"); static final Name N_STDDEV_SAMP = systemName("stddev_samp"); + static final Name N_STRING_TO_ARRAY = systemName("string_to_array"); static final Name N_STRREVERSE = systemName("strreverse"); static final Name N_STRTOK = systemName("strtok"); static final Name N_STR_SPLIT = systemName("str_split"); diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index 0069193c61..afa640e313 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -9063,6 +9063,8 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { return parseFunctionArgs2((f1, f2) -> arrayRemove((Field) f1, (Field) f2)); else if (parseFunctionNameIf("ARRAY_REPLACE")) return parseFunctionArgs3((f1, f2, f3) -> arrayReplace((Field) f1, (Field) f2, (Field) f3)); + else if (parseFunctionNameIf("ARRAY_TO_STRING")) + return parseFunctionArgs3(DSL::arrayToString, DSL::arrayToString); else if ((field = parseFieldArrayConstructIf()) != null) return field; else if (parseFunctionNameIf("ADD")) @@ -9618,6 +9620,8 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { return space((Field) parseFieldParenthesised()); else if (parseFunctionNameIf("SPLIT_PART")) return parseFunctionArgs3(DSL::splitPart); + else if (parseFunctionNameIf("SPLIT", "STRING_TO_ARRAY")) + return parseFunctionArgs3(DSL::stringToArray, DSL::stringToArray); else if (parseFunctionNameIf("STR_REPLACE")) return parseFunctionArgs3(DSL::replace, DSL::replace); else if (parseFunctionNameIf("STARTS_WITH", "startsWith")) diff --git a/jOOQ/src/main/java/org/jooq/impl/QOM.java b/jOOQ/src/main/java/org/jooq/impl/QOM.java index 8e9f73f14d..5b3bee6204 100644 --- a/jOOQ/src/main/java/org/jooq/impl/QOM.java +++ b/jOOQ/src/main/java/org/jooq/impl/QOM.java @@ -6727,6 +6727,53 @@ public final class QOM { @NotNull default ArrayReplace $replace(Field newReplace) { return $arg3(newReplace); } } + /** + * The ARRAY TO STRING function. + *

+ * Join array elements into a string. + */ + public /*sealed*/ interface ArrayToString + extends + UOperator3, Field, Field, ArrayToString>, + org.jooq.Field + //permits + // ArrayToString + { + + /** + * The array whose elements are joined + */ + @NotNull default Field $array() { return $arg1(); } + + /** + * The array whose elements are joined + */ + @CheckReturnValue + @NotNull default ArrayToString $array(Field newArray) { return $arg1(newArray); } + + /** + * The delimiter to place between elements + */ + @NotNull default Field $delimiter() { return $arg2(); } + + /** + * The delimiter to place between elements + */ + @CheckReturnValue + @NotNull default ArrayToString $delimiter(Field newDelimiter) { return $arg2(newDelimiter); } + + /** + * The NULL encoding + */ + @Nullable default Field $nullString() { return $arg3(); } + + /** + * The NULL encoding + */ + @CheckReturnValue + @NotNull default ArrayToString $nullString(Field newNullString) { return $arg3(newNullString); } + } + /** * The ARRAY FILTER function. *

@@ -6907,6 +6954,53 @@ public final class QOM { @NotNull default ArrayNoneMatch $predicate(Lambda1, Condition> newPredicate) { return $arg2(newPredicate); } } + /** + * The STRING TO ARRAY function. + *

+ * Split a string into array elements. + */ + public /*sealed*/ interface StringToArray + extends + UOperator3, Field, Field, StringToArray>, + org.jooq.Field + //permits + // StringToArray + { + + /** + * The string to split + */ + @NotNull default Field $string() { return $arg1(); } + + /** + * The string to split + */ + @CheckReturnValue + @NotNull default StringToArray $string(Field newString) { return $arg1(newString); } + + /** + * The delimiter to parse between elements + */ + @NotNull default Field $delimiter() { return $arg2(); } + + /** + * The delimiter to parse between elements + */ + @CheckReturnValue + @NotNull default StringToArray $delimiter(Field newDelimiter) { return $arg2(newDelimiter); } + + /** + * The NULL encoding + */ + @Nullable default Field $nullString() { return $arg3(); } + + /** + * The NULL encoding + */ + @CheckReturnValue + @NotNull default StringToArray $nullString(Field newNullString) { return $arg3(newNullString); } + } + /** * The NVL function. *

diff --git a/jOOQ/src/main/java/org/jooq/impl/StringToArray.java b/jOOQ/src/main/java/org/jooq/impl/StringToArray.java new file mode 100644 index 0000000000..2e0aba950a --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/StringToArray.java @@ -0,0 +1,216 @@ +/* + * 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 + * + * https://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 + * Apache-2.0 license and offer limited warranties, support, maintenance, and + * commercial database integrations. + * + * For more information, please visit: https://www.jooq.org/legal/licensing + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.impl; + +import static org.jooq.impl.DSL.*; +import static org.jooq.impl.Internal.*; +import static org.jooq.impl.Keywords.*; +import static org.jooq.impl.Names.*; +import static org.jooq.impl.SQLDataType.*; +import static org.jooq.impl.Tools.*; +import static org.jooq.impl.Tools.BooleanDataKey.*; +import static org.jooq.impl.Tools.ExtendedDataKey.*; +import static org.jooq.impl.Tools.SimpleDataKey.*; +import static org.jooq.SQLDialect.*; + +import org.jooq.*; +import org.jooq.Function1; +import org.jooq.Record; +import org.jooq.conf.ParamType; +import org.jooq.tools.StringUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + + + +/** + * The STRING TO ARRAY statement. + */ +@SuppressWarnings({ "rawtypes", "unchecked", "unused" }) +final class StringToArray +extends + AbstractField +implements + QOM.StringToArray +{ + + final Field string; + final Field delimiter; + final Field nullString; + + StringToArray( + Field string, + Field delimiter + ) { + super( + N_STRING_TO_ARRAY, + allNotNull(VARCHAR.array(), string, delimiter) + ); + + this.string = nullSafeNotNull(string, VARCHAR); + this.delimiter = nullSafeNotNull(delimiter, VARCHAR); + this.nullString = null; + } + + StringToArray( + Field string, + Field delimiter, + Field nullString + ) { + super( + N_STRING_TO_ARRAY, + allNotNull(VARCHAR.array(), string, delimiter, nullString) + ); + + this.string = nullSafeNotNull(string, VARCHAR); + this.delimiter = nullSafeNotNull(delimiter, VARCHAR); + this.nullString = nullSafeNotNull(nullString, VARCHAR); + } + + // ------------------------------------------------------------------------- + // XXX: QueryPart API + // ------------------------------------------------------------------------- + + @Override + final boolean parenthesised(Context ctx) { + return true; + } + + @Override + public final void accept(Context ctx) { + switch (ctx.family()) { + + + + + + + + + + + + + + + + default: + if (nullString != null) + ctx.visit(function(N_STRING_TO_ARRAY, getDataType(), string, delimiter, nullString)); + else + ctx.visit(function(N_STRING_TO_ARRAY, getDataType(), string, delimiter)); + break; + } + } + + + + + + + + + + + + + + + + // ------------------------------------------------------------------------- + // XXX: Query Object Model + // ------------------------------------------------------------------------- + + @Override + public final Field $arg1() { + return string; + } + + @Override + public final Field $arg2() { + return delimiter; + } + + @Override + public final Field $arg3() { + return nullString; + } + + @Override + public final QOM.StringToArray $arg1(Field newValue) { + return $constructor().apply(newValue, $arg2(), $arg3()); + } + + @Override + public final QOM.StringToArray $arg2(Field newValue) { + return $constructor().apply($arg1(), newValue, $arg3()); + } + + @Override + public final QOM.StringToArray $arg3(Field newValue) { + return $constructor().apply($arg1(), $arg2(), newValue); + } + + @Override + public final Function3, ? super Field, ? super Field, ? extends QOM.StringToArray> $constructor() { + return (a1, a2, a3) -> new StringToArray(a1, a2, a3); + } + + // ------------------------------------------------------------------------- + // XXX: The Object API + // ------------------------------------------------------------------------- + + @Override + public boolean equals(Object that) { + if (that instanceof QOM.StringToArray o) { + return + StringUtils.equals($string(), o.$string()) && + StringUtils.equals($delimiter(), o.$delimiter()) && + StringUtils.equals($nullString(), o.$nullString()) + ; + } + else + return super.equals(that); + } +}