block_item_comparator.h 8.2 KB

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