diff --git a/ydb/core/viewer/viewer_query.h b/ydb/core/viewer/viewer_query.h index de09c55d4320..1ae429fac55d 100644 --- a/ydb/core/viewer/viewer_query.h +++ b/ydb/core/viewer/viewer_query.h @@ -400,7 +400,13 @@ class TJsonQuery : public TViewerPipeClient { } TStringStream stream; + constexpr ui32 doubleNDigits = std::numeric_limits::max_digits10; + constexpr ui32 floatNDigits = std::numeric_limits::max_digits10; + constexpr EFloatToStringMode floatMode = EFloatToStringMode::PREC_NDIGITS; NJson::WriteJson(&stream, &jsonResponse, { + .DoubleNDigits = doubleNDigits, + .FloatNDigits = floatNDigits, + .FloatToStringMode = floatMode, .ValidateUtf8 = false, .WriteNanAsString = true, }); diff --git a/ydb/core/viewer/viewer_ut.cpp b/ydb/core/viewer/viewer_ut.cpp index f854bed5a06b..618920238373 100644 --- a/ydb/core/viewer/viewer_ut.cpp +++ b/ydb/core/viewer/viewer_ut.cpp @@ -1589,6 +1589,56 @@ Y_UNIT_TEST_SUITE(Viewer) { size_t AuthorizeTicketFails = 0; }; + Y_UNIT_TEST(FloatPointJsonQuery) { + TPortManager tp; + ui16 port = tp.GetPort(2134); + ui16 grpcPort = tp.GetPort(2135); + ui16 monPort = tp.GetPort(8765); + auto settings = TServerSettings(port); + settings.InitKikimrRunConfig() + .SetNodeCount(1) + .SetUseRealThreads(true) + .SetDomainName("Root") + .SetMonitoringPortOffset(monPort, true); + + TServer server(settings); + server.EnableGRpc(grpcPort); + TClient client(settings); + + TTestActorRuntime& runtime = *server.GetRuntime(); + runtime.SetLogPriority(NKikimrServices::GRPC_SERVER, NLog::PRI_TRACE); + runtime.SetLogPriority(NKikimrServices::TICKET_PARSER, NLog::PRI_TRACE); + + TKeepAliveHttpClient httpClient("localhost", monPort); + TStringStream responseStream; + TKeepAliveHttpClient::THeaders headers; + headers["Content-Type"] = "application/json"; + headers["Authorization"] = "test_ydb_token"; + TString requestBody = R"json({ + "query": "SELECT cast('311111111113.222222223' as Double);", + "database": "/Root", + "action": "execute-script", + "syntax": "yql_v1", + "stats": "profile" + })json"; + const TKeepAliveHttpClient::THttpCode statusCode = httpClient.DoPost("/viewer/query?timeout=600000&base64=false&schema=modern", requestBody, &responseStream, headers); + const TString response = responseStream.ReadAll(); + UNIT_ASSERT_EQUAL_C(statusCode, HTTP_OK, statusCode << ": " << response); + { + NJson::TJsonReaderConfig jsonCfg; + + NJson::TJsonValue json; + NJson::ReadJsonTree(response, &jsonCfg, &json, /* throwOnError = */ true); + + auto resultSets = json["result"].GetArray(); + UNIT_ASSERT_EQUAL_C(1, resultSets.size(), response); + + double parsed = resultSets.begin()->GetArray().begin()->GetDouble(); + double expected = 311111111113.22222; + UNIT_ASSERT_DOUBLES_EQUAL(parsed, expected, 0.00001); + } + } + Y_UNIT_TEST(AuthorizeYdbTokenWithDatabaseAttributes) { TPortManager tp; ui16 port = tp.GetPort(2134);