This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 26865 - CastableAs653 and CastableAs654 should expect false instead of true
Summary: CastableAs653 and CastableAs654 should expect false instead of true
Status: CLOSED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XQuery 3 & XPath 3 Test Suite (show other bugs)
Version: Working drafts
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: Michael Kay
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-09-19 19:21 UTC by Josh Spiegel
Modified: 2015-05-05 08:53 UTC (History)
2 users (show)

See Also:


Attachments

Description Josh Spiegel 2014-09-19 19:21:17 UTC
CastableAs653 should expect false instead of true

<test-case name="CastableAs653" xmlns="http://www.w3.org/2010/09/qt-fots-catalog">
      <description>Pattern must match canonical representation (not the result of string())</description>
      <created by="Michael Kay" on="2013-04-08"/>
      <environment ref="derived"/>
      <dependency type="spec" value="XQ10+"/>
      <dependency type="feature" value="schemaImport"/>
      <test><![CDATA[
        import schema namespace d="http://www.w3.org/XQueryTest/derivedTypes";
        12 castable as d:canonicalDecimal
      ]]></test>
      <result>
        <assert-true/>
      </result>
</test-case>

d:canonicalDecimal:

  <xs:simpleType name="canonicalDecimal">
    <xs:restriction base="xs:decimal">
      <xs:pattern value="-?[0-9]+\.[0-9]+"/>
    </xs:restriction>
  </xs:simpleType>


We think the result of this query should be false.

http://www.w3.org/TR/xpath-functions-30/#casting-within-branch

"If the value does not conform to the facets defined for the target type, then a dynamic error is raised [err:FORG0001]. See [XML Schema Part 2: Datatypes Second Edition]. In the case of the pattern facet (which applies to the lexical space rather than the value space), the pattern is tested against the canonical lexical representation of the value, as defined for the source type (or the result of casting the value to an xs:string, in the case of types that have no canonical lexical representation defined for them).

Note that this will cause casts to fail if the pattern excludes the canonical lexical representation of the source type. For example, if the type my:distance is defined as a restriction of xs:decimal with a pattern that requires two digits after the decimal point, casting of an xs:integer to my:distance will always fail, because the canonical representation of an xs:integer does not conform to this pattern."
Comment 1 Josh Spiegel 2014-09-19 20:13:30 UTC
This also applies to CastableAs655 and CastableAs656.
Comment 2 Michael Kay 2014-09-20 15:05:21 UTC
Yes, I think you are probably right.
Comment 3 Michael Kay 2014-09-20 16:06:05 UTC
Fixed as suggested.
Comment 4 Tim Mills 2014-09-23 11:56:14 UTC
I'm not so sure about CastableAs655 and CastableAs656.

Following through the rules:

TT = d:canonicalDouble
ST = xs:decimal
SV = xs:decimal(93.7)

* Casting across the type hierarchy is logically equivalent to three separate steps performed in order. Errors can occur in either of the latter two steps.

* Cast the SV, up the hierarchy, to the primitive type of the source, as described in 18.3.2 Casting from derived types to parent types.

ST' = primitive-type(xs:decimal) = xs:decimal
SV' = xs:decimal(93.7)

* If SV is an instance of xs:string or xs:untypedAtomic, check its value against the pattern facet of TT, and raise a dynamic error [err:FORG0001] if the check fails.

SV is not an instance of xs:string or xs:untypedAtomic.

* Cast the value to the primitive type of TT, as described in 18.1 Casting from primitive types to primitive types.  If TT is derived from xs:NOTATION, assume for the purposes of this rule that casting to xs:NOTATION succeeds.  

ST'' = primitive-type(d:canonicalDouble) = xs:double
SV'' = xs:double(93.7)

Cast the value down to the TT, as described in 18.3.3 Casting within a branch of the type hierarchy

We're now casting a double value (SV'') to d:canonicalDouble.  The canonical form of this value is 9.37E1 which matches the pattern facet.
Comment 5 Josh Spiegel 2014-11-19 18:03:03 UTC
I think Tim is correct (as usual). 

The fix for CastableAs653 and CastableAs654 is correct.  However, the fix for CastableAs655 and CastableAs656 should be reverted.
Comment 6 Michael Kay 2015-01-03 22:24:16 UTC
I think this calls into question the results of CastableAs653 and CastableAs654.

Concentrating on CastableAs653 (shown above), the result seems to hinge on whether xs:integer is considered a primitive type for the purposes of section 18.3.1: specifically, do we regard xs:integer and canonicalDecimal as being derived from the same primitive type?

If they are, then Josh's reasoning in comment #0 is correct.

Section 18.1 says that for the purposes of "this section" xs:integer is treated as a primitive type. It's ambiguous whether 18.3.1 is part of "this section". If we take the view that "this section" refers to the whole of section 18, then 18.3.1 takes us to 18.3.4 Casting across the type hierarchy, and the logic of comment #4 applies. In particular, this means we test the pattern facet against the value considered as an xs:decimal, not against the value considered as an xs:integer, which means the pattern is satisfied and the test returns true. I will raise this as a spec issue.
Comment 7 Michael Kay 2015-01-03 22:46:50 UTC
I have raised bug #27737 against the F+O spec.
Comment 8 Josh Spiegel 2015-01-06 15:20:15 UTC
> Section 18.1 says that for the purposes of "this section" 
> xs:integer is treated as a primitive type.  It's ambiguous 
> whether 18.3.1 is part of "this section".

The second sentence of 18.3.1 clarifies this:

"Note that xs:untypedAtomic, xs:integer and the two derived types of xs:duration:xs:yearMonthDuration and xs:dayTimeDuration are treated as primitive types."
Comment 9 Michael Kay 2015-01-07 11:53:28 UTC
Following WG decision on bug #23777, I am reverting the expected results of tests CastableAs653 and CastableAs654. The cast now succeeds because the relevant section of the spec is "casting across branches of the type hierarchy" (not casting within a branch), and the pattern facet is therefore applied to the value in its canonical form as defined by the xs:decimal type, not its canonical form as an xs:integer.
Comment 10 Tim Mills 2015-02-12 13:30:34 UTC
I hate to reopen this but...

CastableAs653

import schema namespace d="http://www.w3.org/XQueryTest/derivedTypes";
12 castable as d:canonicalDecimal

Following through the rules:

TT = d:canonicalDecimal
ST = xs:integer
SV = xs:integer(12)


Casting a value to a derived type can be separated into four cases. Note that xs:untypedAtomic, xs:integer and the two derived types of xs:duration:xs:yearMonthDuration and xs:dayTimeDuration are treated as primitive types.

*    When SV is an instance of a type that is derived by restriction from TT. This is described in section 19.3.2 Casting from derived types to parent types.

SV xs:integer(12) is not derived by restriction from TT (d:canonicalDecimal)

*    When SV is an instance of a type derived by restriction from the same primitive type as TT. This is described in 19.3.3 Casting within a branch of the type hierarchy.

SV xs:integer(12) has type xs:integer.

xs:integer is derived from xs:decimal, the primitive type of TT (d:canonicalDecimal).  Hence this is a cast within the branch the type hierarchy.


I suspect that the rules can be simplified to:

1.    When SV is an immediate instance of TT, the cast always succeeds, returning SV unchanged.

2.    When SV is an instance of a type that is derived by restriction from TT, the cast proceeds as described in section 19.3.2 Casting from derived types to parent types.

3.    When the primitive type of SV is the same as the primitive type of TT, the cast proceeds as described in 19.3.3 Casting within a branch of the type hierarchy.

4.    Otherwise, the derived type is derived, directly or indirectly, from a different primitive type than the primitive type of ST.  Casting proceeds as described in 19.3.4 Casting across the type hierarchy.
Comment 11 Michael Kay 2015-04-01 22:40:40 UTC
Just a reminder that the test case (653) is

12 castable as d:canonicalDecimal

Section 19.3.1 rule 2 requires us to assess whether " SV is an instance of a type derived by restriction from the same primitive type as TT."

I think this condition is ambiguous, and the ambiguity is the source of the problem. The sentence is worded as if a type can only be derived by restriction from one primitive type, and this is not the case since xs:decimal and xs:integer are both primitive types (as we have defined the term), yet one is derived by restriction from the other.

I think the intended meaning of saying that xs:integer (and xs:dayTimeDuration etc) are primitive types for casting purposes is that for any non-abstract atomic type T there is a primitive type P(T) which is the "nearest" primitive type from which T is derived by restriction, and the rule cited above should read "When P(ST) is the same type as P(TT)". In this case P(ST) is xs:integer and P(TT) is xs:decimal, so rule 2 does not apply.

I suggest the following rewording of the rules in 19.3.1:

Casting a value to a derived type can be separated into four cases. In these rules:

* xs:untypedAtomic, xs:integer and the two derived types of xs:duration:xs:yearMonthDuration and xs:dayTimeDuration are treated as primitive types

* for any atomic type T (other than xs:anyAtomicType), P(T) is the most specific primitive type such that itemType-subtype(T, P(T)) is true.

The rules are then:

1. When ST is the same type as TT: the cast always succeeds, returning SV unchanged.

2. When itemType-subtype(ST, TT) is true: this case is described in section 19.3.2 Casting from derived types to parent types.

3. When P(ST) is the same type as P(TT): this case is described in 19.3.3 Casting within a branch of the type hierarchy.

4. Otherwise (P(ST) is not the same type as P(TT)): this case is described in 19.3.4 Casting across the type hierarchy.
Comment 12 Michael Kay 2015-04-21 16:31:37 UTC
The changes proposed in comment #11 were accepted and have been applied to the spec.