You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2018/02/09 07:47:05 UTC

[camel] branch master updated (fae2179 -> ff245e1)

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git.


    from fae2179  CAMEL-12248 - Camel-Milo: Upgrade Milo to version 0.2.0 - Karaf feature
     new 2f08dab  CAMEL-12212 sql-stored: support INOUT parameters
     new ff245e1  CAMEL-12212 sql-stored: support INOUT parameters (docs)

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../src/main/docs/sql-stored-component.adoc        |  57 +-
 .../BatchCallableStatementCreatorFactory.java      |   6 +-
 .../sql/stored/CallableStatementWrapper.java       |   4 +-
 .../sql/stored/TemplateStoredProcedure.java        |  32 +-
 .../sql/stored/template/TemplateParser.java        |   5 +-
 .../{InputParameter.java => InOutParameter.java}   |  41 +-
 .../ast/{InputParameter.java => InParameter.java}  |  21 +-
 .../stored/template/generated/ParseException.java  | 315 ++++----
 .../sql/stored/template/generated/SSPTParser.java  |  90 ++-
 .../template/generated/SSPTParserConstants.java    |  29 +-
 .../template/generated/SSPTParserTokenManager.java | 176 +++--
 .../template/generated/SimpleCharStream.java       | 854 +++++++++++----------
 .../sql/stored/template/generated/Token.java       | 228 +++---
 .../stored/template/generated/TokenMgrError.java   | 241 +++---
 .../component/sql/stored/template/grammar/sspt.jj  |  30 +-
 .../camel/component/sql/stored/ParserTest.java     |  61 +-
 .../{ProducerTest.java => ProducerInOutTest.java}  |  17 +-
 .../component/sql/stored/TestStoredProcedure.java  |   7 +-
 .../src/test/resources/sql/storedProcedureTest.sql |   6 +
 19 files changed, 1220 insertions(+), 1000 deletions(-)
 copy components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/{InputParameter.java => InOutParameter.java} (74%)
 rename components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/{InputParameter.java => InParameter.java} (78%)
 copy components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/{ProducerTest.java => ProducerInOutTest.java} (82%)

-- 
To stop receiving notification emails like this one, please contact
davsclaus@apache.org.

[camel] 01/02: CAMEL-12212 sql-stored: support INOUT parameters

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 2f08dab593599c1428bae9b17be3616961735cb4
Author: Brett Meyer <br...@3riverdev.com>
AuthorDate: Wed Feb 7 16:09:50 2018 -0500

    CAMEL-12212 sql-stored: support INOUT parameters
---
 .../BatchCallableStatementCreatorFactory.java      |   6 +-
 .../sql/stored/CallableStatementWrapper.java       |   4 +-
 .../sql/stored/TemplateStoredProcedure.java        |  32 +-
 .../sql/stored/template/TemplateParser.java        |   5 +-
 .../{InputParameter.java => InOutParameter.java}   |  41 +-
 .../ast/{InputParameter.java => InParameter.java}  |  21 +-
 .../stored/template/generated/ParseException.java  | 315 ++++----
 .../sql/stored/template/generated/SSPTParser.java  |  90 ++-
 .../template/generated/SSPTParserConstants.java    |  29 +-
 .../template/generated/SSPTParserTokenManager.java | 176 +++--
 .../template/generated/SimpleCharStream.java       | 854 +++++++++++----------
 .../sql/stored/template/generated/Token.java       | 228 +++---
 .../stored/template/generated/TokenMgrError.java   | 241 +++---
 .../component/sql/stored/template/grammar/sspt.jj  |  30 +-
 .../camel/component/sql/stored/ParserTest.java     |  61 +-
 .../component/sql/stored/ProducerInOutTest.java    |  85 ++
 .../component/sql/stored/TestStoredProcedure.java  |   7 +-
 .../src/test/resources/sql/storedProcedureTest.sql |   6 +
 18 files changed, 1257 insertions(+), 974 deletions(-)

diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/BatchCallableStatementCreatorFactory.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/BatchCallableStatementCreatorFactory.java
index 24d087a..59c4e17 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/BatchCallableStatementCreatorFactory.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/BatchCallableStatementCreatorFactory.java
@@ -22,7 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.camel.component.sql.stored.template.ast.InputParameter;
+import org.apache.camel.component.sql.stored.template.ast.InParameter;
 import org.apache.camel.component.sql.stored.template.ast.Template;
 import org.springframework.jdbc.core.CallableStatementCreator;
 import org.springframework.jdbc.core.CallableStatementCreatorFactory;
@@ -73,8 +73,8 @@ public class BatchCallableStatementCreatorFactory {
         List<SqlParameter> params = new ArrayList<>();
 
         for (Object parameter : template.getParameterList()) {
-            if (parameter instanceof InputParameter) {
-                InputParameter inputParameter = (InputParameter) parameter;
+            if (parameter instanceof InParameter) {
+                InParameter inputParameter = (InParameter) parameter;
 
                 SqlParameter sqlParameter;
                 if (inputParameter.getScale() != null) {
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapper.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapper.java
index 2693b0a..be13a0b 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapper.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapper.java
@@ -26,7 +26,7 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.camel.Exchange;
-import org.apache.camel.component.sql.stored.template.ast.InputParameter;
+import org.apache.camel.component.sql.stored.template.ast.InParameter;
 import org.springframework.dao.DataAccessException;
 import org.springframework.jdbc.core.CallableStatementCallback;
 import org.springframework.jdbc.core.CallableStatementCreator;
@@ -116,7 +116,7 @@ public class CallableStatementWrapper implements StatementWrapper {
         Map<String, Object> batchValues = new HashMap<>();
         //only IN-parameters supported by template
         for (Object param : this.batchFactory.getTemplate().getParameterList()) {
-            InputParameter inputParameter = (InputParameter) param;
+            InParameter inputParameter = (InParameter) param;
             Object paramValue = inputParameter.getValueExtractor().eval(exchange, value);
             batchValues.put(inputParameter.getName(), paramValue);
         }
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/TemplateStoredProcedure.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/TemplateStoredProcedure.java
index 3ee4614..cc15041 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/TemplateStoredProcedure.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/TemplateStoredProcedure.java
@@ -22,12 +22,14 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.camel.Exchange;
-import org.apache.camel.component.sql.stored.template.ast.InputParameter;
+import org.apache.camel.component.sql.stored.template.ast.InOutParameter;
+import org.apache.camel.component.sql.stored.template.ast.InParameter;
 import org.apache.camel.component.sql.stored.template.ast.OutParameter;
 import org.apache.camel.component.sql.stored.template.ast.Template;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.SqlInOutParameter;
 import org.springframework.jdbc.core.SqlOutParameter;
 import org.springframework.jdbc.core.SqlParameter;
 import org.springframework.jdbc.object.StoredProcedure;
@@ -38,7 +40,8 @@ public class TemplateStoredProcedure extends StoredProcedure {
 
     private final Template template;
 
-    private List<InputParameter> inputParameterList = new ArrayList<>();
+    private List<InParameter> inParameterList = new ArrayList<>();
+    private List<InOutParameter> inOutParameterList = new ArrayList<>();
 
     public TemplateStoredProcedure(JdbcTemplate jdbcTemplate, Template template, boolean function) {
         this.template = template;
@@ -48,8 +51,8 @@ public class TemplateStoredProcedure extends StoredProcedure {
         setSql(template.getProcedureName());
 
         for (Object parameter : template.getParameterList()) {
-            if (parameter instanceof InputParameter) {
-                InputParameter inputParameter = (InputParameter) parameter;
+            if (parameter instanceof InParameter) {
+                InParameter inputParameter = (InParameter) parameter;
                 SqlParameter sqlParameter;
                 if (inputParameter.getScale() != null) {
                     sqlParameter = new SqlParameter(inputParameter.getName(), inputParameter.getSqlType(), inputParameter.getScale());
@@ -60,8 +63,20 @@ public class TemplateStoredProcedure extends StoredProcedure {
                 }
 
                 declareParameter(sqlParameter);
-                inputParameterList.add(inputParameter);
+                inParameterList.add(inputParameter);
+            } else if (parameter instanceof InOutParameter) {
+                InOutParameter inOutParameter = (InOutParameter) parameter;
+                SqlInOutParameter sqlInOutParameter;
+                if (inOutParameter.getScale() != null) {
+                    sqlInOutParameter = new SqlInOutParameter(inOutParameter.getOutValueMapKey(), inOutParameter.getSqlType(), inOutParameter.getScale());
+                } else if (inOutParameter.getTypeName() != null) {
+                    sqlInOutParameter = new SqlInOutParameter(inOutParameter.getOutValueMapKey(), inOutParameter.getSqlType(), inOutParameter.getTypeName());
+                } else {
+                    sqlInOutParameter = new SqlInOutParameter(inOutParameter.getOutValueMapKey(), inOutParameter.getSqlType());
+                }
 
+                declareParameter(sqlInOutParameter);
+                inOutParameterList.add(inOutParameter);
             } else if (parameter instanceof OutParameter) {
                 OutParameter outParameter = (OutParameter) parameter;
                 SqlOutParameter sqlOutParameter;
@@ -84,8 +99,11 @@ public class TemplateStoredProcedure extends StoredProcedure {
     public Map execute(Exchange exchange, Object rowData) {
         Map<String, Object> params = new HashMap<>();
 
-        for (InputParameter inputParameter : inputParameterList) {
-            params.put(inputParameter.getName(), inputParameter.getValueExtractor().eval(exchange, rowData));
+        for (InParameter inParameter : inParameterList) {
+            params.put(inParameter.getName(), inParameter.getValueExtractor().eval(exchange, rowData));
+        }
+        for (InOutParameter inOutParameter : inOutParameterList) {
+            params.put(inOutParameter.getOutValueMapKey(), inOutParameter.getValueExtractor().eval(exchange, rowData));
         }
 
         LOG.debug("Invoking stored procedure: {}", template.getProcedureName());
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateParser.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateParser.java
index f5632ad..727513a 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateParser.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateParser.java
@@ -18,7 +18,6 @@ package org.apache.camel.component.sql.stored.template;
 
 import java.io.StringReader;
 
-import org.apache.camel.CamelContext;
 import org.apache.camel.component.sql.stored.template.ast.ParseRuntimeException;
 import org.apache.camel.component.sql.stored.template.ast.Template;
 import org.apache.camel.component.sql.stored.template.generated.ParseException;
@@ -38,9 +37,7 @@ public class TemplateParser {
     public Template parseTemplate(String template) {
         try {
             SSPTParser parser = new SSPTParser(new StringReader(template), classResolver);
-            Template ret = validate(parser.parse());
-
-            return ret;
+            return validate(parser.parse());
 
         } catch (ParseException parseException) {
             throw new ParseRuntimeException(parseException);
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InputParameter.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InOutParameter.java
similarity index 74%
copy from components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InputParameter.java
copy to components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InOutParameter.java
index 2fcbff0..2028902 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InputParameter.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InOutParameter.java
@@ -18,26 +18,25 @@ package org.apache.camel.component.sql.stored.template.ast;
 
 import java.util.Map;
 
-import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
 import org.apache.camel.builder.ExpressionBuilder;
 import org.apache.camel.component.sql.stored.template.generated.SSPTParserConstants;
 import org.apache.camel.component.sql.stored.template.generated.Token;
 
-public class InputParameter {
+public class InOutParameter {
 
-    private final String name;
     private final String typeName;
     private final int sqlType;
     private final Integer scale;
     private ValueExtractor valueExtractor;
+    private String outValueMapKey;
 
-    public InputParameter(String name, int sqlType, Token valueSrcToken, Integer scale, String typeName) {
-        this.name = name;
+    public InOutParameter(int sqlType, Token valueSrcToken, Integer scale, String typeName, String outValueMapKey) {
         this.sqlType = sqlType;
         parseValueExpression(valueSrcToken);
         this.scale = scale;
         this.typeName = typeName;
+        this.outValueMapKey = outValueMapKey;
 
         if (this.scale != null && this.typeName != null) {
             throw new ParseRuntimeException(String.format("Both scale=%s and typeName=%s cannot be set", this.scale, this.typeName));
@@ -47,34 +46,14 @@ public class InputParameter {
     private void parseValueExpression(Token valueSrcToken) {
         if (SSPTParserConstants.SIMPLE_EXP_TOKEN == valueSrcToken.kind) {
             final Expression exp = ExpressionBuilder.simpleExpression(valueSrcToken.toString());
-            this.valueExtractor = new ValueExtractor() {
-
-                @Override
-                public Object eval(Exchange exchange, Object container) {
-                    return exp.evaluate(exchange, Object.class);
-                }
-            };
+            this.valueExtractor = (exchange, container) -> exp.evaluate(exchange, Object.class);
         } else if (SSPTParserConstants.PARAMETER_POS_TOKEN == valueSrcToken.kind) {
-
             //remove leading :#
             final String mapKey = valueSrcToken.toString().substring(2);
-            this.valueExtractor = new ValueExtractor() {
-                @Override
-                public Object eval(Exchange exchange, Object container) {
-                    return ((Map) container).get(mapKey);
-                }
-            };
+            this.valueExtractor = (exchange, container) -> ((Map) container).get(mapKey);
         }
     }
 
-    public Integer getScale() {
-        return scale;
-    }
-
-    public String getName() {
-        return name;
-    }
-
     public String getTypeName() {
         return typeName;
     }
@@ -83,7 +62,15 @@ public class InputParameter {
         return sqlType;
     }
 
+    public Integer getScale() {
+        return scale;
+    }
+
     public ValueExtractor getValueExtractor() {
         return valueExtractor;
     }
+
+    public String getOutValueMapKey() {
+        return outValueMapKey;
+    }
 }
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InputParameter.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InParameter.java
similarity index 78%
rename from components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InputParameter.java
rename to components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InParameter.java
index 2fcbff0..62e123b 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InputParameter.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InParameter.java
@@ -18,13 +18,12 @@ package org.apache.camel.component.sql.stored.template.ast;
 
 import java.util.Map;
 
-import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
 import org.apache.camel.builder.ExpressionBuilder;
 import org.apache.camel.component.sql.stored.template.generated.SSPTParserConstants;
 import org.apache.camel.component.sql.stored.template.generated.Token;
 
-public class InputParameter {
+public class InParameter {
 
     private final String name;
     private final String typeName;
@@ -32,7 +31,7 @@ public class InputParameter {
     private final Integer scale;
     private ValueExtractor valueExtractor;
 
-    public InputParameter(String name, int sqlType, Token valueSrcToken, Integer scale, String typeName) {
+    public InParameter(String name, int sqlType, Token valueSrcToken, Integer scale, String typeName) {
         this.name = name;
         this.sqlType = sqlType;
         parseValueExpression(valueSrcToken);
@@ -47,23 +46,11 @@ public class InputParameter {
     private void parseValueExpression(Token valueSrcToken) {
         if (SSPTParserConstants.SIMPLE_EXP_TOKEN == valueSrcToken.kind) {
             final Expression exp = ExpressionBuilder.simpleExpression(valueSrcToken.toString());
-            this.valueExtractor = new ValueExtractor() {
-
-                @Override
-                public Object eval(Exchange exchange, Object container) {
-                    return exp.evaluate(exchange, Object.class);
-                }
-            };
+            this.valueExtractor = (exchange, container) -> exp.evaluate(exchange, Object.class);
         } else if (SSPTParserConstants.PARAMETER_POS_TOKEN == valueSrcToken.kind) {
-
             //remove leading :#
             final String mapKey = valueSrcToken.toString().substring(2);
-            this.valueExtractor = new ValueExtractor() {
-                @Override
-                public Object eval(Exchange exchange, Object container) {
-                    return ((Map) container).get(mapKey);
-                }
-            };
+            this.valueExtractor = (exchange, container) -> ((Map) container).get(mapKey);
         }
     }
 
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/ParseException.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/ParseException.java
index 5e1fe55..30e4737 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/ParseException.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/ParseException.java
@@ -13,168 +13,175 @@ package org.apache.camel.component.sql.stored.template.generated;
  */
 public class ParseException extends Exception {
 
-    /**
-     * The version identifier for this Serializable class.
-     * Increment only if the <i>serialized</i> form of the
-     * class changes.
-     */
-    private static final long serialVersionUID = 1L;
-    /**
-     * This is the last token that has been consumed successfully.  If
-     * this object has been created due to a parse error, the token
-     * followng this token will (therefore) be the first error token.
-     */
-    public Token currentToken;
-    /**
-     * Each entry in this array is an array of integers.  Each array
-     * of integers represents a sequence of tokens (by their ordinal
-     * values) that is expected at this point of the parse.
-     */
-    public int[][] expectedTokenSequences;
-    /**
-     * This is a reference to the "tokenImage" array of the generated
-     * parser within which the parse error occurred.  This array is
-     * defined in the generated ...Constants interface.
-     */
-    public String[] tokenImage;
-    /**
-     * The end of line string for this machine.
-     */
-    protected String eol = System.getProperty("line.separator", "\n");
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
 
-    /**
-     * This constructor is used by the method "generateParseException"
-     * in the generated parser.  Calling this constructor generates
-     * a new object of this type with the fields "currentToken",
-     * "expectedTokenSequences", and "tokenImage" set.
-     */
-    public ParseException(Token currentTokenVal,
-                          int[][] expectedTokenSequencesVal,
-                          String[] tokenImageVal
-    ) {
-        super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
-        currentToken = currentTokenVal;
-        expectedTokenSequences = expectedTokenSequencesVal;
-        tokenImage = tokenImageVal;
-    }
+  /**
+   * This constructor is used by the method "generateParseException"
+   * in the generated parser.  Calling this constructor generates
+   * a new object of this type with the fields "currentToken",
+   * "expectedTokenSequences", and "tokenImage" set.
+   */
+  public ParseException(Token currentTokenVal,
+                        int[][] expectedTokenSequencesVal,
+                        String[] tokenImageVal
+                       )
+  {
+    super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
+    currentToken = currentTokenVal;
+    expectedTokenSequences = expectedTokenSequencesVal;
+    tokenImage = tokenImageVal;
+  }
 
-    /**
-     * The following constructors are for use by you for whatever
-     * purpose you can think of.  Constructing the exception in this
-     * manner makes the exception behave in the normal way - i.e., as
-     * documented in the class "Throwable".  The fields "errorToken",
-     * "expectedTokenSequences", and "tokenImage" do not contain
-     * relevant information.  The JavaCC generated code does not use
-     * these constructors.
-     */
+  /**
+   * The following constructors are for use by you for whatever
+   * purpose you can think of.  Constructing the exception in this
+   * manner makes the exception behave in the normal way - i.e., as
+   * documented in the class "Throwable".  The fields "errorToken",
+   * "expectedTokenSequences", and "tokenImage" do not contain
+   * relevant information.  The JavaCC generated code does not use
+   * these constructors.
+   */
 
-    public ParseException() {
-        super();
-    }
+  public ParseException() {
+    super();
+  }
 
-    /** Constructor with message. */
-    public ParseException(String message) {
-        super(message);
-    }
+  /** Constructor with message. */
+  public ParseException(String message) {
+    super(message);
+  }
 
-    /**
-     * It uses "currentToken" and "expectedTokenSequences" to generate a parse
-     * error message and returns it.  If this object has been created
-     * due to a parse error, and you do not catch it (it gets thrown
-     * from the parser) the correct error message
-     * gets displayed.
-     */
-    private static String initialise(Token currentToken,
-                                     int[][] expectedTokenSequences,
-                                     String[] tokenImage) {
-        String eol = System.getProperty("line.separator", "\n");
-        StringBuffer expected = new StringBuffer();
-        int maxSize = 0;
-        for (int[] expectedTokenSequence : expectedTokenSequences) {
-            if (maxSize < expectedTokenSequence.length) {
-                maxSize = expectedTokenSequence.length;
-            }
-            for (int j = 0; j < expectedTokenSequence.length; j++) {
-                expected.append(tokenImage[expectedTokenSequence[j]]).append(' ');
-            }
-            if (expectedTokenSequence[expectedTokenSequence.length - 1] != 0) {
-                expected.append("...");
-            }
-            expected.append(eol).append("    ");
-        }
-        StringBuilder retval = new StringBuilder("Encountered \"");
-        Token tok = currentToken.next;
-        for (int i = 0; i < maxSize; i++) {
-            if (i != 0) retval.append(" ");
-            if (tok.kind == 0) {
-                retval.append(tokenImage[0]);
-                break;
-            }
-            retval.append(" ").append(tokenImage[tok.kind]);
-            retval.append(" \"");
-            retval.append(add_escapes(tok.image));
-            retval.append(" \"");
-            tok = tok.next;
-        }
-        retval.append("\" at line ").append(currentToken.next.beginLine).append(", column ").append(currentToken.next.beginColumn);
-        retval.append(".").append(eol);
-        if (expectedTokenSequences.length == 1) {
-            retval.append("Was expecting:").append(eol).append("    ");
-        } else {
-            retval.append("Was expecting one of:").append(eol).append("    ");
-        }
-        retval.append(expected.toString());
-        return retval.toString();
+
+  /**
+   * This is the last token that has been consumed successfully.  If
+   * this object has been created due to a parse error, the token
+   * followng this token will (therefore) be the first error token.
+   */
+  public Token currentToken;
+
+  /**
+   * Each entry in this array is an array of integers.  Each array
+   * of integers represents a sequence of tokens (by their ordinal
+   * values) that is expected at this point of the parse.
+   */
+  public int[][] expectedTokenSequences;
+
+  /**
+   * This is a reference to the "tokenImage" array of the generated
+   * parser within which the parse error occurred.  This array is
+   * defined in the generated ...Constants interface.
+   */
+  public String[] tokenImage;
+
+  /**
+   * It uses "currentToken" and "expectedTokenSequences" to generate a parse
+   * error message and returns it.  If this object has been created
+   * due to a parse error, and you do not catch it (it gets thrown
+   * from the parser) the correct error message
+   * gets displayed.
+   */
+  private static String initialise(Token currentToken,
+                           int[][] expectedTokenSequences,
+                           String[] tokenImage) {
+    String eol = System.getProperty("line.separator", "\n");
+    StringBuffer expected = new StringBuffer();
+    int maxSize = 0;
+    for (int i = 0; i < expectedTokenSequences.length; i++) {
+      if (maxSize < expectedTokenSequences[i].length) {
+        maxSize = expectedTokenSequences[i].length;
+      }
+      for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+        expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
+      }
+      if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+        expected.append("...");
+      }
+      expected.append(eol).append("    ");
+    }
+    String retval = "Encountered \"";
+    Token tok = currentToken.next;
+    for (int i = 0; i < maxSize; i++) {
+      if (i != 0) retval += " ";
+      if (tok.kind == 0) {
+        retval += tokenImage[0];
+        break;
+      }
+      retval += " " + tokenImage[tok.kind];
+      retval += " \"";
+      retval += add_escapes(tok.image);
+      retval += " \"";
+      tok = tok.next;
     }
+    retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+    retval += "." + eol;
+    if (expectedTokenSequences.length == 1) {
+      retval += "Was expecting:" + eol + "    ";
+    } else {
+      retval += "Was expecting one of:" + eol + "    ";
+    }
+    retval += expected.toString();
+    return retval;
+  }
+
+  /**
+   * The end of line string for this machine.
+   */
+  protected String eol = System.getProperty("line.separator", "\n");
 
-    /**
-     * Used to convert raw characters to their escaped version
-     * when these raw version cannot be used as part of an ASCII
-     * string literal.
-     */
-    static String add_escapes(String str) {
-        StringBuffer retval = new StringBuffer();
-        char ch;
-        for (int i = 0; i < str.length(); i++) {
-            switch (str.charAt(i)) {
-                case 0:
-                    continue;
-                case '\b':
-                    retval.append("\\b");
-                    continue;
-                case '\t':
-                    retval.append("\\t");
-                    continue;
-                case '\n':
-                    retval.append("\\n");
-                    continue;
-                case '\f':
-                    retval.append("\\f");
-                    continue;
-                case '\r':
-                    retval.append("\\r");
-                    continue;
-                case '\"':
-                    retval.append("\\\"");
-                    continue;
-                case '\'':
-                    retval.append("\\\'");
-                    continue;
-                case '\\':
-                    retval.append("\\\\");
-                    continue;
-                default:
-                    if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
-                        String s = "0000" + Integer.toString(ch, 16);
-                        retval.append("\\u" + s.substring(s.length() - 4, s.length()));
-                    } else {
-                        retval.append(ch);
-                    }
-                    continue;
-            }
+  /**
+   * Used to convert raw characters to their escaped version
+   * when these raw version cannot be used as part of an ASCII
+   * string literal.
+   */
+  static String add_escapes(String str) {
+      StringBuffer retval = new StringBuffer();
+      char ch;
+      for (int i = 0; i < str.length(); i++) {
+        switch (str.charAt(i))
+        {
+           case 0 :
+              continue;
+           case '\b':
+              retval.append("\\b");
+              continue;
+           case '\t':
+              retval.append("\\t");
+              continue;
+           case '\n':
+              retval.append("\\n");
+              continue;
+           case '\f':
+              retval.append("\\f");
+              continue;
+           case '\r':
+              retval.append("\\r");
+              continue;
+           case '\"':
+              retval.append("\\\"");
+              continue;
+           case '\'':
+              retval.append("\\\'");
+              continue;
+           case '\\':
+              retval.append("\\\\");
+              continue;
+           default:
+              if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+                 String s = "0000" + Integer.toString(ch, 16);
+                 retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+              } else {
+                 retval.append(ch);
+              }
+              continue;
         }
-        return retval.toString();
-    }
+      }
+      return retval.toString();
+   }
 
 }
 /* JavaCC - OriginalChecksum=5189b93605d5a3d3833ed059f46e94c9 (do not edit this line) */
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SSPTParser.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SSPTParser.java
index 92bbf21..30f0258 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SSPTParser.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SSPTParser.java
@@ -1,10 +1,14 @@
 /* Generated By:JavaCC: Do not edit this line. SSPTParser.java */
 package org.apache.camel.component.sql.stored.template.generated;
 
-import java.io.Reader;
-
+import org.apache.camel.component.sql.stored.template.ast.InOutParameter;
+import org.apache.camel.component.sql.stored.template.ast.InParameter;
+import org.apache.camel.component.sql.stored.template.ast.OutParameter;
+import org.apache.camel.component.sql.stored.template.ast.ParseHelper;
+import org.apache.camel.component.sql.stored.template.ast.Template;
 import org.apache.camel.spi.ClassResolver;
-import org.apache.camel.component.sql.stored.template.ast.*;
+
+import java.io.Reader;
 
 public class SSPTParser implements SSPTParserConstants {
    int parameterNameCounter = 0;
@@ -28,6 +32,7 @@ public class SSPTParser implements SSPTParserConstants {
     jj_consume_token(PROCEDURE_BEGIN);
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case 2:
+    case 3:
     case NUMBER:
     case PARAMETER_NAME:
     case IDENTIFIER:
@@ -65,12 +70,16 @@ public class SSPTParser implements SSPTParserConstants {
     case NUMBER:
     case PARAMETER_NAME:
     case IDENTIFIER:
-      param = InputParameter();
-                                {if (true) return param;}
+      param = InParameter();
+                             {if (true) return param;}
       break;
     case 2:
       param = OutParameter();
-                                                                          {if (true) return param;}
+                                                                       {if (true) return param;}
+      break;
+    case 3:
+      param = InOutParameter();
+                                                                                                                   {if (true) return param;}
       break;
     default:
       jj_la1[2] = jj_gen;
@@ -80,7 +89,7 @@ public class SSPTParser implements SSPTParserConstants {
     throw new Error("Missing return statement in function");
   }
 
-  final public InputParameter InputParameter() throws ParseException {
+  final public InParameter InParameter() throws ParseException {
      Token sqlTypeToken;
      String name = null;
      Token valueSrcToken;
@@ -114,10 +123,10 @@ public class SSPTParser implements SSPTParserConstants {
       jj_la1[5] = jj_gen;
       ;
     }
-    valueSrcToken = InputParameterSrc();
+    valueSrcToken = InParameterSrc();
         int sqlType = ParseHelper.parseSqlType(sqlTypeToken, classResolver);
 
-        {if (true) return new InputParameter(name == null ? createNextParameterName() : name, sqlType, valueSrcToken, scale, typeName);}
+        {if (true) return new InParameter(name == null ? createNextParameterName() : name, sqlType, valueSrcToken, scale, typeName);}
     throw new Error("Missing return statement in function");
   }
 
@@ -151,6 +160,41 @@ public class SSPTParser implements SSPTParserConstants {
     throw new Error("Missing return statement in function");
   }
 
+  final public InOutParameter InOutParameter() throws ParseException {
+     Token sqlTypeToken;
+     Token valueSrcToken;
+     Integer scale = null;
+     String typeName = null;
+     String outValueMapKey;
+    jj_consume_token(3);
+    sqlTypeToken = ParameterSqlType();
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+    case SCALE:
+      scale = Scale();
+      break;
+    default:
+      jj_la1[8] = jj_gen;
+      ;
+    }
+    jj_consume_token(1);
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+    case PARAMETER_NAME:
+      typeName = ParameterName();
+      jj_consume_token(1);
+      break;
+    default:
+      jj_la1[9] = jj_gen;
+      ;
+    }
+    valueSrcToken = InParameterSrc();
+    jj_consume_token(1);
+    outValueMapKey = OutHeader();
+        int sqlType = ParseHelper.parseSqlType(sqlTypeToken, classResolver);
+
+        {if (true) return new InOutParameter(sqlType, valueSrcToken, scale, typeName, outValueMapKey);}
+    throw new Error("Missing return statement in function");
+  }
+
   final public String ParameterName() throws ParseException {
     Token t = null;
     t = jj_consume_token(PARAMETER_NAME);
@@ -176,7 +220,7 @@ public class SSPTParser implements SSPTParserConstants {
       t = jj_consume_token(IDENTIFIER);
       break;
     default:
-      jj_la1[8] = jj_gen;
+      jj_la1[10] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
     }
@@ -191,7 +235,7 @@ public class SSPTParser implements SSPTParserConstants {
     throw new Error("Missing return statement in function");
   }
 
-  final public Token InputParameterSrc() throws ParseException {
+  final public Token InParameterSrc() throws ParseException {
     Token ret = null;
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case SIMPLE_EXP_TOKEN:
@@ -203,7 +247,7 @@ public class SSPTParser implements SSPTParserConstants {
             {if (true) return ret;}
       break;
     default:
-      jj_la1[9] = jj_gen;
+      jj_la1[11] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
     }
@@ -219,13 +263,13 @@ public class SSPTParser implements SSPTParserConstants {
   public Token jj_nt;
   private int jj_ntk;
   private int jj_gen;
-  final private int[] jj_la1 = new int[10];
+  final private int[] jj_la1 = new int[12];
   static private int[] jj_la1_0;
   static {
       jj_la1_init_0();
    }
    private static void jj_la1_init_0() {
-      jj_la1_0 = new int[] {0x400,0x18014,0x18014,0x8000,0x8,0x8000,0x8,0x8000,0x10010,0x6000,};
+      jj_la1_0 = new int[] {0x800,0x3002c,0x3002c,0x10000,0x10,0x10000,0x10,0x10000,0x10,0x10000,0x20020,0xc000,};
    }
 
   /** Constructor with InputStream. */
@@ -239,7 +283,7 @@ public class SSPTParser implements SSPTParserConstants {
     token = new Token();
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 10; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 12; i++) jj_la1[i] = -1;
   }
 
   /** Reinitialise. */
@@ -253,7 +297,7 @@ public class SSPTParser implements SSPTParserConstants {
     token = new Token();
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 10; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 12; i++) jj_la1[i] = -1;
   }
 
   /** Constructor. */
@@ -263,7 +307,7 @@ public class SSPTParser implements SSPTParserConstants {
     token = new Token();
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 10; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 12; i++) jj_la1[i] = -1;
   }
 
   /** Reinitialise. */
@@ -273,7 +317,7 @@ public class SSPTParser implements SSPTParserConstants {
     token = new Token();
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 10; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 12; i++) jj_la1[i] = -1;
   }
 
   /** Constructor with generated Token Manager. */
@@ -282,7 +326,7 @@ public class SSPTParser implements SSPTParserConstants {
     token = new Token();
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 10; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 12; i++) jj_la1[i] = -1;
   }
 
   /** Reinitialise. */
@@ -291,7 +335,7 @@ public class SSPTParser implements SSPTParserConstants {
     token = new Token();
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 10; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 12; i++) jj_la1[i] = -1;
   }
 
   private Token jj_consume_token(int kind) throws ParseException {
@@ -342,12 +386,12 @@ public class SSPTParser implements SSPTParserConstants {
   /** Generate ParseException. */
   public ParseException generateParseException() {
     jj_expentries.clear();
-    boolean[] la1tokens = new boolean[17];
+    boolean[] la1tokens = new boolean[18];
     if (jj_kind >= 0) {
       la1tokens[jj_kind] = true;
       jj_kind = -1;
     }
-    for (int i = 0; i < 10; i++) {
+    for (int i = 0; i < 12; i++) {
       if (jj_la1[i] == jj_gen) {
         for (int j = 0; j < 32; j++) {
           if ((jj_la1_0[i] & (1<<j)) != 0) {
@@ -356,7 +400,7 @@ public class SSPTParser implements SSPTParserConstants {
         }
       }
     }
-    for (int i = 0; i < 17; i++) {
+    for (int i = 0; i < 18; i++) {
       if (la1tokens[i]) {
         jj_expentry = new int[1];
         jj_expentry[0] = i;
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserConstants.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserConstants.java
index e047cc8..f48d31d 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserConstants.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserConstants.java
@@ -11,33 +11,33 @@ public interface SSPTParserConstants {
   /** End of File. */
   int EOF = 0;
   /** RegularExpression Id. */
-  int SCALE = 3;
+  int SCALE = 4;
   /** RegularExpression Id. */
-  int NUMBER = 4;
+  int NUMBER = 5;
   /** RegularExpression Id. */
-  int DIGIT = 5;
+  int DIGIT = 6;
   /** RegularExpression Id. */
-  int LETTER = 6;
+  int LETTER = 7;
   /** RegularExpression Id. */
-  int SPECIAL = 7;
+  int SPECIAL = 8;
   /** RegularExpression Id. */
-  int WHITESPACE = 8;
+  int WHITESPACE = 9;
   /** RegularExpression Id. */
-  int COMMA = 9;
+  int COMMA = 10;
   /** RegularExpression Id. */
-  int SEPARATOR = 10;
+  int SEPARATOR = 11;
   /** RegularExpression Id. */
-  int PROCEDURE_BEGIN = 11;
+  int PROCEDURE_BEGIN = 12;
   /** RegularExpression Id. */
-  int PROCEDURE_END = 12;
+  int PROCEDURE_END = 13;
   /** RegularExpression Id. */
-  int SIMPLE_EXP_TOKEN = 13;
+  int SIMPLE_EXP_TOKEN = 14;
   /** RegularExpression Id. */
-  int PARAMETER_POS_TOKEN = 14;
+  int PARAMETER_POS_TOKEN = 15;
   /** RegularExpression Id. */
-  int PARAMETER_NAME = 15;
+  int PARAMETER_NAME = 16;
   /** RegularExpression Id. */
-  int IDENTIFIER = 16;
+  int IDENTIFIER = 17;
 
   /** Lexical state. */
   int DEFAULT = 0;
@@ -47,6 +47,7 @@ public interface SSPTParserConstants {
     "<EOF>",
     "\" \"",
     "\"OUT \"",
+    "\"INOUT \"",
     "<SCALE>",
     "<NUMBER>",
     "<DIGIT>",
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserTokenManager.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserTokenManager.java
index 6598fe0..ba002be 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserTokenManager.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserTokenManager.java
@@ -17,30 +17,46 @@ private final int jjStopStringLiteralDfa_0(int pos, long active0)
    switch (pos)
    {
       case 0:
-         if ((active0 & 0x4L) != 0L)
+         if ((active0 & 0xcL) != 0L)
          {
-            jjmatchedKind = 16;
+            jjmatchedKind = 17;
             return 15;
          }
          if ((active0 & 0x2L) != 0L)
             return 25;
          return -1;
       case 1:
-         if ((active0 & 0x4L) != 0L)
+         if ((active0 & 0xcL) != 0L)
          {
-            jjmatchedKind = 16;
+            jjmatchedKind = 17;
             jjmatchedPos = 1;
             return 15;
          }
          return -1;
       case 2:
-         if ((active0 & 0x4L) != 0L)
+         if ((active0 & 0xcL) != 0L)
          {
-            jjmatchedKind = 16;
+            jjmatchedKind = 17;
             jjmatchedPos = 2;
             return 15;
          }
          return -1;
+      case 3:
+         if ((active0 & 0x8L) != 0L)
+         {
+            jjmatchedKind = 17;
+            jjmatchedPos = 3;
+            return 15;
+         }
+         return -1;
+      case 4:
+         if ((active0 & 0x8L) != 0L)
+         {
+            jjmatchedKind = 17;
+            jjmatchedPos = 4;
+            return 15;
+         }
+         return -1;
       default :
          return -1;
    }
@@ -61,6 +77,8 @@ private int jjMoveStringLiteralDfa0_0()
    {
       case 32:
          return jjStartNfaWithStates_0(0, 1, 25);
+      case 73:
+         return jjMoveStringLiteralDfa1_0(0x8L);
       case 79:
          return jjMoveStringLiteralDfa1_0(0x4L);
       default :
@@ -76,6 +94,8 @@ private int jjMoveStringLiteralDfa1_0(long active0)
    }
    switch(curChar)
    {
+      case 78:
+         return jjMoveStringLiteralDfa2_0(active0, 0x8L);
       case 85:
          return jjMoveStringLiteralDfa2_0(active0, 0x4L);
       default :
@@ -94,6 +114,8 @@ private int jjMoveStringLiteralDfa2_0(long old0, long active0)
    }
    switch(curChar)
    {
+      case 79:
+         return jjMoveStringLiteralDfa3_0(active0, 0x8L);
       case 84:
          return jjMoveStringLiteralDfa3_0(active0, 0x4L);
       default :
@@ -116,11 +138,51 @@ private int jjMoveStringLiteralDfa3_0(long old0, long active0)
          if ((active0 & 0x4L) != 0L)
             return jjStopAtPos(3, 2);
          break;
+      case 85:
+         return jjMoveStringLiteralDfa4_0(active0, 0x8L);
       default :
          break;
    }
    return jjStartNfa_0(2, active0);
 }
+private int jjMoveStringLiteralDfa4_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(2, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(3, active0);
+      return 4;
+   }
+   switch(curChar)
+   {
+      case 84:
+         return jjMoveStringLiteralDfa5_0(active0, 0x8L);
+      default :
+         break;
+   }
+   return jjStartNfa_0(3, active0);
+}
+private int jjMoveStringLiteralDfa5_0(long old0, long active0)
+{
+   if (((active0 &= old0)) == 0L)
+      return jjStartNfa_0(3, old0);
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_0(4, active0);
+      return 5;
+   }
+   switch(curChar)
+   {
+      case 32:
+         if ((active0 & 0x8L) != 0L)
+            return jjStopAtPos(5, 3);
+         break;
+      default :
+         break;
+   }
+   return jjStartNfa_0(4, active0);
+}
 private int jjStartNfaWithStates_0(int pos, int kind, int state)
 {
    jjmatchedKind = kind;
@@ -150,38 +212,38 @@ private int jjMoveNfa_0(int startState, int curPos)
                case 8:
                   if ((0x7ff609c00000000L & l) != 0L)
                   {
-                     if (kind > 16)
-                        kind = 16;
+                     if (kind > 17)
+                        kind = 17;
                      jjCheckNAdd(15);
                   }
                   else if ((0x100002600L & l) != 0L)
                   {
-                     if (kind > 8)
-                        kind = 8;
+                     if (kind > 9)
+                        kind = 9;
                      jjCheckNAddStates(0, 5);
                   }
                   else if (curChar == 40)
                   {
-                     if (kind > 11)
-                        kind = 11;
+                     if (kind > 12)
+                        kind = 12;
                      jjCheckNAddTwoStates(17, 19);
                   }
                   else if (curChar == 41)
                   {
-                     if (kind > 12)
-                        kind = 12;
+                     if (kind > 13)
+                        kind = 13;
                      jjCheckNAdd(4);
                   }
                   else if (curChar == 44)
                   {
-                     if (kind > 10)
-                        kind = 10;
+                     if (kind > 11)
+                        kind = 11;
                      jjCheckNAdd(2);
                   }
                   if ((0x3ff200000000000L & l) != 0L)
                   {
-                     if (kind > 4)
-                        kind = 4;
+                     if (kind > 5)
+                        kind = 5;
                      jjCheckNAdd(0);
                   }
                   else if (curChar == 39)
@@ -196,20 +258,20 @@ private int jjMoveNfa_0(int startState, int curPos)
                      jjCheckNAddTwoStates(24, 3);
                   else if (curChar == 41)
                   {
-                     if (kind > 12)
-                        kind = 12;
+                     if (kind > 13)
+                        kind = 13;
                      jjCheckNAdd(4);
                   }
                   else if (curChar == 40)
                   {
-                     if (kind > 11)
-                        kind = 11;
+                     if (kind > 12)
+                        kind = 12;
                      jjCheckNAdd(19);
                   }
                   else if (curChar == 44)
                   {
-                     if (kind > 10)
-                        kind = 10;
+                     if (kind > 11)
+                        kind = 11;
                      jjCheckNAdd(2);
                   }
                   if ((0x100002600L & l) != 0L)
@@ -220,35 +282,35 @@ private int jjMoveNfa_0(int startState, int curPos)
                case 0:
                   if ((0x3ff200000000000L & l) == 0L)
                      break;
-                  if (kind > 4)
-                     kind = 4;
+                  if (kind > 5)
+                     kind = 5;
                   jjCheckNAdd(0);
                   break;
                case 1:
                   if (curChar != 44)
                      break;
-                  kind = 10;
+                  kind = 11;
                   jjCheckNAdd(2);
                   break;
                case 2:
                   if ((0x100002600L & l) == 0L)
                      break;
-                  if (kind > 10)
-                     kind = 10;
+                  if (kind > 11)
+                     kind = 11;
                   jjCheckNAdd(2);
                   break;
                case 3:
                   if (curChar != 41)
                      break;
-                  if (kind > 12)
-                     kind = 12;
+                  if (kind > 13)
+                     kind = 13;
                   jjCheckNAdd(4);
                   break;
                case 4:
                   if ((0x100002600L & l) == 0L)
                      break;
-                  if (kind > 12)
-                     kind = 12;
+                  if (kind > 13)
+                     kind = 13;
                   jjCheckNAdd(4);
                   break;
                case 6:
@@ -262,8 +324,8 @@ private int jjMoveNfa_0(int startState, int curPos)
                case 10:
                   if ((0x7ff609c00000000L & l) == 0L)
                      break;
-                  if (kind > 14)
-                     kind = 14;
+                  if (kind > 15)
+                     kind = 15;
                   jjCheckNAdd(10);
                   break;
                case 11:
@@ -279,21 +341,21 @@ private int jjMoveNfa_0(int startState, int curPos)
                      jjCheckNAddTwoStates(13, 14);
                   break;
                case 14:
-                  if (curChar == 39 && kind > 15)
-                     kind = 15;
+                  if (curChar == 39 && kind > 16)
+                     kind = 16;
                   break;
                case 15:
                   if ((0x7ff609c00000000L & l) == 0L)
                      break;
-                  if (kind > 16)
-                     kind = 16;
+                  if (kind > 17)
+                     kind = 17;
                   jjCheckNAdd(15);
                   break;
                case 16:
                   if (curChar != 40)
                      break;
-                  if (kind > 11)
-                     kind = 11;
+                  if (kind > 12)
+                     kind = 12;
                   jjCheckNAddTwoStates(17, 19);
                   break;
                case 17:
@@ -301,21 +363,21 @@ private int jjMoveNfa_0(int startState, int curPos)
                      jjCheckNAddTwoStates(17, 18);
                   break;
                case 18:
-                  if (curChar == 41 && kind > 3)
-                     kind = 3;
+                  if (curChar == 41 && kind > 4)
+                     kind = 4;
                   break;
                case 19:
                   if ((0x100002600L & l) == 0L)
                      break;
-                  if (kind > 11)
-                     kind = 11;
+                  if (kind > 12)
+                     kind = 12;
                   jjCheckNAdd(19);
                   break;
                case 20:
                   if ((0x100002600L & l) == 0L)
                      break;
-                  if (kind > 8)
-                     kind = 8;
+                  if (kind > 9)
+                     kind = 9;
                   jjCheckNAddStates(0, 5);
                   break;
                case 21:
@@ -329,8 +391,8 @@ private int jjMoveNfa_0(int startState, int curPos)
                case 23:
                   if (curChar != 40)
                      break;
-                  if (kind > 11)
-                     kind = 11;
+                  if (kind > 12)
+                     kind = 12;
                   jjCheckNAdd(19);
                   break;
                case 24:
@@ -352,8 +414,8 @@ private int jjMoveNfa_0(int startState, int curPos)
                case 15:
                   if ((0x2ffffffeaffffffeL & l) == 0L)
                      break;
-                  if (kind > 16)
-                     kind = 16;
+                  if (kind > 17)
+                     kind = 17;
                   jjCheckNAdd(15);
                   break;
                case 5:
@@ -365,14 +427,14 @@ private int jjMoveNfa_0(int startState, int curPos)
                      jjCheckNAddTwoStates(6, 7);
                   break;
                case 7:
-                  if (curChar == 125 && kind > 13)
-                     kind = 13;
+                  if (curChar == 125 && kind > 14)
+                     kind = 14;
                   break;
                case 10:
                   if ((0x2ffffffeaffffffeL & l) == 0L)
                      break;
-                  if (kind > 14)
-                     kind = 14;
+                  if (kind > 15)
+                     kind = 15;
                   jjstateSet[jjnewStateCnt++] = 10;
                   break;
                case 13:
@@ -414,8 +476,8 @@ static final int[] jjnextStates = {
 
 /** Token literal values. */
 public static final String[] jjstrLiteralImages = {
-"", "\40", "\117\125\124\40", null, null, null, null, null, null, null, null, 
-null, null, null, null, null, null, };
+"", "\40", "\117\125\124\40", "\111\116\117\125\124\40", null, null, null, 
+null, null, null, null, null, null, null, null, null, null, null, };
 
 /** Lexer state names. */
 public static final String[] lexStateNames = {
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SimpleCharStream.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SimpleCharStream.java
index 482ba76..38d998e 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SimpleCharStream.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/SimpleCharStream.java
@@ -7,413 +7,465 @@ package org.apache.camel.component.sql.stored.template.generated;
  * contain only ASCII characters (without unicode processing).
  */
 
-public class SimpleCharStream {
-    /** Whether parser is static. */
-    public static final boolean staticFlag = false;
-    /** Position in buffer. */
-    public int bufpos = -1;
-    protected int bufline[];
-    protected int bufcolumn[];
-    protected int column = 0;
-    protected int line = 1;
-    protected boolean prevCharIsCR = false;
-    protected boolean prevCharIsLF = false;
-    protected java.io.Reader inputStream;
-    protected char[] buffer;
-    protected int maxNextCharInd = 0;
-    protected int inBuf = 0;
-    protected int tabSize = 8;
-    int bufsize;
-    int available;
-    int tokenBegin;
-
-    /** Constructor. */
-    public SimpleCharStream(java.io.Reader dstream, int startline,
-                            int startcolumn, int buffersize) {
-        inputStream = dstream;
-        line = startline;
-        column = startcolumn - 1;
-
-        available = bufsize = buffersize;
-        buffer = new char[buffersize];
-        bufline = new int[buffersize];
-        bufcolumn = new int[buffersize];
-    }
-
-    /** Constructor. */
-    public SimpleCharStream(java.io.Reader dstream, int startline,
-                            int startcolumn) {
-        this(dstream, startline, startcolumn, 4096);
-    }
-
-
-    /** Constructor. */
-    public SimpleCharStream(java.io.Reader dstream) {
-        this(dstream, 1, 1, 4096);
-    }
-
-    /** Constructor. */
-    public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
-                            int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException {
-        this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
-    }
-
-    /** Constructor. */
-    public SimpleCharStream(java.io.InputStream dstream, int startline,
-                            int startcolumn, int buffersize) {
-        this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
-    }
-
-    /** Constructor. */
-    public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
-                            int startcolumn) throws java.io.UnsupportedEncodingException {
-        this(dstream, encoding, startline, startcolumn, 4096);
-    }
-
-    /** Constructor. */
-    public SimpleCharStream(java.io.InputStream dstream, int startline,
-                            int startcolumn) {
-        this(dstream, startline, startcolumn, 4096);
-    }
-
-    /** Constructor. */
-    public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException {
-        this(dstream, encoding, 1, 1, 4096);
-    }
-
-    /** Constructor. */
-    public SimpleCharStream(java.io.InputStream dstream) {
-        this(dstream, 1, 1, 4096);
-    }
-
-    protected void setTabSize(int i) {
-        tabSize = i;
-    }
-
-    protected int getTabSize(int i) {
-        return tabSize;
-    }
-
-    protected void ExpandBuff(boolean wrapAround) {
-        char[] newbuffer = new char[bufsize + 2048];
-        int newbufline[] = new int[bufsize + 2048];
-        int newbufcolumn[] = new int[bufsize + 2048];
-
-        try {
-            if (wrapAround) {
-                System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
-                System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
-                buffer = newbuffer;
-
-                System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
-                System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
-                bufline = newbufline;
-
-                System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
-                System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
-                bufcolumn = newbufcolumn;
-
-                maxNextCharInd = (bufpos += (bufsize - tokenBegin));
-            } else {
-                System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
-                buffer = newbuffer;
-
-                System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
-                bufline = newbufline;
-
-                System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
-                bufcolumn = newbufcolumn;
-
-                maxNextCharInd = (bufpos -= tokenBegin);
-            }
-        } catch (Throwable t) {
-            throw new Error(t.getMessage());
+public class SimpleCharStream
+{
+/** Whether parser is static. */
+  public static final boolean staticFlag = false;
+  int bufsize;
+  int available;
+  int tokenBegin;
+/** Position in buffer. */
+  public int bufpos = -1;
+  protected int bufline[];
+  protected int bufcolumn[];
+
+  protected int column = 0;
+  protected int line = 1;
+
+  protected boolean prevCharIsCR = false;
+  protected boolean prevCharIsLF = false;
+
+  protected java.io.Reader inputStream;
+
+  protected char[] buffer;
+  protected int maxNextCharInd = 0;
+  protected int inBuf = 0;
+  protected int tabSize = 8;
+
+  protected void setTabSize(int i) { tabSize = i; }
+  protected int getTabSize(int i) { return tabSize; }
+
+
+  protected void ExpandBuff(boolean wrapAround)
+  {
+    char[] newbuffer = new char[bufsize + 2048];
+    int newbufline[] = new int[bufsize + 2048];
+    int newbufcolumn[] = new int[bufsize + 2048];
+
+    try
+    {
+      if (wrapAround)
+      {
+        System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+        System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
+        buffer = newbuffer;
+
+        System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+        System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+        bufline = newbufline;
+
+        System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+        System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+        bufcolumn = newbufcolumn;
+
+        maxNextCharInd = (bufpos += (bufsize - tokenBegin));
+      }
+      else
+      {
+        System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+        buffer = newbuffer;
+
+        System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+        bufline = newbufline;
+
+        System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+        bufcolumn = newbufcolumn;
+
+        maxNextCharInd = (bufpos -= tokenBegin);
+      }
+    }
+    catch (Throwable t)
+    {
+      throw new Error(t.getMessage());
+    }
+
+
+    bufsize += 2048;
+    available = bufsize;
+    tokenBegin = 0;
+  }
+
+  protected void FillBuff() throws java.io.IOException
+  {
+    if (maxNextCharInd == available)
+    {
+      if (available == bufsize)
+      {
+        if (tokenBegin > 2048)
+        {
+          bufpos = maxNextCharInd = 0;
+          available = tokenBegin;
         }
-
-
-        bufsize += 2048;
+        else if (tokenBegin < 0)
+          bufpos = maxNextCharInd = 0;
+        else
+          ExpandBuff(false);
+      }
+      else if (available > tokenBegin)
         available = bufsize;
-        tokenBegin = 0;
-    }
-
-    protected void FillBuff() throws java.io.IOException {
-        if (maxNextCharInd == available) {
-            if (available == bufsize) {
-                if (tokenBegin > 2048) {
-                    bufpos = maxNextCharInd = 0;
-                    available = tokenBegin;
-                } else if (tokenBegin < 0)
-                    bufpos = maxNextCharInd = 0;
-                else
-                    ExpandBuff(false);
-            } else if (available > tokenBegin)
-                available = bufsize;
-            else if ((tokenBegin - available) < 2048)
-                ExpandBuff(true);
-            else
-                available = tokenBegin;
-        }
-
-        int i;
-        try {
-            if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1) {
-                inputStream.close();
-                throw new java.io.IOException();
-            } else
-                maxNextCharInd += i;
-            return;
-        } catch (java.io.IOException e) {
-            --bufpos;
-            backup(0);
-            if (tokenBegin == -1)
-                tokenBegin = bufpos;
-            throw e;
-        }
-    }
-
-    /** Start. */
-    public char BeginToken() throws java.io.IOException {
-        tokenBegin = -1;
-        char c = readChar();
+      else if ((tokenBegin - available) < 2048)
+        ExpandBuff(true);
+      else
+        available = tokenBegin;
+    }
+
+    int i;
+    try {
+      if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
+      {
+        inputStream.close();
+        throw new java.io.IOException();
+      }
+      else
+        maxNextCharInd += i;
+      return;
+    }
+    catch(java.io.IOException e) {
+      --bufpos;
+      backup(0);
+      if (tokenBegin == -1)
         tokenBegin = bufpos;
-
-        return c;
-    }
-
-    protected void UpdateLineColumn(char c) {
-        column++;
-
-        if (prevCharIsLF) {
-            prevCharIsLF = false;
-            line += (column = 1);
-        } else if (prevCharIsCR) {
-            prevCharIsCR = false;
-            if (c == '\n') {
-                prevCharIsLF = true;
-            } else
-                line += (column = 1);
-        }
-
-        switch (c) {
-            case '\r':
-                prevCharIsCR = true;
-                break;
-            case '\n':
-                prevCharIsLF = true;
-                break;
-            case '\t':
-                column--;
-                column += (tabSize - (column % tabSize));
-                break;
-            default:
-                break;
-        }
-
-        bufline[bufpos] = line;
-        bufcolumn[bufpos] = column;
-    }
-
-    /** Read a character. */
-    public char readChar() throws java.io.IOException {
-        if (inBuf > 0) {
-            --inBuf;
-
-            if (++bufpos == bufsize)
-                bufpos = 0;
-
-            return buffer[bufpos];
-        }
-
-        if (++bufpos >= maxNextCharInd)
-            FillBuff();
-
-        char c = buffer[bufpos];
-
-        UpdateLineColumn(c);
-        return c;
-    }
-
-    @Deprecated
-    /**
-     * @deprecated
-     * @see #getEndColumn
-     */
-
-    public int getColumn() {
-        return bufcolumn[bufpos];
-    }
-
-    @Deprecated
-    /**
-     * @deprecated
-     * @see #getEndLine
-     */
-
-    public int getLine() {
-        return bufline[bufpos];
-    }
-
-    /** Get token end column number. */
-    public int getEndColumn() {
-        return bufcolumn[bufpos];
-    }
-
-    /** Get token end line number. */
-    public int getEndLine() {
-        return bufline[bufpos];
-    }
-
-    /** Get token beginning column number. */
-    public int getBeginColumn() {
-        return bufcolumn[tokenBegin];
-    }
-
-    /** Get token beginning line number. */
-    public int getBeginLine() {
-        return bufline[tokenBegin];
-    }
-
-    /** Backup a number of characters. */
-    public void backup(int amount) {
-
-        inBuf += amount;
-        if ((bufpos -= amount) < 0)
-            bufpos += bufsize;
-    }
-
-    /** Reinitialise. */
-    public void ReInit(java.io.Reader dstream, int startline,
-                       int startcolumn, int buffersize) {
-        inputStream = dstream;
-        line = startline;
-        column = startcolumn - 1;
-
-        if (buffer == null || buffersize != buffer.length) {
-            available = bufsize = buffersize;
-            buffer = new char[buffersize];
-            bufline = new int[buffersize];
-            bufcolumn = new int[buffersize];
-        }
-        prevCharIsLF = prevCharIsCR = false;
-        tokenBegin = inBuf = maxNextCharInd = 0;
-        bufpos = -1;
-    }
-
-    /** Reinitialise. */
-    public void ReInit(java.io.Reader dstream, int startline,
-                       int startcolumn) {
-        ReInit(dstream, startline, startcolumn, 4096);
-    }
-
-    /** Reinitialise. */
-    public void ReInit(java.io.Reader dstream) {
-        ReInit(dstream, 1, 1, 4096);
-    }
-
-    /** Reinitialise. */
-    public void ReInit(java.io.InputStream dstream, String encoding, int startline,
-                       int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException {
-        ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
-    }
-
-    /** Reinitialise. */
-    public void ReInit(java.io.InputStream dstream, int startline,
-                       int startcolumn, int buffersize) {
-        ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
-    }
-
-    /** Reinitialise. */
-    public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException {
-        ReInit(dstream, encoding, 1, 1, 4096);
-    }
-
-    /** Reinitialise. */
-    public void ReInit(java.io.InputStream dstream) {
-        ReInit(dstream, 1, 1, 4096);
-    }
-
-    /** Reinitialise. */
-    public void ReInit(java.io.InputStream dstream, String encoding, int startline,
-                       int startcolumn) throws java.io.UnsupportedEncodingException {
-        ReInit(dstream, encoding, startline, startcolumn, 4096);
-    }
-
-    /** Reinitialise. */
-    public void ReInit(java.io.InputStream dstream, int startline,
-                       int startcolumn) {
-        ReInit(dstream, startline, startcolumn, 4096);
-    }
-
-    /** Get token literal value. */
-    public String GetImage() {
-        if (bufpos >= tokenBegin)
-            return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+      throw e;
+    }
+  }
+
+/** Start. */
+  public char BeginToken() throws java.io.IOException
+  {
+    tokenBegin = -1;
+    char c = readChar();
+    tokenBegin = bufpos;
+
+    return c;
+  }
+
+  protected void UpdateLineColumn(char c)
+  {
+    column++;
+
+    if (prevCharIsLF)
+    {
+      prevCharIsLF = false;
+      line += (column = 1);
+    }
+    else if (prevCharIsCR)
+    {
+      prevCharIsCR = false;
+      if (c == '\n')
+      {
+        prevCharIsLF = true;
+      }
+      else
+        line += (column = 1);
+    }
+
+    switch (c)
+    {
+      case '\r' :
+        prevCharIsCR = true;
+        break;
+      case '\n' :
+        prevCharIsLF = true;
+        break;
+      case '\t' :
+        column--;
+        column += (tabSize - (column % tabSize));
+        break;
+      default :
+        break;
+    }
+
+    bufline[bufpos] = line;
+    bufcolumn[bufpos] = column;
+  }
+
+/** Read a character. */
+  public char readChar() throws java.io.IOException
+  {
+    if (inBuf > 0)
+    {
+      --inBuf;
+
+      if (++bufpos == bufsize)
+        bufpos = 0;
+
+      return buffer[bufpos];
+    }
+
+    if (++bufpos >= maxNextCharInd)
+      FillBuff();
+
+    char c = buffer[bufpos];
+
+    UpdateLineColumn(c);
+    return c;
+  }
+
+  @Deprecated
+  /**
+   * @deprecated
+   * @see #getEndColumn
+   */
+
+  public int getColumn() {
+    return bufcolumn[bufpos];
+  }
+
+  @Deprecated
+  /**
+   * @deprecated
+   * @see #getEndLine
+   */
+
+  public int getLine() {
+    return bufline[bufpos];
+  }
+
+  /** Get token end column number. */
+  public int getEndColumn() {
+    return bufcolumn[bufpos];
+  }
+
+  /** Get token end line number. */
+  public int getEndLine() {
+     return bufline[bufpos];
+  }
+
+  /** Get token beginning column number. */
+  public int getBeginColumn() {
+    return bufcolumn[tokenBegin];
+  }
+
+  /** Get token beginning line number. */
+  public int getBeginLine() {
+    return bufline[tokenBegin];
+  }
+
+/** Backup a number of characters. */
+  public void backup(int amount) {
+
+    inBuf += amount;
+    if ((bufpos -= amount) < 0)
+      bufpos += bufsize;
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    available = bufsize = buffersize;
+    buffer = new char[buffersize];
+    bufline = new int[buffersize];
+    bufcolumn = new int[buffersize];
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader dstream, int startline,
+                          int startcolumn)
+  {
+    this(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader dstream)
+  {
+    this(dstream, 1, 1, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    if (buffer == null || buffersize != buffer.length)
+    {
+      available = bufsize = buffersize;
+      buffer = new char[buffersize];
+      bufline = new int[buffersize];
+      bufcolumn = new int[buffersize];
+    }
+    prevCharIsLF = prevCharIsCR = false;
+    tokenBegin = inBuf = maxNextCharInd = 0;
+    bufpos = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream, int startline,
+                     int startcolumn)
+  {
+    ReInit(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream)
+  {
+    ReInit(dstream, 1, 1, 4096);
+  }
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+  int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+  {
+    this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+                          int startcolumn) throws java.io.UnsupportedEncodingException
+  {
+    this(dstream, encoding, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, int startline,
+                          int startcolumn)
+  {
+    this(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+  {
+    this(dstream, encoding, 1, 1, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream)
+  {
+    this(dstream, 1, 1, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+                          int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, int startline,
+                          int startcolumn, int buffersize)
+  {
+    ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(dstream, encoding, 1, 1, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream)
+  {
+    ReInit(dstream, 1, 1, 4096);
+  }
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+                     int startcolumn) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(dstream, encoding, startline, startcolumn, 4096);
+  }
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, int startline,
+                     int startcolumn)
+  {
+    ReInit(dstream, startline, startcolumn, 4096);
+  }
+  /** Get token literal value. */
+  public String GetImage()
+  {
+    if (bufpos >= tokenBegin)
+      return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+    else
+      return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+                            new String(buffer, 0, bufpos + 1);
+  }
+
+  /** Get the suffix. */
+  public char[] GetSuffix(int len)
+  {
+    char[] ret = new char[len];
+
+    if ((bufpos + 1) >= len)
+      System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+    else
+    {
+      System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+                                                        len - bufpos - 1);
+      System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+    }
+
+    return ret;
+  }
+
+  /** Reset buffer when finished. */
+  public void Done()
+  {
+    buffer = null;
+    bufline = null;
+    bufcolumn = null;
+  }
+
+  /**
+   * Method to adjust line and column numbers for the start of a token.
+   */
+  public void adjustBeginLineColumn(int newLine, int newCol)
+  {
+    int start = tokenBegin;
+    int len;
+
+    if (bufpos >= tokenBegin)
+    {
+      len = bufpos - tokenBegin + inBuf + 1;
+    }
+    else
+    {
+      len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+    }
+
+    int i = 0, j = 0, k = 0;
+    int nextColDiff = 0, columnDiff = 0;
+
+    while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
+    {
+      bufline[j] = newLine;
+      nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+      bufcolumn[j] = newCol + columnDiff;
+      columnDiff = nextColDiff;
+      i++;
+    }
+
+    if (i < len)
+    {
+      bufline[j] = newLine++;
+      bufcolumn[j] = newCol + columnDiff;
+
+      while (i++ < len)
+      {
+        if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+          bufline[j] = newLine++;
         else
-            return new String(buffer, tokenBegin, bufsize - tokenBegin) +
-                    new String(buffer, 0, bufpos + 1);
+          bufline[j] = newLine;
+      }
     }
 
-    /** Get the suffix. */
-    public char[] GetSuffix(int len) {
-        char[] ret = new char[len];
-
-        if ((bufpos + 1) >= len)
-            System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
-        else {
-            System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
-                    len - bufpos - 1);
-            System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
-        }
-
-        return ret;
-    }
-
-    /** Reset buffer when finished. */
-    public void Done() {
-        buffer = null;
-        bufline = null;
-        bufcolumn = null;
-    }
-
-    /**
-     * Method to adjust line and column numbers for the start of a token.
-     */
-    public void adjustBeginLineColumn(int newLine, int newCol) {
-        int start = tokenBegin;
-        int len;
-
-        if (bufpos >= tokenBegin) {
-            len = bufpos - tokenBegin + inBuf + 1;
-        } else {
-            len = bufsize - tokenBegin + bufpos + 1 + inBuf;
-        }
-
-        int i = 0, j = 0, k = 0;
-        int nextColDiff = 0, columnDiff = 0;
-
-        while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) {
-            bufline[j] = newLine;
-            nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
-            bufcolumn[j] = newCol + columnDiff;
-            columnDiff = nextColDiff;
-            i++;
-        }
-
-        if (i < len) {
-            bufline[j] = newLine++;
-            bufcolumn[j] = newCol + columnDiff;
-
-            while (i++ < len) {
-                if (bufline[j = start % bufsize] != bufline[++start % bufsize])
-                    bufline[j] = newLine++;
-                else
-                    bufline[j] = newLine;
-            }
-        }
-
-        line = bufline[j];
-        column = bufcolumn[j];
-    }
+    line = bufline[j];
+    column = bufcolumn[j];
+  }
 
 }
 /* JavaCC - OriginalChecksum=78e981b5210775b82383fb6e32f1e767 (do not edit this line) */
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/Token.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/Token.java
index 22b3b65..c2d86e2 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/Token.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/Token.java
@@ -8,120 +8,124 @@ package org.apache.camel.component.sql.stored.template.generated;
 
 public class Token implements java.io.Serializable {
 
-    /**
-     * The version identifier for this Serializable class.
-     * Increment only if the <i>serialized</i> form of the
-     * class changes.
-     */
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * An integer that describes the kind of this token.  This numbering
-     * system is determined by JavaCCParser, and a table of these numbers is
-     * stored in the file ...Constants.java.
-     */
-    public int kind;
-
-    /** The line number of the first character of this Token. */
-    public int beginLine;
-    /** The column number of the first character of this Token. */
-    public int beginColumn;
-    /** The line number of the last character of this Token. */
-    public int endLine;
-    /** The column number of the last character of this Token. */
-    public int endColumn;
-
-    /**
-     * The string image of the token.
-     */
-    public String image;
-
-    /**
-     * A reference to the next regular (non-special) token from the input
-     * stream.  If this is the last token from the input stream, or if the
-     * token manager has not read tokens beyond this one, this field is
-     * set to null.  This is true only if this token is also a regular
-     * token.  Otherwise, see below for a description of the contents of
-     * this field.
-     */
-    public Token next;
-
-    /**
-     * This field is used to access special tokens that occur prior to this
-     * token, but after the immediately preceding regular (non-special) token.
-     * If there are no such special tokens, this field is set to null.
-     * When there are more than one such special token, this field refers
-     * to the last of these special tokens, which in turn refers to the next
-     * previous special token through its specialToken field, and so on
-     * until the first special token (whose specialToken field is null).
-     * The next fields of special tokens refer to other special tokens that
-     * immediately follow it (without an intervening regular token).  If there
-     * is no such token, this field is null.
-     */
-    public Token specialToken;
-
-    /**
-     * No-argument constructor
-     */
-    public Token() {
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * An integer that describes the kind of this token.  This numbering
+   * system is determined by JavaCCParser, and a table of these numbers is
+   * stored in the file ...Constants.java.
+   */
+  public int kind;
+
+  /** The line number of the first character of this Token. */
+  public int beginLine;
+  /** The column number of the first character of this Token. */
+  public int beginColumn;
+  /** The line number of the last character of this Token. */
+  public int endLine;
+  /** The column number of the last character of this Token. */
+  public int endColumn;
+
+  /**
+   * The string image of the token.
+   */
+  public String image;
+
+  /**
+   * A reference to the next regular (non-special) token from the input
+   * stream.  If this is the last token from the input stream, or if the
+   * token manager has not read tokens beyond this one, this field is
+   * set to null.  This is true only if this token is also a regular
+   * token.  Otherwise, see below for a description of the contents of
+   * this field.
+   */
+  public Token next;
+
+  /**
+   * This field is used to access special tokens that occur prior to this
+   * token, but after the immediately preceding regular (non-special) token.
+   * If there are no such special tokens, this field is set to null.
+   * When there are more than one such special token, this field refers
+   * to the last of these special tokens, which in turn refers to the next
+   * previous special token through its specialToken field, and so on
+   * until the first special token (whose specialToken field is null).
+   * The next fields of special tokens refer to other special tokens that
+   * immediately follow it (without an intervening regular token).  If there
+   * is no such token, this field is null.
+   */
+  public Token specialToken;
+
+  /**
+   * An optional attribute value of the Token.
+   * Tokens which are not used as syntactic sugar will often contain
+   * meaningful values that will be used later on by the compiler or
+   * interpreter. This attribute value is often different from the image.
+   * Any subclass of Token that actually wants to return a non-null value can
+   * override this method as appropriate.
+   */
+  public Object getValue() {
+    return null;
+  }
+
+  /**
+   * No-argument constructor
+   */
+  public Token() {}
+
+  /**
+   * Constructs a new token for the specified Image.
+   */
+  public Token(int kind)
+  {
+    this(kind, null);
+  }
+
+  /**
+   * Constructs a new token for the specified Image and Kind.
+   */
+  public Token(int kind, String image)
+  {
+    this.kind = kind;
+    this.image = image;
+  }
+
+  /**
+   * Returns the image.
+   */
+  public String toString()
+  {
+    return image;
+  }
+
+  /**
+   * Returns a new Token object, by default. However, if you want, you
+   * can create and return subclass objects based on the value of ofKind.
+   * Simply add the cases to the switch for all those special cases.
+   * For example, if you have a subclass of Token called IDToken that
+   * you want to create if ofKind is ID, simply add something like :
+   *
+   *    case MyParserConstants.ID : return new IDToken(ofKind, image);
+   *
+   * to the following switch statement. Then you can cast matchedToken
+   * variable to the appropriate type and use sit in your lexical actions.
+   */
+  public static Token newToken(int ofKind, String image)
+  {
+    switch(ofKind)
+    {
+      default : return new Token(ofKind, image);
     }
+  }
 
-    /**
-     * Constructs a new token for the specified Image.
-     */
-    public Token(int kind) {
-        this(kind, null);
-    }
-
-    /**
-     * Constructs a new token for the specified Image and Kind.
-     */
-    public Token(int kind, String image) {
-        this.kind = kind;
-        this.image = image;
-    }
-
-    /**
-     * Returns a new Token object, by default. However, if you want, you
-     * can create and return subclass objects based on the value of ofKind.
-     * Simply add the cases to the switch for all those special cases.
-     * For example, if you have a subclass of Token called IDToken that
-     * you want to create if ofKind is ID, simply add something like :
-     *
-     * case MyParserConstants.ID : return new IDToken(ofKind, image);
-     *
-     * to the following switch statement. Then you can cast matchedToken
-     * variable to the appropriate type and use sit in your lexical actions.
-     */
-    public static Token newToken(int ofKind, String image) {
-        switch (ofKind) {
-            default:
-                return new Token(ofKind, image);
-        }
-    }
-
-    public static Token newToken(int ofKind) {
-        return newToken(ofKind, null);
-    }
-
-    /**
-     * An optional attribute value of the Token.
-     * Tokens which are not used as syntactic sugar will often contain
-     * meaningful values that will be used later on by the compiler or
-     * interpreter. This attribute value is often different from the image.
-     * Any subclass of Token that actually wants to return a non-null value can
-     * override this method as appropriate.
-     */
-    public Object getValue() {
-        return null;
-    }
-
-    /**
-     * Returns the image.
-     */
-    public String toString() {
-        return image;
-    }
+  public static Token newToken(int ofKind)
+  {
+    return newToken(ofKind, null);
+  }
 
 }
 /* JavaCC - OriginalChecksum=7e8baa74d8a01b01496421112dcea294 (do not edit this line) */
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/TokenMgrError.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/TokenMgrError.java
index 13fd322..3689f73 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/TokenMgrError.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/TokenMgrError.java
@@ -3,138 +3,145 @@
 package org.apache.camel.component.sql.stored.template.generated;
 
 /** Token Manager Error. */
-public class TokenMgrError extends Error {
+public class TokenMgrError extends Error
+{
 
-    /**
-     * Lexical error occurred.
-     */
-    static final int LEXICAL_ERROR = 0;
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
 
   /*
    * Ordinals for various reasons why an Error of this type can be thrown.
    */
-    /**
-     * An attempt was made to create a second instance of a static token manager.
-     */
-    static final int STATIC_LEXER_ERROR = 1;
-    /**
-     * Tried to change to an invalid lexical state.
-     */
-    static final int INVALID_LEXICAL_STATE = 2;
-    /**
-     * Detected (and bailed out of) an infinite loop in the token manager.
-     */
-    static final int LOOP_DETECTED = 3;
-    /**
-     * The version identifier for this Serializable class.
-     * Increment only if the <i>serialized</i> form of the
-     * class changes.
-     */
-    private static final long serialVersionUID = 1L;
-    /**
-     * Indicates the reason why the exception is thrown. It will have
-     * one of the above 4 values.
-     */
-    int errorCode;
 
-    /** No arg constructor. */
-    public TokenMgrError() {
-    }
+  /**
+   * Lexical error occurred.
+   */
+  static final int LEXICAL_ERROR = 0;
 
-    /** Constructor with message and reason. */
-    public TokenMgrError(String message, int reason) {
-        super(message);
-        errorCode = reason;
-    }
+  /**
+   * An attempt was made to create a second instance of a static token manager.
+   */
+  static final int STATIC_LEXER_ERROR = 1;
 
-    /** Full Constructor. */
-    public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
-        this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+  /**
+   * Tried to change to an invalid lexical state.
+   */
+  static final int INVALID_LEXICAL_STATE = 2;
+
+  /**
+   * Detected (and bailed out of) an infinite loop in the token manager.
+   */
+  static final int LOOP_DETECTED = 3;
+
+  /**
+   * Indicates the reason why the exception is thrown. It will have
+   * one of the above 4 values.
+   */
+  int errorCode;
+
+  /**
+   * Replaces unprintable characters by their escaped (or unicode escaped)
+   * equivalents in the given string
+   */
+  protected static final String addEscapes(String str) {
+    StringBuffer retval = new StringBuffer();
+    char ch;
+    for (int i = 0; i < str.length(); i++) {
+      switch (str.charAt(i))
+      {
+        case 0 :
+          continue;
+        case '\b':
+          retval.append("\\b");
+          continue;
+        case '\t':
+          retval.append("\\t");
+          continue;
+        case '\n':
+          retval.append("\\n");
+          continue;
+        case '\f':
+          retval.append("\\f");
+          continue;
+        case '\r':
+          retval.append("\\r");
+          continue;
+        case '\"':
+          retval.append("\\\"");
+          continue;
+        case '\'':
+          retval.append("\\\'");
+          continue;
+        case '\\':
+          retval.append("\\\\");
+          continue;
+        default:
+          if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+            String s = "0000" + Integer.toString(ch, 16);
+            retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+          } else {
+            retval.append(ch);
+          }
+          continue;
+      }
     }
+    return retval.toString();
+  }
+
+  /**
+   * Returns a detailed message for the Error when it is thrown by the
+   * token manager to indicate a lexical error.
+   * Parameters :
+   *    EOFSeen     : indicates if EOF caused the lexical error
+   *    curLexState : lexical state in which this error occurred
+   *    errorLine   : line number when the error occurred
+   *    errorColumn : column number when the error occurred
+   *    errorAfter  : prefix that was seen before this error occurred
+   *    curchar     : the offending character
+   * Note: You can customize the lexical error message by modifying this method.
+   */
+  protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
+    return("Lexical error at line " +
+          errorLine + ", column " +
+          errorColumn + ".  Encountered: " +
+          (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
+          "after : \"" + addEscapes(errorAfter) + "\"");
+  }
+
+  /**
+   * You can also modify the body of this method to customize your error messages.
+   * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+   * of end-users concern, so you can return something like :
+   *
+   *     "Internal Error : Please file a bug report .... "
+   *
+   * from this method for such cases in the release version of your parser.
+   */
+  public String getMessage() {
+    return super.getMessage();
+  }
 
   /*
    * Constructors of various flavors follow.
    */
 
-    /**
-     * Replaces unprintable characters by their escaped (or unicode escaped)
-     * equivalents in the given string
-     */
-    protected static final String addEscapes(String str) {
-        StringBuffer retval = new StringBuffer();
-        char ch;
-        for (int i = 0; i < str.length(); i++) {
-            switch (str.charAt(i)) {
-                case 0:
-                    continue;
-                case '\b':
-                    retval.append("\\b");
-                    continue;
-                case '\t':
-                    retval.append("\\t");
-                    continue;
-                case '\n':
-                    retval.append("\\n");
-                    continue;
-                case '\f':
-                    retval.append("\\f");
-                    continue;
-                case '\r':
-                    retval.append("\\r");
-                    continue;
-                case '\"':
-                    retval.append("\\\"");
-                    continue;
-                case '\'':
-                    retval.append("\\\'");
-                    continue;
-                case '\\':
-                    retval.append("\\\\");
-                    continue;
-                default:
-                    if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
-                        String s = "0000" + Integer.toString(ch, 16);
-                        retval.append("\\u" + s.substring(s.length() - 4, s.length()));
-                    } else {
-                        retval.append(ch);
-                    }
-                    continue;
-            }
-        }
-        return retval.toString();
-    }
+  /** No arg constructor. */
+  public TokenMgrError() {
+  }
 
-    /**
-     * Returns a detailed message for the Error when it is thrown by the
-     * token manager to indicate a lexical error.
-     * Parameters :
-     * EOFSeen     : indicates if EOF caused the lexical error
-     * curLexState : lexical state in which this error occurred
-     * errorLine   : line number when the error occurred
-     * errorColumn : column number when the error occurred
-     * errorAfter  : prefix that was seen before this error occurred
-     * curchar     : the offending character
-     * Note: You can customize the lexical error message by modifying this method.
-     */
-    protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
-        return ("Lexical error at line " +
-                errorLine + ", column " +
-                errorColumn + ".  Encountered: " +
-                (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int) curChar + "), ") +
-                "after : \"" + addEscapes(errorAfter) + "\"");
-    }
+  /** Constructor with message and reason. */
+  public TokenMgrError(String message, int reason) {
+    super(message);
+    errorCode = reason;
+  }
 
-    /**
-     * You can also modify the body of this method to customize your error messages.
-     * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
-     * of end-users concern, so you can return something like :
-     *
-     * "Internal Error : Please file a bug report .... "
-     *
-     * from this method for such cases in the release version of your parser.
-     */
-    public String getMessage() {
-        return super.getMessage();
-    }
+  /** Full Constructor. */
+  public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
+    this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+  }
 }
 /* JavaCC - OriginalChecksum=076ac52ededde06a2bcb85f2834da49c (do not edit this line) */
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/grammar/sspt.jj b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/grammar/sspt.jj
index 96256ee..1b054db 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/grammar/sspt.jj
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/grammar/sspt.jj
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-// Using some token definions from: http://kiwwito.com/build-a-lexical-analyzer-with-javacc/
+// Using some token definitions from: http://kiwwito.com/build-a-lexical-analyzer-with-javacc/
 
 options {
     STATIC = false;
@@ -69,10 +69,10 @@ Object Parameter() :
     Object param;
 }
 {
-     (param = InputParameter() {return param;}) | (param = OutParameter(){return param;})
+     (param = InParameter() {return param;}) | (param = OutParameter(){return param;}) | (param = InOutParameter(){return param;})
 }
 
-InputParameter InputParameter() :
+InParameter InParameter() :
 {
      Token sqlTypeToken;
      String name = null;
@@ -82,11 +82,11 @@ InputParameter InputParameter() :
 }
 {
     ((name = ParameterName() " ")? sqlTypeToken = ParameterSqlType() (scale = Scale())? " " (typeName = ParameterName() " ")? valueSrcToken =
-    InputParameterSrc())
+    InParameterSrc())
     {
         int sqlType = ParseHelper.parseSqlType(sqlTypeToken, classResolver);
 
-        return new InputParameter(name == null ? createNextParameterName() : name, sqlType, valueSrcToken, scale, typeName);
+        return new InParameter(name == null ? createNextParameterName() : name, sqlType, valueSrcToken, scale, typeName);
     }
 }
 
@@ -105,6 +105,24 @@ OutParameter OutParameter() :
     }
 }
 
+InOutParameter InOutParameter() :
+{
+     Token sqlTypeToken;
+     Token valueSrcToken;
+     Integer scale = null;
+     String typeName = null;
+     String outValueMapKey;
+}
+{
+    ("INOUT " sqlTypeToken = ParameterSqlType() (scale = Scale())? " "
+    (typeName = ParameterName() " ")? valueSrcToken = InParameterSrc() " " outValueMapKey = OutHeader())
+    {
+        int sqlType = ParseHelper.parseSqlType(sqlTypeToken, classResolver);
+
+        return new InOutParameter(sqlType, valueSrcToken, scale, typeName, outValueMapKey);
+    }
+}
+
 String ParameterName():
 {
     Token t = null;
@@ -152,7 +170,7 @@ String OutHeader():
         return token.toString();
     }
 }
-Token InputParameterSrc():
+Token InParameterSrc():
 {
     Token ret = null;
 }
diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ParserTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ParserTest.java
index d55c8eb..01e7be4 100644
--- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ParserTest.java
+++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ParserTest.java
@@ -21,12 +21,11 @@ import java.sql.Types;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
-import org.apache.camel.RoutesBuilder;
 import org.apache.camel.component.properties.PropertiesComponent;
 import org.apache.camel.component.sql.stored.template.TemplateParser;
-import org.apache.camel.component.sql.stored.template.ast.InputParameter;
+import org.apache.camel.component.sql.stored.template.ast.InOutParameter;
+import org.apache.camel.component.sql.stored.template.ast.InParameter;
 import org.apache.camel.component.sql.stored.template.ast.OutParameter;
 import org.apache.camel.component.sql.stored.template.ast.ParseRuntimeException;
 import org.apache.camel.component.sql.stored.template.ast.Template;
@@ -38,8 +37,6 @@ public class ParserTest extends CamelTestSupport {
 
     TemplateParser parser;
 
-
-
     @Override
     protected void startCamelContext() throws Exception {
         super.startCamelContext();
@@ -48,35 +45,41 @@ public class ParserTest extends CamelTestSupport {
 
     @Test
     public void shouldParseOk() {
-        Template template = parser.parseTemplate("addnumbers(INTEGER ${header.header1},"
-                + "VARCHAR ${property.property1},BIGINT ${header.header2},OUT INTEGER header1)");
+        Template template = parser.parseTemplate("addnumbers(INTEGER ${header.header1},VARCHAR ${property.property1},"
+                + "BIGINT ${header.header2},INOUT INTEGER ${header.header3} inout1,OUT INTEGER out1)");
 
         Assert.assertEquals("addnumbers", template.getProcedureName());
-        Assert.assertEquals(4, template.getParameterList().size());
+        Assert.assertEquals(5, template.getParameterList().size());
 
         Exchange exchange = createExchangeWithBody(null);
         exchange.getIn().setHeader("header1", 1);
         exchange.setProperty("property1", "constant string");
         exchange.getIn().setHeader("header2", BigInteger.valueOf(2));
+        exchange.getIn().setHeader("header3", BigInteger.valueOf(3));
 
-        InputParameter param1 = (InputParameter) template.getParameterList().get(0);
+        InParameter param1 = (InParameter) template.getParameterList().get(0);
         Assert.assertEquals("_0", param1.getName());
         Assert.assertEquals(Types.INTEGER, param1.getSqlType());
         Assert.assertEquals(1, param1.getValueExtractor().eval(exchange, null));
 
-        InputParameter param2 = (InputParameter) template.getParameterList().get(1);
+        InParameter param2 = (InParameter) template.getParameterList().get(1);
         Assert.assertEquals("_1", param2.getName());
         Assert.assertEquals(Types.VARCHAR, param2.getSqlType());
         Assert.assertEquals("constant string", param2.getValueExtractor().eval(exchange, null));
 
-        InputParameter param3 = (InputParameter) template.getParameterList().get(2);
+        InParameter param3 = (InParameter) template.getParameterList().get(2);
         Assert.assertEquals("_2", param3.getName());
         Assert.assertEquals(Types.BIGINT, param3.getSqlType());
         Assert.assertEquals(BigInteger.valueOf(2L), param3.getValueExtractor().eval(exchange, null));
 
-        OutParameter sptpOutputNode = (OutParameter) template.getParameterList().get(3);
-        Assert.assertEquals(Types.INTEGER, sptpOutputNode.getSqlType());
-        Assert.assertEquals("header1", sptpOutputNode.getOutValueMapKey());
+        InOutParameter inOutNode = (InOutParameter) template.getParameterList().get(3);
+        Assert.assertEquals(Types.INTEGER, inOutNode.getSqlType());
+        Assert.assertEquals("inout1", inOutNode.getOutValueMapKey());
+        Assert.assertEquals(BigInteger.valueOf(3L), inOutNode.getValueExtractor().eval(exchange, null));
+
+        OutParameter outNode = (OutParameter) template.getParameterList().get(4);
+        Assert.assertEquals(Types.INTEGER, outNode.getSqlType());
+        Assert.assertEquals("out1", outNode.getOutValueMapKey());
     }
 
     @Test(expected = ParseRuntimeException.class)
@@ -97,20 +100,20 @@ public class ParserTest extends CamelTestSupport {
         exchange.getIn().setHeader("foo", 1);
         exchange.getIn().setHeader("bar", 3);
         Template template = parser.parseTemplate("ADDNUMBERS2(INTEGER ${header.foo},INTEGER ${header.bar})");
-        assertEquals(1, ((InputParameter) template.getParameterList().get(0)).getValueExtractor().eval(exchange, null));
-        assertEquals(3, ((InputParameter) template.getParameterList().get(1)).getValueExtractor().eval(exchange, null));
+        assertEquals(1, ((InParameter) template.getParameterList().get(0)).getValueExtractor().eval(exchange, null));
+        assertEquals(3, ((InParameter) template.getParameterList().get(1)).getValueExtractor().eval(exchange, null));
     }
 
     @Test
     public void vendorSpecificPositiveSqlType() {
         Template template = parser.parseTemplate("ADDNUMBERS2(1342 ${header.foo})");
-        assertEquals(1342, ((InputParameter) template.getParameterList().get(0)).getSqlType());
+        assertEquals(1342, ((InParameter) template.getParameterList().get(0)).getSqlType());
     }
 
     @Test
     public void vendorSpecificNegativeSqlType() {
         Template template = parser.parseTemplate("ADDNUMBERS2(-1342 ${header.foo})");
-        assertEquals(-1342, ((InputParameter) template.getParameterList().get(0)).getSqlType());
+        assertEquals(-1342, ((InParameter) template.getParameterList().get(0)).getSqlType());
     }
 
     @Test
@@ -120,7 +123,7 @@ public class ParserTest extends CamelTestSupport {
         Exchange exchange = createExchangeWithBody(1);
         Template template = parser.parseTemplate("ADDNUMBERS2(-1342 ${properties:java.naming.factory.initial})");
         assertEquals("org.apache.camel.util.jndi.CamelInitialContextFactory",
-            ((InputParameter) template.getParameterList().get(0)).getValueExtractor().eval(exchange, null));
+            ((InParameter) template.getParameterList().get(0)).getValueExtractor().eval(exchange, null));
     }
 
     @Test
@@ -130,7 +133,7 @@ public class ParserTest extends CamelTestSupport {
 
         Map container = new HashMap();
         container.put("a:", 1);
-        assertEquals(1, ((InputParameter) template.getParameterList().get(0)).getValueExtractor().eval(exchange, container));
+        assertEquals(1, ((InParameter) template.getParameterList().get(0)).getValueExtractor().eval(exchange, container));
     }
 
     @Test
@@ -150,7 +153,7 @@ public class ParserTest extends CamelTestSupport {
         Map<String, String> params = new HashMap<>();
         params.put("P_STR_IN", "a");
         Template template = parser.parseTemplate("IBS.\"Z$IMS_INTERFACE_WS\".TEST_STR(VARCHAR :#P_STR_IN,OUT VARCHAR P_STR_OUT)");
-        assertEquals("a", ((InputParameter) template.getParameterList().get(0)).getValueExtractor().eval(null, params));
+        assertEquals("a", ((InParameter) template.getParameterList().get(0)).getValueExtractor().eval(null, params));
         assertEquals("IBS.\"Z$IMS_INTERFACE_WS\".TEST_STR", template.getProcedureName());
     }
 
@@ -163,32 +166,34 @@ public class ParserTest extends CamelTestSupport {
     @Test
     public void testParameterNameGiven() {
         Template template = parser.parseTemplate("FOO('p_instance_id' INTEGER ${header.foo})");
-        assertEquals("p_instance_id", ((InputParameter) template.getParameterList().get(0)).getName());
+        assertEquals("p_instance_id", ((InParameter) template.getParameterList().get(0)).getName());
     }
 
     @Test
     public void testParameterVendor() {
         Template template = parser.parseTemplate("FOO('p_instance_id' org.apache.camel.component.sql.stored.CustomType.INTEGER ${header.foo})");
-        assertEquals(1, ((InputParameter) template.getParameterList().get(0)).getSqlType());
+        assertEquals(1, ((InParameter) template.getParameterList().get(0)).getSqlType());
     }
 
     @Test
     public void testParameterVendorType() {
         Template template = parser.parseTemplate("FOO('p_instance_id' 2 ${header.foo})");
-        assertEquals(2, ((InputParameter) template.getParameterList().get(0)).getSqlType());
+        assertEquals(2, ((InParameter) template.getParameterList().get(0)).getSqlType());
     }
 
     @Test
     public void testParameterTypeName() {
-        Template template = parser.parseTemplate("FOO('p_instance_id' 2 'p_2' ${header.foo})");
-        assertEquals("p_2", ((InputParameter) template.getParameterList().get(0)).getTypeName());
+        Template template = parser.parseTemplate("FOO('p_instance_1' 1 'p_1' ${header.foo1},"
+                + "INOUT 2 'p_2' ${header.foo2} p_out)");
+        assertEquals("p_1", ((InParameter) template.getParameterList().get(0)).getTypeName());
+        assertEquals("p_2", ((InOutParameter) template.getParameterList().get(1)).getTypeName());
     }
 
 
     @Test
     public void testParameterVendorTypeNegativ() {
         Template template = parser.parseTemplate("FOO('p_instance_id' -2 ${header.foo})");
-        assertEquals(-2, ((InputParameter) template.getParameterList().get(0)).getSqlType());
+        assertEquals(-2, ((InParameter) template.getParameterList().get(0)).getSqlType());
     }
 
     @Test
@@ -221,7 +226,7 @@ public class ParserTest extends CamelTestSupport {
     @Test
     public void testOracleTypesNumeric() {
         Template template = parser.parseTemplate("FOO('p_error_cd' org.apache.camel.component.sql.stored.CustomType.INTEGER(10) ${header.foo})");
-        assertEquals(Integer.valueOf(10), ((InputParameter) template.getParameterList().get(0)).getScale());
+        assertEquals(Integer.valueOf(10), ((InParameter) template.getParameterList().get(0)).getScale());
     }
 
     @Test
diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerInOutTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerInOutTest.java
new file mode 100644
index 0000000..aa74d80
--- /dev/null
+++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerInOutTest.java
@@ -0,0 +1,85 @@
+/**
+ * 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.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
+
+public class ProducerInOutTest extends CamelTestSupport {
+
+    EmbeddedDatabase db;
+
+    @Before
+    public void setUp() throws Exception {
+        db = new EmbeddedDatabaseBuilder()
+                .setType(EmbeddedDatabaseType.DERBY).addScript("sql/storedProcedureTest.sql").build();
+        super.setUp();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+        db.shutdown();
+    }
+
+    @Test
+    public void testInOutStoredProcedure() throws InterruptedException {
+        MockEndpoint mock = getMockEndpoint("mock:query");
+        mock.expectedMessageCount(1);
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put("in1", 0);
+        headers.put("in2", 0);
+        template.requestBodyAndHeaders("direct:query", null, headers);
+
+        assertMockEndpointsSatisfied();
+
+        Exchange exchange = mock.getExchanges().get(0);
+
+        Map results = exchange.getIn().getBody(Map.class);
+        assertEquals(1, results.get("out1"));
+        assertEquals(2, results.get("out2"));
+        assertNotNull(exchange.getIn().getHeader(SqlStoredConstants.SQL_STORED_UPDATE_COUNT));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // required for the sql component
+                getContext().getComponent("sql-stored", SqlStoredComponent.class).setDataSource(db);
+
+                from("direct:query")
+                    .to("sql-stored:INOUTDEMO(INTEGER ${headers.in1},INOUT INTEGER ${headers.in2} out1,OUT INTEGER out2)")
+                    .to("mock:query");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredProcedure.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredProcedure.java
index fea0d11..bc99d45 100644
--- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredProcedure.java
+++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredProcedure.java
@@ -36,7 +36,6 @@ public final class TestStoredProcedure {
         ret[0] = val1 - val2;
     }
 
-
     public static void batchfn(String val1) {
         LOG.info("calling batchfn:{}", val1);
         if (val1 == null) {
@@ -45,9 +44,13 @@ public final class TestStoredProcedure {
         BATCHFN_CALL_COUNTER.incrementAndGet();
     }
 
-
     public static void niladic() {
         LOG.info("nilacid called");
     }
 
+    public static void inoutdemo(int in1, int[] inout1, int[] out1) {
+        LOG.info("calling inoutdemo: {}, {}", inout1[0], out1[0]);
+        inout1[0] = 1;
+        out1[0] = 2;
+    }
 }
diff --git a/components/camel-sql/src/test/resources/sql/storedProcedureTest.sql b/components/camel-sql/src/test/resources/sql/storedProcedureTest.sql
index a1a0750..1cc9540 100644
--- a/components/camel-sql/src/test/resources/sql/storedProcedureTest.sql
+++ b/components/camel-sql/src/test/resources/sql/storedProcedureTest.sql
@@ -33,6 +33,12 @@ CREATE PROCEDURE BATCHFN(VALUE1 CHAR(10))
  EXTERNAL NAME
 'org.apache.camel.component.sql.stored.TestStoredProcedure.batchfn';
 
+CREATE PROCEDURE INOUTDEMO(IN1 INTEGER, INOUT IN2 INTEGER, OUT OUT1 INTEGER)
+ PARAMETER STYLE JAVA
+ LANGUAGE JAVA
+ EXTERNAL NAME
+'org.apache.camel.component.sql.stored.TestStoredProcedure.inoutdemo';
+
 CREATE FUNCTION SUBNUMBERS_FUNCTION(VALUE1 INTEGER, VALUE2 INTEGER)
  RETURNS INTEGER
  PARAMETER STYLE JAVA

-- 
To stop receiving notification emails like this one, please contact
davsclaus@apache.org.

[camel] 02/02: CAMEL-12212 sql-stored: support INOUT parameters (docs)

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit ff245e12bd1b8a29e3a963a42dbf422de0ba03c0
Author: Brett Meyer <br...@3riverdev.com>
AuthorDate: Thu Feb 8 23:52:09 2018 -0500

    CAMEL-12212 sql-stored: support INOUT parameters (docs)
---
 .../src/main/docs/sql-stored-component.adoc        | 57 ++++++++++++++--------
 1 file changed, 38 insertions(+), 19 deletions(-)

diff --git a/components/camel-sql/src/main/docs/sql-stored-component.adoc b/components/camel-sql/src/main/docs/sql-stored-component.adoc
index 664ea9a..19b4e59 100644
--- a/components/camel-sql/src/main/docs/sql-stored-component.adoc
+++ b/components/camel-sql/src/main/docs/sql-stored-component.adoc
@@ -34,7 +34,7 @@ sql-stored:template[?options]
 -----------------------------
 
 Where template is the stored procedure template, where you declare the
-name of the stored procedure and the IN and OUT arguments. 
+name of the stored procedure and the IN, INOUT, and OUT arguments. 
 
 You can also refer to the template in a external file on the file system
 or classpath such as:
@@ -52,7 +52,8 @@ template, as show:
 SUBNUMBERS(
   INTEGER ${headers.num1},
   INTEGER ${headers.num2},
-  OUT INTEGER resultofsub
+  INOUT INTEGER ${headers.num3} out1,
+  OUT INTEGER out2
 )
 --------------------------
 
@@ -119,27 +120,31 @@ method signature. The name of the stored procedure, and then the
 arguments enclosed in parenthesis. An example explains this well:
 
 [source,java]
-----------------------------------------------------------------------------------------------------------
-<to uri="sql-stored:SUBNUMBERS(INTEGER ${headers.num1},INTEGER ${headers.num2},OUT INTEGER resultofsub)"/>
-----------------------------------------------------------------------------------------------------------
+----------------------------------------------------------------------------------------------------------------------------------------------
+<to uri="sql-stored:STOREDSAMPLE(INTEGER ${headers.num1},INTEGER ${headers.num2},INOUT INTEGER ${headers.num3} result1,OUT INTEGER result2)"/>
+----------------------------------------------------------------------------------------------------------------------------------------------
 
-The arguments is declared by a type and then the mapping to the Camel
-message using simple expression. So in this example the first two
-parameters are IN values that are INTEGER type, that maps to the message
-headers. The last parameter is the OUT value, also an INTEGER type.
+The arguments are declared by a type and then a mapping to the Camel
+message using simple expression. So, in this example the first two
+parameters are IN values of INTEGER type, mapped to the message
+headers. The third parameter is INOUT, meaning it accepts an INTEGER
+and then returns a different INTEGER result. The last parameter is
+the OUT value, also an INTEGER type.
 
 In SQL term the stored procedure could be declared as:
 
 [source,java]
-------------------------------------------------------------------------------
-CREATE PROCEDURE SUBNUMBERS(VALUE1 INTEGER, VALUE2 INTEGER,OUT RESULT INTEGER)
-------------------------------------------------------------------------------
+---------------------------------------------------------------------------------------------------------
+CREATE PROCEDURE STOREDSAMPLE(VALUE1 INTEGER, VALUE2 INTEGER, INOUT RESULT1 INTEGER, OUT RESULT2 INTEGER)
+---------------------------------------------------------------------------------------------------------
+
+#### IN Parameters
 
-IN parameters take four parts separated by a space: parameter name, SQL type(with scale), type name and value source.
+IN parameters take four parts separated by a space: parameter name, SQL type (with scale), type name and value source.
 
 Parameter name is optional and will be auto generated if not provided. It must be given between quotes(').
 
-SQL type is required and can be a integer(positive or negative) or reference to integer field in some class.
+SQL type is required and can be an integer (positive or negative) or reference to integer field in some class.
 If SQL type contains a dot then component tries resolve that class and read the given field. For example
 SQL type com.Foo.INTEGER is read from the field INTEGER of class com.Foo. If the type doesn't
 contain comma then class to resolve the integer value will be java.sql.Types.
@@ -147,7 +152,7 @@ Type can be postfixed by scale for example DECIMAL(10) would mean java.sql.Types
 
 Type name is optional and must be given between quotes(').
 
-Value source is required. Value source populates parameter value from the Exchange.
+Value source is required. Value source populates the parameter value from the Exchange.
 It can be either a Simple expression or header location i.e. :#<header name>. For example
 Simple expression ${header.val} would mean that parameter value will be read from the header "val".
 Header location expression :#val would have identical effect.
@@ -168,13 +173,15 @@ URI is identical to previous on except SQL-type is 100 and type name is "mytypen
 
 Actual call will be done using org.springframework.jdbc.core.SqlParameter.
 
-OUT parameters work same way as IN parameters and they they contain three parts: SQL type(with scale), type name and output parameter name.
+#### OUT Parameters
 
-SQL type works as in IN parameters.
+OUT parameters work similarly IN parameters and contain three parts: SQL type(with scale), type name and output parameter name.
 
-Type name is optional and work as in IN parameters.
+SQL type works the same as IN parameters.
 
-Output parameter name is used for the e OUT parameter name and header where the result will be stored there also.
+Type name is optional and also works the same as IN parameters.
+
+Output parameter name is used for the OUT parameter name, as well as the header name where the result will be stored.
 
 [source,java]
 ----------------------------------------------------------------------------------------------------------
@@ -190,6 +197,18 @@ This is identical to previous one but type name will be "mytype".
 
 Actual call will be done using org.springframework.jdbc.core.SqlOutParameter.
 
+#### INOUT Parameters
+
+INOUT parameters are a combination of all of the above.  They receive a value from the exchange, as well as store a
+result as a message header.  The only caveat is that the IN parameter's "name" is skipped.  Instead, the OUT
+parameter's "name" defines both the SQL parameter name, as well as the result header name.
+
+[source,java]
+----------------------------------------------------------------------------------------------------------
+<to uri="sql-stored:MYFUNC(INOUT DECIMAL(10) ${headers.inheader} outheader)"/>
+----------------------------------------------------------------------------------------------------------
+
+Actual call will be done using org.springframework.jdbc.core.SqlInOutParameter.
 
 ### Camel Sql Starter
 

-- 
To stop receiving notification emails like this one, please contact
davsclaus@apache.org.