mkql_weakmember.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #include "mkql_fromyson.h"
  2. #include <library/cpp/yson/varint.h>
  3. #include <library/cpp/yson/detail.h>
  4. #include <yql/essentials/minikql/computation/mkql_computation_node_holders.h>
  5. #include <yql/essentials/minikql/mkql_node_cast.h>
  6. #include <yql/essentials/minikql/mkql_node_builder.h>
  7. #include <yql/essentials/minikql/mkql_string_util.h>
  8. #include <yql/essentials/minikql/mkql_unboxed_value_stream.h>
  9. namespace NKikimr {
  10. namespace NMiniKQL {
  11. namespace {
  12. class TTryWeakMemberFromDictWrapper : public TMutableComputationNode<TTryWeakMemberFromDictWrapper> {
  13. typedef TMutableComputationNode<TTryWeakMemberFromDictWrapper> TBaseComputation;
  14. public:
  15. TTryWeakMemberFromDictWrapper(TComputationMutables& mutables, IComputationNode* otherDict, IComputationNode* restDict, NUdf::TDataTypeId schemeType,
  16. NUdf::TUnboxedValue&& memberName, NUdf::TUnboxedValue&& otherIsStrMemberName)
  17. : TBaseComputation(mutables)
  18. , OtherDict(otherDict)
  19. , RestDict(restDict)
  20. , SchemeType(NUdf::GetDataSlot(schemeType))
  21. , MemberName(std::move(memberName))
  22. , OtherIsStringMemberName(std::move(otherIsStrMemberName))
  23. {
  24. }
  25. NUdf::TUnboxedValuePod DoCalculate(TComputationContext& ctx) const {
  26. if (const auto& restDict = RestDict->GetValue(ctx)) {
  27. if (const auto& tryMember = restDict.Lookup(MemberName)) {
  28. return SimpleValueFromYson(SchemeType, tryMember.AsStringRef());
  29. }
  30. }
  31. if (const auto& otherDict = OtherDict->GetValue(ctx)) {
  32. if (auto tryMember = otherDict.Lookup(MemberName)) {
  33. const bool isString = otherDict.Contains(OtherIsStringMemberName);
  34. if (isString) {
  35. if (SchemeType == NUdf::EDataSlot::Yson) {
  36. const auto& ref = tryMember.AsStringRef();
  37. const auto size = ref.Size();
  38. MKQL_ENSURE(size <= std::numeric_limits<i32>::max(), "TryWeakMemberFromDict: Unable to fit string to i32");
  39. TUnboxedValueStream stringStream;
  40. stringStream.DoWrite(&NYson::NDetail::StringMarker, 1);
  41. NYson::WriteVarInt32(&stringStream, size);
  42. stringStream.DoWrite(ref.Data(), size);
  43. return stringStream.Value();
  44. } else if (SchemeType == NUdf::EDataSlot::String) {
  45. return tryMember.Release();
  46. } else {
  47. return {};
  48. }
  49. } else {
  50. return SimpleValueFromYson(SchemeType, tryMember.AsStringRef());
  51. }
  52. }
  53. }
  54. return NUdf::TUnboxedValuePod();
  55. }
  56. private:
  57. void RegisterDependencies() const final {
  58. DependsOn(OtherDict);
  59. DependsOn(RestDict);
  60. }
  61. IComputationNode* const OtherDict;
  62. IComputationNode* const RestDict;
  63. const NUdf::EDataSlot SchemeType;
  64. const NUdf::TUnboxedValue MemberName;
  65. const NUdf::TUnboxedValue OtherIsStringMemberName;
  66. };
  67. }
  68. IComputationNode* WrapTryWeakMemberFromDict(TCallable& callable, const TComputationNodeFactoryContext& ctx) {
  69. MKQL_ENSURE(callable.GetInputsCount() == 4, "Expected 4 args");
  70. auto otherType = AS_TYPE(TOptionalType, callable.GetInput(0));
  71. auto otherDictType = AS_TYPE(TDictType, otherType->GetItemType());
  72. auto otherDictKeyType = AS_TYPE(TDataType, otherDictType->GetKeyType());
  73. auto otherDictPayloadType = AS_TYPE(TDataType, otherDictType->GetPayloadType());
  74. MKQL_ENSURE(otherDictKeyType->GetSchemeType() == NUdf::TDataType<char*>::Id, "Expected String");
  75. MKQL_ENSURE(otherDictPayloadType->GetSchemeType() == NUdf::TDataType<char*>::Id, "Expected String");
  76. auto restType = AS_TYPE(TOptionalType, callable.GetInput(1));
  77. auto restDictType = AS_TYPE(TDictType, restType->GetItemType());
  78. auto restDictKeyType = AS_TYPE(TDataType, restDictType->GetKeyType());
  79. auto restDictPayloadType = AS_TYPE(TDataType, restDictType->GetPayloadType());
  80. MKQL_ENSURE(restDictKeyType->GetSchemeType() == NUdf::TDataType<char*>::Id, "Expected String");
  81. MKQL_ENSURE(restDictPayloadType->GetSchemeType() == NUdf::TDataType<NUdf::TYson>::Id, "Expected String");
  82. TDataLiteral* schemeTypeData = AS_VALUE(TDataLiteral, callable.GetInput(2));
  83. auto schemeType = schemeTypeData->AsValue().Get<ui32>();
  84. auto memberNameValue = AS_VALUE(TDataLiteral, callable.GetInput(3));
  85. const TString memberName(memberNameValue->AsValue().AsStringRef());
  86. auto otherDict = LocateNode(ctx.NodeLocator, callable, 0);
  87. auto restDict = LocateNode(ctx.NodeLocator, callable, 1);
  88. auto memberNameStr = MakeString(memberName);
  89. auto otherIsStringMemberNameStr = MakeString("_yql_" + memberName);
  90. return new TTryWeakMemberFromDictWrapper(ctx.Mutables, otherDict, restDict, static_cast<NUdf::TDataTypeId>(schemeType),
  91. std::move(memberNameStr), std::move(otherIsStringMemberNameStr));
  92. }
  93. }
  94. }