mkql_tobytes.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #include "mkql_tobytes.h"
  2. #include <yql/essentials/minikql/computation/mkql_computation_node_codegen.h> // Y_IGNORE
  3. #include <yql/essentials/minikql/mkql_node_cast.h>
  4. #include <yql/essentials/minikql/mkql_node_builder.h>
  5. #include <yql/essentials/minikql/mkql_string_util.h>
  6. #include <yql/essentials/utils/swap_bytes.h>
  7. namespace NKikimr {
  8. namespace NMiniKQL {
  9. namespace {
  10. template<bool IsOptional, typename Type>
  11. class TToBytesPrimitiveTypeWrapper : public TDecoratorCodegeneratorNode<TToBytesPrimitiveTypeWrapper<IsOptional, Type>> {
  12. using TBaseComputation = TDecoratorCodegeneratorNode<TToBytesPrimitiveTypeWrapper<IsOptional, Type>>;
  13. public:
  14. TToBytesPrimitiveTypeWrapper(IComputationNode* data)
  15. : TBaseComputation(data)
  16. {}
  17. NUdf::TUnboxedValuePod DoCalculate(TComputationContext&, const NUdf::TUnboxedValuePod& value) const {
  18. if (IsOptional && !value)
  19. return NUdf::TUnboxedValuePod();
  20. const auto& v = value.Get<Type>();
  21. return NUdf::TUnboxedValuePod::Embedded(NUdf::TStringRef(reinterpret_cast<const char*>(&v), sizeof(v)));
  22. }
  23. #ifndef MKQL_DISABLE_CODEGEN
  24. Value* DoGenerateGetValue(const TCodegenContext& ctx, Value* value, BasicBlock*& block) const {
  25. const uint64_t one[] = {0ULL, sizeof(Type) << 48ULL};
  26. const auto size = ConstantInt::get(value->getType(), APInt(128, 2, one));
  27. const uint64_t two[] = {0xFFFFFFFFFFFFFFFFULL, 0xFF00FFFFFFFFFFFFULL};
  28. const auto mask = ConstantInt::get(value->getType(), APInt(128, 2, two));
  29. const auto result = BinaryOperator::CreateOr(BinaryOperator::CreateAnd(value, mask, "and", block), size, "or", block);
  30. if constexpr (IsOptional)
  31. return SelectInst::Create(IsExists(value, block), result, GetEmpty(ctx.Codegen.GetContext()), "select", block);
  32. return result;
  33. }
  34. #endif
  35. };
  36. template<bool IsOptional>
  37. class TToBytesDecimalWrapper : public TMutableComputationNode<TToBytesDecimalWrapper<IsOptional>> {
  38. using TBaseComputation = TMutableComputationNode<TToBytesDecimalWrapper<IsOptional>>;
  39. public:
  40. TToBytesDecimalWrapper(TComputationMutables& mutables, IComputationNode* data)
  41. : TBaseComputation(mutables, EValueRepresentation::String)
  42. , Data(data)
  43. {}
  44. NUdf::TUnboxedValuePod DoCalculate(TComputationContext& ctx) const {
  45. const auto& value = this->Data->GetValue(ctx);
  46. if (IsOptional && !value)
  47. return NUdf::TUnboxedValuePod();
  48. return MakeString(NUdf::TStringRef(reinterpret_cast<const char*>(&value), 15));
  49. }
  50. void RegisterDependencies() const final {
  51. this->DependsOn(Data);
  52. }
  53. IComputationNode* const Data;
  54. };
  55. template<bool IsOptional, typename Type>
  56. class TToBytesTzTypeWrapper : public TDecoratorComputationNode<TToBytesTzTypeWrapper<IsOptional, Type>> {
  57. using TBaseComputation = TDecoratorComputationNode<TToBytesTzTypeWrapper<IsOptional, Type>>;
  58. public:
  59. TToBytesTzTypeWrapper(IComputationNode* data)
  60. : TBaseComputation(data)
  61. {}
  62. NUdf::TUnboxedValuePod DoCalculate(TComputationContext&, const NUdf::TUnboxedValuePod& value) const {
  63. if (IsOptional && !value)
  64. return NUdf::TUnboxedValuePod();
  65. const auto v = NYql::SwapBytes(value.Get<Type>());
  66. const auto tzId = NYql::SwapBytes(value.GetTimezoneId());
  67. char buf[sizeof(Type) + sizeof(ui16)];
  68. std::memcpy(buf, &v, sizeof(v));
  69. std::memcpy(buf + sizeof(Type), &tzId, sizeof(tzId));
  70. return NUdf::TUnboxedValuePod::Embedded(NUdf::TStringRef(buf, sizeof(buf)));
  71. }
  72. };
  73. class TToBytesWrapper : public TDecoratorCodegeneratorNode<TToBytesWrapper> {
  74. using TBaseComputation = TDecoratorCodegeneratorNode<TToBytesWrapper>;
  75. public:
  76. TToBytesWrapper(IComputationNode* optional)
  77. : TBaseComputation(optional)
  78. {}
  79. NUdf::TUnboxedValuePod DoCalculate(TComputationContext&, const NUdf::TUnboxedValuePod& value) const { return value; }
  80. #ifndef MKQL_DISABLE_CODEGEN
  81. Value* DoGenerateGetValue(const TCodegenContext&, Value* value, BasicBlock*&) const { return value; }
  82. #endif
  83. };
  84. }
  85. IComputationNode* WrapToBytes(TCallable& callable, const TComputationNodeFactoryContext& ctx) {
  86. MKQL_ENSURE(callable.GetInputsCount() == 1, "Expected 1 arg");
  87. bool isOptional;
  88. const auto dataType = UnpackOptionalData(callable.GetInput(0), isOptional);
  89. const auto data = LocateNode(ctx.NodeLocator, callable, 0);
  90. switch(dataType->GetSchemeType()) {
  91. #define MAKE_PRIMITIVE_TYPE_BYTES(type, layout) \
  92. case NUdf::TDataType<type>::Id: \
  93. if (isOptional) \
  94. return new TToBytesPrimitiveTypeWrapper<true, layout>(data); \
  95. else \
  96. return new TToBytesPrimitiveTypeWrapper<false, layout>(data);
  97. KNOWN_FIXED_VALUE_TYPES(MAKE_PRIMITIVE_TYPE_BYTES)
  98. #undef MAKE_PRIMITIVE_TYPE_BYTES
  99. #define MAKE_TZ_TYPE_BYTES(type, layout) \
  100. case NUdf::TDataType<type>::Id: \
  101. if (isOptional) \
  102. return new TToBytesTzTypeWrapper<true, layout>(data); \
  103. else \
  104. return new TToBytesTzTypeWrapper<false, layout>(data);
  105. MAKE_TZ_TYPE_BYTES(NUdf::TTzDate, ui16);
  106. MAKE_TZ_TYPE_BYTES(NUdf::TTzDatetime, ui32);
  107. MAKE_TZ_TYPE_BYTES(NUdf::TTzTimestamp, ui64);
  108. MAKE_TZ_TYPE_BYTES(NUdf::TTzDate32, i32);
  109. MAKE_TZ_TYPE_BYTES(NUdf::TTzDatetime64, i64);
  110. MAKE_TZ_TYPE_BYTES(NUdf::TTzTimestamp64, i64);
  111. #undef MAKE_TZ_TYPE_BYTES
  112. case NUdf::TDataType<NUdf::TDecimal>::Id: {
  113. if (isOptional) \
  114. return new TToBytesDecimalWrapper<true>(ctx.Mutables, data);
  115. else
  116. return new TToBytesDecimalWrapper<false>(ctx.Mutables, data);
  117. }
  118. default:
  119. break;
  120. }
  121. return new TToBytesWrapper(data);
  122. }
  123. }
  124. }