diff options
author | azevaykin <145343289+azevaykin@users.noreply.github.com> | 2024-10-08 13:56:35 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-08 13:56:35 +0300 |
commit | 8b39e36b2293ada1eae6b0919d9d12fcdd8e65df (patch) | |
tree | 02854dcba45549bc7117e3aef6633e28fb313e7e | |
parent | dc9f4054d9ad170f88f3099c78caf3d58d095781 (diff) | |
download | ydb-8b39e36b2293ada1eae6b0919d9d12fcdd8e65df.tar.gz |
Allow zero decimal scale (#10168)
-rw-r--r-- | ydb/core/kqp/ut/query/kqp_params_ut.cpp | 60 | ||||
-rw-r--r-- | ydb/core/kqp/ut/scheme/kqp_scheme_ut.cpp | 43 | ||||
-rw-r--r-- | ydb/core/scheme_types/scheme_decimal_type.cpp | 16 | ||||
-rw-r--r-- | ydb/core/scheme_types/scheme_decimal_type.h | 14 | ||||
-rw-r--r-- | ydb/services/ydb/ydb_table_ut.cpp | 107 | ||||
-rw-r--r-- | ydb/services/ydb/ydb_ut.cpp | 98 |
6 files changed, 242 insertions, 96 deletions
diff --git a/ydb/core/kqp/ut/query/kqp_params_ut.cpp b/ydb/core/kqp/ut/query/kqp_params_ut.cpp index 58f36ab60b..454f008821 100644 --- a/ydb/core/kqp/ut/query/kqp_params_ut.cpp +++ b/ydb/core/kqp/ut/query/kqp_params_ut.cpp @@ -609,6 +609,7 @@ Y_UNIT_TEST_SUITE(KqpParams) { .AddParam("$ParamDouble").Double(40.5).Build() .AddParam("$ParamDecimal").Decimal(TDecimalValue("50.5", 22, 9)).Build() .AddParam("$ParamDecimal35").Decimal(TDecimalValue("655555555555555.5", 35, 10)).Build() + .AddParam("$ParamDecimal0").Decimal(TDecimalValue("9", 1, 0)).Build() .AddParam("$ParamDyNumber").DyNumber("60.5").Build() .AddParam("$ParamString").String("StringValue").Build() .AddParam("$ParamUtf8").Utf8("Utf8Value").Build() @@ -670,6 +671,7 @@ Y_UNIT_TEST_SUITE(KqpParams) { DECLARE $ParamDouble AS Double; DECLARE $ParamDecimal AS Decimal(22, 9); DECLARE $ParamDecimal35 AS Decimal(35, 10); + DECLARE $ParamDecimal0 AS Decimal(1, 0); DECLARE $ParamDyNumber AS DyNumber; DECLARE $ParamString AS String; DECLARE $ParamUtf8 AS Utf8; @@ -704,6 +706,7 @@ Y_UNIT_TEST_SUITE(KqpParams) { $ParamDouble AS ValueDouble, $ParamDecimal AS ValueDecimal, $ParamDecimal35 AS ValueDecimal35, + $ParamDecimal0 AS ValueDecimal0, $ParamDyNumber AS ValueDyNumber, $ParamString AS ValueString, $ParamUtf8 AS ValueUtf8, @@ -729,13 +732,13 @@ Y_UNIT_TEST_SUITE(KqpParams) { auto actual = ReformatYson(FormatResultSetYson(result.GetResultSet(0))); auto expected1 = ReformatYson(R"([[ - %true;-5;5u;-8;8u;-10;10u;-20;20u;30.5;40.5;"50.5";"655555555555555.5";".605e2";"StringValue";"Utf8Value";"[{Value=50}]"; + %true;-5;5u;-8;8u;-10;10u;-20;20u;30.5;40.5;"50.5";"655555555555555.5";"9";".605e2";"StringValue";"Utf8Value";"[{Value=50}]"; "[{\"Value\":60}]";"[{\"Value\":70}]";18271u;1578755093u;1578863917000000u;3600;"2022-03-14,GMT"; "2022-03-14T00:00:00,GMT";"2022-03-14T00:00:00.123000,GMT";["Opt"];["Tuple0";1];[17u;19u];[];["Paul";-5]; [["Key2";20u];["Key1";10u]] ]])"); auto expected2 = ReformatYson(R"([[ - %true;-5;5u;-8;8u;-10;10u;-20;20u;30.5;40.5;"50.5";"655555555555555.5";".605e2";"StringValue";"Utf8Value";"[{Value=50}]"; + %true;-5;5u;-8;8u;-10;10u;-20;20u;30.5;40.5;"50.5";"655555555555555.5";"9";".605e2";"StringValue";"Utf8Value";"[{Value=50}]"; "[{\"Value\":60}]";"[{\"Value\":70}]";18271u;1578755093u;1578863917000000u;3600;"2022-03-14,GMT"; "2022-03-14T00:00:00,GMT";"2022-03-14T00:00:00.123000,GMT";["Opt"];["Tuple0";1];[17u;19u];[];["Paul";-5]; [["Key1";10u];["Key2";20u]] @@ -793,6 +796,7 @@ Y_UNIT_TEST_SUITE(KqpParams) { --!syntax_v1 CREATE TABLE Table ( Key Int32, + Value1 Decimal(1,0), Value22 Decimal(22,9), Value35 Decimal(35,10), PRIMARY KEY (Key) @@ -814,11 +818,11 @@ Y_UNIT_TEST_SUITE(KqpParams) { auto execSelectQuery = [&] (const TString& query, const NYdb::TParams& params) -> std::tuple<NYdb::EStatus, TString, TResultSet> { if (QueryService) { auto result = queryClient.ExecuteQuery(query, NYdb::NQuery::TTxControl::BeginTx().CommitTx(), params).ExtractValueSync(); - return {result.GetStatus(), result.GetIssues().ToString(), result.GetResultSet(0)}; + return {result.GetStatus(), result.GetIssues().ToString(), result.GetResultSets().size() ? result.GetResultSet(0) : TResultSet({})}; } else { auto result = session.ExecuteDataQuery(query, TTxControl::BeginTx().CommitTx(), params).ExtractValueSync(); - return {result.GetStatus(), result.GetIssues().ToString(), result.GetResultSet(0)}; + return {result.GetStatus(), result.GetIssues().ToString(), result.GetResultSets().size() ? result.GetResultSet(0) : TResultSet({})}; } }; @@ -826,6 +830,7 @@ Y_UNIT_TEST_SUITE(KqpParams) { { auto upsertParams = tableClient.GetParamsBuilder() .AddParam("$key").Int32(1).Build() + .AddParam("$value1").Decimal(TDecimalValue("9", 1, 0)).Build() .AddParam("$value22").Decimal(TDecimalValue("123.321", 22, 9)).Build() .AddParam("$value35").Decimal(TDecimalValue("555555555555555.1234567890", 35, 10)).Build() .Build(); @@ -834,26 +839,28 @@ Y_UNIT_TEST_SUITE(KqpParams) { { auto [status, issues] = execUpsertQuery(Q1_(R"( DECLARE $key AS Int32; + DECLARE $value1 AS Decimal(1,0); DECLARE $value22 AS Decimal(22,9); DECLARE $value35 AS Decimal(35,10); - UPSERT INTO Table (Key, Value22, Value35) VALUES - ($key, $value22, $value35); + UPSERT INTO Table (Key, Value1, Value22, Value35) VALUES + ($key, $value1, $value22, $value35); )"), upsertParams); UNIT_ASSERT_VALUES_EQUAL_C(status, EStatus::SUCCESS, issues); } // No upsert parameters is declared { auto [status, issues] = execUpsertQuery(Q1_(R"( - UPSERT INTO Table (Key, Value22, Value35) VALUES - ($key, $value22, $value35); + UPSERT INTO Table (Key, Value1, Value22, Value35) VALUES + ($key, $value1, $value22, $value35); )"), upsertParams); UNIT_ASSERT_VALUES_EQUAL_C(status, EStatus::SUCCESS, issues); } - TString expected = R"([[[1];["123.321"];["555555555555555.123456789"]]])"; + TString expected = R"([[[1];["9"];["123.321"];["555555555555555.123456789"]]])"; auto selectParams = tableClient.GetParamsBuilder() .AddParam("$key").Int32(1).Build() + .AddParam("$value1").Decimal(TDecimalValue("9", 1, 0)).Build() .AddParam("$value22").Decimal(TDecimalValue("123.321", 22, 9)).Build() .AddParam("$value35").Decimal(TDecimalValue("555555555555555.1234567890", 35, 10)).Build() .Build(); @@ -862,10 +869,11 @@ Y_UNIT_TEST_SUITE(KqpParams) { { auto [status, issues, resultSet] = execSelectQuery(Q1_(R"( DECLARE $key AS Int32; + DECLARE $value1 AS Decimal(1,0); DECLARE $value22 AS Decimal(22,9); DECLARE $value35 AS Decimal(35,10); - SELECT * FROM Table WHERE Key = $key AND Value22 = $value22 AND Value35 = $value35; + SELECT * FROM Table WHERE Key = $key AND Value1 = $value1 AND Value22 = $value22 AND Value35 = $value35; )"), selectParams); UNIT_ASSERT_VALUES_EQUAL_C(status, EStatus::SUCCESS, issues); CompareYson(expected, FormatResultSetYson(resultSet)); @@ -874,13 +882,27 @@ Y_UNIT_TEST_SUITE(KqpParams) { // No select parameters is declared { auto [status, issues, resultSet] = execSelectQuery(Q1_(R"( - SELECT * FROM Table WHERE Key = $key AND Value22 = $value22 AND Value35 = $value35; + SELECT * FROM Table WHERE Key = $key AND Value1 = $value1 AND Value22 = $value22 AND Value35 = $value35; )"), selectParams); UNIT_ASSERT_VALUES_EQUAL_C(status, EStatus::SUCCESS, issues); CompareYson(expected, FormatResultSetYson(resultSet)); } } + // Declare wrong decimal params + { + auto params = tableClient.GetParamsBuilder() + .AddParam("$value99").Decimal(TDecimalValue("0", 99, 99)).Build() + .Build(); + + auto [status, issues, _] = execSelectQuery(Q1_(R"( + DECLARE $value99 AS Decimal(99,99); + SELECT $value99 AS value99; + )"), params); + UNIT_ASSERT_VALUES_EQUAL(status, EStatus::GENERIC_ERROR); + UNIT_ASSERT_STRING_CONTAINS(issues, "Invalid decimal precision: 99"); + } + // Declare decimal params mismatch { auto upsertParams = tableClient.GetParamsBuilder() @@ -940,17 +962,19 @@ Y_UNIT_TEST_SUITE(KqpParams) { { auto upsertParams = tableClient.GetParamsBuilder() .AddParam("$key").Int32(1001).Build() + .AddParam("$value1").Decimal(TDecimalValue("10", 1, 0)).Build() .AddParam("$value22").Decimal(TDecimalValue("12345678901234567890.1234567891", 22, 9)).Build() .AddParam("$value35").Decimal(TDecimalValue("1234567890123456789012345678901234567890.1234567891", 35, 10)).Build() .Build(); auto [status, issues] = execUpsertQuery(Q1_(R"( DECLARE $key AS Int32; + DECLARE $value1 AS Decimal(1,0); DECLARE $value22 AS Decimal(22,9); DECLARE $value35 AS Decimal(35,10); - UPSERT INTO Table (Key, Value22, Value35) VALUES - ($key, $value22, $value35); + UPSERT INTO Table (Key, Value1, Value22, Value35) VALUES + ($key, $value1, $value22, $value35); )"), upsertParams); UNIT_ASSERT_VALUES_EQUAL_C(status, EStatus::SUCCESS, issues); } @@ -958,17 +982,19 @@ Y_UNIT_TEST_SUITE(KqpParams) { { auto upsertParams = tableClient.GetParamsBuilder() .AddParam("$key").Int32(1002).Build() + .AddParam("$value1").Decimal(TDecimalValue("inf", 1, 0)).Build() .AddParam("$value22").Decimal(TDecimalValue("inf", 22, 9)).Build() .AddParam("$value35").Decimal(TDecimalValue("inf", 35, 10)).Build() .Build(); auto [status, issues] = execUpsertQuery(Q1_(R"( DECLARE $key AS Int32; + DECLARE $value1 AS Decimal(1,0); DECLARE $value22 AS Decimal(22,9); DECLARE $value35 AS Decimal(35,10); - UPSERT INTO Table (Key, Value22, Value35) VALUES - ($key, $value22, $value35); + UPSERT INTO Table (Key, Value1, Value22, Value35) VALUES + ($key, $value1, $value22, $value35); )"), upsertParams); UNIT_ASSERT_VALUES_EQUAL_C(status, EStatus::SUCCESS, issues); } @@ -980,8 +1006,8 @@ Y_UNIT_TEST_SUITE(KqpParams) { )"), emptyParams); UNIT_ASSERT_VALUES_EQUAL_C(status, EStatus::SUCCESS, issues); TString expected = R"([ - [[1001];["inf"];["inf"]]; - [[1002];["inf"];["inf"]] + [[1001];["inf"];["inf"];["inf"]]; + [[1002];["inf"];["inf"];["inf"]] ])"; TString actual = FormatResultSetYson(resultSet); CompareYson(expected, actual); diff --git a/ydb/core/kqp/ut/scheme/kqp_scheme_ut.cpp b/ydb/core/kqp/ut/scheme/kqp_scheme_ut.cpp index c3098ce723..f39e02b2f6 100644 --- a/ydb/core/kqp/ut/scheme/kqp_scheme_ut.cpp +++ b/ydb/core/kqp/ut/scheme/kqp_scheme_ut.cpp @@ -2294,6 +2294,16 @@ Y_UNIT_TEST_SUITE(KqpScheme) { );)", tableName.c_str(), precision, scale); auto createResult = session.ExecuteSchemeQuery(createQuery).GetValueSync(); + if (precision == 0) { + UNIT_ASSERT_VALUES_EQUAL_C(createResult.GetStatus(), EStatus::GENERIC_ERROR, createResult.GetIssues().ToString()); + UNIT_ASSERT_STRING_CONTAINS(createResult.GetIssues().ToString(), "Invalid decimal precision"); + return; + } + if (precision == 33) { + UNIT_ASSERT_VALUES_EQUAL_C(createResult.GetStatus(), EStatus::GENERIC_ERROR, createResult.GetIssues().ToString()); + UNIT_ASSERT_STRING_CONTAINS(createResult.GetIssues().ToString(), "Invalid decimal parameters"); + return; + } if (precision == 36) { UNIT_ASSERT_VALUES_EQUAL_C(createResult.GetStatus(), EStatus::GENERIC_ERROR, createResult.GetIssues().ToString()); UNIT_ASSERT_STRING_CONTAINS(createResult.GetIssues().ToString(), "Invalid decimal precision"); @@ -2324,10 +2334,13 @@ Y_UNIT_TEST_SUITE(KqpScheme) { UNIT_ASSERT_VALUES_EQUAL(decimalType.Scale, scale); }; + createAndCheck(0, 0); + createAndCheck(1, 0); createAndCheck(2, 1); createAndCheck(22, 9); - createAndCheck(35, 9); + createAndCheck(35, 10); createAndCheck(22, 20); + createAndCheck(33, 34); createAndCheck(36, 35); createAndCheck(999, 99); } @@ -2969,6 +2982,16 @@ Y_UNIT_TEST_SUITE(KqpScheme) { )", tableName.c_str(), columnName.c_str(), precision, scale); auto result = session.ExecuteSchemeQuery(query).GetValueSync(); + if (precision == 0) { + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::GENERIC_ERROR, result.GetIssues().ToString()); + UNIT_ASSERT_STRING_CONTAINS(result.GetIssues().ToString(), "Invalid decimal precision"); + return; + } + if (precision == 33) { + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::GENERIC_ERROR, result.GetIssues().ToString()); + UNIT_ASSERT_STRING_CONTAINS(result.GetIssues().ToString(), "Invalid decimal parameters"); + return; + } if (precision == 36) { UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::GENERIC_ERROR, result.GetIssues().ToString()); UNIT_ASSERT_STRING_CONTAINS(result.GetIssues().ToString(), "Invalid decimal precision"); @@ -2983,10 +3006,13 @@ Y_UNIT_TEST_SUITE(KqpScheme) { UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); }; + addColumn(0, 0); + addColumn(1, 0); addColumn(2, 1); addColumn(22, 9); - addColumn(35, 9); + addColumn(35, 10); addColumn(22, 20); + addColumn(33, 34); addColumn(36, 35); addColumn(999, 99); @@ -2994,7 +3020,7 @@ Y_UNIT_TEST_SUITE(KqpScheme) { UNIT_ASSERT_EQUAL_C(describe.GetStatus(), EStatus::SUCCESS, describe.GetIssues().ToString()); auto tableDesc = describe.GetTableDescription(); TVector<TTableColumn> columns = tableDesc.GetTableColumns(); - UNIT_ASSERT_VALUES_EQUAL(columns.size(), 6); + UNIT_ASSERT_VALUES_EQUAL(columns.size(), 7); auto checkColumn = [&] (ui64 columnIdx, ui32 precision, ui32 scale) { TType valueType = columns[columnIdx].Type; @@ -3003,16 +3029,17 @@ Y_UNIT_TEST_SUITE(KqpScheme) { UNIT_ASSERT_EQUAL(optionalKind, TTypeParser::ETypeKind::Optional); parser.OpenOptional(); auto kind = parser.GetKind(); - UNIT_ASSERT_EQUAL(kind, TTypeParser::ETypeKind::Decimal); + UNIT_ASSERT_VALUES_EQUAL(kind, TTypeParser::ETypeKind::Decimal); TDecimalType decimalType = parser.GetDecimal(); UNIT_ASSERT_VALUES_EQUAL(decimalType.Precision, precision); UNIT_ASSERT_VALUES_EQUAL(decimalType.Scale, scale); }; - checkColumn(2, 2, 1); - checkColumn(3, 22, 9); - checkColumn(4, 35,9); - checkColumn(5, 22, 20); + checkColumn(0,22, 20); + checkColumn(3, 1, 0); + checkColumn(4, 2, 1); + checkColumn(5, 22,9); + checkColumn(6, 35, 10); } Y_UNIT_TEST(CreateUserWithPassword) { diff --git a/ydb/core/scheme_types/scheme_decimal_type.cpp b/ydb/core/scheme_types/scheme_decimal_type.cpp index dc0cd7958e..63a5f92fb3 100644 --- a/ydb/core/scheme_types/scheme_decimal_type.cpp +++ b/ydb/core/scheme_types/scheme_decimal_type.cpp @@ -11,6 +11,18 @@ namespace NKikimr::NScheme { +TDecimalType::TDecimalType(ui32 precision, ui32 scale) + : Precision(precision) + , Scale(scale) +{ + TString error; + Y_ABORT_UNLESS(Validate(precision, scale, error), "%s", error.c_str()); +} + +bool TDecimalType::operator==(const TDecimalType& other) const { + return Precision == other.Precision && Scale == other.Scale; +} + TString TDecimalType::CellValueToString(const std::pair<ui64, i64>& cellValue) const { return NYql::NDecimal::ToString(NYql::NDecimal::FromHalfs(cellValue.first, cellValue.second), Precision, Scale); @@ -44,6 +56,10 @@ const std::optional<TDecimalType> TDecimalType::ParseTypeName(const TStringBuf& } bool TDecimalType::Validate(ui32 precision, ui32 scale, TString& error) { + if (precision == 0) { + error = Sprintf("Decimal precision should not be zero"); + return false; + } if (precision > NKikimr::NScheme::DECIMAL_MAX_PRECISION) { error = Sprintf("Decimal precision %u should be less than %u", precision, NKikimr::NScheme::DECIMAL_MAX_PRECISION); return false; diff --git a/ydb/core/scheme_types/scheme_decimal_type.h b/ydb/core/scheme_types/scheme_decimal_type.h index e0372e8644..ae0310aa81 100644 --- a/ydb/core/scheme_types/scheme_decimal_type.h +++ b/ydb/core/scheme_types/scheme_decimal_type.h @@ -11,17 +11,9 @@ namespace NKikimr::NScheme { class TDecimalType { public: - constexpr TDecimalType(ui32 precision, ui32 scale) - : Precision(precision) - , Scale(scale) - { - Y_ABORT_UNLESS(Precision); - Y_ABORT_UNLESS(Scale); - } + TDecimalType(ui32 precision, ui32 scale); - constexpr bool operator==(const TDecimalType& other) const { - return Precision == other.Precision && Scale == other.Scale; - } + bool operator==(const TDecimalType& other) const; TString CellValueToString(const std::pair<ui64, i64>& cellValue) const; void CellValueToStream(const std::pair<ui64, i64>& cellValue, IOutputStream& out) const; @@ -29,7 +21,7 @@ public: static const std::optional<TDecimalType> ParseTypeName(const TStringBuf& typeName); static bool Validate(ui32 precision, ui32 scale, TString& error); - constexpr static TDecimalType Default() { + static TDecimalType Default() { return TDecimalType(DECIMAL_PRECISION, DECIMAL_SCALE); } private: diff --git a/ydb/services/ydb/ydb_table_ut.cpp b/ydb/services/ydb/ydb_table_ut.cpp index 52d3c7f51d..8f16c2f5de 100644 --- a/ydb/services/ydb/ydb_table_ut.cpp +++ b/ydb/services/ydb/ydb_table_ut.cpp @@ -325,6 +325,43 @@ Y_UNIT_TEST_SUITE(YdbYqlClient) { } } + Y_UNIT_TEST(TestDecimal1) { + TKikimrWithGrpcAndRootSchema server; + ui16 grpc = server.GetPort(); + + TString location = TStringBuilder() << "localhost:" << grpc; + + auto connection = NYdb::TDriver( + TDriverConfig() + .SetEndpoint(location)); + auto session = CreateSession(connection); + + auto result = session.ExecuteDataQuery(R"___( + SELECT CAST("9" as Decimal(1,0)); + )___", TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync(); + + UNIT_ASSERT_EQUAL(result.IsTransportError(), false); + UNIT_ASSERT_EQUAL(result.GetStatus(), EStatus::SUCCESS); + TVector<TResultSet> resultSets = result.GetResultSets(); + UNIT_ASSERT_EQUAL(resultSets.size(), 1); + UNIT_ASSERT_EQUAL(resultSets[0].ColumnsCount(), 1); + UNIT_ASSERT_EQUAL(resultSets[0].GetColumnsMeta().size(), 1); + auto column = resultSets[0].GetColumnsMeta()[0]; + TTypeParser typeParser(column.Type); + typeParser.OpenOptional(); + UNIT_ASSERT_EQUAL(typeParser.GetKind(), TTypeParser::ETypeKind::Decimal); + + TResultSetParser rsParser(resultSets[0]); + while (rsParser.TryNextRow()) { + auto columnParser = std::move(rsParser.ColumnParser(0)); + columnParser.OpenOptional(); + auto decimalString = columnParser.GetDecimal().ToString(); + UNIT_ASSERT_EQUAL(decimalString, "9"); + UNIT_ASSERT_VALUES_EQUAL(columnParser.GetDecimal().DecimalType_.Precision, 1); + UNIT_ASSERT_VALUES_EQUAL(columnParser.GetDecimal().DecimalType_.Scale, 0); + } + } + Y_UNIT_TEST(TestDecimal35) { TKikimrWithGrpcAndRootSchema server; ui16 grpc = server.GetPort(); @@ -382,7 +419,9 @@ Y_UNIT_TEST_SUITE(YdbYqlClient) { auto tableBuilder = client.GetTableBuilder(); tableBuilder .AddNullableColumn("Key", EPrimitiveType::Int32) - .AddNullableColumn("Value", TDecimalType(22,9)); + .AddNullableColumn("Value1", TDecimalType(1,0)) + .AddNullableColumn("Value22", TDecimalType(22,9)) + .AddNullableColumn("Value35", TDecimalType(35,10)); tableBuilder.SetPrimaryKeyColumn("Key"); auto result = session.CreateTable("/Root/FooTable", tableBuilder.Build()).ExtractValueSync(); UNIT_ASSERT_EQUAL(result.IsTransportError(), false); @@ -391,29 +430,51 @@ Y_UNIT_TEST_SUITE(YdbYqlClient) { { TString query = R"___( - DECLARE $Value AS Decimal(22,9); + DECLARE $Value1 AS Decimal(1,0); + DECLARE $Value22 AS Decimal(22,9); + DECLARE $Value35 AS Decimal(35,10); DECLARE $Key AS Int32; - UPSERT INTO `Root/FooTable` (Key, Value) VALUES - ($Key, $Value); + UPSERT INTO `Root/FooTable` (Key, Value1, Value22, Value35) VALUES + ($Key, $Value1, $Value22, $Value35); )___"; constexpr int records = 5; int count = records; - const TString decimalParams[records] = { + const TString decimalParams1[records] = { + "1", + "4", + "0", + "-4", + "-1" + }; + const TString decimalParams22[records] = { "123", "4.56", "0", "-4.56", "-123" }; + const TString decimalParams35[records] = { + "155555555555555.12345678", + "4.56", + "0", + "-4.56", + "-155555555555555.12345678" + }; while (count--) { auto paramsBuilder = client.GetParamsBuilder(); auto params = paramsBuilder .AddParam("$Key") .Int32(count) .Build() - .AddParam("$Value") - .Decimal(TDecimalValue(decimalParams[count], 22, 9)) + .AddParam("$Value1") + .Decimal(TDecimalValue(decimalParams1[count], 1, 0)) + .Build() + .AddParam("$Value22") + .Decimal(TDecimalValue(decimalParams22[count], 22, 9)) + .Build() + .AddParam("$Value35") + .Decimal(TDecimalValue(decimalParams35[count], 35, 10)) .Build() .Build(); auto result = session @@ -421,36 +482,42 @@ Y_UNIT_TEST_SUITE(YdbYqlClient) { .CommitTx(), std::move(params)) .ExtractValueSync(); - UNIT_ASSERT_EQUAL(result.GetStatus(), EStatus::SUCCESS); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); } } { - TString query = R"___(SELECT SUM(Value),MIN(Value),MAX(Value) FROM `Root/FooTable`)___"; + TString query = R"___(SELECT SUM(Value1),MIN(Value1),MAX(Value1),SUM(Value22),MIN(Value22),MAX(Value22),SUM(Value35),MIN(Value35),MAX(Value35) FROM `Root/FooTable`)___"; auto result = session .ExecuteDataQuery(query, TTxControl::BeginTx(TTxSettings::SerializableRW()) .CommitTx()) .ExtractValueSync(); - UNIT_ASSERT_EQUAL(result.GetStatus(), EStatus::SUCCESS); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); TVector<TResultSet> resultSets = result.GetResultSets(); - UNIT_ASSERT_EQUAL(resultSets.size(), 1); - UNIT_ASSERT_EQUAL(resultSets[0].ColumnsCount(), 3); - UNIT_ASSERT_EQUAL(resultSets[0].GetColumnsMeta().size(), 3); + UNIT_ASSERT_VALUES_EQUAL(resultSets.size(), 1); + UNIT_ASSERT_VALUES_EQUAL(resultSets[0].ColumnsCount(), 9); + UNIT_ASSERT_VALUES_EQUAL(resultSets[0].GetColumnsMeta().size(), 9); for (auto column : resultSets[0].GetColumnsMeta()) { TTypeParser typeParser(column.Type); - UNIT_ASSERT_EQUAL(typeParser.GetKind(), TTypeParser::ETypeKind::Optional); + UNIT_ASSERT_VALUES_EQUAL(typeParser.GetKind(), TTypeParser::ETypeKind::Optional); typeParser.OpenOptional(); - UNIT_ASSERT_EQUAL(typeParser.GetKind(), TTypeParser::ETypeKind::Decimal); + UNIT_ASSERT_VALUES_EQUAL(typeParser.GetKind(), TTypeParser::ETypeKind::Decimal); } TResultSetParser rsParser(resultSets[0]); - const TString expected[3] = { + const TString expected[9] = { + "0", + "-4", + "4", "0", "-123", - "123" + "123", + "0", + "-155555555555555.12345678", + "155555555555555.12345678", }; while (rsParser.TryNextRow()) { for (size_t i = 0; i < resultSets[0].ColumnsCount(); i++) { @@ -465,10 +532,10 @@ Y_UNIT_TEST_SUITE(YdbYqlClient) { { auto res = session.DescribeTable("Root/FooTable").ExtractValueSync(); UNIT_ASSERT_EQUAL(res.IsTransportError(), false); - UNIT_ASSERT_EQUAL(res.GetStatus(), EStatus::SUCCESS); - UNIT_ASSERT_EQUAL(res.GetTableDescription().GetColumns().size(), 2); + UNIT_ASSERT_VALUES_EQUAL_C(res.GetStatus(), EStatus::SUCCESS, res.GetIssues().ToString()); + UNIT_ASSERT_VALUES_EQUAL(res.GetTableDescription().GetColumns().size(), 4); - TTypeParser::ETypeKind kinds[2] = {TTypeParser::ETypeKind::Primitive, TTypeParser::ETypeKind::Decimal}; + TTypeParser::ETypeKind kinds[4] = {TTypeParser::ETypeKind::Primitive, TTypeParser::ETypeKind::Decimal, TTypeParser::ETypeKind::Decimal, TTypeParser::ETypeKind::Decimal}; int i = 0; for (const auto& column : res.GetTableDescription().GetColumns()) { auto tParser = TTypeParser(column.Type); diff --git a/ydb/services/ydb/ydb_ut.cpp b/ydb/services/ydb/ydb_ut.cpp index f60da5a872..cbcedf92be 100644 --- a/ydb/services/ydb/ydb_ut.cpp +++ b/ydb/services/ydb/ydb_ut.cpp @@ -4887,7 +4887,7 @@ Ydb::Table::ExecuteQueryResult ExecYql(std::shared_ptr<grpc::Channel> channel, c NYql::IssuesFromMessage(deferred.issues(), issues); issues.PrintTo(Cerr); - UNIT_ASSERT(deferred.status() == Ydb::StatusIds::SUCCESS); + UNIT_ASSERT_VALUES_EQUAL(deferred.status(), Ydb::StatusIds::SUCCESS); Ydb::Table::ExecuteQueryResult result; Y_ABORT_UNLESS(deferred.result().UnpackTo(&result)); @@ -4895,7 +4895,7 @@ Ydb::Table::ExecuteQueryResult ExecYql(std::shared_ptr<grpc::Channel> channel, c } void CheckYqlDecimalValues(std::shared_ptr<grpc::Channel> channel, const TString &sessionId, const TString &yql, - TVector<std::pair<i64, ui64>> vals) + TVector<std::pair<i64, ui64>> vals, ui64 scale) { auto result = ExecYql(channel, sessionId, yql); UNIT_ASSERT_VALUES_EQUAL(result.result_sets_size(), 1); @@ -4903,7 +4903,7 @@ void CheckYqlDecimalValues(std::shared_ptr<grpc::Channel> channel, const TString TVector<std::pair<ui64, ui64>> halves; for (auto &pr : vals) { NYql::NDecimal::TInt128 val = pr.first; - val *= Power(10, NScheme::DECIMAL_SCALE); + val *= Power(10ull, scale); if (val >= 0) val += pr.second; else @@ -4933,18 +4933,23 @@ void CreateTable(std::shared_ptr<grpc::Channel> channel, UNIT_ASSERT_VALUES_EQUAL(deferred.status(), Ydb::StatusIds::SUCCESS); } -void CreateTable(std::shared_ptr<grpc::Channel> channel) +void CreateTableDecimal(std::shared_ptr<grpc::Channel> channel) { Ydb::Table::CreateTableRequest request; request.set_path("/Root/table-1"); + auto &col = *request.add_columns(); + col.set_name("key"); + col.mutable_type()->mutable_optional_type()->mutable_item()->set_type_id(Ydb::Type::INT32); auto &col1 = *request.add_columns(); - col1.set_name("key"); - col1.mutable_type()->mutable_optional_type()->mutable_item()->set_type_id(Ydb::Type::INT32); - auto &col2 = *request.add_columns(); - col2.set_name("value"); - auto &decimalType = *col2.mutable_type()->mutable_optional_type()->mutable_item()->mutable_decimal_type(); - decimalType.set_precision(NScheme::DECIMAL_PRECISION); - decimalType.set_scale(NScheme::DECIMAL_SCALE); + col1.set_name("value1"); + auto &decimalType1 = *col1.mutable_type()->mutable_optional_type()->mutable_item()->mutable_decimal_type(); + decimalType1.set_precision(1); + decimalType1.set_scale(0); + auto &col35 = *request.add_columns(); + col35.set_name("value35"); + auto &decimalType35 = *col35.mutable_type()->mutable_optional_type()->mutable_item()->mutable_decimal_type(); + decimalType35.set_precision(35); + decimalType35.set_scale(10); request.add_primary_key("key"); CreateTable(channel, request); @@ -4959,19 +4964,25 @@ Y_UNIT_TEST_SUITE(TYqlDecimalTests) { = grpc::CreateChannel("localhost:" + ToString(grpc), grpc::InsecureChannelCredentials()); TString sessionId = CreateSession(channel); - CreateTable(channel); + CreateTableDecimal(channel); ExecYql(channel, sessionId, - "UPSERT INTO `/Root/table-1` (key, value) VALUES " - "(1, CAST(\"1\" as DECIMAL(22,9)))," - "(2, CAST(\"22.22\" as DECIMAL(22,9)))," - "(3, CAST(\"9999999999999.999999999\" as DECIMAL(22,9)));"); + "UPSERT INTO `/Root/table-1` (key, value1, value35) VALUES " + "(1, CAST(\"1\" as DECIMAL(1,0)), CAST(\"1234567890.1234567891\" as DECIMAL(35,10)))," + "(2, CAST(\"2\" as DECIMAL(1,0)), CAST(\"2234567890.1234567891\" as DECIMAL(35,10)))," + "(3, CAST(\"3\" as DECIMAL(1,0)), CAST(\"3234567890.1234567891\" as DECIMAL(35,10)));"); - CheckYqlDecimalValues(channel, sessionId, "SELECT value FROM `/Root/table-1` WHERE key=1;", - {{1, 0}}); + CheckYqlDecimalValues(channel, sessionId, "SELECT value1 FROM `/Root/table-1` WHERE key=1;", + {{1, 0}}, 0); - CheckYqlDecimalValues(channel, sessionId, "SELECT value FROM `/Root/table-1` WHERE key >= 1 AND key <= 3;", - {{1, 0}, {22, 220000000}, {9999999999999, 999999999}}); + CheckYqlDecimalValues(channel, sessionId, "SELECT value1 FROM `/Root/table-1` WHERE key >= 1 AND key <= 3;", + {{1, 0}, {2, 0}, {3, 0}}, 0); + + CheckYqlDecimalValues(channel, sessionId, "SELECT value35 FROM `/Root/table-1` WHERE key=1;", + {{1234567890, 1234567891}}, 10); + + CheckYqlDecimalValues(channel, sessionId, "SELECT value35 FROM `/Root/table-1` WHERE key >= 1 AND key <= 3;", + {{1234567890, 1234567891}, {2234567890, 1234567891}, {3234567890, 1234567891}}, 10); } Y_UNIT_TEST(NegativeValues) { @@ -4982,19 +4993,26 @@ Y_UNIT_TEST_SUITE(TYqlDecimalTests) { = grpc::CreateChannel("localhost:" + ToString(grpc), grpc::InsecureChannelCredentials()); TString sessionId = CreateSession(channel); - CreateTable(channel); + CreateTableDecimal(channel); ExecYql(channel, sessionId, - "UPSERT INTO `/Root/table-1` (key, value) VALUES " - "(1, CAST(\"-1\" as DECIMAL(22,9)))," - "(2, CAST(\"-22.22\" as DECIMAL(22,9)))," - "(3, CAST(\"-9999999999999.999999999\" as DECIMAL(22,9)));"); + "UPSERT INTO `/Root/table-1` (key, value1, value35) VALUES " + "(1, CAST(\"-1\" as DECIMAL(1,0)), CAST(\"-1234567890.1234567891\" as DECIMAL(35,10)))," + "(2, CAST(\"-2\" as DECIMAL(1,0)), CAST(\"-2234567890.1234567891\" as DECIMAL(35,10)))," + "(3, CAST(\"-3\" as DECIMAL(1,0)), CAST(\"-3234567890.1234567891\" as DECIMAL(35,10)));"); + + CheckYqlDecimalValues(channel, sessionId, "SELECT value1 FROM `/Root/table-1` WHERE key=1;", + {{-1, 0}}, 0); + + CheckYqlDecimalValues(channel, sessionId, "SELECT value1 FROM `/Root/table-1` WHERE key >= 1 AND key <= 3;", + {{-1, 0}, {-2, 0}, {-3, 0}}, 0); + + CheckYqlDecimalValues(channel, sessionId, "SELECT value35 FROM `/Root/table-1` WHERE key=1;", + {{-1234567890, 1234567891}} ,10); - CheckYqlDecimalValues(channel, sessionId, "SELECT value FROM `/Root/table-1` WHERE key=1;", - {{-1, 0}}); + CheckYqlDecimalValues(channel, sessionId, "SELECT value35 FROM `/Root/table-1` WHERE key >= 1 AND key <= 3;", + {{-1234567890, 1234567891}, {-2234567890, 1234567891}, {-3234567890, 1234567891}}, 10); - CheckYqlDecimalValues(channel, sessionId, "SELECT value FROM `/Root/table-1` WHERE key >= 1 AND key <= 3;", - {{-1, 0}, {-22, 220000000}, {-9999999999999, 999999999}}); } Y_UNIT_TEST(DecimalKey) { @@ -5010,8 +5028,8 @@ Y_UNIT_TEST_SUITE(TYqlDecimalTests) { auto &col1 = *request.add_columns(); col1.set_name("key"); auto &decimalType = *col1.mutable_type()->mutable_optional_type()->mutable_item()->mutable_decimal_type(); - decimalType.set_precision(NScheme::DECIMAL_PRECISION); - decimalType.set_scale(NScheme::DECIMAL_SCALE); + decimalType.set_precision(22); + decimalType.set_scale(9); auto &col2 = *request.add_columns(); col2.set_name("value"); col2.mutable_type()->CopyFrom(col1.type()); @@ -5030,33 +5048,33 @@ Y_UNIT_TEST_SUITE(TYqlDecimalTests) { )"); CheckYqlDecimalValues(channel, sessionId, "SELECT value FROM `/Root/table-1` WHERE key=CAST(\"1\" as DECIMAL(22,9));", - {{1, 0}}); + {{1, 0}}, 9); CheckYqlDecimalValues(channel, sessionId, "SELECT value FROM `/Root/table-1` WHERE key=CAST(\"22.22\" as DECIMAL(22,9));", - {{22, 220000000}}); + {{22, 220000000}}, 9); CheckYqlDecimalValues(channel, sessionId, "SELECT value FROM `/Root/table-1` WHERE key=CAST(\"9999999999999.999999999\" as DECIMAL(22,9));", - {{9999999999999, 999999999}}); + {{9999999999999, 999999999}}, 9); CheckYqlDecimalValues(channel, sessionId, "SELECT value FROM `/Root/table-1` WHERE key=CAST(\"-1\" as DECIMAL(22,9));", - {{-1, 0}}); + {{-1, 0}}, 9); CheckYqlDecimalValues(channel, sessionId, "SELECT value FROM `/Root/table-1` WHERE key=CAST(\"-22.22\" as DECIMAL(22,9));", - {{-22, 220000000}}); + {{-22, 220000000}}, 9); CheckYqlDecimalValues(channel, sessionId, "SELECT value FROM `/Root/table-1` WHERE key=CAST(\"-9999999999999.999999999\" as DECIMAL(22,9));", - {{-9999999999999, 999999999}}); + {{-9999999999999, 999999999}}, 9); CheckYqlDecimalValues(channel, sessionId, "SELECT value FROM `/Root/table-1` WHERE key >= CAST(\"-22.22\" as DECIMAL(22,9))", {{-22, 220000000}, {-1, 0}, - {1, 0}, {22, 220000000}, {9999999999999, 999999999}}); + {1, 0}, {22, 220000000}, {9999999999999, 999999999}}, 9); CheckYqlDecimalValues(channel, sessionId, "SELECT value FROM `/Root/table-1` WHERE key < CAST(\"-22.22\" as DECIMAL(22,9))", - {{-9999999999999, 999999999}}); + {{-9999999999999, 999999999}}, 9); CheckYqlDecimalValues(channel, sessionId, "SELECT value FROM `/Root/table-1` WHERE key > CAST(\"-22.222\" as DECIMAL(22,9)) AND key < CAST(\"22.222\" as DECIMAL(22,9))", {{-22, 220000000}, {-1, 0}, - {1, 0}, {22, 220000000}}); + {1, 0}, {22, 220000000}}, 9); } } |