Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON UInt64 as string #114

Closed
tobia opened this issue Sep 19, 2016 · 6 comments
Closed

JSON UInt64 as string #114

tobia opened this issue Sep 19, 2016 · 6 comments

Comments

@tobia
Copy link

tobia commented Sep 19, 2016

Is there a reason why Int64 and UInt64 are output as string in JSON?

 :) select toUInt64(1) as n format JSONEachRow;
 {"n":"1"}

 :) select toUInt32(1) as n format JSONEachRow;
 {"n":1}

As far as I can tell, JSON does not put a limit on the size of a number, and most implementations use double precision floats, which are a superset of 53 bit integers (which should be enough for most needs, even if the field is 64 bit wide in CH.)

This stringification causes problems in the frontend code, where one needs to call parseInt() on almost every value returned by queries. Can I override this setting somewhere?

@zhouhong
Copy link

I Found "IDataTypeNumber.h" had wrote like this :
template <> inline void IDataTypeNumber::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
{
writeChar('"', ostr);
serializeText(column, row_num, ostr);
writeChar('"', ostr);
}

I guess that's the reason. And they would like to do that for themselves.

@alexey-milovidov
Copy link
Member

As far as I can tell, JSON does not put a limit on the size of a number, and most implementations use double precision floats, which are a superset of 53 bit integers (which should be enough for most needs, even if the field is 64 bit wide in CH.)

We need to make JSON format compatible with JavaScript.
JavaScript represents numbers as double. It is suitable for some, but not for all UInt64 numbers.
So, we have following variants:

  1. Always place UInt64 values in quotes.
  2. Never place UInt64 values in quotes.
  3. Write values that fit in double as number and other values in quotes.

We are using first variant.

Second variant is inappropriate because it will lead to silent loss of precision in most implementations. But it is suitable for some sophisticated JSON implementations.

Third variant is inappropriate (in my sense) too, because it will lead to surprising, non obvious behaviour. And to have full support of UInt64, you need to call parseInt for some numbers, just as in first variant - so, this variant has no advantages for correct implementations of readers.

@tobia
Copy link
Author

tobia commented Sep 20, 2016

Just to be obvious, Uint32 holds values from 0 to ~ 4 billions, while UInt64 goes from 0 to ~ 18 billion billions.

A JavaScript number is a double precision float, so it can store numbers from 0 to 253 (~ 9 million billions) with exact precision, and subsequent numbers up to the UInt64 range (and beyond) with some loss in precision.

For example the largest UInt64 number, 18 billion billions, is represented as a JavaScript double with an error of ± 0.00000000000001%. All the other numbers have a smaller error (or no error at all if they are < 9 million billions.)

I would argue that for 99.99% of applications, especially JavaScript front-end applications, this level of precision is enough.

My opinion is that it would be much more useful to have UInt64 and Int64 values without quotes by default, which includes all the aggregate results such as count(), and accept the very rare and small loss of precision that happens when one is dealing with numbers greater than 9 million billions in JavaScript.

In the remaining cases (if any) in which the developer really needs to perform exact integer arithmetic on large numbers on the client side, they can always use toString() on the SQL query to transmit the value as a string and use some unlimited precision numeric library on the JavaScript side.

@alexey-milovidov
Copy link
Member

I agree, but only partially.
UInt64 is frequently used for hash codes and identifiers. In that cases, loss of precision is inappropriate.

Maybe better to add setting, which will allow to write UInt64 without quotes?

@tobia
Copy link
Author

tobia commented Sep 21, 2016

Maybe better to add setting, which will allow to write UInt64 without quotes?

I think that would be very appropriate.

@ludv1x
Copy link
Contributor

ludv1x commented Oct 4, 2016

PR #126 adds new option that switches "quoted" and unquoted formats of *Int64 numbers.

blinkov pushed a commit that referenced this issue May 19, 2020
…U. (#11001)

* DOCSUP-1063 (#114)

* added first draft

* added translation for force_optimize_skip_unused_shards and fixed anchors

* fixes

* fixes

* fixed alter.md

Co-authored-by: Elizaveta Mironyuk <emironyuk@yandex-team.ru>

* CLICKHOUSEDOCS-627: Updated templated.

* Fixed markup.

* CLICKHOUSEDOCS-627: Fixed links.

Co-authored-by: Sergei Shtykov <bayonet@yandex-team.ru>
Co-authored-by: emironyuk <62014692+emironyuk@users.noreply.github.com>
Co-authored-by: Elizaveta Mironyuk <emironyuk@yandex-team.ru>
Enmk added a commit to Enmk/ClickHouse that referenced this issue Feb 21, 2022
taiyang-li pushed a commit to bigo-sg/ClickHouse that referenced this issue Sep 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants