#include "mkql_pickle.h" #include #include #include #include #include namespace NKikimr { namespace NMiniKQL { namespace { template class TPickleWrapper : public TMutableComputationNode> { typedef TMutableComputationNode> TBaseComputation; public: TPickleWrapper(TComputationMutables& mutables, TType* type, IComputationNode* data) : TBaseComputation(mutables) , Type(type) , ValuePacker(mutables) , Data(data) { } NUdf::TUnboxedValuePod DoCalculate(TComputationContext& ctx) const { return MakeString(ValuePacker.RefMutableObject(ctx, Stable, Type).Pack(Data->GetValue(ctx))); } private: void RegisterDependencies() const final { this->DependsOn(Data); } TType* Type; TMutableObjectOverBoxedValue ValuePacker; IComputationNode *const Data; }; class TUnpickleWrapper : public TMutableComputationNode { typedef TMutableComputationNode TBaseComputation; public: TUnpickleWrapper(TComputationMutables& mutables, TType* type, IComputationNode* data) : TBaseComputation(mutables) , Type(type) , ValuePacker(mutables) , Data(data) { } NUdf::TUnboxedValuePod DoCalculate(TComputationContext& ctx) const { auto data = Data->GetValue(ctx); auto buffer = data.AsStringRef(); return ValuePacker.RefMutableObject(ctx, false, Type).Unpack(buffer, ctx.HolderFactory).Release(); } private: void RegisterDependencies() const final { DependsOn(Data); } TType* const Type; TMutableObjectOverBoxedValue ValuePacker; IComputationNode *const Data; }; class TGenericPresortEncoderBoxed : public TComputationValue, public TGenericPresortEncoder { typedef TComputationValue TBase; public: TGenericPresortEncoderBoxed(TMemoryUsageInfo* memInfo, TType* type) : TBase(memInfo) , TGenericPresortEncoder(type) {} }; template class TPresortEncodeWrapper : public TMutableComputationNode> { typedef TMutableComputationNode> TBaseComputation; public: TPresortEncodeWrapper(TComputationMutables& mutables, TType* type, IComputationNode* data) : TBaseComputation(mutables) , Type(type) , Encoder(mutables) , Data(data) { } NUdf::TUnboxedValuePod DoCalculate(TComputationContext& ctx) const { return MakeString(Encoder.RefMutableObject(ctx, Type).Encode(Data->GetValue(ctx), Desc)); } private: void RegisterDependencies() const final { this->DependsOn(Data); } TType* Type; TMutableObjectOverBoxedValue Encoder; IComputationNode *const Data; }; } IComputationNode* WrapPickle(TCallable& callable, const TComputationNodeFactoryContext& ctx) { MKQL_ENSURE(callable.GetInputsCount() == 1, "Expected 1 arg"); return new TPickleWrapper(ctx.Mutables, callable.GetInput(0).GetStaticType(), LocateNode(ctx.NodeLocator, callable, 0)); } IComputationNode* WrapStablePickle(TCallable& callable, const TComputationNodeFactoryContext& ctx) { MKQL_ENSURE(callable.GetInputsCount() == 1, "Expected 1 arg"); return new TPickleWrapper(ctx.Mutables, callable.GetInput(0).GetStaticType(), LocateNode(ctx.NodeLocator, callable, 0)); } IComputationNode* WrapUnpickle(TCallable& callable, const TComputationNodeFactoryContext& ctx) { MKQL_ENSURE(callable.GetInputsCount() == 2, "Expected 2 args"); MKQL_ENSURE(callable.GetInput(0).IsImmediate() && callable.GetInput(0).GetNode()->GetType()->IsType(), "Expected type"); return new TUnpickleWrapper(ctx.Mutables, static_cast(callable.GetInput(0).GetNode()), LocateNode(ctx.NodeLocator, callable, 1)); } IComputationNode* WrapAscending(TCallable& callable, const TComputationNodeFactoryContext& ctx) { MKQL_ENSURE(callable.GetInputsCount() == 1, "Expected 1 arg"); return new TPresortEncodeWrapper(ctx.Mutables, callable.GetInput(0).GetStaticType(), LocateNode(ctx.NodeLocator, callable, 0)); } IComputationNode* WrapDescending(TCallable& callable, const TComputationNodeFactoryContext& ctx) { MKQL_ENSURE(callable.GetInputsCount() == 1, "Expected 1 arg"); return new TPresortEncodeWrapper(ctx.Mutables, callable.GetInput(0).GetStaticType(), LocateNode(ctx.NodeLocator, callable, 0)); } } }