aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikolay Shumkov <shumkovnd@ydb.tech>2024-09-23 12:49:16 +0300
committerGitHub <noreply@github.com>2024-09-23 12:49:16 +0300
commit7b2c0d2d086042a9ebed7eb6c77048e2a062c17e (patch)
tree52beafcb97d4b21455ce11dfc1b3dbf873bc854b
parenta10501dd46b54d91bc43766bfd8190e35776ac55 (diff)
downloadydb-7b2c0d2d086042a9ebed7eb6c77048e2a062c17e.tar.gz
Support ydb dump for tables with serial types (#9272)
-rw-r--r--ydb/core/grpc_services/rpc_create_table.cpp25
-rw-r--r--ydb/core/grpc_services/rpc_describe_table.cpp12
-rw-r--r--ydb/core/ydb_convert/table_description.cpp12
-rw-r--r--ydb/core/ydb_convert/table_description.h5
-rw-r--r--ydb/library/backup/backup.cpp29
-rw-r--r--ydb/public/api/protos/ydb_table.proto2
-rw-r--r--ydb/public/sdk/cpp/client/ydb_table/impl/table_client.cpp4
-rw-r--r--ydb/public/sdk/cpp/client/ydb_table/table.cpp57
-rw-r--r--ydb/public/sdk/cpp/client/ydb_table/table.h16
-rw-r--r--ydb/services/ydb/backup_ut/ydb_backup_ut.cpp82
10 files changed, 217 insertions, 27 deletions
diff --git a/ydb/core/grpc_services/rpc_create_table.cpp b/ydb/core/grpc_services/rpc_create_table.cpp
index 556004f466d..88fed4de46d 100644
--- a/ydb/core/grpc_services/rpc_create_table.cpp
+++ b/ydb/core/grpc_services/rpc_create_table.cpp
@@ -181,8 +181,28 @@ private:
return;
}
+ StatusIds::StatusCode code = StatusIds::SUCCESS;
+ TString error;
+
+ bool hasSerial = false;
+ for (const auto& column : req->columns()) {
+ switch (column.default_value_case()) {
+ case Ydb::Table::ColumnMeta::kFromSequence: {
+ auto* seqDesc = modifyScheme->MutableCreateIndexedTable()->MutableSequenceDescription()->Add();
+ if (!FillSequenceDescription(*seqDesc, column.from_sequence(), code, error)) {
+ NYql::TIssues issues;
+ issues.AddIssue(NYql::TIssue(error));
+ return Reply(code, issues, ctx);
+ }
+ hasSerial = true;
+ break;
+ }
+ default: break;
+ }
+ }
+
NKikimrSchemeOp::TTableDescription* tableDesc = nullptr;
- if (req->indexesSize()) {
+ if (req->indexesSize() || hasSerial) {
modifyScheme->SetOperationType(NKikimrSchemeOp::EOperationType::ESchemeOpCreateIndexedTable);
tableDesc = modifyScheme->MutableCreateIndexedTable()->MutableTableDescription();
} else {
@@ -192,9 +212,6 @@ private:
tableDesc->SetName(name);
- StatusIds::StatusCode code = StatusIds::SUCCESS;
- TString error;
-
if (!FillColumnDescription(*tableDesc, req->columns(), code, error)) {
NYql::TIssues issues;
issues.AddIssue(NYql::TIssue(error));
diff --git a/ydb/core/grpc_services/rpc_describe_table.cpp b/ydb/core/grpc_services/rpc_describe_table.cpp
index 06e7b5ac375..c608fe57cec 100644
--- a/ydb/core/grpc_services/rpc_describe_table.cpp
+++ b/ydb/core/grpc_services/rpc_describe_table.cpp
@@ -143,6 +143,14 @@ private:
return Reply(Ydb::StatusIds::INTERNAL_ERROR, ctx);
}
+ StatusIds::StatusCode code = StatusIds::SUCCESS;
+ TString error;
+ if (!FillSequenceDescription(describeTableResult, tableDescription, code, error)) {
+ LOG_ERROR(ctx, NKikimrServices::GRPC_SERVER, "Unable to fill sequence description: %s", error.c_str());
+ Request_->RaiseIssue(NYql::TIssue(error));
+ return Reply(Ydb::StatusIds::INTERNAL_ERROR, ctx);
+ }
+
describeTableResult.mutable_primary_key()->CopyFrom(tableDescription.GetKeyColumnNames());
try {
@@ -213,6 +221,10 @@ private:
record->MutableOptions()->SetReturnPartitionStats(true);
}
+ if (req->include_set_val()) {
+ record->MutableOptions()->SetReturnSetVal(true);
+ }
+
record->MutableOptions()->SetShowPrivateTable(ShowPrivatePath(path));
ctx.Send(MakeTxProxyID(), navigateRequest.release());
diff --git a/ydb/core/ydb_convert/table_description.cpp b/ydb/core/ydb_convert/table_description.cpp
index aa1b7bb41d2..cc43b464398 100644
--- a/ydb/core/ydb_convert/table_description.cpp
+++ b/ydb/core/ydb_convert/table_description.cpp
@@ -1425,7 +1425,6 @@ bool FillTableDescription(NKikimrSchemeOp::TModifyScheme& out,
const Ydb::Table::CreateTableRequest& in, const TTableProfiles& profiles,
Ydb::StatusIds::StatusCode& status, TString& error, bool indexedTable)
{
-
NKikimrSchemeOp::TTableDescription* tableDesc = nullptr;
if (indexedTable) {
tableDesc = out.MutableCreateIndexedTable()->MutableTableDescription();
@@ -1467,7 +1466,8 @@ bool FillTableDescription(NKikimrSchemeOp::TModifyScheme& out,
return true;
}
-bool FillSequenceDescription(Ydb::Table::CreateTableRequest& out, const NKikimrSchemeOp::TTableDescription& in, Ydb::StatusIds::StatusCode& status, TString& error) {
+template <typename TYdbProto>
+bool FillSequenceDescriptionImpl(TYdbProto& out, const NKikimrSchemeOp::TTableDescription& in, Ydb::StatusIds::StatusCode& status, TString& error) {
THashMap<TString, NKikimrSchemeOp::TSequenceDescription> sequences;
for (const auto& sequenceDescription : in.GetSequences()) {
@@ -1568,6 +1568,14 @@ bool FillSequenceDescription(Ydb::Table::CreateTableRequest& out, const NKikimrS
return true;
}
+bool FillSequenceDescription(Ydb::Table::DescribeTableResult& out, const NKikimrSchemeOp::TTableDescription& in, Ydb::StatusIds::StatusCode& status, TString& error) {
+ return FillSequenceDescriptionImpl(out, in, status, error);
+}
+
+bool FillSequenceDescription(Ydb::Table::CreateTableRequest& out, const NKikimrSchemeOp::TTableDescription& in, Ydb::StatusIds::StatusCode& status, TString& error) {
+ return FillSequenceDescriptionImpl(out, in, status, error);
+}
+
bool FillSequenceDescription(NKikimrSchemeOp::TSequenceDescription& out, const Ydb::Table::SequenceDescription& in, Ydb::StatusIds::StatusCode& status, TString& error) {
out.SetName(in.name());
if (in.has_min_value()) {
diff --git a/ydb/core/ydb_convert/table_description.h b/ydb/core/ydb_convert/table_description.h
index 99e9d04fd97..aada5d1f767 100644
--- a/ydb/core/ydb_convert/table_description.h
+++ b/ydb/core/ydb_convert/table_description.h
@@ -133,8 +133,9 @@ bool FillTableDescription(NKikimrSchemeOp::TModifyScheme& out,
// out
-bool FillSequenceDescription(Ydb::Table::CreateTableRequest& out, const NKikimrSchemeOp::TTableDescription& in,
- Ydb::StatusIds::StatusCode& status, TString& error);
+bool FillSequenceDescription(Ydb::Table::DescribeTableResult& out, const NKikimrSchemeOp::TTableDescription& in, Ydb::StatusIds::StatusCode& status, TString& error);
+
+bool FillSequenceDescription(Ydb::Table::CreateTableRequest& out, const NKikimrSchemeOp::TTableDescription& in, Ydb::StatusIds::StatusCode& status, TString& error);
// in
bool FillSequenceDescription(
diff --git a/ydb/library/backup/backup.cpp b/ydb/library/backup/backup.cpp
index 5dae04564bd..d869449c80d 100644
--- a/ydb/library/backup/backup.cpp
+++ b/ydb/library/backup/backup.cpp
@@ -374,7 +374,7 @@ NTable::TTableDescription DescribeTable(TDriver driver, const TString& fullTable
NTable::TTableClient client(driver);
TStatus status = client.RetryOperationSync([fullTablePath, &desc](NTable::TSession session) {
- auto settings = NTable::TDescribeTableSettings().WithKeyShardBoundary(true);
+ auto settings = NTable::TDescribeTableSettings().WithKeyShardBoundary(true).WithSetVal(true);
auto result = session.DescribeTable(fullTablePath, settings).GetValueSync();
VerifyStatus(result);
@@ -514,6 +514,7 @@ void BackupTable(TDriver driver, const TString& dbPrefix, const TString& backupP
<< " backupPrefix: " << backupPrefix << " path: " << path);
auto desc = DescribeTable(driver, JoinDatabasePath(schemaOnly ? dbPrefix : backupPrefix, path));
+
auto proto = ProtoFromTableDescription(desc, preservePoolKinds);
TString schemaStr;
@@ -742,19 +743,26 @@ void BackupFolder(TDriver driver, const TString& database, const TString& relDbP
// Restore
////////////////////////////////////////////////////////////////////////////////
-TString ProcessColumnType(const TString& name, TTypeParser parser, NTable::TTableBuilder *builder) {
+TString ProcessColumnType(const TString& name, TTypeParser parser, NTable::TTableBuilder *builder, std::optional<NTable::TSequenceDescription> sequenceDescription) {
TStringStream ss;
ss << "name: " << name << "; ";
if (parser.GetKind() == TTypeParser::ETypeKind::Optional) {
ss << " optional; ";
parser.OpenOptional();
}
+ if (sequenceDescription.has_value()) {
+ ss << "serial; ";
+ }
ss << "kind: " << parser.GetKind() << "; ";
switch (parser.GetKind()) {
case TTypeParser::ETypeKind::Primitive:
ss << " type_id: " << parser.GetPrimitive() << "; ";
if (builder) {
- builder->AddNullableColumn(name, parser.GetPrimitive());
+ if (sequenceDescription.has_value()) {
+ builder->AddSerialColumn(name, parser.GetPrimitive(), std::move(*sequenceDescription));
+ } else {
+ builder->AddNullableColumn(name, parser.GetPrimitive());
+ }
}
break;
case TTypeParser::ETypeKind::Decimal:
@@ -775,8 +783,19 @@ TString ProcessColumnType(const TString& name, TTypeParser parser, NTable::TTabl
NTable::TTableDescription TableDescriptionFromProto(const Ydb::Table::CreateTableRequest& proto) {
NTable::TTableBuilder builder;
+ std::optional<NTable::TSequenceDescription> sequenceDescription;
for (const auto &col : proto.Getcolumns()) {
- LOG_DEBUG("AddNullableColumn: " << ProcessColumnType(col.Getname(), TType(col.Gettype()), &builder));
+ if (col.from_sequence().name() == "_serial_column_" + col.name()) {
+ NTable::TSequenceDescription currentSequenceDescription;
+ if (col.from_sequence().has_set_val()) {
+ NTable::TSequenceDescription::TSetVal setVal;
+ setVal.NextUsed = col.from_sequence().set_val().next_used();
+ setVal.NextValue = col.from_sequence().set_val().next_value();
+ currentSequenceDescription.SetVal = std::move(setVal);
+ }
+ sequenceDescription = std::move(currentSequenceDescription);
+ }
+ LOG_DEBUG("AddColumn: " << ProcessColumnType(col.Getname(), TType(col.Gettype()), &builder, std::move(sequenceDescription)));
}
for (const auto &primary : proto.Getprimary_key()) {
@@ -805,7 +824,7 @@ TString SerializeColumnsToString(const TVector<TColumn>& columns, TVector<TStrin
if (BinarySearch(primary.cbegin(), primary.cend(), col.Name)) {
ss << "primary; ";
}
- ss << ProcessColumnType(col.Name, col.Type, nullptr) << Endl;
+ ss << ProcessColumnType(col.Name, col.Type, nullptr, std::nullopt) << Endl;
}
// Cerr << "Parse column to : " << ss.Str() << Endl;
return ss.Str();
diff --git a/ydb/public/api/protos/ydb_table.proto b/ydb/public/api/protos/ydb_table.proto
index 94c0c816601..736332ddaf4 100644
--- a/ydb/public/api/protos/ydb_table.proto
+++ b/ydb/public/api/protos/ydb_table.proto
@@ -779,6 +779,8 @@ message DescribeTableRequest {
bool include_table_stats = 6;
// Includes partition statistics (required include_table_statistics)
bool include_partition_stats = 7;
+ // Includes set_val settings for sequences
+ bool include_set_val = 8;
}
message DescribeTableResponse {
diff --git a/ydb/public/sdk/cpp/client/ydb_table/impl/table_client.cpp b/ydb/public/sdk/cpp/client/ydb_table/impl/table_client.cpp
index eb6848f56e8..23006f7ff9f 100644
--- a/ydb/public/sdk/cpp/client/ydb_table/impl/table_client.cpp
+++ b/ydb/public/sdk/cpp/client/ydb_table/impl/table_client.cpp
@@ -525,6 +525,10 @@ TAsyncDescribeTableResult TTableClient::TImpl::DescribeTable(const TString& sess
request.set_include_partition_stats(true);
}
+ if (settings.WithSetVal_) {
+ request.set_include_set_val(true);
+ }
+
auto promise = NewPromise<TDescribeTableResult>();
auto extractor = [promise, settings]
diff --git a/ydb/public/sdk/cpp/client/ydb_table/table.cpp b/ydb/public/sdk/cpp/client/ydb_table/table.cpp
index ef0f593037e..6764312c5dc 100644
--- a/ydb/public/sdk/cpp/client/ydb_table/table.cpp
+++ b/ydb/public/sdk/cpp/client/ydb_table/table.cpp
@@ -291,7 +291,24 @@ class TTableDescription::TImpl {
if (col.has_not_null()) {
not_null = col.not_null();
}
- Columns_.emplace_back(col.name(), col.type(), col.family(), not_null);
+ std::optional<TSequenceDescription> sequenceDescription;
+ switch (col.default_value_case()) {
+ case Ydb::Table::ColumnMeta::kFromSequence: {
+ if (col.from_sequence().name() == "_serial_column_" + col.name()) {
+ TSequenceDescription currentSequenceDescription;
+ if (col.from_sequence().has_set_val()) {
+ TSequenceDescription::TSetVal setVal;
+ setVal.NextUsed = col.from_sequence().set_val().next_used();
+ setVal.NextValue = col.from_sequence().set_val().next_value();
+ currentSequenceDescription.SetVal = std::move(setVal);
+ }
+ sequenceDescription = std::move(currentSequenceDescription);
+ }
+ break;
+ }
+ default: break;
+ }
+ Columns_.emplace_back(col.name(), col.type(), col.family(), not_null, std::move(sequenceDescription));
}
// indexes
@@ -453,8 +470,8 @@ public:
return Proto_;
}
- void AddColumn(const TString& name, const Ydb::Type& type, const TString& family, std::optional<bool> notNull) {
- Columns_.emplace_back(name, type, family, notNull);
+ void AddColumn(const TString& name, const Ydb::Type& type, const TString& family, std::optional<bool> notNull, std::optional<TSequenceDescription> sequenceDescription) {
+ Columns_.emplace_back(name, type, family, notNull, std::move(sequenceDescription));
}
void SetPrimaryKeyColumns(const TVector<TString>& primaryKeyColumns) {
@@ -737,8 +754,8 @@ const TVector<TKeyRange>& TTableDescription::GetKeyRanges() const {
return Impl_->GetKeyRanges();
}
-void TTableDescription::AddColumn(const TString& name, const Ydb::Type& type, const TString& family, std::optional<bool> notNull) {
- Impl_->AddColumn(name, type, family, notNull);
+void TTableDescription::AddColumn(const TString& name, const Ydb::Type& type, const TString& family, std::optional<bool> notNull, std::optional<TSequenceDescription> sequenceDescription) {
+ Impl_->AddColumn(name, type, family, notNull, std::move(sequenceDescription));
}
void TTableDescription::SetPrimaryKeyColumns(const TVector<TString>& primaryKeyColumns) {
@@ -914,6 +931,15 @@ void TTableDescription::SerializeTo(Ydb::Table::CreateTableRequest& request) con
if (column.NotNull.has_value()) {
protoColumn.set_not_null(column.NotNull.value());
}
+ if (column.SequenceDescription.has_value()) {
+ auto* fromSequence = protoColumn.mutable_from_sequence();
+ if (column.SequenceDescription->SetVal.has_value()) {
+ auto* setVal = fromSequence->mutable_set_val();
+ setVal->set_next_value(column.SequenceDescription->SetVal->NextValue);
+ setVal->set_next_used(column.SequenceDescription->SetVal->NextUsed);
+ }
+ fromSequence->set_name("_serial_column_" + column.Name);
+ }
}
for (const auto& pk : Impl_->GetPrimaryKeyColumns()) {
@@ -1121,7 +1147,7 @@ TTableBuilder& TTableBuilder::AddNullableColumn(const TString& name, const EPrim
.EndOptional()
.Build();
- TableDescription_.AddColumn(name, TProtoAccessor::GetProto(columnType), family, false);
+ TableDescription_.AddColumn(name, TProtoAccessor::GetProto(columnType), family, false, std::nullopt);
return *this;
}
@@ -1131,7 +1157,7 @@ TTableBuilder& TTableBuilder::AddNullableColumn(const TString& name, const TDeci
.Decimal(type)
.EndOptional()
.Build();
- TableDescription_.AddColumn(name, TProtoAccessor::GetProto(columnType), family, false);
+ TableDescription_.AddColumn(name, TProtoAccessor::GetProto(columnType), family, false, std::nullopt);
return *this;
}
@@ -1140,7 +1166,7 @@ TTableBuilder& TTableBuilder::AddNullableColumn(const TString& name, const TPgTy
.Pg(type)
.Build();
- TableDescription_.AddColumn(name, TProtoAccessor::GetProto(columnType), family, false);
+ TableDescription_.AddColumn(name, TProtoAccessor::GetProto(columnType), family, false, std::nullopt);
return *this;
}
@@ -1149,7 +1175,7 @@ TTableBuilder& TTableBuilder::AddNonNullableColumn(const TString& name, const EP
.Primitive(type)
.Build();
- TableDescription_.AddColumn(name, TProtoAccessor::GetProto(columnType), family, true);
+ TableDescription_.AddColumn(name, TProtoAccessor::GetProto(columnType), family, true, std::nullopt);
return *this;
}
@@ -1158,7 +1184,7 @@ TTableBuilder& TTableBuilder::AddNonNullableColumn(const TString& name, const TD
.Decimal(type)
.Build();
- TableDescription_.AddColumn(name, TProtoAccessor::GetProto(columnType), family, true);
+ TableDescription_.AddColumn(name, TProtoAccessor::GetProto(columnType), family, true, std::nullopt);
return *this;
}
@@ -1167,7 +1193,16 @@ TTableBuilder& TTableBuilder::AddNonNullableColumn(const TString& name, const TP
.Pg(type)
.Build();
- TableDescription_.AddColumn(name, TProtoAccessor::GetProto(columnType), family, true);
+ TableDescription_.AddColumn(name, TProtoAccessor::GetProto(columnType), family, true, std::nullopt);
+ return *this;
+}
+
+TTableBuilder& TTableBuilder::AddSerialColumn(const TString& name, const EPrimitiveType& type, TSequenceDescription sequenceDescription, const TString& family) {
+ auto columnType = TTypeBuilder()
+ .Primitive(type)
+ .Build();
+
+ TableDescription_.AddColumn(name, TProtoAccessor::GetProto(columnType), family, true, std::move(sequenceDescription));
return *this;
}
diff --git a/ydb/public/sdk/cpp/client/ydb_table/table.h b/ydb/public/sdk/cpp/client/ydb_table/table.h
index d87ccf9be98..fb94b201b5a 100644
--- a/ydb/public/sdk/cpp/client/ydb_table/table.h
+++ b/ydb/public/sdk/cpp/client/ydb_table/table.h
@@ -100,19 +100,29 @@ private:
TMaybe<TKeyBound> To_;
};
+struct TSequenceDescription {
+ struct TSetVal {
+ i64 NextValue;
+ bool NextUsed;
+ };
+ std::optional<TSetVal> SetVal;
+};
+
struct TTableColumn {
TString Name;
TType Type;
TString Family;
std::optional<bool> NotNull;
+ std::optional<TSequenceDescription> SequenceDescription;
TTableColumn() = default;
- TTableColumn(TString name, TType type, TString family = TString(), std::optional<bool> notNull = std::nullopt)
+ TTableColumn(TString name, TType type, TString family = TString(), std::optional<bool> notNull = std::nullopt, std::optional<TSequenceDescription> sequenceDescription = std::nullopt)
: Name(std::move(name))
, Type(std::move(type))
, Family(std::move(family))
, NotNull(std::move(notNull))
+ , SequenceDescription(std::move(sequenceDescription))
{ }
// Conversion from TColumn for API compatibility
@@ -636,7 +646,7 @@ private:
TTableDescription();
explicit TTableDescription(const Ydb::Table::CreateTableRequest& request);
- void AddColumn(const TString& name, const Ydb::Type& type, const TString& family, std::optional<bool> notNull);
+ void AddColumn(const TString& name, const Ydb::Type& type, const TString& family, std::optional<bool> notNull, std::optional<TSequenceDescription> sequenceDescription);
void SetPrimaryKeyColumns(const TVector<TString>& primaryKeyColumns);
// common
@@ -854,6 +864,7 @@ public:
TTableBuilder& AddNonNullableColumn(const TString& name, const TPgType& type, const TString& family = TString());
TTableBuilder& SetPrimaryKeyColumns(const TVector<TString>& primaryKeyColumns);
TTableBuilder& SetPrimaryKeyColumn(const TString& primaryKeyColumn);
+ TTableBuilder& AddSerialColumn(const TString& name, const EPrimitiveType& type, TSequenceDescription sequenceDescription, const TString& family = TString());
// common
TTableBuilder& AddSecondaryIndex(const TIndexDescription& indexDescription);
@@ -1629,6 +1640,7 @@ struct TDescribeTableSettings : public TOperationRequestSettings<TDescribeTableS
FLUENT_SETTING_DEFAULT(bool, WithKeyShardBoundary, false);
FLUENT_SETTING_DEFAULT(bool, WithTableStatistics, false);
FLUENT_SETTING_DEFAULT(bool, WithPartitionStatistics, false);
+ FLUENT_SETTING_DEFAULT(bool, WithSetVal, false);
};
struct TExplainDataQuerySettings : public TOperationRequestSettings<TExplainDataQuerySettings> {
diff --git a/ydb/services/ydb/backup_ut/ydb_backup_ut.cpp b/ydb/services/ydb/backup_ut/ydb_backup_ut.cpp
index e2318a1dfff..5b5723fb7af 100644
--- a/ydb/services/ydb/backup_ut/ydb_backup_ut.cpp
+++ b/ydb/services/ydb/backup_ut/ydb_backup_ut.cpp
@@ -96,6 +96,7 @@ auto CreateMinPartitionsChecker(ui32 expectedMinPartitions, const TString& debug
expectedMinPartitions,
debugHint
);
+ return true;
};
}
@@ -110,10 +111,25 @@ auto CreateHasIndexChecker(const TString& indexName) {
};
}
+auto CreateHasSerialChecker(i64 nextValue, bool nextUsed) {
+ return [=](const TTableDescription& tableDescription) {
+ for (const auto& column : tableDescription.GetTableColumns()) {
+ if (column.Name == "Key") {
+ UNIT_ASSERT(column.SequenceDescription.has_value());
+ UNIT_ASSERT(column.SequenceDescription->SetVal.has_value());
+ UNIT_ASSERT_VALUES_EQUAL(column.SequenceDescription->SetVal->NextValue, nextValue);
+ UNIT_ASSERT_VALUES_EQUAL(column.SequenceDescription->SetVal->NextUsed, nextUsed);
+ return true;
+ }
+ }
+ return false;
+ };
+}
+
void CheckTableDescription(TSession& session, const TString& path, auto&& checker,
const TDescribeTableSettings& settings = {}
) {
- checker(GetTableDescription(session, path, settings));
+ UNIT_ASSERT(checker(GetTableDescription(session, path, settings)));
}
void CheckBuildIndexOperationsCleared(TDriver& driver) {
@@ -330,6 +346,41 @@ void TestIndexTableSplitBoundariesArePreserved(
UNIT_ASSERT_EQUAL(restoredKeyRanges, originalKeyRanges);
}
+void TestRestoreTableWithSerial(
+ const char* table, TSession& session, TBackupFunction&& backup, TRestoreFunction&& restore
+) {
+ ExecuteDataDefinitionQuery(session, Sprintf(R"(
+ CREATE TABLE `%s` (
+ Key Serial,
+ Value Uint32,
+ PRIMARY KEY (Key)
+ );
+ )",
+ table
+ ));
+ ExecuteDataModificationQuery(session, Sprintf(R"(
+ UPSERT INTO `%s` (
+ Value
+ )
+ VALUES (1), (2), (3), (4), (5), (6), (7);
+ )",
+ table
+ ));
+ const auto originalContent = GetTableContent(session, table);
+
+ backup(table);
+
+ ExecuteDataDefinitionQuery(session, Sprintf(R"(
+ DROP TABLE `%s`;
+ )", table
+ ));
+
+ restore(table);
+
+ CheckTableDescription(session, table, CreateHasSerialChecker(8, false), TDescribeTableSettings().WithSetVal(true));
+ CompareResults(GetTableContent(session, table), originalContent);
+}
+
}
Y_UNIT_TEST_SUITE(BackupRestore) {
@@ -473,6 +524,23 @@ Y_UNIT_TEST_SUITE(BackupRestore) {
CheckTableDescription(session, table, CreateHasIndexChecker(index));
CheckBuildIndexOperationsCleared(driver);
}
+
+ Y_UNIT_TEST(BasicRestoreTableWithSerial) {
+ TKikimrWithGrpcAndRootSchema server;
+ auto driver = TDriver(TDriverConfig().SetEndpoint(Sprintf("localhost:%d", server.GetPort())));
+ TTableClient tableClient(driver);
+ auto session = tableClient.GetSession().ExtractValueSync().GetSession();
+ TTempDir tempDir;
+ const auto& pathToBackup = tempDir.Path();
+ constexpr const char* table = "/Root/table";
+
+ TestRestoreTableWithSerial(
+ table,
+ session,
+ CreateBackupLambda(driver, pathToBackup),
+ CreateRestoreLambda(driver, pathToBackup)
+ );
+ }
}
Y_UNIT_TEST_SUITE(BackupRestoreS3) {
@@ -679,4 +747,16 @@ Y_UNIT_TEST_SUITE(BackupRestoreS3) {
);
}
+ Y_UNIT_TEST(RestoreTableWithSerial) {
+ TS3TestEnv testEnv;
+ constexpr const char* table = "/Root/table";
+
+ TestRestoreTableWithSerial(
+ table,
+ testEnv.GetSession(),
+ CreateBackupLambda(testEnv.GetDriver(), testEnv.GetS3Port()),
+ CreateRestoreLambda(testEnv.GetDriver(), testEnv.GetS3Port())
+ );
+ }
+
}