[jOOQ/jOOQ#11485] Support for Trino DB
- Correct parser and interpreter name cases - Remove workarounds for https://github.com/trinodb/trino/issues/16489 - Emulate LISTAGG .. FILTER - Emulate INSERT INTO <aliased table> - Support TIMESTAMPTZ literals and binds - Correctly recognise ARRAY types in MetaTable - Add M_SOURCES query to MetaSQL
This commit is contained in:
parent
1c367c0511
commit
56e36a422d
@ -53,6 +53,7 @@ import java.util.List;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Record12;
|
||||
import org.jooq.Record4;
|
||||
import org.jooq.Record6;
|
||||
import org.jooq.ResultQuery;
|
||||
import org.jooq.SQLDialect;
|
||||
@ -65,6 +66,7 @@ import org.jooq.meta.DefaultRelations;
|
||||
import org.jooq.meta.DomainDefinition;
|
||||
import org.jooq.meta.EnumDefinition;
|
||||
import org.jooq.meta.PackageDefinition;
|
||||
import org.jooq.meta.ResultQueryDatabase;
|
||||
import org.jooq.meta.RoutineDefinition;
|
||||
import org.jooq.meta.SchemaDefinition;
|
||||
import org.jooq.meta.SequenceDefinition;
|
||||
@ -73,12 +75,14 @@ import org.jooq.meta.UDTDefinition;
|
||||
import org.jooq.meta.XMLSchemaCollectionDefinition;
|
||||
import org.jooq.meta.hsqldb.HSQLDBDatabase;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* The Trino database
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public class TrinoDatabase extends AbstractDatabase {
|
||||
public class TrinoDatabase extends AbstractDatabase implements ResultQueryDatabase {
|
||||
|
||||
@Override
|
||||
protected DSLContext create0() {
|
||||
@ -96,7 +100,7 @@ public class TrinoDatabase extends AbstractDatabase {
|
||||
when(TABLES.TABLE_TYPE.eq(inline("VIEW")), inline(TableType.VIEW.name()))
|
||||
.else_(inline(TableType.TABLE.name())).trim().as("table_type"),
|
||||
when(VIEWS.VIEW_DEFINITION.lower().like(inline("create%")), VIEWS.VIEW_DEFINITION)
|
||||
.else_(inline("create view \"").concat(TABLES.TABLE_NAME).concat("\" as ").concat(VIEWS.VIEW_DEFINITION)).as(VIEWS.VIEW_DEFINITION)
|
||||
.else_(inline("create view \"").concat(TABLES.TABLE_NAME).concat(inline("\" as ")).concat(VIEWS.VIEW_DEFINITION)).as(VIEWS.VIEW_DEFINITION)
|
||||
)
|
||||
.from(TABLES)
|
||||
.leftJoin(VIEWS)
|
||||
@ -135,6 +139,38 @@ public class TrinoDatabase extends AbstractDatabase {
|
||||
protected void loadCheckConstraints(DefaultRelations relations) throws SQLException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ResultQuery<Record6<String, String, String, String, String, Integer>> primaryKeys(List<String> schemas) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ResultQuery<Record6<String, String, String, String, String, Integer>> uniqueKeys(List<String> schemas) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ResultQuery<Record12<String, String, String, String, Integer, Integer, Long, Long, BigDecimal, BigDecimal, Boolean, Long>> sequences(List<String> schemas) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ResultQuery<Record4<String, String, String, String>> sources(List<String> schemas) {
|
||||
return create()
|
||||
.select(
|
||||
inline("").as(VIEWS.TABLE_CATALOG),
|
||||
VIEWS.TABLE_SCHEMA,
|
||||
VIEWS.TABLE_NAME,
|
||||
when(VIEWS.VIEW_DEFINITION.lower().like(inline("create%")), VIEWS.VIEW_DEFINITION)
|
||||
.else_(inline("create view \"").concat(VIEWS.TABLE_NAME).concat(inline("\" as ")).concat(VIEWS.VIEW_DEFINITION)).as(VIEWS.VIEW_DEFINITION)
|
||||
)
|
||||
.from(VIEWS)
|
||||
.where(VIEWS.TABLE_SCHEMA.in(schemas))
|
||||
.orderBy(
|
||||
VIEWS.TABLE_SCHEMA,
|
||||
VIEWS.TABLE_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<DomainDefinition> getDomains0() throws SQLException {
|
||||
return new ArrayList<>();
|
||||
|
||||
@ -343,7 +343,7 @@ implements
|
||||
}
|
||||
}
|
||||
|
||||
private final boolean supportsFilter(Context<?> ctx) {
|
||||
/* non-final */ boolean supportsFilter(Context<?> ctx) {
|
||||
return !(
|
||||
NO_SUPPORT_FILTER.contains(ctx.dialect())
|
||||
|| NO_SUPPORT_WINDOW_FILTER.contains(ctx.dialect()) && isWindow()
|
||||
|
||||
@ -181,7 +181,7 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractRowCountQuery
|
||||
|
||||
private static final JooqLogger log = JooqLogger.getLogger(AbstractQuery.class);
|
||||
|
||||
private static final Set<SQLDialect> NO_SUPPORT_INSERT_ALIASED_TABLE = SQLDialect.supportedBy(DERBY, FIREBIRD, H2, MARIADB, MYSQL);
|
||||
private static final Set<SQLDialect> NO_SUPPORT_INSERT_ALIASED_TABLE = SQLDialect.supportedBy(DERBY, FIREBIRD, H2, MARIADB, MYSQL, TRINO);
|
||||
private static final Set<SQLDialect> NO_NATIVE_SUPPORT_INSERT_RETURNING = SQLDialect.supportedUntil(CUBRID, DERBY, H2, HSQLDB, IGNITE, MYSQL, SQLITE, TRINO);
|
||||
private static final Set<SQLDialect> NO_NATIVE_SUPPORT_UPDATE_RETURNING = SQLDialect.supportedUntil(CUBRID, DERBY, H2, HSQLDB, IGNITE, MYSQL, SQLITE, TRINO);
|
||||
private static final Set<SQLDialect> NO_NATIVE_SUPPORT_DELETE_RETURNING = SQLDialect.supportedUntil(CUBRID, DERBY, H2, HSQLDB, IGNITE, MYSQL, SQLITE, TRINO);
|
||||
|
||||
@ -823,6 +823,16 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
if (dataType.getType() == OffsetDateTime.class ||
|
||||
dataType.getType() == OffsetTime.class ||
|
||||
dataType.getType() == Instant.class
|
||||
) {
|
||||
switch (ctx.family()) {
|
||||
case TRINO:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -3320,6 +3330,7 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
|
||||
|
||||
case HSQLDB:
|
||||
case TRINO:
|
||||
ctx.render().visit(K_TIMESTAMP).sql(" '").sql(escape(format(value, family), ctx.render())).sql('\'');
|
||||
break;
|
||||
|
||||
|
||||
@ -48,6 +48,7 @@ import static org.jooq.SQLDialect.MARIADB;
|
||||
import static org.jooq.SQLDialect.MYSQL;
|
||||
import static org.jooq.SQLDialect.POSTGRES;
|
||||
import static org.jooq.SQLDialect.SQLITE;
|
||||
import static org.jooq.SQLDialect.TRINO;
|
||||
import static org.jooq.SQLDialect.YUGABYTEDB;
|
||||
import static org.jooq.impl.CommentImpl.NO_COMMENT;
|
||||
import static org.jooq.impl.DSL.systemName;
|
||||
@ -141,6 +142,7 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
|
||||
private static final Set<SQLDialect> NO_SUPPORT_TIMESTAMP_PRECISION = SQLDialect.supportedBy(FIREBIRD, MYSQL, SQLITE);
|
||||
private static final Set<SQLDialect> SUPPORT_POSTGRES_ARRAY_NOTATION = SQLDialect.supportedBy(POSTGRES, YUGABYTEDB);
|
||||
private static final Set<SQLDialect> SUPPORT_HSQLDB_ARRAY_NOTATION = SQLDialect.supportedBy(H2, HSQLDB);
|
||||
private static final Set<SQLDialect> SUPPORT_TRINO_ARRAY_NOTATION = SQLDialect.supportedBy(TRINO);
|
||||
|
||||
/**
|
||||
* A pattern for data type name normalisation.
|
||||
@ -692,6 +694,10 @@ public class DefaultDataType<T> extends AbstractDataTypeX<T> {
|
||||
else if (result == null && SUPPORT_HSQLDB_ARRAY_NOTATION.contains(dialect) && upper.equals("ARRAY"))
|
||||
result = SQLDataType.OTHER.getArrayDataType();
|
||||
|
||||
// [#11485] Trino lists arrays as array(component_type)
|
||||
else if (result == null && SUPPORT_TRINO_ARRAY_NOTATION.contains(dialect) && upper.startsWith("ARRAY("))
|
||||
result = getDataType(dialect, typeName.substring(6, typeName.length() - 1)).getArrayDataType();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1422,6 +1422,7 @@ final class Interpreter {
|
||||
case MARIADB:
|
||||
case MYSQL:
|
||||
case SQLITE:
|
||||
case TRINO:
|
||||
return InterpreterNameLookupCaseSensitivity.NEVER;
|
||||
|
||||
case DEFAULT:
|
||||
|
||||
@ -298,12 +298,6 @@ final class JSONEntryImpl<T> extends AbstractQueryPart implements JSONEntry<T>,
|
||||
|
||||
case TRINO:
|
||||
|
||||
// [#11485] https://github.com/trinodb/trino/issues/16489
|
||||
// This isn't necessary when emulating JSON_OBJECT and JSON_ARRAY
|
||||
// with CAST(MAP) and CAST(ARRAY), however:
|
||||
// if (field instanceof Param)
|
||||
// return inlined(field);
|
||||
|
||||
// [#11485] CHAR types can't be cast to JSON: https://trino.io/docs/current/functions/json.html#cast-to-json
|
||||
if (type.getSQLDataType() == SQLDataType.CHAR)
|
||||
return field.cast(VARCHAR);
|
||||
|
||||
@ -180,6 +180,16 @@ final class ListAgg extends AbstractAggregateFunction<String> implements UNotYet
|
||||
return i == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean supportsFilter(Context<?> ctx) {
|
||||
switch (ctx.family()) {
|
||||
case TRINO:
|
||||
return false;
|
||||
default:
|
||||
return super.supportsFilter(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [#1273] <code>LIST_AGG</code> emulation for MySQL
|
||||
*/
|
||||
|
||||
@ -103,6 +103,7 @@ final class MetaSQL {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
M_SEQUENCES.put(DERBY, "select cast(null as varchar(32672)) as catalog, alias_8805161.SCHEMANAME, SYS.SYSSEQUENCES.SEQUENCENAME, SYS.SYSSEQUENCES.SEQUENCEDATATYPE, cast(null as int) as numeric_precision, cast(null as int) as numeric_scale, nullif(SYS.SYSSEQUENCES.STARTVALUE, 1) as STARTVALUE, nullif(SYS.SYSSEQUENCES.INCREMENT, 1) as INCREMENT, nullif(SYS.SYSSEQUENCES.MINIMUMVALUE, case when cast(SYS.SYSSEQUENCES.SEQUENCEDATATYPE as varchar(32672)) = 'SMALLINT' then -32768 when cast(SYS.SYSSEQUENCES.SEQUENCEDATATYPE as varchar(32672)) = 'INTEGER' then -2147483648 when cast(SYS.SYSSEQUENCES.SEQUENCEDATATYPE as varchar(32672)) = 'BIGINT' then -9223372036854775808 end) as MINIMUMVALUE, nullif(SYS.SYSSEQUENCES.MAXIMUMVALUE, case when cast(SYS.SYSSEQUENCES.SEQUENCEDATATYPE as varchar(32672)) = 'SMALLINT' then 32767 when cast(SYS.SYSSEQUENCES.SEQUENCEDATATYPE as varchar(32672)) = 'INTEGER' then 2147483647 when cast(SYS.SYSSEQUENCES.SEQUENCEDATATYPE as varchar(32672)) = 'BIGINT' then 9223372036854775807 end) as MAXIMUMVALUE, (SYS.SYSSEQUENCES.CYCLEOPTION = 'Y') as CYCLEOPTION, cast(null as bigint) as cache from (SYS.SYSSEQUENCES join SYS.SYSSCHEMAS as alias_8805161 on SYS.SYSSEQUENCES.SCHEMAID = alias_8805161.SCHEMAID) where cast(alias_8805161.SCHEMANAME as varchar(32672)) in (cast(? as varchar(32672))) order by alias_8805161.SCHEMANAME, SYS.SYSSEQUENCES.SEQUENCENAME");
|
||||
@ -153,6 +154,7 @@ final class MetaSQL {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
M_SEQUENCES_INCLUDING_SYSTEM_SEQUENCES.put(DERBY, "select cast(null as varchar(32672)) as catalog, alias_8805161.SCHEMANAME, SYS.SYSSEQUENCES.SEQUENCENAME, SYS.SYSSEQUENCES.SEQUENCEDATATYPE, cast(null as int) as numeric_precision, cast(null as int) as numeric_scale, nullif(SYS.SYSSEQUENCES.STARTVALUE, 1) as STARTVALUE, nullif(SYS.SYSSEQUENCES.INCREMENT, 1) as INCREMENT, nullif(SYS.SYSSEQUENCES.MINIMUMVALUE, case when cast(SYS.SYSSEQUENCES.SEQUENCEDATATYPE as varchar(32672)) = 'SMALLINT' then -32768 when cast(SYS.SYSSEQUENCES.SEQUENCEDATATYPE as varchar(32672)) = 'INTEGER' then -2147483648 when cast(SYS.SYSSEQUENCES.SEQUENCEDATATYPE as varchar(32672)) = 'BIGINT' then -9223372036854775808 end) as MINIMUMVALUE, nullif(SYS.SYSSEQUENCES.MAXIMUMVALUE, case when cast(SYS.SYSSEQUENCES.SEQUENCEDATATYPE as varchar(32672)) = 'SMALLINT' then 32767 when cast(SYS.SYSSEQUENCES.SEQUENCEDATATYPE as varchar(32672)) = 'INTEGER' then 2147483647 when cast(SYS.SYSSEQUENCES.SEQUENCEDATATYPE as varchar(32672)) = 'BIGINT' then 9223372036854775807 end) as MAXIMUMVALUE, (SYS.SYSSEQUENCES.CYCLEOPTION = 'Y') as CYCLEOPTION, cast(null as bigint) as cache from (SYS.SYSSEQUENCES join SYS.SYSSCHEMAS as alias_8805161 on SYS.SYSSEQUENCES.SCHEMAID = alias_8805161.SCHEMAID) where cast(alias_8805161.SCHEMANAME as varchar(32672)) in (cast(? as varchar(32672))) order by alias_8805161.SCHEMANAME, SYS.SYSSEQUENCES.SEQUENCENAME");
|
||||
@ -203,6 +205,7 @@ final class MetaSQL {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
M_SOURCES.put(DERBY, "select cast(null as varchar(32672)) as catalog, alias_57844683.SCHEMANAME, SYS.SYSTABLES.TABLENAME, SYS.SYSVIEWS.VIEWDEFINITION from (SYS.SYSTABLES join SYS.SYSSCHEMAS as alias_57844683 on SYS.SYSTABLES.SCHEMAID = alias_57844683.SCHEMAID) left outer join SYS.SYSVIEWS on SYS.SYSTABLES.TABLEID = SYS.SYSVIEWS.TABLEID where cast(alias_57844683.SCHEMANAME as varchar(32672)) in (cast(? as varchar(32672))) order by alias_57844683.SCHEMANAME, SYS.SYSTABLES.TABLENAME");
|
||||
@ -213,6 +216,7 @@ final class MetaSQL {
|
||||
M_SOURCES.put(MYSQL, "select information_schema.VIEWS.TABLE_CATALOG, information_schema.VIEWS.TABLE_SCHEMA, information_schema.VIEWS.TABLE_NAME, information_schema.VIEWS.VIEW_DEFINITION from information_schema.VIEWS where information_schema.VIEWS.TABLE_SCHEMA in (?) order by information_schema.VIEWS.TABLE_SCHEMA, information_schema.VIEWS.TABLE_NAME");
|
||||
M_SOURCES.put(POSTGRES, "select information_schema.views.table_catalog, information_schema.views.table_schema, information_schema.views.table_name, information_schema.views.view_definition from information_schema.views where information_schema.views.table_schema in (?) order by information_schema.views.table_schema, information_schema.views.table_name");
|
||||
M_SOURCES.put(SQLITE, "select null as catalog, null as schema, sqlite_master.name, sqlite_master.sql from sqlite_master order by sqlite_master.name");
|
||||
M_SOURCES.put(TRINO, "select '' TABLE_CATALOG, INFORMATION_SCHEMA.VIEWS.TABLE_SCHEMA, INFORMATION_SCHEMA.VIEWS.TABLE_NAME, case when lower(INFORMATION_SCHEMA.VIEWS.VIEW_DEFINITION) like 'create%' then INFORMATION_SCHEMA.VIEWS.VIEW_DEFINITION else ((('create view \"' || INFORMATION_SCHEMA.VIEWS.TABLE_NAME) || '\" as ') || INFORMATION_SCHEMA.VIEWS.VIEW_DEFINITION) end VIEW_DEFINITION from INFORMATION_SCHEMA.VIEWS where INFORMATION_SCHEMA.VIEWS.TABLE_SCHEMA in (?) order by INFORMATION_SCHEMA.VIEWS.TABLE_SCHEMA, INFORMATION_SCHEMA.VIEWS.TABLE_NAME");
|
||||
M_SOURCES.put(YUGABYTEDB, "select information_schema.views.table_catalog, information_schema.views.table_schema, information_schema.views.table_name, information_schema.views.view_definition from information_schema.views where information_schema.views.table_schema in (?) order by information_schema.views.table_schema, information_schema.views.table_name");
|
||||
|
||||
|
||||
@ -283,6 +287,7 @@ final class MetaSQL {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -6896,6 +6896,7 @@ final class Tools {
|
||||
case MARIADB:
|
||||
case MYSQL:
|
||||
case SQLITE:
|
||||
case TRINO:
|
||||
return ParseNameCase.AS_IS;
|
||||
|
||||
default:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user