Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions src/main/java/org/duckdb/DuckDBAppender.java
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,13 @@ private Column nextColumn(Column curCol) {
if (null == curCol.parent) {
cols = columns;
} else {
cols = curCol.parent.children;
if (DUCKDB_TYPE_UNION == curCol.parent.colType) {
curCol = curCol.parent;
// recurse up the union
return nextColumn(curCol);
} else {
cols = curCol.parent.children;
}
}
int nextColIdx = curCol.idx + 1;
if (nextColIdx < cols.size()) {
Expand All @@ -1004,11 +1010,7 @@ private Column nextColumn(Column curCol) {
private void moveToNextColumn() throws SQLException {
Column col = currentColumn();
this.prevColumn = currentColumn;
if (unionBegunInvariant()) {
this.currentColumn = nextColumn(col.parent);
} else {
this.currentColumn = nextColumn(col);
}
this.currentColumn = nextColumn(col);
}

// checks
Expand Down Expand Up @@ -2127,11 +2129,6 @@ private boolean structCompletedInvariant() {
prevColumn.idx == prevColumn.parent.children.size() - 1;
}

private boolean unionBegunInvariant() {
return null != currentColumn && null != currentColumn.parent &&
currentColumn.parent.colType == DUCKDB_TYPE_UNION;
}

private boolean unionCompletedInvariant() {
return null != prevColumn && null != prevColumn.parent && prevColumn.parent.colType == DUCKDB_TYPE_UNION;
}
Expand Down
107 changes: 107 additions & 0 deletions src/test/java/org/duckdb/TestAppenderComposite.java
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,113 @@ public static void test_appender_union_nested() throws Exception {
}
}

public static void test_appender_union_struct() throws Exception {
try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class);
Statement stmt = conn.createStatement()) {
stmt.execute("CREATE TABLE tab1 ("
+ "col1 INTEGER, "
+ "col2 UNION("
+ " u1 STRUCT("
+ " s1 INTEGER, "
+ " s2 INTEGER"
+ " ), "
+ " u2 INTEGER"
+ " )"
+ ")");

try (DuckDBAppender appender = conn.createAppender("tab1")) {
appender.beginRow()
.append(42)
.beginUnion("u1")
.beginStruct()
.append(43)
.append(44)
.endStruct()
.endUnion()
.endRow()

.beginRow()
.append(45)
.beginUnion("u2")
.append(46)
.endUnion()
.endRow()

.beginRow()
.append(47)
.beginUnion("u1")
.appendNull()
.endUnion()
.endRow()

.beginRow()
.append(48)
.beginUnion("u2")
.appendNull()
.endUnion()
.endRow()

.beginRow()
.append(49)
.appendNull()
.endRow()

.beginRow()
.append(50)
.beginUnion("u1")
.beginStruct()
.append(51)
.append(52)
.endStruct()
.endUnion()
.endRow();
}

try (ResultSet rs = stmt.executeQuery("SELECT * FROM tab1 ORDER BY col1")) {
{
assertTrue(rs.next());
assertEquals(rs.getInt(1), 42);
DuckDBStruct struct = (DuckDBStruct) rs.getObject(2);
Map<String, Object> map = struct.getMap();
assertEquals(map.size(), 2);
assertEquals(map.get("s1"), 43);
assertEquals(map.get("s2"), 44);
}

assertTrue(rs.next());
assertEquals(rs.getInt(1), 45);
assertEquals(rs.getInt(2), 46);

assertTrue(rs.next());
assertEquals(rs.getInt(1), 47);
assertNull(rs.getObject(2));
assertFalse(rs.wasNull());

assertTrue(rs.next());
assertEquals(rs.getInt(1), 48);
assertNull(rs.getObject(2));
assertFalse(rs.wasNull());

assertTrue(rs.next());
assertEquals(rs.getInt(1), 49);
assertNull(rs.getObject(2));
assertTrue(rs.wasNull());

{
assertTrue(rs.next());
assertEquals(rs.getInt(1), 50);
DuckDBStruct struct = (DuckDBStruct) rs.getObject(2);
Map<String, Object> map = struct.getMap();
assertEquals(map.size(), 2);
assertEquals(map.get("s1"), 51);
assertEquals(map.get("s2"), 52);
}

assertFalse(rs.next());
}
}
}

private static void assertFetchedStructEquals(Object dbs, Collection<Object> struct) throws Exception {
DuckDBStruct dbStruct = (DuckDBStruct) dbs;
Map<String, Object> map = dbStruct.getMap();
Expand Down