[jOOQ/jOOQ#7539] More ClickHouse support

This includes:

- Relational division
- JSON_ARRAYAGG()
- Nested JSON (requires allow_experimental_object_type = 1)
This commit is contained in:
Lukas Eder 2024-04-04 19:49:06 +02:00
parent 0e4a9be380
commit 2e6e83afaa
8 changed files with 63 additions and 36 deletions

View File

@ -41,6 +41,7 @@ package org.jooq;
// ...
// ...
// ...
import static org.jooq.SQLDialect.CLICKHOUSE;
// ...
import static org.jooq.SQLDialect.CUBRID;
// ...
@ -100,7 +101,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* {@link Operator#AND} operator.
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep and(Condition condition);
/**
@ -108,7 +109,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* {@link Operator#AND} operator.
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep and(Field<Boolean> condition);
/**
@ -124,7 +125,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* @see SQL
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@PlainSQL
DivideByOnConditionStep and(SQL sql);
@ -141,7 +142,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* @see SQL
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@PlainSQL
DivideByOnConditionStep and(String sql);
@ -159,7 +160,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* @see SQL
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@PlainSQL
DivideByOnConditionStep and(String sql, Object... bindings);
@ -177,7 +178,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* @see SQL
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@PlainSQL
DivideByOnConditionStep and(String sql, QueryPart... parts);
@ -186,7 +187,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* the {@link Operator#AND} operator.
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep andNot(Condition condition);
/**
@ -194,7 +195,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* the {@link Operator#AND} operator.
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep andNot(Field<Boolean> condition);
/**
@ -202,7 +203,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* clause using the {@link Operator#AND} operator.
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep andExists(Select<?> select);
/**
@ -210,7 +211,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* clause using the {@link Operator#AND} operator.
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep andNotExists(Select<?> select);
/**
@ -218,7 +219,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* {@link Operator#OR} operator.
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep or(Condition condition);
/**
@ -226,7 +227,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* {@link Operator#OR} operator.
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep or(Field<Boolean> condition);
/**
@ -242,7 +243,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* @see SQL
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@PlainSQL
DivideByOnConditionStep or(SQL sql);
@ -259,7 +260,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* @see SQL
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@PlainSQL
DivideByOnConditionStep or(String sql);
@ -277,7 +278,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* @see SQL
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@PlainSQL
DivideByOnConditionStep or(String sql, Object... bindings);
@ -295,7 +296,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* @see SQL
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@PlainSQL
DivideByOnConditionStep or(String sql, QueryPart... parts);
@ -304,7 +305,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* the {@link Operator#OR} operator.
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep orNot(Condition condition);
/**
@ -312,7 +313,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* the {@link Operator#OR} operator.
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep orNot(Field<Boolean> condition);
/**
@ -320,7 +321,7 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* clause using the {@link Operator#OR} operator.
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep orExists(Select<?> select);
/**
@ -328,6 +329,6 @@ public interface DivideByOnConditionStep extends DivideByReturningStep {
* clause using the {@link Operator#OR} operator.
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep orNotExists(Select<?> select);
}

View File

@ -41,6 +41,7 @@ package org.jooq;
// ...
// ...
// ...
import static org.jooq.SQLDialect.CLICKHOUSE;
// ...
import static org.jooq.SQLDialect.CUBRID;
// ...
@ -100,7 +101,7 @@ public interface DivideByOnStep {
* them with each other with {@link Operator#AND}.
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep on(Condition condition);
/**
@ -108,14 +109,14 @@ public interface DivideByOnStep {
* them with each other with {@link Operator#AND}.
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep on(Condition... conditions);
/**
* Add a division condition to the <code>DIVIDE BY</code> clause
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnConditionStep on(Field<Boolean> condition);
/**
@ -130,7 +131,7 @@ public interface DivideByOnStep {
* @see SQL
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@PlainSQL
DivideByOnConditionStep on(SQL sql);
@ -146,7 +147,7 @@ public interface DivideByOnStep {
* @see SQL
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@PlainSQL
DivideByOnConditionStep on(String sql);
@ -163,7 +164,7 @@ public interface DivideByOnStep {
* @see SQL
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@PlainSQL
DivideByOnConditionStep on(String sql, Object... bindings);
@ -180,7 +181,7 @@ public interface DivideByOnStep {
* @see SQL
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@PlainSQL
DivideByOnConditionStep on(String sql, QueryPart... parts);
}

View File

@ -41,6 +41,7 @@ package org.jooq;
// ...
// ...
// ...
import static org.jooq.SQLDialect.CLICKHOUSE;
// ...
import static org.jooq.SQLDialect.CUBRID;
// ...
@ -98,13 +99,13 @@ public interface DivideByReturningStep {
* Specify the fields that you want the division to return from the dividend
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
Table<Record> returning(Field<?>... fields);
/**
* Specify the fields that you want the division to return from the dividend
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
Table<Record> returning(Collection<? extends Field<?>> fields);
}

View File

@ -3745,7 +3745,7 @@ extends
* This has been observed to work with all dialects
*/
@NotNull
@Support({ CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
@Support({ CLICKHOUSE, CUBRID, DERBY, DUCKDB, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE })
DivideByOnStep divideBy(Table<?> divisor);
/**

View File

@ -624,7 +624,7 @@ implements
private final String getCastTypeName0(Configuration configuration) {
switch (configuration.family()) {
case CLICKHOUSE:
if (nullable())
if (nullable() && !isJSON() && !isArray())
return "Nullable(" + getCastTypeName1(configuration) + ")";
else
return getCastTypeName1(configuration);

View File

@ -29534,7 +29534,7 @@ public class DSL {
* The JSON array aggregate function.
*/
@NotNull
@Support({ H2, MARIADB, MYSQL, POSTGRES, SQLITE, TRINO, YUGABYTEDB })
@Support({ CLICKHOUSE, H2, MARIADB, MYSQL, POSTGRES, SQLITE, TRINO, YUGABYTEDB })
public static JSONArrayAggOrderByStep<JSON> jsonArrayAgg(Field<?> value) {
return new JSONArrayAgg<>(JSON, value, false);
}
@ -29543,7 +29543,7 @@ public class DSL {
* The JSON array aggregate function.
*/
@NotNull
@Support({ H2, MARIADB, MYSQL, POSTGRES, SQLITE, TRINO, YUGABYTEDB })
@Support({ CLICKHOUSE, H2, MARIADB, MYSQL, POSTGRES, SQLITE, TRINO, YUGABYTEDB })
public static JSONArrayAggOrderByStep<JSONB> jsonbArrayAgg(Field<?> value) {
return new JSONArrayAgg<>(JSONB, value, false);
}
@ -29552,7 +29552,7 @@ public class DSL {
* The JSON array aggregate function.
*/
@NotNull
@Support({ H2, MARIADB, MYSQL, SQLITE, TRINO })
@Support({ CLICKHOUSE, H2, MARIADB, MYSQL, SQLITE, TRINO })
public static JSONArrayAggOrderByStep<JSON> jsonArrayAggDistinct(Field<?> value) {
return new JSONArrayAgg<>(JSON, value, true);
}
@ -29561,7 +29561,7 @@ public class DSL {
* The JSON array aggregate function.
*/
@NotNull
@Support({ H2, MARIADB, MYSQL, POSTGRES, SQLITE, TRINO, YUGABYTEDB })
@Support({ CLICKHOUSE, H2, MARIADB, MYSQL, POSTGRES, SQLITE, TRINO, YUGABYTEDB })
public static JSONArrayAggOrderByStep<JSONB> jsonbArrayAggDistinct(Field<?> value) {
return new JSONArrayAgg<>(JSONB, value, true);
}

View File

@ -43,11 +43,13 @@ import static org.jooq.SQLDialect.MYSQL;
// ...
// ...
// ...
// ...
import static org.jooq.impl.DSL.arrayAgg;
import static org.jooq.impl.DSL.arrayAggDistinct;
import static org.jooq.impl.DSL.function;
import static org.jooq.impl.DSL.groupConcat;
import static org.jooq.impl.DSL.groupConcatDistinct;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.orderBy;
import static org.jooq.impl.JSONEntryImpl.jsonCast;
import static org.jooq.impl.JSONEntryImpl.jsonCastMapper;
import static org.jooq.impl.JSONEntryImpl.jsonMerge;
@ -63,6 +65,7 @@ import static org.jooq.impl.Names.N_JSON_AGG;
import static org.jooq.impl.Names.N_JSON_ARRAYAGG;
import static org.jooq.impl.Names.N_JSON_GROUP_ARRAY;
import static org.jooq.impl.Names.N_JSON_QUOTE;
import static org.jooq.impl.Names.N_toJSONString;
import static org.jooq.impl.QOM.JSONOnNull.ABSENT_ON_NULL;
import static org.jooq.impl.QOM.JSONOnNull.NULL_ON_NULL;
import static org.jooq.impl.SQLDataType.BLOB;
@ -70,6 +73,7 @@ import static org.jooq.impl.SQLDataType.INTEGER;
import static org.jooq.impl.SQLDataType.JSON;
import static org.jooq.impl.SQLDataType.JSONB;
import static org.jooq.impl.SQLDataType.VARCHAR;
import static org.jooq.impl.Tools.apply;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_FORCE_CASE_ELSE_NULL;
import java.util.Collection;
@ -174,6 +178,17 @@ implements
acceptOverClause(ctx);
break;
case CLICKHOUSE:
ctx.visit(N_toJSONString).sql('(').visit(
apply(
arrayAggEmulation(distinct, arguments.get(0), withinGroupOrderBy),
a -> arguments.get(0).getDataType().isJSON()
? a.cast(JSON.array())
: a
)
).sql(')');
break;
case SQLITE:
ctx.visit(N_JSON_GROUP_ARRAY).sql('(');
acceptDistinct(ctx);
@ -278,6 +293,13 @@ implements
);
}
static final Field<?> arrayAggEmulation(boolean distinct, Field<?> field, SortFieldList orderBy) {
return Tools.apply(
distinct ? arrayAggDistinct(field) : arrayAgg(field),
agg -> Tools.isEmpty(orderBy) ? agg : agg.orderBy(orderBy)
);
}

View File

@ -241,6 +241,8 @@ final class JSONEntryImpl<T> extends AbstractQueryPart implements JSONEntry<T>,
case CLICKHOUSE:
if (isType(type, Boolean.class))
return field.cast(BOOLEAN);
else if (isJSON(ctx, type))
return field.cast(JSON);
break;