|
1 | 1 | package org.duckdb; |
2 | 2 |
|
| 3 | +import static java.util.Arrays.asList; |
| 4 | +import static java.util.Collections.singletonList; |
3 | 5 | import static org.duckdb.TestDuckDBJDBC.JDBC_URL; |
4 | 6 | import static org.duckdb.test.Assertions.*; |
| 7 | +import static org.duckdb.test.Helpers.createMap; |
5 | 8 |
|
| 9 | +import java.math.BigDecimal; |
| 10 | +import java.math.BigInteger; |
6 | 11 | import java.sql.DriverManager; |
7 | 12 | import java.sql.ResultSet; |
8 | 13 | import java.sql.SQLException; |
9 | 14 | import java.sql.Statement; |
10 | | -import java.util.Map; |
| 15 | +import java.util.*; |
11 | 16 |
|
12 | 17 | public class TestAppenderComposite { |
13 | 18 |
|
@@ -474,4 +479,195 @@ public static void test_appender_union_nested() throws Exception { |
474 | 479 | } |
475 | 480 | } |
476 | 481 | } |
| 482 | + |
| 483 | + private static void assertFetchedStructEquals(Object dbs, Collection<Object> struct) throws Exception { |
| 484 | + DuckDBStruct dbStruct = (DuckDBStruct) dbs; |
| 485 | + Map<String, Object> map = dbStruct.getMap(); |
| 486 | + Collection<Object> fetched = map.values(); |
| 487 | + assertEquals(fetched.size(), struct.size()); |
| 488 | + List<Object> structList = new ArrayList<>(struct); |
| 489 | + int i = 0; |
| 490 | + for (Object f : fetched) { |
| 491 | + assertEquals(f, structList.get(i)); |
| 492 | + i++; |
| 493 | + } |
| 494 | + } |
| 495 | + |
| 496 | + public static void test_appender_list_basic_struct() throws Exception { |
| 497 | + Collection<Object> struct1 = asList(42, "foo"); |
| 498 | + Collection<Object> struct2 = asList(null, "bar"); |
| 499 | + Collection<Object> struct3 = asList(43, null); |
| 500 | + Collection<Object> struct4 = asList(44, "baz"); |
| 501 | + try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); |
| 502 | + Statement stmt = conn.createStatement()) { |
| 503 | + stmt.execute("CREATE TABLE tab1(col1 INT, col2 STRUCT(s1 INT, s2 VARCHAR)[])"); |
| 504 | + try (DuckDBAppender appender = conn.createAppender("tab1")) { |
| 505 | + appender.beginRow() |
| 506 | + .append(42) |
| 507 | + .append(asList(struct1, struct2, struct3)) |
| 508 | + .endRow() |
| 509 | + .beginRow() |
| 510 | + .append(43) |
| 511 | + .append((List<Object>) null) |
| 512 | + .endRow() |
| 513 | + .beginRow() |
| 514 | + .append(44) |
| 515 | + .append(asList(null, struct4)) |
| 516 | + .endRow() |
| 517 | + .flush(); |
| 518 | + } |
| 519 | + |
| 520 | + try (ResultSet rs = stmt.executeQuery("SELECT unnest(col2) from tab1 WHERE col1 = 42")) { |
| 521 | + assertTrue(rs.next()); |
| 522 | + assertFetchedStructEquals(rs.getObject(1), struct1); |
| 523 | + assertTrue(rs.next()); |
| 524 | + assertFetchedStructEquals(rs.getObject(1), struct2); |
| 525 | + assertTrue(rs.next()); |
| 526 | + assertFetchedStructEquals(rs.getObject(1), struct3); |
| 527 | + assertFalse(rs.next()); |
| 528 | + } |
| 529 | + try (ResultSet rs = stmt.executeQuery("SELECT col2 from tab1 WHERE col1 = 43")) { |
| 530 | + assertTrue(rs.next()); |
| 531 | + assertNull(rs.getObject(1)); |
| 532 | + assertTrue(rs.wasNull()); |
| 533 | + assertFalse(rs.next()); |
| 534 | + } |
| 535 | + try (ResultSet rs = stmt.executeQuery("SELECT unnest(col2) from tab1 WHERE col1 = 44")) { |
| 536 | + assertTrue(rs.next()); |
| 537 | + assertNull(rs.getObject(1)); |
| 538 | + assertTrue(rs.wasNull()); |
| 539 | + assertTrue(rs.next()); |
| 540 | + assertFetchedStructEquals(rs.getObject(1), struct4); |
| 541 | + assertFalse(rs.next()); |
| 542 | + } |
| 543 | + } |
| 544 | + } |
| 545 | + |
| 546 | + public static void test_appender_list_basic_struct_as_map() throws Exception { |
| 547 | + LinkedHashMap<Object, Object> struct1 = createMap("key1", 42, "key2", "foo"); |
| 548 | + LinkedHashMap<Object, Object> struct2 = createMap("key1", null, "key2", "bar"); |
| 549 | + LinkedHashMap<Object, Object> struct3 = createMap("key1", 43, "key2", null); |
| 550 | + LinkedHashMap<Object, Object> struct4 = createMap("key1", 44, "key2", "baz"); |
| 551 | + try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); |
| 552 | + Statement stmt = conn.createStatement()) { |
| 553 | + stmt.execute("CREATE TABLE tab1(col1 INT, col2 STRUCT(s1 INT, s2 VARCHAR)[])"); |
| 554 | + try (DuckDBAppender appender = conn.createAppender("tab1")) { |
| 555 | + appender.beginRow() |
| 556 | + .append(42) |
| 557 | + .append(asList(struct1, struct2, struct3)) |
| 558 | + .endRow() |
| 559 | + .beginRow() |
| 560 | + .append(43) |
| 561 | + .append((List<Object>) null) |
| 562 | + .endRow() |
| 563 | + .beginRow() |
| 564 | + .append(44) |
| 565 | + .append(asList(null, struct4)) |
| 566 | + .endRow() |
| 567 | + .flush(); |
| 568 | + } |
| 569 | + |
| 570 | + try (ResultSet rs = stmt.executeQuery("SELECT unnest(col2) from tab1 WHERE col1 = 42")) { |
| 571 | + assertTrue(rs.next()); |
| 572 | + assertFetchedStructEquals(rs.getObject(1), struct1.values()); |
| 573 | + assertTrue(rs.next()); |
| 574 | + assertFetchedStructEquals(rs.getObject(1), struct2.values()); |
| 575 | + assertTrue(rs.next()); |
| 576 | + assertFetchedStructEquals(rs.getObject(1), struct3.values()); |
| 577 | + assertFalse(rs.next()); |
| 578 | + } |
| 579 | + try (ResultSet rs = stmt.executeQuery("SELECT col2 from tab1 WHERE col1 = 43")) { |
| 580 | + assertTrue(rs.next()); |
| 581 | + assertNull(rs.getObject(1)); |
| 582 | + assertTrue(rs.wasNull()); |
| 583 | + assertFalse(rs.next()); |
| 584 | + } |
| 585 | + try (ResultSet rs = stmt.executeQuery("SELECT unnest(col2) from tab1 WHERE col1 = 44")) { |
| 586 | + assertTrue(rs.next()); |
| 587 | + assertNull(rs.getObject(1)); |
| 588 | + assertTrue(rs.wasNull()); |
| 589 | + assertTrue(rs.next()); |
| 590 | + assertFetchedStructEquals(rs.getObject(1), struct4.values()); |
| 591 | + assertFalse(rs.next()); |
| 592 | + } |
| 593 | + } |
| 594 | + } |
| 595 | + |
| 596 | + public static void test_appender_list_basic_struct_with_primitives() throws Exception { |
| 597 | + Collection<Object> struct1 = asList(true, (byte) 42, (short) 43, 44, 45L, BigInteger.valueOf(46), 47.1F, 48.1D, |
| 598 | + BigDecimal.valueOf(49.123)); |
| 599 | + try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); |
| 600 | + Statement stmt = conn.createStatement()) { |
| 601 | + stmt.execute("CREATE TABLE tab1(col1 INT, col2 STRUCT(" |
| 602 | + + "s1 BOOL," |
| 603 | + + "s2 TINYINT," |
| 604 | + + "s3 SMALLINT," |
| 605 | + + "s4 INTEGER," |
| 606 | + + "s5 BIGINT," |
| 607 | + + "s6 HUGEINT," |
| 608 | + + "s7 FLOAT," |
| 609 | + + "s8 DOUBLE," |
| 610 | + + "s9 DECIMAL" |
| 611 | + + ")[])"); |
| 612 | + try (DuckDBAppender appender = conn.createAppender("tab1")) { |
| 613 | + appender.beginRow().append(42).append(singletonList(struct1)).endRow().flush(); |
| 614 | + } |
| 615 | + |
| 616 | + try (ResultSet rs = stmt.executeQuery("SELECT unnest(col2) from tab1 WHERE col1 = 42")) { |
| 617 | + assertTrue(rs.next()); |
| 618 | + assertFetchedStructEquals(rs.getObject(1), struct1); |
| 619 | + assertFalse(rs.next()); |
| 620 | + } |
| 621 | + } |
| 622 | + } |
| 623 | + |
| 624 | + public static void test_appender_list_basic_union() throws Exception { |
| 625 | + Map.Entry<String, Object> union1 = new AbstractMap.SimpleEntry<>("u1", 42); |
| 626 | + Map.Entry<String, Object> union2 = new AbstractMap.SimpleEntry<>("u2", "foo"); |
| 627 | + Map.Entry<String, Object> union3 = new AbstractMap.SimpleEntry<>("u1", null); |
| 628 | + Map.Entry<String, Object> union4 = new AbstractMap.SimpleEntry<>("u2", "bar"); |
| 629 | + try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); |
| 630 | + Statement stmt = conn.createStatement()) { |
| 631 | + stmt.execute("CREATE TABLE tab1(col1 INT, col2 UNION(u1 INT, u2 VARCHAR)[])"); |
| 632 | + try (DuckDBAppender appender = conn.createAppender("tab1")) { |
| 633 | + appender.beginRow() |
| 634 | + .append(42) |
| 635 | + .append(asList(union1, union2, union3)) |
| 636 | + .endRow() |
| 637 | + .beginRow() |
| 638 | + .append(43) |
| 639 | + .append((List<Object>) null) |
| 640 | + .endRow() |
| 641 | + .beginRow() |
| 642 | + .append(44) |
| 643 | + .append(asList(null, union4)) |
| 644 | + .endRow() |
| 645 | + .flush(); |
| 646 | + } |
| 647 | + |
| 648 | + try (ResultSet rs = stmt.executeQuery("SELECT unnest(col2) from tab1 WHERE col1 = 42")) { |
| 649 | + assertTrue(rs.next()); |
| 650 | + assertEquals(rs.getObject(1), union1.getValue()); |
| 651 | + assertTrue(rs.next()); |
| 652 | + assertEquals(rs.getObject(1), union2.getValue()); |
| 653 | + assertTrue(rs.next()); |
| 654 | + assertEquals(rs.getObject(1), union3.getValue()); |
| 655 | + assertFalse(rs.next()); |
| 656 | + } |
| 657 | + try (ResultSet rs = stmt.executeQuery("SELECT col2 from tab1 WHERE col1 = 43")) { |
| 658 | + assertTrue(rs.next()); |
| 659 | + assertNull(rs.getObject(1)); |
| 660 | + assertTrue(rs.wasNull()); |
| 661 | + assertFalse(rs.next()); |
| 662 | + } |
| 663 | + try (ResultSet rs = stmt.executeQuery("SELECT unnest(col2) from tab1 WHERE col1 = 44")) { |
| 664 | + assertTrue(rs.next()); |
| 665 | + assertNull(rs.getObject(1)); |
| 666 | + assertTrue(rs.wasNull()); |
| 667 | + assertTrue(rs.next()); |
| 668 | + assertEquals(rs.getObject(1), union4.getValue()); |
| 669 | + assertFalse(rs.next()); |
| 670 | + } |
| 671 | + } |
| 672 | + } |
477 | 673 | } |
0 commit comments