Skip to content

Commit d4a880d

Browse files
authored
Add binary operators for block decimal (#7707)
1 parent 43e2061 commit d4a880d

File tree

21 files changed

+456
-13
lines changed

21 files changed

+456
-13
lines changed

ydb/library/yql/minikql/arrow/arrow_util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ struct TPrimitiveDataType<NYql::NUdf::TUtf8> {
173173

174174
template<>
175175
struct TPrimitiveDataType<NYql::NDecimal::TInt128> {
176+
using TLayout = NYql::NDecimal::TInt128;
176177
using TArithmetic = NYql::NDecimal::TDecimal;
177178

178179
class TResult: public arrow::FixedSizeBinaryType

ydb/library/yql/minikql/comp_nodes/mkql_block_func.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,12 @@ IComputationNode* WrapBlockFunc(TCallable& callable, const TComputationNodeFacto
7575
}
7676

7777
const TKernel& kernel = ResolveKernel(*ctx.FunctionRegistry.GetBuiltins(), funcName, argsTypes, callableType->GetReturnType());
78-
return new TBlockFuncNode(ctx.Mutables, funcName, std::move(argsNodes), argsTypes, kernel.GetArrowKernel(), {}, kernel.Family.FunctionOptions);
78+
if (kernel.IsPolymorphic()) {
79+
auto arrowKernel = kernel.MakeArrowKernel(argsTypes, callableType->GetReturnType());
80+
return new TBlockFuncNode(ctx.Mutables, funcName, std::move(argsNodes), argsTypes, *arrowKernel, arrowKernel, kernel.Family.FunctionOptions);
81+
} else {
82+
return new TBlockFuncNode(ctx.Mutables, funcName, std::move(argsNodes), argsTypes, kernel.GetArrowKernel(), {}, kernel.Family.FunctionOptions);
83+
}
7984
}
8085

8186
IComputationNode* WrapBlockBitCast(TCallable& callable, const TComputationNodeFactoryContext& ctx) {

ydb/library/yql/minikql/invoke_builtins/mkql_builtins_add.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ void RegisterAdd(TKernelFamilyMap& kernelFamilyMap) {
348348

349349
AddBinaryIntegralKernels<TAdd>(*family);
350350
AddBinaryRealKernels<TAdd>(*family);
351+
AddBinaryDecimalKernels<TDecimalAdd>(*family);
351352

352353
RegisterDateAddInterval<false, false, false>(*family);
353354
RegisterDateAddInterval<true, false, false>(*family);

ydb/library/yql/minikql/invoke_builtins/mkql_builtins_impl.cpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "mkql_builtins_impl.h" // Y_IGNORE
2+
#include <ydb/library/yql/minikql/mkql_node_builder.h> // UnpackOptionalData
23

34
namespace NKikimr {
45
namespace NMiniKQL {
@@ -70,6 +71,7 @@ arrow::compute::InputType GetPrimitiveInputArrowType(NUdf::EDataSlot slot) {
7071
case NUdf::EDataSlot::Timestamp64: return GetPrimitiveInputArrowType<i64>();
7172
case NUdf::EDataSlot::TzTimestamp64: return GetPrimitiveInputArrowType<i64>(true);
7273
case NUdf::EDataSlot::Interval64: return GetPrimitiveInputArrowType<i64>();
74+
case NUdf::EDataSlot::Decimal: return GetPrimitiveInputArrowType<NYql::NDecimal::TInt128>();
7375
default:
7476
ythrow yexception() << "Unexpected data slot: " << slot;
7577
}
@@ -104,6 +106,7 @@ arrow::compute::OutputType GetPrimitiveOutputArrowType(NUdf::EDataSlot slot) {
104106
case NUdf::EDataSlot::Timestamp64: return GetPrimitiveOutputArrowType<i64>();
105107
case NUdf::EDataSlot::TzTimestamp64: return GetPrimitiveOutputArrowType<i64>(true);
106108
case NUdf::EDataSlot::Interval64: return GetPrimitiveOutputArrowType<i64>();
109+
case NUdf::EDataSlot::Decimal: return GetPrimitiveOutputArrowType<NYql::NDecimal::TInt128>();
107110
default:
108111
ythrow yexception() << "Unexpected data slot: " << slot;
109112
}
@@ -260,6 +263,68 @@ const arrow::compute::ScalarKernel& TPlainKernel::GetArrowKernel() const {
260263
return *ArrowKernel;
261264
}
262265

266+
std::shared_ptr<arrow::compute::ScalarKernel> TPlainKernel::MakeArrowKernel(const TVector<TType*>&, TType*) const {
267+
ythrow yexception() << "Unsupported kernel";
268+
}
269+
270+
bool TPlainKernel::IsPolymorphic() const {
271+
return false;
272+
}
273+
274+
TDecimalKernel::TDecimalKernel(const TKernelFamily& family, const std::vector<NUdf::TDataTypeId>& argTypes,
275+
NUdf::TDataTypeId returnType, TStatelessArrayKernelExec exec,
276+
TKernel::ENullMode nullMode)
277+
: TKernel(family, argTypes, returnType, nullMode)
278+
, Exec(exec)
279+
{
280+
}
281+
282+
const arrow::compute::ScalarKernel& TDecimalKernel::GetArrowKernel() const {
283+
ythrow yexception() << "Unsupported kernel";
284+
}
285+
286+
std::shared_ptr<arrow::compute::ScalarKernel> TDecimalKernel::MakeArrowKernel(const TVector<TType*>& argTypes, TType* resultType) const {
287+
MKQL_ENSURE(argTypes.size() == 2, "Require 2 arguments");
288+
MKQL_ENSURE(argTypes[0]->GetKind() == TType::EKind::Block, "Require block");
289+
MKQL_ENSURE(argTypes[1]->GetKind() == TType::EKind::Block, "Require block");
290+
MKQL_ENSURE(resultType->GetKind() == TType::EKind::Block, "Require block");
291+
292+
bool isOptional = false;
293+
auto dataType1 = UnpackOptionalData(static_cast<TBlockType*>(argTypes[0])->GetItemType(), isOptional);
294+
auto dataType2 = UnpackOptionalData(static_cast<TBlockType*>(argTypes[1])->GetItemType(), isOptional);
295+
auto dataResultType = UnpackOptionalData(static_cast<TBlockType*>(resultType)->GetItemType(), isOptional);
296+
297+
MKQL_ENSURE(*dataType1->GetDataSlot() == NUdf::EDataSlot::Decimal, "Require decimal");
298+
MKQL_ENSURE(*dataType2->GetDataSlot() == NUdf::EDataSlot::Decimal, "Require decimal");
299+
MKQL_ENSURE(*dataResultType->GetDataSlot() == NUdf::EDataSlot::Decimal, "Require decimal");
300+
301+
auto decimalType1 = static_cast<TDataDecimalType*>(dataType1);
302+
auto decimalType2 = static_cast<TDataDecimalType*>(dataType2);
303+
auto decimalResultType = static_cast<TDataDecimalType*>(dataResultType);
304+
305+
MKQL_ENSURE(decimalType1->GetParams() == decimalType2->GetParams(), "Require same precision/scale");
306+
MKQL_ENSURE(decimalType1->GetParams() == decimalResultType->GetParams(), "Require same precision/scale");
307+
308+
ui8 precision = decimalType1->GetParams().first;
309+
MKQL_ENSURE(precision >= 1&& precision <= 35, TStringBuilder() << "Wrong precision: " << (int)precision);
310+
311+
auto k = std::make_shared<arrow::compute::ScalarKernel>(std::vector<arrow::compute::InputType>{
312+
GetPrimitiveInputArrowType(NUdf::EDataSlot::Decimal), GetPrimitiveInputArrowType(NUdf::EDataSlot::Decimal)
313+
}, GetPrimitiveOutputArrowType(NUdf::EDataSlot::Decimal), Exec);
314+
k->null_handling = arrow::compute::NullHandling::INTERSECTION;
315+
k->init = [precision](arrow::compute::KernelContext*, const arrow::compute::KernelInitArgs&) {
316+
auto state = std::make_unique<TDecimalKernel::TKernelState>();
317+
state->Precision = precision;
318+
return arrow::Result(std::move(state));
319+
};
320+
321+
return k;
322+
}
323+
324+
bool TDecimalKernel::IsPolymorphic() const {
325+
return true;
326+
}
327+
263328
void AddUnaryKernelImpl(TKernelFamilyBase& owner, NUdf::EDataSlot arg1, NUdf::EDataSlot res,
264329
TStatelessArrayKernelExec exec, TKernel::ENullMode nullMode) {
265330
auto type1 = NUdf::GetDataTypeInfo(arg1).TypeId;
@@ -600,5 +665,100 @@ arrow::Status ExecBinaryOptImpl(arrow::compute::KernelContext* kernelCtx,
600665
}
601666
}
602667

668+
arrow::Status ExecDecimalArrayScalarOptImpl(const arrow::compute::ExecBatch& batch, arrow::Datum* res,
669+
TUntypedBinaryArrayOptFuncPtr func) {
670+
MKQL_ENSURE(batch.values.size() == 2, "Expected 2 args");
671+
const auto& arg1 = batch.values[0];
672+
const auto& arg2 = batch.values[1];
673+
auto& resArr = *res->array();
674+
if (arg2.scalar()->is_valid) {
675+
const auto& arr1 = *arg1.array();
676+
const auto val1Ptr = arr1.buffers[1]->data();
677+
auto length = arr1.length;
678+
const auto nullCount1 = arr1.GetNullCount();
679+
const auto valid1 = (nullCount1 == 0) ? nullptr : arr1.GetValues<uint8_t>(0);
680+
const auto val2Ptr = GetStringScalarValue(*arg2.scalar());
681+
auto resPtr = resArr.buffers[1]->mutable_data();
682+
auto resValid = res->array()->GetMutableValues<uint8_t>(0);
683+
func(val1Ptr, valid1, val2Ptr.data(), nullptr, resPtr, resValid, length, arr1.offset, 0);
684+
} else {
685+
GetBitmap(resArr, 0).SetBitsTo(false);
686+
}
687+
688+
return arrow::Status::OK();
689+
}
690+
691+
arrow::Status ExecDecimalScalarArrayOptImpl(const arrow::compute::ExecBatch& batch, arrow::Datum* res,
692+
TUntypedBinaryArrayOptFuncPtr func) {
693+
MKQL_ENSURE(batch.values.size() == 2, "Expected 2 args");
694+
const auto& arg1 = batch.values[0];
695+
const auto& arg2 = batch.values[1];
696+
auto& resArr = *res->array();
697+
if (arg1.scalar()->is_valid) {
698+
const auto val1Ptr = GetStringScalarValue(*arg1.scalar());
699+
const auto& arr2 = *arg2.array();
700+
auto length = arr2.length;
701+
const auto val2Ptr = arr2.buffers[1]->data();
702+
const auto nullCount2 = arr2.GetNullCount();
703+
const auto valid2 = (nullCount2 == 0) ? nullptr : arr2.GetValues<uint8_t>(0);
704+
auto resPtr = resArr.buffers[1]->mutable_data();
705+
auto resValid = res->array()->GetMutableValues<uint8_t>(0);
706+
func(val1Ptr.data(), nullptr, val2Ptr, valid2, resPtr, resValid, length, 0, arr2.offset);
707+
} else {
708+
GetBitmap(resArr, 0).SetBitsTo(false);
709+
}
710+
711+
return arrow::Status::OK();
712+
}
713+
714+
arrow::Status ExecDecimalScalarScalarOptImpl(arrow::compute::KernelContext* kernelCtx,
715+
const arrow::compute::ExecBatch& batch, arrow::Datum* res,
716+
TPrimitiveDataTypeGetter typeGetter, TUntypedBinaryScalarOptFuncPtr func) {
717+
MKQL_ENSURE(batch.values.size() == 2, "Expected 2 args");
718+
const auto& arg1 = batch.values[0];
719+
const auto& arg2 = batch.values[1];
720+
if (!arg1.scalar()->is_valid || !arg2.scalar()->is_valid) {
721+
*res = arrow::MakeNullScalar(typeGetter());
722+
} else {
723+
const auto val1Ptr = GetStringScalarValue(*arg1.scalar());
724+
const auto val2Ptr = GetStringScalarValue(*arg2.scalar());
725+
std::shared_ptr<arrow::Buffer> buffer(ARROW_RESULT(arrow::AllocateBuffer(16, kernelCtx->memory_pool())));
726+
auto resDatum = arrow::Datum(std::make_shared<TPrimitiveDataType<NYql::NDecimal::TInt128>::TScalarResult>(buffer));
727+
if (!func(val1Ptr.data(), val2Ptr.data(), buffer->mutable_data())) {
728+
*res = arrow::MakeNullScalar(typeGetter());
729+
} else {
730+
*res = resDatum.scalar();
731+
}
732+
}
733+
734+
return arrow::Status::OK();
735+
}
736+
737+
arrow::Status ExecDecimalBinaryOptImpl(arrow::compute::KernelContext* kernelCtx,
738+
const arrow::compute::ExecBatch& batch, arrow::Datum* res,
739+
TPrimitiveDataTypeGetter typeGetter,
740+
size_t outputSizeOf,
741+
TUntypedBinaryScalarOptFuncPtr scalarScalarFunc,
742+
TUntypedBinaryArrayOptFuncPtr scalarArrayFunc,
743+
TUntypedBinaryArrayOptFuncPtr arrayScalarFunc,
744+
TUntypedBinaryArrayOptFuncPtr arrayArrayFunc) {
745+
MKQL_ENSURE(batch.values.size() == 2, "Expected 2 args");
746+
const auto& arg1 = batch.values[0];
747+
const auto& arg2 = batch.values[1];
748+
if (arg1.is_scalar()) {
749+
if (arg2.is_scalar()) {
750+
return ExecDecimalScalarScalarOptImpl(kernelCtx, batch, res, typeGetter, scalarScalarFunc);
751+
} else {
752+
return ExecDecimalScalarArrayOptImpl(batch, res, scalarArrayFunc);
753+
}
754+
} else {
755+
if (arg2.is_scalar()) {
756+
return ExecDecimalArrayScalarOptImpl(batch, res, arrayScalarFunc);
757+
} else {
758+
return ExecArrayArrayOptImpl(kernelCtx, batch, res, arrayArrayFunc, outputSizeOf, typeGetter, false, false, EPropagateTz::None);
759+
}
760+
}
761+
}
762+
603763
} // namespace NMiniKQL
604764
} // namespace NKikimr

ydb/library/yql/minikql/invoke_builtins/mkql_builtins_impl.h.txt

Lines changed: 93 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,15 @@ arrow::Status ExecBinaryOptImpl(arrow::compute::KernelContext* kernelCtx,
10121012
TUntypedBinaryArrayOptFuncPtr arrayScalarFunc,
10131013
TUntypedBinaryArrayOptFuncPtr arrayArrayFunc);
10141014

1015+
arrow::Status ExecDecimalBinaryOptImpl(arrow::compute::KernelContext* kernelCtx,
1016+
const arrow::compute::ExecBatch& batch, arrow::Datum* res,
1017+
TPrimitiveDataTypeGetter typeGetter,
1018+
size_t outputSizeOf,
1019+
TUntypedBinaryScalarOptFuncPtr scalarScalarFunc,
1020+
TUntypedBinaryArrayOptFuncPtr scalarArrayFunc,
1021+
TUntypedBinaryArrayOptFuncPtr arrayScalarFunc,
1022+
TUntypedBinaryArrayOptFuncPtr arrayArrayFunc);
1023+
10151024
template<typename TInput1, bool Tz1, typename TInput2, bool Tz2, typename TOutput, EPropagateTz PropagateTz,
10161025
typename TFuncInstance, TKernel::ENullMode NullMode>
10171026
struct TBinaryKernelExecs;
@@ -1097,9 +1106,8 @@ struct TBinaryKernelExecs<TInput1, Tz1, TInput2, Tz2, TOutput, PropagateTz, TFun
10971106
}
10981107
};
10991108

1100-
template<typename TInput1, bool Tz1, typename TInput2, bool Tz2, typename TOutput, EPropagateTz PropagateTz,
1101-
typename TFuncInstance>
1102-
struct TBinaryKernelExecs<TInput1, Tz1, TInput2, Tz2, TOutput, PropagateTz, TFuncInstance, TKernel::ENullMode::AlwaysNull>
1109+
template<typename TInput1, typename TInput2, typename TOutput, typename TFuncInstance>
1110+
struct TBinaryKernelOptExecsImpl
11031111
{
11041112
using TTypedBinaryScalarOptFuncPtr = bool(*)(
11051113
const typename TPrimitiveDataType<TInput1>::TLayout* val1Ptr,
@@ -1212,12 +1220,17 @@ struct TBinaryKernelExecs<TInput1, Tz1, TInput2, Tz2, TOutput, PropagateTz, TFun
12121220
arrow::BitUtil::ClearBit(resValid, i);
12131221
}
12141222
}
1215-
1223+
};
1224+
1225+
template<typename TInput1, bool Tz1, typename TInput2, bool Tz2, typename TOutput, EPropagateTz PropagateTz,
1226+
typename TFuncInstance>
1227+
struct TBinaryKernelExecs<TInput1, Tz1, TInput2, Tz2, TOutput, PropagateTz, TFuncInstance, TKernel::ENullMode::AlwaysNull>
1228+
{
12161229
static arrow::Status Exec(arrow::compute::KernelContext* kernelCtx, const arrow::compute::ExecBatch& batch, arrow::Datum* res) {
1217-
TTypedBinaryScalarOptFuncPtr scalarScalarFunc = &ScalarScalarCoreOpt;
1218-
TTypedBinaryArrayOptFuncPtr scalarArrayFunc = &ScalarArrayCoreOpt;
1219-
TTypedBinaryArrayOptFuncPtr arrayScalarFunc = &ArrayScalarCoreOpt;
1220-
TTypedBinaryArrayOptFuncPtr arrayArrayFunc = &ArrayArrayCoreOpt;
1230+
auto scalarScalarFunc = &TBinaryKernelOptExecsImpl<TInput1, TInput2, TOutput, TFuncInstance>::ScalarScalarCoreOpt;
1231+
auto scalarArrayFunc = &TBinaryKernelOptExecsImpl<TInput1, TInput2, TOutput, TFuncInstance>::ScalarArrayCoreOpt;
1232+
auto arrayScalarFunc = &TBinaryKernelOptExecsImpl<TInput1, TInput2, TOutput, TFuncInstance>::ArrayScalarCoreOpt;
1233+
auto arrayArrayFunc = &TBinaryKernelOptExecsImpl<TInput1, TInput2, TOutput, TFuncInstance>::ArrayArrayCoreOpt;
12211234
return ExecBinaryOptImpl(kernelCtx, batch, res,
12221235
&GetPrimitiveDataType<TOutput>,
12231236
&MakeDefaultScalarDatum<TOutput>,
@@ -1236,6 +1249,8 @@ public:
12361249
TKernel::ENullMode nullMode);
12371250

12381251
const arrow::compute::ScalarKernel& GetArrowKernel() const final;
1252+
std::shared_ptr<arrow::compute::ScalarKernel> MakeArrowKernel(const TVector<TType*>& argTypes, TType* resultType) const final;
1253+
bool IsPolymorphic() const final;
12391254

12401255
private:
12411256
const std::unique_ptr<arrow::compute::ScalarKernel> ArrowKernel;
@@ -1586,5 +1601,75 @@ void AddDateComparisonKernels(TKernelFamilyBase& owner) {
15861601
AddBinaryPredicateKernelPoly<NUdf::TDataType<NUdf::TInterval64>, NUdf::TDataType<NUdf::TInterval64>, TPred>(owner);
15871602
}
15881603

1604+
class TDecimalKernel : public TKernel {
1605+
public:
1606+
struct TKernelState : arrow::compute::KernelState {
1607+
ui8 Precision;
1608+
};
1609+
1610+
TDecimalKernel(const TKernelFamily& family, const std::vector<NUdf::TDataTypeId>& argTypes,
1611+
NUdf::TDataTypeId returnType, TStatelessArrayKernelExec exec,
1612+
TKernel::ENullMode nullMode);
1613+
1614+
const arrow::compute::ScalarKernel& GetArrowKernel() const final;
1615+
std::shared_ptr<arrow::compute::ScalarKernel> MakeArrowKernel(const TVector<TType*>& argTypes, TType* resultType) const final;
1616+
bool IsPolymorphic() const final;
1617+
1618+
private:
1619+
TStatelessArrayKernelExec Exec;
1620+
};
1621+
1622+
template<template<ui8> class TFuncInstance>
1623+
struct TDecimalKernelExecs
1624+
{
1625+
using TInput1 = NYql::NDecimal::TInt128;
1626+
using TInput2 = NYql::NDecimal::TInt128;
1627+
using TOutput = NYql::NDecimal::TInt128;
1628+
1629+
template<ui8 precision>
1630+
static arrow::Status ExecImpl(arrow::compute::KernelContext* kernelCtx, const arrow::compute::ExecBatch& batch, arrow::Datum* res) {
1631+
auto scalarScalarFunc = &TBinaryKernelOptExecsImpl<TInput1, TInput2, TOutput, TFuncInstance<precision>>::ScalarScalarCoreOpt;
1632+
auto scalarArrayFunc = &TBinaryKernelOptExecsImpl<TInput1, TInput2, TOutput, TFuncInstance<precision>>::ScalarArrayCoreOpt;
1633+
auto arrayScalarFunc = &TBinaryKernelOptExecsImpl<TInput1, TInput2, TOutput, TFuncInstance<precision>>::ArrayScalarCoreOpt;
1634+
auto arrayArrayFunc = &TBinaryKernelOptExecsImpl<TInput1, TInput2, TOutput, TFuncInstance<precision>>::ArrayArrayCoreOpt;
1635+
1636+
return ExecDecimalBinaryOptImpl(kernelCtx, batch, res,
1637+
&GetPrimitiveDataType<TOutput>,
1638+
sizeof(TOutput),
1639+
(TUntypedBinaryScalarOptFuncPtr)scalarScalarFunc,
1640+
(TUntypedBinaryArrayOptFuncPtr)scalarArrayFunc,
1641+
(TUntypedBinaryArrayOptFuncPtr)arrayScalarFunc,
1642+
(TUntypedBinaryArrayOptFuncPtr)arrayArrayFunc);
1643+
}
1644+
1645+
using ExecFunc = arrow::Status(*)(arrow::compute::KernelContext* kernelCtx, const arrow::compute::ExecBatch& batch, arrow::Datum* res) ;
1646+
1647+
template <size_t... Is>
1648+
static constexpr auto GenerateTable(std::index_sequence<Is...>) {
1649+
return std::array<ExecFunc, sizeof...(Is)>{ExecImpl<Is+1>...};
1650+
}
1651+
1652+
static arrow::Status Exec(arrow::compute::KernelContext* kernelCtx, const arrow::compute::ExecBatch& batch, arrow::Datum* res) {
1653+
ui8 precision = static_cast<TDecimalKernel::TKernelState*>(kernelCtx->state())->Precision;
1654+
Y_DEBUG_ABORT_UNLESS(precision >= 1&& precision <= 35);
1655+
1656+
static constexpr auto jumpTable = GenerateTable(std::make_index_sequence<35>{});
1657+
return jumpTable[precision-1](kernelCtx, batch, res);
1658+
}
1659+
};
1660+
1661+
1662+
template<template<ui8> class TFunc>
1663+
void AddBinaryDecimalKernels(TKernelFamilyBase& owner) {
1664+
auto type1 = NUdf::GetDataTypeInfo(NUdf::EDataSlot::Decimal).TypeId;
1665+
auto type2 = type1;
1666+
auto returnType = type1;
1667+
std::vector<NUdf::TDataTypeId> argTypes({ type1, type2 });
1668+
1669+
using Execs = TDecimalKernelExecs<TFunc>;
1670+
auto kernel = std::make_unique<TDecimalKernel>(owner, argTypes, returnType, &Execs::Exec, TKernel::ENullMode::Default);
1671+
owner.Adopt(argTypes, returnType, std::move(kernel));
1672+
}
1673+
15891674
}
15901675
}

ydb/library/yql/minikql/invoke_builtins/mkql_builtins_sub.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,7 @@ void RegisterSub(TKernelFamilyMap& kernelFamilyMap) {
481481

482482
AddBinaryIntegralKernels<TSub>(*family);
483483
AddBinaryRealKernels<TSub>(*family);
484+
AddBinaryDecimalKernels<TDecimalSub>(*family);
484485

485486
RegisterDateSub<false, false, false, false>(*family);
486487
RegisterDateSub<false, true, false, false>(*family);

ydb/library/yql/minikql/mkql_function_metadata.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <ydb/library/yql/minikql/defs.h>
4+
#include <ydb/library/yql/minikql/mkql_node.h>
45
#include <ydb/library/yql/public/udf/udf_value.h>
56
#include <util/digest/numeric.h>
67
#include <util/generic/vector.h>
@@ -89,6 +90,8 @@ class TKernel {
8990
}
9091

9192
virtual const arrow::compute::ScalarKernel& GetArrowKernel() const = 0;
93+
virtual std::shared_ptr<arrow::compute::ScalarKernel> MakeArrowKernel(const TVector<TType*>& argTypes, TType* resultType) const = 0;
94+
virtual bool IsPolymorphic() const = 0;
9295

9396
virtual ~TKernel() = default;
9497
};

ydb/library/yql/public/udf/udf_value.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,7 @@ friend class TUnboxedValue;
808808
inline bool IsEmbedded() const { return EMarkers::Embedded == Raw.GetMarkers(); }
809809

810810
// Data accessors
811-
template <typename T, typename = std::enable_if_t<TPrimitiveDataType<T>::Result>>
811+
template <typename T, typename = std::enable_if_t<TPrimitiveDataType<T>::Result || std::is_same_v<T, NYql::NDecimal::TInt128>>>
812812
inline T Get() const;
813813
template <typename T, typename = std::enable_if_t<TPrimitiveDataType<T>::Result>>
814814
inline T GetOrDefault(T ifEmpty) const;

0 commit comments

Comments
 (0)