block_item_comparator.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. #pragma once
  2. #include "block_item.h"
  3. #include <yql/essentials/public/udf/udf_ptr.h>
  4. #include <yql/essentials/public/udf/udf_type_inspection.h>
  5. #include <yql/essentials/public/udf/udf_type_size_check.h>
  6. namespace NYql::NUdf {
  7. // ABI stable
  8. class IBlockItemComparator {
  9. public:
  10. using TPtr = TUniquePtr<IBlockItemComparator>;
  11. virtual ~IBlockItemComparator() = default;
  12. virtual i64 Compare(TBlockItem lhs, TBlockItem rhs) const = 0;
  13. virtual bool Equals(TBlockItem lhs, TBlockItem rhs) const = 0;
  14. virtual bool Less(TBlockItem lhs, TBlockItem rhs) const = 0;
  15. inline bool Greater(TBlockItem lhs, TBlockItem rhs) const {
  16. return Less(rhs, lhs);
  17. }
  18. };
  19. UDF_ASSERT_TYPE_SIZE(IBlockItemComparator, 8);
  20. template <typename TDerived, bool Nullable>
  21. class TBlockItemComparatorBase : public IBlockItemComparator {
  22. public:
  23. const TDerived* Derived() const {
  24. return static_cast<const TDerived*>(this);
  25. }
  26. // returns <0 if lhs < rhs
  27. i64 Compare(TBlockItem lhs, TBlockItem rhs) const final {
  28. if constexpr (Nullable) {
  29. if (lhs) {
  30. if (rhs) {
  31. return Derived()->DoCompare(lhs, rhs);
  32. } else {
  33. return +1;
  34. }
  35. } else {
  36. if (rhs) {
  37. return -1;
  38. } else {
  39. return 0;
  40. }
  41. }
  42. } else {
  43. return Derived()->DoCompare(lhs, rhs);
  44. }
  45. }
  46. bool Equals(TBlockItem lhs, TBlockItem rhs) const final {
  47. if constexpr (Nullable) {
  48. if (lhs) {
  49. if (rhs) {
  50. return Derived()->DoEquals(lhs, rhs);
  51. } else {
  52. return false;
  53. }
  54. } else {
  55. if (rhs) {
  56. return false;
  57. } else {
  58. return true;
  59. }
  60. }
  61. } else {
  62. return Derived()->DoEquals(lhs, rhs);
  63. }
  64. }
  65. bool Less(TBlockItem lhs, TBlockItem rhs) const final {
  66. if constexpr (Nullable) {
  67. if (lhs) {
  68. if (rhs) {
  69. return Derived()->DoLess(lhs, rhs);
  70. }
  71. else {
  72. return false;
  73. }
  74. } else {
  75. if (rhs) {
  76. return true;
  77. } else {
  78. return false;
  79. }
  80. }
  81. } else {
  82. return Derived()->DoLess(lhs, rhs);
  83. }
  84. }
  85. };
  86. template <typename T, bool Nullable>
  87. class TFixedSizeBlockItemComparator : public TBlockItemComparatorBase<TFixedSizeBlockItemComparator<T, Nullable>, Nullable> {
  88. public:
  89. i64 DoCompare(TBlockItem lhs, TBlockItem rhs) const {
  90. if constexpr (std::is_integral<T>::value && sizeof(T) < sizeof(i64)) {
  91. return i64(lhs.As<T>()) - i64(rhs.As<T>());
  92. } else {
  93. if constexpr (std::is_floating_point<T>::value) {
  94. if (std::isunordered(lhs.As<T>(), rhs.As<T>())) {
  95. return i64(std::isnan(lhs.As<T>())) - i64(std::isnan(rhs.As<T>()));
  96. }
  97. }
  98. return (lhs.As<T>() > rhs.As<T>()) - (lhs.As<T>() < rhs.As<T>());
  99. }
  100. }
  101. bool DoEquals(TBlockItem lhs, TBlockItem rhs) const {
  102. if constexpr (std::is_floating_point<T>::value) {
  103. if (std::isunordered(lhs.As<T>(), rhs.As<T>())) {
  104. return std::isnan(lhs.As<T>()) == std::isnan(rhs.As<T>());
  105. }
  106. }
  107. return lhs.As<T>() == rhs.As<T>();
  108. }
  109. bool DoLess(TBlockItem lhs, TBlockItem rhs) const {
  110. if constexpr (std::is_floating_point<T>::value) {
  111. if (std::isunordered(lhs.As<T>(), rhs.As<T>())) {
  112. return std::isnan(lhs.As<T>()) < std::isnan(rhs.As<T>());
  113. }
  114. }
  115. return lhs.As<T>() < rhs.As<T>();
  116. }
  117. };
  118. template <bool Nullable>
  119. class TFixedSizeBlockItemComparator<NYql::NDecimal::TInt128, Nullable> : public TBlockItemComparatorBase<TFixedSizeBlockItemComparator<NYql::NDecimal::TInt128, Nullable>, Nullable> {
  120. public:
  121. i64 DoCompare(TBlockItem lhs, TBlockItem rhs) const {
  122. auto l = lhs.GetInt128();
  123. auto r = rhs.GetInt128();
  124. return (l > r) - (l < r);
  125. }
  126. bool DoEquals(TBlockItem lhs, TBlockItem rhs) const {
  127. auto l = lhs.GetInt128();
  128. auto r = rhs.GetInt128();
  129. return l == r;
  130. }
  131. bool DoLess(TBlockItem lhs, TBlockItem rhs) const {
  132. auto l = lhs.GetInt128();
  133. auto r = rhs.GetInt128();
  134. return l < r;
  135. }
  136. };
  137. template <typename TStringType, bool Nullable>
  138. class TStringBlockItemComparator : public TBlockItemComparatorBase<TStringBlockItemComparator<TStringType, Nullable>, Nullable> {
  139. public:
  140. i64 DoCompare(TBlockItem lhs, TBlockItem rhs) const {
  141. return lhs.AsStringRef().Compare(rhs.AsStringRef());
  142. }
  143. bool DoEquals(TBlockItem lhs, TBlockItem rhs) const {
  144. return lhs.AsStringRef() == rhs.AsStringRef();
  145. }
  146. bool DoLess(TBlockItem lhs, TBlockItem rhs) const {
  147. return lhs.AsStringRef() < rhs.AsStringRef();
  148. }
  149. };
  150. template<typename TTzType, bool Nullable>
  151. class TTzDateBlockItemComparator : public TBlockItemComparatorBase<TTzDateBlockItemComparator<TTzType, Nullable>, Nullable> {
  152. using TLayout = typename TDataType<TTzType>::TLayout;
  153. public:
  154. bool DoCompare(TBlockItem lhs, TBlockItem rhs) const {
  155. const auto x = lhs.Get<TLayout>();
  156. const auto y = rhs.Get<TLayout>();
  157. if (x == y) {
  158. const auto tx = lhs.GetTimezoneId();
  159. const auto ty = rhs.GetTimezoneId();
  160. return (tx == ty) ? 0 : (tx < ty ? -1 : 1);
  161. }
  162. if (x < y) {
  163. return -1;
  164. }
  165. return 1;
  166. }
  167. bool DoEquals(TBlockItem lhs, TBlockItem rhs) const {
  168. return lhs.Get<TLayout>() == rhs.Get<TLayout>() && lhs.GetTimezoneId() == rhs.GetTimezoneId();
  169. }
  170. bool DoLess(TBlockItem lhs, TBlockItem rhs) const {
  171. return std::forward_as_tuple(lhs.Get<TLayout>(), lhs.GetTimezoneId()) < std::forward_as_tuple(rhs.Get<TLayout>(), rhs.GetTimezoneId());
  172. }
  173. };
  174. template <bool Nullable>
  175. class TTupleBlockItemComparator : public TBlockItemComparatorBase<TTupleBlockItemComparator<Nullable>, Nullable> {
  176. public:
  177. TTupleBlockItemComparator(TVector<std::unique_ptr<IBlockItemComparator>>&& children)
  178. : Children_(std::move(children))
  179. {}
  180. public:
  181. i64 DoCompare(TBlockItem lhs, TBlockItem rhs) const {
  182. for (ui32 i = 0; i < Children_.size(); ++i) {
  183. auto res = Children_[i]->Compare(lhs.AsTuple()[i], rhs.AsTuple()[i]);
  184. if (res != 0) {
  185. return res;
  186. }
  187. }
  188. return 0;
  189. }
  190. bool DoEquals(TBlockItem lhs, TBlockItem rhs) const {
  191. for (ui32 i = 0; i < Children_.size(); ++i) {
  192. if (!Children_[i]->Equals(lhs.AsTuple()[i], rhs.AsTuple()[i])) {
  193. return false;
  194. }
  195. }
  196. return true;
  197. }
  198. bool DoLess(TBlockItem lhs, TBlockItem rhs) const {
  199. for (ui32 i = 0; i < Children_.size(); ++i) {
  200. auto res = Children_[i]->Compare(lhs.AsTuple()[i], rhs.AsTuple()[i]);
  201. if (res < 0) {
  202. return true;
  203. }
  204. if (res > 0) {
  205. return false;
  206. }
  207. }
  208. return false;
  209. }
  210. private:
  211. const TVector<std::unique_ptr<IBlockItemComparator>> Children_;
  212. };
  213. class TExternalOptionalBlockItemComparator : public TBlockItemComparatorBase<TExternalOptionalBlockItemComparator, true> {
  214. public:
  215. TExternalOptionalBlockItemComparator(std::unique_ptr<IBlockItemComparator> inner)
  216. : Inner_(std::move(inner))
  217. {}
  218. i64 DoCompare(TBlockItem lhs, TBlockItem rhs) const {
  219. return Inner_->Compare(lhs.GetOptionalValue(), rhs.GetOptionalValue());
  220. }
  221. bool DoEquals(TBlockItem lhs, TBlockItem rhs) const {
  222. return Inner_->Equals(lhs.GetOptionalValue(), rhs.GetOptionalValue());
  223. }
  224. bool DoLess(TBlockItem lhs, TBlockItem rhs) const {
  225. return Inner_->Less(lhs.GetOptionalValue(), rhs.GetOptionalValue());
  226. }
  227. private:
  228. std::unique_ptr<IBlockItemComparator> Inner_;
  229. };
  230. }