Skip to content

Commit ffe6c72

Browse files
SammyVimesdcherednik
authored andcommitted
YDB-2757 Fix UUID column export (ydb-platform#2789)
Fixes ydb-platform#2757
1 parent 090c0ad commit ffe6c72

File tree

6 files changed

+135
-1
lines changed

6 files changed

+135
-1
lines changed

ydb/core/io_formats/cell_maker/cell_maker.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <ydb/library/binary_json/write.h>
44
#include <ydb/library/dynumber/dynumber.h>
5+
#include <ydb/library/uuid/uuid.h>
56

67
#include <ydb/library/yql/minikql/dom/yson.h>
78
#include <ydb/library/yql/minikql/dom/json.h>
@@ -132,6 +133,21 @@ namespace {
132133
return true;
133134
}
134135

136+
struct TUuidHolder {
137+
union {
138+
ui16 Array[8];
139+
ui64 Halves[2];
140+
} Buf;
141+
};
142+
143+
template <>
144+
bool TryParse(TStringBuf value, TUuidHolder& result) {
145+
if (!NUuid::ParseUuidToArray(value, result.Buf.Array, false)) {
146+
return false;
147+
}
148+
return true;
149+
}
150+
135151
template <typename T, typename U>
136152
using TConverter = std::function<U(const T&)>;
137153

@@ -171,6 +187,14 @@ namespace {
171187
return v.Str;
172188
}
173189

190+
TStringBuf UuidToStringBuf(const TUuidHolder& uuid) {
191+
char uuidBuf[16];
192+
193+
NUuid::UuidHalfsToBytes(uuidBuf, 16, uuid.Buf.Halves[1], uuid.Buf.Halves[0]);
194+
195+
return TStringBuf(uuidBuf, 16);
196+
}
197+
174198
template <typename T, typename U = T>
175199
struct TCellMaker {
176200
static bool Make(TCell& c, TStringBuf v, TMemoryPool& pool, TString& err, TConverter<T, U> conv = &Implicit<T, U>) {
@@ -297,6 +321,8 @@ bool MakeCell(TCell& cell, TStringBuf value, NScheme::TTypeInfo type, TMemoryPoo
297321
return TCellMaker<NYql::NDecimal::TInt128, std::pair<ui64, ui64>>::Make(cell, value, pool, err, &Int128ToPair);
298322
case NScheme::NTypeIds::Pg:
299323
return TCellMaker<NPg::TConvertResult, TStringBuf>::Make(cell, value, pool, err, &PgToStringBuf, type.GetTypeDesc());
324+
case NScheme::NTypeIds::Uuid:
325+
return TCellMaker<TUuidHolder, TStringBuf>::Make(cell, value, pool, err, &UuidToStringBuf);
300326
default:
301327
return false;
302328
}
@@ -390,6 +416,7 @@ bool CheckCellValue(const TCell& cell, NScheme::TTypeInfo type) {
390416
case NScheme::NTypeIds::JsonDocument: // checked at parsing time
391417
case NScheme::NTypeIds::DyNumber: // checked at parsing time
392418
case NScheme::NTypeIds::Pg: // checked at parsing time
419+
case NScheme::NTypeIds::Uuid: // checked at parsing time
393420
return true;
394421
case NScheme::NTypeIds::Date:
395422
return cell.AsValue<ui16>() < NUdf::MAX_DATE;

ydb/core/tx/datashard/export_common.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,5 +118,15 @@ bool PgToStream(TStringBuf data, void* typeDesc, IOutputStream& out, TString& er
118118
return true;
119119
}
120120

121+
bool UuidToStream(const std::pair<ui64, ui64>& loHi, IOutputStream& out, TString& err) {
122+
Y_UNUSED(err);
123+
124+
NYdb::TUuidValue uuid(loHi.first, loHi.second);
125+
126+
out << uuid.ToString();
127+
128+
return true;
129+
}
130+
121131
} // NDataShard
122132
} // NKikimr

ydb/core/tx/datashard/export_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ TString DyNumberToString(TStringBuf data);
4040
bool DecimalToStream(const std::pair<ui64, i64>& loHi, IOutputStream& out, TString& err);
4141
bool DyNumberToStream(TStringBuf data, IOutputStream& out, TString& err);
4242
bool PgToStream(TStringBuf data, void* typeDesc, IOutputStream& out, TString& err);
43+
bool UuidToStream(const std::pair<ui64, ui64>& loHi, IOutputStream& out, TString& err);
4344

4445
} // NDataShard
4546
} // NKikimr

ydb/core/tx/datashard/export_s3_buffer_raw.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ bool TS3BufferRaw::Collect(const NTable::IScan::TRow& row, IOutputStream& out) {
125125
case NScheme::NTypeIds::Pg:
126126
serialized = PgToStream(cell.AsBuf(), column.Type.GetTypeDesc(), out, ErrorString);
127127
break;
128+
case NScheme::NTypeIds::Uuid:
129+
serialized = UuidToStream(cell.AsValue<std::pair<ui64, ui64>>(), out, ErrorString);
130+
break;
128131
default:
129132
Y_ABORT("Unsupported type");
130133
}

ydb/core/tx/schemeshard/ut_backup/ut_backup.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,30 @@ Y_UNIT_TEST_SUITE(TBackupTests) {
100100
});
101101
}
102102

103+
Y_UNIT_TEST_WITH_COMPRESSION(BackupUuidColumn) {
104+
TTestBasicRuntime runtime;
105+
106+
Backup(runtime, ToString(Codec), R"(
107+
Name: "Table"
108+
Columns { Name: "key" Type: "Uint32" }
109+
Columns { Name: "value" Type: "Uuid" }
110+
KeyColumnNames: ["key"]
111+
)", [](TTestBasicRuntime& runtime) {
112+
NKikimrMiniKQL::TResult result;
113+
TString error;
114+
NKikimrProto::EReplyStatus status = LocalMiniKQL(runtime, TTestTxConfig::FakeHiveTablets, Sprintf(R"(
115+
(
116+
(let key '( '('key (Uint32 '%d) ) ) )
117+
(let row '( '('value (Uuid '"%s") ) ) )
118+
(return (AsList (UpdateRow '__user__%s key row) ))
119+
)
120+
)", 1, "0000111122223333", "Table"), result, error);
121+
122+
UNIT_ASSERT_VALUES_EQUAL_C(status, NKikimrProto::EReplyStatus::OK, error);
123+
UNIT_ASSERT_VALUES_EQUAL(error, "");
124+
});
125+
}
126+
103127
template<ECompressionCodec Codec>
104128
void ShouldSucceedOnLargeData(ui32 minWriteBatchSize, const std::pair<ui32, ui32>& expectedResult) {
105129
TTestBasicRuntime runtime;

ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,76 @@ value {
11351135
env.TestWaitNotification(runtime, txId);
11361136
TestGetExport(runtime, txId, "/MyRoot");
11371137

1138-
TestImport(runtime, txId, "/MyRoot", Sprintf(R"(
1138+
TestImport(runtime, ++txId, "/MyRoot", Sprintf(R"(
1139+
ImportFromS3Settings {
1140+
endpoint: "localhost:%d"
1141+
scheme: HTTP
1142+
items {
1143+
source_prefix: "Backup1"
1144+
destination_path: "/MyRoot/Restored"
1145+
}
1146+
}
1147+
)", port));
1148+
env.TestWaitNotification(runtime, txId);
1149+
TestGetImport(runtime, txId, "/MyRoot");
1150+
}
1151+
1152+
Y_UNIT_TEST(ExportImportUuid) {
1153+
TTestBasicRuntime runtime;
1154+
TTestEnv env(runtime, TTestEnvOptions().EnableTablePgTypes(true));
1155+
ui64 txId = 100;
1156+
1157+
TestCreateTable(runtime, ++txId, "/MyRoot", R"(
1158+
Name: "Table"
1159+
Columns { Name: "key" Type: "Uint32" }
1160+
Columns { Name: "value" Type: "Uuid" }
1161+
KeyColumnNames: ["key"]
1162+
)");
1163+
env.TestWaitNotification(runtime, txId);
1164+
1165+
{
1166+
TString tablePath = "/MyRoot/Table";
1167+
int partitionIdx = 0;
1168+
1169+
auto tableDesc = DescribePath(runtime, tablePath, true, true);
1170+
const auto& tablePartitions = tableDesc.GetPathDescription().GetTablePartitions();
1171+
UNIT_ASSERT(partitionIdx < tablePartitions.size());
1172+
const ui64 datashardTabletId = tablePartitions[partitionIdx].GetDatashardId();
1173+
1174+
NKikimrMiniKQL::TResult result;
1175+
TString error;
1176+
NKikimrProto::EReplyStatus status = LocalMiniKQL(runtime, datashardTabletId, Sprintf(R"(
1177+
(
1178+
(let key '( '('key (Uint32 '%d) ) ) )
1179+
(let row '( '('value (Uuid '"%s") ) ) )
1180+
(return (AsList (UpdateRow '__user__%s key row) ))
1181+
)
1182+
)", 1, "0123456789012345", "Table"), result, error);
1183+
1184+
UNIT_ASSERT_VALUES_EQUAL_C(status, NKikimrProto::EReplyStatus::OK, error);
1185+
UNIT_ASSERT_VALUES_EQUAL(error, "");
1186+
}
1187+
1188+
TPortManager portManager;
1189+
const ui16 port = portManager.GetPort();
1190+
1191+
TS3Mock s3Mock({}, TS3Mock::TSettings(port));
1192+
UNIT_ASSERT(s3Mock.Start());
1193+
1194+
TestExport(runtime, ++txId, "/MyRoot", Sprintf(R"(
1195+
ExportToS3Settings {
1196+
endpoint: "localhost:%d"
1197+
scheme: HTTP
1198+
items {
1199+
source_path: "/MyRoot/Table"
1200+
destination_prefix: "Backup1"
1201+
}
1202+
}
1203+
)", port));
1204+
env.TestWaitNotification(runtime, txId);
1205+
TestGetExport(runtime, txId, "/MyRoot");
1206+
1207+
TestImport(runtime, ++txId, "/MyRoot", Sprintf(R"(
11391208
ImportFromS3Settings {
11401209
endpoint: "localhost:%d"
11411210
scheme: HTTP

0 commit comments

Comments
 (0)