Hello,
On 2018-01-25 22:08, Stephen Chrzanowski wrote:
According to https://www.sqlite.org/datatype3.html
*2. Storage Classes and DatatypesEach value stored in an SQLite database
(or manipulated by the database engine) has one of the following storage
classes: NULL. The value is a NULL value. INTEGER. The value is a
signed integer, stored in 1, 2, 3, 4, 6, or 8 bytes depending on the
magnitude of the value. REAL. The value is a floating point value,
stored as an 8-byte IEEE floating point number. TEXT. The value is a
text string, stored using the database encoding (UTF-8, UTF-16BE or
UTF-16LE). BLOB. The value is a blob of data, stored exactly as it was
input.*
*Each column in an SQLite 3 database is assigned one of the following type
affinities:*
- *TEXT*
- *NUMERIC*
- *INTEGER*
- *REAL*
- *BLOB*
*...*
*A column with NUMERIC affinity may contain values using all five storage
classes. When text data is inserted into a NUMERIC column, the storage
class of the text is converted to INTEGER or REAL (in order of preference)
if such conversion is lossless and reversible.*
*...*
3 paragraphs.
My understanding of this is that since you're using strings as integer
literals, its going to use integer calculations, and not go back to using
"REAL" calculations as you'll be losing information. According to
http://en.cppreference.com/w/cpp/language/types if the engine was able to
predetermine that your string (Which looks like an integer, not a REAL)
it'd have more than a just over (1.7 * 10^308) but you're going to lose a
lot of accuracy as the IEEE specs state that there's 15 digit accuracy, and
you're asking for 23. You can't just stuff that many numbers in a 64-bit
number and maintain accuracy, plus, you're looking at data loss since
you're going from a 23 digit number to a maximum of 15. So according to
documentation, this is working as intended. IMO, the query you gave should
FAULT as its an overrun and what you're asking it to do is impossible at a
64-bit integer level.
For me, it looks like an attorney's speech in a court. From 3 paragraphs
going more or less around a problem you draw conclusions which are
contradictory to the explicit documentation's statement
(https://www.sqlite.org/lang_expr.html#castexpr):
INTEGER: ``When casting a TEXT value to INTEGER, the longest possible
prefix of the value that can be interpreted as an integer number is
extracted from the TEXT value and the remainder ignored. [...] If there
is no prefix that can be interpreted as an integer number, the result of
the conversion is 0.''
To test, I ran this:
C:\Users\schrzanowski.YKF>sqlite3
SQLite version 3.20.0 2017-08-01 13:24:15
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> SELECT CAST('12345678901234567890123' AS INTEGER);
4807115922877859019
If this is good, then what prefix of ``12345678901234567890123'' could
be interpreted as ``4807115922877859019''?
sqlite> SELECT CAST('12345678901234567890123.0' AS INTEGER);
4807115922877859019
If this is good, then what prefix of ``12345678901234567890123'' could
be interpreted as ``4807115922877859019''?
I'm not a developer of SQLite3 by any stretch of the imagination, so I
can't say for certain whether your patch is going to be accepted or not.
In my view, I've never had to deal with numbers that large, and I suspect
this is going to end up being looked at as an edge case.
Ok, to summarize, in your opinion, (a) ``CAST('...' AS INTEGER) => (not
so) quite random number [NSQRN follows]'' and (b) losing of an info
(900...001 => 900...000, etc.) is good (or, at least better then (a) ...
=> {SMALLEST,LARGEST}_INT64; (b) not losing of an info), because:
(a) It is impossible to express some number '112676...878676878' by a
64bit variable, then
(a.1) CAST('toobignum' AS INTEGER) => [NSQRN]) is ok and conforming to
the doc (``working as intended''). CAST('toobignumstring' AS INTEGER) =>
LARGEST_INT64) is not ok and not conforming to the doc (``not working as
intended''), if so, then report that CAST of string numbers
<'9223372036854775809';'18446744073709551615'> AS INTEGER ``is not
working as intended'', or
(a.2) both ways are ``working as intended'', if so, then I proposed a
patch which requires 5 characters and is making a SQLite behave in a
more (IMHO) reasonable way;
(b) I'm sorry - I haven't got your point here. Appending a trailing
space would lose 10 bits because 'toobignumstring' lose accuracy when
converting to FLOAT?? There is other thing then (a). I did not postulate
to convert '4444444444444444444444444444444444444444444444444444' into
exact INT64 value. I agree with you that it is impossible. Simply, I do
not agree that appending a space to a number which _can_ be fully
represented causes that the number needlessly loses an accuracy, and
have proposed the (second part of the) patch which requires copying of
one line of code with less then 20 chars of change, that's all. (Though
it does not solves the problem in full.)
And at the end: an introduction of such small changes is not worth of
price, because you are not using such big numbers and are classifying
the problem as an edge case? Really, is not it? I do not understand why
are you bringing that argument up. Some kind of argument by an authority?
As you said, probably the problem is an edge one. Probably most people
contending with the problem have found more or less trivial solution. I
have just shared my observations of a bit strange behavior and proposed
a solution. What are you trying to say? That [NSQRN] as a result of
conversion of a 'bignumstring' is better that saturated value MIN/MAX.
That needless loss of info without any benefits is good?
-- best regards
Cezary H. Noweta
_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users