Details
-
Improvement
-
Status: Resolved
-
Minor
-
Resolution: Fixed
-
2.18.5, 2.19.4, 2.20.1
-
None
-
any
-
Unknown
Description
When injecting parameters into the Saxon XQuery engine, the Camel component is not sophisticated enough to inject the parameter as the right type for Saxon to bind it properly.
Let's say we have a XQuery 3.0 compliant variable definition:
declare variable $extParam as xs:boolean external := false();
and we set a property on the exchange
exchange.setProperty("extParam ", true);
our XQuery execution will fail with the following error as the value bound into Saxon is not a Boolean type:
Type error on line 3 column 5
XPTY0004: Required item type of value of variable $extParam is xs:boolean; supplied value
has item type xs:string
The part(s) that need to get more sophisticated are:
- XQueryBuilder.addParameter()
- XQueryBuilder.configureQuery() - set in body
- XQueryBuilder.configureQuery() - set out body
At the bare minimum probably should be supporting to set query parameters for all the basic types like string, boolean, int, decimal etc.
I was thinking of a simple if then else block to check the content type and then call the appropriate Saxon value wrapper but am a bit unsure as the body could be simple type or DOM or Source or something else depending on the marshalling that is going on beforehand.
Here a very basic setup that shows what is happening when Saxon parameters are just bound as Object values:
package com.virginaustralia.bind.xquery; import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; import net.sf.saxon.Configuration; import net.sf.saxon.om.Item; import net.sf.saxon.om.StructuredQName; import net.sf.saxon.query.DynamicQueryContext; import net.sf.saxon.query.XQueryExpression; import net.sf.saxon.value.BooleanValue; import net.sf.saxon.value.ObjectValue; public class ParameterDynamicTest { private static final String TEST_QUERY = new StringBuilder() .append("xquery version \"3.0\" encoding \"UTF-8\";\n") .append("declare variable $extParam as xs:boolean external := false();\n") .append("if($extParam) then(true()) else (false())") .toString(); Configuration conf = new Configuration(); XQueryExpression query; DynamicQueryContext context; @Before public void setup() throws Exception { conf.setCompileWithTracing(true); query = conf.newStaticQueryContext().compileQuery(TEST_QUERY); context = new DynamicQueryContext(conf); } /** * This is what Camel XQueryBuilder executes, which leads to a parameter binding type error. * */ @Test public void testObjectParameter() throws Exception { context.setParameter(StructuredQName.fromClarkName("extParam"), new ObjectValue<>(true)); Item result = query.iterator(context).next(); assertTrue(result instanceof BooleanValue); assertEquals(true, ((BooleanValue) result).getBooleanValue()); } /** * This is what Camel XQueryBuilder should execute to allow Saxon to bind the parameter type properly. */ @Test public void testBooleanParameter() throws Exception { context.setParameter(StructuredQName.fromClarkName("extParam"), BooleanValue.TRUE); Item result = query.iterator(context).next(); assertTrue(result instanceof BooleanValue); assertEquals(true, ((BooleanValue) result).getBooleanValue()); } }