Skip to content

Commit

Permalink
CAMEL-11393: sql-stored - Add support for typeNames and scale in grammar
Browse files Browse the repository at this point in the history
* Added docs and output parameter scale and type name
  • Loading branch information
snurmine committed Jun 10, 2017
1 parent b534115 commit 54adc7e
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 32 deletions.
56 changes: 56 additions & 0 deletions components/camel-sql/src/main/docs/sql-stored-component.adoc
Expand Up @@ -132,6 +132,62 @@ In SQL term the stored procedure could be declared as:
CREATE PROCEDURE SUBNUMBERS(VALUE1 INTEGER, VALUE2 INTEGER,OUT RESULT INTEGER) CREATE PROCEDURE SUBNUMBERS(VALUE1 INTEGER, VALUE2 INTEGER,OUT RESULT INTEGER)
------------------------------------------------------------------------------ ------------------------------------------------------------------------------


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.
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.
Type can be postfixed by scale for example DECIMAL(10) would mean java.sql.Types.DECIMAL with scale 10.

Type name is optional and must be given between quotes(').

Value source is required. Value source populates 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.

[source,java]
----------------------------------------------------------------------------------------------------------
<to uri="sql-stored:MYFUNC('param1' org.example.Types.INTEGER(10) ${header.srcValue})"/>
----------------------------------------------------------------------------------------------------------
URI means that the stored procedure will be called with parameter name "param1",
it's SQL type is read from field INTEGER of class org.example.Types and scale will be set to 10.
Input value for the parameter is passed from the header "srcValue".

[source,java]
----------------------------------------------------------------------------------------------------------
<to uri="sql-stored:MYFUNC('param1' 100 'mytypename' ${header.srcValue})"/>
----------------------------------------------------------------------------------------------------------
URI is identical to previous on except SQL-type is 100 and type name is "mytypename".

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.

SQL type works as in IN parameters.

Type name is optional and work as in IN parameters.

Output parameter name is used for the e OUT parameter name and header where the result will be stored there also.

[source,java]
----------------------------------------------------------------------------------------------------------
<to uri="sql-stored:MYFUNC(OUT org.example.Types.DECIMAL(10) outheader1)"/>
----------------------------------------------------------------------------------------------------------
URI means that OUT parameter's name is "outheader1" and result will be but into header "outheader1".

[source,java]
----------------------------------------------------------------------------------------------------------
<to uri="sql-stored:MYFUNC(OUT org.example.Types.NUMERIC(10) 'mytype' outheader1)"/>
----------------------------------------------------------------------------------------------------------
This is identical to previous one but type name will be "mytype".

Actual call will be done using org.springframework.jdbc.core.SqlOutParameter.


### Camel Sql Starter ### Camel Sql Starter


A starter module is available to spring-boot users. When using the starter, A starter module is available to spring-boot users. When using the starter,
Expand Down
Expand Up @@ -75,7 +75,17 @@ private List<SqlParameter> createParams() {
for (Object parameter : template.getParameterList()) { for (Object parameter : template.getParameterList()) {
if (parameter instanceof InputParameter) { if (parameter instanceof InputParameter) {
InputParameter inputParameter = (InputParameter) parameter; InputParameter inputParameter = (InputParameter) parameter;
params.add(new SqlParameter(inputParameter.getName(), inputParameter.getSqlType()));
SqlParameter sqlParameter;
if (inputParameter.getScale() != null) {
sqlParameter = new SqlParameter(inputParameter.getName(), inputParameter.getSqlType(), inputParameter.getScale());
} else if (inputParameter.getTypeName() != null) {
sqlParameter = new SqlParameter(inputParameter.getName(), inputParameter.getSqlType(), inputParameter.getTypeName());
} else {
sqlParameter = new SqlParameter(inputParameter.getName(), inputParameter.getSqlType());
}

params.add(sqlParameter);


} else { } else {
throw new UnsupportedOperationException("Only IN parameters supported by batch!"); throw new UnsupportedOperationException("Only IN parameters supported by batch!");
Expand Down
Expand Up @@ -64,7 +64,16 @@ public TemplateStoredProcedure(JdbcTemplate jdbcTemplate, Template template, boo


} else if (parameter instanceof OutParameter) { } else if (parameter instanceof OutParameter) {
OutParameter outParameter = (OutParameter) parameter; OutParameter outParameter = (OutParameter) parameter;
declareParameter(new SqlOutParameter(outParameter.getOutValueMapKey(), outParameter.getSqlType())); SqlOutParameter sqlOutParameter;
if (outParameter.getScale() != null) {
sqlOutParameter = new SqlOutParameter(outParameter.getOutValueMapKey(), outParameter.getSqlType(), outParameter.getScale());
} else if (outParameter.getTypeName() != null) {
sqlOutParameter = new SqlOutParameter(outParameter.getOutValueMapKey(), outParameter.getSqlType(), outParameter.getTypeName());
} else {
sqlOutParameter = new SqlOutParameter(outParameter.getOutValueMapKey(), outParameter.getSqlType());
}

declareParameter(sqlOutParameter);
setFunction(false); setFunction(false);
} }
} }
Expand Down
Expand Up @@ -18,18 +18,16 @@


public class OutParameter { public class OutParameter {


private String name;
private int sqlType; private int sqlType;
private String outValueMapKey; private String outValueMapKey;
private Integer scale;
private String typeName;


public OutParameter(String name, int sqlType, String outValueMapKey) { public OutParameter(int sqlType, String outValueMapKey, Integer scale, String typeName) {
this.name = name;
this.sqlType = sqlType; this.sqlType = sqlType;
this.outValueMapKey = outValueMapKey; this.outValueMapKey = outValueMapKey;
} this.scale = scale;

this.typeName = typeName;
public String getName() {
return name;
} }


public int getSqlType() { public int getSqlType() {
Expand All @@ -39,4 +37,12 @@ public int getSqlType() {
public String getOutValueMapKey() { public String getOutValueMapKey() {
return outValueMapKey; return outValueMapKey;
} }

public Integer getScale() {
return scale;
}

public String getTypeName() {
return typeName;
}
} }
Expand Up @@ -123,22 +123,31 @@ final public InputParameter InputParameter() throws ParseException {


final public OutParameter OutParameter() throws ParseException { final public OutParameter OutParameter() throws ParseException {
Token sqlTypeToken; Token sqlTypeToken;
String name = null;
String outValueMapKey; String outValueMapKey;
Integer scale = null;
String typeName = null;
jj_consume_token(2); jj_consume_token(2);
sqlTypeToken = ParameterSqlType();
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case PARAMETER_NAME: case SCALE:
name = ParameterName(); scale = Scale();
jj_consume_token(1);
break; break;
default: default:
jj_la1[6] = jj_gen; jj_la1[6] = jj_gen;
; ;
} }
sqlTypeToken = ParameterSqlType();
jj_consume_token(1); 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[7] = jj_gen;
;
}
outValueMapKey = OutHeader(); outValueMapKey = OutHeader();
{if (true) return new OutParameter(name == null ? createNextParameterName() : name, ParseHelper.parseSqlType(sqlTypeToken, classResolver), outValueMapKey);} {if (true) return new OutParameter(ParseHelper.parseSqlType(sqlTypeToken, classResolver), outValueMapKey, scale, typeName);}
throw new Error("Missing return statement in function"); throw new Error("Missing return statement in function");
} }


Expand Down Expand Up @@ -167,7 +176,7 @@ final public Token ParameterSqlType() throws ParseException {
t = jj_consume_token(IDENTIFIER); t = jj_consume_token(IDENTIFIER);
break; break;
default: default:
jj_la1[7] = jj_gen; jj_la1[8] = jj_gen;
jj_consume_token(-1); jj_consume_token(-1);
throw new ParseException(); throw new ParseException();
} }
Expand All @@ -194,7 +203,7 @@ final public Token InputParameterSrc() throws ParseException {
{if (true) return ret;} {if (true) return ret;}
break; break;
default: default:
jj_la1[8] = jj_gen; jj_la1[9] = jj_gen;
jj_consume_token(-1); jj_consume_token(-1);
throw new ParseException(); throw new ParseException();
} }
Expand All @@ -210,13 +219,13 @@ final public Token InputParameterSrc() throws ParseException {
public Token jj_nt; public Token jj_nt;
private int jj_ntk; private int jj_ntk;
private int jj_gen; private int jj_gen;
final private int[] jj_la1 = new int[9]; final private int[] jj_la1 = new int[10];
static private int[] jj_la1_0; static private int[] jj_la1_0;
static { static {
jj_la1_init_0(); jj_la1_init_0();
} }
private static void jj_la1_init_0() { private static void jj_la1_init_0() {
jj_la1_0 = new int[] {0x400,0x18014,0x18014,0x8000,0x8,0x8000,0x8000,0x10010,0x6000,}; jj_la1_0 = new int[] {0x400,0x18014,0x18014,0x8000,0x8,0x8000,0x8,0x8000,0x10010,0x6000,};
} }


/** Constructor with InputStream. */ /** Constructor with InputStream. */
Expand All @@ -230,7 +239,7 @@ public SSPTParser(java.io.InputStream stream, String encoding) {
token = new Token(); token = new Token();
jj_ntk = -1; jj_ntk = -1;
jj_gen = 0; jj_gen = 0;
for (int i = 0; i < 9; i++) jj_la1[i] = -1; for (int i = 0; i < 10; i++) jj_la1[i] = -1;
} }


/** Reinitialise. */ /** Reinitialise. */
Expand All @@ -244,7 +253,7 @@ public void ReInit(java.io.InputStream stream, String encoding) {
token = new Token(); token = new Token();
jj_ntk = -1; jj_ntk = -1;
jj_gen = 0; jj_gen = 0;
for (int i = 0; i < 9; i++) jj_la1[i] = -1; for (int i = 0; i < 10; i++) jj_la1[i] = -1;
} }


/** Constructor. */ /** Constructor. */
Expand All @@ -254,7 +263,7 @@ public SSPTParser(java.io.Reader stream) {
token = new Token(); token = new Token();
jj_ntk = -1; jj_ntk = -1;
jj_gen = 0; jj_gen = 0;
for (int i = 0; i < 9; i++) jj_la1[i] = -1; for (int i = 0; i < 10; i++) jj_la1[i] = -1;
} }


/** Reinitialise. */ /** Reinitialise. */
Expand All @@ -264,7 +273,7 @@ public void ReInit(java.io.Reader stream) {
token = new Token(); token = new Token();
jj_ntk = -1; jj_ntk = -1;
jj_gen = 0; jj_gen = 0;
for (int i = 0; i < 9; i++) jj_la1[i] = -1; for (int i = 0; i < 10; i++) jj_la1[i] = -1;
} }


/** Constructor with generated Token Manager. */ /** Constructor with generated Token Manager. */
Expand All @@ -273,7 +282,7 @@ public SSPTParser(SSPTParserTokenManager tm) {
token = new Token(); token = new Token();
jj_ntk = -1; jj_ntk = -1;
jj_gen = 0; jj_gen = 0;
for (int i = 0; i < 9; i++) jj_la1[i] = -1; for (int i = 0; i < 10; i++) jj_la1[i] = -1;
} }


/** Reinitialise. */ /** Reinitialise. */
Expand All @@ -282,7 +291,7 @@ public void ReInit(SSPTParserTokenManager tm) {
token = new Token(); token = new Token();
jj_ntk = -1; jj_ntk = -1;
jj_gen = 0; jj_gen = 0;
for (int i = 0; i < 9; i++) jj_la1[i] = -1; for (int i = 0; i < 10; i++) jj_la1[i] = -1;
} }


private Token jj_consume_token(int kind) throws ParseException { private Token jj_consume_token(int kind) throws ParseException {
Expand Down Expand Up @@ -338,7 +347,7 @@ public ParseException generateParseException() {
la1tokens[jj_kind] = true; la1tokens[jj_kind] = true;
jj_kind = -1; jj_kind = -1;
} }
for (int i = 0; i < 9; i++) { for (int i = 0; i < 10; i++) {
if (jj_la1[i] == jj_gen) { if (jj_la1[i] == jj_gen) {
for (int j = 0; j < 32; j++) { for (int j = 0; j < 32; j++) {
if ((jj_la1_0[i] & (1<<j)) != 0) { if ((jj_la1_0[i] & (1<<j)) != 0) {
Expand Down
Expand Up @@ -93,14 +93,15 @@ InputParameter InputParameter() :
OutParameter OutParameter() : OutParameter OutParameter() :
{ {
Token sqlTypeToken; Token sqlTypeToken;
String name = null;
String outValueMapKey; String outValueMapKey;
Integer scale = null;
String typeName = null;
} }
{ {
("OUT " (name = ParameterName() " ")? sqlTypeToken = ParameterSqlType() " " outValueMapKey = ("OUT " sqlTypeToken = ParameterSqlType() (scale = Scale())? " " (typeName = ParameterName() " ")? outValueMapKey =
OutHeader()) OutHeader())
{ {
return new OutParameter(name == null ? createNextParameterName() : name, ParseHelper.parseSqlType(sqlTypeToken, classResolver), outValueMapKey); return new OutParameter(ParseHelper.parseSqlType(sqlTypeToken, classResolver), outValueMapKey, scale, typeName);
} }
} }


Expand Down
Expand Up @@ -75,7 +75,6 @@ public void shouldParseOk() {
Assert.assertEquals(BigInteger.valueOf(2L), param3.getValueExtractor().eval(exchange, null)); Assert.assertEquals(BigInteger.valueOf(2L), param3.getValueExtractor().eval(exchange, null));


OutParameter sptpOutputNode = (OutParameter) template.getParameterList().get(3); OutParameter sptpOutputNode = (OutParameter) template.getParameterList().get(3);
Assert.assertEquals("_3", sptpOutputNode.getName());
Assert.assertEquals(Types.INTEGER, sptpOutputNode.getSqlType()); Assert.assertEquals(Types.INTEGER, sptpOutputNode.getSqlType());
Assert.assertEquals("header1", sptpOutputNode.getOutValueMapKey()); Assert.assertEquals("header1", sptpOutputNode.getOutValueMapKey());
} }
Expand Down Expand Up @@ -194,22 +193,45 @@ public void testParameterVendorTypeNegativ() {


@Test @Test
public void testOracleTypesOut() { public void testOracleTypesOut() {
Template template = parser.parseTemplate("FOO(OUT 'p_error_cd' 1 header1)"); Template template = parser.parseTemplate("FOO(OUT 1 p_error_cd)");
assertEquals(1, ((OutParameter) template.getParameterList().get(0)).getSqlType()); assertEquals(1, ((OutParameter) template.getParameterList().get(0)).getSqlType());
} }


@Test @Test
public void testOracleTypesOutParameterVendor() { public void testOracleTypesOutParameterVendor() {
Template template = parser.parseTemplate("FOO(OUT 'p_error_cd' org.apache.camel.component.sql.stored.CustomType.INTEGER header1)"); Template template = parser.parseTemplate("FOO(OUT org.apache.camel.component.sql.stored.CustomType.INTEGER p_error_cd)");
assertEquals(1, ((OutParameter) template.getParameterList().get(0)).getSqlType()); assertEquals(1, ((OutParameter) template.getParameterList().get(0)).getSqlType());
} }


@Test
public void testOracleTypesOutParameterVendorWithScale() {
Template template = parser.parseTemplate("FOO(OUT org.apache.camel.component.sql.stored.CustomType.INTEGER(11) p_error_cd)");
assertEquals(Integer.valueOf(11), ((OutParameter) template.getParameterList().get(0)).getScale());
}

@Test
public void testOracleTypesOutParameterVendorWithTypeName() {
Template template = parser.parseTemplate("FOO(OUT org.apache.camel.component.sql.stored.CustomType.INTEGER 'mytype' p_error_cd)");
assertEquals("mytype", ((OutParameter) template.getParameterList().get(0)).getTypeName());
assertEquals("p_error_cd", ((OutParameter) template.getParameterList().get(0)).getOutValueMapKey());

}



@Test @Test
public void testOracleTypesNumeric() { public void testOracleTypesNumeric() {
Template template = parser.parseTemplate("FOO('p_error_cd' org.apache.camel.component.sql.stored.CustomType.INTEGER(10) ${header.foo})"); 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), ((InputParameter) template.getParameterList().get(0)).getScale());
} }


@Test
public void examplesSyntaxTest() {
parser.parseTemplate("SUBNUMBERS(INTEGER ${headers.num1},INTEGER ${headers.num2},OUT INTEGER resultofsub)");
parser.parseTemplate("MYFUNC('param1' java.sql.Types.INTEGER(10) ${header.srcValue})");
parser.parseTemplate("MYFUNC('param1' 100 'mytypename' ${header.srcValue})");
parser.parseTemplate("MYFUNC(OUT java.sql.Types.DECIMAL(10) outheader1)");
parser.parseTemplate("MYFUNC(OUT java.sql.Types.NUMERIC(10) 'mytype' outheader1)");
}



} }

0 comments on commit 54adc7e

Please sign in to comment.