PhoenixmlDb.XQuery

XdmShape

The one place that states how an XDM sequence and an XDM array are told apart at runtime, and the safe operations over that distinction.

#XdmShape

Namespace: PhoenixmlDb.XQuery

The one place that states how an XDM

sequence

and an XDM

array

are told apart at runtime, and the safe operations over that distinction.

The convention: a SEQUENCE is object?[], an ARRAY is List<object?>, and a single item is itself. Nothing in the type system says so — both are just containers of object?, they have the same shape, and the compiler cannot help. Every consumer has to remember, and five did not:

  • the xquery CLI's serializer printed 12 for [1,2]

  • SerializeItemAdaptive gave sequences array brackets

  • the QT3 runner flattened arrays when binding $result — 56 failures

  • xsl:array's spread would have flattened a nested array member

  • xsl:array handed the finished array on AS a sequence

The last is the one to learn from. It produced the RIGHT answer for the obvious case — <xsl:array select="1 to 5"/> still printed [1,2,3,4,5] — and broke only at the edges, where a one-member array collapsed to its member and composite="yes" silently became a no-op. A fix verified against the reported case alone would have shipped looking complete.

This is mitigation, not the fix. The fix is a wrapper type so the compiler enforces the distinction; that is a refactor of ~90 sites across two shipping engines and has not been done. What this class does is give the three decisions that actually went wrong — "is this one item or many?", "what do I iterate?", "how do I hand this on?" — names that say which answer you are asking for.

#Methods

#ArrayMembers(Object)

The members of

when it is an array;

null

when it is not.

Use when you mean "look inside this array", never to iterate a sequence.

#AsArray(Collections.Generic.IEnumerable<Object>)

Packages

as an ARRAY value — always one item, never unwrapped.

The counterpart to

, and the operation

xsl:array

got wrong by calling

.ToArray()

: that produced a sequence of the members instead of an array.

#AsSequence(Collections.Generic.IReadOnlyList<Object>)

Packages

as a SEQUENCE value: empty stays empty, one item unwraps to itself, and more become

object?[]

.

The unwrap matters: a one-item sequence IS its item in XDM, and leaving it wrapped makes downstream shape tests disagree with the spec.

#IsArray(Object)

True if the value is an XDM array. An array is ONE item.

#IsSequence(Object)

True if the value is a multi-item sequence representation.

#Render(Object)

The XQuery type name of a VALUE — "xs:integer", "xs:byte", "map(*)" — for diagnostics and for

fn:type

.

Renders a value for human display, as

fn:trace

and other diagnostics need.

Exists because CLR class names were leaking into user-visible text. Two symptoms, one cause:

fn:type(xs:byte(1))

reported

"XsTypedInteger"

, and type errors read "but got Int64". Both are the runtime describing its own implementation to someone who wrote XQuery and can only act on XQuery type names. Derived values carry their subtype in a TypeName tag (XsTypedInteger / XsTypedString), so xs:byte(1) reports "xs:byte" while an untagged 1 reports "xs:integer" — which is the correct XDM answer, not an approximation: an untagged integer's dynamic type IS xs:integer and never a proper subtype of it.

Interpolating a value directly gives the CLR type name for anything held in a container: a sequence prints as System.Object[] and an array as System.Collections.Generic.List`1[System.Object]. That is useless in a diagnostic and actively defeats fn:trace, whose entire purpose is letting someone look at a value.

Lives here, beside XdmShape.TypeOf, because this is the third caller to need the shape vocabulary and the first two were only unified after they had already drifted. Rendering is deliberately approximate rather than a serialization: it exists to be read, not parsed, and must never throw or run long on a pathological value.

#SequenceItems(Object)

The items of

viewed as a SEQUENCE: a sequence yields its items, and everything else — including an array — is a single item.

Use when iterating "the things in this value". An array must NOT be spread here: it is one item whose members are its own business.

#TypeNameOf(Object)

The XQuery type name of a value. See

.