Search code examples
xqueryxquery-sqlxquery-update

Why do we use [1] behind an order by clause in xquery expressions?


SELECT xText.query (' let $planes := /planes/plane
return <results>
{
  for $x in $planes
  where $x/year >= 1970
  order by ($x/year)[1]
  return ($x/make, $x/model,$x/year )
}
</results>
')
FROM planes

In this code, what is the purpose of [1] in line order by ($x/year)[1]

I have tried to execute this code without using [1] behind order by clause. Then this error has occurred.

XQuery [planes.xtext.query()]: 'order by' requires a singleton (or empty sequence), found operand of type 'xtd:untypedAtomic*'


Solution

  • XQuery 1.0 defined an option called "static type checking": if this option is in force, you need to write queries in such a way that the compiler can tell in advance ("statically") that the result will not be a type error. The operand of "order by" needs to be a singleton, and with static type checking in force, the compiler needs to be able to verify that it will be a singleton, which is why the [1] has been added. It would have been better to write exactly-one($x/year) because this doesn't only keep the compiler happy, it also demands a run-time check that $x/year is actually a singleton.

    Very few XQuery vendors chose to implement static type checking, for very good reasons in my view: it makes queries harder to write, and it actually encourages you to write things like this example that do LESS checking than a system without this "feature".

    In fact, as far as I know the only mainstream (non-academic) implementation that does static type checking is Microsoft's SQL Server.

    Static type checking should not be confused with optimistic type checking where the compiler tells you about things that are bound to fail, but defers checking until run-time for things that might or might not be correct.

    Actually the above is a bit of a guess. It's also possible that some <plane> elements have more than one child called <year>, and that you want to sort on the first of these. That would justify the [1] even on products that don't do static type checking.