#include "mkql_next_value.h" #include #include #include #include #include #include #include #include #include namespace NKikimr { namespace NMiniKQL { using namespace NYql::NUdf; namespace { class TNextValueStringWrapper : public TMutableComputationNode { using TSelf = TNextValueStringWrapper; using TBase = TMutableComputationNode; typedef TBase TBaseComputation; public: TNextValueStringWrapper(TComputationMutables& mutables, IComputationNode* source, EDataSlot slot) : TBaseComputation(mutables) , Source(source) , Slot(slot) { } NUdf::TUnboxedValuePod DoCalculate(TComputationContext& ctx) const { TUnboxedValue input = Source->GetValue(ctx); const auto& inputStr = input.AsStringRef(); auto output = (Slot == EDataSlot::Utf8) ? NYql::NextValidUtf8(inputStr) : NYql::NextLexicographicString(inputStr); if (!output) { return {}; } return MakeString(*output); } private: void RegisterDependencies() const final { this->DependsOn(Source); } IComputationNode* const Source; const EDataSlot Slot; }; } // namespace IComputationNode* WrapNextValue(TCallable& callable, const TComputationNodeFactoryContext& ctx) { MKQL_ENSURE(callable.GetInputsCount() == 1, "Expecting exactly one argument"); auto type = callable.GetInput(0).GetStaticType(); MKQL_ENSURE(type->IsData(), "Expecting Data as argument"); auto returnType = callable.GetType()->GetReturnType(); MKQL_ENSURE(returnType->IsOptional(), "Expecting Optional as return type"); auto targetType = static_cast(returnType)->GetItemType(); MKQL_ENSURE(targetType->IsData(), "Expecting Optional of Data as return type"); auto from = GetDataSlot(static_cast(type)->GetSchemeType()); auto to = GetDataSlot(static_cast(targetType)->GetSchemeType()); MKQL_ENSURE(from == to, "Input/output should have the same Data slot"); MKQL_ENSURE(from == EDataSlot::String || from == EDataSlot::Utf8, "Only String or Utf8 is supported"); auto source = LocateNode(ctx.NodeLocator, callable, 0); return new TNextValueStringWrapper(ctx.Mutables, source, from); } } }