diff --git a/presto-base-jdbc/src/main/java/io/prestosql/plugin/jdbc/BaseJdbcClient.java b/presto-base-jdbc/src/main/java/io/prestosql/plugin/jdbc/BaseJdbcClient.java index 501680dadb23..5cb7f355052c 100644 --- a/presto-base-jdbc/src/main/java/io/prestosql/plugin/jdbc/BaseJdbcClient.java +++ b/presto-base-jdbc/src/main/java/io/prestosql/plugin/jdbc/BaseJdbcClient.java @@ -275,7 +275,7 @@ public List getColumns(ConnectorSession session, JdbcTableHand resultSet.getInt("DATA_TYPE"), Optional.ofNullable(resultSet.getString("TYPE_NAME")), resultSet.getInt("COLUMN_SIZE"), - resultSet.getInt("DECIMAL_DIGITS"), + getInteger(resultSet, "DECIMAL_DIGITS"), Optional.empty(), Optional.empty()); Optional columnMapping = toPrestoType(session, connection, typeHandle); @@ -315,6 +315,16 @@ public List getColumns(ConnectorSession session, JdbcTableHand } } + protected static Optional getInteger(ResultSet resultSet, String columnLabel) + throws SQLException + { + int value = resultSet.getInt(columnLabel); + if (resultSet.wasNull()) { + return Optional.empty(); + } + return Optional.of(value); + } + protected ResultSet getColumns(JdbcTableHandle tableHandle, DatabaseMetaData metadata) throws SQLException { diff --git a/presto-base-jdbc/src/main/java/io/prestosql/plugin/jdbc/JdbcTypeHandle.java b/presto-base-jdbc/src/main/java/io/prestosql/plugin/jdbc/JdbcTypeHandle.java index 668e34168b4f..ee1a02562ab5 100644 --- a/presto-base-jdbc/src/main/java/io/prestosql/plugin/jdbc/JdbcTypeHandle.java +++ b/presto-base-jdbc/src/main/java/io/prestosql/plugin/jdbc/JdbcTypeHandle.java @@ -27,7 +27,7 @@ public final class JdbcTypeHandle private final int jdbcType; private final Optional jdbcTypeName; private final int columnSize; - private final int decimalDigits; + private final Optional decimalDigits; private final Optional arrayDimensions; private final Optional caseSensitivity; @@ -37,7 +37,7 @@ public JdbcTypeHandle(int jdbcType, Optional jdbcTypeName, int columnSiz this(jdbcType, jdbcTypeName, columnSize, decimalDigits, arrayDimensions, Optional.empty()); } - @JsonCreator + @Deprecated public JdbcTypeHandle( @JsonProperty("jdbcType") int jdbcType, @JsonProperty("jdbcTypeName") Optional jdbcTypeName, @@ -45,11 +45,23 @@ public JdbcTypeHandle( @JsonProperty("decimalDigits") int decimalDigits, @JsonProperty("arrayDimensions") Optional arrayDimensions, @JsonProperty("caseSensitivity") Optional caseSensitivity) + { + this(jdbcType, jdbcTypeName, columnSize, Optional.of(decimalDigits), arrayDimensions, caseSensitivity); + } + + @JsonCreator + public JdbcTypeHandle( + @JsonProperty("jdbcType") int jdbcType, + @JsonProperty("jdbcTypeName") Optional jdbcTypeName, + @JsonProperty("columnSize") int columnSize, + @JsonProperty("decimalDigits") Optional decimalDigits, + @JsonProperty("arrayDimensions") Optional arrayDimensions, + @JsonProperty("caseSensitivity") Optional caseSensitivity) { this.jdbcType = jdbcType; this.jdbcTypeName = requireNonNull(jdbcTypeName, "jdbcTypeName is null"); this.columnSize = columnSize; - this.decimalDigits = decimalDigits; + this.decimalDigits = requireNonNull(decimalDigits, "decimalDigits is null"); this.arrayDimensions = requireNonNull(arrayDimensions, "arrayDimensions is null"); this.caseSensitivity = requireNonNull(caseSensitivity, "caseSensitivity is null"); } @@ -73,7 +85,7 @@ public int getColumnSize() } @JsonProperty - public int getDecimalDigits() + public Optional getDecimalDigits() { return decimalDigits; } diff --git a/presto-base-jdbc/src/main/java/io/prestosql/plugin/jdbc/StandardColumnMappings.java b/presto-base-jdbc/src/main/java/io/prestosql/plugin/jdbc/StandardColumnMappings.java index 2c6a97681443..b5801a799a1d 100644 --- a/presto-base-jdbc/src/main/java/io/prestosql/plugin/jdbc/StandardColumnMappings.java +++ b/presto-base-jdbc/src/main/java/io/prestosql/plugin/jdbc/StandardColumnMappings.java @@ -494,7 +494,7 @@ public static Optional jdbcTypeToPrestoType(JdbcTypeHandle type) case Types.NUMERIC: case Types.DECIMAL: - int decimalDigits = type.getDecimalDigits(); + int decimalDigits = type.getDecimalDigits().orElseThrow(() -> new IllegalStateException("decimal digits not present")); int precision = columnSize + max(-decimalDigits, 0); // Map decimal(p, -s) (negative scale) to decimal(p+s, 0). if (precision > Decimals.MAX_PRECISION) { return Optional.empty(); diff --git a/presto-base-jdbc/src/test/java/io/prestosql/plugin/jdbc/TestingH2JdbcClient.java b/presto-base-jdbc/src/test/java/io/prestosql/plugin/jdbc/TestingH2JdbcClient.java index ae07ab02195d..5bac16535b1e 100644 --- a/presto-base-jdbc/src/test/java/io/prestosql/plugin/jdbc/TestingH2JdbcClient.java +++ b/presto-base-jdbc/src/test/java/io/prestosql/plugin/jdbc/TestingH2JdbcClient.java @@ -27,7 +27,7 @@ class TestingH2JdbcClient extends BaseJdbcClient { - private static final JdbcTypeHandle BIGINT_TYPE_HANDLE = new JdbcTypeHandle(Types.BIGINT, Optional.empty(), -1, -1, Optional.empty(), Optional.empty()); + private static final JdbcTypeHandle BIGINT_TYPE_HANDLE = new JdbcTypeHandle(Types.BIGINT, Optional.empty(), -1, Optional.empty(), Optional.empty(), Optional.empty()); public TestingH2JdbcClient(BaseJdbcConfig config, ConnectionFactory connectionFactory) { diff --git a/presto-base-jdbc/src/test/java/io/prestosql/plugin/jdbc/TestingJdbcTypeHandle.java b/presto-base-jdbc/src/test/java/io/prestosql/plugin/jdbc/TestingJdbcTypeHandle.java index f0f7f747bb87..b6997ba7c4dd 100644 --- a/presto-base-jdbc/src/test/java/io/prestosql/plugin/jdbc/TestingJdbcTypeHandle.java +++ b/presto-base-jdbc/src/test/java/io/prestosql/plugin/jdbc/TestingJdbcTypeHandle.java @@ -20,20 +20,20 @@ public final class TestingJdbcTypeHandle { private TestingJdbcTypeHandle() {} - public static final JdbcTypeHandle JDBC_BOOLEAN = new JdbcTypeHandle(Types.BOOLEAN, Optional.of("boolean"), 1, 0, Optional.empty(), Optional.empty()); + public static final JdbcTypeHandle JDBC_BOOLEAN = new JdbcTypeHandle(Types.BOOLEAN, Optional.of("boolean"), 1, Optional.empty(), Optional.empty(), Optional.empty()); - public static final JdbcTypeHandle JDBC_SMALLINT = new JdbcTypeHandle(Types.SMALLINT, Optional.of("smallint"), 1, 0, Optional.empty(), Optional.empty()); - public static final JdbcTypeHandle JDBC_TINYINT = new JdbcTypeHandle(Types.TINYINT, Optional.of("tinyint"), 2, 0, Optional.empty(), Optional.empty()); - public static final JdbcTypeHandle JDBC_INTEGER = new JdbcTypeHandle(Types.INTEGER, Optional.of("integer"), 4, 0, Optional.empty(), Optional.empty()); - public static final JdbcTypeHandle JDBC_BIGINT = new JdbcTypeHandle(Types.BIGINT, Optional.of("bigint"), 8, 0, Optional.empty(), Optional.empty()); + public static final JdbcTypeHandle JDBC_SMALLINT = new JdbcTypeHandle(Types.SMALLINT, Optional.of("smallint"), 1, Optional.empty(), Optional.empty(), Optional.empty()); + public static final JdbcTypeHandle JDBC_TINYINT = new JdbcTypeHandle(Types.TINYINT, Optional.of("tinyint"), 2, Optional.empty(), Optional.empty(), Optional.empty()); + public static final JdbcTypeHandle JDBC_INTEGER = new JdbcTypeHandle(Types.INTEGER, Optional.of("integer"), 4, Optional.empty(), Optional.empty(), Optional.empty()); + public static final JdbcTypeHandle JDBC_BIGINT = new JdbcTypeHandle(Types.BIGINT, Optional.of("bigint"), 8, Optional.empty(), Optional.empty(), Optional.empty()); - public static final JdbcTypeHandle JDBC_REAL = new JdbcTypeHandle(Types.REAL, Optional.of("real"), 8, 0, Optional.empty(), Optional.empty()); - public static final JdbcTypeHandle JDBC_DOUBLE = new JdbcTypeHandle(Types.DOUBLE, Optional.of("double precision"), 8, 0, Optional.empty(), Optional.empty()); + public static final JdbcTypeHandle JDBC_REAL = new JdbcTypeHandle(Types.REAL, Optional.of("real"), 8, Optional.empty(), Optional.empty(), Optional.empty()); + public static final JdbcTypeHandle JDBC_DOUBLE = new JdbcTypeHandle(Types.DOUBLE, Optional.of("double precision"), 8, Optional.empty(), Optional.empty(), Optional.empty()); - public static final JdbcTypeHandle JDBC_CHAR = new JdbcTypeHandle(Types.CHAR, Optional.of("char"), 10, 0, Optional.empty(), Optional.empty()); - public static final JdbcTypeHandle JDBC_VARCHAR = new JdbcTypeHandle(Types.VARCHAR, Optional.of("varchar"), 10, 0, Optional.empty(), Optional.empty()); + public static final JdbcTypeHandle JDBC_CHAR = new JdbcTypeHandle(Types.CHAR, Optional.of("char"), 10, Optional.empty(), Optional.empty(), Optional.empty()); + public static final JdbcTypeHandle JDBC_VARCHAR = new JdbcTypeHandle(Types.VARCHAR, Optional.of("varchar"), 10, Optional.empty(), Optional.empty(), Optional.empty()); - public static final JdbcTypeHandle JDBC_DATE = new JdbcTypeHandle(Types.DATE, Optional.of("date"), 8, 0, Optional.empty(), Optional.empty()); - public static final JdbcTypeHandle JDBC_TIME = new JdbcTypeHandle(Types.TIME, Optional.of("time"), 4, 0, Optional.empty(), Optional.empty()); - public static final JdbcTypeHandle JDBC_TIMESTAMP = new JdbcTypeHandle(Types.TIMESTAMP, Optional.of("timestamp"), 8, 0, Optional.empty(), Optional.empty()); + public static final JdbcTypeHandle JDBC_DATE = new JdbcTypeHandle(Types.DATE, Optional.of("date"), 8, Optional.empty(), Optional.empty(), Optional.empty()); + public static final JdbcTypeHandle JDBC_TIME = new JdbcTypeHandle(Types.TIME, Optional.of("time"), 4, Optional.empty(), Optional.empty(), Optional.empty()); + public static final JdbcTypeHandle JDBC_TIMESTAMP = new JdbcTypeHandle(Types.TIMESTAMP, Optional.of("timestamp"), 8, Optional.empty(), Optional.empty(), Optional.empty()); } diff --git a/presto-mysql/src/main/java/io/prestosql/plugin/mysql/ImplementAvgBigint.java b/presto-mysql/src/main/java/io/prestosql/plugin/mysql/ImplementAvgBigint.java index 29ced9fe0b49..6ef88593f2bc 100644 --- a/presto-mysql/src/main/java/io/prestosql/plugin/mysql/ImplementAvgBigint.java +++ b/presto-mysql/src/main/java/io/prestosql/plugin/mysql/ImplementAvgBigint.java @@ -64,6 +64,6 @@ public Optional rewrite(AggregateFunction aggregateFunction, Cap return Optional.of(new JdbcExpression( format("avg((%s * 1.0))", columnHandle.toSqlExpression(context.getIdentifierQuote())), - new JdbcTypeHandle(Types.DOUBLE, Optional.of("double"), 0, 0, Optional.empty(), Optional.empty()))); + new JdbcTypeHandle(Types.DOUBLE, Optional.of("double"), 0, Optional.empty(), Optional.empty(), Optional.empty()))); } } diff --git a/presto-mysql/src/main/java/io/prestosql/plugin/mysql/MySqlClient.java b/presto-mysql/src/main/java/io/prestosql/plugin/mysql/MySqlClient.java index 1196706f52ec..03d8e15e46d7 100644 --- a/presto-mysql/src/main/java/io/prestosql/plugin/mysql/MySqlClient.java +++ b/presto-mysql/src/main/java/io/prestosql/plugin/mysql/MySqlClient.java @@ -112,7 +112,7 @@ public MySqlClient(BaseJdbcConfig config, ConnectionFactory connectionFactory, T super(config, "`", connectionFactory); this.jsonType = typeManager.getType(new TypeSignature(StandardTypes.JSON)); - JdbcTypeHandle bigintTypeHandle = new JdbcTypeHandle(Types.BIGINT, Optional.of("bigint"), 0, 0, Optional.empty(), Optional.empty()); + JdbcTypeHandle bigintTypeHandle = new JdbcTypeHandle(Types.BIGINT, Optional.of("bigint"), 0, Optional.empty(), Optional.empty(), Optional.empty()); this.aggregateFunctionRewriter = new AggregateFunctionRewriter( this::quoted, ImmutableSet.builder() @@ -135,7 +135,7 @@ public Optional implementAggregation(ConnectorSession session, A private static Optional toTypeHandle(DecimalType decimalType) { - return Optional.of(new JdbcTypeHandle(Types.NUMERIC, Optional.of("decimal"), decimalType.getPrecision(), decimalType.getScale(), Optional.empty(), Optional.empty())); + return Optional.of(new JdbcTypeHandle(Types.NUMERIC, Optional.of("decimal"), decimalType.getPrecision(), Optional.of(decimalType.getScale()), Optional.empty(), Optional.empty())); } @Override @@ -241,8 +241,9 @@ public Optional toPrestoType(ConnectorSession session, Connection case Types.DECIMAL: int precision = columnSize; + int decimalDigits = typeHandle.getDecimalDigits().orElseThrow(() -> new IllegalStateException("decimal digits not present")); if (getDecimalRounding(session) == ALLOW_OVERFLOW && precision > Decimals.MAX_PRECISION) { - int scale = min(typeHandle.getDecimalDigits(), getDecimalDefaultScale(session)); + int scale = min(decimalDigits, getDecimalDefaultScale(session)); return Optional.of(decimalColumnMapping(createDecimalType(Decimals.MAX_PRECISION, scale), getDecimalRoundingMode(session))); } } diff --git a/presto-mysql/src/test/java/io/prestosql/plugin/mysql/TestMySqlClient.java b/presto-mysql/src/test/java/io/prestosql/plugin/mysql/TestMySqlClient.java index 0b68f8123496..8ca136146799 100644 --- a/presto-mysql/src/test/java/io/prestosql/plugin/mysql/TestMySqlClient.java +++ b/presto-mysql/src/test/java/io/prestosql/plugin/mysql/TestMySqlClient.java @@ -49,14 +49,14 @@ public class TestMySqlClient JdbcColumnHandle.builder() .setColumnName("c_bigint") .setColumnType(BIGINT) - .setJdbcTypeHandle(new JdbcTypeHandle(Types.BIGINT, Optional.of("int8"), 0, 0, Optional.empty(), Optional.empty())) + .setJdbcTypeHandle(new JdbcTypeHandle(Types.BIGINT, Optional.of("int8"), 0, Optional.empty(), Optional.empty(), Optional.empty())) .build(); private static final JdbcColumnHandle DOUBLE_COLUMN = JdbcColumnHandle.builder() .setColumnName("c_double") .setColumnType(DOUBLE) - .setJdbcTypeHandle(new JdbcTypeHandle(Types.DOUBLE, Optional.of("double"), 0, 0, Optional.empty(), Optional.empty())) + .setJdbcTypeHandle(new JdbcTypeHandle(Types.DOUBLE, Optional.of("double"), 0, Optional.empty(), Optional.empty(), Optional.empty())) .build(); private static final JdbcClient JDBC_CLIENT = new MySqlClient( diff --git a/presto-oracle/src/main/java/io/prestosql/plugin/oracle/OracleClient.java b/presto-oracle/src/main/java/io/prestosql/plugin/oracle/OracleClient.java index 64f204fe6034..3cd0cc916691 100644 --- a/presto-oracle/src/main/java/io/prestosql/plugin/oracle/OracleClient.java +++ b/presto-oracle/src/main/java/io/prestosql/plugin/oracle/OracleClient.java @@ -271,7 +271,7 @@ public Optional toPrestoType(ConnectorSession session, Connection oracleDoubleWriteFunction(), OracleClient::fullPushdownIfSupported)); case OracleTypes.NUMBER: - int decimalDigits = typeHandle.getDecimalDigits(); + int decimalDigits = typeHandle.getDecimalDigits().orElseThrow(() -> new IllegalStateException("decimal digits not present")); // Map negative scale to decimal(p+s, 0). int precision = columnSize + max(-decimalDigits, 0); int scale = max(decimalDigits, 0); diff --git a/presto-postgresql/src/main/java/io/prestosql/plugin/postgresql/ImplementAvgBigint.java b/presto-postgresql/src/main/java/io/prestosql/plugin/postgresql/ImplementAvgBigint.java index ad888bd08cc9..d73f80054c7c 100644 --- a/presto-postgresql/src/main/java/io/prestosql/plugin/postgresql/ImplementAvgBigint.java +++ b/presto-postgresql/src/main/java/io/prestosql/plugin/postgresql/ImplementAvgBigint.java @@ -61,6 +61,6 @@ public Optional rewrite(AggregateFunction aggregateFunction, Cap return Optional.of(new JdbcExpression( format("avg(CAST(%s AS double precision))", columnHandle.toSqlExpression(context.getIdentifierQuote())), - new JdbcTypeHandle(Types.DOUBLE, Optional.of("double"), 0, 0, Optional.empty(), Optional.empty()))); + new JdbcTypeHandle(Types.DOUBLE, Optional.of("double"), 0, Optional.empty(), Optional.empty(), Optional.empty()))); } } diff --git a/presto-postgresql/src/main/java/io/prestosql/plugin/postgresql/PostgreSqlClient.java b/presto-postgresql/src/main/java/io/prestosql/plugin/postgresql/PostgreSqlClient.java index b661221e34c8..7b619b938b33 100644 --- a/presto-postgresql/src/main/java/io/prestosql/plugin/postgresql/PostgreSqlClient.java +++ b/presto-postgresql/src/main/java/io/prestosql/plugin/postgresql/PostgreSqlClient.java @@ -185,7 +185,7 @@ public PostgreSqlClient( } this.tableTypes = tableTypes.toArray(new String[0]); - JdbcTypeHandle bigintTypeHandle = new JdbcTypeHandle(Types.BIGINT, Optional.of("bigint"), 0, 0, Optional.empty(), Optional.empty()); + JdbcTypeHandle bigintTypeHandle = new JdbcTypeHandle(Types.BIGINT, Optional.of("bigint"), 0, Optional.empty(), Optional.empty(), Optional.empty()); this.aggregateFunctionRewriter = new AggregateFunctionRewriter( this::quoted, ImmutableSet.builder() @@ -263,7 +263,7 @@ public List getColumns(ConnectorSession session, JdbcTableHand resultSet.getInt("DATA_TYPE"), Optional.of(resultSet.getString("TYPE_NAME")), resultSet.getInt("COLUMN_SIZE"), - resultSet.getInt("DECIMAL_DIGITS"), + getInteger(resultSet, "DECIMAL_DIGITS"), Optional.ofNullable(arrayColumnDimensions.get(columnName)), Optional.empty()); Optional columnMapping = toPrestoType(session, connection, typeHandle); @@ -347,7 +347,8 @@ public Optional toPrestoType(ConnectorSession session, Connection return Optional.of(jsonColumnMapping()); case "timestamptz": // PostgreSQL's "timestamp with time zone" is reported as Types.TIMESTAMP rather than Types.TIMESTAMP_WITH_TIMEZONE - return Optional.of(timestampWithTimeZoneColumnMapping(typeHandle.getDecimalDigits())); + int decimalDigits = typeHandle.getDecimalDigits().orElseThrow(() -> new IllegalStateException("decimal digits not present")); + return Optional.of(timestampWithTimeZoneColumnMapping(decimalDigits)); case "hstore": return Optional.of(hstoreColumnMapping(session)); } @@ -361,7 +362,8 @@ public Optional toPrestoType(ConnectorSession session, Connection return Optional.of(timeColumnMappingWithTruncation()); } if (typeHandle.getJdbcType() == Types.TIMESTAMP) { - TimestampType timestampType = createTimestampType(typeHandle.getDecimalDigits()); + int decimalDigits = typeHandle.getDecimalDigits().orElseThrow(() -> new IllegalStateException("decimal digits not present")); + TimestampType timestampType = createTimestampType(decimalDigits); return Optional.of(ColumnMapping.longMapping( timestampType, timestampReadFunction(timestampType), @@ -374,8 +376,9 @@ public Optional toPrestoType(ConnectorSession session, Connection return Optional.of(decimalColumnMapping(createDecimalType(Decimals.MAX_PRECISION, getDecimalDefaultScale(session)), getDecimalRoundingMode(session))); } int precision = typeHandle.getColumnSize(); + int decimalDigits = typeHandle.getDecimalDigits().orElseThrow(() -> new IllegalStateException("decimal digits not present")); if (precision > Decimals.MAX_PRECISION) { - int scale = min(typeHandle.getDecimalDigits(), getDecimalDefaultScale(session)); + int scale = min(decimalDigits, getDecimalDefaultScale(session)); return Optional.of(decimalColumnMapping(createDecimalType(Decimals.MAX_PRECISION, scale), getDecimalRoundingMode(session))); } } @@ -481,7 +484,7 @@ public Optional implementAggregation(ConnectorSession session, A private static Optional toTypeHandle(DecimalType decimalType) { - return Optional.of(new JdbcTypeHandle(Types.NUMERIC, Optional.of("decimal"), decimalType.getPrecision(), decimalType.getScale(), Optional.empty(), Optional.empty())); + return Optional.of(new JdbcTypeHandle(Types.NUMERIC, Optional.of("decimal"), decimalType.getPrecision(), Optional.of(decimalType.getScale()), Optional.empty(), Optional.empty())); } @Override diff --git a/presto-postgresql/src/test/java/io/prestosql/plugin/postgresql/TestPostgreSqlClient.java b/presto-postgresql/src/test/java/io/prestosql/plugin/postgresql/TestPostgreSqlClient.java index 75eb8271482b..1365f8b0e546 100644 --- a/presto-postgresql/src/test/java/io/prestosql/plugin/postgresql/TestPostgreSqlClient.java +++ b/presto-postgresql/src/test/java/io/prestosql/plugin/postgresql/TestPostgreSqlClient.java @@ -49,14 +49,14 @@ public class TestPostgreSqlClient JdbcColumnHandle.builder() .setColumnName("c_bigint") .setColumnType(BIGINT) - .setJdbcTypeHandle(new JdbcTypeHandle(Types.BIGINT, Optional.of("int8"), 0, 0, Optional.empty(), Optional.empty())) + .setJdbcTypeHandle(new JdbcTypeHandle(Types.BIGINT, Optional.of("int8"), 0, Optional.empty(), Optional.empty(), Optional.empty())) .build(); private static final JdbcColumnHandle DOUBLE_COLUMN = JdbcColumnHandle.builder() .setColumnName("c_double") .setColumnType(DOUBLE) - .setJdbcTypeHandle(new JdbcTypeHandle(Types.DOUBLE, Optional.of("double"), 0, 0, Optional.empty(), Optional.empty())) + .setJdbcTypeHandle(new JdbcTypeHandle(Types.DOUBLE, Optional.of("double"), 0, Optional.empty(), Optional.empty(), Optional.empty())) .build(); private static final JdbcClient JDBC_CLIENT = new PostgreSqlClient(