mkql_dynamic_variant.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #include "mkql_dynamic_variant.h"
  2. #include <yql/essentials/minikql/computation/mkql_computation_node_impl.h>
  3. #include <yql/essentials/minikql/computation/mkql_computation_node_holders.h>
  4. #include <yql/essentials/minikql/mkql_node_cast.h>
  5. #include <yql/essentials/minikql/mkql_node_builder.h>
  6. namespace NKikimr {
  7. namespace NMiniKQL {
  8. namespace {
  9. template <typename TDerived>
  10. class TDynamicVariantBaseWrapper : public TMutableComputationNode<TDerived> {
  11. public:
  12. using TBase = TMutableComputationNode<TDerived>;
  13. TDynamicVariantBaseWrapper(TComputationMutables& mutables, IComputationNode* item,
  14. IComputationNode* index)
  15. : TBase(mutables)
  16. , Item(item)
  17. , Index(index)
  18. {}
  19. private:
  20. void RegisterDependencies() const final {
  21. this->DependsOn(Item);
  22. this->DependsOn(Index);
  23. }
  24. protected:
  25. IComputationNode* const Item;
  26. IComputationNode* const Index;
  27. };
  28. class TDynamicVariantTupleWrapper : public TDynamicVariantBaseWrapper<TDynamicVariantTupleWrapper> {
  29. public:
  30. using TBase = TDynamicVariantBaseWrapper<TDynamicVariantTupleWrapper>;
  31. TDynamicVariantTupleWrapper(TComputationMutables& mutables, IComputationNode* item,
  32. IComputationNode* index, TVariantType* varType)
  33. : TBase(mutables, item, index)
  34. , AltCounts(varType->GetAlternativesCount())
  35. {}
  36. NUdf::TUnboxedValuePod DoCalculate(TComputationContext& ctx) const {
  37. auto indexValue = Index->GetValue(ctx);
  38. if (!indexValue || indexValue.Get<ui32>() >= AltCounts) {
  39. return {};
  40. }
  41. NUdf::TUnboxedValuePod item = Item->GetValue(ctx).Release();
  42. NUdf::TUnboxedValuePod var = ctx.HolderFactory.CreateVariantHolder(item, indexValue.Get<ui32>());
  43. return var.MakeOptional();
  44. }
  45. private:
  46. const ui32 AltCounts;
  47. };
  48. class TDynamicVariantStructWrapper : public TDynamicVariantBaseWrapper<TDynamicVariantStructWrapper> {
  49. public:
  50. using TBase = TDynamicVariantBaseWrapper<TDynamicVariantStructWrapper>;
  51. TDynamicVariantStructWrapper(TComputationMutables& mutables, IComputationNode* item,
  52. IComputationNode* index, TVariantType* varType)
  53. : TBase(mutables, item, index)
  54. , Fields(MakeFields(varType))
  55. {}
  56. NUdf::TUnboxedValuePod DoCalculate(TComputationContext& ctx) const {
  57. auto indexValue = Index->GetValue(ctx);
  58. if (!indexValue) {
  59. return {};
  60. }
  61. TStringBuf indexStr = indexValue.AsStringRef();
  62. auto ptr = Fields.FindPtr(indexStr);
  63. if (!ptr) {
  64. return {};
  65. }
  66. NUdf::TUnboxedValuePod item = Item->GetValue(ctx).Release();
  67. NUdf::TUnboxedValuePod var = ctx.HolderFactory.CreateVariantHolder(item, *ptr);
  68. return var.MakeOptional();
  69. }
  70. private:
  71. static THashMap<TStringBuf, ui32> MakeFields(TVariantType* varType) {
  72. THashMap<TStringBuf, ui32> res;
  73. auto structType = AS_TYPE(TStructType, varType->GetUnderlyingType());
  74. for (ui32 i = 0; i < structType->GetMembersCount(); ++i) {
  75. res[structType->GetMemberName(i)] = i;
  76. }
  77. return res;
  78. }
  79. private:
  80. const THashMap<TStringBuf, ui32> Fields;
  81. };
  82. }
  83. IComputationNode* WrapDynamicVariant(TCallable& callable, const TComputationNodeFactoryContext& ctx) {
  84. MKQL_ENSURE(callable.GetInputsCount() == 3, "Expected 3 arguments");
  85. const auto item = LocateNode(ctx.NodeLocator, callable, 0);
  86. const auto index = LocateNode(ctx.NodeLocator, callable, 1);
  87. const auto varTypeNode = callable.GetInput(2);
  88. MKQL_ENSURE(varTypeNode.IsImmediate() && varTypeNode.GetStaticType()->IsType(), "Expected immediate type");
  89. const auto varType = AS_TYPE(TVariantType, static_cast<TType*>(varTypeNode.GetNode()));
  90. if (varType->GetUnderlyingType()->IsTuple()) {
  91. return new TDynamicVariantTupleWrapper(ctx.Mutables, item, index, varType);
  92. } else {
  93. return new TDynamicVariantStructWrapper(ctx.Mutables, item, index, varType);
  94. }
  95. return nullptr;
  96. }
  97. }
  98. }