aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorazevaykin <145343289+azevaykin@users.noreply.github.com>2024-10-08 13:56:35 +0300
committerGitHub <noreply@github.com>2024-10-08 13:56:35 +0300
commit8b39e36b2293ada1eae6b0919d9d12fcdd8e65df (patch)
tree02854dcba45549bc7117e3aef6633e28fb313e7e
parentdc9f4054d9ad170f88f3099c78caf3d58d095781 (diff)
downloadydb-8b39e36b2293ada1eae6b0919d9d12fcdd8e65df.tar.gz
Allow zero decimal scale (#10168)
-rw-r--r--ydb/core/kqp/ut/query/kqp_params_ut.cpp60
-rw-r--r--ydb/core/kqp/ut/scheme/kqp_scheme_ut.cpp43
-rw-r--r--ydb/core/scheme_types/scheme_decimal_type.cpp16
-rw-r--r--ydb/core/scheme_types/scheme_decimal_type.h14
-rw-r--r--ydb/services/ydb/ydb_table_ut.cpp107
-rw-r--r--ydb/services/ydb/ydb_ut.cpp98
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);
}
}