B Type Promotion and Operator Mapping

B.1 Type Promotion

[Definition: Under certain circumstances, an atomic value can be promoted from one type to another. Type promotion is used in evaluating function calls (see 4.4.1.1 Static Function Call Syntax), order by clauses (see 4.15.8 Order By Clause), and operators that accept numeric or string operands (see B.2 Operator Mapping).] The following type promotions are permitted:

  1. Numeric type promotion:

    1. A value of type xs:float (or any type derived by restriction from xs:float) can be promoted to the type xs:double. The result is the xs:double value that is the same as the original value.

    2. A value of type xs:decimal (or any type derived by restriction from xs:decimal) can be promoted to either of the types xs:float or xs:double. The result of this promotion is created by casting the original value to the required type. This kind of promotion may cause loss of precision.

  2. URI type promotion: A value of type xs:anyURI (or any type derived by restriction from xs:anyURI) can be promoted to the type xs:string. The result of this promotion is created by casting the original value to the type xs:string.

    Note:

    Since xs:anyURI values can be promoted to xs:string, functions and operators that compare strings using the default collation also compare xs:anyURI values using the default collation. This ensures that orderings that include strings, xs:anyURI values, or any combination of the two types are consistent and well-defined.

Note that type promotion is different from subtype substitution. For example:

B.2 Operator Mapping

The operator mapping tables in this section list the combinations of types for which the various operators of XQuery 4.0 are defined. [Definition: For each operator and valid combination of operand types, the operator mapping tables specify a result type and an operator function that implements the semantics of the operator for the given types.] The definitions of the operator functions are given in [XQuery and XPath Functions and Operators 4.0]. The result of an operator may be the raising of an error by its operator function, as defined in [XQuery and XPath Functions and Operators 4.0]. The operator function fully defines the semantics of a given operator for the case where the operands are single atomic values of the types given in the table. For the definition of each operator (including its behavior for empty sequences or sequences of length greater than one), see the descriptive material in the main part of this document.

The and and or operators are defined directly in the main body of this document, and do not occur in the operator mapping table.

The operators ne, le, gt, and ge do not occur in the operator mapping table, but are instead defined by the following equivalences:

If an operator in the operator mapping tables expects an operand of type ET, that operator can be applied to an operand of type AT if type AT can be converted to type ET by a combination of type promotion and subtype substitution. For example, a table entry indicates that the gt operator may be applied to two xs:date operands, returning xs:boolean. Therefore, the gt operator may also be applied to two (possibly different) subtypes of xs:date, also returning xs:boolean.

[Definition: When referring to a type, the term numeric denotes the types xs:integer, xs:decimal, xs:float, and xs:double which are all member types of the built-in union type xs:numeric.] An operator whose operands and result are designated as numeric might be thought of as representing four operators, one for each of the numeric types. For example, the numeric + operator might be thought of as representing the following four operators:

Operator First operand type Second operand type Result type
+ xs:integer xs:integer xs:integer
+ xs:decimal xs:decimal xs:decimal
+ xs:float xs:float xs:float
+ xs:double xs:double xs:double

A numeric operator may be validly applied to an operand of type AT if type AT can be converted to any of the four numeric types by a combination of type promotion and subtype substitution. If the result type of an operator is listed as numeric, it means "the first type in the ordered list (xs:integer, xs:decimal, xs:float, xs:double) into which all operands can be converted by subtype substitution and type promotion." As an example, suppose that the type hatsize is derived from xs:integer and the type shoesize is derived from xs:float. Then if the + operator is invoked with operands of type hatsize and shoesize, it returns a result of type xs:float. Similarly, if + is invoked with two operands of type hatsize it returns a result of type xs:integer.

[Definition: In the operator mapping tables, the term Gregorian refers to the types xs:gYearMonth, xs:gYear, xs:gMonthDay, xs:gDay, and xs:gMonth.] For binary operators that accept two Gregorian-type operands, both operands must have the same type (for example, if one operand is of type xs:gDay, the other operand must be of type xs:gDay.)

Binary Operators
Operator Type(A) Type(B) Function Result type
A + B numeric numeric op:numeric-add(A, B) numeric
A + B xs:date xs:yearMonthDuration op:add-yearMonthDuration-to-date(A, B) xs:date
A + B xs:yearMonthDuration xs:date op:add-yearMonthDuration-to-date(B, A) xs:date
A + B xs:date xs:dayTimeDuration op:add-dayTimeDuration-to-date(A, B) xs:date
A + B xs:dayTimeDuration xs:date op:add-dayTimeDuration-to-date(B, A) xs:date
A + B xs:time xs:dayTimeDuration op:add-dayTimeDuration-to-time(A, B) xs:time
A + B xs:dayTimeDuration xs:time op:add-dayTimeDuration-to-time(B, A) xs:time
A + B xs:dateTime xs:yearMonthDuration op:add-yearMonthDuration-to-dateTime(A, B) xs:dateTime
A + B xs:yearMonthDuration xs:dateTime op:add-yearMonthDuration-to-dateTime(B, A) xs:dateTime
A + B xs:dateTime xs:dayTimeDuration op:add-dayTimeDuration-to-dateTime(A, B) xs:dateTime
A + B xs:dayTimeDuration xs:dateTime op:add-dayTimeDuration-to-dateTime(B, A) xs:dateTime
A + B xs:yearMonthDuration xs:yearMonthDuration op:add-yearMonthDurations(A, B) xs:yearMonthDuration
A + B xs:dayTimeDuration xs:dayTimeDuration op:add-dayTimeDurations(A, B) xs:dayTimeDuration
A - B numeric numeric op:numeric-subtract(A, B) numeric
A - B xs:date xs:date op:subtract-dates(A, B) xs:dayTimeDuration
A - B xs:date xs:yearMonthDuration op:subtract-yearMonthDuration-from-date(A, B) xs:date
A - B xs:date xs:dayTimeDuration op:subtract-dayTimeDuration-from-date(A, B) xs:date
A - B xs:time xs:time op:subtract-times(A, B) xs:dayTimeDuration
A - B xs:time xs:dayTimeDuration op:subtract-dayTimeDuration-from-time(A, B) xs:time
A - B xs:dateTime xs:dateTime op:subtract-dateTimes(A, B) xs:dayTimeDuration
A - B xs:dateTime xs:yearMonthDuration op:subtract-yearMonthDuration-from-dateTime(A, B) xs:dateTime
A - B xs:dateTime xs:dayTimeDuration op:subtract-dayTimeDuration-from-dateTime(A, B) xs:dateTime
A - B xs:yearMonthDuration xs:yearMonthDuration op:subtract-yearMonthDurations(A, B) xs:yearMonthDuration
A - B xs:dayTimeDuration xs:dayTimeDuration op:subtract-dayTimeDurations(A, B) xs:dayTimeDuration
A * B numeric numeric op:numeric-multiply(A, B) numeric
A * B xs:yearMonthDuration numeric op:multiply-yearMonthDuration(A, B) xs:yearMonthDuration
A * B numeric xs:yearMonthDuration op:multiply-yearMonthDuration(B, A) xs:yearMonthDuration
A * B xs:dayTimeDuration numeric op:multiply-dayTimeDuration(A, B) xs:dayTimeDuration
A * B numeric xs:dayTimeDuration op:multiply-dayTimeDuration(B, A) xs:dayTimeDuration
A idiv B numeric numeric op:numeric-integer-divide(A, B) xs:integer
A div B numeric numeric op:numeric-divide(A, B) numeric; but xs:decimal if both operands are xs:integer
A div B xs:yearMonthDuration numeric op:divide-yearMonthDuration(A, B) xs:yearMonthDuration
A div B xs:dayTimeDuration numeric op:divide-dayTimeDuration(A, B) xs:dayTimeDuration
A div B xs:yearMonthDuration xs:yearMonthDuration op:divide-yearMonthDuration-by-yearMonthDuration (A, B) xs:decimal
A div B xs:dayTimeDuration xs:dayTimeDuration op:divide-dayTimeDuration-by-dayTimeDuration (A, B) xs:decimal
A mod B numeric numeric op:numeric-mod(A, B) numeric
A eq B numeric numeric op:numeric-equal(A, B) xs:boolean
A eq B xs:boolean xs:boolean op:boolean-equal(A, B) xs:boolean
A eq B xs:string xs:string op:numeric-equal(fn:compare(A, B), 0) xs:boolean
A eq B xs:date xs:date op:date-equal(A, B) xs:boolean
A eq B xs:time xs:time op:time-equal(A, B) xs:boolean
A eq B xs:dateTime xs:dateTime op:dateTime-equal(A, B) xs:boolean
A eq B xs:duration xs:duration op:duration-equal(A, B) xs:boolean
A eq B Gregorian Gregorian op:gYear-equal(A, B) etc. xs:boolean
A eq B xs:hexBinary xs:hexBinary op:hexBinary-equal(A, B) xs:boolean
A eq B xs:base64Binary xs:base64Binary op:base64Binary-equal(A, B) xs:boolean
A eq B xs:QName xs:QName op:QName-equal(A, B) xs:boolean
A eq B xs:NOTATION xs:NOTATION op:NOTATION-equal(A, B) xs:boolean
A eq B xs:hexBinary xs:hexBinary op:hexBinary-equal(A, B) xs:boolean
A eq B xs:base64Binary xs:base64Binary op:hexBinary-equal(A, B) xs:boolean
A lt B numeric numeric op:numeric-less-than(A, B) xs:boolean
A lt B xs:boolean xs:boolean op:boolean-less-than(A, B) xs:boolean
A lt B xs:string xs:string op:numeric-less-than(fn:compare(A, B), 0) xs:boolean
A lt B xs:date xs:date op:date-less-than(A, B) xs:boolean
A lt B xs:time xs:time op:time-less-than(A, B) xs:boolean
A lt B xs:dateTime xs:dateTime op:dateTime-less-than(A, B) xs:boolean
A lt B xs:yearMonthDuration xs:yearMonthDuration op:yearMonthDuration-less-than(A, B) xs:boolean
A lt B xs:dayTimeDuration xs:dayTimeDuration op:dayTimeDuration-less-than(A, B) xs:boolean
A lt B xs:hexBinary xs:hexBinary op:hexBinary-less-than(A, B) xs:boolean
A lt B xs:base64Binary xs:base64Binary op:base64Binary-less-than(A, B) xs:boolean
Unary Operators
Operator Operand type Function Result type
+ A numeric op:numeric-unary-plus(A) numeric
- A numeric op:numeric-unary-minus(A) numeric

B.3 Mathematical Operator Symbols

Various operators written in the grammar using alphabetic keywords (such as and, or, le, ge) can instead be written using mathematical symbols. The equivalents are given in the table below:

Mathematical Operator Symbols
Operator Symbol Codepoint
and x2227
or x2228
eq x2250
ne x2260
lt x22D6
gt x22D7
le x2264
ge x2265
div ÷ xF7
mod
idiv x2A38
union (|) x222A
intersect x2229
except x2216
is x2261
<< (precedes) x226A
>> (follows) x226B
otherwise x22A9
some x2203
every x2200
satisfies x29F4

For example, the expression some $x in $X satisfies $x le 17 can equivalently be written ∃ $x in $X ⧴ $x ≤ 17