diff --git a/dbms/include/DB/DataStreams/JSONCompactRowOutputStream.h b/dbms/include/DB/DataStreams/JSONCompactRowOutputStream.h index baf1a880fcd..30b10920c58 100644 --- a/dbms/include/DB/DataStreams/JSONCompactRowOutputStream.h +++ b/dbms/include/DB/DataStreams/JSONCompactRowOutputStream.h @@ -14,7 +14,7 @@ namespace DB class JSONCompactRowOutputStream : public JSONRowOutputStream { public: - JSONCompactRowOutputStream(WriteBuffer & ostr_, const Block & sample_, bool write_statistics_); + JSONCompactRowOutputStream(WriteBuffer & ostr_, const Block & sample_, bool write_statistics_, bool force_quoting_); void writeField(const IColumn & column, const IDataType & type, size_t row_num) override; void writeFieldDelimiter() override; diff --git a/dbms/include/DB/DataStreams/JSONEachRowRowOutputStream.h b/dbms/include/DB/DataStreams/JSONEachRowRowOutputStream.h index 6ca1b33563f..a4686c7e078 100644 --- a/dbms/include/DB/DataStreams/JSONEachRowRowOutputStream.h +++ b/dbms/include/DB/DataStreams/JSONEachRowRowOutputStream.h @@ -14,7 +14,7 @@ namespace DB class JSONEachRowRowOutputStream : public IRowOutputStream { public: - JSONEachRowRowOutputStream(WriteBuffer & ostr_, const Block & sample); + JSONEachRowRowOutputStream(WriteBuffer & ostr_, const Block & sample, bool force_quoting_ = true); void writeField(const IColumn & column, const IDataType & type, size_t row_num) override; void writeFieldDelimiter() override; @@ -30,6 +30,7 @@ private: WriteBuffer & ostr; size_t field_number = 0; Names fields; + bool force_quoting; }; } diff --git a/dbms/include/DB/DataStreams/JSONRowOutputStream.h b/dbms/include/DB/DataStreams/JSONRowOutputStream.h index e1da63a80ea..da4cd50a458 100644 --- a/dbms/include/DB/DataStreams/JSONRowOutputStream.h +++ b/dbms/include/DB/DataStreams/JSONRowOutputStream.h @@ -16,7 +16,7 @@ class JSONRowOutputStream : public IRowOutputStream { public: JSONRowOutputStream(WriteBuffer & ostr_, const Block & sample_, - bool write_statistics_); + bool write_statistics_, bool force_quoting_ = true); void writeField(const IColumn & column, const IDataType & type, size_t row_num) override; void writeFieldDelimiter() override; @@ -68,6 +68,7 @@ protected: Progress progress; Stopwatch watch; bool write_statistics; + bool force_quoting; }; } diff --git a/dbms/include/DB/DataTypes/DataTypeAggregateFunction.h b/dbms/include/DB/DataTypes/DataTypeAggregateFunction.h index e811a919cce..b081f964226 100644 --- a/dbms/include/DB/DataTypes/DataTypeAggregateFunction.h +++ b/dbms/include/DB/DataTypes/DataTypeAggregateFunction.h @@ -53,7 +53,7 @@ public: void deserializeTextEscaped(IColumn & column, ReadBuffer & istr) const override; void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override; - void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; + void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override; void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override; void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; void serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; diff --git a/dbms/include/DB/DataTypes/DataTypeArray.h b/dbms/include/DB/DataTypes/DataTypeArray.h index d6553213c3c..2d70c42a6a2 100644 --- a/dbms/include/DB/DataTypes/DataTypeArray.h +++ b/dbms/include/DB/DataTypes/DataTypeArray.h @@ -46,7 +46,7 @@ public: void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override; - void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; + void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override; void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override; void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; diff --git a/dbms/include/DB/DataTypes/DataTypeDate.h b/dbms/include/DB/DataTypes/DataTypeDate.h index f9d21e0442f..1509f00b987 100644 --- a/dbms/include/DB/DataTypes/DataTypeDate.h +++ b/dbms/include/DB/DataTypes/DataTypeDate.h @@ -58,7 +58,7 @@ public: static_cast(column).getData().push_back(x); /// Важно делать это в конце - для exception safety. } - void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override + void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override { writeChar('"', ostr); serializeText(column, row_num, ostr); diff --git a/dbms/include/DB/DataTypes/DataTypeDateTime.h b/dbms/include/DB/DataTypes/DataTypeDateTime.h index a944b67aa1a..b4f9071da37 100644 --- a/dbms/include/DB/DataTypes/DataTypeDateTime.h +++ b/dbms/include/DB/DataTypes/DataTypeDateTime.h @@ -58,7 +58,7 @@ public: static_cast(column).getData().push_back(x); /// Важно делать это в конце - для exception safety. } - void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override + void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override { writeChar('"', ostr); serializeText(column, row_num, ostr); diff --git a/dbms/include/DB/DataTypes/DataTypeEnum.h b/dbms/include/DB/DataTypes/DataTypeEnum.h index 2b9071c1533..69b3db87cb5 100644 --- a/dbms/include/DB/DataTypes/DataTypeEnum.h +++ b/dbms/include/DB/DataTypes/DataTypeEnum.h @@ -81,7 +81,7 @@ public: void deserializeTextEscaped(IColumn & column, ReadBuffer & istr) const override; void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override; - void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; + void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override; void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override; void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; void serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; diff --git a/dbms/include/DB/DataTypes/DataTypeFixedString.h b/dbms/include/DB/DataTypes/DataTypeFixedString.h index 76c2c7918fb..3fd85e5ae06 100644 --- a/dbms/include/DB/DataTypes/DataTypeFixedString.h +++ b/dbms/include/DB/DataTypes/DataTypeFixedString.h @@ -52,7 +52,7 @@ public: void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override; - void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; + void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override; void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override; void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; diff --git a/dbms/include/DB/DataTypes/DataTypeString.h b/dbms/include/DB/DataTypes/DataTypeString.h index 8271fad42b3..f230594c2a5 100644 --- a/dbms/include/DB/DataTypes/DataTypeString.h +++ b/dbms/include/DB/DataTypes/DataTypeString.h @@ -39,7 +39,7 @@ public: void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override; - void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; + void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override; void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override; void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; diff --git a/dbms/include/DB/DataTypes/DataTypeTuple.h b/dbms/include/DB/DataTypes/DataTypeTuple.h index 59cd8f1f1c2..d26f684490f 100644 --- a/dbms/include/DB/DataTypes/DataTypeTuple.h +++ b/dbms/include/DB/DataTypes/DataTypeTuple.h @@ -31,7 +31,7 @@ public: void deserializeTextEscaped(IColumn & column, ReadBuffer & istr) const override; void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override; - void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; + void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override; void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override; void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; diff --git a/dbms/include/DB/DataTypes/IDataType.h b/dbms/include/DB/DataTypes/IDataType.h index 88a01121c98..7ba9055b488 100644 --- a/dbms/include/DB/DataTypes/IDataType.h +++ b/dbms/include/DB/DataTypes/IDataType.h @@ -87,9 +87,10 @@ public: */ virtual void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr) const = 0; - /** Текстовая сериализация в виде литерала для использования в формате JSON. + /** Text serialization intended for using in JSON format. + * If values can be serizlized without quotes, force_quoting parameter forces to brace them into quotes (make sense for Int64 types). */ - virtual void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const = 0; + virtual void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool force_quoting) const = 0; virtual void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const = 0; /** Текстовая сериализация для подстановки в формат XML. diff --git a/dbms/include/DB/DataTypes/IDataTypeDummy.h b/dbms/include/DB/DataTypes/IDataTypeDummy.h index 33daf8af761..1cbae93974e 100644 --- a/dbms/include/DB/DataTypes/IDataTypeDummy.h +++ b/dbms/include/DB/DataTypes/IDataTypeDummy.h @@ -38,7 +38,7 @@ public: void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override { throwNoSerialization(); } void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override { throwNoSerialization(); } - void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override { throwNoSerialization(); } + void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override { throwNoSerialization(); } void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override { throwNoSerialization(); } void serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override { throwNoSerialization(); } diff --git a/dbms/include/DB/DataTypes/IDataTypeNumber.h b/dbms/include/DB/DataTypes/IDataTypeNumber.h index c65fdf7acae..234d294eeab 100644 --- a/dbms/include/DB/DataTypes/IDataTypeNumber.h +++ b/dbms/include/DB/DataTypes/IDataTypeNumber.h @@ -56,7 +56,7 @@ public: deserializeText(column, istr); } - inline void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override; + inline void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override; void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override { @@ -121,7 +121,7 @@ public: void deserializeTextEscaped(IColumn & column, ReadBuffer & istr) const override {} void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override {} void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override {} - void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override {} + void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override {} void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override {} void serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override {} void deserializeTextCSV(IColumn & column, ReadBuffer & istr, const char delimiter) const override {} @@ -129,26 +129,30 @@ public: Field getDefault() const override { return {}; } }; -template inline void IDataTypeNumber::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const +template inline void IDataTypeNumber::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const { serializeText(column, row_num, ostr); } -template <> inline void IDataTypeNumber::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const +template <> inline void IDataTypeNumber::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool force_quoting) const { - writeChar('"', ostr); + if (force_quoting) + writeChar('"', ostr); serializeText(column, row_num, ostr); - writeChar('"', ostr); + if (force_quoting) + writeChar('"', ostr); } -template <> inline void IDataTypeNumber::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const +template <> inline void IDataTypeNumber::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool force_quoting) const { - writeChar('"', ostr); + if (force_quoting) + writeChar('"', ostr); serializeText(column, row_num, ostr); - writeChar('"', ostr); + if (force_quoting) + writeChar('"', ostr); } -template <> inline void IDataTypeNumber::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const +template <> inline void IDataTypeNumber::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const { auto x = static_cast(column).getData()[row_num]; if (likely(std::isfinite(x))) @@ -157,7 +161,7 @@ template <> inline void IDataTypeNumber::serializeTextJSON(const IColum writeCString("null", ostr); } -template <> inline void IDataTypeNumber::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const +template <> inline void IDataTypeNumber::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const { auto x = static_cast(column).getData()[row_num]; if (likely(std::isfinite(x))) diff --git a/dbms/include/DB/Interpreters/Settings.h b/dbms/include/DB/Interpreters/Settings.h index 6124be139a3..9e1577d9a74 100644 --- a/dbms/include/DB/Interpreters/Settings.h +++ b/dbms/include/DB/Interpreters/Settings.h @@ -225,7 +225,10 @@ struct Settings M(SettingBool, add_http_cors_header, false) \ \ /** Skip columns with unknown names from input data (it works for JSONEachRow and TSKV formats). */ \ - M(SettingBool, input_format_skip_unknown_fields, false) + M(SettingBool, input_format_skip_unknown_fields, false) \ + \ + /** Controls quoting of 64-bit integers in JSON output format. */ \ + M(SettingBool, output_format_json_quote_64bit_integers, true) /// Всевозможные ограничения на выполнение запроса. Limits limits; diff --git a/dbms/src/DataStreams/FormatFactory.cpp b/dbms/src/DataStreams/FormatFactory.cpp index 671efc310a7..71729c27bb7 100644 --- a/dbms/src/DataStreams/FormatFactory.cpp +++ b/dbms/src/DataStreams/FormatFactory.cpp @@ -135,12 +135,13 @@ static BlockOutputStreamPtr getOutputImpl(const String & name, WriteBuffer & buf return std::make_shared(std::make_shared(buf)); else if (name == "JSON") return std::make_shared(std::make_shared(buf, sample, - context.getSettingsRef().output_format_write_statistics)); + context.getSettingsRef().output_format_write_statistics, context.getSettingsRef().output_format_json_quote_64bit_integers)); else if (name == "JSONCompact") return std::make_shared(std::make_shared(buf, sample, - context.getSettingsRef().output_format_write_statistics)); + context.getSettingsRef().output_format_write_statistics, context.getSettingsRef().output_format_json_quote_64bit_integers)); else if (name == "JSONEachRow") - return std::make_shared(std::make_shared(buf, sample)); + return std::make_shared(std::make_shared(buf, sample, + context.getSettingsRef().output_format_json_quote_64bit_integers)); else if (name == "XML") return std::make_shared(std::make_shared(buf, sample, context.getSettingsRef().output_format_write_statistics)); diff --git a/dbms/src/DataStreams/JSONCompactRowOutputStream.cpp b/dbms/src/DataStreams/JSONCompactRowOutputStream.cpp index 6b3ea17be0e..81b1c22180a 100644 --- a/dbms/src/DataStreams/JSONCompactRowOutputStream.cpp +++ b/dbms/src/DataStreams/JSONCompactRowOutputStream.cpp @@ -6,15 +6,15 @@ namespace DB { -JSONCompactRowOutputStream::JSONCompactRowOutputStream(WriteBuffer & ostr_, const Block & sample_, bool write_statistics_) - : JSONRowOutputStream(ostr_, sample_, write_statistics_) +JSONCompactRowOutputStream::JSONCompactRowOutputStream(WriteBuffer & ostr_, const Block & sample_, bool write_statistics_, bool force_quoting_) + : JSONRowOutputStream(ostr_, sample_, write_statistics_, force_quoting_) { } void JSONCompactRowOutputStream::writeField(const IColumn & column, const IDataType & type, size_t row_num) { - type.serializeTextJSON(column, row_num, *ostr); + type.serializeTextJSON(column, row_num, *ostr, force_quoting); ++field_number; } @@ -56,7 +56,7 @@ void JSONCompactRowOutputStream::writeTotals() writeChar(',', *ostr); const ColumnWithTypeAndName & column = totals.getByPosition(i); - column.type->serializeTextJSON(*column.column.get(), 0, *ostr); + column.type->serializeTextJSON(*column.column.get(), 0, *ostr, force_quoting); } writeChar(']', *ostr); @@ -64,7 +64,7 @@ void JSONCompactRowOutputStream::writeTotals() } -static void writeExtremesElement(const char * title, const Block & extremes, size_t row_num, WriteBuffer & ostr) +static void writeExtremesElement(const char * title, const Block & extremes, size_t row_num, WriteBuffer & ostr, bool force_quoting) { writeCString("\t\t\"", ostr); writeCString(title, ostr); @@ -77,7 +77,7 @@ static void writeExtremesElement(const char * title, const Block & extremes, siz writeChar(',', ostr); const ColumnWithTypeAndName & column = extremes.getByPosition(i); - column.type->serializeTextJSON(*column.column.get(), row_num, ostr); + column.type->serializeTextJSON(*column.column.get(), row_num, ostr, force_quoting); } writeChar(']', ostr); @@ -92,9 +92,9 @@ void JSONCompactRowOutputStream::writeExtremes() writeCString("\t\"extremes\":\n", *ostr); writeCString("\t{\n", *ostr); - writeExtremesElement("min", extremes, 0, *ostr); + writeExtremesElement("min", extremes, 0, *ostr, force_quoting); writeCString(",\n", *ostr); - writeExtremesElement("max", extremes, 1, *ostr); + writeExtremesElement("max", extremes, 1, *ostr, force_quoting); writeChar('\n', *ostr); writeCString("\t}", *ostr); diff --git a/dbms/src/DataStreams/JSONEachRowRowOutputStream.cpp b/dbms/src/DataStreams/JSONEachRowRowOutputStream.cpp index 1b1f00b07e9..abf8519a9b1 100644 --- a/dbms/src/DataStreams/JSONEachRowRowOutputStream.cpp +++ b/dbms/src/DataStreams/JSONEachRowRowOutputStream.cpp @@ -7,8 +7,8 @@ namespace DB { -JSONEachRowRowOutputStream::JSONEachRowRowOutputStream(WriteBuffer & ostr_, const Block & sample) - : ostr(ostr_) +JSONEachRowRowOutputStream::JSONEachRowRowOutputStream(WriteBuffer & ostr_, const Block & sample, bool force_quoting_) + : ostr(ostr_), force_quoting(force_quoting_) { size_t columns = sample.columns(); fields.resize(columns); @@ -25,7 +25,7 @@ void JSONEachRowRowOutputStream::writeField(const IColumn & column, const IDataT { writeString(fields[field_number], ostr); writeChar(':', ostr); - type.serializeTextJSON(column, row_num, ostr); + type.serializeTextJSON(column, row_num, ostr, force_quoting); ++field_number; } diff --git a/dbms/src/DataStreams/JSONRowOutputStream.cpp b/dbms/src/DataStreams/JSONRowOutputStream.cpp index 04014cc335e..c804bd03160 100644 --- a/dbms/src/DataStreams/JSONRowOutputStream.cpp +++ b/dbms/src/DataStreams/JSONRowOutputStream.cpp @@ -7,8 +7,8 @@ namespace DB { -JSONRowOutputStream::JSONRowOutputStream(WriteBuffer & ostr_, const Block & sample_, bool write_statistics_) - : dst_ostr(ostr_), write_statistics(write_statistics_) +JSONRowOutputStream::JSONRowOutputStream(WriteBuffer & ostr_, const Block & sample_, bool write_statistics_, bool force_quoting_) + : dst_ostr(ostr_), write_statistics(write_statistics_), force_quoting(force_quoting_) { NamesAndTypesList columns(sample_.getColumnsList()); fields.assign(columns.begin(), columns.end()); @@ -72,7 +72,7 @@ void JSONRowOutputStream::writeField(const IColumn & column, const IDataType & t writeCString("\t\t\t", *ostr); writeString(fields[field_number].name, *ostr); writeCString(": ", *ostr); - type.serializeTextJSON(column, row_num, *ostr); + type.serializeTextJSON(column, row_num, *ostr, force_quoting); ++field_number; } @@ -152,7 +152,7 @@ void JSONRowOutputStream::writeTotals() writeCString("\t\t", *ostr); writeJSONString(column.name, *ostr); writeCString(": ", *ostr); - column.type->serializeTextJSON(*column.column.get(), 0, *ostr); + column.type->serializeTextJSON(*column.column.get(), 0, *ostr, force_quoting); } writeChar('\n', *ostr); @@ -161,7 +161,7 @@ void JSONRowOutputStream::writeTotals() } -static void writeExtremesElement(const char * title, const Block & extremes, size_t row_num, WriteBuffer & ostr) +static void writeExtremesElement(const char * title, const Block & extremes, size_t row_num, WriteBuffer & ostr, bool force_quoting) { writeCString("\t\t\"", ostr); writeCString(title, ostr); @@ -179,7 +179,7 @@ static void writeExtremesElement(const char * title, const Block & extremes, siz writeCString("\t\t\t", ostr); writeJSONString(column.name, ostr); writeCString(": ", ostr); - column.type->serializeTextJSON(*column.column.get(), row_num, ostr); + column.type->serializeTextJSON(*column.column.get(), row_num, ostr, force_quoting); } writeChar('\n', ostr); @@ -195,9 +195,9 @@ void JSONRowOutputStream::writeExtremes() writeCString("\t\"extremes\":\n", *ostr); writeCString("\t{\n", *ostr); - writeExtremesElement("min", extremes, 0, *ostr); + writeExtremesElement("min", extremes, 0, *ostr, force_quoting); writeCString(",\n", *ostr); - writeExtremesElement("max", extremes, 1, *ostr); + writeExtremesElement("max", extremes, 1, *ostr, force_quoting); writeChar('\n', *ostr); writeCString("\t}", *ostr); diff --git a/dbms/src/DataTypes/DataTypeAggregateFunction.cpp b/dbms/src/DataTypes/DataTypeAggregateFunction.cpp index 1bb410ade44..48214fb33db 100644 --- a/dbms/src/DataTypes/DataTypeAggregateFunction.cpp +++ b/dbms/src/DataTypes/DataTypeAggregateFunction.cpp @@ -195,7 +195,7 @@ void DataTypeAggregateFunction::deserializeTextQuoted(IColumn & column, ReadBuff } -void DataTypeAggregateFunction::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const +void DataTypeAggregateFunction::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const { writeJSONString(serializeToString(function, column, row_num), ostr); } diff --git a/dbms/src/DataTypes/DataTypeArray.cpp b/dbms/src/DataTypes/DataTypeArray.cpp index 738719ab7b1..e458317bdd7 100644 --- a/dbms/src/DataTypes/DataTypeArray.cpp +++ b/dbms/src/DataTypes/DataTypeArray.cpp @@ -288,7 +288,7 @@ void DataTypeArray::deserializeTextQuoted(IColumn & column, ReadBuffer & istr) c } -void DataTypeArray::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const +void DataTypeArray::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool force_quoting) const { const ColumnArray & column_array = static_cast(column); const ColumnArray::Offsets_t & offsets = column_array.getOffsets(); @@ -303,7 +303,7 @@ void DataTypeArray::serializeTextJSON(const IColumn & column, size_t row_num, Wr { if (i != offset) writeChar(',', ostr); - nested->serializeTextJSON(nested_column, i, ostr); + nested->serializeTextJSON(nested_column, i, ostr, force_quoting); } writeChar(']', ostr); } diff --git a/dbms/src/DataTypes/DataTypeEnum.cpp b/dbms/src/DataTypes/DataTypeEnum.cpp index 208e9a470fc..c298cd1feb0 100644 --- a/dbms/src/DataTypes/DataTypeEnum.cpp +++ b/dbms/src/DataTypes/DataTypeEnum.cpp @@ -170,7 +170,7 @@ void DataTypeEnum::deserializeTextQuoted(IColumn & column, ReadBuffer & is } template -void DataTypeEnum::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const +void DataTypeEnum::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const { writeJSONString(getNameForValue(static_cast(column).getData()[row_num]), ostr); } diff --git a/dbms/src/DataTypes/DataTypeFixedString.cpp b/dbms/src/DataTypes/DataTypeFixedString.cpp index 1ec5e0379d9..f0b67d36aae 100644 --- a/dbms/src/DataTypes/DataTypeFixedString.cpp +++ b/dbms/src/DataTypes/DataTypeFixedString.cpp @@ -158,7 +158,7 @@ void DataTypeFixedString::deserializeTextQuoted(IColumn & column, ReadBuffer & i } -void DataTypeFixedString::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const +void DataTypeFixedString::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const { const char * pos = reinterpret_cast(&static_cast(column).getChars()[n * row_num]); writeJSONString(pos, pos + n, ostr); diff --git a/dbms/src/DataTypes/DataTypeString.cpp b/dbms/src/DataTypes/DataTypeString.cpp index 4f0bad798ea..4a80971c288 100644 --- a/dbms/src/DataTypes/DataTypeString.cpp +++ b/dbms/src/DataTypes/DataTypeString.cpp @@ -266,7 +266,7 @@ void DataTypeString::deserializeTextQuoted(IColumn & column, ReadBuffer & istr) } -void DataTypeString::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const +void DataTypeString::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const { writeJSONString(static_cast(column).getDataAt(row_num), ostr); } diff --git a/dbms/src/DataTypes/DataTypeTuple.cpp b/dbms/src/DataTypes/DataTypeTuple.cpp index 5f2a4ae64c0..99b83a4e7d1 100644 --- a/dbms/src/DataTypes/DataTypeTuple.cpp +++ b/dbms/src/DataTypes/DataTypeTuple.cpp @@ -144,14 +144,14 @@ void DataTypeTuple::deserializeTextQuoted(IColumn & column, ReadBuffer & istr) c deserializeText(column, istr); } -void DataTypeTuple::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr) const +void DataTypeTuple::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool force_quoting) const { writeChar('[', ostr); for (const auto i : ext::range(0, ext::size(elems))) { if (i != 0) writeChar(',', ostr); - elems[i]->serializeTextJSON(extractElementColumn(column, i), row_num, ostr); + elems[i]->serializeTextJSON(extractElementColumn(column, i), row_num, ostr, force_quoting); } writeChar(']', ostr); } diff --git a/dbms/tests/queries/0_stateless/00378_json_quote_64bit_integers.reference b/dbms/tests/queries/0_stateless/00378_json_quote_64bit_integers.reference new file mode 100644 index 00000000000..8240d0b21f6 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00378_json_quote_64bit_integers.reference @@ -0,0 +1,264 @@ +{ + "meta": + [ + { + "name": "i0", + "type": "Int64" + }, + { + "name": "u0", + "type": "UInt64" + }, + { + "name": "ip", + "type": "Int64" + }, + { + "name": "in", + "type": "Int64" + }, + { + "name": "up", + "type": "UInt64" + }, + { + "name": "arr", + "type": "Array(Int64)" + }, + { + "name": "tuple", + "type": "Tuple(UInt64, UInt64)" + } + ], + + "data": + [ + { + "i0": "0", + "u0": "0", + "ip": "9223372036854775807", + "in": "-9223372036854775808", + "up": "18446744073709551615", + "arr": ["0"], + "tuple": ["0","0"] + } + ], + + "totals": + { + "i0": "0", + "u0": "0", + "ip": "0", + "in": "0", + "up": "0", + "arr": [], + "tuple": ["0","0"] + }, + + "extremes": + { + "min": + { + "i0": "0", + "u0": "0", + "ip": "9223372036854775807", + "in": "-9223372036854775808", + "up": "18446744073709551615", + "arr": [], + "tuple": ["0","0"] + }, + "max": + { + "i0": "0", + "u0": "0", + "ip": "9223372036854775807", + "in": "-9223372036854775808", + "up": "18446744073709551615", + "arr": [], + "tuple": ["0","0"] + } + }, + + "rows": 1 +} +{ + "meta": + [ + { + "name": "i0", + "type": "Int64" + }, + { + "name": "u0", + "type": "UInt64" + }, + { + "name": "ip", + "type": "Int64" + }, + { + "name": "in", + "type": "Int64" + }, + { + "name": "up", + "type": "UInt64" + }, + { + "name": "arr", + "type": "Array(Int64)" + }, + { + "name": "tuple", + "type": "Tuple(UInt64, UInt64)" + } + ], + + "data": + [ + ["0", "0", "9223372036854775807", "-9223372036854775808", "18446744073709551615", ["0"], ["0","0"]] + ], + + "totals": ["0","0","0","0","0",[],["0","0"]], + + "extremes": + { + "min": ["0","0","9223372036854775807","-9223372036854775808","18446744073709551615",[],["0","0"]], + "max": ["0","0","9223372036854775807","-9223372036854775808","18446744073709551615",[],["0","0"]] + }, + + "rows": 1 +} +{"i0":"0","u0":"0","ip":"9223372036854775807","in":"-9223372036854775808","up":"18446744073709551615","arr":["0"],"tuple":["0","0"]} +{ + "meta": + [ + { + "name": "i0", + "type": "Int64" + }, + { + "name": "u0", + "type": "UInt64" + }, + { + "name": "ip", + "type": "Int64" + }, + { + "name": "in", + "type": "Int64" + }, + { + "name": "up", + "type": "UInt64" + }, + { + "name": "arr", + "type": "Array(Int64)" + }, + { + "name": "tuple", + "type": "Tuple(UInt64, UInt64)" + } + ], + + "data": + [ + { + "i0": 0, + "u0": 0, + "ip": 9223372036854775807, + "in": -9223372036854775808, + "up": 18446744073709551615, + "arr": [0], + "tuple": [0,0] + } + ], + + "totals": + { + "i0": 0, + "u0": 0, + "ip": 0, + "in": 0, + "up": 0, + "arr": [], + "tuple": [0,0] + }, + + "extremes": + { + "min": + { + "i0": 0, + "u0": 0, + "ip": 9223372036854775807, + "in": -9223372036854775808, + "up": 18446744073709551615, + "arr": [], + "tuple": [0,0] + }, + "max": + { + "i0": 0, + "u0": 0, + "ip": 9223372036854775807, + "in": -9223372036854775808, + "up": 18446744073709551615, + "arr": [], + "tuple": [0,0] + } + }, + + "rows": 1 +} +{ + "meta": + [ + { + "name": "i0", + "type": "Int64" + }, + { + "name": "u0", + "type": "UInt64" + }, + { + "name": "ip", + "type": "Int64" + }, + { + "name": "in", + "type": "Int64" + }, + { + "name": "up", + "type": "UInt64" + }, + { + "name": "arr", + "type": "Array(Int64)" + }, + { + "name": "tuple", + "type": "Tuple(UInt64, UInt64)" + } + ], + + "data": + [ + [0, 0, 9223372036854775807, -9223372036854775808, 18446744073709551615, [0], [0,0]] + ], + + "totals": [0,0,0,0,0,[],[0,0]], + + "extremes": + { + "min": [0,0,9223372036854775807,-9223372036854775808,18446744073709551615,[],[0,0]], + "max": [0,0,9223372036854775807,-9223372036854775808,18446744073709551615,[],[0,0]] + }, + + "rows": 1 +} +{"i0":0,"u0":0,"ip":9223372036854775807,"in":-9223372036854775808,"up":18446744073709551615,"arr":[0],"tuple":[0,0]} diff --git a/dbms/tests/queries/0_stateless/00378_json_quote_64bit_integers.sql b/dbms/tests/queries/0_stateless/00378_json_quote_64bit_integers.sql new file mode 100644 index 00000000000..261a044c711 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00378_json_quote_64bit_integers.sql @@ -0,0 +1,12 @@ +SET output_format_write_statistics = 0; +SET extremes = 1; + +SET output_format_json_quote_64bit_integers = 1; +SELECT toInt64(0) as i0, toUInt64(0) as u0, toInt64(9223372036854775807) as ip, toInt64(-9223372036854775808) as in, toUInt64(18446744073709551615) as up, [toInt64(0)] as arr, (toUInt64(0), toUInt64(0)) as tuple WITH TOTALS FORMAT JSON; +SELECT toInt64(0) as i0, toUInt64(0) as u0, toInt64(9223372036854775807) as ip, toInt64(-9223372036854775808) as in, toUInt64(18446744073709551615) as up, [toInt64(0)] as arr, (toUInt64(0), toUInt64(0)) as tuple WITH TOTALS FORMAT JSONCompact; +SELECT toInt64(0) as i0, toUInt64(0) as u0, toInt64(9223372036854775807) as ip, toInt64(-9223372036854775808) as in, toUInt64(18446744073709551615) as up, [toInt64(0)] as arr, (toUInt64(0), toUInt64(0)) as tuple WITH TOTALS FORMAT JSONEachRow; + +SET output_format_json_quote_64bit_integers = 0; +SELECT toInt64(0) as i0, toUInt64(0) as u0, toInt64(9223372036854775807) as ip, toInt64(-9223372036854775808) as in, toUInt64(18446744073709551615) as up, [toInt64(0)] as arr, (toUInt64(0), toUInt64(0)) as tuple WITH TOTALS FORMAT JSON; +SELECT toInt64(0) as i0, toUInt64(0) as u0, toInt64(9223372036854775807) as ip, toInt64(-9223372036854775808) as in, toUInt64(18446744073709551615) as up, [toInt64(0)] as arr, (toUInt64(0), toUInt64(0)) as tuple WITH TOTALS FORMAT JSONCompact; +SELECT toInt64(0) as i0, toUInt64(0) as u0, toInt64(9223372036854775807) as ip, toInt64(-9223372036854775808) as in, toUInt64(18446744073709551615) as up, [toInt64(0)] as arr, (toUInt64(0), toUInt64(0)) as tuple WITH TOTALS FORMAT JSONEachRow; \ No newline at end of file