Affects Version/s: V4.01_CSD02
Fix Version/s: V4.01_CSD03
1) Restrict the 'special' numeric values to types Single, Double, and Decimal (scale=floating), partly revoking
2) keep 4.0 behavior for div operator - fail for division by zero for dividends other than Single, Double, and Decimal(Scale=floating)
3) support fail-safe division by zero (resulting in -INF, INF, or null) for all numeric types only in the new divby operator1) Restrict the 'special' numeric values to types Single, Double, and Decimal (scale=floating), partly revoking ODATA-920 2) keep 4.0 behavior for div operator - fail for division by zero for dividends other than Single, Double, and Decimal(Scale=floating) 3) support fail-safe division by zero (resulting in -INF, INF, or null) for all numeric types only in the new divby operator
Resolution:https://tools.oasis-open.org/version-control/browse/wsvn/odata/trunk/4.01%20spec/ABNF/odata-abnf-construction-rules.txt?op=diff&rev=1064 https://www.oasis-open.org/committees/download.php/61369/odata-v4.01-wd03-part2-url-conventions-2017-08-10.docx https://www.oasis-open.org/committees/download.php/61370/odata-csdl-json-v4.01-wd02-2017-08-10.docx https://www.oasis-open.org/committees/download.php/61371/odata-csdl-xml-v4.01-wd03-2017-08-10.docx
Public Review Comment https://lists.oasis-open.org/archives/odata-comment/201707/msg00002.html
Comment on: 4.01 Committee Specification Draft 02 / Public Review Draft 02
One of the new provisions in 4.01 is:
All numeric types allow the special numeric values ‑INF, INF, and NaN
This feels onerous given typical technologies for storing integer numeric types. The ABNF for values of Int16, for example, now reads:
int16Value = [ SIGN ] 1*5DIGIT / nanInfinity ; numbers in the range from -32768 to 32767
Clearly this now requires MORE than 16 bits to store.
Given that the numeric integer types are typically used as keys for entities there are some odd implications too. Clearly the definitions of INF and -INF can still work as they compare equal to themselves and top/tail the value range when ordering. I'm more concerned about NaN which doesn't compare equal to itself, this is likely to cause issues if it is used as the value of an entity key. (I believe PostgreSQL allows these values as keys but treats Nan == Nan as true and Nan > x as true for all x != Nan, this goes against IEEE but seems necessary if they are to be used in context where ordering is required.)
To use XML schema vocab, it feels like the abstract values and lexical representations have become muddled. The desire to use special values in JSON representations of integers has serious implications for the abstract value space.
The 'special' values INF, -INF and NaN are actually values in the abstract value spaces of Single and Double types (as per IEEE, extendable to Decimal). They are not universal special (numeric) values with a status similar to 'null'. It feels like the language of the specification is sliding toward treating all of these in a similar way. Witness the definition of equals in Part 2 §22.214.171.124.1
Each of the special values null -INF, and INF is equal to itself, and only to itself.
The special value NaN is not equal to anything, even to itself.
You might find this SO answer in relation to C++ interesting: https://stackoverflow.com/questions/38795544/is-casting-of-infinity-to-integer-undefined I particularly like the parenthetical comment...
truncation of infinity is still infinity, and infinity cannot be represented in int (I hope there's no question about this part)
There's a serious point to this quote though. W.r.t. https://issues.oasis-open.org/browse/ODATA-785 I reject point (2) in the working proposal (add +inf/-inf/nan to int) for this reason.
My proposal is to clarify that the 'special' numeric values are values of type Single, Double or Decimal only. You already have sufficient type promotion to resolve any ambiguity when parsing the literals. For example, the less contentious promotion of the constant parsed from the string "42" to any of the numeric types is already accepted without the special modifiers used in OData 2/3.
The second part of my proposal is that if the abstract result of an operation cannot be represented in the return type defined for that operation then the result should be the special value null. This would include the special case of integer division by zero (where 4.0 says the request fails) but also covers overflow of integers in other operations. I sense the panel dislikes failing requests so my proposal fixes that by silently carrying on - the alternative is to continue to raise an exception or put in some more general provision that says that an expression that fails with a division by zero is treat as null (WITHOUT continuing the computation). The latter version has less of an impact on existing behaviour in 4.0 I guess so might be worth considering.
The NULLIF pattern for treat division by 0 as null is fairly widespread though and it is more consistent with the definition of cast:
Numeric primitive types are cast to each other with appropriate rounding. The cast fails if the integer
part doesn't fit into target type.
If the cast fails, the cast function returns null.
As a follow-up point on your open issue: https://issues.oasis-open.org/browse/ODATA-919
The idea of doing general type promotion to the largest integer type makes sense to me, if the result overflows Int64 then you'd get null (according to my proposal) which is freely castable to any of the integer types.
But I propose that Single operations that overflow Single results should be promoted to Double in a similar way. The definition of cast will need to be modified to allow for the cast of a Double to Single with overflow resulting in INF (not a failed cast). The proposed difference between the way integers and floating point numbers behave in this respect is precisely because the latter can represent INF.
Hope this helps.