From commits-return-70571-archive-asf-public=cust-asf.ponee.io@camel.apache.org Mon Mar 11 07:15:49 2019 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id 1A31E180657 for ; Mon, 11 Mar 2019 08:15:48 +0100 (CET) Received: (qmail 81819 invoked by uid 500); 11 Mar 2019 07:15:47 -0000 Mailing-List: contact commits-help@camel.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@camel.apache.org Delivered-To: mailing list commits@camel.apache.org Received: (qmail 81810 invoked by uid 99); 11 Mar 2019 07:15:47 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 11 Mar 2019 07:15:47 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id 22A5B879A8; Mon, 11 Mar 2019 07:15:47 +0000 (UTC) Date: Mon, 11 Mar 2019 07:15:46 +0000 To: "commits@camel.apache.org" Subject: [camel] branch camel-2.x updated: [CAMEL-13305] camel-sql cannot resolve nested simple expression MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Message-ID: <155228854567.7746.9789243483155756333@gitbox.apache.org> From: acosentino@apache.org X-Git-Host: gitbox.apache.org X-Git-Repo: camel X-Git-Refname: refs/heads/camel-2.x X-Git-Reftype: branch X-Git-Oldrev: c4bc06042a1487dd937f2101308a8d72c3f4af76 X-Git-Newrev: 9103385906df175ac2fb7c6f8ef916171f9f486c X-Git-Rev: 9103385906df175ac2fb7c6f8ef916171f9f486c X-Git-NotificationType: ref_changed_plus_diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated 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 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); + } + +}