diff --git a/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt b/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt index 7a3ed19b21..96f2fb3848 100644 --- a/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt +++ b/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt @@ -79,6 +79,16 @@ inline fun Field.orNotExists(select: Select<*>): Condition = condition( inline fun Field.not(): Condition = condition(this).not() +// ---------------------------------------------------------------------------- +// Extensions to make Field aware of its being an array +// ---------------------------------------------------------------------------- + +@Support +inline operator fun Field>.get(index: Int) = arrayGet(this, index) + +@Support +inline operator fun Field>.get(index: Field) = arrayGet(this, index) + // ---------------------------------------------------------------------------- // Extensions to make Select> a scalar subquery of type Field // ---------------------------------------------------------------------------- @@ -194,4 +204,3 @@ inline fun Select>.notIn(vararg values: T): Conditio @Support inline fun Select>.notIn(vararg values: Field<*>): Condition = field(this).notIn(values.asList()) - diff --git a/jOOQ/src/main/java/org/jooq/DataType.java b/jOOQ/src/main/java/org/jooq/DataType.java index 2a7b0ec73d..45c4e5ed0e 100644 --- a/jOOQ/src/main/java/org/jooq/DataType.java +++ b/jOOQ/src/main/java/org/jooq/DataType.java @@ -140,6 +140,20 @@ public interface DataType extends Named { @NotNull DataType getArrayDataType(); + /** + * Retrieve the Java component type if this is an ARRAY type, or + * null, otherwise. + */ + @Nullable + Class getArrayComponentType(); + + /** + * Retrieve the Java component data type if this is an ARRAY type, or + * null, otherwise. + */ + @Nullable + DataType getArrayComponentDataType(); + diff --git a/jOOQ/src/main/java/org/jooq/impl/ArrayDataType.java b/jOOQ/src/main/java/org/jooq/impl/ArrayDataType.java index 25d5a09a36..4d2d852f76 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ArrayDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/ArrayDataType.java @@ -123,6 +123,17 @@ final class ArrayDataType extends DefaultDataType { return getArrayType(configuration, castTypeName); } + @Override + public final Class getArrayComponentType() { + return elementType.getType(); + } + + @Override + public final DataType getArrayComponentDataType() { + return elementType; + } + + private static String getArrayType(Configuration configuration, String dataType) { switch (configuration.family()) { diff --git a/jOOQ/src/main/java/org/jooq/impl/ArrayGet.java b/jOOQ/src/main/java/org/jooq/impl/ArrayGet.java new file mode 100644 index 0000000000..024b5c9c41 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/ArrayGet.java @@ -0,0 +1,101 @@ +/* + * 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.DSL.cardinality; +import static org.jooq.impl.DSL.when; +import static org.jooq.impl.Names.N_ARRAY_GET; + +import org.jooq.Context; +import org.jooq.DataType; +import org.jooq.Field; + +/** + * @author Lukas Eder + */ +final class ArrayGet extends AbstractField { + + /** + * Generated UID + */ + private static final long serialVersionUID = 1852008882778358276L; + private final Field field; + private final Field index; + + @SuppressWarnings("unchecked") + ArrayGet(Field field, Field index) { + super(N_ARRAY_GET, (DataType) field.getDataType().getArrayComponentDataType()); + + this.field = field; + this.index = index; + } + + @Override + public final void accept(Context ctx) { + switch (ctx.family()) { + case H2: + ctx.visit(N_ARRAY_GET).sql('(').visit(field).sql(", ").visit(index).sql(')'); + break; + + case HSQLDB: + ctx.visit(when(cardinality(field).ge(index), new Standard())); + break; + + default: + ctx.visit(new Standard()); + break; + } + } + + private class Standard extends AbstractField { + + /** + * Generated UID + */ + private static final long serialVersionUID = 7727869539823288556L; + + Standard() { + super(ArrayGet.this.getQualifiedName(), ArrayGet.this.getDataType()); + } + + @Override + public void accept(Context ctx) { + ctx.visit(field).sql('[').visit(index).sql(']'); + } + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java index 3f27467bd7..3af92b2a91 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DSL.java +++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java @@ -21126,6 +21126,24 @@ public class DSL { return new Cardinality(field); } + /** + * Get an array element at a given index (1 based) + */ + @NotNull + @Support({ H2, HSQLDB, POSTGRES }) + public static Field arrayGet(Field field, int index) { + return arrayGet(field, Tools.field(index)); + } + + /** + * Get an array element at a given index (1 based) + */ + @NotNull + @Support({ H2, HSQLDB, POSTGRES }) + public static Field arrayGet(Field field, Field index) { + return new ArrayGet<>(field, index); + } + /** * Get the max value over a field: max(field). */ diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java b/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java index b8e09be33a..38d5f732e3 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java @@ -797,11 +797,6 @@ public class DefaultDataType extends AbstractNamed implements DataType { return binding.converter(); } - @Override - public final Class getArrayType() { - return arrayType; - } - @Override public final String getTypeName() { return typeName; @@ -835,11 +830,26 @@ public class DefaultDataType extends AbstractNamed implements DataType { return getDataType(configuration).getCastTypeName(); } + @Override + public final Class getArrayType() { + return arrayType; + } + @Override public final DataType getArrayDataType() { return new ArrayDataType<>(this); } + @Override + public /* non-final */ Class getArrayComponentType() { + return null; + } + + @Override + public /* non-final */ DataType getArrayComponentDataType() { + return null; + } + diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index f604b69a57..5f6145d973 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_GET = unquotedName("array_get"); static final Name N_ARRAY_LENGTH = unquotedName("array_length"); static final Name N_ASC = unquotedName("asc"); static final Name N_ASCII = unquotedName("ascii");