mkql_join_ut.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #include "mkql_computation_node_ut.h"
  2. #include <yql/essentials/minikql/mkql_runtime_version.h>
  3. namespace NKikimr {
  4. namespace NMiniKQL {
  5. Y_UNIT_TEST_SUITE(TMiniKQLCommonJoinCoreTupleTest) {
  6. Y_UNIT_TEST_LLVM(Inner) {
  7. TSetup<LLVM> setup;
  8. TProgramBuilder& pb = *setup.PgmBuilder;
  9. const auto indexType = pb.NewDataType(NUdf::TDataType<ui32>::Id);
  10. const auto optionalType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  11. const auto tupleType = pb.NewTupleType({optionalType, optionalType, optionalType, indexType});
  12. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(-1)), pb.NewDataLiteral<ui32>(0)});
  13. const auto data2 = pb.NewTuple(tupleType, {pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(2)), pb.NewOptional(pb.NewDataLiteral<i32>(-2)), pb.NewDataLiteral<ui32>(0)});
  14. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(-3)), pb.NewDataLiteral<ui32>(1)});
  15. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(optionalType), pb.NewDataLiteral<ui32>(1)});
  16. const auto list = pb.NewList(tupleType, {data1, data3, data2, data4});
  17. const auto outputType = pb.NewFlowType(pb.NewMultiType({optionalType, optionalType}));
  18. const auto pgmReturn = pb.Collect(pb.CommonJoinCore(pb.ToFlow(list), EJoinKind::Inner, {0U, 0U}, {1U, 1U}, {}, {2U}, 0ULL, std::nullopt, EAnyJoinSettings::None, 3U, outputType));
  19. const auto graph = setup.BuildGraph(pgmReturn);
  20. const auto iterator = graph->GetValue().GetListIterator();
  21. NUdf::TUnboxedValue item;
  22. UNIT_ASSERT(iterator.Next(item));
  23. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 1);
  24. UNIT_ASSERT(!item.GetElement(1));
  25. UNIT_ASSERT(iterator.Next(item));
  26. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 1);
  27. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  28. UNIT_ASSERT(iterator.Next(item));
  29. UNIT_ASSERT(!item.GetElement(0));
  30. UNIT_ASSERT(!item.GetElement(1));
  31. UNIT_ASSERT(iterator.Next(item));
  32. UNIT_ASSERT(!item.GetElement(0));
  33. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  34. UNIT_ASSERT(!iterator.Next(item));
  35. UNIT_ASSERT(!iterator.Next(item));
  36. }
  37. Y_UNIT_TEST_LLVM(InnerOrderLeftFirst) {
  38. TSetup<LLVM> setup;
  39. TProgramBuilder& pb = *setup.PgmBuilder;
  40. const auto indexType = pb.NewDataType(NUdf::TDataType<ui32>::Id);
  41. const auto optionalType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  42. const auto tupleType = pb.NewTupleType({optionalType, optionalType, optionalType, indexType});
  43. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(-1)), pb.NewDataLiteral<ui32>(0)});
  44. const auto data2 = pb.NewTuple(tupleType, {pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(2)), pb.NewOptional(pb.NewDataLiteral<i32>(-2)), pb.NewDataLiteral<ui32>(0)});
  45. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(-3)), pb.NewDataLiteral<ui32>(1)});
  46. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(optionalType), pb.NewDataLiteral<ui32>(1)});
  47. const auto list = pb.NewList(tupleType, {data1, data2, data3, data4});
  48. const auto outputType = pb.NewFlowType(pb.NewMultiType({optionalType, optionalType}));
  49. const auto pgmReturn = pb.Collect(pb.CommonJoinCore(pb.ToFlow(list), EJoinKind::Inner, {0U, 0U}, {1U, 1U}, {}, {2U}, 0ULL, {0U}, EAnyJoinSettings::None, 3U, outputType));
  50. const auto graph = setup.BuildGraph(pgmReturn);
  51. const auto iterator = graph->GetValue().GetListIterator();
  52. NUdf::TUnboxedValue item;
  53. UNIT_ASSERT(iterator.Next(item));
  54. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 1);
  55. UNIT_ASSERT(!item.GetElement(1));
  56. UNIT_ASSERT(iterator.Next(item));
  57. UNIT_ASSERT(!item.GetElement(0));
  58. UNIT_ASSERT(!item.GetElement(1));
  59. UNIT_ASSERT(iterator.Next(item));
  60. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 1);
  61. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  62. UNIT_ASSERT(iterator.Next(item));
  63. UNIT_ASSERT(!item.GetElement(0));
  64. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  65. UNIT_ASSERT(!iterator.Next(item));
  66. UNIT_ASSERT(!iterator.Next(item));
  67. }
  68. Y_UNIT_TEST_LLVM(InnerOrderRightFirst) {
  69. TSetup<LLVM> setup;
  70. TProgramBuilder& pb = *setup.PgmBuilder;
  71. const auto indexType = pb.NewDataType(NUdf::TDataType<ui32>::Id);
  72. const auto optionalType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  73. const auto tupleType = pb.NewTupleType({optionalType, optionalType, optionalType, indexType});
  74. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(-1)), pb.NewDataLiteral<ui32>(0)});
  75. const auto data2 = pb.NewTuple(tupleType, {pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(2)), pb.NewOptional(pb.NewDataLiteral<i32>(-2)), pb.NewDataLiteral<ui32>(0)});
  76. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(-3)), pb.NewDataLiteral<ui32>(1)});
  77. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(optionalType), pb.NewDataLiteral<ui32>(1)});
  78. const auto list = pb.NewList(tupleType, {data3, data4, data1, data2});
  79. const auto outputType = pb.NewFlowType(pb.NewMultiType({optionalType, optionalType}));
  80. const auto pgmReturn = pb.Collect(pb.CommonJoinCore(pb.ToFlow(list), EJoinKind::Inner, {0U, 0U}, {1U, 1U}, {}, {2U}, 0ULL, {1U}, EAnyJoinSettings::None, 3U, outputType));
  81. const auto graph = setup.BuildGraph(pgmReturn);
  82. const auto iterator = graph->GetValue().GetListIterator();
  83. NUdf::TUnboxedValue item;
  84. UNIT_ASSERT(iterator.Next(item));
  85. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 1);
  86. UNIT_ASSERT(!item.GetElement(1));
  87. UNIT_ASSERT(iterator.Next(item));
  88. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 1);
  89. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  90. UNIT_ASSERT(iterator.Next(item));
  91. UNIT_ASSERT(!item.GetElement(0));
  92. UNIT_ASSERT(!item.GetElement(1));
  93. UNIT_ASSERT(iterator.Next(item));
  94. UNIT_ASSERT(!item.GetElement(0));
  95. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  96. UNIT_ASSERT(!iterator.Next(item));
  97. UNIT_ASSERT(!iterator.Next(item));
  98. }
  99. }
  100. #if !defined(MKQL_RUNTIME_VERSION) || MKQL_RUNTIME_VERSION >= 18u
  101. Y_UNIT_TEST_SUITE(TMiniKQLCommonJoinCoreWideTest) {
  102. Y_UNIT_TEST_LLVM(Inner) {
  103. TSetup<LLVM> setup;
  104. TProgramBuilder& pb = *setup.PgmBuilder;
  105. const auto indexType = pb.NewDataType(NUdf::TDataType<ui32>::Id);
  106. const auto optionalType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  107. const auto tupleType = pb.NewTupleType({optionalType, optionalType, optionalType, indexType});
  108. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(-1)), pb.NewDataLiteral<ui32>(0)});
  109. const auto data2 = pb.NewTuple(tupleType, {pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(2)), pb.NewOptional(pb.NewDataLiteral<i32>(-2)), pb.NewDataLiteral<ui32>(0)});
  110. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(-3)), pb.NewDataLiteral<ui32>(1)});
  111. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(optionalType), pb.NewDataLiteral<ui32>(1)});
  112. const auto list = pb.NewList(tupleType, {data1, data3, data2, data4});
  113. const auto outputType = pb.NewFlowType(pb.NewMultiType({optionalType, optionalType}));
  114. const auto pgmReturn = pb.Collect(pb.NarrowMap(pb.CommonJoinCore(pb.ExpandMap(pb.ToFlow(list),
  115. [&](TRuntimeNode item) -> TRuntimeNode::TList { return {pb.Nth(item, 0U), pb.Nth(item, 1U), pb.Nth(item, 2U), pb.Nth(item, 3U)}; }),
  116. EJoinKind::Inner, {0U, 0U}, {1U, 1U}, {}, {2U}, 0ULL, std::nullopt, EAnyJoinSettings::None, 3U, outputType),
  117. [&](TRuntimeNode::TList items) -> TRuntimeNode { return pb.NewTuple(items); })
  118. );
  119. const auto graph = setup.BuildGraph(pgmReturn);
  120. const auto iterator = graph->GetValue().GetListIterator();
  121. NUdf::TUnboxedValue item;
  122. UNIT_ASSERT(iterator.Next(item));
  123. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 1);
  124. UNIT_ASSERT(!item.GetElement(1));
  125. UNIT_ASSERT(iterator.Next(item));
  126. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 1);
  127. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  128. UNIT_ASSERT(iterator.Next(item));
  129. UNIT_ASSERT(!item.GetElement(0));
  130. UNIT_ASSERT(!item.GetElement(1));
  131. UNIT_ASSERT(iterator.Next(item));
  132. UNIT_ASSERT(!item.GetElement(0));
  133. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  134. UNIT_ASSERT(!iterator.Next(item));
  135. UNIT_ASSERT(!iterator.Next(item));
  136. }
  137. Y_UNIT_TEST_LLVM(InnerOrderLeftFirst) {
  138. TSetup<LLVM> setup;
  139. TProgramBuilder& pb = *setup.PgmBuilder;
  140. const auto indexType = pb.NewDataType(NUdf::TDataType<ui32>::Id);
  141. const auto optionalType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  142. const auto tupleType = pb.NewTupleType({optionalType, optionalType, optionalType, indexType});
  143. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(-1)), pb.NewDataLiteral<ui32>(0)});
  144. const auto data2 = pb.NewTuple(tupleType, {pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(2)), pb.NewOptional(pb.NewDataLiteral<i32>(-2)), pb.NewDataLiteral<ui32>(0)});
  145. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(-3)), pb.NewDataLiteral<ui32>(1)});
  146. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(optionalType), pb.NewDataLiteral<ui32>(1)});
  147. const auto list = pb.NewList(tupleType, {data1, data2, data3, data4});
  148. const auto outputType = pb.NewFlowType(pb.NewMultiType({optionalType, optionalType}));
  149. const auto pgmReturn = pb.Collect(pb.NarrowMap(pb.CommonJoinCore(pb.ExpandMap(pb.ToFlow(list),
  150. [&](TRuntimeNode item) -> TRuntimeNode::TList { return {pb.Nth(item, 0U), pb.Nth(item, 1U), pb.Nth(item, 2U), pb.Nth(item, 3U)}; }),
  151. EJoinKind::Inner, {0U, 0U}, {1U, 1U}, {}, {2U}, 0ULL, {0U}, EAnyJoinSettings::None, 3U, outputType),
  152. [&](TRuntimeNode::TList items) -> TRuntimeNode { return pb.NewTuple(items); })
  153. );
  154. const auto graph = setup.BuildGraph(pgmReturn);
  155. const auto iterator = graph->GetValue().GetListIterator();
  156. NUdf::TUnboxedValue item;
  157. UNIT_ASSERT(iterator.Next(item));
  158. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 1);
  159. UNIT_ASSERT(!item.GetElement(1));
  160. UNIT_ASSERT(iterator.Next(item));
  161. UNIT_ASSERT(!item.GetElement(0));
  162. UNIT_ASSERT(!item.GetElement(1));
  163. UNIT_ASSERT(iterator.Next(item));
  164. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 1);
  165. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  166. UNIT_ASSERT(iterator.Next(item));
  167. UNIT_ASSERT(!item.GetElement(0));
  168. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  169. UNIT_ASSERT(!iterator.Next(item));
  170. UNIT_ASSERT(!iterator.Next(item));
  171. }
  172. Y_UNIT_TEST_LLVM(InnerOrderRightFirst) {
  173. TSetup<LLVM> setup;
  174. TProgramBuilder& pb = *setup.PgmBuilder;
  175. const auto indexType = pb.NewDataType(NUdf::TDataType<ui32>::Id);
  176. const auto optionalType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  177. const auto tupleType = pb.NewTupleType({optionalType, optionalType, optionalType, indexType});
  178. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(-1)), pb.NewDataLiteral<ui32>(0)});
  179. const auto data2 = pb.NewTuple(tupleType, {pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(2)), pb.NewOptional(pb.NewDataLiteral<i32>(-2)), pb.NewDataLiteral<ui32>(0)});
  180. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), pb.NewEmptyOptional(optionalType), pb.NewOptional(pb.NewDataLiteral<i32>(-3)), pb.NewDataLiteral<ui32>(1)});
  181. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(optionalType), pb.NewDataLiteral<ui32>(1)});
  182. const auto list = pb.NewList(tupleType, {data3, data4, data1, data2});
  183. const auto outputType = pb.NewFlowType(pb.NewMultiType({optionalType, optionalType}));
  184. const auto pgmReturn = pb.Collect(pb.NarrowMap(pb.CommonJoinCore(pb.ExpandMap(pb.ToFlow(list),
  185. [&](TRuntimeNode item) -> TRuntimeNode::TList { return {pb.Nth(item, 0U), pb.Nth(item, 1U), pb.Nth(item, 2U), pb.Nth(item, 3U)}; }),
  186. EJoinKind::Inner, {0U, 0U}, {1U, 1U}, {}, {2U}, 0ULL, {1U}, EAnyJoinSettings::None, 3U, outputType),
  187. [&](TRuntimeNode::TList items) -> TRuntimeNode { return pb.NewTuple(items); })
  188. );
  189. const auto graph = setup.BuildGraph(pgmReturn);
  190. const auto iterator = graph->GetValue().GetListIterator();
  191. NUdf::TUnboxedValue item;
  192. UNIT_ASSERT(iterator.Next(item));
  193. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 1);
  194. UNIT_ASSERT(!item.GetElement(1));
  195. UNIT_ASSERT(iterator.Next(item));
  196. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(0).template Get<i32>(), 1);
  197. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  198. UNIT_ASSERT(iterator.Next(item));
  199. UNIT_ASSERT(!item.GetElement(0));
  200. UNIT_ASSERT(!item.GetElement(1));
  201. UNIT_ASSERT(iterator.Next(item));
  202. UNIT_ASSERT(!item.GetElement(0));
  203. UNIT_ASSERT_VALUES_EQUAL(item.GetElement(1).template Get<i32>(), 4);
  204. UNIT_ASSERT(!iterator.Next(item));
  205. UNIT_ASSERT(!iterator.Next(item));
  206. }
  207. Y_UNIT_TEST_LLVM(ExclusionOrderLeftFirstAny) {
  208. TSetup<LLVM> setup;
  209. TProgramBuilder& pb = *setup.PgmBuilder;
  210. const auto indexType = pb.NewDataType(NUdf::TDataType<ui32>::Id);
  211. const auto stringType = pb.NewDataType(NUdf::TDataType<NUdf::TUtf8>::Id);
  212. const auto optStrType = pb.NewOptionalType(stringType);
  213. const auto optionalType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  214. const auto tupleType = pb.NewTupleType({optionalType, optStrType, optStrType, indexType});
  215. const auto value1 = pb.NewOptional(pb.NewDataLiteral<NUdf::EDataSlot::Utf8>("very long value 1"));
  216. const auto value2 = pb.NewOptional(pb.NewDataLiteral<NUdf::EDataSlot::Utf8>("very long value 2"));
  217. const auto value3 = pb.NewOptional(pb.NewDataLiteral<NUdf::EDataSlot::Utf8>("very long value 3"));
  218. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), pb.NewEmptyOptional(optStrType), value1, pb.NewDataLiteral<ui32>(1)});
  219. const auto data2 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(2)), pb.NewEmptyOptional(optStrType), value2, pb.NewDataLiteral<ui32>(1)});
  220. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), pb.NewEmptyOptional(optStrType), value3, pb.NewDataLiteral<ui32>(1)});
  221. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(optStrType), pb.NewEmptyOptional(optStrType), pb.NewDataLiteral<ui32>(1)});
  222. const auto list = pb.NewList(tupleType, {data1, data2, data3, data4});
  223. const auto outputType = pb.NewFlowType(pb.NewMultiType({optStrType, optStrType}));
  224. const auto landmine = pb.NewDataLiteral<NUdf::EDataSlot::Utf8>("ACHTUNG MINEN!");
  225. const auto pgmReturn = pb.Collect(pb.NarrowMap(pb.CommonJoinCore(pb.ExpandMap(pb.ToFlow(list),
  226. [&](TRuntimeNode item) -> TRuntimeNode::TList { return {pb.Nth(item, 0U), pb.Nth(item, 1U), pb.NewOptional(pb.Unwrap(pb.Nth(item, 2U), landmine, __FILE__, __LINE__, 0)), pb.Nth(item, 3U)}; }),
  227. EJoinKind::Exclusion, {1U, 0U}, {2U, 1U}, {0U}, {0U}, 0ULL, {0U}, EAnyJoinSettings::Right, 3U, outputType),
  228. [&](TRuntimeNode::TList items) -> TRuntimeNode { return pb.NewTuple(items); })
  229. );
  230. const auto graph = setup.BuildGraph(pgmReturn);
  231. const auto iterator = graph->GetValue().GetListIterator();
  232. NUdf::TUnboxedValue item;
  233. UNIT_ASSERT(iterator.Next(item));
  234. UNIT_ASSERT(!item.GetElement(0));
  235. UNBOXED_VALUE_STR_EQUAL(item.GetElement(1), "very long value 1");
  236. UNIT_ASSERT(!iterator.Next(item));
  237. UNIT_ASSERT(!iterator.Next(item));
  238. }
  239. Y_UNIT_TEST_LLVM(ExclusionOrderRightFirstAny) {
  240. TSetup<LLVM> setup;
  241. TProgramBuilder& pb = *setup.PgmBuilder;
  242. const auto indexType = pb.NewDataType(NUdf::TDataType<ui32>::Id);
  243. const auto stringType = pb.NewDataType(NUdf::TDataType<NUdf::TUtf8>::Id);
  244. const auto optStrType = pb.NewOptionalType(stringType);
  245. const auto optionalType = pb.NewOptionalType(pb.NewDataType(NUdf::TDataType<i32>::Id));
  246. const auto tupleType = pb.NewTupleType({optionalType, optStrType, optStrType, indexType});
  247. const auto value1 = pb.NewOptional(pb.NewDataLiteral<NUdf::EDataSlot::Utf8>("very long value 1"));
  248. const auto value2 = pb.NewOptional(pb.NewDataLiteral<NUdf::EDataSlot::Utf8>("very long value 2"));
  249. const auto value3 = pb.NewOptional(pb.NewDataLiteral<NUdf::EDataSlot::Utf8>("very long value 3"));
  250. const auto data1 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(1)), value1, pb.NewEmptyOptional(optStrType), pb.NewDataLiteral<ui32>(0)});
  251. const auto data2 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(2)), value2, pb.NewEmptyOptional(optStrType), pb.NewDataLiteral<ui32>(0)});
  252. const auto data3 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(3)), value3, pb.NewEmptyOptional(optStrType), pb.NewDataLiteral<ui32>(0)});
  253. const auto data4 = pb.NewTuple(tupleType, {pb.NewOptional(pb.NewDataLiteral<i32>(4)), pb.NewEmptyOptional(optStrType), pb.NewEmptyOptional(optStrType), pb.NewDataLiteral<ui32>(0)});
  254. const auto list = pb.NewList(tupleType, {data1, data2, data3, data4});
  255. const auto outputType = pb.NewFlowType(pb.NewMultiType({optStrType, optStrType}));
  256. const auto landmine = pb.NewDataLiteral<NUdf::EDataSlot::Utf8>("ACHTUNG MINEN!");
  257. const auto pgmReturn = pb.Collect(pb.NarrowMap(pb.CommonJoinCore(pb.ExpandMap(pb.ToFlow(list),
  258. [&](TRuntimeNode item) -> TRuntimeNode::TList { return {pb.Nth(item, 0U), pb.NewOptional(pb.Unwrap(pb.Nth(item, 1U), landmine, __FILE__, __LINE__, 0)), pb.Nth(item, 2U), pb.Nth(item, 3U)}; }),
  259. EJoinKind::Exclusion, {1U, 0U}, {2U, 1U}, {0U}, {0U}, 0ULL, {1U}, EAnyJoinSettings::Left, 3U, outputType),
  260. [&](TRuntimeNode::TList items) -> TRuntimeNode { return pb.NewTuple(items); })
  261. );
  262. const auto graph = setup.BuildGraph(pgmReturn);
  263. const auto iterator = graph->GetValue().GetListIterator();
  264. NUdf::TUnboxedValue item;
  265. UNIT_ASSERT(iterator.Next(item));
  266. UNIT_ASSERT(!item.GetElement(1));
  267. UNBOXED_VALUE_STR_EQUAL(item.GetElement(0), "very long value 1");
  268. UNIT_ASSERT(!iterator.Next(item));
  269. UNIT_ASSERT(!iterator.Next(item));
  270. }
  271. }
  272. #endif
  273. }
  274. }