Predicates

A predicate selects nodes in a path expression that satisfy a given expression. Here is an example:

 $auction/articles/article[start_date <= date()]  has type  element(article)* 

The path extracts one or more articles from the auction, and then selects zero, one, or more of these.

Sometimes, predicates are intended to single out a particular item, but, in general, the type system is not clever enough to know this.

 $auction/articles/article[@id=$id]  has type  element(article)* 

Here the type assigned suggests that there may be zero, one, or many articles. But if the id attribute is used as a key, then there will be at most one result, and if $id is bound to a valid key, then there will be exactly one result. XQuery provides three functions, exactly-one , zero-or-one , and one-or-more to allow the query writer to provide additional information about the number of items that might be returned by an expression.

 exactly-one($auction/articles/article[@id=$id])  has type  element(article) zero-or-one($auction/articles/article[@id=$id])  has type  element(article)? 

At analysis time, these occurrence functions adjust the type of their result accordingly ; at evaluation time, they check that the argument sequence contains a number of items in the specified range and raise an error if it does not.

The designers of XQuery separated errors into two classes: type errors are either caught at analysis time (if static typing is in use) or at evaluation time (if static typing is not in use); other errors may be caught at any time. Occurrence functions only raise errors at evaluation time, so the errors they raise are not classed as type errors.

Predicates may be used to pick out elements according to their position. Predicates with numeric type (rather than Boolean) select elements at the current position; and a Boolean predicate may mention the special function position() . Here are some examples:

 $auction/articles/article[1]  has type  element(article) $auction/articles/article[2]  has type  element(article)? $auction/articles/article[position() > 2]  has type  element(article)* 

The first expression selects the first article; since there are one or more articles in an auction, this always yields exactly one article. The second expression selects the second article; since there are one or more articles in an auction, this may yield zero or one articles. The third expression selects all articles after the second article; since there are one or more articles in an auction, this may yield zero or more articles.

More than one predicate may appear in a path expression.

 $auction/articles/article[start_date <= current_date()]  has type  element(article)* $auction/articles/article[start_date <= current_date()][1]  has type  element(article)? 

The first expression picks out all articles with a start date before the current date; there may be zero or more such articles. The second predicate selects the first of these, if there is a first, and so has a type indicating zero or one article. Sometimes, the query writer will know that there is at least one auction currently in progress, and will want to adjust the type accordingly.

 exactly-one($auction/articles/article[start_date <= current_date()][1])  has type  element(article) 

This uses the exactly - one() function described above.

The following two expressions have the same meaning, but different types.

 $auction/articles/article[1] has type element(article) $auction/articles/article[position() = 1]  has type  element(article)* 

The designers of XQuery decided to include a special type rule for the case where the predicate is an integer literal, because it is so common. Note, however, if the predicate is an integer-valued expression, then no special rule applies, and the type can be more general than one might expect. Here are four examples:

 $auction/articles/article[$i]  has type  element(article)* $auction/articles/article[last()]  has type  element(article)* $auction/articles/article[position()]  has type  element(article)* $auction/articles/(let $i := position() return article[$i])  has type  element(article)* 

These have exactly the same meaning, and the same type, as these examples:

 $auction/articles/article[position() = $i]  has type  element(article)* $auction/articles/article[position() = last()]  has type  element(article)* $auction/articles/article[position() = position()]  has type  element(article)* $auction/articles/(let $i := position() return article[position() = $i])  has type  element(article)* 

Note that the second-to-last of these will return every article, which shows why, in general, a predicate that has an integer value might still select more than one item.



XQuery from the Experts(c) A Guide to the W3C XML Query Language
Beginning ASP.NET Databases Using VB.NET
ISBN: N/A
EAN: 2147483647
Year: 2005
Pages: 102

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net