diff --git a/docs/src/main/sphinx/connector/phoenix.rst b/docs/src/main/sphinx/connector/phoenix.rst index a5d3ab306a53..2513c02887bd 100644 --- a/docs/src/main/sphinx/connector/phoenix.rst +++ b/docs/src/main/sphinx/connector/phoenix.rst @@ -108,19 +108,28 @@ The data type mappings are as follows: Phoenix Trino ========================== ============ ``BOOLEAN`` (same) -``BIGINT`` (same) -``INTEGER`` (same) -``SMALLINT`` (same) ``TINYINT`` (same) -``DOUBLE`` (same) +``UNSIGNED_TINYINT`` ``TINYINT`` +``SMALLINT`` (same) +``UNSIGNED_SMALLINT`` ``SMALLINT`` +``INTEGER`` (same) +``UNSIGNED_INTEGER`` ``INTEGER`` +``BIGINT`` (same) +``UNSIGNED_LONG`` ``BIGINT`` ``FLOAT`` ``REAL`` +``UNSIGNED_FLOAT`` ``FLOAT`` +``DOUBLE`` (same) +``UNSIGNED_DOUBLE`` ``DOUBLE`` ``DECIMAL`` (same) ``BINARY`` ``VARBINARY`` ``VARBINARY`` (same) -``DATE`` (same) ``TIME`` (same) -``VARCHAR`` (same) +``UNSIGNED_TIME`` ``TIME`` +``DATE`` (same) +``UNSIGNED_DATE`` ``DATE`` ``CHAR`` (same) +``VARCHAR`` (same) +``ARRAY`` (same) ========================== ============ The Phoenix fixed length ``BINARY`` data type is mapped to the Trino diff --git a/plugin/trino-phoenix/src/main/java/io/trino/plugin/phoenix/PhoenixClient.java b/plugin/trino-phoenix/src/main/java/io/trino/plugin/phoenix/PhoenixClient.java index 5cd3df98402d..d44f87751bbe 100644 --- a/plugin/trino-phoenix/src/main/java/io/trino/plugin/phoenix/PhoenixClient.java +++ b/plugin/trino-phoenix/src/main/java/io/trino/plugin/phoenix/PhoenixClient.java @@ -423,6 +423,7 @@ public Optional toColumnMapping(ConnectorSession session, Connect } return Optional.of(defaultVarcharColumnMapping(typeHandle.getRequiredColumnSize(), true)); + case Types.BINARY: case Types.VARBINARY: return Optional.of(varbinaryColumnMapping()); diff --git a/plugin/trino-phoenix/src/test/java/io/trino/plugin/phoenix/TestPhoenixTypeMapping.java b/plugin/trino-phoenix/src/test/java/io/trino/plugin/phoenix/TestPhoenixTypeMapping.java index 51d924c247e5..67bc5d3b1f14 100644 --- a/plugin/trino-phoenix/src/test/java/io/trino/plugin/phoenix/TestPhoenixTypeMapping.java +++ b/plugin/trino-phoenix/src/test/java/io/trino/plugin/phoenix/TestPhoenixTypeMapping.java @@ -344,6 +344,28 @@ public void testChar() .execute(getQueryRunner(), phoenixCreateAndInsert("tpch.test_char")); } + @Test + public void testBinary() + { + // Not testing max length (2147483647) because it leads to 'Requested array size exceeds VM limit' + SqlDataTypeTest.create() + .addRoundTrip("binary(1)", "NULL", VARBINARY, "X'00'") // NULL stored as zeros + .addRoundTrip("binary(10)", "DECODE('', 'HEX')", VARBINARY, "X'00000000000000000000'") // empty stored as zeros + .addRoundTrip("binary(5)", "DECODE('68656C6C6F', 'HEX')", VARBINARY, "to_utf8('hello')") + .addRoundTrip("binary(26)", "DECODE('5069C4996B6E6120C582C4856B61207720E69DB1E4BAACE983BD', 'HEX')", VARBINARY, "to_utf8('Piękna łąka w 東京都')") + .addRoundTrip("binary(16)", "DECODE('4261672066756C6C206F6620F09F92B0', 'HEX')", VARBINARY, "to_utf8('Bag full of 💰')") + .addRoundTrip("binary(17)", "DECODE('0001020304050607080DF9367AA7000000', 'HEX')", VARBINARY, "X'0001020304050607080DF9367AA7000000'") // non-text + .addRoundTrip("binary(6)", "DECODE('000000000000', 'HEX')", VARBINARY, "X'000000000000'") + .addRoundTrip("integer primary key", "1", INTEGER, "1") + .execute(getQueryRunner(), phoenixCreateAndInsert("tpch.test_binary")); + + // Verify 'IS NULL' doesn't get rows where the value is X'00...' padded in Phoenix + try (TestTable table = new TestTable(new PhoenixSqlExecutor(phoenixServer.getJdbcUrl()), "tpch.test_binary", "(null_binary binary(1), empty_binary binary(10), pk integer primary key)", ImmutableList.of("NULL, DECODE('', 'HEX'), 1"))) { + assertQueryReturnsEmptyResult(format("SELECT * FROM %s WHERE null_binary IS NULL", table.getName())); + assertQueryReturnsEmptyResult(format("SELECT * FROM %s WHERE empty_binary IS NULL", table.getName())); + } + } + @Test public void testVarbinary() { diff --git a/plugin/trino-phoenix5/src/main/java/io/trino/plugin/phoenix5/PhoenixClient.java b/plugin/trino-phoenix5/src/main/java/io/trino/plugin/phoenix5/PhoenixClient.java index 50446804e126..a77e5b0eed66 100644 --- a/plugin/trino-phoenix5/src/main/java/io/trino/plugin/phoenix5/PhoenixClient.java +++ b/plugin/trino-phoenix5/src/main/java/io/trino/plugin/phoenix5/PhoenixClient.java @@ -415,6 +415,7 @@ public Optional toColumnMapping(ConnectorSession session, Connect } return Optional.of(defaultVarcharColumnMapping(typeHandle.getRequiredColumnSize(), true)); + case Types.BINARY: case Types.VARBINARY: return Optional.of(varbinaryColumnMapping()); diff --git a/plugin/trino-phoenix5/src/test/java/io/trino/plugin/phoenix5/TestPhoenixTypeMapping.java b/plugin/trino-phoenix5/src/test/java/io/trino/plugin/phoenix5/TestPhoenixTypeMapping.java index 160a49c42c23..28f141697e8e 100644 --- a/plugin/trino-phoenix5/src/test/java/io/trino/plugin/phoenix5/TestPhoenixTypeMapping.java +++ b/plugin/trino-phoenix5/src/test/java/io/trino/plugin/phoenix5/TestPhoenixTypeMapping.java @@ -344,6 +344,28 @@ public void testChar() .execute(getQueryRunner(), phoenixCreateAndInsert("tpch.test_char")); } + @Test + public void testBinary() + { + // Not testing max length (2147483647) because it leads to 'Requested array size exceeds VM limit' + SqlDataTypeTest.create() + .addRoundTrip("binary(1)", "NULL", VARBINARY, "X'00'") // NULL stored as zeros + .addRoundTrip("binary(10)", "DECODE('', 'HEX')", VARBINARY, "X'00000000000000000000'") // empty stored as zeros + .addRoundTrip("binary(5)", "DECODE('68656C6C6F', 'HEX')", VARBINARY, "to_utf8('hello')") + .addRoundTrip("binary(26)", "DECODE('5069C4996B6E6120C582C4856B61207720E69DB1E4BAACE983BD', 'HEX')", VARBINARY, "to_utf8('Piękna łąka w 東京都')") + .addRoundTrip("binary(16)", "DECODE('4261672066756C6C206F6620F09F92B0', 'HEX')", VARBINARY, "to_utf8('Bag full of 💰')") + .addRoundTrip("binary(17)", "DECODE('0001020304050607080DF9367AA7000000', 'HEX')", VARBINARY, "X'0001020304050607080DF9367AA7000000'") // non-text + .addRoundTrip("binary(6)", "DECODE('000000000000', 'HEX')", VARBINARY, "X'000000000000'") + .addRoundTrip("integer primary key", "1", INTEGER, "1") + .execute(getQueryRunner(), phoenixCreateAndInsert("tpch.test_binary")); + + // Verify 'IS NULL' doesn't get rows where the value is X'00...' padded in Phoenix + try (TestTable table = new TestTable(new PhoenixSqlExecutor(phoenixServer.getJdbcUrl()), "tpch.test_binary", "(null_binary binary(1), empty_binary binary(10), pk integer primary key)", ImmutableList.of("NULL, DECODE('', 'HEX'), 1"))) { + assertQueryReturnsEmptyResult(format("SELECT * FROM %s WHERE null_binary IS NULL", table.getName())); + assertQueryReturnsEmptyResult(format("SELECT * FROM %s WHERE empty_binary IS NULL", table.getName())); + } + } + @Test public void testVarbinary() {