This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 30393 - Asymmetry between try/catch and fn:error looses information
Summary: Asymmetry between try/catch and fn:error looses information
Status: NEW
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XQuery 3.0 (show other bugs)
Version: Working drafts
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: Jonathan Robie
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-01-16 03:53 UTC by Adam Retter
Modified: 2019-01-16 03:53 UTC (History)
0 users

See Also:


Attachments

Description Adam Retter 2019-01-16 03:53:49 UTC
I think this affects both XQuery 3.0, 3.1, and XSLT 3.0.

It is impossible to re-raise an error without loosing information.

If I write a function that catches some exceptions depending on their value, but otherwise re-raises the error, I cannot re-raise the error in such a way that the next catch will receive the same information as the first.

This is because fn:error only takes 3 arguments: $code, $description, and $value.

However catch in XQuery gives us 7 parameters: $err:code, $err:description, $err:value, $err:module, $err:line-number, $err:column-number, $additional.

XSLT catch is the same, but with only 6 parameters, for some reason it omits $additional.

Consider the following code:


function local:catch-conditional($some-function, $errors-to-catch as xs:QName*, $catch-response-function) {
	try {
	  $some-function()
	} catch * {
	  (: only handle those errors we are interested in :)
	  if (empty($errors-to-catch) or $err:code = $errors-to-catch) then
	    $catch-response-function()
	  else
	    (: otherwise re-raise the error :)
	    fn:error($err:code, $err:description, $err:value)

            (: NOTE: we have to discard $err:value, $err:module, $err:line-number, $err:column-number, $additional, as we can't pass to fn:error :)
	}
}


Okay, so I could wrap things in a map and pass them through as the $err:value:

fn:error($err:code, $err:description,
  map {
    xs:QName("err:value") : $err:value,
    xs:QName("err:module") : $err:module,
    xs:QName("err:line-number") : $err:line-number,
    xs:QName("err:column-number") : $err:column-number,
    xs:QName("err:additional") : $err:additional
  }
)


...but that doesn't really work if we start nesting such computations, the first time the error is re-raised, our new $err:value becomes a map, on the second time, it becomes a map of map, and on the third time, a map of map of map, and so on...

I think there should be two additional arity signatures added to fn:error in XPath, one which is fn:error#6 for XSLT and one for fn:error#7 for XQuery. This would allow us to re-raise errors without loosing information or resorting to some hideous hack. Adding such signatures as a small revision to XPath 3.1 F+O would not break anything as far as I can see.