mkql_builtins_sub.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. #include "mkql_builtins_impl.h" // Y_IGNORE
  2. #include "mkql_builtins_datetime.h"
  3. #include "mkql_builtins_decimal.h" // Y_IGNORE
  4. #include <yql/essentials/minikql/mkql_type_ops.h>
  5. namespace NKikimr {
  6. namespace NMiniKQL {
  7. namespace {
  8. template<typename TLeft, typename TRight, typename TOutput>
  9. struct TSub : public TSimpleArithmeticBinary<TLeft, TRight, TOutput, TSub<TLeft, TRight, TOutput>> {
  10. static constexpr auto NullMode = TKernel::ENullMode::Default;
  11. static TOutput Do(TOutput left, TOutput right)
  12. {
  13. return left - right;
  14. }
  15. #ifndef MKQL_DISABLE_CODEGEN
  16. static Value* Gen(Value* left, Value* right, const TCodegenContext&, BasicBlock*& block)
  17. {
  18. return std::is_integral<TOutput>() ? BinaryOperator::CreateSub(left, right, "sub", block) : BinaryOperator::CreateFSub(left, right, "sub", block);
  19. }
  20. #endif
  21. };
  22. template<ui8 Precision>
  23. struct TDecimalSub {
  24. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& left, const NUdf::TUnboxedValuePod& right) {
  25. const auto l = left.GetInt128();
  26. const auto r = right.GetInt128();
  27. const auto s = l - r;
  28. using namespace NYql::NDecimal;
  29. if (IsNormal<Precision>(l) && IsNormal<Precision>(r) && IsNormal<Precision>(s))
  30. return NUdf::TUnboxedValuePod(s);
  31. if (IsNan(l) || IsNan(r) || !s)
  32. return NUdf::TUnboxedValuePod(Nan());
  33. else
  34. return NUdf::TUnboxedValuePod(s > 0 ? +Inf() : -Inf());
  35. }
  36. #ifndef MKQL_DISABLE_CODEGEN
  37. static Value* Generate(Value* left, Value* right, const TCodegenContext& ctx, BasicBlock*& block)
  38. {
  39. auto& context = ctx.Codegen.GetContext();
  40. const auto& bounds = NDecimal::GenBounds<Precision>(context);
  41. const auto l = GetterForInt128(left, block);
  42. const auto r = GetterForInt128(right, block);
  43. const auto sub = BinaryOperator::CreateSub(l, r, "sub", block);
  44. const auto lok = NDecimal::GenInBounds(l, bounds.first, bounds.second, block);
  45. const auto rok = NDecimal::GenInBounds(r, bounds.first, bounds.second, block);
  46. const auto sok = NDecimal::GenInBounds(sub, bounds.first, bounds.second, block);
  47. const auto bok = BinaryOperator::CreateAnd(lok, rok, "bok", block);
  48. const auto ok = BinaryOperator::CreateAnd(sok, bok, "ok", block);
  49. const auto bads = BasicBlock::Create(context, "bads", ctx.Func);
  50. const auto infs = BasicBlock::Create(context, "infs", ctx.Func);
  51. const auto done = BasicBlock::Create(context, "done", ctx.Func);
  52. const auto result = PHINode::Create(sub->getType(), 3, "result", done);
  53. result->addIncoming(sub, block);
  54. BranchInst::Create(done, bads, ok, block);
  55. block = bads;
  56. const auto lnan = NDecimal::GenIsNonComparable(l, context, block);
  57. const auto rnan = NDecimal::GenIsNonComparable(r, context, block);
  58. const auto anan = BinaryOperator::CreateOr(lnan, rnan, "anan", block);
  59. const auto null = ConstantInt::get(sub->getType(), 0);
  60. const auto zero = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_EQ, sub, null, "zero", block);
  61. const auto nan = BinaryOperator::CreateOr(anan, zero, "nan", block);
  62. result->addIncoming(GetDecimalNan(context), block);
  63. BranchInst::Create(done, infs, nan, block);
  64. block = infs;
  65. const auto plus = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SGT, sub, null, "plus", block);
  66. const auto inf = SelectInst::Create(plus, GetDecimalPlusInf(context), GetDecimalMinusInf(context), "inf", block);
  67. result->addIncoming(inf, block);
  68. BranchInst::Create(done, block);
  69. block = done;
  70. return SetterForInt128(result, block);
  71. }
  72. #endif
  73. static_assert(Precision <= NYql::NDecimal::MaxPrecision, "Too large precision!");
  74. };
  75. template<typename TLeft, typename TRight, typename TOutput>
  76. struct TDateTimeSub : public TSimpleArithmeticBinary<typename TLeft::TLayout, typename TRight::TLayout, typename TOutput::TLayout, TDateTimeSub<TLeft, TRight, TOutput>, true>{
  77. static constexpr auto NullMode = TKernel::ENullMode::Default;
  78. static_assert(TOutput::Features & NYql::NUdf::TimeIntervalType, "Interval type expected");
  79. static typename TOutput::TLayout Do(typename TLeft::TLayout left, typename TRight::TLayout right)
  80. {
  81. return ToScaledDate<TLeft>(left) - ToScaledDate<TRight>(right);
  82. }
  83. #ifndef MKQL_DISABLE_CODEGEN
  84. static Value* Gen(Value* left, Value* right, const TCodegenContext& ctx, BasicBlock*& block)
  85. {
  86. auto& context = ctx.Codegen.GetContext();
  87. const auto lhs = GenToScaledDate<TLeft>(left, context, block);
  88. const auto rhs = GenToScaledDate<TRight>(right, context, block);
  89. const auto sub = BinaryOperator::CreateSub(lhs, rhs, "sub", block);
  90. return sub;
  91. }
  92. #endif
  93. };
  94. template<typename TLeft, typename TRight, typename TOutput>
  95. struct TIntervalSubInterval {
  96. static_assert(TLeft::Features & NYql::NUdf::TimeIntervalType, "Left must be interval type");
  97. static_assert(TRight::Features & NYql::NUdf::TimeIntervalType, "Right must be interval type");
  98. static_assert(TOutput::Features & NYql::NUdf::TimeIntervalType, "Output must be interval type");
  99. static constexpr auto NullMode = TKernel::ENullMode::AlwaysNull;
  100. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& left, const NUdf::TUnboxedValuePod& right)
  101. {
  102. const auto lv = left.template Get<typename TLeft::TLayout>();
  103. const auto rv = right.template Get<typename TRight::TLayout>();
  104. const auto ret = lv - rv;
  105. return IsBadInterval<TOutput>(ret) ? NUdf::TUnboxedValuePod() : NUdf::TUnboxedValuePod(ret);
  106. }
  107. #ifndef MKQL_DISABLE_CODEGEN
  108. static Value* Generate(Value* left, Value* right, const TCodegenContext& ctx, BasicBlock*& block)
  109. {
  110. auto& context = ctx.Codegen.GetContext();
  111. const auto lhs = GetterFor<typename TLeft::TLayout>(left, context, block);
  112. const auto rhs = GetterFor<typename TRight::TLayout>(right, context, block);
  113. const auto sub = BinaryOperator::CreateSub(lhs, rhs, "sub", block);
  114. const auto full = SetterFor<typename TOutput::TLayout>(sub, context, block);
  115. const auto bad = GenIsBadInterval<TOutput>(sub, context, block);
  116. const auto zero = ConstantInt::get(Type::getInt128Ty(context), 0);
  117. const auto sel = SelectInst::Create(bad, zero, full, "sel", block);
  118. return sel;
  119. }
  120. #endif
  121. };
  122. template<typename TLeft, typename TRight, typename TOutput>
  123. struct TBigIntervalSub {
  124. static_assert(std::is_same_v<typename TLeft::TLayout, i64>, "Left must be i64");
  125. static_assert(std::is_same_v<typename TRight::TLayout, i64>, "Right must be i64");
  126. static_assert(std::is_same_v<typename TOutput::TLayout, i64>, "Output must be i64");
  127. static constexpr auto NullMode = TKernel::ENullMode::AlwaysNull;
  128. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& left, const NUdf::TUnboxedValuePod& right)
  129. {
  130. i64 lv = left.Get<i64>();
  131. i64 rv = right.Get<i64>();
  132. i64 ret = lv - rv;
  133. // detect overflow
  134. if (lv > 0 && rv < 0 && ret < 0) {
  135. return NUdf::TUnboxedValuePod();
  136. } else if (lv < 0 && rv > 0 && ret > 0) {
  137. return NUdf::TUnboxedValuePod();
  138. } else if (IsBadInterval<NUdf::TDataType<NUdf::TInterval64>>(ret)) {
  139. return NUdf::TUnboxedValuePod();
  140. }
  141. return NUdf::TUnboxedValuePod(ret);
  142. }
  143. #ifndef MKQL_DISABLE_CODEGEN
  144. static Value* Generate(Value* left, Value* right, const TCodegenContext& ctx, BasicBlock*& block)
  145. {
  146. auto& context = ctx.Codegen.GetContext();
  147. const auto lhs = GetterFor<i64>(left, context, block);
  148. const auto rhs = GetterFor<i64>(right, context, block);
  149. const auto sub = BinaryOperator::CreateSub(lhs, rhs, "sub", block);
  150. const auto wide = SetterFor<i64>(sub, context, block);
  151. const auto lneg = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SLT, lhs, ConstantInt::get(lhs->getType(), 0), "lneg", block);
  152. const auto rpos = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SGT, rhs, ConstantInt::get(rhs->getType(), 0), "rpos", block);
  153. const auto apos = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SGT, sub, ConstantInt::get(sub->getType(), 0), "apos", block);
  154. const auto npp = BinaryOperator::CreateAnd(apos, BinaryOperator::CreateAnd(lneg, rpos, "np", block), "npp", block);
  155. const auto lpos = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SGT, lhs, ConstantInt::get(lhs->getType(), 0), "lpos", block);
  156. const auto rneg = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SLT, rhs, ConstantInt::get(rhs->getType(), 0), "rneg", block);
  157. const auto aneg = CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_SLT, sub, ConstantInt::get(sub->getType(), 0), "aneg", block);
  158. const auto pnn = BinaryOperator::CreateAnd(aneg, BinaryOperator::CreateAnd(lpos, rneg, "pn", block), "pnn", block);
  159. const auto bad = BinaryOperator::CreateOr(
  160. BinaryOperator::CreateOr(npp, pnn, "overflow", block),
  161. GenIsBadInterval<NUdf::TDataType<NUdf::TInterval64>>(sub, context, block),
  162. "bad", block);
  163. const auto zero = ConstantInt::get(Type::getInt128Ty(context), 0);
  164. const auto sel = SelectInst::Create(bad, zero, wide, "sel", block);
  165. return sel;
  166. }
  167. #endif
  168. };
  169. template<typename TLeft, typename TRight, typename TOutput, bool Tz>
  170. struct TAnyDateTimeSubIntervalT {
  171. static_assert(TRight::Features & NYql::NUdf::TimeIntervalType, "right must be interval type");
  172. static_assert(std::is_same<TLeft, TOutput>::value, "left and output must be same");
  173. static constexpr auto NullMode = TKernel::ENullMode::AlwaysNull;
  174. static NUdf::TUnboxedValuePod Execute(const NUdf::TUnboxedValuePod& left, const NUdf::TUnboxedValuePod& right)
  175. {
  176. const auto lv = ToScaledDate<TLeft>(left.template Get<typename TLeft::TLayout>());
  177. const auto rv = ToScaledDate<TRight>(right.template Get<typename TRight::TLayout>());
  178. const auto ret = lv - rv;
  179. if (IsBadDateTime<TOutput>(ret)) {
  180. return NUdf::TUnboxedValuePod();
  181. }
  182. auto data = NUdf::TUnboxedValuePod(FromScaledDate<TOutput>(ret));
  183. if (Tz) {
  184. data.SetTimezoneId(left.GetTimezoneId());
  185. }
  186. return data;
  187. }
  188. #ifndef MKQL_DISABLE_CODEGEN
  189. static Value* Generate(Value* left, Value* right, const TCodegenContext& ctx, BasicBlock*& block)
  190. {
  191. auto& context = ctx.Codegen.GetContext();
  192. const auto lhs = GenToScaledDate<TLeft>(GetterFor<typename TLeft::TLayout>(left, context, block), context, block);
  193. const auto rhs = GenToScaledDate<TRight>(GetterFor<typename TRight::TLayout>(right, context, block), context, block);
  194. const auto sub = BinaryOperator::CreateSub(lhs, rhs, "sub", block);
  195. const auto wide = SetterFor<typename TOutput::TLayout>(GenFromScaledDate<TOutput>(sub, context, block), context, block);
  196. const auto bad = GenIsBadDateTime<TOutput>(sub, context, block);
  197. const auto type = Type::getInt128Ty(context);
  198. const auto zero = ConstantInt::get(type, 0);
  199. if (Tz) {
  200. const uint64_t init[] = {0ULL, 0xFFFFULL};
  201. const auto mask = ConstantInt::get(type, APInt(128, 2, init));
  202. const auto tzid = BinaryOperator::CreateAnd(left, mask, "tzid", block);
  203. const auto full = BinaryOperator::CreateOr(wide, tzid, "full", block);
  204. const auto sel = SelectInst::Create(bad, zero, full, "sel", block);
  205. return sel;
  206. } else {
  207. const auto sel = SelectInst::Create(bad, zero, wide, "sel", block);
  208. return sel;
  209. }
  210. }
  211. #endif
  212. };
  213. template<typename TLeft, typename TRight, typename TOutput>
  214. using TAnyDateTimeSubInterval = TAnyDateTimeSubIntervalT<TLeft, TRight, TOutput, false>;
  215. template<typename TLeft, typename TRight, typename TOutput>
  216. using TAnyDateTimeSubIntervalTz = TAnyDateTimeSubIntervalT<TLeft, TRight, TOutput, true>;
  217. }
  218. template <bool LeftTz, bool RightTz, bool LeftBig, bool RightBig>
  219. void RegisterDateSub(IBuiltinFunctionRegistry& registry) {
  220. using TDateLeft1 = std::conditional_t<LeftBig,
  221. std::conditional_t<LeftTz, NUdf::TDataType<NUdf::TTzDate32>, NUdf::TDataType<NUdf::TDate32>>,
  222. std::conditional_t<LeftTz, NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<NUdf::TDate>>>;
  223. using TDateLeft2 = std::conditional_t<LeftBig,
  224. std::conditional_t<LeftTz, NUdf::TDataType<NUdf::TTzDatetime64>, NUdf::TDataType<NUdf::TDatetime64>>,
  225. std::conditional_t<LeftTz, NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<NUdf::TDatetime>>>;
  226. using TDateLeft3 = std::conditional_t<LeftBig,
  227. std::conditional_t<LeftTz, NUdf::TDataType<NUdf::TTzTimestamp64>, NUdf::TDataType<NUdf::TTimestamp64>>,
  228. std::conditional_t<LeftTz, NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<NUdf::TTimestamp>>>;
  229. using TDateRight1 = std::conditional_t<RightBig,
  230. std::conditional_t<RightTz, NUdf::TDataType<NUdf::TTzDate32>, NUdf::TDataType<NUdf::TDate32>>,
  231. std::conditional_t<RightTz, NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<NUdf::TDate>>>;
  232. using TDateRight2 = std::conditional_t<RightBig,
  233. std::conditional_t<RightTz, NUdf::TDataType<NUdf::TTzDatetime64>, NUdf::TDataType<NUdf::TDatetime64>>,
  234. std::conditional_t<RightTz, NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<NUdf::TDatetime>>>;
  235. using TDateRight3 = std::conditional_t<RightBig,
  236. std::conditional_t<RightTz, NUdf::TDataType<NUdf::TTzTimestamp64>, NUdf::TDataType<NUdf::TTimestamp64>>,
  237. std::conditional_t<RightTz, NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<NUdf::TTimestamp>>>;
  238. using TOutput = std::conditional_t<LeftBig || RightBig,
  239. NUdf::TDataType<NUdf::TInterval64>,
  240. NUdf::TDataType<NUdf::TInterval>>;
  241. RegisterFunctionBinPolyOpt<TDateLeft1, TDateRight1,
  242. TOutput, TDateTimeSub, TBinaryArgsOpt>(registry, "Sub");
  243. RegisterFunctionBinPolyOpt<TDateLeft1, TDateRight2,
  244. TOutput, TDateTimeSub, TBinaryArgsOpt>(registry, "Sub");
  245. RegisterFunctionBinPolyOpt<TDateLeft1, TDateRight3,
  246. TOutput, TDateTimeSub, TBinaryArgsOpt>(registry, "Sub");
  247. RegisterFunctionBinPolyOpt<TDateLeft2, TDateRight1,
  248. TOutput, TDateTimeSub, TBinaryArgsOpt>(registry, "Sub");
  249. RegisterFunctionBinPolyOpt<TDateLeft2, TDateRight2,
  250. TOutput, TDateTimeSub, TBinaryArgsOpt>(registry, "Sub");
  251. RegisterFunctionBinPolyOpt<TDateLeft2, TDateRight3,
  252. TOutput, TDateTimeSub, TBinaryArgsOpt>(registry, "Sub");
  253. RegisterFunctionBinPolyOpt<TDateLeft3, TDateRight1,
  254. TOutput, TDateTimeSub, TBinaryArgsOpt>(registry, "Sub");
  255. RegisterFunctionBinPolyOpt<TDateLeft3, TDateRight2,
  256. TOutput, TDateTimeSub, TBinaryArgsOpt>(registry, "Sub");
  257. RegisterFunctionBinPolyOpt<TDateLeft3, TDateRight3,
  258. TOutput, TDateTimeSub, TBinaryArgsOpt>(registry, "Sub");
  259. }
  260. template <bool LeftTz, bool RightTz, bool LeftBig, bool RightBig>
  261. void RegisterDateSub(TKernelFamilyBase& owner) {
  262. using TDateLeft1 = std::conditional_t<LeftBig,
  263. std::conditional_t<LeftTz, NUdf::TDataType<NUdf::TTzDate32>, NUdf::TDataType<NUdf::TDate32>>,
  264. std::conditional_t<LeftTz, NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<NUdf::TDate>>>;
  265. using TDateLeft2 = std::conditional_t<LeftBig,
  266. std::conditional_t<LeftTz, NUdf::TDataType<NUdf::TTzDatetime64>, NUdf::TDataType<NUdf::TDatetime64>>,
  267. std::conditional_t<LeftTz, NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<NUdf::TDatetime>>>;
  268. using TDateLeft3 = std::conditional_t<LeftBig,
  269. std::conditional_t<LeftTz, NUdf::TDataType<NUdf::TTzTimestamp64>, NUdf::TDataType<NUdf::TTimestamp64>>,
  270. std::conditional_t<LeftTz, NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<NUdf::TTimestamp>>>;
  271. using TDateRight1 = std::conditional_t<RightBig,
  272. std::conditional_t<RightTz, NUdf::TDataType<NUdf::TTzDate32>, NUdf::TDataType<NUdf::TDate32>>,
  273. std::conditional_t<RightTz, NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<NUdf::TDate>>>;
  274. using TDateRight2 = std::conditional_t<RightBig,
  275. std::conditional_t<RightTz, NUdf::TDataType<NUdf::TTzDatetime64>, NUdf::TDataType<NUdf::TDatetime64>>,
  276. std::conditional_t<RightTz, NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<NUdf::TDatetime>>>;
  277. using TDateRight3 = std::conditional_t<RightBig,
  278. std::conditional_t<RightTz, NUdf::TDataType<NUdf::TTzTimestamp64>, NUdf::TDataType<NUdf::TTimestamp64>>,
  279. std::conditional_t<RightTz, NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<NUdf::TTimestamp>>>;
  280. using TOutput = std::conditional_t<LeftBig || RightBig,
  281. NUdf::TDataType<NUdf::TInterval64>,
  282. NUdf::TDataType<NUdf::TInterval>>;
  283. AddBinaryKernelPoly<TDateLeft1, TDateRight1, TOutput, TDateTimeSub>(owner);
  284. AddBinaryKernelPoly<TDateLeft1, TDateRight2, TOutput, TDateTimeSub>(owner);
  285. AddBinaryKernelPoly<TDateLeft1, TDateRight3, TOutput, TDateTimeSub>(owner);
  286. AddBinaryKernelPoly<TDateLeft2, TDateRight1, TOutput, TDateTimeSub>(owner);
  287. AddBinaryKernelPoly<TDateLeft2, TDateRight2, TOutput, TDateTimeSub>(owner);
  288. AddBinaryKernelPoly<TDateLeft2, TDateRight3, TOutput, TDateTimeSub>(owner);
  289. AddBinaryKernelPoly<TDateLeft3, TDateRight1, TOutput, TDateTimeSub>(owner);
  290. AddBinaryKernelPoly<TDateLeft3, TDateRight2, TOutput, TDateTimeSub>(owner);
  291. AddBinaryKernelPoly<TDateLeft3, TDateRight3, TOutput, TDateTimeSub>(owner);
  292. }
  293. void RegisterSub(IBuiltinFunctionRegistry& registry) {
  294. RegisterBinaryNumericFunctionOpt<TSub, TBinaryArgsOpt>(registry, "Sub");
  295. NDecimal::RegisterBinaryFunctionForAllPrecisions<TDecimalSub, TBinaryArgsOpt>(registry, "Sub_");
  296. RegisterDateSub<false, false, false, false>(registry);
  297. RegisterDateSub<false, true, false, false>(registry);
  298. RegisterDateSub<true, false, false, false>(registry);
  299. RegisterDateSub<true, true, false, false>(registry);
  300. // NarrowDate minus BigDate
  301. RegisterDateSub<false, false, false, true>(registry);
  302. RegisterDateSub<true, false, false, true>(registry);
  303. RegisterDateSub<false, true, false, true>(registry);
  304. RegisterDateSub<true, true, false, true>(registry);
  305. // BigDate minus NarrowDate
  306. RegisterDateSub<false, false, true, false>(registry);
  307. RegisterDateSub<false, true, true, false>(registry);
  308. RegisterDateSub<true, false, true, false>(registry);
  309. RegisterDateSub<true, true, true, false>(registry);
  310. // BigDate minus BigDate
  311. RegisterDateSub<false, false, true, true>(registry);
  312. RegisterDateSub<true, false, true, true>(registry);
  313. RegisterDateSub<false, true, true, true>(registry);
  314. RegisterDateSub<true, true, true, true>(registry);
  315. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TInterval>, NUdf::TDataType<NUdf::TInterval>,
  316. NUdf::TDataType<NUdf::TInterval>, TIntervalSubInterval, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  317. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TInterval>, NUdf::TDataType<NUdf::TInterval64>,
  318. NUdf::TDataType<NUdf::TInterval64>, TBigIntervalSub, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  319. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TInterval64>, NUdf::TDataType<NUdf::TInterval>,
  320. NUdf::TDataType<NUdf::TInterval64>, TBigIntervalSub, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  321. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TInterval64>, NUdf::TDataType<NUdf::TInterval64>,
  322. NUdf::TDataType<NUdf::TInterval64>, TBigIntervalSub, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  323. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<NUdf::TInterval>,
  324. NUdf::TDataType<NUdf::TDate>, TAnyDateTimeSubInterval, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  325. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<NUdf::TInterval>,
  326. NUdf::TDataType<NUdf::TDatetime>, TAnyDateTimeSubInterval, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  327. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TInterval>,
  328. NUdf::TDataType<NUdf::TTimestamp>, TAnyDateTimeSubInterval, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  329. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<NUdf::TInterval>,
  330. NUdf::TDataType<NUdf::TTzDate>, TAnyDateTimeSubIntervalTz, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  331. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<NUdf::TInterval>,
  332. NUdf::TDataType<NUdf::TTzDatetime>, TAnyDateTimeSubIntervalTz, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  333. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<NUdf::TInterval>,
  334. NUdf::TDataType<NUdf::TTzTimestamp>, TAnyDateTimeSubIntervalTz, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  335. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TDate>, NUdf::TDataType<NUdf::TInterval64>,
  336. NUdf::TDataType<NUdf::TDate>, TAnyDateTimeSubInterval, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  337. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TDatetime>, NUdf::TDataType<NUdf::TInterval64>,
  338. NUdf::TDataType<NUdf::TDatetime>, TAnyDateTimeSubInterval, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  339. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTimestamp>, NUdf::TDataType<NUdf::TInterval64>,
  340. NUdf::TDataType<NUdf::TTimestamp>, TAnyDateTimeSubInterval, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  341. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<NUdf::TInterval64>,
  342. NUdf::TDataType<NUdf::TTzDate>, TAnyDateTimeSubIntervalTz, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  343. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<NUdf::TInterval64>,
  344. NUdf::TDataType<NUdf::TTzDatetime>, TAnyDateTimeSubIntervalTz, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  345. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<NUdf::TInterval64>,
  346. NUdf::TDataType<NUdf::TTzTimestamp>, TAnyDateTimeSubIntervalTz, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  347. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TInterval64>,
  348. NUdf::TDataType<NUdf::TDate32>, TAnyDateTimeSubInterval, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  349. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TInterval64>,
  350. NUdf::TDataType<NUdf::TDatetime64>, TAnyDateTimeSubInterval, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  351. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TInterval64>,
  352. NUdf::TDataType<NUdf::TTimestamp64>, TAnyDateTimeSubInterval, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  353. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TDate32>, NUdf::TDataType<NUdf::TInterval>,
  354. NUdf::TDataType<NUdf::TDate32>, TAnyDateTimeSubInterval, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  355. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TDatetime64>, NUdf::TDataType<NUdf::TInterval>,
  356. NUdf::TDataType<NUdf::TDatetime64>, TAnyDateTimeSubInterval, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  357. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTimestamp64>, NUdf::TDataType<NUdf::TInterval>,
  358. NUdf::TDataType<NUdf::TTimestamp64>, TAnyDateTimeSubInterval, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  359. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTzDate32>, NUdf::TDataType<NUdf::TInterval64>,
  360. NUdf::TDataType<NUdf::TTzDate32>, TAnyDateTimeSubIntervalTz, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  361. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTzDatetime64>, NUdf::TDataType<NUdf::TInterval64>,
  362. NUdf::TDataType<NUdf::TTzDatetime64>, TAnyDateTimeSubIntervalTz, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  363. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTzTimestamp64>, NUdf::TDataType<NUdf::TInterval64>,
  364. NUdf::TDataType<NUdf::TTzTimestamp64>, TAnyDateTimeSubIntervalTz, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  365. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTzDate32>, NUdf::TDataType<NUdf::TInterval>,
  366. NUdf::TDataType<NUdf::TTzDate32>, TAnyDateTimeSubIntervalTz, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  367. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTzDatetime64>, NUdf::TDataType<NUdf::TInterval>,
  368. NUdf::TDataType<NUdf::TTzDatetime64>, TAnyDateTimeSubIntervalTz, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  369. RegisterFunctionBinPolyOpt<NUdf::TDataType<NUdf::TTzTimestamp64>, NUdf::TDataType<NUdf::TInterval>,
  370. NUdf::TDataType<NUdf::TTzTimestamp64>, TAnyDateTimeSubIntervalTz, TBinaryArgsOptWithNullableResult>(registry, "Sub");
  371. }
  372. template <bool Tz, bool BigDate, bool BigInterval>
  373. void RegisterDateSubInterval(TKernelFamilyBase& owner) {
  374. using TDateLeft1 = std::conditional_t<BigDate,
  375. std::conditional_t<Tz, NUdf::TDataType<NUdf::TTzDate32>, NUdf::TDataType<NUdf::TDate32>>,
  376. std::conditional_t<Tz, NUdf::TDataType<NUdf::TTzDate>, NUdf::TDataType<NUdf::TDate>>>;
  377. using TDateLeft2 = std::conditional_t<BigDate,
  378. std::conditional_t<Tz, NUdf::TDataType<NUdf::TTzDatetime64>, NUdf::TDataType<NUdf::TDatetime64>>,
  379. std::conditional_t<Tz, NUdf::TDataType<NUdf::TTzDatetime>, NUdf::TDataType<NUdf::TDatetime>>>;
  380. using TDateLeft3 = std::conditional_t<BigDate,
  381. std::conditional_t<Tz, NUdf::TDataType<NUdf::TTzTimestamp64>, NUdf::TDataType<NUdf::TTimestamp64>>,
  382. std::conditional_t<Tz, NUdf::TDataType<NUdf::TTzTimestamp>, NUdf::TDataType<NUdf::TTimestamp>>>;
  383. using TIntervalRight = std::conditional_t<BigInterval,
  384. NUdf::TDataType<NUdf::TInterval64>, NUdf::TDataType<NUdf::TInterval>>;
  385. AddBinaryKernelPoly<TDateLeft1, TIntervalRight, TDateLeft1, TAnyDateTimeSubInterval>(owner);
  386. AddBinaryKernelPoly<TDateLeft2, TIntervalRight, TDateLeft2, TAnyDateTimeSubInterval>(owner);
  387. AddBinaryKernelPoly<TDateLeft3, TIntervalRight, TDateLeft3, TAnyDateTimeSubInterval>(owner);
  388. }
  389. template <bool BigInterval1, bool BigInterval2>
  390. void RegisterIntervalSubInterval(TKernelFamilyBase& owner) {
  391. using TLeft = std::conditional_t<BigInterval1,
  392. NUdf::TDataType<NUdf::TInterval64>, NUdf::TDataType<NUdf::TInterval>>;
  393. using TRight = std::conditional_t<BigInterval2,
  394. NUdf::TDataType<NUdf::TInterval64>, NUdf::TDataType<NUdf::TInterval>>;
  395. using TOutput = std::conditional_t<BigInterval1 || BigInterval2,
  396. NUdf::TDataType<NUdf::TInterval64>, NUdf::TDataType<NUdf::TInterval>>;
  397. if constexpr (BigInterval1 || BigInterval2) {
  398. AddBinaryKernelPoly<TLeft, TRight, TOutput, TBigIntervalSub>(owner);
  399. } else {
  400. AddBinaryKernelPoly<TLeft, TRight, TOutput, TIntervalSubInterval>(owner);
  401. }
  402. }
  403. void RegisterSub(TKernelFamilyMap& kernelFamilyMap) {
  404. auto family = std::make_unique<TKernelFamilyBase>();
  405. AddBinaryIntegralKernels<TSub>(*family);
  406. AddBinaryRealKernels<TSub>(*family);
  407. AddBinaryDecimalKernels<TDecimalSub>(*family);
  408. RegisterDateSub<false, false, false, false>(*family);
  409. RegisterDateSub<false, true, false, false>(*family);
  410. RegisterDateSub<true, false, false, false>(*family);
  411. RegisterDateSub<true, true, false, false>(*family);
  412. // NarrowDate minus BigDate
  413. RegisterDateSub<false, false, false, true>(*family);
  414. RegisterDateSub<true, false, false, true>(*family);
  415. RegisterDateSub<false, true, false, true>(*family);
  416. RegisterDateSub<true, true, false, true>(*family);
  417. // BigDate minus NarrowDate
  418. RegisterDateSub<false, false, true, false>(*family);
  419. RegisterDateSub<false, true, true, false>(*family);
  420. RegisterDateSub<true, false, true, false>(*family);
  421. RegisterDateSub<true, true, true, false>(*family);
  422. // BigDate minus BigDate
  423. RegisterDateSub<false, false, true, true>(*family);
  424. RegisterDateSub<false, true, true, true>(*family);
  425. RegisterDateSub<true, false, true, true>(*family);
  426. RegisterDateSub<true, true, true, true>(*family);
  427. RegisterDateSubInterval<false, false, false>(*family);
  428. RegisterDateSubInterval<true, false, false>(*family);
  429. RegisterDateSubInterval<false, true, false>(*family);
  430. RegisterDateSubInterval<true, true, false>(*family);
  431. RegisterDateSubInterval<false, false, true>(*family);
  432. RegisterDateSubInterval<true, false, true>(*family);
  433. RegisterDateSubInterval<false, true, true>(*family);
  434. RegisterDateSubInterval<true, true, true>(*family);
  435. RegisterIntervalSubInterval<false, false>(*family);
  436. RegisterIntervalSubInterval<false, true>(*family);
  437. RegisterIntervalSubInterval<true, false>(*family);
  438. RegisterIntervalSubInterval<true, true>(*family);
  439. kernelFamilyMap["Sub"] = std::move(family);
  440. }
  441. } // namespace NMiniKQL
  442. } // namespace NKikimr