From 26c78916ea9c8837a5046c87bd701926cdf2be87 Mon Sep 17 00:00:00 2001 From: Nikolay Shumkov <153636981+shnikd@users.noreply.github.com> Date: Thu, 7 Mar 2024 17:42:35 +0300 Subject: [PATCH] Copy table with sequences and backup without NextVal (#2285) --- ydb/core/tx/datashard/export_common.cpp | 1 + ...meshard__operation_backup_restore_common.h | 2 +- ...hard__operation_consistent_copy_tables.cpp | 40 +++++++++- .../schemeshard__operation_copy_table.cpp | 62 +++++++++++++-- .../schemeshard/schemeshard__operation_part.h | 3 +- .../schemeshard_import__create.cpp | 5 +- .../schemeshard_import_flow_proposals.cpp | 42 +++++++++- ydb/core/tx/schemeshard/schemeshard_path.cpp | 17 ++++ ydb/core/tx/schemeshard/schemeshard_path.h | 1 + .../tx/schemeshard/ut_restore/ut_restore.cpp | 78 +++++++++++++++++++ .../schemeshard/ut_sequence/ut_sequence.cpp | 29 +++++++ ydb/core/ydb_convert/table_description.cpp | 70 +++++++++++++++-- ydb/core/ydb_convert/table_description.h | 8 +- 13 files changed, 337 insertions(+), 21 deletions(-) diff --git a/ydb/core/tx/datashard/export_common.cpp b/ydb/core/tx/datashard/export_common.cpp index bbedc5c02c86..5675d7de11e4 100644 --- a/ydb/core/tx/datashard/export_common.cpp +++ b/ydb/core/tx/datashard/export_common.cpp @@ -66,6 +66,7 @@ TMaybe GenYdbScheme( FillPartitioningSettings(scheme, tableDesc); FillKeyBloomFilter(scheme, tableDesc); FillReadReplicasSettings(scheme, tableDesc); + FillSequenceDescription(scheme, tableDesc); return scheme; } diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_backup_restore_common.h b/ydb/core/tx/schemeshard/schemeshard__operation_backup_restore_common.h index eb4ef7a61dfc..42667ec26505 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_backup_restore_common.h +++ b/ydb/core/tx/schemeshard/schemeshard__operation_backup_restore_common.h @@ -619,7 +619,7 @@ class TBackupRestoreOperationBase: public TSubOperation { .NotAsyncReplicaTable() .NotUnderOperation() .IsCommonSensePath() //forbid alter impl index tables - .NotChildren(); //forbid backup table with indexes + .CanBackupTable(); //forbid backup table with indexes if (!checks) { result->SetError(checks.GetStatus(), checks.GetError()); diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_consistent_copy_tables.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_consistent_copy_tables.cpp index bb715ab8b955..88034eec52fb 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_consistent_copy_tables.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_consistent_copy_tables.cpp @@ -115,13 +115,33 @@ TVector CreateConsistentCopyTables(TOperationId nextId, con TPath dstPath = TPath::Resolve(dstStr, context.SS); TPath dstParentPath = dstPath.Parent(); + THashSet sequences; + for (const auto& child: srcPath.Base()->GetChildren()) { + auto name = child.first; + auto pathId = child.second; + + TPath childPath = srcPath.Child(name); + if (!childPath.IsSequence() || childPath.IsDeleted()) { + continue; + } + + Y_ABORT_UNLESS(childPath.Base()->PathId == pathId); + + TSequenceInfo::TPtr sequenceInfo = context.SS->Sequences.at(pathId); + const auto& sequenceDesc = sequenceInfo->Description; + const auto& sequenceName = sequenceDesc.GetName(); + + sequences.emplace(sequenceName); + } + result.push_back(CreateCopyTable(NextPartId(nextId, result), - CopyTableTask(srcPath, dstPath, descr.GetOmitFollowers(), descr.GetIsBackup()))); + CopyTableTask(srcPath, dstPath, descr.GetOmitFollowers(), descr.GetIsBackup()), sequences)); if (descr.GetOmitIndexes()) { continue; } + TVector sequenceDescriptions; for (const auto& child: srcPath.Base()->GetChildren()) { const auto& name = child.first; const auto& pathId = child.second; @@ -133,6 +153,13 @@ TVector CreateConsistentCopyTables(TOperationId nextId, con continue; } + if (srcIndexPath.IsSequence()) { + TSequenceInfo::TPtr sequenceInfo = context.SS->Sequences.at(pathId); + const auto& sequenceDesc = sequenceInfo->Description; + sequenceDescriptions.push_back(sequenceDesc); + continue; + } + if (!srcIndexPath.IsTableIndex()) { continue; } @@ -151,6 +178,17 @@ TVector CreateConsistentCopyTables(TOperationId nextId, con result.push_back(CreateCopyTable(NextPartId(nextId, result), CopyTableTask(srcImplTable, dstImplTable, descr.GetOmitFollowers(), descr.GetIsBackup()))); } + + for (auto&& sequenceDescription : sequenceDescriptions) { + auto scheme = TransactionTemplate( + dstPath.PathString(), + NKikimrSchemeOp::EOperationType::ESchemeOpCreateSequence); + scheme.SetFailOnExist(true); + + *scheme.MutableSequence() = std::move(sequenceDescription); + + result.push_back(CreateNewSequence(NextPartId(nextId, result), scheme)); + } } return result; diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp index d67b2bf91a00..25bc09da6648 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_copy_table.cpp @@ -226,6 +226,9 @@ class TPropose: public TSubOperationState { }; class TCopyTable: public TSubOperation { + + THashSet LocalSequences; + static TTxState::ETxState NextState() { return TTxState::CreateParts; } @@ -267,6 +270,12 @@ class TCopyTable: public TSubOperation { public: using TSubOperation::TSubOperation; + explicit TCopyTable(const TOperationId& id, const TTxTransaction& tx, const THashSet& localSequences) + : TSubOperation(id, tx) + , LocalSequences(localSequences) + { + } + bool IsShadowDataAllowed() const { return AppData()->AllowShadowDataInSchemeShardForTests; } @@ -459,7 +468,8 @@ class TCopyTable: public TSubOperation { const NScheme::TTypeRegistry* typeRegistry = AppData()->TypeRegistry; const TSchemeLimits& limits = domainInfo->GetSchemeLimits(); - TTableInfo::TAlterDataPtr alterData = TTableInfo::CreateAlterData(nullptr, schema, *typeRegistry, limits, *domainInfo, context.SS->EnableTablePgTypes, errStr); + TTableInfo::TAlterDataPtr alterData = TTableInfo::CreateAlterData(nullptr, schema, *typeRegistry, + limits, *domainInfo, context.SS->EnableTablePgTypes, errStr, LocalSequences); if (!alterData.Get()) { result->SetError(NKikimrScheme::StatusSchemeError, errStr); return result; @@ -626,8 +636,9 @@ class TCopyTable: public TSubOperation { namespace NKikimr::NSchemeShard { -ISubOperation::TPtr CreateCopyTable(TOperationId id, const TTxTransaction& tx) { - return MakeSubOperation(id, tx); +ISubOperation::TPtr CreateCopyTable(TOperationId id, const TTxTransaction& tx, const THashSet& localSequences) +{ + return MakeSubOperation(id, tx, localSequences); } ISubOperation::TPtr CreateCopyTable(TOperationId id, TTxState::ETxState state) { @@ -659,6 +670,25 @@ TVector CreateCopyTable(TOperationId nextId, const TTxTrans } } + THashSet sequences; + for (auto& child: srcPath.Base()->GetChildren()) { + auto name = child.first; + auto pathId = child.second; + + TPath childPath = srcPath.Child(name); + if (!childPath.IsSequence() || childPath.IsDeleted()) { + continue; + } + + Y_ABORT_UNLESS(childPath.Base()->PathId == pathId); + + TSequenceInfo::TPtr sequenceInfo = context.SS->Sequences.at(pathId); + const auto& sequenceDesc = sequenceInfo->Description; + const auto& sequenceName = sequenceDesc.GetName(); + + sequences.emplace(sequenceName); + } + TPath workDir = TPath::Resolve(tx.GetWorkingDir(), context.SS); TPath dstPath = workDir.Child(copying.GetName()); @@ -674,15 +704,27 @@ TVector CreateCopyTable(TOperationId nextId, const TTxTrans operation->SetIsBackup(copying.GetIsBackup()); operation->MutablePartitionConfig()->CopyFrom(copying.GetPartitionConfig()); - result.push_back(CreateCopyTable(NextPartId(nextId, result), schema)); + result.push_back(CreateCopyTable(NextPartId(nextId, result), schema, sequences)); } + TVector sequenceDescriptions; for (auto& child: srcPath.Base()->GetChildren()) { auto name = child.first; auto pathId = child.second; TPath childPath = srcPath.Child(name); - if (!childPath.IsTableIndex() || childPath.IsDeleted()) { + if (childPath.IsDeleted()) { + continue; + } + + if (childPath.IsSequence()) { + TSequenceInfo::TPtr sequenceInfo = context.SS->Sequences.at(pathId); + const auto& sequenceDesc = sequenceInfo->Description; + sequenceDescriptions.push_back(sequenceDesc); + continue; + } + + if (!childPath.IsTableIndex()) { continue; } @@ -727,6 +769,16 @@ TVector CreateCopyTable(TOperationId nextId, const TTxTrans } } + for (auto&& sequenceDescription : sequenceDescriptions) { + auto scheme = TransactionTemplate( + tx.GetWorkingDir() + "/" + copying.GetName(), + NKikimrSchemeOp::EOperationType::ESchemeOpCreateSequence); + scheme.SetFailOnExist(tx.GetFailOnExist()); + + *scheme.MutableSequence() = std::move(sequenceDescription); + + result.push_back(CreateNewSequence(NextPartId(nextId, result), scheme)); + } return result; } diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_part.h b/ydb/core/tx/schemeshard/schemeshard__operation_part.h index 0a9cf8b6b8b3..76baccd4dabf 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_part.h +++ b/ydb/core/tx/schemeshard/schemeshard__operation_part.h @@ -340,7 +340,8 @@ ISubOperation::TPtr CreateForceDropUnsafe(TOperationId id, TTxState::ETxState st ISubOperation::TPtr CreateNewTable(TOperationId id, const TTxTransaction& tx, const THashSet& localSequences = { }); ISubOperation::TPtr CreateNewTable(TOperationId id, TTxState::ETxState state); -ISubOperation::TPtr CreateCopyTable(TOperationId id, const TTxTransaction& tx); +ISubOperation::TPtr CreateCopyTable(TOperationId id, const TTxTransaction& tx, + const THashSet& localSequences = { }); ISubOperation::TPtr CreateCopyTable(TOperationId id, TTxState::ETxState state); TVector CreateCopyTable(TOperationId nextId, const TTxTransaction& tx, TOperationContext& context); diff --git a/ydb/core/tx/schemeshard/schemeshard_import__create.cpp b/ydb/core/tx/schemeshard/schemeshard_import__create.cpp index adcae1ce16bb..1f4336fac255 100644 --- a/ydb/core/tx/schemeshard/schemeshard_import__create.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_import__create.cpp @@ -850,7 +850,10 @@ struct TSchemeShard::TImport::TTxProgress: public TSchemeShard::TXxport::TTxBase } if (item.State == EState::CreateTable) { - item.DstPathId = Self->MakeLocalId(TLocalPathId(record.GetPathId())); + auto createPath = TPath::Resolve(item.DstPathName, Self); + Y_ABORT_UNLESS(createPath); + + item.DstPathId = createPath.Base()->PathId; Self->PersistImportItemDstPathId(db, importInfo, itemIdx); } diff --git a/ydb/core/tx/schemeshard/schemeshard_import_flow_proposals.cpp b/ydb/core/tx/schemeshard/schemeshard_import_flow_proposals.cpp index 7d81246bd758..9b4f9ad1d573 100644 --- a/ydb/core/tx/schemeshard/schemeshard_import_flow_proposals.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_import_flow_proposals.cpp @@ -25,7 +25,7 @@ THolder CreateTablePropose( } auto& modifyScheme = *record.AddTransaction(); - modifyScheme.SetOperationType(NKikimrSchemeOp::ESchemeOpCreateTable); + modifyScheme.SetOperationType(NKikimrSchemeOp::ESchemeOpCreateIndexedTable); modifyScheme.SetInternal(true); const TPath domainPath = TPath::Init(importInfo->DomainPathId, ss); @@ -37,15 +37,51 @@ THolder CreateTablePropose( modifyScheme.SetWorkingDir(wdAndPath.first); - auto& tableDesc = *modifyScheme.MutableCreateTable(); + auto* indexedTable = modifyScheme.MutableCreateIndexedTable(); + auto& tableDesc = *(indexedTable->MutableTableDescription()); tableDesc.SetName(wdAndPath.second); Y_ABORT_UNLESS(ss->TableProfilesLoaded); Ydb::StatusIds::StatusCode status; - if (!FillTableDescription(modifyScheme, item.Scheme, ss->TableProfiles, status, error)) { + if (!FillTableDescription(modifyScheme, item.Scheme, ss->TableProfiles, status, error, true)) { return nullptr; } + for(const auto& column: item.Scheme.columns()) { + switch (column.default_value_case()) { + case Ydb::Table::ColumnMeta::kFromSequence: { + const auto& fromSequence = column.from_sequence(); + + auto seqDesc = indexedTable->MutableSequenceDescription()->Add(); + seqDesc->SetName(fromSequence.name()); + if (fromSequence.has_min_value()) { + seqDesc->SetMinValue(fromSequence.min_value()); + } + if (fromSequence.has_max_value()) { + seqDesc->SetMaxValue(fromSequence.max_value()); + } + if (fromSequence.has_start_value()) { + seqDesc->SetStartValue(fromSequence.start_value()); + } + if (fromSequence.has_cache()) { + seqDesc->SetCache(fromSequence.cache()); + } + if (fromSequence.has_increment()) { + seqDesc->SetIncrement(fromSequence.increment()); + } + if (fromSequence.has_cycle()) { + seqDesc->SetCycle(fromSequence.cycle()); + } + + break; + } + case Ydb::Table::ColumnMeta::kFromLiteral: { + break; + } + default: break; + } + } + return propose; } diff --git a/ydb/core/tx/schemeshard/schemeshard_path.cpp b/ydb/core/tx/schemeshard/schemeshard_path.cpp index cf5674c4ad1e..65c69d043ff4 100644 --- a/ydb/core/tx/schemeshard/schemeshard_path.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_path.cpp @@ -923,6 +923,23 @@ const TPath::TChecker& TPath::TChecker::NotChildren(EStatus status) const { << ", children: " << childrenCount); } +const TPath::TChecker& TPath::TChecker::CanBackupTable(EStatus status) const { + if (Failed) { + return *this; + } + + for (const auto& child: Path.Base()->GetChildren()) { + auto name = child.first; + + TPath childPath = Path.Child(name); + if (childPath->IsTableIndex()) { + return Fail(status, TStringBuilder() << "path has indexes, request doesn't accept it"); + } + } + + return *this; +} + const TPath::TChecker& TPath::TChecker::NotDeleted(EStatus status) const { if (Failed) { return *this; diff --git a/ydb/core/tx/schemeshard/schemeshard_path.h b/ydb/core/tx/schemeshard/schemeshard_path.h index 2087a853f06e..cc6e9cffd7b0 100644 --- a/ydb/core/tx/schemeshard/schemeshard_path.h +++ b/ydb/core/tx/schemeshard/schemeshard_path.h @@ -86,6 +86,7 @@ class TPath { const TChecker& ShardsLimit(ui64 delta = 1, EStatus status = EStatus::StatusResourceExhausted) const; const TChecker& PathShardsLimit(ui64 delta = 1, EStatus status = EStatus::StatusResourceExhausted) const; const TChecker& NotChildren(EStatus status = EStatus::StatusInvalidParameter) const; + const TChecker& CanBackupTable(EStatus status = EStatus::StatusInvalidParameter) const; const TChecker& IsValidACL(const TString& acl, EStatus status = EStatus::StatusInvalidParameter) const; const TChecker& PQPartitionsLimit(ui64 delta = 1, EStatus status = EStatus::StatusResourceExhausted) const; const TChecker& PQReservedStorageLimit(ui64 delta = 1, EStatus status = EStatus::StatusResourceExhausted) const; diff --git a/ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp b/ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp index 70607eb29404..605f53b6e530 100644 --- a/ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp +++ b/ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp @@ -373,6 +373,22 @@ Y_UNIT_TEST_SUITE(TRestoreTests) { NKqp::CompareYson(data.YsonStr, content); } + bool CheckDefaultFromSequence(const NKikimrSchemeOp::TTableDescription& desc) { + for (const auto& column: desc.GetColumns()) { + if (column.GetName() == "key") { + switch (column.GetDefaultValueCase()) { + case NKikimrSchemeOp::TColumnDescription::kDefaultFromSequence: { + const auto& fromSequence = column.GetDefaultFromSequence(); + return fromSequence == "myseq"; + } + default: break; + } + break; + } + } + return false; + } + bool CheckDefaultFromLiteral(const NKikimrSchemeOp::TTableDescription& desc) { for (const auto& column: desc.GetColumns()) { if (column.GetName() == "value") { @@ -877,6 +893,68 @@ value { UNIT_ASSERT_C(CheckDefaultFromLiteral(table), "Invalid default value"); } + Y_UNIT_TEST(ShouldRestoreDefaultValuesFromSequence) { + TPortManager portManager; + const ui16 port = portManager.GetPort(); + + TS3Mock s3Mock({}, TS3Mock::TSettings(port)); + UNIT_ASSERT(s3Mock.Start()); + + TTestBasicRuntime runtime; + TTestEnv env(runtime); + ui64 txId = 100; + + runtime.SetLogPriority(NKikimrServices::DATASHARD_BACKUP, NActors::NLog::PRI_TRACE); + runtime.SetLogPriority(NKikimrServices::DATASHARD_RESTORE, NActors::NLog::PRI_TRACE); + runtime.SetLogPriority(NKikimrServices::EXPORT, NActors::NLog::PRI_TRACE); + runtime.SetLogPriority(NKikimrServices::IMPORT, NActors::NLog::PRI_TRACE); + + TestCreateIndexedTable(runtime, ++txId, "/MyRoot", R"( + TableDescription { + Name: "Original" + Columns { Name: "key" Type: "Uint64" DefaultFromSequence: "myseq" } + Columns { Name: "value" Type: "Uint64" } + KeyColumnNames: ["key"] + } + SequenceDescription { + Name: "myseq" + } + )"); + + TestExport(runtime, ++txId, "/MyRoot", Sprintf(R"( + ExportToS3Settings { + endpoint: "localhost:%d" + scheme: HTTP + items { + source_path: "/MyRoot/Original" + destination_prefix: "" + } + } + )", port)); + env.TestWaitNotification(runtime, txId); + TestGetExport(runtime, txId, "/MyRoot"); + + TestImport(runtime, ++txId, "/MyRoot", Sprintf(R"( + ImportFromS3Settings { + endpoint: "localhost:%d" + scheme: HTTP + items { + source_prefix: "" + destination_path: "/MyRoot/Restored" + } + } + )", port)); + env.TestWaitNotification(runtime, txId); + TestGetImport(runtime, txId, "/MyRoot"); + + const auto desc = DescribePath(runtime, "/MyRoot/Restored", true, true); + UNIT_ASSERT_VALUES_EQUAL(desc.GetStatus(), NKikimrScheme::StatusSuccess); + + const auto& table = desc.GetPathDescription().GetTable(); + + UNIT_ASSERT_C(CheckDefaultFromSequence(table), "Invalid default value"); + } + Y_UNIT_TEST(ExportImportPg) { TTestBasicRuntime runtime; TTestEnv env(runtime, TTestEnvOptions().EnableTablePgTypes(true)); diff --git a/ydb/core/tx/schemeshard/ut_sequence/ut_sequence.cpp b/ydb/core/tx/schemeshard/ut_sequence/ut_sequence.cpp index 2056b24ff823..9ecada64c2eb 100644 --- a/ydb/core/tx/schemeshard/ut_sequence/ut_sequence.cpp +++ b/ydb/core/tx/schemeshard/ut_sequence/ut_sequence.cpp @@ -336,4 +336,33 @@ Y_UNIT_TEST_SUITE(TSequence) { TestLs(runtime, "/MyRoot/Table", false, NLs::PathNotExist); } + Y_UNIT_TEST(CopyTableWithSequence) { + TTestBasicRuntime runtime; + TTestEnv env(runtime); + ui64 txId = 100; + + runtime.SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NActors::NLog::PRI_TRACE); + runtime.SetLogPriority(NKikimrServices::SEQUENCESHARD, NActors::NLog::PRI_TRACE); + + TestCreateIndexedTable(runtime, ++txId, "/MyRoot", R"( + TableDescription { + Name: "Table" + Columns { Name: "key" Type: "Uint64" DefaultFromSequence: "myseq" } + Columns { Name: "value" Type: "Utf8" } + KeyColumnNames: ["key"] + } + IndexDescription { + Name: "ValueIndex" + KeyColumnNames: ["value"] + } + SequenceDescription { + Name: "myseq" + } + )"); + env.TestWaitNotification(runtime, txId); + + TestCopyTable(runtime, ++txId, "/MyRoot", "copy", "/MyRoot/Table"); + env.TestWaitNotification(runtime, txId); + } + } // Y_UNIT_TEST_SUITE(TSequence) diff --git a/ydb/core/ydb_convert/table_description.cpp b/ydb/core/ydb_convert/table_description.cpp index e4d9f477e60a..b60ccd52e64a 100644 --- a/ydb/core/ydb_convert/table_description.cpp +++ b/ydb/core/ydb_convert/table_description.cpp @@ -439,6 +439,11 @@ Ydb::Type* AddColumn(Ydb::Table::ColumnMeta *fromLiteral = column.GetDefaultFromLiteral(); break; } + case NKikimrSchemeOp::TColumnDescription::kDefaultFromSequence: { + auto* fromSequence = newColumn->mutable_from_sequence(); + fromSequence->set_name(column.GetDefaultFromSequence()); + break; + } default: break; } @@ -661,6 +666,11 @@ bool FillColumnDescription(NKikimrSchemeOp::TTableDescription& out, *fromLiteral = column.from_literal(); break; } + case Ydb::Table::ColumnMeta::kFromSequence: { + auto fromSequence = cd->MutableDefaultFromSequence(); + *fromSequence = column.from_sequence().name(); + break; + } default: break; } } @@ -1332,21 +1342,27 @@ void FillReadReplicasSettings(Ydb::Table::CreateTableRequest& out, bool FillTableDescription(NKikimrSchemeOp::TModifyScheme& out, const Ydb::Table::CreateTableRequest& in, const TTableProfiles& profiles, - Ydb::StatusIds::StatusCode& status, TString& error) + Ydb::StatusIds::StatusCode& status, TString& error, bool indexedTable) { - auto& tableDesc = *out.MutableCreateTable(); - if (!FillColumnDescription(tableDesc, in.columns(), status, error)) { + NKikimrSchemeOp::TTableDescription* tableDesc = nullptr; + if (indexedTable) { + tableDesc = out.MutableCreateIndexedTable()->MutableTableDescription(); + } else { + tableDesc = out.MutableCreateTable(); + } + + if (!FillColumnDescription(*tableDesc, in.columns(), status, error)) { return false; } - tableDesc.MutableKeyColumnNames()->CopyFrom(in.primary_key()); + tableDesc->MutableKeyColumnNames()->CopyFrom(in.primary_key()); - if (!profiles.ApplyTableProfile(in.profile(), tableDesc, status, error)) { + if (!profiles.ApplyTableProfile(in.profile(), *tableDesc, status, error)) { return false; } - TColumnFamilyManager families(tableDesc.MutablePartitionConfig()); + TColumnFamilyManager families(tableDesc->MutablePartitionConfig()); if (in.has_storage_settings() && !families.ApplyStorageSettings(in.storage_settings(), &status, &error)) { return false; } @@ -1363,11 +1379,51 @@ bool FillTableDescription(NKikimrSchemeOp::TModifyScheme& out, } TList warnings; - if (!FillCreateTableSettingsDesc(tableDesc, in, status, error, warnings, false)) { + if (!FillCreateTableSettingsDesc(*tableDesc, in, status, error, warnings, false)) { return false; } return true; } +void FillSequenceDescription(Ydb::Table::CreateTableRequest& out, const NKikimrSchemeOp::TTableDescription& in) { + THashMap sequences; + + for (const auto& sequenceDescription : in.GetSequences()) { + sequences[sequenceDescription.GetName()] = sequenceDescription; + } + + for (auto& column : *out.mutable_columns()) { + + switch (column.default_value_case()) { + case Ydb::Table::ColumnMeta::kFromSequence: { + auto* fromSequence = column.mutable_from_sequence(); + + const auto& sequenceDescription = sequences.at(fromSequence->name()); + + if (sequenceDescription.HasMinValue()) { + fromSequence->set_min_value(sequenceDescription.GetMinValue()); + } + if (sequenceDescription.HasMaxValue()) { + fromSequence->set_max_value(sequenceDescription.GetMaxValue()); + } + if (sequenceDescription.HasStartValue()) { + fromSequence->set_start_value(sequenceDescription.GetStartValue()); + } + if (sequenceDescription.HasCache()) { + fromSequence->set_cache(sequenceDescription.GetCache()); + } + if (sequenceDescription.HasIncrement()) { + fromSequence->set_increment(sequenceDescription.GetIncrement()); + } + break; + } + case Ydb::Table::ColumnMeta::kFromLiteral: { + break; + } + default: break; + } + } +} + } // namespace NKikimr diff --git a/ydb/core/ydb_convert/table_description.h b/ydb/core/ydb_convert/table_description.h index a81401bee522..28f45b421993 100644 --- a/ydb/core/ydb_convert/table_description.h +++ b/ydb/core/ydb_convert/table_description.h @@ -30,7 +30,7 @@ enum class EAlterOperationKind { struct TPathId; -THashSet GetAlterOperationKinds(const Ydb::Table::AlterTableRequest* req); +THashSet GetAlterOperationKinds(const Ydb::Table::AlterTableRequest* req); bool BuildAlterTableModifyScheme(const Ydb::Table::AlterTableRequest* req, NKikimrSchemeOp::TModifyScheme* modifyScheme, const TTableProfiles& profiles, const TPathId& resolvedPathId, Ydb::StatusIds::StatusCode& status, TString& error); @@ -126,6 +126,10 @@ void FillReadReplicasSettings(Ydb::Table::CreateTableRequest& out, // in bool FillTableDescription(NKikimrSchemeOp::TModifyScheme& out, const Ydb::Table::CreateTableRequest& in, const TTableProfiles& profiles, - Ydb::StatusIds::StatusCode& status, TString& error); + Ydb::StatusIds::StatusCode& status, TString& error, bool indexedTable = false); + +// out +void FillSequenceDescription(Ydb::Table::CreateTableRequest& out, + const NKikimrSchemeOp::TTableDescription& in); } // namespace NKikimr