diff --git a/doc/changes/changelog.md b/doc/changes/changelog.md
index 3a9335b..b9d17d2 100644
--- a/doc/changes/changelog.md
+++ b/doc/changes/changelog.md
@@ -1,5 +1,6 @@
# Changes
+* [0.6.20](changes_0.6.20.md)
* [0.6.19](changes_0.6.19.md)
* [0.6.18](changes_0.6.18.md)
* [0.6.17](changes_0.6.17.md)
diff --git a/doc/changes/changes_0.6.20.md b/doc/changes/changes_0.6.20.md
new file mode 100644
index 0000000..42b191f
--- /dev/null
+++ b/doc/changes/changes_0.6.20.md
@@ -0,0 +1,14 @@
+# Udf Debugging Java 0.6.20, released 2026-07-16
+
+Code name: Code Coverage > 80%
+
+## Summary
+
+In this release we fixed Sonar findings and raised the code coverage ot over 80%.
+
+We added an integration test for `PushDownTesting`.
+
+## Features
+
+* Fixed Sonar findings and raised test coverage. (PR #86)
+
diff --git a/pk_generated_parent.pom b/pk_generated_parent.pom
index dff9fa9..d776ad2 100644
--- a/pk_generated_parent.pom
+++ b/pk_generated_parent.pom
@@ -3,7 +3,7 @@
4.0.0
com.exasol
udf-debugging-java-generated-parent
- 0.6.19
+ 0.6.20
pom
UTF-8
diff --git a/pom.xml b/pom.xml
index b88de7a..685740a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
4.0.0
udf-debugging-java
- 0.6.19
+ 0.6.20
udf-debugging-java
Utilities for debugging, profiling and code coverage measure for UDFs.
https://github.com/exasol/udf-debugging-java/
@@ -147,7 +147,7 @@
udf-debugging-java-generated-parent
com.exasol
- 0.6.19
+ 0.6.20
pk_generated_parent.pom
diff --git a/src/main/java/com/exasol/udfdebugging/PushDownTesting.java b/src/main/java/com/exasol/udfdebugging/PushDownTesting.java
index f09f147..724b132 100644
--- a/src/main/java/com/exasol/udfdebugging/PushDownTesting.java
+++ b/src/main/java/com/exasol/udfdebugging/PushDownTesting.java
@@ -21,9 +21,10 @@ private PushDownTesting() {
* @return generated push down query
* @throws SQLException if execution fails
*/
+ @SuppressWarnings("java:S2077") // Constructed SQL only used in tests.
public static String getPushDownSql(final Statement statement, final String query) throws SQLException {
try (final ResultSet pushDownSqlResult = statement
- .executeQuery("SELECT PUSHDOWN_SQL FROM (EXPLAIN VIRTUAL " + query + ");")) {
+ .executeQuery("SELECT PUSHDOWN_SQL FROM (EXPLAIN VIRTUAL " + query + ")")) {
pushDownSqlResult.next();
return pushDownSqlResult.getString("PUSHDOWN_SQL");
}
@@ -37,10 +38,11 @@ public static String getPushDownSql(final Statement statement, final String quer
* @return selection (where clause)
* @throws SQLException if SQL statement fails
*/
+ @SuppressWarnings("java:S2077") // Constructed SQL only used in tests.
public static String getSelectionThatIsSentToTheAdapter(final Statement statement, final String query)
throws SQLException {
try (final ResultSet pushDownSqlResult = statement
- .executeQuery("SELECT PUSHDOWN_JSON FROM (EXPLAIN VIRTUAL " + query + ");")) {
+ .executeQuery("SELECT PUSHDOWN_JSON FROM (EXPLAIN VIRTUAL " + query + ")")) {
pushDownSqlResult.next();
final String pushdownJson = pushDownSqlResult.getString("PUSHDOWN_JSON");
try (final JsonReader reader = Json.createReader(new StringReader(pushdownJson))) {
diff --git a/src/test/java/com/exasol/udfdebugging/PushDownTestingIT.java b/src/test/java/com/exasol/udfdebugging/PushDownTestingIT.java
new file mode 100644
index 0000000..834c65c
--- /dev/null
+++ b/src/test/java/com/exasol/udfdebugging/PushDownTestingIT.java
@@ -0,0 +1,69 @@
+package com.exasol.udfdebugging;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.junit.jupiter.api.Test;
+
+import com.exasol.udfdebugging.modules.TestSetup;
+
+class PushDownTestingIT {
+ private static final String VS_SCHEMA = "VS_SCHEMA";
+ private static final String VS_ADAPTER = VS_SCHEMA + ".VS_ADAPTER";
+ private static final String VIRTUAL_SCHEMA_NAME = "TEST_VS";
+ private static final String TABLE_NAME = "THE_TABLE";
+
+ private static String loadAdapterScriptContent() {
+ try (InputStream adapterScriptStream = PushDownTestingIT.class.getClassLoader()
+ .getResourceAsStream("virtual_schema_stub.lua")) {
+ if (adapterScriptStream == null) {
+ throw new AssertionError("Failed to find adapter script resource on the classpath.");
+ }
+ return new String(adapterScriptStream.readAllBytes(), StandardCharsets.UTF_8);
+ } catch (IOException exception) {
+ throw new AssertionError("Failed to read adapter script resource.", exception);
+ }
+ }
+
+
+ @Test
+ void testGetPushDownSqlFromExplainVirtual() throws SQLException {
+ try (
+ final TestSetup testSetup = new TestSetup();
+ final Statement statement = testSetup.getConnection().createStatement()
+ ) {
+ createVirtualSchema(statement);
+ final String pushDownSql = PushDownTesting.getPushDownSql(statement,
+ "SELECT THE_VALUE FROM " + VIRTUAL_SCHEMA_NAME + "." + TABLE_NAME);
+ assertThat(pushDownSql, equalTo("SELECT 'Hello VS!'"));
+ }
+ }
+
+ @Test
+ void testGetSelectionThatIsSentToTheAdapter() throws SQLException {
+ try (
+ final TestSetup testSetup = new TestSetup();
+ final Statement statement = testSetup.getConnection().createStatement()
+ ) {
+ createVirtualSchema(statement);
+ final String pushDownSql = PushDownTesting.getSelectionThatIsSentToTheAdapter(statement,
+ "SELECT THE_VALUE FROM " + VIRTUAL_SCHEMA_NAME + "." + TABLE_NAME
+ + " WHERE THE_VALUE = 'something'");
+ assertThat(pushDownSql, equalTo(TABLE_NAME +".THE_VALUE='something'"));
+ }
+ }
+
+ private void createVirtualSchema(final Statement statement) throws SQLException {
+ statement.execute("DROP SCHEMA IF EXISTS " + VS_SCHEMA + "CASCADE");
+ statement.execute("CREATE SCHEMA " + VS_SCHEMA);
+ statement.execute("CREATE TABLE ORIGIN_TABLE(THE_VALUE CHAR(9))");
+ statement.execute("CREATE LUA ADAPTER SCRIPT " + VS_ADAPTER + " AS\n" + loadAdapterScriptContent() + "\n/");
+ statement.execute("CREATE VIRTUAL SCHEMA " + VIRTUAL_SCHEMA_NAME + " USING " + VS_ADAPTER);
+ }
+}
diff --git a/src/test/resources/virtual_schema_stub.lua b/src/test/resources/virtual_schema_stub.lua
new file mode 100644
index 0000000..5d62432
--- /dev/null
+++ b/src/test/resources/virtual_schema_stub.lua
@@ -0,0 +1,61 @@
+-- A minimal Lua virtual schema that allows testing VS interaction.
+local cjson = require("cjson");
+
+function report_schema()
+ return {
+ schemaMetadata = {
+ tables = {
+ {
+ name = "THE_TABLE",
+ columns = {
+ {
+ name = "THE_VALUE",
+ dataType = {
+ type = "CHAR",
+ size = 9
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+end
+
+function report_capabilities()
+ return {
+ capabilities = { "SELECTLIST_PROJECTION", "FILTER_EXPRESSIONS", "FN_PRED_EQUAL", "LITERAL_STRING" }
+ }
+end
+
+function pushdown(request)
+ if (request.filter == nil) then
+ return {
+ type = "select",
+ sql = "SELECT 'Hello VS!'"
+ }
+ else
+ return {
+ type = "select",
+ sql = "SELECT 'Hello VS!' FROM VS_SCHEMA.ORIGIN_TABLE WHERE THE_VALUE = 'something'"
+ }
+ end
+end
+
+function adapter_call(request_as_json)
+ local request = cjson.decode(request_as_json)
+ local response;
+ if request.type == "createVirtualSchema" or request.type == "refresh" then
+ response = report_schema()
+ elseif request.type == "dropVirtualSchema" or request.type == "setProperties" then
+ response = {}
+ elseif request.type == "getCapabilities" then
+ response = report_capabilities()
+ elseif request.type == "pushdown" then
+ response = pushdown(request.pushdownRequest)
+ else
+ error("Unsupported adapter request: " .. (request.type or "'nil'"))
+ end
+ response.type = request.type
+ return cjson.encode(response)
+end
\ No newline at end of file