diff options
author | svc <svc@yandex-team.ru> | 2022-02-11 20:16:50 +0300 |
---|---|---|
committer | svc <svc@yandex-team.ru> | 2022-02-11 20:16:50 +0300 |
commit | 05ac286ec4ba733e0b158caa74c576e49b24b23e (patch) | |
tree | c6745be0ed51113b82280626fd47c296a0867390 | |
parent | 2a307bcbf7913175505081578c9f70f76071bd6e (diff) | |
download | ydb-05ac286ec4ba733e0b158caa74c576e49b24b23e.tar.gz |
KIKIMR-13964 alter index directly by administator
ref:673a9bc62ce066c5d033ffa17f9826953bb4e06a
11 files changed, 461 insertions, 34 deletions
diff --git a/ydb/core/kqp/ut/kqp_indexes_multishard_ut.cpp b/ydb/core/kqp/ut/kqp_indexes_multishard_ut.cpp index c80b2282be..59b3b823c9 100644 --- a/ydb/core/kqp/ut/kqp_indexes_multishard_ut.cpp +++ b/ydb/core/kqp/ut/kqp_indexes_multishard_ut.cpp @@ -67,7 +67,129 @@ Y_UNIT_TEST_SUITE(KqpMultishardIndex) { UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString()); UNIT_ASSERT_VALUES_EQUAL(NYdb::FormatResultSetYson(result.GetResultSet(0)), "[[[4294967295u];[4u];[\"v4\"]]]"); } - } + } + + Y_UNIT_TEST_NEW_ENGINE(YqWorksFineAfterAlterIndexTableDirectly) { + TKikimrRunner kikimr(SyntaxV1Settings()); + CreateTableWithMultishardIndex(kikimr.GetTestClient()); + auto db = kikimr.GetTableClient(); + auto session = db.CreateSession().GetValueSync().GetSession(); + + { + const TString query(Q_(R"( + UPSERT INTO `/Root/MultiShardIndexed` (key, fk, value) VALUES + (1, 1000000000, "v1"), + (2, 2000000000, "v2"), + (3, 3000000000, "v3"), + (4, 4294967295, "v4"); + )")); + + auto result = session.ExecuteDataQuery( + query, + TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()) + .ExtractValueSync(); + UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString()); + } + + kikimr.GetTestServer().GetRuntime()->GetAppData().AdministrationAllowedSIDs.push_back("root@builtin"); + + { // without token request is forbidded + Tests::TClient& client = kikimr.GetTestClient(); + const TString scheme = R"( + Name: "indexImplTable" + PartitionConfig { + PartitioningPolicy { + MinPartitionsCount: 1 + SizeToSplit: 100500 + FastSplitSettings { + SizeThreshold: 100500 + RowCountThreshold: 100500 + } + } + } + )"; + auto result = client.AlterTable("/Root/MultiShardIndexed/index", scheme, "user@builtin"); + UNIT_ASSERT_VALUES_EQUAL_C(result->Record.GetStatus(), NMsgBusProxy::MSTATUS_ERROR, "User must not be able to alter index impl table"); + UNIT_ASSERT_VALUES_EQUAL(result->Record.GetErrorReason(), "Administrative access denied"); + } + + { // with root token request is accepted + Tests::TClient& client = kikimr.GetTestClient(); + const TString scheme = R"( + Name: "indexImplTable" + PartitionConfig { + PartitioningPolicy { + MinPartitionsCount: 1 + SizeToSplit: 100500 + FastSplitSettings { + SizeThreshold: 100500 + RowCountThreshold: 100500 + } + } + } + )"; + auto result = client.AlterTable("/Root/MultiShardIndexed/index", scheme, "root@builtin"); + UNIT_ASSERT_VALUES_EQUAL_C(result->Record.GetStatus(), NMsgBusProxy::MSTATUS_OK, "Super user must be able to alter partition config"); + } + + { // after alter yql works fine + const TString query(Q_(R"( + SELECT * FROM `/Root/MultiShardIndexed` VIEW index ORDER BY fk DESC LIMIT 1; + )")); + + auto result = session.ExecuteDataQuery( + query, + TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()) + .ExtractValueSync(); + UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString()); + UNIT_ASSERT_VALUES_EQUAL(NYdb::FormatResultSetYson(result.GetResultSet(0)), "[[[4294967295u];[4u];[\"v4\"]]]"); + } + + { // write request works well too + const TString query(Q_(R"( + UPSERT INTO `/Root/MultiShardIndexed` (key, fk, value) VALUES + (1, 1000000000, "v1"), + (2, 2000000000, "v2"), + (3, 3000000000, "v3"), + (4, 4294967295, "v4"); + )")); + + auto result = session.ExecuteDataQuery( + query, + TTxControl::BeginTx(TTxSettings::SerializableRW()).CommitTx()) + .ExtractValueSync(); + UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString()); + } + + { // just for sure, public api got error when alter index + auto settings = NYdb::NTable::TAlterTableSettings() + .BeginAlterPartitioningSettings() + .SetPartitionSizeMb(50) + .SetMinPartitionsCount(4) + .SetMaxPartitionsCount(5) + .EndAlterPartitioningSettings(); + + auto result = session.AlterTable("/Root/MultiShardIndexed/index/indexImplTable", settings).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SCHEME_ERROR, result.GetIssues().ToString()); + } + + { // however public api is able to perform alter index if user has AlterSchema right and user is a member of the list AdministrationAllowedSIDs + auto clSettings = NYdb::NTable::TClientSettings().AuthToken("root@builtin").UseQueryCache(false); + auto client = NYdb::NTable::TTableClient(kikimr.GetDriver(), clSettings); + auto session = client.CreateSession().GetValueSync().GetSession(); + + auto settings = NYdb::NTable::TAlterTableSettings() + .BeginAlterPartitioningSettings() + .SetPartitionSizeMb(50) + .SetMinPartitionsCount(4) + .SetMaxPartitionsCount(5) + .EndAlterPartitioningSettings(); + + auto result = session.AlterTable("/Root/MultiShardIndexed/index/indexImplTable", settings).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + + } } } diff --git a/ydb/core/tx/schemeshard/schemeshard__operation.cpp b/ydb/core/tx/schemeshard/schemeshard__operation.cpp index daf1218bcf..cdd5f0ba73 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation.cpp @@ -932,7 +932,7 @@ ISubOperationBase::TPtr TOperation::ConstructPart(NKikimrSchemeOp::EOperationTyp case NKikimrSchemeOp::EOperationType::ESchemeOpCreateTable: return CreateNewTable(NextPartId(), tx); case NKikimrSchemeOp::EOperationType::ESchemeOpAlterTable: - return CreateAlterTable(NextPartId(), tx); + Y_FAIL("in general, alter table is multipart operation now due table indexes"); case NKikimrSchemeOp::EOperationType::ESchemeOpSplitMergeTablePartitions: return CreateSplitMerge(NextPartId(), tx); case NKikimrSchemeOp::EOperationType::ESchemeOpBackup: @@ -1130,6 +1130,9 @@ TVector<ISubOperationBase::TPtr> TOperation::ConstructParts(const TTxTransaction return CreateDropCdcStream(NextPartId(), tx, context); case NKikimrSchemeOp::EOperationType::ESchemeOpMoveTable: return CreateConsistentMoveTable(NextPartId(), tx, context); + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterTable: + return CreateConsistentAlterTable(NextPartId(), tx, context); + default: return {ConstructPart(opType, tx)}; } diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_alter_index.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_alter_index.cpp index 10688f0991..3617728fbe 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_alter_index.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_alter_index.cpp @@ -52,6 +52,12 @@ public: context.SS->ClearDescribePathCaches(path); context.OnComplete.PublishToSchemeBoard(OperationId, path->PathId); + auto parentDir = context.SS->PathsById.at(path->ParentPathId); + ++parentDir->DirAlterVersion; + context.SS->PersistPathDirAlterVersion(db, parentDir); + context.SS->ClearDescribePathCaches(parentDir); + context.OnComplete.PublishToSchemeBoard(OperationId, parentDir->PathId); + context.SS->ChangeTxState(db, OperationId, TTxState::Done); return true; } @@ -206,29 +212,28 @@ public: return result; } - TTableIndexInfo::TPtr indexData = context.SS->Indexes.at(dstPath.Base()->PathId); + auto indexPath = dstPath.Base(); + + context.MemChanges.GrabPath(context.SS, indexPath->PathId); + context.MemChanges.GrabPath(context.SS, indexPath->ParentPathId); + context.MemChanges.GrabNewTxState(context.SS, OperationId); + context.MemChanges.GrabIndex(context.SS, indexPath->PathId); + + context.DbChanges.PersistPath(indexPath->PathId); + context.DbChanges.PersistAlterIndex(indexPath->PathId); + context.DbChanges.PersistTxState(OperationId); + + TTableIndexInfo::TPtr indexData = context.SS->Indexes.at(indexPath->PathId); TTableIndexInfo::TPtr newIndexData = indexData->CreateNextVersion(); - if (!newIndexData) { - result->SetError(TEvSchemeShard::EStatus::StatusInvalidParameter, errMsg); - return result; - } + Y_VERIFY(newIndexData); newIndexData->State = tableIndexAlter.GetState(); - NIceDb::TNiceDb db(context.Txc.DB); - // store table index description - auto indexPath = dstPath.Base(); - Y_VERIFY(!context.SS->FindTx(OperationId)); TTxState& txState = context.SS->CreateTx(OperationId, TTxState::TxAlterTableIndex, indexPath->PathId); txState.State = TTxState::Propose; indexPath->PathState = NKikimrSchemeOp::EPathStateAlter; indexPath->LastTxId = OperationId.GetTxId(); - context.SS->PersistLastTxId(db, indexPath); - - context.SS->PersistTableIndexAlterData(db, indexPath->PathId); - - context.SS->PersistTxState(db, OperationId); context.OnComplete.ActivateTx(OperationId); @@ -237,8 +242,11 @@ public: return result; } - void AbortPropose(TOperationContext&) override { - Y_FAIL("no AbortPropose for TAlterTableIndex"); + void AbortPropose(TOperationContext& context) override { + LOG_NOTICE_S(context.Ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, + "TAlterTableIndex AbortPropose" + << ", opId: " << OperationId + << ", at schemeshard: " << context.SS->TabletID()); } void AbortUnsafe(TTxId forceDropTxId, TOperationContext& context) override { diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_alter_table.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_alter_table.cpp index b6c0b6c8b2..849a111d91 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_alter_table.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_alter_table.cpp @@ -46,8 +46,6 @@ TTableInfo::TAlterDataPtr ParseParams(const TPath& path, TTableInfo::TPtr table, const TAppData* appData = AppData(context.Ctx); if (!path.IsCommonSensePath()) { - Y_VERIFY_DEBUG(IsSuperUser(context.UserToken.Get()) || context.IsAllowedPrivateTables, "Only superuser can alter index impl table"); - if (alter.ColumnsSize() != 0 || alter.DropColumnsSize() != 0) { errStr = "Adding or dropping columns in index table is not supported"; status = NKikimrScheme::StatusInvalidParameter; @@ -512,8 +510,8 @@ public: .IsTable() .NotUnderOperation(); - if (!context.IsAllowedPrivateTables && !IsSuperUser(context.UserToken.Get())) { - checks.IsCommonSensePath(); //forbid alter impl index tables + if (!context.IsAllowedPrivateTables) { + checks.IsCommonSensePath(); //forbid alter impl index tables outside consistent operation } if (!checks) { @@ -642,5 +640,64 @@ ISubOperationBase::TPtr CreateFinalizeBuildIndexImplTable(TOperationId id, TTxSt return obj.Release(); } +TVector<ISubOperationBase::TPtr> CreateConsistentAlterTable(TOperationId id, const TTxTransaction& tx, TOperationContext& context) { + Y_VERIFY(tx.GetOperationType() == NKikimrSchemeOp::EOperationType::ESchemeOpAlterTable); + + auto alter = tx.GetAlterTable(); + + const TString& parentPathStr = tx.GetWorkingDir(); + const TString& name = alter.GetName(); + + TPathId pathId = alter.HasPathId() ? PathIdFromPathId(alter.GetPathId()) : InvalidPathId; + + if (!alter.HasName() && !pathId) { + return {CreateAlterTable(id, tx)}; + } + + TPath path = pathId + ? TPath::Init(pathId, context.SS) + : TPath::Resolve(parentPathStr, context.SS).Dive(name); + + if (!path.IsResolved()) { + return {CreateAlterTable(id, tx)}; + } + + if (!path->IsTable()) { + return {CreateAlterTable(id, tx)}; + } + + if (path.IsCommonSensePath()) { + return {CreateAlterTable(id, tx)}; + } + + TPath parent = path.Parent(); + + if (!parent.IsTableIndex()) { + return {CreateAlterTable(id, tx)}; + } + + TVector<ISubOperationBase::TPtr> result; + + // only for super user use + // until correct and safe altering index api is released + if (!IsSuperUser(context.UserToken.Get())) { + return {CreateAlterTable(id, tx)}; + } + + { + auto tableIndexAltering = TransactionTemplate(parent.Parent().PathString(), NKikimrSchemeOp::EOperationType::ESchemeOpAlterTableIndex); + auto alterIndex = tableIndexAltering.MutableAlterTableIndex(); + alterIndex->SetName(parent.LeafName()); + alterIndex->SetState(NKikimrSchemeOp::EIndexState::EIndexStateReady); + + result.push_back(CreateAlterTableIndex(NextPartId(id, result), tableIndexAltering)); + } + + result.push_back(CreateAlterTable(NextPartId(id, result), tx)); + + + return result; +} + } } diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_memory_changes.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_memory_changes.cpp index e4151fd8df..d7efc1dbf5 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_memory_changes.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_memory_changes.cpp @@ -63,6 +63,13 @@ void TMemoryChanges::GrabNewIndex(TSchemeShard* ss, const TPathId& pathId) { Indexes.emplace(pathId, nullptr); } +void TMemoryChanges::GrabIndex(TSchemeShard* ss, const TPathId& pathId) { + Y_VERIFY(ss->Indexes.contains(pathId)); + + TTableIndexInfo::TPtr copy = new TTableIndexInfo(*ss->Indexes.at(pathId)); + Indexes.emplace(pathId, copy); +} + void TMemoryChanges::GrabNewCdcStream(TSchemeShard* ss, const TPathId& pathId) { Y_VERIFY(!ss->CdcStreams.contains(pathId)); diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_memory_changes.h b/ydb/core/tx/schemeshard/schemeshard__operation_memory_changes.h index c6ec264ffe..7bc04e3beb 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_memory_changes.h +++ b/ydb/core/tx/schemeshard/schemeshard__operation_memory_changes.h @@ -53,6 +53,7 @@ public: void GrabDomain(TSchemeShard* ss, const TPathId& pathId); void GrabNewIndex(TSchemeShard* ss, const TPathId& pathId); + void GrabIndex(TSchemeShard* ss, const TPathId& pathId); void GrabNewCdcStream(TSchemeShard* ss, const TPathId& pathId); diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_part.h b/ydb/core/tx/schemeshard/schemeshard__operation_part.h index 4a639e6342..579b52a461 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_part.h +++ b/ydb/core/tx/schemeshard/schemeshard__operation_part.h @@ -211,6 +211,7 @@ TVector<ISubOperationBase::TPtr> CreateCopyTable(TOperationId nextId, const TTxT ISubOperationBase::TPtr CreateAlterTable(TOperationId id, const TTxTransaction& tx); ISubOperationBase::TPtr CreateAlterTable(TOperationId id, TTxState::ETxState state); +TVector<ISubOperationBase::TPtr> CreateConsistentAlterTable(TOperationId id, const TTxTransaction& tx, TOperationContext& context); ISubOperationBase::TPtr CreateSplitMerge(TOperationId id, const TTxTransaction& tx); ISubOperationBase::TPtr CreateSplitMerge(TOperationId id, TTxState::ETxState state); diff --git a/ydb/core/tx/schemeshard/schemeshard_info_types.cpp b/ydb/core/tx/schemeshard/schemeshard_info_types.cpp index fcb564b606..332746dae0 100644 --- a/ydb/core/tx/schemeshard/schemeshard_info_types.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_info_types.cpp @@ -449,7 +449,7 @@ bool TPartitionConfigMerger::ApplyChanges( if (changes.HasCrossDataCenterFollowerCount()) { if (result.FollowerGroupsSize()) { - errDesr = TStringBuilder() << "Forbided downgrade from FollowerGroup option to the HasCrossDataCenterFollowerCount option"; + errDesr = TStringBuilder() << "Forbidded downgrade from FollowerGroup option to the HasCrossDataCenterFollowerCount option"; return false; } @@ -464,12 +464,12 @@ bool TPartitionConfigMerger::ApplyChanges( if (changes.HasFollowerCount()) { if (result.HasCrossDataCenterFollowerCount()) { - errDesr = TStringBuilder() << "Forbided downgrade from CrossDataCenterFollowerCount option to the FollowerGroup option"; + errDesr = TStringBuilder() << "Forbidded downgrade from CrossDataCenterFollowerCount option to the FollowerGroup option"; return false; } if (result.FollowerGroupsSize()) { - errDesr = TStringBuilder() << "Forbided downgrade from FollowerGroup option to the FollowerGroup option"; + errDesr = TStringBuilder() << "Forbidded downgrade from FollowerGroup option to the FollowerGroup option"; return false; } @@ -478,7 +478,7 @@ bool TPartitionConfigMerger::ApplyChanges( if (changes.HasAllowFollowerPromotion()) { if (result.FollowerGroupsSize()) { - errDesr = TStringBuilder() << "Forbided downgrade from FollowerGroup option to the AllowFollowerPromotion option"; + errDesr = TStringBuilder() << "Forbidded downgrade from FollowerGroup option to the AllowFollowerPromotion option"; return false; } diff --git a/ydb/core/tx/schemeshard/ut_base.cpp b/ydb/core/tx/schemeshard/ut_base.cpp index a76dcf9d5b..9b135fc880 100644 --- a/ydb/core/tx/schemeshard/ut_base.cpp +++ b/ydb/core/tx/schemeshard/ut_base.cpp @@ -2135,6 +2135,11 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { Columns { Name: "add_2" Type: "Uint64"} )", {TEvSchemeShard::EStatus::StatusNameConflict}); + TestAlterTable(runtime, ++txId, "/MyRoot/DirA/Table1/UserDefinedIndexByValue0", R"( + Name: "indexImplTable" + DropColumns { Name: "key" Type: "Uint64"} + )", {TEvSchemeShard::EStatus::StatusNameConflict}); + TestCopyTable(runtime, ++txId, "/MyRoot/DirA", "copy_is_ok", "/MyRoot/DirA/Table1"); env.TestWaitNotification(runtime, txId); @@ -9747,7 +9752,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { TestDescribeResult(DescribePath(runtime, "/MyRoot/Table1"), {NLs::IsTable, - NLs::PathVersionEqual(7), + NLs::PathVersionEqual(8), NLs::CheckColumns("Table1", {"key", "value"}, {}, {"key"}), NLs::IndexesCount(0)}); @@ -9776,7 +9781,7 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { TestDescribeResult(DescribePath(runtime, "/MyRoot/Table1"), {NLs::IsTable, - NLs::PathVersionEqual(7), + NLs::PathVersionEqual(8), NLs::IndexesCount(0)}); TestDescribeResult(DescribePath(runtime, "/MyRoot/Copy1"), @@ -9847,4 +9852,227 @@ Y_UNIT_TEST_SUITE(TSchemeShardTest) { } } + + Y_UNIT_TEST(AlterIndexTableDirectly) { + TTestBasicRuntime runtime; + + TTestEnvOptions opts; + opts.EnableBackgroundCompaction(false); + + TTestEnv env(runtime, opts); + + ui64 txId = 100; + + NDataShard::gDbStatsReportInterval = TDuration::Seconds(1); + NDataShard::gDbStatsDataSizeResolution = 10; + NDataShard::gDbStatsRowCountResolution = 10; + + runtime.GetAppData().AdministrationAllowedSIDs.push_back("true-root@builtin"); + + runtime.SetLogPriority(NKikimrServices::TX_DATASHARD, NActors::NLog::PRI_DEBUG); + + TestCreateTable(runtime, ++txId, "/MyRoot", R"( + Name: "table" + Columns { Name: "key" Type: "Uint32" } + Columns { Name: "value" Type: "Utf8" } + KeyColumnNames: ["key"] + )"); + env.TestWaitNotification(runtime, {txId, txId-1}); + + { + auto fnWriteRow = [&] (ui64 tabletId, ui32 key, TString value, const char* table) { + TString writeQuery = Sprintf(R"( + ( + (let key '( '('key (Uint32 '%u ) ) ) ) + (let row '( '('value (Utf8 '%s) ) ) ) + (return (AsList (UpdateRow '__user__%s key row) )) + ) + )", key, value.c_str(), table); + NKikimrMiniKQL::TResult result; + TString err; + NKikimrProto::EReplyStatus status = LocalMiniKQL(runtime, tabletId, writeQuery, result, err); + UNIT_ASSERT_VALUES_EQUAL(err, ""); + UNIT_ASSERT_VALUES_EQUAL(status, NKikimrProto::EReplyStatus::OK);; + }; + + fnWriteRow(TTestTxConfig::FakeHiveTablets, 1, "A", "table"); + fnWriteRow(TTestTxConfig::FakeHiveTablets, 2, "B", "table"); + fnWriteRow(TTestTxConfig::FakeHiveTablets, 3, "C", "table"); + fnWriteRow(TTestTxConfig::FakeHiveTablets, 4, "D", "table"); + fnWriteRow(TTestTxConfig::FakeHiveTablets, 5, "E", "table"); + + fnWriteRow(TTestTxConfig::FakeHiveTablets, 6, "F", "table"); + fnWriteRow(TTestTxConfig::FakeHiveTablets, 7, "G", "table"); + fnWriteRow(TTestTxConfig::FakeHiveTablets, 8, "H", "table"); + fnWriteRow(TTestTxConfig::FakeHiveTablets, 9, "I", "table"); + fnWriteRow(TTestTxConfig::FakeHiveTablets, 10, "J", "table"); + + + fnWriteRow(TTestTxConfig::FakeHiveTablets, 11, "K", "table"); + fnWriteRow(TTestTxConfig::FakeHiveTablets, 12, "L", "table"); + fnWriteRow(TTestTxConfig::FakeHiveTablets, 13, "M", "table"); + fnWriteRow(TTestTxConfig::FakeHiveTablets, 14, "N", "table"); + fnWriteRow(TTestTxConfig::FakeHiveTablets, 15, "O", "table"); + } + + TestDescribeResult(DescribePath(runtime, "/MyRoot/table"), + {NLs::PathExist, + NLs::IndexesCount(0), + NLs::PathVersionEqual(3)}); + + { + TestBuilIndex(runtime, ++txId, TTestTxConfig::SchemeShard, "/MyRoot", "/MyRoot/table", "indexByValue", {"value"}); + ui64 builIndexId = txId; + + auto listing = TestListBuilIndex(runtime, TTestTxConfig::SchemeShard, "/MyRoot"); + Y_ASSERT(listing.EntriesSize() == 1); + + env.TestWaitNotification(runtime, builIndexId, TTestTxConfig::SchemeShard); + + auto descr = TestGetBuilIndex(runtime, TTestTxConfig::SchemeShard, "/MyRoot", builIndexId); + Y_ASSERT(descr.GetIndexBuild().GetState() == Ydb::Table::IndexBuildState::STATE_DONE); + } + + TestDescribeResult(DescribePath(runtime, "/MyRoot/table"), + {NLs::PathExist, + NLs::IndexesCount(1), + NLs::PathVersionEqual(6)}); + + TestDescribeResult(DescribePath(runtime, "/MyRoot/table/indexByValue", true, true, true), + {NLs::PathExist, + NLs::PathVersionEqual(3)}); + + TestDescribeResult(DescribePath(runtime, "/MyRoot/table/indexByValue/indexImplTable", true, true, true), + {NLs::PathExist, + NLs::PathVersionEqual(4), + NLs::PartitionCount(1), + NLs::MinPartitionsCountEqual(0), + NLs::MaxPartitionsCountEqual(100)}); + + + TestSplitTable(runtime, ++txId, "/MyRoot/table/indexByValue/indexImplTable", R"( + SourceTabletId: 9437195 + SplitBoundary { + KeyPrefix { + Tuple { Optional { Text: "B" } } + } + } + SplitBoundary { + KeyPrefix { + Tuple { Optional { Text: "D" } } Tuple {} + } + })"); + env.TestWaitNotification(runtime, txId); + + TestDescribeResult(DescribePath(runtime, "/MyRoot/table/indexByValue/indexImplTable", true, true, true), + {NLs::PathExist, + NLs::PathVersionEqual(5), + NLs::PartitionCount(3), + NLs::MinPartitionsCountEqual(0), + NLs::MaxPartitionsCountEqual(100)}); + + // request without token + TestAlterTable(runtime, ++txId, "/MyRoot/table/indexByValue/", R"( + Name: "indexImplTable" + PartitionConfig { + PartitioningPolicy { + MinPartitionsCount: 1 + SizeToSplit: 100502 + FastSplitSettings { + SizeThreshold: 100502 + RowCountThreshold: 100502 + } + } + } + )", {NKikimrScheme::StatusNameConflict}); + + { // request with not a super user token + auto request = AlterTableRequest(++txId, "/MyRoot/table/indexByValue/", R"( + Name: "indexImplTable" + PartitionConfig { + PartitioningPolicy { + MinPartitionsCount: 1 + SizeToSplit: 100501 + FastSplitSettings { + SizeThreshold: 100501 + RowCountThreshold: 100501 + } + } + } + )"); + + auto wellCookedToken = NACLib::TUserToken(TVector<TString>{"not-a-root@builtin"}); + request->Record.SetUserToken(wellCookedToken.SerializeAsString()); + TActorId sender = runtime.AllocateEdgeActor(); + ForwardToTablet(runtime, TTestTxConfig::SchemeShard, sender, request); + TestModificationResults(runtime, txId, {TEvSchemeShard::EStatus::StatusNameConflict}); + } + + { + auto request = AlterTableRequest(++txId, "/MyRoot/table/indexByValue/", R"( + Name: "indexImplTable" + PartitionConfig { + PartitioningPolicy { + MinPartitionsCount: 1 + SizeToSplit: 100500 + FastSplitSettings { + SizeThreshold: 100500 + RowCountThreshold: 100500 + } + } + } + )"); + auto wellCookedToken = NACLib::TUserToken(TVector<TString>{"true-root@builtin"}); + request->Record.SetUserToken(wellCookedToken.SerializeAsString()); + TActorId sender = runtime.AllocateEdgeActor(); + ForwardToTablet(runtime, TTestTxConfig::SchemeShard, sender, request); + TestModificationResults(runtime, txId, {TEvSchemeShard::EStatus::StatusAccepted}); + + env.TestWaitNotification(runtime, txId); + } + + while (true) { + TVector<THolder<IEventHandle>> suppressed; + auto prevObserver = SetSuppressObserver(runtime, suppressed, TEvDataShard::TEvPeriodicTableStats::EventType); + + WaitForSuppressed(runtime, suppressed, 10, prevObserver); + for (auto &msg : suppressed) { + runtime.Send(msg.Release()); + } + suppressed.clear(); + + bool itIsEnough = false; + + auto desrc = DescribePath(runtime, "/MyRoot/table/indexByValue/indexImplTable", true, true, true); + + NLs::TCheckFunc checkPartitionCount = [&] (const NKikimrScheme::TEvDescribeSchemeResult& record) { + if (record.GetPathDescription().TablePartitionsSize() == 1) { + itIsEnough = true; + } + }; + + auto pathVersion = TestDescribeResult(desrc, {checkPartitionCount}); + + if (itIsEnough) { + break; + } + + for (const auto& tPart: desrc.GetPathDescription().GetTablePartitions()) { + TActorId sender = runtime.AllocateEdgeActor(); + auto evTx = new TEvDataShard::TEvCompactBorrowed(pathVersion.PathId); + ForwardToTablet(runtime, tPart.GetDatashardId(), sender, evTx); + } + } + + TestDescribeResult(DescribePath(runtime, "/MyRoot/table/indexByValue", true, true, true), + {NLs::PathExist, + NLs::PathVersionEqual(4)}); + + TestDescribeResult(DescribePath(runtime, "/MyRoot/table/indexByValue/indexImplTable", true, true, true), + {NLs::PathExist, + NLs::PathVersionOneOf({8}), + NLs::PartitionCount(1), + NLs::MinPartitionsCountEqual(1), + NLs::MaxPartitionsCountEqual(100)}); + } } diff --git a/ydb/core/tx/schemeshard/ut_index_build.cpp b/ydb/core/tx/schemeshard/ut_index_build.cpp index 88860481cc..bde0dbc59f 100644 --- a/ydb/core/tx/schemeshard/ut_index_build.cpp +++ b/ydb/core/tx/schemeshard/ut_index_build.cpp @@ -298,7 +298,7 @@ Y_UNIT_TEST_SUITE(IndexBuildTest) { TestDescribeResult(DescribePath(runtime, tenantSchemeShard, "/MyRoot/ServerLessDB/Table"), {NLs::PathExist, NLs::IndexesCount(1), - NLs::PathVersionEqual(5)}); + NLs::PathVersionEqual(6)}); TestDescribeResult(DescribePath(runtime, tenantSchemeShard, "/MyRoot/ServerLessDB/Table/index1", true, true, true), {NLs::PathExist, @@ -319,7 +319,7 @@ Y_UNIT_TEST_SUITE(IndexBuildTest) { TestDescribeResult(DescribePath(runtime, tenantSchemeShard, "/MyRoot/ServerLessDB/Table"), {NLs::PathExist, NLs::IndexesCount(0), - NLs::PathVersionEqual(7)}); + NLs::PathVersionEqual(8)}); // Test that index build succeeds on recreated columns @@ -561,7 +561,7 @@ Y_UNIT_TEST_SUITE(IndexBuildTest) { TestDescribeResult(DescribePath(runtime, "/MyRoot/WithFollowers"), {NLs::PathExist, NLs::IndexesCount(1), - NLs::PathVersionEqual(5)}); + NLs::PathVersionEqual(6)}); TestDescribeResult(DescribePath(runtime, "/MyRoot/WithFollowers/UserDefinedIndexByValue0", true, true, true), {NLs::PathExist, @@ -580,7 +580,7 @@ Y_UNIT_TEST_SUITE(IndexBuildTest) { TestDescribeResult(DescribePath(runtime, "/MyRoot/WithFollowers"), {NLs::PathExist, NLs::IndexesCount(0), - NLs::PathVersionEqual(7)}); + NLs::PathVersionEqual(8)}); } Y_UNIT_TEST(RejectsCreate) { @@ -992,7 +992,7 @@ Y_UNIT_TEST_SUITE(IndexBuildTest) { TestDescribeResult(DescribePath(runtime, "/MyRoot/Table"), {NLs::PathExist, NLs::IndexesCount(1), - NLs::PathVersionEqual(5)}); + NLs::PathVersionEqual(6)}); TestDescribeResult(DescribePath(runtime, "/MyRoot/Table/index1", true, true, true), {NLs::PathExist}); diff --git a/ydb/core/tx/schemeshard/ut_index_build_reboots.cpp b/ydb/core/tx/schemeshard/ut_index_build_reboots.cpp index d270fd87e6..543d52895d 100644 --- a/ydb/core/tx/schemeshard/ut_index_build_reboots.cpp +++ b/ydb/core/tx/schemeshard/ut_index_build_reboots.cpp @@ -415,7 +415,7 @@ Y_UNIT_TEST_SUITE(IndexBuildTestReboots) { TestDescribeResult(DescribePath(runtime, "/MyRoot/dir/Table"), {NLs::PathExist, NLs::IndexesCount(1), - NLs::PathVersionEqual(5)}); + NLs::PathVersionEqual(6)}); TestDescribeResult(DescribePath(runtime, "/MyRoot/dir/Table/index1", true, true, true), {NLs::PathExist}); |