This post is about the good practice on how to handle the data issues with XQuery. We store a huge amount of xml data in Sedna XML database, and there happen to be synchronization issues with external systems resulting in xml data issues. One of possible consequences is that an XQuery function may receive an input parameter of an unexpected type. The limitation of the problem is that Sedna supports only XQuery 1.0 and not XQuery 3.0. As a result, try/catch expressions are not yet available for Sedna that makes handling issues harder and nastier. BTW, a while ago I created a feature request for Sedna to add support of XQuery 3.0 - you're welcome to upvote it!
Issue description
Here is the initial XQuery that simply returns the subtitle tag value.
declare function vp:getMapSubtitle($vp as element(value-proposition)?) as xs:string? { data($vp/topicmeta/subtitle) };
We faced a data issue when there appeared two value propositions as an input parameter $vp. It resulted in the following Java exception and Sedna error message:
org.xmldb.api.base.XMLDBException: SEDNA Message: ERROR XPTY0004 It is a type error if, during the static analysis phase, an expression is found to have a static type that is not appropriate for the context in which the expression occurs, or during the dynamic evaluation phase, the dynamic type of a value does not match a required type as specified by the matching rules in 2.5.4 SequenceType Matching. Details: Error in function call. Return value does not match the required type. Expected type is [element(value-proposition)?], more than one item is given. Query line: 7, column:1
It's a pretty good message, contains all the required details to locate the failing code, including the query line. However, it still takes time to navigate there, to make sure that it was indeed a data issue and finally to sort it out. Also it'd be unwise to fix the input parameter type to accept any number of elements as it would result in ignoring the data issues. So the problem here is to reduce the amount of time wasted on unnecessary (and probably repeated) investigations.
Solution
That's why it makes sense to catch the error using if condition as a workaround and provide an appropriate error message with a sufficient data issue description. Here is the new code:
declare function vp:getMapSubtitle($vp as element(value-proposition)*) as xs:string? { if (count($vp) < 2) then data($vp/topicmeta/subtitle) else let $vp_ids := for $single_vp in $vp return data($single_vp/@id) return error(xs:QName("vp_getMapSubtitle"), concat("More than one VP provided: ", string-join($vp_ids, ", "))) };
As a result, in case of the frequent data issue with multiple VP’s, we’ll see the following message in Java application logs:
org.xmldb.api.base.XMLDBException: SEDNA Message: ERROR vp_getMapSubtitle More than one VP provided: vp_ACTT4S-800E, vp_BT136B-600E
This approach saves plenty of time, allowing to resolve the data issue right away. Still it's far from perfect as the message is hidden in the application logs. So the next step will be to show a proper message to the end user and set up a log checker system to notify responsible parties about the data issue.
Comments
Post a Comment