Skip to content

Error when appending to DuckLake table #249

@arouel

Description

@arouel

When I want to append many records to a DuckLake table with an appender, I get the following error when closing the DuckDBAppender instance. I used duckdb-java version 1.3.0.0.

java.sql.SQLException: INTERNAL Error: Calling GetStorage on a TableCatalogEntry that is not a DuckTableEntry
This error signals an assertion failure within DuckDB. This usually occurs due to unexpected conditions or errors in the program's logic.
For more information, see https://duckdb.org/docs/stable/dev/internal_errors
	at org.duckdb.DuckDBNative.duckdb_jdbc_appender_close(Native Method)
	at org.duckdb.DuckDBAppender.close(DuckDBAppender.java:102)
	at test.DuckLakeAppenderTest.fails_appender_ducklake(DuckLakeAppenderTest.java:32)
	at java.base/java.lang.reflect.Method.invoke(Method.java:565)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)

The following test cases may help to reproduce the error.

package test;

import static org.assertj.core.api.BDDAssertions.*;

import java.sql.DriverManager;
import java.sql.SQLException;

import org.duckdb.DuckDBConnection;
import org.junit.jupiter.api.Test;

class DuckLakeAppenderTest {

    @Test
    void fails_appender_ducklake() throws SQLException {
        try (
            var connection = (DuckDBConnection) DriverManager.getConnection("jdbc:duckdb:");
            var statement = connection.createStatement()
        ) {
            // not necessary with duckdb 1.3.1
            connection.setAutoCommit(false);

            statement.execute("""
                ATTACH 'ducklake:/tmp/test_fails_appender_ducklake.ducklake' AS my_ducklake;
                USE my_ducklake;
                CREATE TABLE IF NOT EXISTS test (a INT);
                """);

            try (var appender = connection.createAppender("main", "test")) {
                appender.beginRow();
                appender.append(124);
                appender.endRow();
                // fails: INTERNAL Error: Calling GetStorage on a TableCatalogEntry that is not a DuckTableEntry
            }

            try (var rs = statement.executeQuery("select * from test")) {
                rs.next();
                then(rs.getInt(1)).isEqualTo(124);
            }
        }
    }

    // workaround via temporary table
    @Test
    void succeeds_appender_ducklake_via_temporary_table() throws SQLException {
        try (
            var connection = (DuckDBConnection) DriverManager.getConnection("jdbc:duckdb:");
            var statement = connection.createStatement()
        ) {
            connection.setAutoCommit(false);

            statement.execute("""
                CREATE TEMP TABLE IF NOT EXISTS test_temp (a INT);
                ATTACH 'ducklake:/tmp/test_succeeds_appender_ducklake_via_temporary_table.ducklake' AS my_ducklake;
                USE my_ducklake;
                CREATE TABLE IF NOT EXISTS test (a INT);
                """);

            try (var appender = connection.createAppender("main", "test_temp")) {
                appender.beginRow();
                appender.append(124);
                appender.endRow();
            }

            statement.execute("""
                INSERT INTO test SELECT * FROM test_temp;
                DROP TABLE test_temp;
                """);

            try (var rs = statement.executeQuery("select * from test")) {
                rs.next();
                then(rs.getInt(1)).isEqualTo(124);
            }
        }
    }
}

Is there a plan to implement or fix it so that we can append directly the records to a DuckLake table?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions