[jOOQ/jOOQ#10695] [jOOQ/jOOQ16179] Quantified comparison fixes

This includes:

- [jOOQ/jOOQ#10695] ANY clause does not generate correct SQL for
forced-type fields
- [jOOQ/jOOQ#16179] QuantifiedSelect wrapping array doesn't correctly
convert array component types
- [jOOQ/jOOQ#16439] Ignored test for quantified comparisons of array
types
This commit is contained in:
Lukas Eder 2024-03-13 10:29:15 +01:00
parent 3d36c257d1
commit c06dc86c42
11 changed files with 29 additions and 12 deletions

View File

@ -211,7 +211,7 @@ public interface DataType<T> extends Named {
* A convenient short for form {@link #getArrayDataType()} for DSL usage
*/
@NotNull
@Support({ DUCKDB, H2, HSQLDB, POSTGRES, TRINO, YUGABYTEDB })
@Support({ CLICKHOUSE, DUCKDB, H2, HSQLDB, POSTGRES, TRINO, YUGABYTEDB })
DataType<T[]> array() throws DataTypeException;
/**

View File

@ -81,7 +81,7 @@ implements
) {
this.arg1 = nullSafeNotNull(arg1, (DataType) OTHER);
this.arg2 = arg2;
this.arg2 = nullSafeQuantifiedSelect(arg2, arg1.getDataType());
}
// -------------------------------------------------------------------------

View File

@ -81,7 +81,7 @@ implements
) {
this.arg1 = nullSafeNotNull(arg1, (DataType) OTHER);
this.arg2 = arg2;
this.arg2 = nullSafeQuantifiedSelect(arg2, arg1.getDataType());
}
// -------------------------------------------------------------------------

View File

@ -81,7 +81,7 @@ implements
) {
this.arg1 = nullSafeNotNull(arg1, (DataType) OTHER);
this.arg2 = arg2;
this.arg2 = nullSafeQuantifiedSelect(arg2, arg1.getDataType());
}
// -------------------------------------------------------------------------

View File

@ -81,7 +81,7 @@ implements
) {
this.arg1 = nullSafeNotNull(arg1, (DataType) OTHER);
this.arg2 = arg2;
this.arg2 = nullSafeQuantifiedSelect(arg2, arg1.getDataType());
}
// -------------------------------------------------------------------------

View File

@ -153,6 +153,7 @@ final class LegacyConvertedDataType<T, U> extends DefaultDataType<U> {
static final boolean isInstance(DataType<?> t) {
return t instanceof LegacyConvertedDataType
|| t instanceof ArrayDataType && isInstance(((ArrayDataType<?>) t).getArrayComponentDataType())
|| t instanceof DataTypeProxy && isInstance(((DataTypeProxy<?>) t).type());
}
}

View File

@ -81,7 +81,7 @@ implements
) {
this.arg1 = nullSafeNotNull(arg1, (DataType) OTHER);
this.arg2 = arg2;
this.arg2 = nullSafeQuantifiedSelect(arg2, arg1.getDataType());
}
// -------------------------------------------------------------------------

View File

@ -81,7 +81,7 @@ implements
) {
this.arg1 = nullSafeNotNull(arg1, (DataType) OTHER);
this.arg2 = arg2;
this.arg2 = nullSafeQuantifiedSelect(arg2, arg1.getDataType());
}
// -------------------------------------------------------------------------

View File

@ -48,6 +48,7 @@ import static org.jooq.impl.Tools.visitSubquery;
import org.jooq.Configuration;
import org.jooq.Context;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.Function2;
import org.jooq.Param;
@ -154,13 +155,14 @@ implements
// use nested derived tables with UNION ALL
if (array instanceof Param) {
Object[] values0 = ((Param<? extends Object[]>) array).getValue();
DataType<Object> type = (DataType<Object>) array.getDataType().getArrayComponentDataType();
Select<Record1<Object>> select = null;
for (Object value : values0)
if (select == null)
select = select(val(value));
select = select(val(value, type));
else
select = select.unionAll(select(val(value)));
select = select.unionAll(select(val(value, type)));
return select;
}

View File

@ -7502,6 +7502,20 @@ final class Tools {
: convertVal(field, type);
}
@SuppressWarnings("unchecked")
static final <T, R extends Record1<T>> QuantifiedSelect<? extends Record1<T>> nullSafeQuantifiedSelect(QuantifiedSelect<? extends Record1<T>> s, DataType<?> type) {
if (s instanceof QuantifiedArray) {
QuantifiedArray<R> a = (QuantifiedArray<R>) s;
Field<R[]> a1 = a.array;
Field<R[]> a2 = convertVal(a1, type.array());
if (a1 != a2) {
return (QuantifiedArray) a.$array(a2);
}
}
return s;
}
/**
* In very rare cases, we want {@link #nullSafe(Field, DataType)} behaviour
* but only for <code>null</code> values.

View File

@ -170,14 +170,14 @@ final class Val<T> extends AbstractParam<T> implements UEmpty {
}
final <U> Val<U> convertTo0(DataType<U> type) {
Val<U> w = new Val<>(type.convert(getValue()), type, inferredDataType, getParamName());
Val<U> w = new Val<>(type.convert(getValue()), type, LegacyConvertedDataType.isInstance(type) || type.isOther(), getParamName());
w.setInline0(isInline());
return w;
}
@Override
public void accept(Context<?> ctx) {
// [#16090] [#16425] Inferred user types shouldn't rely on static type registry
if (inferredDataType)
DefaultDataType.check(getDataType());