diff --git a/ydb/core/formats/arrow/accessor/abstract/constructor.h b/ydb/core/formats/arrow/accessor/abstract/constructor.h index aa99260e097a..363565e1a89b 100644 --- a/ydb/core/formats/arrow/accessor/abstract/constructor.h +++ b/ydb/core/formats/arrow/accessor/abstract/constructor.h @@ -25,10 +25,15 @@ class IConstructor { virtual TString DoDebugString() const { return ""; } + virtual bool DoIsEqualWithSameTypeTo(const IConstructor& item) const = 0; public: virtual ~IConstructor() = default; + bool IsEqualWithSameTypeTo(const IConstructor& item) const { + return DoIsEqualWithSameTypeTo(item); + } + TString DebugString() const { return TStringBuilder() << GetClassName() << ":" << DoDebugString(); } @@ -69,6 +74,19 @@ class TConstructorContainer: public NBackgroundTasks::TInterfaceProtoContainerGetClassName() != item.GetObjectPtr()->GetClassName()) { + return false; + } + return GetObjectPtr()->IsEqualWithSameTypeTo(*item.GetObjectPtr()); + } else { + return false; + } + } + static TConstructorContainer GetDefaultConstructor(); }; diff --git a/ydb/core/formats/arrow/accessor/plain/constructor.h b/ydb/core/formats/arrow/accessor/plain/constructor.h index 57c366689eb0..eb82e3c93ccd 100644 --- a/ydb/core/formats/arrow/accessor/plain/constructor.h +++ b/ydb/core/formats/arrow/accessor/plain/constructor.h @@ -12,6 +12,11 @@ class TConstructor: public IConstructor { private: static inline auto Registrator = TFactory::TRegistrator(GetClassNameStatic()); + + virtual bool DoIsEqualWithSameTypeTo(const IConstructor& /*item*/) const override { + return true; + } + virtual TConclusion> DoConstruct( const std::shared_ptr& originalData, const TChunkConstructionData& externalInfo) const override; virtual NKikimrArrowAccessorProto::TConstructor DoSerializeToProto() const override; diff --git a/ydb/core/formats/arrow/accessor/sparsed/constructor.h b/ydb/core/formats/arrow/accessor/sparsed/constructor.h index 0ccf5efdd70f..5112f2c4e9c0 100644 --- a/ydb/core/formats/arrow/accessor/sparsed/constructor.h +++ b/ydb/core/formats/arrow/accessor/sparsed/constructor.h @@ -12,6 +12,11 @@ class TConstructor: public IConstructor { private: static inline auto Registrator = TFactory::TRegistrator(GetClassNameStatic()); + + virtual bool DoIsEqualWithSameTypeTo(const IConstructor& /*item*/) const override { + return true; + } + virtual TConclusion> DoConstruct( const std::shared_ptr& originalData, const TChunkConstructionData& externalInfo) const override; virtual NKikimrArrowAccessorProto::TConstructor DoSerializeToProto() const override; diff --git a/ydb/core/formats/arrow/save_load/loader.cpp b/ydb/core/formats/arrow/save_load/loader.cpp index c9328f751d4a..d4707712c8b9 100644 --- a/ydb/core/formats/arrow/save_load/loader.cpp +++ b/ydb/core/formats/arrow/save_load/loader.cpp @@ -65,4 +65,19 @@ std::shared_ptr TColumnLoader::BuildD return AccessorConstructor->ConstructDefault(TChunkConstructionData(recordsCount, DefaultValue, ResultField->type())).DetachResult(); } +bool TColumnLoader::IsEqualTo(const TColumnLoader& item) const { + if (!!Transformer != !!item.Transformer) { + return false; + } else if (!!Transformer && !Transformer->IsEqualTo(*item.Transformer)) { + return false; + } + if (!Serializer.IsEqualTo(item.Serializer)) { + return false; + } + if (!AccessorConstructor.IsEqualTo(item.AccessorConstructor)) { + return false; + } + return true; +} + } // namespace NKikimr::NArrow::NAccessor diff --git a/ydb/core/formats/arrow/save_load/loader.h b/ydb/core/formats/arrow/save_load/loader.h index 2d3119ac3fa8..580e19ca96a0 100644 --- a/ydb/core/formats/arrow/save_load/loader.h +++ b/ydb/core/formats/arrow/save_load/loader.h @@ -25,17 +25,7 @@ class TColumnLoader { public: std::shared_ptr BuildDefaultAccessor(const ui32 recordsCount) const; - bool IsEqualTo(const TColumnLoader& item) const { - if (!!Transformer != !!item.Transformer) { - return false; - } else if (!!Transformer && !Transformer->IsEqualTo(*item.Transformer)) { - return false; - } - if (!Serializer.IsEqualTo(item.Serializer)) { - return false; - } - return true; - } + bool IsEqualTo(const TColumnLoader& item) const; TString DebugString() const; diff --git a/ydb/core/kqp/ut/olap/sparsed_ut.cpp b/ydb/core/kqp/ut/olap/sparsed_ut.cpp index 73b75f2cc53f..22b9ac600abb 100644 --- a/ydb/core/kqp/ut/olap/sparsed_ut.cpp +++ b/ydb/core/kqp/ut/olap/sparsed_ut.cpp @@ -21,7 +21,7 @@ Y_UNIT_TEST_SUITE(KqpOlapSparsed) { const TString StoreName; ui32 MultiColumnRepCount = 100; static const ui32 SKIP_GROUPS = 7; - const TVector FIELD_NAMES{"utf", "int", "uint", "float", "double"}; + const TVector FIELD_NAMES{ "utf", "int", "uint", "float", "double" }; public: TSparsedDataTest(const TString& storeName) : Kikimr(Settings) @@ -302,6 +302,48 @@ Y_UNIT_TEST_SUITE(KqpOlapSparsed) { TSparsedDataTest test(""); test.Execute(); } + + Y_UNIT_TEST(AccessorActualization) { + auto settings = TKikimrSettings().SetWithSampleTables(false); + TKikimrRunner kikimr(settings); + + auto csController = NYDBTest::TControllers::RegisterCSControllerGuard(); + csController->SetOverridePeriodicWakeupActivationPeriod(TDuration::Seconds(1)); + csController->SetOverrideLagForCompactionBeforeTierings(TDuration::Seconds(1)); + csController->SetOverrideReduceMemoryIntervalLimit(1LLU << 30); + + TLocalHelper(kikimr).CreateTestOlapTable(); + auto tableClient = kikimr.GetTableClient(); + + auto session = tableClient.CreateSession().GetValueSync().GetSession(); + Tests::NCommon::TLoggerInit(kikimr).SetComponents({ NKikimrServices::TX_COLUMNSHARD }, "CS").SetPriority(NActors::NLog::PRI_DEBUG).Initialize(); + + for (ui32 i = 0; i < 10; ++i) { + WriteTestData(kikimr, "/Root/olapStore/olapTable", 1000000, 300000000 + i * 1000, 10000); + } + csController->WaitIndexation(TDuration::Seconds(3)); + csController->WaitCompactions(TDuration::Seconds(3)); + + { + auto result = session.ExecuteSchemeQuery("ALTER OBJECT `/Root/olapStore` (TYPE TABLESTORE) SET (ACTION=ALTER_COLUMN, NAME=uid, `DATA_ACCESSOR_CONSTRUCTOR.CLASS_NAME`=`SPARSED`)").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), NYdb::EStatus::SUCCESS, result.GetIssues().ToString()); + } + + { + auto result = session.ExecuteSchemeQuery("ALTER OBJECT `/Root/olapStore` (TYPE TABLESTORE) SET (ACTION=UPSERT_OPTIONS, SCHEME_NEED_ACTUALIZATION=`true`)").GetValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), NYdb::EStatus::SUCCESS, result.GetIssues().ToString()); + } + csController->WaitActualization(TDuration::Seconds(5)); + { + auto it = tableClient.StreamExecuteScanQuery(R"( + --!syntax_v1 + SELECT count(uid) FROM `/Root/olapStore/olapTable` + )").GetValueSync(); + UNIT_ASSERT_C(it.IsSuccess(), it.GetIssues().ToString()); + Cerr << StreamResultToYson(it) << Endl; + } + } + } } // namespace