@@ -4293,7 +4293,7 @@ const NTable::TScheme& TExecutor::DatabaseScheme()
42934293 return Scheme ();
42944294}
42954295
4296- TIntrusiveConstPtr<NTable::TRowScheme> TExecutor::RowScheme (ui32 table)
4296+ TIntrusiveConstPtr<NTable::TRowScheme> TExecutor::RowScheme (ui32 table) const
42974297{
42984298 return Database->GetRowScheme (table);
42994299}
@@ -4334,6 +4334,80 @@ const NTable::TRowVersionRanges& TExecutor::TableRemovedRowVersions(ui32 table)
43344334 return Database->GetRemovedRowVersions (table);
43354335}
43364336
4337+ bool TExecutor::HasSchemaChanges (ui32 table) const {
4338+ auto *tableInfo = Scheme ().GetTableInfo (table);
4339+ auto rowScheme = RowScheme (table);
4340+ if (!tableInfo || !rowScheme) {
4341+ return false ;
4342+ }
4343+
4344+ auto subset = Database->Subset (table, NTable::TEpoch::Max (), { } , { });
4345+ for (const auto & partView : subset->Flatten ) {
4346+ if (HasSchemaChanges (partView, *tableInfo, *rowScheme)) {
4347+ return true ;
4348+ }
4349+ }
4350+
4351+ return false ;
4352+ }
4353+
4354+ bool TExecutor::HasSchemaChanges (const NTable::TPartView& partView, const NTable::TScheme::TTableInfo& tableInfo, const NTable::TRowScheme& rowScheme) const {
4355+ if (partView.Part ->Stat .Rows == 0 ) {
4356+ return false ;
4357+ }
4358+
4359+ { // Check by key filter existence
4360+ bool partByKeyFilter = bool (partView->ByKey );
4361+ bool schemeByKeyFilter = tableInfo.ByKeyFilter ;
4362+ if (partByKeyFilter != schemeByKeyFilter) {
4363+ return true ;
4364+ }
4365+ }
4366+
4367+ { // Check B-Tree index existence
4368+ if (AppData ()->FeatureFlags .GetEnableLocalDBBtreeIndex () && !partView->IndexPages .HasBTree ()) {
4369+ return true ;
4370+ }
4371+ }
4372+
4373+ { // Check families
4374+ size_t partFamiliesCount = partView->GroupsCount ;
4375+ size_t schemeFamiliesCount = rowScheme.Families .size ();
4376+ if (partFamiliesCount != schemeFamiliesCount) {
4377+ return true ;
4378+ }
4379+
4380+ for (size_t index : xrange (rowScheme.Families .size ())) {
4381+ auto familyId = rowScheme.Families [index];
4382+ static const NTable::TScheme::TFamily defaultFamilySettings;
4383+ const auto & family = tableInfo.Families .ValueRef (familyId, defaultFamilySettings); // Workaround for KIKIMR-17222
4384+
4385+ const auto * schemeGroupRoom = tableInfo.Rooms .FindPtr (family.Room );
4386+ Y_ABORT_UNLESS (schemeGroupRoom, " Cannot find room %" PRIu32 " in table %" PRIu32, family.Room , tableInfo.Id );
4387+
4388+ ui32 partGroupChannel = partView.Part ->GetGroupChannel (NTable::NPage::TGroupId (index));
4389+ if (partGroupChannel != schemeGroupRoom->Main ) {
4390+ return true ;
4391+ }
4392+ }
4393+ }
4394+
4395+ { // Check columns
4396+ THashMap<NTable::TTag, ui32> partColumnGroups, schemeColumnGroups;
4397+ for (const auto & column : partView->Scheme ->AllColumns ) {
4398+ partColumnGroups[column.Tag ] = column.Group ;
4399+ }
4400+ for (const auto & col : rowScheme.Cols ) {
4401+ schemeColumnGroups[col.Tag ] = col.Group ;
4402+ }
4403+ if (partColumnGroups != schemeColumnGroups) {
4404+ return true ;
4405+ }
4406+ }
4407+
4408+ return false ;
4409+ }
4410+
43374411ui64 TExecutor::BeginCompaction (THolder<NTable::TCompactionParams> params)
43384412{
43394413 if (auto logl = Logger->Log (ELnLev::Info))
@@ -4379,37 +4453,29 @@ ui64 TExecutor::BeginCompaction(THolder<NTable::TCompactionParams> params)
43794453
43804454 for (size_t group : xrange (rowScheme->Families .size ())) {
43814455 auto familyId = rowScheme->Families [group];
4382- const auto * family = tableInfo->Families .FindPtr (familyId);
4383- if (Y_UNLIKELY (!family)) {
4384- // FIXME: workaround for KIKIMR-17222
4385- // Column families with default settings may be missing in schema,
4386- // so we have to use a static variable as a substitute
4387- static const NTable::TScheme::TFamily defaultFamilySettings;
4388- family = &defaultFamilySettings;
4389- }
4390- Y_ABORT_UNLESS (family, " Cannot find family %" PRIu32 " in table %" PRIu32, familyId, table);
4456+ static const NTable::TScheme::TFamily defaultFamilySettings;
4457+ const auto & family = tableInfo->Families .ValueRef (familyId, defaultFamilySettings); // Workaround for KIKIMR-17222
43914458
4392- auto roomId = family->Room ;
4393- auto * room = tableInfo->Rooms .FindPtr (roomId);
4394- Y_ABORT_UNLESS (room, " Cannot find room %" PRIu32 " in table %" PRIu32, roomId, table);
4459+ auto * room = tableInfo->Rooms .FindPtr (family.Room );
4460+ Y_ABORT_UNLESS (room, " Cannot find room %" PRIu32 " in table %" PRIu32, family.Room , table);
43954461
43964462 auto & pageGroup = comp->Layout .Groups .at (group);
43974463 auto & writeGroup = comp->Writer .Groups .at (group);
43984464
4399- pageGroup.Codec = family-> Codec ;
4465+ pageGroup.Codec = family. Codec ;
44004466 pageGroup.PageSize = policy->MinDataPageSize ;
44014467 pageGroup.BTreeIndexNodeTargetSize = policy->MinBTreeIndexNodeSize ;
44024468 pageGroup.BTreeIndexNodeKeysMin = policy->MinBTreeIndexNodeKeys ;
44034469
4404- writeGroup.Cache = Max (family-> Cache , cache);
4470+ writeGroup.Cache = Max (family. Cache , cache);
44054471 writeGroup.MaxBlobSize = NBlockIO::BlockSize;
44064472 writeGroup.Channel = room->Main ;
44074473 addChannel (room->Main );
44084474
44094475 if (group == 0 ) {
44104476 // Small/Large edges are taken from the leader family
4411- comp->Layout .SmallEdge = family-> Small ;
4412- comp->Layout .LargeEdge = family-> Large ;
4477+ comp->Layout .SmallEdge = family. Small ;
4478+ comp->Layout .LargeEdge = family. Large ;
44134479
44144480 // Small/Large channels are taken from the leader family
44154481 comp->Writer .BlobsChannels = room->Blobs ;
0 commit comments