diff --git a/ydb/core/protos/flat_scheme_op.proto b/ydb/core/protos/flat_scheme_op.proto index 165b66347f7d..7d8065c27278 100644 --- a/ydb/core/protos/flat_scheme_op.proto +++ b/ydb/core/protos/flat_scheme_op.proto @@ -1294,6 +1294,10 @@ message TMoveIndex { } message TSequenceDescription { + message TSetVal { + optional sint64 NextValue = 1; + optional bool NextUsed = 2; + } optional string Name = 1; // mandatory optional NKikimrProto.TPathID PathId = 2; // sequence path id, assigned by schemeshard optional uint64 Version = 3; // incremented every time sequence is altered @@ -1305,6 +1309,7 @@ message TSequenceDescription { optional uint64 Cache = 8; // number of items to cache, defaults to 1 optional sint64 Increment = 9; // increment at each call, defaults to 1 optional bool Cycle = 10; // true when cycle on overflow is allowed + optional TSetVal SetVal = 11; // SetVal(NextValue, NextUsed) is executed atomically when creating } message TSequenceSharding { @@ -1613,6 +1618,7 @@ message TDescribeOptions { optional bool ShowPrivateTable = 7 [default = false]; optional bool ReturnChannelsBinding = 8 [default = false]; optional bool ReturnRangeKey = 9 [default = true]; + optional bool ReturnSetVal = 10 [default = false]; } // Request to read scheme for a specific path diff --git a/ydb/core/protos/tx_sequenceshard.proto b/ydb/core/protos/tx_sequenceshard.proto index 0f13af504618..e092dc447bd7 100644 --- a/ydb/core/protos/tx_sequenceshard.proto +++ b/ydb/core/protos/tx_sequenceshard.proto @@ -18,6 +18,11 @@ message TEvMarkSchemeShardPipe { } message TEvCreateSequence { + message TSetVal { + sint64 NextValue = 1; + bool NextUsed = 2; + } + NKikimrProto.TPathID PathId = 1; uint64 TxId = 2; uint64 TxPartId = 3; @@ -40,6 +45,7 @@ message TEvCreateSequence { bool Cycle = 9; } bool Frozen = 10; // defaults to false + TSetVal SetVal = 11; } message TEvCreateSequenceResult { 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 88034eec52fb..c9b3a1ab0ca4 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_consistent_copy_tables.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_consistent_copy_tables.cpp @@ -137,10 +137,6 @@ TVector CreateConsistentCopyTables(TOperationId nextId, con result.push_back(CreateCopyTable(NextPartId(nextId, result), 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; @@ -160,6 +156,10 @@ TVector CreateConsistentCopyTables(TOperationId nextId, con continue; } + if (descr.GetOmitIndexes()) { + continue; + } + if (!srcIndexPath.IsTableIndex()) { continue; } @@ -185,9 +185,11 @@ TVector CreateConsistentCopyTables(TOperationId nextId, con NKikimrSchemeOp::EOperationType::ESchemeOpCreateSequence); scheme.SetFailOnExist(true); + auto* copySequence = scheme.MutableCopySequence(); + copySequence->SetCopyFrom(srcPath.PathString() + "/" + sequenceDescription.GetName()); *scheme.MutableSequence() = std::move(sequenceDescription); - result.push_back(CreateNewSequence(NextPartId(nextId, result), scheme)); + result.push_back(CreateCopySequence(NextPartId(nextId, result), scheme)); } } diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_copy_sequence.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_copy_sequence.cpp index f1f408817e99..b1232aa0d6a8 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_copy_sequence.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_copy_sequence.cpp @@ -115,7 +115,7 @@ class TConfigureParts : public TSubOperationState { event->Record.SetFrozen(true); LOG_DEBUG_S(context.Ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, - "TCoptSequence TConfigureParts ProgressState" + "TCopySequence TConfigureParts ProgressState" << " sending TEvCreateSequence to tablet " << tabletId << " operationId# " << OperationId << " at tablet " << ssId); @@ -274,6 +274,18 @@ class TProposedCopySequence : public TSubOperationState { << " operationId#" << OperationId; } + void UpdateSequenceDescription(NKikimrSchemeOp::TSequenceDescription& descr) { + descr.SetStartValue(GetSequenceResult.GetStartValue()); + descr.SetMinValue(GetSequenceResult.GetMinValue()); + descr.SetMaxValue(GetSequenceResult.GetMaxValue()); + descr.SetCache(GetSequenceResult.GetCache()); + descr.SetIncrement(GetSequenceResult.GetIncrement()); + descr.SetCycle(GetSequenceResult.GetCycle()); + auto* setValMsg = descr.MutableSetVal(); + setValMsg->SetNextValue(GetSequenceResult.GetNextValue()); + setValMsg->SetNextUsed(GetSequenceResult.GetNextUsed()); + } + public: TProposedCopySequence(TOperationId id) : OperationId(id) @@ -333,7 +345,15 @@ class TProposedCopySequence : public TSubOperationState { return false; } + TPathId pathId = txState->TargetPathId; + NIceDb::TNiceDb db(context.GetDB()); + + auto sequenceInfo = context.SS->Sequences.at(pathId); + UpdateSequenceDescription(sequenceInfo->Description); + + context.SS->PersistSequence(db, pathId, *sequenceInfo); + context.SS->ChangeTxState(db, OperationId, TTxState::Done); context.OnComplete.ActivateTx(OperationId); return true; @@ -387,7 +407,7 @@ class TProposedCopySequence : public TSubOperationState { return false; } - auto getSequenceResult = ev->Get()->Record; + GetSequenceResult = ev->Get()->Record; Y_ABORT_UNLESS(txState->Shards.size() == 1); for (auto shard : txState->Shards) { @@ -397,7 +417,8 @@ class TProposedCopySequence : public TSubOperationState { Y_ABORT_UNLESS(currentTabletId != InvalidTabletId); auto event = MakeHolder( - txState->TargetPathId, getSequenceResult); + txState->TargetPathId, GetSequenceResult); + event->Record.SetTxId(ui64(OperationId.GetTxId())); event->Record.SetTxPartId(OperationId.GetSubTxId()); diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_create_sequence.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_create_sequence.cpp index 6c2a700a8a7f..8745837bd96a 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_create_sequence.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_create_sequence.cpp @@ -142,6 +142,10 @@ class TConfigureParts : public TSubOperationState { if (alterData->Description.HasCycle()) { event->Record.SetCycle(alterData->Description.GetCycle()); } + if (alterData->Description.HasSetVal()) { + event->Record.MutableSetVal()->SetNextValue(alterData->Description.GetSetVal().GetNextValue()); + event->Record.MutableSetVal()->SetNextUsed(alterData->Description.GetSetVal().GetNextUsed()); + } LOG_DEBUG_S(context.Ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, "TCreateSequence TConfigureParts ProgressState" diff --git a/ydb/core/tx/schemeshard/schemeshard_export_flow_proposals.cpp b/ydb/core/tx/schemeshard/schemeshard_export_flow_proposals.cpp index e80f3b09f958..4af5a86d53ea 100644 --- a/ydb/core/tx/schemeshard/schemeshard_export_flow_proposals.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_export_flow_proposals.cpp @@ -83,6 +83,30 @@ static NKikimrSchemeOp::TPathDescription GetTableDescription(TSchemeShard* ss, c return record.GetPathDescription(); } +void FillSetValForSequences(TSchemeShard* ss, NKikimrSchemeOp::TTableDescription& description, + const TPathId& exportItemPathId) { + NKikimrSchemeOp::TDescribeOptions opts; + opts.SetReturnSetVal(true); + + auto pathDescription = DescribePath(ss, TlsActivationContext->AsActorContext(), exportItemPathId, opts); + auto tableDescription = pathDescription->GetRecord().GetPathDescription().GetTable(); + + THashMap setValForSequences; + + for (const auto& sequenceDescription : tableDescription.GetSequences()) { + if (sequenceDescription.HasSetVal()) { + setValForSequences[sequenceDescription.GetName()] = sequenceDescription.GetSetVal(); + } + } + + for (auto& sequenceDescription : *description.MutableSequences()) { + auto it = setValForSequences.find(sequenceDescription.GetName()); + if (it != setValForSequences.end()) { + *sequenceDescription.MutableSetVal() = it->second; + } + } +} + THolder BackupPropose( TSchemeShard* ss, TTxId txId, @@ -106,8 +130,14 @@ THolder BackupPropose( task.SetNeedToBill(!exportInfo->UserSID || !ss->SystemBackupSIDs.contains(*exportInfo->UserSID)); const TPath sourcePath = TPath::Init(exportInfo->Items[itemIdx].SourcePathId, ss); - if (sourcePath.IsResolved()) { - task.MutableTable()->CopyFrom(GetTableDescription(ss, sourcePath.Base()->PathId)); + const TPath exportItemPath = exportPath.Child(ToString(itemIdx)); + if (sourcePath.IsResolved() && exportItemPath.IsResolved()) { + auto sourceDescription = GetTableDescription(ss, sourcePath.Base()->PathId); + if (sourceDescription.HasTable()) { + FillSetValForSequences( + ss, *sourceDescription.MutableTable(), exportItemPath.Base()->PathId); + } + task.MutableTable()->CopyFrom(sourceDescription); } task.SetSnapshotStep(exportInfo->SnapshotStep); diff --git a/ydb/core/tx/schemeshard/schemeshard_impl.h b/ydb/core/tx/schemeshard/schemeshard_impl.h index 2b560c12f506..40c8c427996f 100644 --- a/ydb/core/tx/schemeshard/schemeshard_impl.h +++ b/ydb/core/tx/schemeshard/schemeshard_impl.h @@ -992,8 +992,10 @@ class TSchemeShard void DescribeTableIndex(const TPathId& pathId, const TString& name, TTableIndexInfo::TPtr indexInfo, NKikimrSchemeOp::TIndexDescription& entry); void DescribeCdcStream(const TPathId& pathId, const TString& name, NKikimrSchemeOp::TCdcStreamDescription& desc); void DescribeCdcStream(const TPathId& pathId, const TString& name, TCdcStreamInfo::TPtr info, NKikimrSchemeOp::TCdcStreamDescription& desc); - void DescribeSequence(const TPathId& pathId, const TString& name, NKikimrSchemeOp::TSequenceDescription& desc); - void DescribeSequence(const TPathId& pathId, const TString& name, TSequenceInfo::TPtr info, NKikimrSchemeOp::TSequenceDescription& desc); + void DescribeSequence(const TPathId& pathId, const TString& name, + NKikimrSchemeOp::TSequenceDescription& desc, bool fillSetVal = false); + void DescribeSequence(const TPathId& pathId, const TString& name, TSequenceInfo::TPtr info, + NKikimrSchemeOp::TSequenceDescription& desc, bool fillSetVal = false); void DescribeReplication(const TPathId& pathId, const TString& name, NKikimrSchemeOp::TReplicationDescription& desc); void DescribeReplication(const TPathId& pathId, const TString& name, TReplicationInfo::TPtr info, NKikimrSchemeOp::TReplicationDescription& desc); void DescribeBlobDepot(const TPathId& pathId, const TString& name, NKikimrSchemeOp::TBlobDepotDescription& desc); diff --git a/ydb/core/tx/schemeshard/schemeshard_import_flow_proposals.cpp b/ydb/core/tx/schemeshard/schemeshard_import_flow_proposals.cpp index 9b4f9ad1d573..bed9631994bb 100644 --- a/ydb/core/tx/schemeshard/schemeshard_import_flow_proposals.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_import_flow_proposals.cpp @@ -72,6 +72,11 @@ THolder CreateTablePropose( if (fromSequence.has_cycle()) { seqDesc->SetCycle(fromSequence.cycle()); } + if (fromSequence.has_set_val()) { + auto* setVal = seqDesc->MutableSetVal(); + setVal->SetNextUsed(fromSequence.set_val().next_used()); + setVal->SetNextValue(fromSequence.set_val().next_value()); + } break; } diff --git a/ydb/core/tx/schemeshard/schemeshard_path_describer.cpp b/ydb/core/tx/schemeshard/schemeshard_path_describer.cpp index e24a1f59f8dd..d53f6b62d416 100644 --- a/ydb/core/tx/schemeshard/schemeshard_path_describer.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_path_describer.cpp @@ -211,6 +211,7 @@ void TPathDescriber::DescribeTable(const TActorContext& ctx, TPathId pathId, TPa bool returnBackupInfo = Params.GetBackupInfo(); bool returnBoundaries = false; bool returnRangeKey = true; + bool returnSetVal = Params.GetOptions().GetReturnSetVal(); if (Params.HasOptions()) { returnConfig = Params.GetOptions().GetReturnPartitionConfig(); returnPartitioning = Params.GetOptions().GetReturnPartitioningInfo(); @@ -361,7 +362,7 @@ void TPathDescriber::DescribeTable(const TActorContext& ctx, TPathId pathId, TPa Self->DescribeCdcStream(childPathId, childName, *entry->AddCdcStreams()); break; case NKikimrSchemeOp::EPathTypeSequence: - Self->DescribeSequence(childPathId, childName, *entry->AddSequences()); + Self->DescribeSequence(childPathId, childName, *entry->AddSequences(), returnSetVal); break; default: Y_FAIL_S("Unexpected table's child" @@ -1241,17 +1242,17 @@ void TSchemeShard::DescribeCdcStream(const TPathId& pathId, const TString& name, } void TSchemeShard::DescribeSequence(const TPathId& pathId, const TString& name, - NKikimrSchemeOp::TSequenceDescription& desc) + NKikimrSchemeOp::TSequenceDescription& desc, bool fillSetVal) { auto it = Sequences.find(pathId); Y_VERIFY_S(it != Sequences.end(), "Sequence not found" << " pathId# " << pathId << " name# " << name); - DescribeSequence(pathId, name, it->second, desc); + DescribeSequence(pathId, name, it->second, desc, fillSetVal); } void TSchemeShard::DescribeSequence(const TPathId& pathId, const TString& name, TSequenceInfo::TPtr info, - NKikimrSchemeOp::TSequenceDescription& desc) + NKikimrSchemeOp::TSequenceDescription& desc, bool fillSetVal) { Y_VERIFY_S(info, "Empty sequence info" << " pathId# " << pathId @@ -1259,6 +1260,10 @@ void TSchemeShard::DescribeSequence(const TPathId& pathId, const TString& name, desc = info->Description; + if (!fillSetVal) { + desc.ClearSetVal(); + } + desc.SetName(name); PathIdFromPathId(pathId, desc.MutablePathId()); desc.SetVersion(info->AlterVersion); diff --git a/ydb/core/tx/schemeshard/ut_helpers/helpers.cpp b/ydb/core/tx/schemeshard/ut_helpers/helpers.cpp index c3e0c5a65ae9..4f8832022eb8 100644 --- a/ydb/core/tx/schemeshard/ut_helpers/helpers.cpp +++ b/ydb/core/tx/schemeshard/ut_helpers/helpers.cpp @@ -2362,16 +2362,17 @@ namespace NSchemeShardUT_Private { runtime.Send(new IEventHandle(NSequenceProxy::MakeSequenceProxyServiceID(), sender, request.Release())); } - i64 WaitNextValResult(TTestActorRuntime& runtime, const TActorId& sender) { + i64 WaitNextValResult( + TTestActorRuntime& runtime, const TActorId& sender, Ydb::StatusIds::StatusCode expectedStatus) { auto ev = runtime.GrabEdgeEventRethrow(sender); auto* msg = ev->Get(); - UNIT_ASSERT_VALUES_EQUAL(msg->Status, Ydb::StatusIds::SUCCESS); + UNIT_ASSERT_VALUES_EQUAL(msg->Status, expectedStatus); return msg->Value; } - i64 DoNextVal(TTestActorRuntime& runtime, const TString& path) { + i64 DoNextVal(TTestActorRuntime& runtime, const TString& path, Ydb::StatusIds::StatusCode expectedStatus) { auto sender = runtime.AllocateEdgeActor(0); SendNextValRequest(runtime, sender, path); - return WaitNextValResult(runtime, sender); + return WaitNextValResult(runtime, sender, expectedStatus); } } diff --git a/ydb/core/tx/schemeshard/ut_helpers/helpers.h b/ydb/core/tx/schemeshard/ut_helpers/helpers.h index 1c2e5df68d4b..d3c79c0e6946 100644 --- a/ydb/core/tx/schemeshard/ut_helpers/helpers.h +++ b/ydb/core/tx/schemeshard/ut_helpers/helpers.h @@ -553,7 +553,11 @@ namespace NSchemeShardUT_Private { void WriteRow(TTestActorRuntime& runtime, const ui64 txId, const TString& tablePath, int partitionIdx, const ui32 key, const TString& value, bool successIsExpected = true); void SendNextValRequest(TTestActorRuntime& runtime, const TActorId& sender, const TString& path); - i64 WaitNextValResult(TTestActorRuntime& runtime, const TActorId& sender); - i64 DoNextVal(TTestActorRuntime& runtime, const TString& path); + i64 WaitNextValResult( + TTestActorRuntime& runtime, const TActorId& sender, + Ydb::StatusIds::StatusCode expectedStatus = Ydb::StatusIds::SUCCESS); + i64 DoNextVal( + TTestActorRuntime& runtime, const TString& path, + Ydb::StatusIds::StatusCode expectedStatus = Ydb::StatusIds::SUCCESS); } //NSchemeShardUT_Private diff --git a/ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp b/ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp index f4658249fb8f..c46eadac26ae 100644 --- a/ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp +++ b/ydb/core/tx/schemeshard/ut_restore/ut_restore.cpp @@ -955,6 +955,152 @@ value { UNIT_ASSERT_C(CheckDefaultFromSequence(table), "Invalid default value"); } + Y_UNIT_TEST(ShouldRestoreSequence) { + 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); + runtime.SetLogPriority(NKikimrServices::SEQUENCEPROXY, 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" + } + )"); + env.TestWaitNotification(runtime, txId); + + i64 value = DoNextVal(runtime, "/MyRoot/Original/myseq"); + UNIT_ASSERT_VALUES_EQUAL(value, 1); + + 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(); + + value = DoNextVal(runtime, "/MyRoot/Restored/myseq"); + UNIT_ASSERT_VALUES_EQUAL(value, 2); + + UNIT_ASSERT_C(CheckDefaultFromSequence(table), "Invalid default value"); + } + + Y_UNIT_TEST(ShouldRestoreSequenceWithOverflow) { + 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); + runtime.SetLogPriority(NKikimrServices::SEQUENCEPROXY, 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" + MinValue: 1 + MaxValue: 2 + } + )"); + env.TestWaitNotification(runtime, txId); + + i64 value = DoNextVal(runtime, "/MyRoot/Original/myseq"); + UNIT_ASSERT_VALUES_EQUAL(value, 1); + + value = DoNextVal(runtime, "/MyRoot/Original/myseq"); + UNIT_ASSERT_VALUES_EQUAL(value, 2); + + 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(); + + value = DoNextVal(runtime, "/MyRoot/Restored/myseq", Ydb::StatusIds::SCHEME_ERROR); + + 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_restore/ya.make b/ydb/core/tx/schemeshard/ut_restore/ya.make index 308dd73133fa..7044d4283b5e 100644 --- a/ydb/core/tx/schemeshard/ut_restore/ya.make +++ b/ydb/core/tx/schemeshard/ut_restore/ya.make @@ -21,7 +21,7 @@ PEERDIR( ydb/core/wrappers/ut_helpers ydb/core/ydb_convert ydb/library/yql/sql/pg - ydb/library/yql/parser/pg_wrapper + ydb/library/yql/parser/pg_wrapper ) SRCS( diff --git a/ydb/core/tx/sequenceshard/tx_create_sequence.cpp b/ydb/core/tx/sequenceshard/tx_create_sequence.cpp index 38822c47c10e..8df1e6092ed3 100644 --- a/ydb/core/tx/sequenceshard/tx_create_sequence.cpp +++ b/ydb/core/tx/sequenceshard/tx_create_sequence.cpp @@ -74,8 +74,15 @@ namespace NSequenceShard { sequence.Cycle = msg->Record.GetCycle(); } - sequence.NextValue = sequence.StartValue; - sequence.NextUsed = false; + + if (msg->Record.HasSetVal()) { + sequence.NextValue = msg->Record.GetSetVal().GetNextValue(); + sequence.NextUsed = msg->Record.GetSetVal().GetNextUsed(); + } else { + sequence.NextUsed = false; + sequence.NextValue = sequence.StartValue; + } + if (msg->Record.OptionalCache_case() == NKikimrTxSequenceShard::TEvCreateSequence::kCache) { sequence.Cache = msg->Record.GetCache(); if (sequence.Cache < 1) { diff --git a/ydb/core/ydb_convert/table_description.cpp b/ydb/core/ydb_convert/table_description.cpp index b60ccd52e64a..fc8a40a8e8ad 100644 --- a/ydb/core/ydb_convert/table_description.cpp +++ b/ydb/core/ydb_convert/table_description.cpp @@ -1416,6 +1416,14 @@ void FillSequenceDescription(Ydb::Table::CreateTableRequest& out, const NKikimrS if (sequenceDescription.HasIncrement()) { fromSequence->set_increment(sequenceDescription.GetIncrement()); } + if (sequenceDescription.HasCycle()) { + fromSequence->set_cycle(sequenceDescription.GetCycle()); + } + if (sequenceDescription.HasSetVal()) { + auto* setVal = fromSequence->mutable_set_val(); + setVal->set_next_used(sequenceDescription.GetSetVal().GetNextUsed()); + setVal->set_next_value(sequenceDescription.GetSetVal().GetNextValue()); + } break; } case Ydb::Table::ColumnMeta::kFromLiteral: { diff --git a/ydb/public/api/protos/ydb_table.proto b/ydb/public/api/protos/ydb_table.proto index 295b67c12777..50887aadf3d2 100644 --- a/ydb/public/api/protos/ydb_table.proto +++ b/ydb/public/api/protos/ydb_table.proto @@ -334,6 +334,10 @@ message TableProfile { } message SequenceDescription { + message SetVal { + optional sint64 next_value = 1; + optional bool next_used = 2; + } optional string name = 1; // mandatorys optional sint64 min_value = 2; // minimum value, defaults to 1 or Min optional sint64 max_value = 3; // maximum value, defaults to Max or -1 @@ -341,6 +345,7 @@ message SequenceDescription { optional uint64 cache = 5; // number of items to cache, defaults to 1 optional sint64 increment = 6; // increment at each call, defaults to 1 optional bool cycle = 7; // true when cycle on overflow is allowed + optional SetVal set_val = 8; // set_val(next_value, next_used) is executed atomically when creating } message ColumnMeta {