This is an automated email from the ASF dual-hosted git repository.
acosentino pushed a commit to branch camel-2.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-2.x by this push:
new 9103385 [CAMEL-13305] camel-sql cannot resolve nested simple expression
9103385 is described below
commit 9103385906df175ac2fb7c6f8ef916171f9f486c
Author: rnetuka <rnetuka@redhat.com>
AuthorDate: Tue Mar 5 14:35:52 2019 +0100
[CAMEL-13305] camel-sql cannot resolve nested simple expression
---
.../sql/DefaultSqlPrepareStatementStrategy.java | 79 +++++++++++++++++++++-
.../DefaultSqlPrepareStatementStrategyTest.java | 37 ++++++++++
2 files changed, 114 insertions(+), 2 deletions(-)
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultSqlPrepareStatementStrategy.java
b/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultSqlPrepareStatementStrategy.java
index cc64fda..0e42b95 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultSqlPrepareStatementStrategy.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultSqlPrepareStatementStrategy.java
@@ -82,7 +82,7 @@ public class DefaultSqlPrepareStatementStrategy implements SqlPrepareStatementSt
}
}
// replace all :?word and :?${foo} with just ?
- answer = REPLACE_PATTERN.matcher(query).replaceAll("\\?");
+ answer = replaceParams(query);
} else {
answer = query;
}
@@ -91,6 +91,56 @@ public class DefaultSqlPrepareStatementStrategy implements SqlPrepareStatementSt
return answer;
}
+ private String replaceParams(String query) {
+ // nested parameters are not replaced properly just by the REPLACE_PATTERN
+ // for example ":?${array[${index}]}"
+ query = replaceBracketedParams(query);
+ return REPLACE_PATTERN.matcher(query).replaceAll("\\?");
+ }
+
+ private String replaceBracketedParams(String query) {
+ while (query.contains(":?${")) {
+ int i = query.indexOf(":?${");
+ int j = findClosingBracket(query, i + 3);
+
+ if (j == -1) {
+ throw new IllegalArgumentException("String doesn't have equal opening and
closing brackets: " + query);
+ }
+
+ query = query.substring(0, i) + "?" + query.substring(j + 1);
+ }
+ return query;
+ }
+
+ /**
+ * Finds closing bracket in text for named parameter.
+ *
+ * @param text
+ * @param openPosition
+ * position of the opening bracket
+ *
+ * @return index of corresponding closing bracket, or -1, if none was found
+ */
+ private static int findClosingBracket(String text, int openPosition) {
+ if (text.charAt(openPosition) != '{') {
+ throw new IllegalArgumentException("Character at specified position is not an
open bracket");
+ }
+
+ int remainingClosingBrackets = 0;
+
+ for (int i = openPosition; i < text.length(); i++) {
+ if (text.charAt(i) == '{') {
+ remainingClosingBrackets++;
+ } else if (text.charAt(i) == '}') {
+ remainingClosingBrackets--;
+ }
+ if (remainingClosingBrackets == 0) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
@Override
public Iterator<?> createPopulateIterator(final String query, final String preparedQuery,
final int expectedParams, final Exchange exchange,
final Object value) throws SQLException {
@@ -166,15 +216,40 @@ public class DefaultSqlPrepareStatementStrategy implements SqlPrepareStatementSt
private static final class NamedQueryParser {
+ private final String query;
private final Matcher matcher;
private NamedQueryParser(String query) {
+ this.query = query;
this.matcher = NAME_PATTERN.matcher(query);
}
public String next() {
if (matcher.find()) {
- return matcher.group(1);
+ String param = matcher.group(1);
+
+ int openingBrackets = 0;
+ int closingBrackets = 0;
+ for (int i = 0; i < param.length(); i++) {
+ if (param.charAt(i) == '{') {
+ openingBrackets++;
+ }
+ if (param.charAt(i) == '}') {
+ closingBrackets++;
+ }
+ }
+ if (openingBrackets != closingBrackets) {
+ // nested parameters are not found properly by the NAME_PATTERN
+ // for example param ":?${array[?${index}]}"
+ // is detected as "${array[?${index}"
+ // we have to find correct closing bracket manually
+ String querySubstring = query.substring(matcher.start());
+ int i = querySubstring.indexOf('{');
+ int j = findClosingBracket(querySubstring, i);
+ param = "$" + querySubstring.substring(i, j + 1);
+ }
+
+ return param;
}
return null;
diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/DefaultSqlPrepareStatementStrategyTest.java
b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/DefaultSqlPrepareStatementStrategyTest.java
new file mode 100644
index 0000000..63318f0
--- /dev/null
+++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/DefaultSqlPrepareStatementStrategyTest.java
@@ -0,0 +1,37 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.sql.stored;
+
+import java.sql.SQLException;
+import org.apache.camel.component.sql.DefaultSqlPrepareStatementStrategy;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class DefaultSqlPrepareStatementStrategyTest {
+
+ @Test
+ public void testReplaceNestedExpressions() throws SQLException {
+ DefaultSqlPrepareStatementStrategy strategy = new DefaultSqlPrepareStatementStrategy();
+ String sql = "INSERT INTO example VALUES (:?${array[${index}]})";
+
+ String expected = "INSERT INTO example VALUES (?)";
+ String query = strategy.prepareQuery(sql, true, null);
+ assertEquals(expected, query);
+ }
+
+}
|