XQueryMark

This is a simple benchmark for XQuery. It consists of a list of queries; each query is first described in natural language and then translated in XQuery language. The functional aim of the query is written in curly brackets. The queries should be interpreted over XMark documents according to XMark DTD. Here is an example of XMark document of size 1MB.

Q1 The id, name, and email address of all persons {projecting}

let $doc := doc("auction.xml")
for $p in $doc/site/people/person
return <person id = "{$p/@id}">
         {$p/name}
         {$p/emailaddress}
       </person>

Q2 The id, name, email address, and income of all persons sorted by income {sorting}

let $doc := doc("auction.xml")
for $p in $doc/site/people/person
order by $p/profile/number(@income)
return <person id = "{$p/@id}" income = "{$p/profile/@income}">
         {$p/name}
         {$p/emailaddress}
       </person>

Q3 The id, name, email address, income, and age of all persons of age sorted by income and age {filtering and double sorting}

let $doc := doc("auction.xml")
for $p in $doc/site/people/person
where $p/profile/number(age) >= 18
order by $p/profile/number(@income), $p/profile/number(age)
return <person id = "{$p/@id}" income = "{$p/profile/@income}">
         {$p/name}
         {$p/emailaddress}
         {$p/profile/age}
       </person>

Q4 The initial amount of closed auctions that contain an annotation made by a person with an income greater than 50000 {XPath join}

doc("auction.xml")/site/closed_auctions/closed_auction
[annotation/author/id(@person)[profile/number(@income) > 50000]]/initial

Q5 The name of persons that are bidders of open auctions that are watched by some person {XPath double join}

doc("auction.xml")/site/people/person/watches/watch/
id(@open_auction)/bidder/personref/id(@person)/name

Q6 The name of persons that are bidders of open auctions that are watched by some person that is a bidder of an open auction that is watched by some person {XPath quadruple join}

doc("auction.xml")/site/people/person/watches/watch/id(@open_auction)
/bidder/personref/id(@person)/watches/watch/id(@open_auction)
/bidder/personref/id(@person)/name

Q7 All persons and the open auctions that they watch {Many-to-many relationship, XQuery join using function id()}

let $doc := doc("auction.xml")
for $x in $doc/site/people/person
let $y := $x/watches/watch/id(@open_auction)
return <person id = "{$x/@id}">
         {$y}
       </person>

Q8 All open auctions and the persons that watch them {Many-to-many relationship, XQuery join using a sub-query}

let $doc := doc("auction.xml")
for $x in $doc/site/open_auctions/open_auction
let $y := $doc/site/people/person[watches/watch/@open_auction = $x/@id]
return <auction id = "{$x/@id}">
         {$y}
       </auction>

Q9 All open auctions and the item they sell {One-to-one relationship, XQuery join using function id()}

let $doc := doc("auction.xml")
for $x in $doc/site/open_auctions/open_auction
let $y := $x/itemref/id(@item)
return <auction id = "{$x/@id}">
         {$y}
       </auction>

Q10 All items and the open auction that sell them {One-to-one relationship, pure XQuery join}

let $doc := doc("auction.xml")
for $x in $doc/site/regions/*/item
let $y := $doc/site/open_auctions/open_auction[itemref/@item = $x/@id]
return <item id = "{$x/@id}">
         {$y}
       </item>

Q11 All persons and the European item they bought {XQuery join}

let $doc := doc("auction.xml")
for $p in $doc/site/people/person
let $i := $doc/site/closed_auctions/closed_auction
          [(buyer/@person = $p/@id) and itemref/id(@item)/parent::europe]
          /itemref/id(@item)
where count($i) > 0
return <person id="{$p/@id}">
         {$i}
       </person>

Q12 For each person, the number of open auctions whose current price does not exceed 0.2% of the person's income {XQuery join on values}

let $doc := doc("auction.xml")
for $p in $doc/site/people/person
let $a := $doc/site/open_auctions/open_auction[$p/profile/@income * 0.002 > current]
return <result person = "{$p/name}" 
               income = "{$p/profile/@income}" 
               cheapItems = "{count($a)}"/>

Q13 The keywords contained in annotations of closed auctions {exploiting the recursive part of the DTD structure}

doc("auction.xml")/site/closed_auctions/closed_auction
/annotation/description//keyword

Q14 The paragraph items containing a keyword {searching over the whole dataset and exploiting the recursive part of the DTD structure}

doc("auction.xml")//listitem[descendant::keyword] 

Q15 The current amount of all open auctions whose last increase is at least twice as high as the first increase {accessing elements with a specific position with respect to the document order}

doc("auction.xml")/site/open_auctions/open_auction
[bidder[1]/number(increase) * 2 <= bidder[last()]/number(increase)]/current

Q16 The initial amount of open auctions in which a certain person issued a bid before another person with respect to the document order {exploiting the document order on sibling nodes}

doc("auction.xml")/site/open_auctions/open_auction
[bidder[personref/@person="person18"]/following-sibling::bidder
[personref/@person="person198"]]/initial

Q17 The bids issued by a certain person that precedes, in document order, the last bid in document order of another person {exploiting the document order on all nodes}

doc("auction.xml")/site/open_auctions/open_auction/bidder
[personref/@person="person198"]/preceding::bidder[personref/@person="person18"]

Q18 The initial amount of open auctions having more than 3 bidders {counting}

doc("auction.xml")/site/open_auctions/open_auction[count(bidder) > 3]/initial

Q19 The initial amount of open auctions with a total increase greater or equal to 70 {summing}

doc("auction.xml")/site/open_auctions/open_auction
[sum(bidder/increase) >= 70]/initial

Q20 The name of items whose description contains the word gold {searching for a piece of text}

doc("auction.xml")/site/regions/*/item[contains(description,"gold")]/name

Q21 Categories that are reachable from a given category through an arbitrary path in the category graph {user-define function: transitive closure}

declare namespace fun = 'have.more.fun';
declare function fun:closure($input as node()*, $result as node()*) as node()*
{
   let $current := ($input | doc("auction.xml")//edge[@from = $input]/@to)
   let $new := $current except $result 
   let $all := ($result,$new) 
 
   return
      if(exists($new)) 
      then ($new, fun:closure($new,$all))
      else ()
};

for $c in doc("auction.xml")/fun:closure(id("category0")/@id,())
return <category id="{$c}"/>

XHTML + CSS