|
35 | 35 | import java.time.temporal.ChronoUnit; |
36 | 36 | import java.util.*; |
37 | 37 | import java.util.concurrent.TimeUnit; |
| 38 | +import java.util.function.Consumer; |
38 | 39 |
|
39 | 40 | import static org.testng.Assert.assertEquals; |
40 | 41 | import static org.testng.Assert.assertFalse; |
@@ -653,6 +654,59 @@ static Object[][] testGetMetadataDataProvider() { |
653 | 654 | }; |
654 | 655 | } |
655 | 656 |
|
| 657 | + @Test(groups = { "integration" }) |
| 658 | + void testGetMetadataAppliesCustomTypeMapping() throws Exception { |
| 659 | + // Custom mapping overrides the Java class / JDBC type reported for integer columns. The metadata |
| 660 | + // returned by PreparedStatementImpl#getMetaData must honor this mapping both before the statement is |
| 661 | + // executed (resolved from the parsed query schema) and after it is executed (resolved from the result set). |
| 662 | + Properties properties = new Properties(); |
| 663 | + properties.setProperty(DriverProperties.JDBC_TYPE_MAPPINGS.getKey(), "Int32=Long,UInt64=String"); |
| 664 | + |
| 665 | + Consumer<ResultSetMetaData> verify = (metaData) -> { |
| 666 | + try { |
| 667 | + assertEquals(metaData.getColumnCount(), 3); |
| 668 | + |
| 669 | + assertEquals(metaData.getColumnName(1), "i32"); |
| 670 | + assertEquals(metaData.getColumnClassName(1), Long.class.getName()); |
| 671 | + assertEquals(metaData.getColumnType(1), Types.BIGINT); |
| 672 | + |
| 673 | + assertEquals(metaData.getColumnName(2), "u64"); |
| 674 | + assertEquals(metaData.getColumnClassName(2), String.class.getName()); |
| 675 | + assertEquals(metaData.getColumnType(2), Types.VARCHAR); |
| 676 | + |
| 677 | + assertEquals(metaData.getColumnName(3), "u16"); |
| 678 | + assertEquals(metaData.getColumnClassName(3), Integer.class.getName()); |
| 679 | + assertEquals(metaData.getColumnType(3), Types.INTEGER); |
| 680 | + |
| 681 | + } catch (SQLException e) { |
| 682 | + fail("no exception expected", e); |
| 683 | + } |
| 684 | + }; |
| 685 | + |
| 686 | + try (Connection conn = getJdbcConnection(properties); |
| 687 | + PreparedStatement stmt = conn.prepareStatement("SELECT toInt32(?) AS i32, toUInt64(?) AS u64, toUInt16(?) as u16")) { |
| 688 | + // Before execution: metadata is derived from the query schema and must already reflect the mapping. |
| 689 | + ResultSetMetaData beforeExec = stmt.getMetaData(); |
| 690 | + assertNotNull(beforeExec); |
| 691 | + |
| 692 | + stmt.setInt(1, 42); |
| 693 | + stmt.setLong(2, 7L); |
| 694 | + stmt.setInt(3, 20); |
| 695 | + try (ResultSet rs = stmt.executeQuery()) { |
| 696 | + assertTrue(rs.next()); |
| 697 | + // Values are materialized using the same mapping. |
| 698 | + assertTrue(rs.getObject("i32") instanceof Long, "i32 should be mapped to Long"); |
| 699 | + assertTrue(rs.getObject("u64") instanceof String, "u64 should be mapped to String"); |
| 700 | + assertTrue(rs.getObject("u16") instanceof Integer, "u16 should be mapped to Integer"); |
| 701 | + |
| 702 | + // After execution: metadata is taken from the result set but must stay in sync with the mapping. |
| 703 | + ResultSetMetaData afterExec = stmt.getMetaData(); |
| 704 | + assertNotNull(afterExec); |
| 705 | + verify.accept(afterExec); |
| 706 | + } |
| 707 | + } |
| 708 | + } |
| 709 | + |
656 | 710 | @Test(groups = { "integration" }) |
657 | 711 | void testMetabaseBug01() throws Exception { |
658 | 712 | try (Connection conn = getJdbcConnection()) { |
|
0 commit comments