mkql_dict_ut.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. #include "mkql_computation_node_ut.h"
  2. #include <yql/essentials/minikql/mkql_node_cast.h>
  3. #include <yql/essentials/minikql/mkql_string_util.h>
  4. namespace NKikimr {
  5. namespace NMiniKQL {
  6. Y_UNIT_TEST_SUITE(TMiniKQLDictRelatedNodesTest) {
  7. Y_UNIT_TEST_LLVM(TestDictLength) {
  8. TSetup<LLVM> setup;
  9. TProgramBuilder& pgmBuilder = *setup.PgmBuilder;
  10. const auto key1 = pgmBuilder.NewDataLiteral<ui32>(1);
  11. const auto key2 = pgmBuilder.NewDataLiteral<ui32>(2);
  12. const auto key3 = pgmBuilder.NewDataLiteral<ui32>(2);
  13. const auto payload1 = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("A");
  14. const auto payload2 = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("B");
  15. const auto payload3 = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("C");
  16. TVector<std::pair<TRuntimeNode, TRuntimeNode>> dictItems;
  17. dictItems.push_back(std::make_pair(key1, payload1));
  18. dictItems.push_back(std::make_pair(key2, payload2));
  19. dictItems.push_back(std::make_pair(key3, payload3));
  20. const auto dictType = pgmBuilder.NewDictType(pgmBuilder.NewDataType(NUdf::TDataType<ui32>::Id),
  21. pgmBuilder.NewDataType(NUdf::TDataType<char*>::Id), false);
  22. const auto dict = pgmBuilder.NewDict(dictType, dictItems);
  23. const auto pgmReturn = pgmBuilder.Length(dict);
  24. const auto graph = setup.BuildGraph(pgmReturn);
  25. UNIT_ASSERT_VALUES_EQUAL(graph->GetValue().template Get<ui64>(), 2);
  26. }
  27. Y_UNIT_TEST_LLVM(TestDictContains) {
  28. TSetup<LLVM> setup;
  29. TProgramBuilder& pgmBuilder = *setup.PgmBuilder;
  30. const auto key1 = pgmBuilder.NewDataLiteral<ui32>(1);
  31. const auto key2 = pgmBuilder.NewDataLiteral<ui32>(2);
  32. const auto key3 = pgmBuilder.NewDataLiteral<ui32>(2);
  33. const auto missingKey = pgmBuilder.NewDataLiteral<ui32>(3);
  34. const auto payload1 = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("A");
  35. const auto payload2 = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("B");
  36. const auto payload3 = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("C");
  37. TVector<std::pair<TRuntimeNode, TRuntimeNode>> dictItems;
  38. dictItems.push_back(std::make_pair(key1, payload1));
  39. dictItems.push_back(std::make_pair(key2, payload2));
  40. dictItems.push_back(std::make_pair(key3, payload3));
  41. const auto dictType = pgmBuilder.NewDictType(pgmBuilder.NewDataType(NUdf::TDataType<ui32>::Id),
  42. pgmBuilder.NewDataType(NUdf::TDataType<char*>::Id), false);
  43. const auto dict = pgmBuilder.NewDict(dictType, dictItems);
  44. const auto keys = pgmBuilder.NewList(pgmBuilder.NewDataType(NUdf::TDataType<ui32>::Id), {key1, key2, missingKey});
  45. const auto pgmReturn = pgmBuilder.Map(keys,
  46. [&](TRuntimeNode key) {
  47. return pgmBuilder.Contains(dict, key);
  48. });
  49. const auto graph = setup.BuildGraph(pgmReturn);
  50. const auto iterator = graph->GetValue().GetListIterator();
  51. NUdf::TUnboxedValue item;
  52. UNIT_ASSERT(iterator.Next(item));
  53. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  54. UNIT_ASSERT(iterator.Next(item));
  55. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  56. UNIT_ASSERT(iterator.Next(item));
  57. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  58. UNIT_ASSERT(!iterator.Next(item));
  59. UNIT_ASSERT(!iterator.Next(item));
  60. }
  61. Y_UNIT_TEST_LLVM(TestDictLookup) {
  62. TSetup<LLVM> setup;
  63. TProgramBuilder& pgmBuilder = *setup.PgmBuilder;
  64. const auto key1 = pgmBuilder.NewDataLiteral<ui32>(1);
  65. const auto key2 = pgmBuilder.NewDataLiteral<ui32>(2);
  66. const auto key3 = pgmBuilder.NewDataLiteral<ui32>(2);
  67. const auto missingKey = pgmBuilder.NewDataLiteral<ui32>(3);
  68. const auto payload1 = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("A");
  69. const auto payload2 = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("B");
  70. const auto payload3 = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("C");
  71. TVector<std::pair<TRuntimeNode, TRuntimeNode>> dictItems;
  72. dictItems.push_back(std::make_pair(key1, payload1));
  73. dictItems.push_back(std::make_pair(key2, payload2));
  74. dictItems.push_back(std::make_pair(key3, payload3));
  75. const auto dictType = pgmBuilder.NewDictType(pgmBuilder.NewDataType(NUdf::TDataType<ui32>::Id),
  76. pgmBuilder.NewDataType(NUdf::TDataType<char*>::Id), false);
  77. const auto dict = pgmBuilder.NewDict(dictType, dictItems);
  78. const auto keys = pgmBuilder.NewList(pgmBuilder.NewDataType(NUdf::TDataType<ui32>::Id), {key1, key2, missingKey});
  79. const auto pgmReturn = pgmBuilder.Map(keys,
  80. [&](TRuntimeNode key) {
  81. return pgmBuilder.Lookup(dict, key);
  82. });
  83. const auto graph = setup.BuildGraph(pgmReturn);
  84. const auto iterator = graph->GetValue().GetListIterator();
  85. NUdf::TUnboxedValue item;
  86. UNIT_ASSERT(iterator.Next(item));
  87. UNIT_ASSERT(item);
  88. UNBOXED_VALUE_STR_EQUAL(item, "A");
  89. UNIT_ASSERT(iterator.Next(item));
  90. UNIT_ASSERT(item);
  91. UNBOXED_VALUE_STR_EQUAL(item, "B");
  92. UNIT_ASSERT(iterator.Next(item));
  93. UNIT_ASSERT(!item);
  94. UNIT_ASSERT(!iterator.Next(item));
  95. UNIT_ASSERT(!iterator.Next(item));
  96. }
  97. template<bool Multi>
  98. TRuntimeNode PrepareTestDict(TProgramBuilder& pgmBuilder, TRuntimeNode(TProgramBuilder::* factory)(TRuntimeNode list, bool multi,
  99. const TProgramBuilder::TUnaryLambda& keySelector,
  100. const TProgramBuilder::TUnaryLambda& payloadSelector, bool isCompact, ui64 itemsCountHint)) {
  101. const auto key1 = pgmBuilder.NewDataLiteral<ui32>(1);
  102. const auto key2 = pgmBuilder.NewDataLiteral<ui32>(2);
  103. const auto key3 = pgmBuilder.NewDataLiteral<ui32>(2);
  104. const auto key4 = pgmBuilder.NewDataLiteral<ui32>(5);
  105. const auto key5 = pgmBuilder.NewDataLiteral<ui32>(7);
  106. const auto payload1 = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("A");
  107. const auto payload2 = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("B");
  108. const auto payload3 = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("C");
  109. const auto payload4 = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("D");
  110. const auto payload5 = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("E");
  111. auto structType = pgmBuilder.NewStructType(pgmBuilder.NewEmptyStructType(), "Key", pgmBuilder.NewDataType(NUdf::TDataType<ui32>::Id));
  112. structType = pgmBuilder.NewStructType(structType, "Payload", pgmBuilder.NewDataType(NUdf::TDataType<char*>::Id));
  113. const auto list = pgmBuilder.NewList(structType, {
  114. pgmBuilder.AddMember(pgmBuilder.AddMember(pgmBuilder.NewEmptyStruct(), "Key", key3), "Payload", payload3),
  115. pgmBuilder.AddMember(pgmBuilder.AddMember(pgmBuilder.NewEmptyStruct(), "Key", key1), "Payload", payload1),
  116. pgmBuilder.AddMember(pgmBuilder.AddMember(pgmBuilder.NewEmptyStruct(), "Key", key5), "Payload", payload5),
  117. pgmBuilder.AddMember(pgmBuilder.AddMember(pgmBuilder.NewEmptyStruct(), "Key", key4), "Payload", payload4),
  118. pgmBuilder.AddMember(pgmBuilder.AddMember(pgmBuilder.NewEmptyStruct(), "Key", key2), "Payload", payload2)
  119. });
  120. const auto dict = (pgmBuilder.*factory)(list, Multi,
  121. [&](TRuntimeNode item) {
  122. return pgmBuilder.Member(item, "Key");
  123. },
  124. [&](TRuntimeNode item) {
  125. return pgmBuilder.Member(item, "Payload");
  126. }, false, 0);
  127. return dict;
  128. }
  129. template<bool LLVM>
  130. void TestConvertedDictContains(TRuntimeNode(TProgramBuilder::* factory)(TRuntimeNode list, bool multi,
  131. const TProgramBuilder::TUnaryLambda& keySelector,
  132. const TProgramBuilder::TUnaryLambda& payloadSelector, bool isCompact, ui64 itemsCountHint)) {
  133. TSetup<LLVM> setup;
  134. TProgramBuilder& pgmBuilder = *setup.PgmBuilder;
  135. const auto dict = PrepareTestDict<false>(pgmBuilder, factory);
  136. const auto key1 = pgmBuilder.NewDataLiteral<ui32>(1);
  137. const auto key2 = pgmBuilder.NewDataLiteral<ui32>(2);
  138. const auto missingKey = pgmBuilder.NewDataLiteral<ui32>(42);
  139. const auto keys = pgmBuilder.NewList(pgmBuilder.NewDataType(NUdf::TDataType<ui32>::Id), {key1, key2, missingKey});
  140. const auto pgmReturn = pgmBuilder.Map(keys,
  141. [&](TRuntimeNode key) {
  142. return pgmBuilder.Contains(dict, key);
  143. });
  144. const auto graph = setup.BuildGraph(pgmReturn);
  145. const auto iterator = graph->GetValue().GetListIterator();
  146. NUdf::TUnboxedValue item;
  147. UNIT_ASSERT(iterator.Next(item));
  148. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  149. UNIT_ASSERT(iterator.Next(item));
  150. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), true);
  151. UNIT_ASSERT(iterator.Next(item));
  152. UNIT_ASSERT_VALUES_EQUAL(item.template Get<bool>(), false);
  153. UNIT_ASSERT(!iterator.Next(item));
  154. UNIT_ASSERT(!iterator.Next(item));
  155. }
  156. template<bool LLVM>
  157. void TestConvertedDictLookup(TRuntimeNode(TProgramBuilder::* factory)(TRuntimeNode list, bool multi,
  158. const TProgramBuilder::TUnaryLambda& keySelector,
  159. const TProgramBuilder::TUnaryLambda& payloadSelector, bool isCompact, ui64 itemsCountHint)) {
  160. TSetup<LLVM> setup;
  161. TProgramBuilder& pgmBuilder = *setup.PgmBuilder;
  162. const auto dict = PrepareTestDict<false>(pgmBuilder, factory);
  163. const auto key1 = pgmBuilder.NewDataLiteral<ui32>(1);
  164. const auto key2 = pgmBuilder.NewDataLiteral<ui32>(2);
  165. const auto missingKey = pgmBuilder.NewDataLiteral<ui32>(18);
  166. const auto keys = pgmBuilder.NewList(pgmBuilder.NewDataType(NUdf::TDataType<ui32>::Id), {key1, key2, missingKey});
  167. const auto pgmReturn = pgmBuilder.Map(keys,
  168. [&](TRuntimeNode key) {
  169. return pgmBuilder.Lookup(dict, key);
  170. });
  171. const auto graph = setup.BuildGraph(pgmReturn);
  172. const auto iterator = graph->GetValue().GetListIterator();
  173. NUdf::TUnboxedValue item;
  174. UNIT_ASSERT(iterator.Next(item));
  175. UNIT_ASSERT(item);
  176. UNBOXED_VALUE_STR_EQUAL(item, "A");
  177. UNIT_ASSERT(iterator.Next(item));
  178. UNIT_ASSERT(item);
  179. UNBOXED_VALUE_STR_EQUAL(item, "C");
  180. UNIT_ASSERT(iterator.Next(item));
  181. UNIT_ASSERT(!item);
  182. UNIT_ASSERT(!iterator.Next(item));
  183. UNIT_ASSERT(!iterator.Next(item));
  184. }
  185. Y_UNIT_TEST_LLVM(TestSortedDictContains) {
  186. TestConvertedDictContains<LLVM>(&TProgramBuilder::ToSortedDict);
  187. }
  188. Y_UNIT_TEST_LLVM(TestSortedDictLookup) {
  189. TestConvertedDictLookup<LLVM>(&TProgramBuilder::ToSortedDict);
  190. }
  191. Y_UNIT_TEST_LLVM(TestHashedDictContains) {
  192. TestConvertedDictContains<LLVM>(&TProgramBuilder::ToHashedDict);
  193. }
  194. Y_UNIT_TEST_LLVM(TestHashedDictLookup) {
  195. TestConvertedDictLookup<LLVM>(&TProgramBuilder::ToHashedDict);
  196. }
  197. template<bool LLVM, bool SortBeforeCompare>
  198. void TestDictItemsImpl(TRuntimeNode(TProgramBuilder::* factory)(TRuntimeNode list, bool multi,
  199. const TProgramBuilder::TUnaryLambda& keySelector,
  200. const TProgramBuilder::TUnaryLambda& payloadSelector, bool isCompact, ui64 itemsCountHint)) {
  201. TSetup<LLVM> setup;
  202. TProgramBuilder& pgmBuilder = *setup.PgmBuilder;
  203. const auto dict = PrepareTestDict<false>(pgmBuilder, factory);
  204. const auto pgmReturn = pgmBuilder.DictItems(dict);
  205. const auto graph = setup.BuildGraph(pgmReturn);
  206. const auto iterator = graph->GetValue().GetListIterator();
  207. std::vector<std::pair<ui32, TString>> items;
  208. for (NUdf::TUnboxedValue item; iterator.Next(item);) {
  209. const auto& pay = item.GetElement(1);
  210. items.emplace_back(item.GetElement(0).template Get<ui32>(), pay.AsStringRef());
  211. }
  212. if (SortBeforeCompare) {
  213. std::sort(items.begin(), items.end(), [](const std::pair<ui32, TString>& left, const std::pair<ui32, TString>& right) {
  214. return left.first < right.first;
  215. });
  216. }
  217. UNIT_ASSERT_VALUES_EQUAL(items.size(), 4U);
  218. UNIT_ASSERT_VALUES_EQUAL(items[0].first, 1);
  219. UNIT_ASSERT_VALUES_EQUAL(items[0].second, "A");
  220. UNIT_ASSERT_VALUES_EQUAL(items[1].first, 2);
  221. UNIT_ASSERT_VALUES_EQUAL(items[1].second, "C");
  222. UNIT_ASSERT_VALUES_EQUAL(items[2].first, 5);
  223. UNIT_ASSERT_VALUES_EQUAL(items[2].second, "D");
  224. UNIT_ASSERT_VALUES_EQUAL(items[3].first, 7);
  225. UNIT_ASSERT_VALUES_EQUAL(items[3].second, "E");
  226. }
  227. template<bool LLVM, bool SortBeforeCompare>
  228. void TestDictKeysImpl(TRuntimeNode(TProgramBuilder::* factory)(TRuntimeNode list, bool multi,
  229. const TProgramBuilder::TUnaryLambda& keySelector,
  230. const TProgramBuilder::TUnaryLambda& payloadSelector, bool isCompact, ui64 itemsCountHint)) {
  231. TSetup<LLVM> setup;
  232. TProgramBuilder& pgmBuilder = *setup.PgmBuilder;
  233. const auto dict = PrepareTestDict<false>(pgmBuilder, factory);
  234. const auto pgmReturn = pgmBuilder.DictKeys(dict);
  235. const auto graph = setup.BuildGraph(pgmReturn);
  236. const auto iterator = graph->GetValue().GetListIterator();
  237. std::vector<ui32> items;
  238. for (NUdf::TUnboxedValue item; iterator.Next(item);) {
  239. items.emplace_back(item.template Get<ui32>());
  240. }
  241. if (SortBeforeCompare) {
  242. std::sort(items.begin(), items.end());
  243. }
  244. UNIT_ASSERT_VALUES_EQUAL(items.size(), 4U);
  245. UNIT_ASSERT_VALUES_EQUAL(items[0], 1);
  246. UNIT_ASSERT_VALUES_EQUAL(items[1], 2);
  247. UNIT_ASSERT_VALUES_EQUAL(items[2], 5);
  248. UNIT_ASSERT_VALUES_EQUAL(items[3], 7);
  249. }
  250. template<bool LLVM, bool SortBeforeCompare>
  251. void TestDictPayloadsImpl(TRuntimeNode(TProgramBuilder::* factory)(TRuntimeNode list, bool multi,
  252. const TProgramBuilder::TUnaryLambda& keySelector,
  253. const TProgramBuilder::TUnaryLambda& payloadSelector, bool isCompact, ui64 itemsCountHint)) {
  254. TSetup<LLVM> setup;
  255. TProgramBuilder& pgmBuilder = *setup.PgmBuilder;
  256. const auto dict = PrepareTestDict<false>(pgmBuilder, factory);
  257. const auto pgmReturn = pgmBuilder.DictPayloads(dict);
  258. const auto graph = setup.BuildGraph(pgmReturn);
  259. const auto iterator = graph->GetValue().GetListIterator();
  260. std::vector<TString> items;
  261. for (NUdf::TUnboxedValue item; iterator.Next(item);) {
  262. items.emplace_back(item.AsStringRef());
  263. }
  264. if (SortBeforeCompare) {
  265. std::sort(items.begin(), items.end());
  266. }
  267. UNIT_ASSERT_VALUES_EQUAL(items.size(), 4U);
  268. UNIT_ASSERT_VALUES_EQUAL(items[0], "A");
  269. UNIT_ASSERT_VALUES_EQUAL(items[1], "C");
  270. UNIT_ASSERT_VALUES_EQUAL(items[2], "D");
  271. UNIT_ASSERT_VALUES_EQUAL(items[3], "E");
  272. }
  273. Y_UNIT_TEST_LLVM(TestSortedDictItems) {
  274. TestDictItemsImpl<LLVM, false>(&TProgramBuilder::ToSortedDict);
  275. }
  276. Y_UNIT_TEST_LLVM(TestHashedDictItems) {
  277. TestDictItemsImpl<LLVM, true>(&TProgramBuilder::ToHashedDict);
  278. }
  279. Y_UNIT_TEST_LLVM(TestSortedDictKeys) {
  280. TestDictKeysImpl<LLVM, false>(&TProgramBuilder::ToSortedDict);
  281. }
  282. Y_UNIT_TEST_LLVM(TestHashedDictKeys) {
  283. TestDictKeysImpl<LLVM, true>(&TProgramBuilder::ToHashedDict);
  284. }
  285. Y_UNIT_TEST_LLVM(TestSortedPayloadsKeys) {
  286. TestDictPayloadsImpl<LLVM, false>(&TProgramBuilder::ToSortedDict);
  287. }
  288. Y_UNIT_TEST_LLVM(TestHashedPayloadsKeys) {
  289. TestDictPayloadsImpl<LLVM, true>(&TProgramBuilder::ToHashedDict);
  290. }
  291. template<bool LLVM>
  292. void TestConvertedMultiDictLookup(TRuntimeNode(TProgramBuilder::* factory)(TRuntimeNode list, bool multi,
  293. const TProgramBuilder::TUnaryLambda& keySelector,
  294. const TProgramBuilder::TUnaryLambda& payloadSelector, bool isCompact, ui64 itemsCountHint)) {
  295. TSetup<LLVM> setup;
  296. TProgramBuilder& pgmBuilder = *setup.PgmBuilder;
  297. const auto dict = PrepareTestDict<true>(pgmBuilder, factory);
  298. const auto key1 = pgmBuilder.NewDataLiteral<ui32>(1);
  299. const auto key2 = pgmBuilder.NewDataLiteral<ui32>(2);
  300. const auto missingKey = pgmBuilder.NewDataLiteral<ui32>(3);
  301. const auto keys = pgmBuilder.NewList(pgmBuilder.NewDataType(NUdf::TDataType<ui32>::Id), {key1, key2, missingKey});
  302. const auto pgmReturn = pgmBuilder.Map(keys,
  303. [&](TRuntimeNode key) {
  304. return pgmBuilder.Lookup(dict, key);
  305. });
  306. const auto graph = setup.BuildGraph(pgmReturn);
  307. const auto iterator = graph->GetValue().GetListIterator();
  308. NUdf::TUnboxedValue item, item2;
  309. UNIT_ASSERT(iterator.Next(item));
  310. UNIT_ASSERT(item);
  311. auto iter2 = item.GetListIterator();
  312. UNIT_ASSERT(iter2.Next(item2));
  313. UNBOXED_VALUE_STR_EQUAL(item2, "A");
  314. UNIT_ASSERT(!iter2.Next(item2));
  315. UNIT_ASSERT(!iter2.Next(item2));
  316. UNIT_ASSERT(iterator.Next(item));
  317. UNIT_ASSERT(item);
  318. iter2 = item.GetListIterator();
  319. UNIT_ASSERT(iter2.Next(item2));
  320. UNBOXED_VALUE_STR_EQUAL(item2, "C");
  321. UNIT_ASSERT(iter2.Next(item2));
  322. UNBOXED_VALUE_STR_EQUAL(item2, "B");
  323. UNIT_ASSERT(!iter2.Next(item2));
  324. UNIT_ASSERT(!iter2.Next(item2));
  325. UNIT_ASSERT(iterator.Next(item));
  326. UNIT_ASSERT(!item);
  327. UNIT_ASSERT(!iterator.Next(item));
  328. UNIT_ASSERT(!iterator.Next(item));
  329. }
  330. Y_UNIT_TEST_LLVM(TestSortedMultiDictLookup) {
  331. TestConvertedMultiDictLookup<LLVM>(&TProgramBuilder::ToSortedDict);
  332. }
  333. Y_UNIT_TEST_LLVM(TestHashedMultiDictLookup) {
  334. TestConvertedMultiDictLookup<LLVM>(&TProgramBuilder::ToHashedDict);
  335. }
  336. }
  337. }
  338. }