From 3c4662a03134469d232daa03a243deaf793151ec Mon Sep 17 00:00:00 2001 From: maartenb Date: Mon, 17 Feb 2025 21:10:51 +0100 Subject: [PATCH 1/5] DuckDBAppender now supports Long, Integer, Short and Boolean. --- src/main/java/org/duckdb/DuckDBAppender.java | 36 +++++++ src/test/java/org/duckdb/TestDuckDBJDBC.java | 103 +++++++++++++++++++ 2 files changed, 139 insertions(+) diff --git a/src/main/java/org/duckdb/DuckDBAppender.java b/src/main/java/org/duckdb/DuckDBAppender.java index 08eb5ef35..134757766 100644 --- a/src/main/java/org/duckdb/DuckDBAppender.java +++ b/src/main/java/org/duckdb/DuckDBAppender.java @@ -93,6 +93,42 @@ public void append(byte[] value) throws SQLException { } } + private void appendNull() throws SQLException { + DuckDBNative.duckdb_jdbc_appender_append_null(appender_ref); + } + + public void append(Boolean value) throws SQLException { + if (value == null) { + this.appendNull(); + } else { + append(value.booleanValue()); + } + } + + public void append(Long value) throws SQLException { + if (value == null) { + this.appendNull(); + } else { + append(value.longValue()); + } + } + + public void append(Short value) throws SQLException { + if (value == null) { + this.appendNull(); + } else { + append(value.shortValue()); + } + } + + public void append(Integer value) throws SQLException { + if (value == null) { + this.appendNull(); + } else { + append(value.intValue()); + } + } + protected void finalize() throws Throwable { close(); } diff --git a/src/test/java/org/duckdb/TestDuckDBJDBC.java b/src/test/java/org/duckdb/TestDuckDBJDBC.java index 1908d89e9..a6bdf0387 100644 --- a/src/test/java/org/duckdb/TestDuckDBJDBC.java +++ b/src/test/java/org/duckdb/TestDuckDBJDBC.java @@ -2713,6 +2713,109 @@ public static void test_appender_null_integer() throws Exception { conn.close(); } + public static void test_appender_Boolean() throws Exception { + try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); Statement stmt = conn.createStatement();) { + + stmt.execute("CREATE TABLE data (a BOOLEAN)"); + DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); + Boolean[] values = new Boolean[] { Boolean.TRUE, Boolean.FALSE, null}; + for (Boolean value : values) { + appender.beginRow(); + appender.append(value); + appender.endRow(); + } + appender.flush(); + appender.close(); + + try (ResultSet results = stmt.executeQuery("SELECT count(1) FROM data WHERE a = true");) { + assertTrue(results.next()); + assertEquals(1, results.getInt(1)); + } + try (ResultSet results = stmt.executeQuery("SELECT count(1) FROM data WHERE a = false");) { + assertTrue(results.next()); + assertEquals(1, results.getInt(1)); + } + try (ResultSet results = stmt.executeQuery("SELECT count(1) FROM data WHERE a is null");) { + assertTrue(results.next()); + assertEquals(1, results.getInt(1)); + } + } + } + + + public static void test_appender_Integer() throws Exception { + try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); Statement stmt = conn.createStatement();) { + + stmt.execute("CREATE TABLE data (a INTEGER)"); + DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); + appender.beginRow(); + + Integer value = Integer.MAX_VALUE - 10; + + appender.append(value); + appender.endRow(); + appender.flush(); + appender.close(); + + try (ResultSet results = stmt.executeQuery("SELECT * FROM data");) { + assertTrue(results.next()); + assertEquals(value, results.getInt(1)); + assertFalse(results.wasNull()); + } + } + } + + public static void test_appender_Long() throws Exception { + try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); Statement stmt = conn.createStatement();) { + + stmt.execute("CREATE TABLE data (a LONG)"); + DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); + appender.beginRow(); + + Long value = Long.MAX_VALUE - 10; + + appender.append(value); + appender.endRow(); + appender.flush(); + appender.close(); + + try (ResultSet results = stmt.executeQuery("SELECT * FROM data");) { + assertTrue(results.next()); + assertEquals(value, results.getLong(1)); + assertFalse(results.wasNull()); + } + } + } + + public static void test_appender_Short() throws Exception { + try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); Statement stmt = conn.createStatement();) { + + stmt.execute("CREATE TABLE data (a SHORT)"); + DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); + + Short shortValue = Short.MIN_VALUE; + while (true) { + appender.beginRow(); + appender.append(shortValue); + appender.endRow(); + if (shortValue == Short.MAX_VALUE) { + break; + } + shortValue++; + } + appender.flush(); + appender.close(); + + try (ResultSet results = stmt.executeQuery("SELECT min(a), max(a), avg(a) FROM data");) { + assertTrue(results.next()); + assertEquals(Short.MIN_VALUE, results.getShort(1)); + assertEquals(Short.MAX_VALUE, results.getShort(2)); + assertEquals(-0.5f, results.getFloat(3)); + assertFalse(results.wasNull()); + } + } + } + public static void test_appender_null_varchar() throws Exception { DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); Statement stmt = conn.createStatement(); From 5237e18dad30d0635ee991a02c41914725a36e8d Mon Sep 17 00:00:00 2001 From: Maarten Bosteels Date: Wed, 19 Feb 2025 11:19:55 +0100 Subject: [PATCH 2/5] Disable uploading artifacts --- .github/workflows/Java.yml | 118 ++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/.github/workflows/Java.yml b/.github/workflows/Java.yml index 950d109da..e70410c6a 100644 --- a/.github/workflows/Java.yml +++ b/.github/workflows/Java.yml @@ -55,19 +55,19 @@ jobs: if: ${{ inputs.skip_tests != 'true' }} run: make test - - name: Deploy - shell: bash - env: - AWS_ACCESS_KEY_ID: ${{ secrets.S3_DUCKDB_STAGING_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_DUCKDB_STAGING_KEY }} - run: | - cp build/release/duckdb_jdbc.jar duckdb_jdbc-linux-amd64.jar - ./scripts/upload-assets-to-staging.sh github_release duckdb_jdbc-linux-amd64.jar - - uses: actions/upload-artifact@v3 - with: - name: java-linux-amd64 - path: | - build/release/duckdb_jdbc.jar + # - name: Deploy + # shell: bash + # env: + # AWS_ACCESS_KEY_ID: ${{ secrets.S3_DUCKDB_STAGING_ID }} + # AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_DUCKDB_STAGING_KEY }} + # run: | + # cp build/release/duckdb_jdbc.jar duckdb_jdbc-linux-amd64.jar + # ./scripts/upload-assets-to-staging.sh github_release duckdb_jdbc-linux-amd64.jar + # - uses: actions/upload-artifact@v4 + # with: + # name: java-linux-amd64 + # path: | + # build/release/duckdb_jdbc.jar java-linux-aarch64: name: Java Linux (aarch64) @@ -99,20 +99,20 @@ jobs: shell: bash run: CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ OVERRIDE_JDBC_OS_ARCH=arm64 make release - - name: Deploy - shell: bash - env: - AWS_ACCESS_KEY_ID: ${{ secrets.S3_DUCKDB_STAGING_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_DUCKDB_STAGING_KEY }} - run: | - cp build/release/duckdb_jdbc.jar duckdb_jdbc-linux-aarch64.jar - # ./scripts/upload-assets-to-staging.sh github_release duckdb_jdbc-linux-aarch64.jar + # - name: Deploy + # shell: bash + # env: + # AWS_ACCESS_KEY_ID: ${{ secrets.S3_DUCKDB_STAGING_ID }} + # AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_DUCKDB_STAGING_KEY }} + # run: | + # cp build/release/duckdb_jdbc.jar duckdb_jdbc-linux-aarch64.jar + # # ./scripts/upload-assets-to-staging.sh github_release duckdb_jdbc-linux-aarch64.jar - - uses: actions/upload-artifact@v3 - with: - name: java-linux-aarch64 - path: | - build/release/duckdb_jdbc.jar + # - uses: actions/upload-artifact@v4 + # with: + # name: java-linux-aarch64 + # path: | + # build/release/duckdb_jdbc.jar java-windows-amd64: @@ -142,19 +142,19 @@ jobs: run: | ls -R . make test - - name: Deploy - shell: bash - env: - AWS_ACCESS_KEY_ID: ${{ secrets.S3_DUCKDB_STAGING_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_DUCKDB_STAGING_KEY }} - run: | - cp build/release/duckdb_jdbc.jar duckdb_jdbc-windows-amd64.jar - ./scripts/upload-assets-to-staging.sh github_release duckdb_jdbc-windows-amd64.jar - - uses: actions/upload-artifact@v3 - with: - name: java-windows-amd64 - path: | - build/release/duckdb_jdbc.jar + # - name: Deploy + # shell: bash + # env: + # AWS_ACCESS_KEY_ID: ${{ secrets.S3_DUCKDB_STAGING_ID }} + # AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_DUCKDB_STAGING_KEY }} + # run: | + # cp build/release/duckdb_jdbc.jar duckdb_jdbc-windows-amd64.jar + # ./scripts/upload-assets-to-staging.sh github_release duckdb_jdbc-windows-amd64.jar + # - uses: actions/upload-artifact@v4 + # with: + # name: java-windows-amd64 + # path: | + # build/release/duckdb_jdbc.jar java-osx-universal: @@ -184,19 +184,19 @@ jobs: - name: See if this actually universal shell: bash run: lipo -archs build/release/libduckdb_java.so_osx_universal | grep "x86_64 arm64" - - name: Deploy - shell: bash - env: - AWS_ACCESS_KEY_ID: ${{ secrets.S3_DUCKDB_STAGING_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_DUCKDB_STAGING_KEY }} - run: | - cp build/release/duckdb_jdbc.jar duckdb_jdbc-osx-universal.jar - ./scripts/upload-assets-to-staging.sh github_release duckdb_jdbc-osx-universal.jar - - uses: actions/upload-artifact@v3 - with: - name: java-osx-universal - path: | - build/release/duckdb_jdbc.jar + # - name: Deploy + # shell: bash + # env: + # AWS_ACCESS_KEY_ID: ${{ secrets.S3_DUCKDB_STAGING_ID }} + # AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_DUCKDB_STAGING_KEY }} + # run: | + # cp build/release/duckdb_jdbc.jar duckdb_jdbc-osx-universal.jar + # ./scripts/upload-assets-to-staging.sh github_release duckdb_jdbc-osx-universal.jar + # - uses: actions/upload-artifact@v4 + # with: + # name: java-osx-universal + # path: | + # build/release/duckdb_jdbc.jar java-combine: @@ -265,13 +265,13 @@ jobs: fi ls -lahR jdbc-artifacts - - name: Upload artifacts - if: always() - uses: actions/upload-artifact@v3 - with: - name: java-jars - path: | - jdbc-artifacts + # - name: Upload artifacts + # if: always() + # uses: actions/upload-artifact@v4 + # with: + # name: java-jars + # path: | + # jdbc-artifacts jdbc-compliance: name: JDBC Compliance From 7870d30ce52035099a8d34277fde19e0a8b88a7d Mon Sep 17 00:00:00 2001 From: maartenb Date: Wed, 19 Feb 2025 19:27:28 +0100 Subject: [PATCH 3/5] DuckDBAppender now supports Long, Integer, Short and Boolean. --- src/test/test.iml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/test.iml b/src/test/test.iml index a0e49a3ba..5ebc6f48e 100644 --- a/src/test/test.iml +++ b/src/test/test.iml @@ -7,5 +7,6 @@ + \ No newline at end of file From dbeb1f1079ca71fc8dcbf4259bda12d14fad4dd6 Mon Sep 17 00:00:00 2001 From: maartenb Date: Wed, 19 Feb 2025 19:30:54 +0100 Subject: [PATCH 4/5] DuckDBAppender now supports Long, Integer, Short and Boolean. --- .gitignore | 1 + src/main/main.iml | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 src/main/main.iml diff --git a/.gitignore b/.gitignore index 427bdb67f..2d635d6bf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build .idea cmake-build-debug +out diff --git a/src/main/main.iml b/src/main/main.iml new file mode 100644 index 000000000..908ad4f52 --- /dev/null +++ b/src/main/main.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file From 3fd6a873c87790ca5c52826a62dda491ef15815a Mon Sep 17 00:00:00 2001 From: maartenb Date: Wed, 19 Feb 2025 19:40:08 +0100 Subject: [PATCH 5/5] DuckDBAppender now supports Long, Integer, Short and Boolean (ran make format) --- src/main/java/org/duckdb/DuckDBAppender.java | 42 ++++++++++---------- src/test/java/org/duckdb/TestDuckDBJDBC.java | 15 ++++--- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/duckdb/DuckDBAppender.java b/src/main/java/org/duckdb/DuckDBAppender.java index 134757766..814be1be3 100644 --- a/src/main/java/org/duckdb/DuckDBAppender.java +++ b/src/main/java/org/duckdb/DuckDBAppender.java @@ -98,35 +98,35 @@ private void appendNull() throws SQLException { } public void append(Boolean value) throws SQLException { - if (value == null) { - this.appendNull(); - } else { - append(value.booleanValue()); - } + if (value == null) { + this.appendNull(); + } else { + append(value.booleanValue()); + } } - + public void append(Long value) throws SQLException { - if (value == null) { - this.appendNull(); - } else { - append(value.longValue()); - } + if (value == null) { + this.appendNull(); + } else { + append(value.longValue()); + } } public void append(Short value) throws SQLException { - if (value == null) { - this.appendNull(); - } else { - append(value.shortValue()); - } + if (value == null) { + this.appendNull(); + } else { + append(value.shortValue()); + } } public void append(Integer value) throws SQLException { - if (value == null) { - this.appendNull(); - } else { - append(value.intValue()); - } + if (value == null) { + this.appendNull(); + } else { + append(value.intValue()); + } } protected void finalize() throws Throwable { diff --git a/src/test/java/org/duckdb/TestDuckDBJDBC.java b/src/test/java/org/duckdb/TestDuckDBJDBC.java index a6bdf0387..9ed04eda2 100644 --- a/src/test/java/org/duckdb/TestDuckDBJDBC.java +++ b/src/test/java/org/duckdb/TestDuckDBJDBC.java @@ -2714,11 +2714,12 @@ public static void test_appender_null_integer() throws Exception { } public static void test_appender_Boolean() throws Exception { - try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); Statement stmt = conn.createStatement();) { + try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); + Statement stmt = conn.createStatement();) { stmt.execute("CREATE TABLE data (a BOOLEAN)"); DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); - Boolean[] values = new Boolean[] { Boolean.TRUE, Boolean.FALSE, null}; + Boolean[] values = new Boolean[] {Boolean.TRUE, Boolean.FALSE, null}; for (Boolean value : values) { appender.beginRow(); appender.append(value); @@ -2742,9 +2743,9 @@ public static void test_appender_Boolean() throws Exception { } } - public static void test_appender_Integer() throws Exception { - try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); Statement stmt = conn.createStatement();) { + try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); + Statement stmt = conn.createStatement();) { stmt.execute("CREATE TABLE data (a INTEGER)"); DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); @@ -2766,7 +2767,8 @@ public static void test_appender_Integer() throws Exception { } public static void test_appender_Long() throws Exception { - try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); Statement stmt = conn.createStatement();) { + try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); + Statement stmt = conn.createStatement();) { stmt.execute("CREATE TABLE data (a LONG)"); DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data"); @@ -2788,7 +2790,8 @@ public static void test_appender_Long() throws Exception { } public static void test_appender_Short() throws Exception { - try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); Statement stmt = conn.createStatement();) { + try (DuckDBConnection conn = DriverManager.getConnection(JDBC_URL).unwrap(DuckDBConnection.class); + Statement stmt = conn.createStatement();) { stmt.execute("CREATE TABLE data (a SHORT)"); DuckDBAppender appender = conn.createAppender(DuckDBConnection.DEFAULT_SCHEMA, "data");