0
votes

I came across a weird issue today. Please see the two XQuery main modules (they are just samples to illustrate the issue). The first one, when executed against ML7, creates 3 documents in the database while the second one doesn't create any. Could someone please explain how these two modules are different in terms of transactional semantics? (Note that the first module uses function mapping)

module 1

xquery version "1.0-ml";

declare variable $xml := 
  <root>
    <child>1</child>
    <child>2</child>
    <child>3</child>
    <child>4</child>
  </root>;

declare function local:create-child-method1($child as element(child))
{
  try {
    let $num := $child/text()
    return 
      if($num eq 2) then 
        fn:error() 
      else 
        xdmp:document-insert($num, <sample>{$num}</sample> )
  } catch ($ex) {
    $ex
  }
};

local:create-child-method1($xml/child)

module 2

xquery version "1.0-ml";

declare variable $xml := 
  <root>
    <child>1</child>
    <child>2</child>
    <child>3</child>
    <child>4</child>
  </root>;

declare function local:create-child-method2($child as element(root))
{
  try {
    for $each-child in $child/child
    let $num := $each-child/text()
    return 
      if($num eq 2) then 
        fn:error() 
      else 
        xdmp:document-insert($num, <sample>{$num}</sample> )
  } catch ($ex) {
    $ex
  }
};

local:create-child-method2($xml)
1

1 Answers

1
votes

It is correct behavior, and not really related to transaction management.

The error case ($num eq 2) gets raised in both cases, but the try catch will capture only the error-case (num = 2), and silently continue in module 1. But throwing the error in module 2 will stop the entire FLWOR from completing, so nothing gets written.

Move the for of the FLWOR to outside the try catch to make module 2 behave like module 1:

xquery version "1.0-ml";

declare variable $xml := <root>
                        <child>1</child>
                        <child>2</child>
                        <child>3</child>
                        <child>4</child>
                    </root>;

declare function local:create-child-method2($child as element(root))
{
  for $each-child in $child/child
  return
    try {
      let $num := $each-child/text()
      return if($num eq 2) then 
                   fn:error() 
             else 
                   xdmp:document-insert($num, <sample>{$num}</sample> )
    } catch ($ex)
    {
      $ex
    }
};

local:create-child-method2($xml)

HTH!