mkql_next_value.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #include "mkql_next_value.h"
  2. #include <yql/essentials/minikql/computation/mkql_computation_node_holders.h>
  3. #include <yql/essentials/minikql/computation/presort.h>
  4. #include <yql/essentials/minikql/mkql_node_cast.h>
  5. #include <yql/essentials/minikql/mkql_node_builder.h>
  6. #include <yql/essentials/minikql/mkql_type_builder.h>
  7. #include <yql/essentials/minikql/mkql_string_util.h>
  8. #include <yql/essentials/public/udf/udf_data_type.h>
  9. #include <yql/essentials/utils/utf8.h>
  10. #include <algorithm>
  11. namespace NKikimr {
  12. namespace NMiniKQL {
  13. using namespace NYql::NUdf;
  14. namespace {
  15. class TNextValueStringWrapper : public TMutableComputationNode<TNextValueStringWrapper> {
  16. using TSelf = TNextValueStringWrapper;
  17. using TBase = TMutableComputationNode<TSelf>;
  18. typedef TBase TBaseComputation;
  19. public:
  20. TNextValueStringWrapper(TComputationMutables& mutables, IComputationNode* source, EDataSlot slot)
  21. : TBaseComputation(mutables)
  22. , Source(source)
  23. , Slot(slot)
  24. {
  25. }
  26. NUdf::TUnboxedValuePod DoCalculate(TComputationContext& ctx) const {
  27. TUnboxedValue input = Source->GetValue(ctx);
  28. const auto& inputStr = input.AsStringRef();
  29. auto output = (Slot == EDataSlot::Utf8) ? NYql::NextValidUtf8(inputStr) : NYql::NextLexicographicString(inputStr);
  30. if (!output) {
  31. return {};
  32. }
  33. return MakeString(*output);
  34. }
  35. private:
  36. void RegisterDependencies() const final {
  37. this->DependsOn(Source);
  38. }
  39. IComputationNode* const Source;
  40. const EDataSlot Slot;
  41. };
  42. } // namespace
  43. IComputationNode* WrapNextValue(TCallable& callable, const TComputationNodeFactoryContext& ctx) {
  44. MKQL_ENSURE(callable.GetInputsCount() == 1, "Expecting exactly one argument");
  45. auto type = callable.GetInput(0).GetStaticType();
  46. MKQL_ENSURE(type->IsData(), "Expecting Data as argument");
  47. auto returnType = callable.GetType()->GetReturnType();
  48. MKQL_ENSURE(returnType->IsOptional(), "Expecting Optional as return type");
  49. auto targetType = static_cast<TOptionalType*>(returnType)->GetItemType();
  50. MKQL_ENSURE(targetType->IsData(), "Expecting Optional of Data as return type");
  51. auto from = GetDataSlot(static_cast<TDataType*>(type)->GetSchemeType());
  52. auto to = GetDataSlot(static_cast<TDataType*>(targetType)->GetSchemeType());
  53. MKQL_ENSURE(from == to, "Input/output should have the same Data slot");
  54. MKQL_ENSURE(from == EDataSlot::String || from == EDataSlot::Utf8, "Only String or Utf8 is supported");
  55. auto source = LocateNode(ctx.NodeLocator, callable, 0);
  56. return new TNextValueStringWrapper(ctx.Mutables, source, from);
  57. }
  58. }
  59. }