Ashish Patil
Ashish Patil

Reputation: 192

"xdmp:eval" throws "XDMP-ARG: -- vars is invalid" exception when "()" [empty sequence] is passed for an optional external parameter

Below is the sample code where $p2 is an optional external parameter (i.e. with ? modifier); the code gives XDMP-ARG: -- vars is invalid exception when empty sequence-() is passed against $p2.

Tried it on Marklogic 8 & 9

let $query := 
"
declare variable $p1 as node()? external;
declare variable $p2 as node()? external;
(
if($p1) then xdmp:log('P1') else ()
,
if($p2) then xdmp:log('P2') else ()
)

"
let $p1 := <p></p>
let $p2 := ()
return 
xdmp:eval(
          $query,
          (xs:QName('p1'), $p1, xs:QName('p2'), $p2)
         )

I expected the code to run and print logs. Can I get some deep insights into how the exception occurred?

Upvotes: 0

Views: 192

Answers (2)

DALDEI
DALDEI

Reputation: 3732

A less-clean alternatives is to use a special marker value to represent 'empty' instead of a literal empty sequence -- which as HTH says, is not preserved when passed IN another sequence (not only do sequences not 'nest' but empty sequences are not 'countable' or 'identifiable' values exactly -- don't know the precise term).

this should demonstrate:

  let $x := ( 1 , () , () , 2 )

$x is now a sequence of length 2 not 4, empty sequences resolve to nothing and the containing sequence 'collapses' (removes the slot, not putting a kind of 'null' value in it)

So a approach in general can be used which you substitute a 'empty token' of some kind. like

  declare variable $empty :=  <empty/>  

(: ANY single value or node type will work that is type compatible with non-empty uses :)

Now

  let $x :=  (1,$empty,$empty,2)  (: sequence length 4 :)

and thus you can pass to eval() replacing () with $empty. The called code needs a test against $empty as well

  if( $p1 != $empty ) then xdmp:log("P1 is" , $p1 )

This technique is used sometimes to create sparse tree structures like binary trees, red/black trees etc.

HTH's solution is better. (this just demonstrates an alternative to help understand the core issue better)

Upvotes: 1

grtjn
grtjn

Reputation: 20414

If you pass in vars as a Sequence of key,val,key,val it needs to be even (multiple of 2). You can't embed sequences like that, as nested sequences get flattened automatically in XQuery. Pass in your vars using a map:map:

map:new((
  map:entry("p1", $p1),
  map:entry("p2", $p2),
))

HTH!

Upvotes: 5

Related Questions