aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordcherednik <dcherednik@ydb.tech>2022-10-28 11:39:33 +0300
committerdcherednik <dcherednik@ydb.tech>2022-10-28 11:39:33 +0300
commit7d2f2555b228e6d9eb05fb8d3e42f9bedd717bbe (patch)
treea2485d467ab713cb511443541ce4fbb784a04a62
parentb1ebe898664fc5fdf6704ca0b252fce57faf901f (diff)
downloadydb-7d2f2555b228e6d9eb05fb8d3e42f9bedd717bbe.tar.gz
Uuid support for c++ SDK.
-rw-r--r--ydb/core/kqp/provider/yql_kikimr_results.cpp3
-rw-r--r--ydb/library/CMakeLists.txt1
-rw-r--r--ydb/library/uuid/CMakeLists.txt17
-rw-r--r--ydb/library/uuid/uuid.cpp58
-rw-r--r--ydb/library/uuid/uuid.h96
-rw-r--r--ydb/library/yql/minikql/CMakeLists.txt1
-rw-r--r--ydb/library/yql/minikql/mkql_type_ops.cpp136
-rw-r--r--ydb/library/yql/minikql/mkql_type_ops.h2
-rw-r--r--ydb/public/lib/json_value/CMakeLists.txt1
-rw-r--r--ydb/public/lib/json_value/ydb_json_value.cpp7
-rw-r--r--ydb/public/lib/yson_value/CMakeLists.txt1
-rw-r--r--ydb/public/lib/yson_value/ydb_yson_value.cpp3
-rw-r--r--ydb/public/sdk/cpp/client/ydb_value/CMakeLists.txt1
-rw-r--r--ydb/public/sdk/cpp/client/ydb_value/value.cpp59
-rw-r--r--ydb/public/sdk/cpp/client/ydb_value/value.h15
-rw-r--r--ydb/public/sdk/cpp/client/ydb_value/value_ut.cpp15
-rw-r--r--ydb/services/ydb/ut/CMakeLists.darwin.txt1
-rw-r--r--ydb/services/ydb/ut/CMakeLists.linux-aarch64.txt1
-rw-r--r--ydb/services/ydb/ut/CMakeLists.linux.txt1
-rw-r--r--ydb/services/ydb/ydb_ut.cpp65
20 files changed, 350 insertions, 134 deletions
diff --git a/ydb/core/kqp/provider/yql_kikimr_results.cpp b/ydb/core/kqp/provider/yql_kikimr_results.cpp
index b1a5f90ea94..be8238bceeb 100644
--- a/ydb/core/kqp/provider/yql_kikimr_results.cpp
+++ b/ydb/core/kqp/provider/yql_kikimr_results.cpp
@@ -2,6 +2,7 @@
#include <ydb/library/binary_json/read.h>
#include <ydb/library/dynumber/dynumber.h>
+#include <ydb/library/uuid/uuid.h>
#include <ydb/library/yql/providers/common/codec/yql_codec_results.h>
#include <ydb/library/yql/providers/common/provider/yql_provider.h>
@@ -49,7 +50,7 @@ void WriteValueToYson(const TStringStream& stream, NCommon::TYsonResultWriter& w
}
if (type.GetData().GetScheme() == NYql::NProto::TypeIds::Uuid) {
- using NKikimr::NMiniKQL::UuidHalfsToByteString;
+ using NKikimr::NUuid::UuidHalfsToByteString;
TStringStream stream;
UuidHalfsToByteString(value.GetLow128(), value.GetHi128(), stream);
diff --git a/ydb/library/CMakeLists.txt b/ydb/library/CMakeLists.txt
index d0c39c49203..e6671974c27 100644
--- a/ydb/library/CMakeLists.txt
+++ b/ydb/library/CMakeLists.txt
@@ -26,6 +26,7 @@ add_subdirectory(protobuf_printer)
add_subdirectory(schlab)
add_subdirectory(security)
add_subdirectory(testlib)
+add_subdirectory(uuid)
add_subdirectory(workload)
add_subdirectory(yaml_config)
add_subdirectory(ycloud)
diff --git a/ydb/library/uuid/CMakeLists.txt b/ydb/library/uuid/CMakeLists.txt
new file mode 100644
index 00000000000..4cda6e401bc
--- /dev/null
+++ b/ydb/library/uuid/CMakeLists.txt
@@ -0,0 +1,17 @@
+
+# This file was gererated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(ydb-library-uuid)
+target_link_libraries(ydb-library-uuid PUBLIC
+ contrib-libs-cxxsupp
+ yutil
+)
+target_sources(ydb-library-uuid PRIVATE
+ ${CMAKE_SOURCE_DIR}/ydb/library/uuid/uuid.cpp
+)
diff --git a/ydb/library/uuid/uuid.cpp b/ydb/library/uuid/uuid.cpp
new file mode 100644
index 00000000000..aa12c7664b4
--- /dev/null
+++ b/ydb/library/uuid/uuid.cpp
@@ -0,0 +1,58 @@
+#include "uuid.h"
+
+#include <util/stream/str.h>
+
+namespace NKikimr {
+namespace NUuid {
+
+static void WriteHexDigit(ui8 digit, IOutputStream& out) {
+ if (digit <= 9) {
+ out << char('0' + digit);
+ }
+ else {
+ out << char('a' + digit - 10);
+ }
+}
+
+static void WriteHex(ui16 bytes, IOutputStream& out, bool reverseBytes = false) {
+ if (reverseBytes) {
+ WriteHexDigit((bytes >> 4) & 0x0f, out);
+ WriteHexDigit(bytes & 0x0f, out);
+ WriteHexDigit((bytes >> 12) & 0x0f, out);
+ WriteHexDigit((bytes >> 8) & 0x0f, out);
+ } else {
+ WriteHexDigit((bytes >> 12) & 0x0f, out);
+ WriteHexDigit((bytes >> 8) & 0x0f, out);
+ WriteHexDigit((bytes >> 4) & 0x0f, out);
+ WriteHexDigit(bytes & 0x0f, out);
+ }
+}
+
+void UuidToString(ui16 dw[8], IOutputStream& out) {
+ WriteHex(dw[1], out);
+ WriteHex(dw[0], out);
+ out << '-';
+ WriteHex(dw[2], out);
+ out << '-';
+ WriteHex(dw[3], out);
+ out << '-';
+ WriteHex(dw[4], out, true);
+ out << '-';
+ WriteHex(dw[5], out, true);
+ WriteHex(dw[6], out, true);
+ WriteHex(dw[7], out, true);
+}
+
+void UuidHalfsToByteString(ui64 low, ui64 hi, IOutputStream& out) {
+ union {
+ char bytes[16];
+ ui64 half[2];
+ } buf;
+ buf.half[0] = low;
+ buf.half[1] = hi;
+ out.Write(buf.bytes, 16);
+}
+
+}
+}
+
diff --git a/ydb/library/uuid/uuid.h b/ydb/library/uuid/uuid.h
new file mode 100644
index 00000000000..4c890903713
--- /dev/null
+++ b/ydb/library/uuid/uuid.h
@@ -0,0 +1,96 @@
+#pragma once
+#include <util/system/types.h>
+
+#include <cctype>
+#include <utility>
+
+class IOutputStream;
+
+namespace NKikimr {
+namespace NUuid {
+
+void UuidToString(ui16 dw[8], IOutputStream& out);
+void UuidHalfsToByteString(ui64 low, ui64 hi, IOutputStream& out);
+
+inline bool GetDigit(char c, ui32& digit) {
+ digit = 0;
+ if ('0' <= c && c <= '9') {
+ digit = c - '0';
+ }
+ else if ('a' <= c && c <= 'f') {
+ digit = c - 'a' + 10;
+ }
+ else if ('A' <= c && c <= 'F') {
+ digit = c - 'A' + 10;
+ }
+ else {
+ return false; // non-hex character
+ }
+ return true;
+}
+
+template<typename T>
+inline bool IsValidUuid(const T& buf) {
+ if (buf.Size() != 36) {
+ return false;
+ }
+
+ for (size_t i = 0; i < buf.Size(); ++i) {
+ const char c = buf.Data()[i];
+
+ if (c == '-') {
+ if (i != 8 && i != 13 && i != 18 && i != 23) {
+ return false;
+ }
+ } else if (!std::isxdigit(c)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template<typename T>
+bool ParseUuidToArray(const T& buf, ui16* dw, bool shortForm) {
+ if (buf.Size() != (shortForm ? 32 : 36)) {
+ return false;
+ }
+
+ size_t partId = 0;
+ ui64 partValue = 0;
+ size_t digitCount = 0;
+
+ for (size_t i = 0; i < buf.Size(); ++i) {
+ const char c = buf.Data()[i];
+
+ if (!shortForm && (i == 8 || i == 13 || i == 18 || i == 23)) {
+ if (c == '-') {
+ continue;
+ } else {
+ return false;
+ }
+ }
+
+ ui32 digit = 0;
+ if (!GetDigit(c, digit)) {
+ return false;
+ }
+
+ partValue = partValue * 16 + digit;
+
+ if (++digitCount == 4) {
+ dw[partId++] = partValue;
+ digitCount = 0;
+ }
+ }
+
+ std::swap(dw[0], dw[1]);
+ for (ui32 i = 4; i < 8; ++i) {
+ dw[i] = ((dw[i] >> 8) & 0xff) | ((dw[i] & 0xff) << 8);
+ }
+
+ return true;
+}
+
+}
+}
diff --git a/ydb/library/yql/minikql/CMakeLists.txt b/ydb/library/yql/minikql/CMakeLists.txt
index d3aab5921b0..e91dcfdbd71 100644
--- a/ydb/library/yql/minikql/CMakeLists.txt
+++ b/ydb/library/yql/minikql/CMakeLists.txt
@@ -41,6 +41,7 @@ target_link_libraries(library-yql-minikql PUBLIC
yql-public-udf
public-udf-tz
library-yql-utils
+ ydb-library-uuid
)
target_sources(library-yql-minikql PRIVATE
${CMAKE_SOURCE_DIR}/ydb/library/yql/minikql/aligned_page_pool.cpp
diff --git a/ydb/library/yql/minikql/mkql_type_ops.cpp b/ydb/library/yql/minikql/mkql_type_ops.cpp
index 8b6fe3caa4e..8f092c63850 100644
--- a/ydb/library/yql/minikql/mkql_type_ops.cpp
+++ b/ydb/library/yql/minikql/mkql_type_ops.cpp
@@ -11,6 +11,7 @@
#include <ydb/library/binary_json/write.h>
#include <ydb/library/binary_json/read.h>
+#include <ydb/library/uuid/uuid.h>
#include <ydb/library/dynumber/dynumber.h>
#include <library/cpp/containers/stack_vector/stack_vec.h>
@@ -311,54 +312,6 @@ bool WriteInterval(IOutputStream& out, i64 signedValue) {
return true;
}
-static void WriteHexDigit(ui8 digit, IOutputStream& out) {
- if (digit <= 9) {
- out << char('0' + digit);
- }
- else {
- out << char('a' + digit - 10);
- }
-}
-
-static void WriteHex(ui16 bytes, IOutputStream& out, bool reverseBytes = false) {
- if (reverseBytes) {
- WriteHexDigit((bytes >> 4) & 0x0f, out);
- WriteHexDigit(bytes & 0x0f, out);
- WriteHexDigit((bytes >> 12) & 0x0f, out);
- WriteHexDigit((bytes >> 8) & 0x0f, out);
- } else {
- WriteHexDigit((bytes >> 12) & 0x0f, out);
- WriteHexDigit((bytes >> 8) & 0x0f, out);
- WriteHexDigit((bytes >> 4) & 0x0f, out);
- WriteHexDigit(bytes & 0x0f, out);
- }
-}
-
-static void UuidToString(ui16 dw[8], IOutputStream& out) {
- WriteHex(dw[1], out);
- WriteHex(dw[0], out);
- out << '-';
- WriteHex(dw[2], out);
- out << '-';
- WriteHex(dw[3], out);
- out << '-';
- WriteHex(dw[4], out, true);
- out << '-';
- WriteHex(dw[5], out, true);
- WriteHex(dw[6], out, true);
- WriteHex(dw[7], out, true);
-}
-
-}
-
-void UuidHalfsToByteString(ui64 low, ui64 hi, IOutputStream& out) {
- union {
- char bytes[16];
- ui64 half[2];
- } buf;
- buf.half[0] = low;
- buf.half[1] = hi;
- out.Write(buf.bytes, 16);
}
NUdf::TUnboxedValuePod ValueToString(NUdf::EDataSlot type, NUdf::TUnboxedValuePod value) {
@@ -417,7 +370,7 @@ NUdf::TUnboxedValuePod ValueToString(NUdf::EDataSlot type, NUdf::TUnboxedValuePo
case NUdf::EDataSlot::Uuid: {
ui16 dw[8];
std::memcpy(dw, value.AsStringRef().Data(), sizeof(dw));
- UuidToString(dw, out);
+ NUuid::UuidToString(dw, out);
break;
}
@@ -969,89 +922,10 @@ ui32 ParseNumber(ui32& pos, NUdf::TStringRef buf, ui32& value, i8 dig_cnt) {
return count;
}
-static bool GetDigit(char c, ui32& digit) {
- digit = 0;
- if ('0' <= c && c <= '9') {
- digit = c - '0';
- }
- else if ('a' <= c && c <= 'f') {
- digit = c - 'a' + 10;
- }
- else if ('A' <= c && c <= 'F') {
- digit = c - 'A' + 10;
- }
- else {
- return false; // non-hex character
- }
- return true;
-}
-
-bool IsValidUuid(NUdf::TStringRef buf) {
- if (buf.Size() != 36) {
- return false;
- }
-
- for (size_t i = 0; i < buf.Size(); ++i) {
- const char c = buf.Data()[i];
-
- if (c == '-') {
- if (i != 8 && i != 13 && i != 18 && i != 23) {
- return false;
- }
- } else if (!std::isxdigit(c)) {
- return false;
- }
- }
-
- return true;
-}
-
-
-static bool ParseUuidToArray(NUdf::TStringRef buf, ui16* dw, bool shortForm) {
- if (buf.Size() != (shortForm ? 32 : 36)) {
- return false;
- }
-
- size_t partId = 0;
- ui64 partValue = 0;
- size_t digitCount = 0;
-
- for (size_t i = 0; i < buf.Size(); ++i) {
- const char c = buf.Data()[i];
-
- if (!shortForm && (i == 8 || i == 13 || i == 18 || i == 23)) {
- if (c == '-') {
- continue;
- } else {
- return false;
- }
- }
-
- ui32 digit = 0;
- if (!GetDigit(c, digit)) {
- return false;
- }
-
- partValue = partValue * 16 + digit;
-
- if (++digitCount == 4) {
- dw[partId++] = partValue;
- digitCount = 0;
- }
- }
-
- std::swap(dw[0], dw[1]);
- for (ui32 i = 4; i < 8; ++i) {
- dw[i] = ((dw[i] >> 8) & 0xff) | ((dw[i] & 0xff) << 8);
- }
-
- return true;
-}
-
NUdf::TUnboxedValuePod ParseUuid(NUdf::TStringRef buf, bool shortForm) {
ui16 dw[8];
- if (!ParseUuidToArray(buf, dw, shortForm)) {
+ if (!NUuid::ParseUuidToArray(buf, dw, shortForm)) {
return NUdf::TUnboxedValuePod();
}
@@ -1061,7 +935,7 @@ NUdf::TUnboxedValuePod ParseUuid(NUdf::TStringRef buf, bool shortForm) {
bool ParseUuid(NUdf::TStringRef buf, void* out, bool shortForm) {
ui16 dw[8];
- if (!ParseUuidToArray(buf, dw, shortForm)) {
+ if (!NUuid::ParseUuidToArray(buf, dw, shortForm)) {
return false;
}
@@ -1685,7 +1559,7 @@ bool IsValidStringValue(NUdf::EDataSlot type, NUdf::TStringRef buf) {
case NUdf::EDataSlot::JsonDocument:
return NDom::IsValidJson(buf);
case NUdf::EDataSlot::Uuid:
- return IsValidUuid(buf);
+ return NUuid::IsValidUuid(buf);
case NUdf::EDataSlot::DyNumber:
return NDyNumber::IsValidDyNumberString(buf);
diff --git a/ydb/library/yql/minikql/mkql_type_ops.h b/ydb/library/yql/minikql/mkql_type_ops.h
index 8ff9b258ddf..4c30121e9ac 100644
--- a/ydb/library/yql/minikql/mkql_type_ops.h
+++ b/ydb/library/yql/minikql/mkql_type_ops.h
@@ -19,8 +19,6 @@ bool IsLeapYear(ui32 year);
ui32 GetMonthLength(ui32 month, bool isLeap);
-void UuidHalfsToByteString(ui64 low, ui64 hi, IOutputStream& out);
-
bool IsValidStringValue(NUdf::EDataSlot type, NUdf::TStringRef buf);
NUdf::TUnboxedValuePod ValueFromString(NUdf::EDataSlot type, NUdf::TStringRef buf);
diff --git a/ydb/public/lib/json_value/CMakeLists.txt b/ydb/public/lib/json_value/CMakeLists.txt
index 5a8f7be33d7..704967228b5 100644
--- a/ydb/public/lib/json_value/CMakeLists.txt
+++ b/ydb/public/lib/json_value/CMakeLists.txt
@@ -16,6 +16,7 @@ target_link_libraries(public-lib-json_value PUBLIC
cpp-string_utils-base64
cpp-client-ydb_result
cpp-client-ydb_value
+ ydb-library-uuid
)
target_sources(public-lib-json_value PRIVATE
${CMAKE_SOURCE_DIR}/ydb/public/lib/json_value/ydb_json_value.cpp
diff --git a/ydb/public/lib/json_value/ydb_json_value.cpp b/ydb/public/lib/json_value/ydb_json_value.cpp
index a8d48c77d45..dbfb05b315e 100644
--- a/ydb/public/lib/json_value/ydb_json_value.cpp
+++ b/ydb/public/lib/json_value/ydb_json_value.cpp
@@ -189,6 +189,9 @@ namespace NYdb {
case EPrimitiveType::Json:
Writer.WriteString(Parser.GetJson());
break;
+ case EPrimitiveType::Uuid:
+ Writer.WriteString(Parser.GetUuid().ToString());
+ break;
case EPrimitiveType::JsonDocument:
Writer.WriteString(Parser.GetJsonDocument());
break;
@@ -552,6 +555,10 @@ namespace {
EnsureType(jsonValue, NJson::JSON_STRING);
ValueBuilder.Json(jsonValue.GetString());
break;
+ case EPrimitiveType::Uuid:
+ EnsureType(jsonValue, NJson::JSON_STRING);
+ ValueBuilder.Uuid(jsonValue.GetString());
+ break;
case EPrimitiveType::JsonDocument:
EnsureType(jsonValue, NJson::JSON_STRING);
ValueBuilder.JsonDocument(jsonValue.GetString());
diff --git a/ydb/public/lib/yson_value/CMakeLists.txt b/ydb/public/lib/yson_value/CMakeLists.txt
index 86f9e8efce5..737b5947458 100644
--- a/ydb/public/lib/yson_value/CMakeLists.txt
+++ b/ydb/public/lib/yson_value/CMakeLists.txt
@@ -15,6 +15,7 @@ target_link_libraries(public-lib-yson_value PUBLIC
cpp-yson-node
cpp-client-ydb_result
cpp-client-ydb_value
+ ydb-library-uuid
)
target_sources(public-lib-yson_value PRIVATE
${CMAKE_SOURCE_DIR}/ydb/public/lib/yson_value/ydb_yson_value.cpp
diff --git a/ydb/public/lib/yson_value/ydb_yson_value.cpp b/ydb/public/lib/yson_value/ydb_yson_value.cpp
index d73b1c41e7a..5658f1edbd5 100644
--- a/ydb/public/lib/yson_value/ydb_yson_value.cpp
+++ b/ydb/public/lib/yson_value/ydb_yson_value.cpp
@@ -79,6 +79,9 @@ static void PrimitiveValueToYson(EPrimitiveType type, TValueParser& parser, NYso
case EPrimitiveType::JsonDocument:
writer.OnStringScalar(parser.GetJsonDocument());
break;
+ case EPrimitiveType::Uuid:
+ writer.OnStringScalar(parser.GetUuid().ToString());
+ break;
case EPrimitiveType::DyNumber:
writer.OnStringScalar(parser.GetDyNumber());
break;
diff --git a/ydb/public/sdk/cpp/client/ydb_value/CMakeLists.txt b/ydb/public/sdk/cpp/client/ydb_value/CMakeLists.txt
index b622bb115ee..5e1a1bd390b 100644
--- a/ydb/public/sdk/cpp/client/ydb_value/CMakeLists.txt
+++ b/ydb/public/sdk/cpp/client/ydb_value/CMakeLists.txt
@@ -19,6 +19,7 @@ target_link_libraries(cpp-client-ydb_value PUBLIC
cpp-client-ydb_proto
client-ydb_types-fatal_error_handlers
yql-public-decimal
+ ydb-library-uuid
)
target_sources(cpp-client-ydb_value PRIVATE
${CMAKE_SOURCE_DIR}/ydb/public/sdk/cpp/client/ydb_value/value.cpp
diff --git a/ydb/public/sdk/cpp/client/ydb_value/value.cpp b/ydb/public/sdk/cpp/client/ydb_value/value.cpp
index 25336625a07..c9c9a7edd59 100644
--- a/ydb/public/sdk/cpp/client/ydb_value/value.cpp
+++ b/ydb/public/sdk/cpp/client/ydb_value/value.cpp
@@ -13,6 +13,7 @@
#include <library/cpp/containers/stack_vector/stack_vec.h>
#include <ydb/library/yql/public/decimal/yql_decimal.h>
+#include <ydb/library/uuid/uuid.h>
#include <util/generic/bitmap.h>
#include <util/generic/map.h>
@@ -950,6 +951,32 @@ bool TPgValue::IsText() const {
////////////////////////////////////////////////////////////////////////////////
+TUuidValue::TUuidValue(const Ydb::Value& valueProto) {
+ Buf_.Halfs[0] = valueProto.low_128();
+ Buf_.Halfs[1] = valueProto.high_128();
+}
+
+TUuidValue::TUuidValue(const TString& uuidString) {
+ ui16 dw[8];
+ if (!NKikimr::NUuid::ParseUuidToArray(uuidString, dw, false)) {
+ ThrowFatalError(TStringBuilder() << "Unable to parse string as uuid");
+ }
+ static_assert(sizeof(dw) == sizeof(Buf_.Bytes));
+ std::memcpy(Buf_.Bytes, dw, sizeof(dw));
+}
+
+TString TUuidValue::ToString() const {
+ TStringStream s;
+ ui16 dw[8];
+ static_assert(sizeof(dw) == sizeof(Buf_.Bytes));
+ std::memcpy(dw, Buf_.Bytes, sizeof(dw));
+ NKikimr::NUuid::UuidToString(dw, s);
+ return s.Str();
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
class TValue::TImpl {
public:
TImpl(const TType& type, const Ydb::Value& valueProto)
@@ -1135,6 +1162,11 @@ public:
return GetProto().text_value();
}
+ TUuidValue GetUuid() const {
+ CheckPrimitive(NYdb::EPrimitiveType::Uuid);
+ return TUuidValue(GetProto());
+ }
+
const TString& GetJsonDocument() const {
CheckPrimitive(NYdb::EPrimitiveType::JsonDocument);
return GetProto().text_value();
@@ -1491,6 +1523,8 @@ private:
case NYdb::EPrimitiveType::JsonDocument:
case NYdb::EPrimitiveType::DyNumber:
return Ydb::Value::kTextValue;
+ case NYdb::EPrimitiveType::Uuid:
+ return Ydb::Value::kLow128;
default:
FatalError(TStringBuilder() << "Unexpected primitive type: " << primitiveTypeId);
return Ydb::Value::kBytesValue;
@@ -1620,6 +1654,10 @@ const TString& TValueParser::GetJson() const {
return Impl_->GetJson();
}
+TUuidValue TValueParser::GetUuid() const {
+ return Impl_->GetUuid();
+}
+
const TString& TValueParser::GetJsonDocument() const {
return Impl_->GetJsonDocument();
}
@@ -1732,6 +1770,10 @@ TMaybe<TString> TValueParser::GetOptionalJson() const {
RET_OPT_VALUE(TString, Json);
}
+TMaybe<TUuidValue> TValueParser::GetOptionalUuid() const {
+ RET_OPT_VALUE(TUuidValue, Uuid);
+}
+
TMaybe<TString> TValueParser::GetOptionalJsonDocument() const {
RET_OPT_VALUE(TString, JsonDocument);
}
@@ -2008,6 +2050,12 @@ public:
GetValue().set_text_value(value);
}
+ void Uuid(const TUuidValue& value) {
+ FillPrimitiveType(EPrimitiveType::Uuid);
+ GetValue().set_low_128(value.Buf_.Halfs[0]);
+ GetValue().set_high_128(value.Buf_.Halfs[1]);
+ }
+
void JsonDocument(const TString& value) {
FillPrimitiveType(EPrimitiveType::JsonDocument);
GetValue().set_text_value(value);
@@ -2707,6 +2755,12 @@ TDerived& TValueBuilderBase<TDerived>::Json(const TString& value) {
}
template<typename TDerived>
+TDerived& TValueBuilderBase<TDerived>::Uuid(const TUuidValue& value) {
+ Impl_->Uuid(value);
+ return static_cast<TDerived&>(*this);
+}
+
+template<typename TDerived>
TDerived& TValueBuilderBase<TDerived>::JsonDocument(const TString& value) {
Impl_->JsonDocument(value);
return static_cast<TDerived&>(*this);
@@ -2857,6 +2911,11 @@ TDerived& TValueBuilderBase<TDerived>::OptionalJson(const TMaybe<TString>& value
}
template<typename TDerived>
+TDerived& TValueBuilderBase<TDerived>::OptionalUuid(const TMaybe<TUuidValue>& value) {
+ SET_OPT_VALUE_MAYBE(Uuid);
+}
+
+template<typename TDerived>
TDerived& TValueBuilderBase<TDerived>::OptionalJsonDocument(const TMaybe<TString>& value) {
SET_OPT_VALUE_MAYBE(JsonDocument);
}
diff --git a/ydb/public/sdk/cpp/client/ydb_value/value.h b/ydb/public/sdk/cpp/client/ydb_value/value.h
index 2a5a96d1826..0186260a984 100644
--- a/ydb/public/sdk/cpp/client/ydb_value/value.h
+++ b/ydb/public/sdk/cpp/client/ydb_value/value.h
@@ -237,6 +237,17 @@ struct TPgValue {
TString Content_;
};
+struct TUuidValue {
+ TString ToString() const;
+ TUuidValue(const Ydb::Value& uuidValueProto);
+ TUuidValue(const TString& uuidString);
+
+ union {
+ char Bytes[16];
+ ui64 Halfs[2];
+ } Buf_;
+};
+
//! Representation of YDB value.
class TValue {
friend class TValueParser;
@@ -290,6 +301,7 @@ public:
const TString& GetJson() const;
TDecimalValue GetDecimal() const;
TPgValue GetPg() const;
+ TUuidValue GetUuid() const;
const TString& GetJsonDocument() const;
const TString& GetDyNumber() const;
@@ -316,6 +328,7 @@ public:
TMaybe<TString> GetOptionalYson() const;
TMaybe<TString> GetOptionalJson() const;
TMaybe<TDecimalValue> GetOptionalDecimal() const;
+ TMaybe<TUuidValue> GetOptionalUuid() const;
TMaybe<TString> GetOptionalJsonDocument() const;
TMaybe<TString> GetOptionalDyNumber() const;
@@ -394,6 +407,7 @@ public:
TDerived& Json(const TString& value);
TDerived& Decimal(const TDecimalValue& value);
TDerived& Pg(const TPgValue& value);
+ TDerived& Uuid(const TUuidValue& value);
TDerived& JsonDocument(const TString& value);
TDerived& DyNumber(const TString& value);
@@ -419,6 +433,7 @@ public:
TDerived& OptionalUtf8(const TMaybe<TString>& value);
TDerived& OptionalYson(const TMaybe<TString>& value);
TDerived& OptionalJson(const TMaybe<TString>& value);
+ TDerived& OptionalUuid(const TMaybe<TUuidValue>& value);
TDerived& OptionalJsonDocument(const TMaybe<TString>& value);
TDerived& OptionalDyNumber(const TMaybe<TString>& value);
diff --git a/ydb/public/sdk/cpp/client/ydb_value/value_ut.cpp b/ydb/public/sdk/cpp/client/ydb_value/value_ut.cpp
index 8f6b8553f9d..43c23dbbd69 100644
--- a/ydb/public/sdk/cpp/client/ydb_value/value_ut.cpp
+++ b/ydb/public/sdk/cpp/client/ydb_value/value_ut.cpp
@@ -1,6 +1,7 @@
#include <ydb/public/api/protos/ydb_value.pb.h>
#include <ydb/public/sdk/cpp/client/ydb_proto/accessor.h>
#include <ydb/public/sdk/cpp/client/ydb_value/value.h>
+#include <ydb/public/sdk/cpp/client/ydb_types/exceptions/exceptions.h>
#include <ydb/public/lib/json_value/ydb_json_value.h>
#include <ydb/public/lib/yson_value/ydb_yson_value.h>
@@ -1311,6 +1312,20 @@ Y_UNIT_TEST_SUITE(YdbValue) {
UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode),
R"([{"Name":"Sergey","Value":1},null,[true],[[10,null]],"12.345"])");
}
+
+ Y_UNIT_TEST(CorrectUuid) {
+ TString uuidStr = "5ca32c22-841b-11e8-adc0-fa7ae01bbebc";
+ TUuidValue uuid(uuidStr);
+ UNIT_ASSERT_VALUES_EQUAL(uuidStr, uuid.ToString());
+ }
+
+ Y_UNIT_TEST(IncorrectUuid) {
+ UNIT_ASSERT_EXCEPTION(TUuidValue(""), TContractViolation);
+ UNIT_ASSERT_EXCEPTION(TUuidValue("0123456789abcdef0123456789abcdef0123456789abcdef"), TContractViolation);
+ UNIT_ASSERT_EXCEPTION(TUuidValue("5ca32c22+841b-11e8-adc0-fa7ae01bbebc"), TContractViolation);
+ UNIT_ASSERT_EXCEPTION(TUuidValue("5ca32-c22841b-11e8-adc0-fa7ae01bbebc"), TContractViolation);
+ }
+
}
} // namespace NYdb
diff --git a/ydb/services/ydb/ut/CMakeLists.darwin.txt b/ydb/services/ydb/ut/CMakeLists.darwin.txt
index 1e8060eaff9..1fb9b5abfd9 100644
--- a/ydb/services/ydb/ut/CMakeLists.darwin.txt
+++ b/ydb/services/ydb/ut/CMakeLists.darwin.txt
@@ -30,6 +30,7 @@ target_link_libraries(ydb-services-ydb-ut PUBLIC
yql-minikql-dom
yql-minikql-jsonpath
public-lib-experimental
+ public-lib-json_value
public-lib-yson_value
cpp-client-draft
cpp-client-ydb_coordination
diff --git a/ydb/services/ydb/ut/CMakeLists.linux-aarch64.txt b/ydb/services/ydb/ut/CMakeLists.linux-aarch64.txt
index 65218c59d4f..346b86dd319 100644
--- a/ydb/services/ydb/ut/CMakeLists.linux-aarch64.txt
+++ b/ydb/services/ydb/ut/CMakeLists.linux-aarch64.txt
@@ -30,6 +30,7 @@ target_link_libraries(ydb-services-ydb-ut PUBLIC
yql-minikql-dom
yql-minikql-jsonpath
public-lib-experimental
+ public-lib-json_value
public-lib-yson_value
cpp-client-draft
cpp-client-ydb_coordination
diff --git a/ydb/services/ydb/ut/CMakeLists.linux.txt b/ydb/services/ydb/ut/CMakeLists.linux.txt
index b4c55437f16..82a7bd8b799 100644
--- a/ydb/services/ydb/ut/CMakeLists.linux.txt
+++ b/ydb/services/ydb/ut/CMakeLists.linux.txt
@@ -32,6 +32,7 @@ target_link_libraries(ydb-services-ydb-ut PUBLIC
yql-minikql-dom
yql-minikql-jsonpath
public-lib-experimental
+ public-lib-json_value
public-lib-yson_value
cpp-client-draft
cpp-client-ydb_coordination
diff --git a/ydb/services/ydb/ydb_ut.cpp b/ydb/services/ydb/ydb_ut.cpp
index acb0647aa61..fb6a522f67a 100644
--- a/ydb/services/ydb/ydb_ut.cpp
+++ b/ydb/services/ydb/ydb_ut.cpp
@@ -29,6 +29,9 @@
#include <ydb/public/sdk/cpp/client/ydb_table/table.h>
#include <ydb/public/sdk/cpp/client/resources/ydb_resources.h>
+#include <ydb/public/lib/yson_value/ydb_yson_value.h>
+#include <ydb/public/lib/json_value/ydb_json_value.h>
+
#include "ydb_common_ut.h"
#include <util/generic/ymath.h>
@@ -1963,6 +1966,68 @@ tx_meta {
}
}
+ Y_UNIT_TEST(SdkUuid) {
+ TKikimrWithGrpcAndRootSchema server;
+ ui16 grpc = server.GetPort();
+
+ TString location = TStringBuilder() << "localhost:" << grpc;
+
+ auto connection = NYdb::TDriver(
+ TDriverConfig()
+ .SetEndpoint(location));
+ auto client = NYdb::NTable::TTableClient(connection);
+ auto session = client.CreateSession().ExtractValueSync().GetSession();
+
+ auto result = session.ExecuteDataQuery(R"(
+ SELECT CAST("5ca32c22-841b-11e8-adc0-fa7ae01bbebc" AS Uuid);
+ )", TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()).ExtractValueSync();
+
+ UNIT_ASSERT(result.IsSuccess());
+
+ TString expectedJson = R"({"column0":"5ca32c22-841b-11e8-adc0-fa7ae01bbebc"}
+)";
+ UNIT_ASSERT_VALUES_EQUAL(expectedJson, NYdb::FormatResultSetJson(result.GetResultSet(0), NYdb::EBinaryStringEncoding::Base64));
+
+ UNIT_ASSERT_VALUES_EQUAL(R"([[["5ca32c22-841b-11e8-adc0-fa7ae01bbebc"]]])", NYdb::FormatResultSetYson(result.GetResultSet(0)));
+ }
+
+ Y_UNIT_TEST(SdkUuidViaParams) {
+ TKikimrWithGrpcAndRootSchema server;
+ ui16 grpc = server.GetPort();
+
+ TString location = TStringBuilder() << "localhost:" << grpc;
+
+ auto connection = NYdb::TDriver(
+ TDriverConfig()
+ .SetEndpoint(location));
+ auto client = NYdb::NTable::TTableClient(connection);
+ auto session = client.CreateSession().ExtractValueSync().GetSession();
+
+ auto param = client.GetParamsBuilder()
+ .AddParam("$in")
+ .BeginList()
+ .AddListItem()
+ .BeginStruct()
+ .AddMember("u").Uuid(TUuidValue("5ca32c22-841b-11e8-adc0-fa7ae01bbebc"))
+ .EndStruct()
+ .EndList()
+ .Build()
+ .Build();
+ auto result = session.ExecuteDataQuery(R"(
+ DECLARE $in AS List<Struct<u: Uuid>>;
+ SELECT * FROM AS_TABLE($in);
+ )", TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx(), param).ExtractValueSync();
+
+ UNIT_ASSERT(result.IsSuccess());
+
+ TString expectedJson = R"({"u":"5ca32c22-841b-11e8-adc0-fa7ae01bbebc"}
+)";
+ UNIT_ASSERT_VALUES_EQUAL(expectedJson, NYdb::FormatResultSetJson(result.GetResultSet(0), NYdb::EBinaryStringEncoding::Base64));
+
+ UNIT_ASSERT_VALUES_EQUAL(R"([["5ca32c22-841b-11e8-adc0-fa7ae01bbebc"]])", NYdb::FormatResultSetYson(result.GetResultSet(0)));
+ }
+
+
Y_UNIT_TEST(ExecuteQueryWithParametersBadRequest) {
TKikimrWithGrpcAndRootSchema server;
ui16 grpc = server.GetPort();