diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java index 582d498ece..f52240e8d8 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java @@ -2421,7 +2421,7 @@ implements name != null ? name(name) : AbstractRoutine.this.getQualifiedName(ctx), returnType, false, - fields.toArray(EMPTY_FIELD) + fields ); // [#3592] Decrease SQL -> PL/SQL context switches with Oracle Scalar Subquery Caching diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java index 3988a7b173..6be3029e2f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DSL.java +++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java @@ -15920,7 +15920,7 @@ public class DSL { @Support @PlainSQL public static Field function(String name, Class type, Field... arguments) { - return function(name, getDataType(type), Tools.nullSafe(arguments)); + return function(name, type, asList(arguments)); } /** @@ -15941,7 +15941,7 @@ public class DSL { @Support @PlainSQL public static Field function(String name, DataType type, Field... arguments) { - return new org.jooq.impl.Function<>(name, type, Tools.nullSafe(arguments)); + return function(name, type, asList(arguments)); } /** @@ -15963,7 +15963,7 @@ public class DSL { @NotNull @Support public static Field function(Name name, Class type, Field... arguments) { - return function(name, getDataType(type), Tools.nullSafe(arguments)); + return function(name, type, asList(arguments)); } /** @@ -15977,6 +15977,92 @@ public class DSL { @NotNull @Support public static Field function(Name name, DataType type, Field... arguments) { + return function(name, type, asList(arguments)); + } + + /** + * function() can be used to access native or user-defined + * functions that are not yet or insufficiently supported by jOOQ. + *

+ * NOTE: When inserting plain SQL into jOOQ objects, you must + * guarantee syntax integrity. You may also create the possibility of + * malicious SQL injection. Be sure to properly use bind variables and/or + * escape literals when concatenated into SQL clauses! + *

+ * NOTE [#15286]: It is strongly recommended to pass only + * {@link Class} references of types supported by jOOQ internally, i.e. + * types from {@link SQLDataType}. If you're using any custom data types by + * means of a {@link Converter} or {@link Binding}, it's better to pass that + * converted {@link DataType} reference explicitly to + * {@link #function(String, DataType, Field...)}. + * + * @param name The function name (without parentheses) + * @param type The function return type (a type that is supported by + * {@link SQLDataType}) + * @param arguments The function arguments + * @see SQL + */ + @NotNull + @Support + @PlainSQL + public static Field function(String name, Class type, Collection> arguments) { + return function(name, getDataType(type), Tools.nullSafe(arguments)); + } + + /** + * function() can be used to access native or user-defined + * functions that are not yet or insufficiently supported by jOOQ. + *

+ * NOTE: When inserting plain SQL into jOOQ objects, you must + * guarantee syntax integrity. You may also create the possibility of + * malicious SQL injection. Be sure to properly use bind variables and/or + * escape literals when concatenated into SQL clauses! + * + * @param name The function name (without parentheses) + * @param type The function return type + * @param arguments The function arguments + * @see SQL + */ + @NotNull + @Support + @PlainSQL + public static Field function(String name, DataType type, Collection> arguments) { + return new org.jooq.impl.Function<>(name, type, Tools.nullSafe(arguments)); + } + + /** + * function() can be used to access native or user-defined + * functions that are not yet or insufficiently supported by jOOQ. + *

+ * NOTE [#15286]: It is strongly recommended to pass only + * {@link Class} references of types supported by jOOQ internally, i.e. + * types from {@link SQLDataType}. If you're using any custom data types by + * means of a {@link Converter} or {@link Binding}, it's better to pass that + * converted {@link DataType} reference explicitly to + * {@link #function(Name, DataType, Field...)}. + * + * @param name The function name (possibly qualified) + * @param type The function return type (a type that is supported by + * {@link SQLDataType}) + * @param arguments The function arguments + */ + @NotNull + @Support + public static Field function(Name name, Class type, Collection> arguments) { + return function(name, getDataType(type), Tools.nullSafe(arguments)); + } + + /** + * function() can be used to access native or user-defined + * functions that are not yet or insufficiently supported by jOOQ. + * + * @param name The function name (possibly qualified) + * @param type The function return type + * @param arguments The function arguments + */ + @NotNull + @Support + public static Field function(Name name, DataType type, Collection> arguments) { return new org.jooq.impl.Function<>(name, type, Tools.nullSafe(arguments)); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Function.java b/jOOQ/src/main/java/org/jooq/impl/Function.java index aa2c27a69a..87b5434d81 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Function.java +++ b/jOOQ/src/main/java/org/jooq/impl/Function.java @@ -40,6 +40,8 @@ package org.jooq.impl; import static org.jooq.impl.DSL.unquotedName; import static org.jooq.impl.Tools.EMPTY_FIELD; +import java.util.Collection; + import org.jooq.DataType; import org.jooq.Field; import org.jooq.Name; @@ -54,15 +56,15 @@ final class Function extends AbstractFunction { private final QueryPartList> arguments; - Function(String name, DataType type, Field... arguments) { + Function(String name, DataType type, Collection> arguments) { this(unquotedName(name), type, arguments); } - Function(Name name, DataType type, Field... arguments) { + Function(Name name, DataType type, Collection> arguments) { this(name, type, true, arguments); } - Function(Name name, DataType type, boolean applySchemaMapping, Field... arguments) { + Function(Name name, DataType type, boolean applySchemaMapping, Collection> arguments) { super(name, type, applySchemaMapping); this.arguments = new QueryPartList<>(arguments); diff --git a/jOOQ/src/main/java/org/jooq/impl/Greatest.java b/jOOQ/src/main/java/org/jooq/impl/Greatest.java index 59f603efb7..5782a34754 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Greatest.java +++ b/jOOQ/src/main/java/org/jooq/impl/Greatest.java @@ -105,15 +105,15 @@ final class Greatest extends AbstractField implements QOM.Greatest { } case FIREBIRD: - ctx.visit(function(N_MAXVALUE, getDataType(), args.toArray(EMPTY_FIELD))); + ctx.visit(function(N_MAXVALUE, getDataType(), args)); return; case SQLITE: - ctx.visit(function(N_MAX, getDataType(), args.toArray(EMPTY_FIELD))); + ctx.visit(function(N_MAX, getDataType(), args)); return; default: - ctx.visit(function(N_GREATEST, getDataType(), args.toArray(EMPTY_FIELD))); + ctx.visit(function(N_GREATEST, getDataType(), args)); return; } } diff --git a/jOOQ/src/main/java/org/jooq/impl/Least.java b/jOOQ/src/main/java/org/jooq/impl/Least.java index 2cc292017f..eeb6b3357a 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Least.java +++ b/jOOQ/src/main/java/org/jooq/impl/Least.java @@ -105,15 +105,15 @@ final class Least extends AbstractField implements QOM.Least { } case FIREBIRD: - ctx.visit(function(N_MINVALUE, getDataType(), args.toArray(EMPTY_FIELD))); + ctx.visit(function(N_MINVALUE, getDataType(), args)); return; case SQLITE: - ctx.visit(function(N_MIN, getDataType(), args.toArray(EMPTY_FIELD))); + ctx.visit(function(N_MIN, getDataType(), args)); return; default: - ctx.visit(function(N_LEAST, getDataType(), args.toArray(EMPTY_FIELD))); + ctx.visit(function(N_LEAST, getDataType(), args)); return; } } diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index 3440d1203d..ded02fcb67 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -13000,7 +13000,7 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { // [#10107] Completely ignore functions in the DDLDatabase return isDDLDatabase() ? inline((Object) null) - : function(name, Object.class, arguments.toArray(EMPTY_FIELD)); + : function(name, Object.class, arguments); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 84ab0e80f8..cbfe3f53a6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -7380,6 +7380,17 @@ final class Tools { : field; } + static final List> nullSafe(Collection> fields) { + if (fields == null) + return emptyList(); + + List> result = new ArrayList<>(fields.size()); + for (Field f : fields) + result.add(nullSafe(f)); + + return result; + } + static final Field[] nullSafe(Field... fields) { if (fields == null) return EMPTY_FIELD;