diff --git a/build.gradle b/build.gradle index fea0ce21..d6549cf3 100644 --- a/build.gradle +++ b/build.gradle @@ -67,9 +67,6 @@ subprojects { // Logs compileOnly'org.slf4j:slf4j-api' - - //SQL named parameters binding - implementation group: 'org.httprpc', name: 'httprpc', version: '5.9' } } diff --git a/plugin-jdbc/src/main/java/io/kestra/plugin/jdbc/AbstractJdbcQueries.java b/plugin-jdbc/src/main/java/io/kestra/plugin/jdbc/AbstractJdbcQueries.java index 9b43e083..5e645ed1 100644 --- a/plugin-jdbc/src/main/java/io/kestra/plugin/jdbc/AbstractJdbcQueries.java +++ b/plugin-jdbc/src/main/java/io/kestra/plugin/jdbc/AbstractJdbcQueries.java @@ -1,11 +1,11 @@ package io.kestra.plugin.jdbc; +import io.kestra.core.exceptions.IllegalVariableEvaluationException; import io.kestra.core.models.executions.metrics.Counter; import io.kestra.core.models.property.Property; import io.kestra.core.runners.RunContext; import lombok.*; import lombok.experimental.SuperBuilder; -import org.httprpc.sql.Parameters; import org.slf4j.Logger; import java.sql.*; @@ -13,6 +13,8 @@ import java.util.List; import java.util.Map; import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; @SuperBuilder @ToString @@ -31,6 +33,7 @@ public AbstractJdbcQueries.MultiQueryOutput run(RunContext runContext) throws Ex final boolean isTransactional = this.transaction.as(runContext, Boolean.class); Connection conn = null; + PreparedStatement stmt = null; Savepoint savepoint = null; try { //Create connection in not autocommit mode to enable rollback on error @@ -42,17 +45,7 @@ public AbstractJdbcQueries.MultiQueryOutput run(RunContext runContext) throws Ex String sqlRendered = runContext.render(this.sql, this.additionalVars); - //Inject named parameters (ex: ':param') - Parameters namedParams = Parameters.parse(sqlRendered); - PreparedStatement stmt = conn.prepareStatement(namedParams.getSQL(), ResultSet.TYPE_FORWARD_ONLY, - ResultSet.CONCUR_READ_ONLY); - - Map namedParamsRendered = this.getParameters() == null ? null : this.getParameters().asMap(runContext, String.class, Object.class); - if(namedParamsRendered != null && !namedParamsRendered.isEmpty()) { - namedParams.putAll(namedParamsRendered); - namedParams.apply(stmt); - } - + stmt = createPreparedStatementAndPopulateParameters(runContext, conn, sqlRendered); stmt.setFetchSize(this.getFetchSize()); @@ -87,9 +80,8 @@ public AbstractJdbcQueries.MultiQueryOutput run(RunContext runContext) throws Ex } throw new RuntimeException(e); } finally { - if(conn != null) { - conn.close(); - } + if(conn != null) { conn.close(); } + if(stmt != null) { stmt.close(); } } } @@ -111,4 +103,34 @@ protected long fetch(Statement stmt, ResultSet rs, Consumer> public static class MultiQueryOutput implements io.kestra.core.models.tasks.Output { List outputs; } + + private PreparedStatement createPreparedStatementAndPopulateParameters(RunContext runContext, Connection conn, String sql) throws SQLException, IllegalVariableEvaluationException { + //Inject named parameters (ex: ':param') + Map namedParamsRendered = this.getParameters() == null ? null : this.getParameters().asMap(runContext, String.class, Object.class); + + if(namedParamsRendered == null || namedParamsRendered.isEmpty()) { + return conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + } + + //Extract parameters in orders and replace them with '?' + String preparedSql = new String(sql); + Pattern pattern = Pattern.compile(" :\\w+"); + Matcher matcher = pattern.matcher(preparedSql); + + List params = new LinkedList<>(); + + while (matcher.find()) { + String param = matcher.group(); + params.add(param.substring(2)); + preparedSql = matcher.replaceFirst( " ?"); + matcher = pattern.matcher(preparedSql); + } + PreparedStatement stmt = conn.prepareStatement(preparedSql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + + for(int i=0; i