mkql_opt_literal_ut.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. #include "mkql_opt_literal.h"
  2. #include "mkql_program_builder.h"
  3. #include "mkql_node_printer.h"
  4. #include "mkql_function_registry.h"
  5. #include <library/cpp/testing/unittest/registar.h>
  6. namespace NKikimr {
  7. namespace NMiniKQL {
  8. TRuntimeNode MakeVoidCallable(TProgramBuilder& pgmBuilder) {
  9. TCallableBuilder callableBuilder(pgmBuilder.GetTypeEnvironment(), "Effect", pgmBuilder.NewVoid().GetStaticType());
  10. return TRuntimeNode(callableBuilder.Build(), false);
  11. }
  12. Y_UNIT_TEST_SUITE(TMiniKQLLPOTest) {
  13. Y_UNIT_TEST(TestIfPredicateTrue) {
  14. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  15. TScopedAlloc alloc(__LOCATION__);
  16. TTypeEnvironment env(alloc);
  17. TProgramBuilder pgmBuilder(env, *functionRegistry);
  18. auto pgmReturn = pgmBuilder.AsList(pgmBuilder.If(pgmBuilder.NewDataLiteral(true), MakeVoidCallable(pgmBuilder), pgmBuilder.NewVoid()));
  19. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  20. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::List);
  21. const auto& list = static_cast<const TListLiteral&>(*pgm);
  22. UNIT_ASSERT_EQUAL(list.GetItemsCount(), 1);
  23. auto item = list.GetItems()[0];
  24. UNIT_ASSERT(!item.IsImmediate());
  25. UNIT_ASSERT_EQUAL(item.GetNode()->GetType()->GetKind(), TType::EKind::Callable);
  26. UNIT_ASSERT_EQUAL(static_cast<TCallableType&>(*item.GetNode()->GetType()).GetName(), "Effect");
  27. }
  28. Y_UNIT_TEST(TestIfPredicateSame) {
  29. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  30. TScopedAlloc alloc(__LOCATION__);
  31. TTypeEnvironment env(alloc);
  32. TProgramBuilder pgmBuilder(env, *functionRegistry);
  33. auto pgmReturn = pgmBuilder.AsList(pgmBuilder.If(pgmBuilder.NewDataLiteral(true), MakeVoidCallable(pgmBuilder), MakeVoidCallable(pgmBuilder)));
  34. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  35. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::List);
  36. const auto& list = static_cast<const TListLiteral&>(*pgm);
  37. UNIT_ASSERT_EQUAL(list.GetItemsCount(), 1);
  38. auto item = list.GetItems()[0];
  39. UNIT_ASSERT(!item.IsImmediate());
  40. UNIT_ASSERT_EQUAL(item.GetNode()->GetType()->GetKind(), TType::EKind::Callable);
  41. UNIT_ASSERT_EQUAL(static_cast<TCallableType&>(*item.GetNode()->GetType()).GetName(), "Effect");
  42. }
  43. Y_UNIT_TEST(TestIfPredicateFalse) {
  44. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  45. TScopedAlloc alloc(__LOCATION__);
  46. TTypeEnvironment env(alloc);
  47. TProgramBuilder pgmBuilder(env, *functionRegistry);
  48. auto pgmReturn = pgmBuilder.AsList(pgmBuilder.If(pgmBuilder.NewDataLiteral(false), pgmBuilder.NewVoid(), MakeVoidCallable(pgmBuilder)));
  49. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  50. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::List);
  51. const auto& list = static_cast<const TListLiteral&>(*pgm);
  52. UNIT_ASSERT_EQUAL(list.GetItemsCount(), 1);
  53. auto item = list.GetItems()[0];
  54. UNIT_ASSERT(!item.IsImmediate());
  55. UNIT_ASSERT_EQUAL(item.GetNode()->GetType()->GetKind(), TType::EKind::Callable);
  56. UNIT_ASSERT_EQUAL(static_cast<TCallableType&>(*item.GetNode()->GetType()).GetName(), "Effect");
  57. }
  58. Y_UNIT_TEST(TestSize) {
  59. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  60. TScopedAlloc alloc(__LOCATION__);
  61. TTypeEnvironment env(alloc);
  62. TProgramBuilder pgmBuilder(env, *functionRegistry);
  63. auto pgmReturn = pgmBuilder.Size(pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("abc"));
  64. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  65. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::Data);
  66. UNIT_ASSERT_EQUAL(static_cast<TDataType&>(*pgm->GetType()).GetSchemeType(), NUdf::TDataType<ui32>::Id);
  67. UNIT_ASSERT_EQUAL(static_cast<TDataLiteral&>(*pgm).AsValue().Get<ui32>(), 3);
  68. }
  69. Y_UNIT_TEST(TestLength) {
  70. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  71. TScopedAlloc alloc(__LOCATION__);
  72. TTypeEnvironment env(alloc);
  73. TProgramBuilder pgmBuilder(env, *functionRegistry);
  74. auto list = pgmBuilder.AsList(pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("abc"));
  75. auto pgmReturn = pgmBuilder.Length(list);
  76. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  77. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::Data);
  78. UNIT_ASSERT_EQUAL(static_cast<TDataType&>(*pgm->GetType()).GetSchemeType(), NUdf::TDataType<ui64>::Id);
  79. UNIT_ASSERT_EQUAL(static_cast<TDataLiteral&>(*pgm).AsValue().Get<ui64>(), 1);
  80. }
  81. Y_UNIT_TEST(TestAddMember) {
  82. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  83. TScopedAlloc alloc(__LOCATION__);
  84. TTypeEnvironment env(alloc);
  85. TProgramBuilder pgmBuilder(env, *functionRegistry);
  86. auto struct1 = pgmBuilder.NewEmptyStruct();
  87. struct1 = pgmBuilder.AddMember(struct1, "x", pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("abc"));
  88. auto pgm = LiteralPropagationOptimization(struct1, env, true).GetNode();
  89. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::Struct);
  90. UNIT_ASSERT_EQUAL(static_cast<TStructLiteral&>(*pgm).GetValuesCount(), 1);
  91. auto struct2 = pgmBuilder.NewEmptyStruct();
  92. struct2 = pgmBuilder.AddMember(struct2, "x", pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("abc"));
  93. struct2 = pgmBuilder.AddMember(struct2, "z", pgmBuilder.NewDataLiteral<ui32>(11));
  94. pgm = LiteralPropagationOptimization(struct2, env, true).GetNode();
  95. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::Struct);
  96. UNIT_ASSERT_EQUAL(static_cast<TStructLiteral&>(*pgm).GetValuesCount(), 2);
  97. auto struct3 = pgmBuilder.NewEmptyStruct();
  98. struct3 = pgmBuilder.AddMember(struct3, "x", pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("abc"));
  99. struct3 = pgmBuilder.AddMember(struct3, "z", pgmBuilder.NewDataLiteral<ui32>(11));
  100. struct3 = pgmBuilder.AddMember(struct3, "y", pgmBuilder.NewDataLiteral<ui64>(777));
  101. pgm = LiteralPropagationOptimization(struct3, env, true).GetNode();
  102. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::Struct);
  103. UNIT_ASSERT_EQUAL(static_cast<TStructLiteral&>(*pgm).GetValuesCount(), 3);
  104. }
  105. Y_UNIT_TEST(TestMember) {
  106. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  107. TScopedAlloc alloc(__LOCATION__);
  108. TTypeEnvironment env(alloc);
  109. TProgramBuilder pgmBuilder(env, *functionRegistry);
  110. auto struct1 = pgmBuilder.NewEmptyStruct();
  111. struct1 = pgmBuilder.AddMember(struct1, "x", pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("abc"));
  112. struct1 = pgmBuilder.AddMember(struct1, "z", MakeVoidCallable(pgmBuilder));
  113. struct1 = pgmBuilder.AddMember(struct1, "y", pgmBuilder.NewVoid());
  114. auto pgm = LiteralPropagationOptimization(pgmBuilder.Member(struct1, "y"), env, true).GetNode();
  115. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::Void);
  116. }
  117. Y_UNIT_TEST(TestFilterPredicateTrue) {
  118. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  119. TScopedAlloc alloc(__LOCATION__);
  120. TTypeEnvironment env(alloc);
  121. TProgramBuilder pgmBuilder(env, *functionRegistry);
  122. TVector<TRuntimeNode> items;
  123. items.push_back(pgmBuilder.NewDataLiteral<ui32>(1));
  124. items.push_back(pgmBuilder.NewDataLiteral<ui32>(2));
  125. auto list = pgmBuilder.AsList(items);
  126. auto pgmReturn = pgmBuilder.Filter(list,
  127. [&](TRuntimeNode item) {
  128. Y_UNUSED(item);
  129. return pgmBuilder.NewDataLiteral(true);
  130. });
  131. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  132. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::List);
  133. UNIT_ASSERT_EQUAL(static_cast<TListLiteral&>(*pgm).GetItemsCount(), 2);
  134. }
  135. Y_UNIT_TEST(TestFilterPredicateFalse) {
  136. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  137. TScopedAlloc alloc(__LOCATION__);
  138. TTypeEnvironment env(alloc);
  139. TProgramBuilder pgmBuilder(env, *functionRegistry);
  140. TVector<TRuntimeNode> items;
  141. items.push_back(pgmBuilder.NewDataLiteral<ui32>(1));
  142. items.push_back(pgmBuilder.NewDataLiteral<ui32>(2));
  143. auto list = pgmBuilder.AsList(items);
  144. auto pgmReturn = pgmBuilder.Filter(list,
  145. [&](TRuntimeNode item) {
  146. Y_UNUSED(item);
  147. return pgmBuilder.NewDataLiteral(false);
  148. });
  149. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  150. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::List);
  151. UNIT_ASSERT_EQUAL(static_cast<TListLiteral&>(*pgm).GetItemsCount(), 0);
  152. }
  153. Y_UNIT_TEST(TestMapToVoid) {
  154. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  155. TScopedAlloc alloc(__LOCATION__);
  156. TTypeEnvironment env(alloc);
  157. TProgramBuilder pgmBuilder(env, *functionRegistry);
  158. TVector<TRuntimeNode> items;
  159. items.push_back(pgmBuilder.NewDataLiteral<ui32>(1));
  160. items.push_back(pgmBuilder.NewDataLiteral<ui32>(2));
  161. auto list = pgmBuilder.AsList(items);
  162. auto pgmReturn = pgmBuilder.Map(list,
  163. [&](TRuntimeNode item) {
  164. Y_UNUSED(item);
  165. return pgmBuilder.NewVoid();
  166. });
  167. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  168. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::List);
  169. UNIT_ASSERT_EQUAL(static_cast<TListLiteral&>(*pgm).GetItemsCount(), 0);
  170. }
  171. Y_UNIT_TEST(TestFlatMapToLiteralListOfVoid) {
  172. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  173. TScopedAlloc alloc(__LOCATION__);
  174. TTypeEnvironment env(alloc);
  175. TProgramBuilder pgmBuilder(env, *functionRegistry);
  176. TVector<TRuntimeNode> items;
  177. items.push_back(pgmBuilder.NewDataLiteral<ui32>(1));
  178. items.push_back(pgmBuilder.NewDataLiteral<ui32>(2));
  179. auto list = pgmBuilder.AsList(items);
  180. auto pgmReturn = pgmBuilder.FlatMap(list,
  181. [&](TRuntimeNode item) {
  182. Y_UNUSED(item);
  183. return pgmBuilder.NewEmptyListOfVoid();
  184. });
  185. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  186. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::List);
  187. UNIT_ASSERT_EQUAL(static_cast<TListLiteral&>(*pgm).GetItemsCount(), 0);
  188. }
  189. Y_UNIT_TEST(TestFlatMapToLiteralListOfVoid_Optional) {
  190. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  191. TScopedAlloc alloc(__LOCATION__);
  192. TTypeEnvironment env(alloc);
  193. TProgramBuilder pgmBuilder(env, *functionRegistry);
  194. TVector<TRuntimeNode> items;
  195. items.push_back(pgmBuilder.NewDataLiteral<ui32>(1));
  196. items.push_back(pgmBuilder.NewDataLiteral<ui32>(2));
  197. auto list = pgmBuilder.AsList(items);
  198. auto pgmReturn = pgmBuilder.FlatMap(list,
  199. [&](TRuntimeNode item) {
  200. Y_UNUSED(item);
  201. return pgmBuilder.NewEmptyOptional(pgmBuilder.NewOptionalType(env.GetTypeOfVoidLazy()));
  202. });
  203. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  204. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::List);
  205. UNIT_ASSERT_EQUAL(static_cast<TListLiteral&>(*pgm).GetItemsCount(), 0);
  206. }
  207. Y_UNIT_TEST(TestLiteralCoalesceExist) {
  208. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  209. TScopedAlloc alloc(__LOCATION__);
  210. TTypeEnvironment env(alloc);
  211. TProgramBuilder pgmBuilder(env, *functionRegistry);
  212. auto pgmReturn = pgmBuilder.Coalesce(pgmBuilder.NewOptional(pgmBuilder.NewDataLiteral<ui32>(1)),
  213. pgmBuilder.NewDataLiteral<ui32>(2));
  214. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  215. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::Data);
  216. UNIT_ASSERT_EQUAL(static_cast<TDataLiteral&>(*pgm).AsValue().Get<ui32>(), 1);
  217. }
  218. Y_UNIT_TEST(TestLiteralCoalesceNotExist) {
  219. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  220. TScopedAlloc alloc(__LOCATION__);
  221. TTypeEnvironment env(alloc);
  222. TProgramBuilder pgmBuilder(env, *functionRegistry);
  223. auto pgmReturn = pgmBuilder.Coalesce(pgmBuilder.NewEmptyOptionalDataLiteral(NUdf::TDataType<ui32>::Id),
  224. pgmBuilder.NewDataLiteral<ui32>(2));
  225. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  226. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::Data);
  227. UNIT_ASSERT_EQUAL(static_cast<TDataLiteral&>(*pgm).AsValue().Get<ui32>(), 2);
  228. }
  229. Y_UNIT_TEST(TestLiteralExists) {
  230. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  231. TScopedAlloc alloc(__LOCATION__);
  232. TTypeEnvironment env(alloc);
  233. TProgramBuilder pgmBuilder(env, *functionRegistry);
  234. auto pgmReturn = pgmBuilder.Exists(pgmBuilder.NewOptional(pgmBuilder.NewDataLiteral<ui32>(1)));
  235. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  236. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::Data);
  237. UNIT_ASSERT_EQUAL(static_cast<TDataLiteral&>(*pgm).AsValue().Get<bool>(), true);
  238. }
  239. Y_UNIT_TEST(TestNth) {
  240. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  241. TScopedAlloc alloc(__LOCATION__);
  242. TTypeEnvironment env(alloc);
  243. TProgramBuilder pgmBuilder(env, *functionRegistry);
  244. TVector<TRuntimeNode> elements(2);
  245. elements[0] = pgmBuilder.NewDataLiteral<NUdf::EDataSlot::String>("34");
  246. elements[1] = pgmBuilder.NewDataLiteral<ui32>(56);
  247. auto tuple = pgmBuilder.NewTuple(elements);
  248. auto pgmReturn = pgmBuilder.Nth(tuple, 1);
  249. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  250. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::Data);
  251. UNIT_ASSERT_EQUAL(static_cast<TDataType&>(*pgm->GetType()).GetSchemeType(), NUdf::TDataType<ui32>::Id);
  252. UNIT_ASSERT_EQUAL(static_cast<TDataLiteral&>(*pgm).AsValue().Get<ui32>(), 56);
  253. }
  254. Y_UNIT_TEST(TestExtend) {
  255. auto functionRegistry = CreateFunctionRegistry(IBuiltinFunctionRegistry::TPtr());
  256. TScopedAlloc alloc(__LOCATION__);
  257. TTypeEnvironment env(alloc);
  258. TProgramBuilder pgmBuilder(env, *functionRegistry);
  259. auto pgmReturn = pgmBuilder.Extend({
  260. pgmBuilder.NewEmptyListOfVoid(),
  261. pgmBuilder.NewEmptyListOfVoid(),
  262. pgmBuilder.NewEmptyListOfVoid()});
  263. auto pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  264. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::List);
  265. const auto& result1 = static_cast<const TListLiteral&>(*pgm);
  266. UNIT_ASSERT_EQUAL(result1.GetItemsCount(), 0);
  267. pgmReturn = pgmBuilder.Extend({
  268. pgmBuilder.NewEmptyListOfVoid(),
  269. pgmBuilder.Extend({
  270. pgmBuilder.NewEmptyListOfVoid(),
  271. pgmBuilder.NewEmptyListOfVoid(),
  272. }),
  273. pgmBuilder.NewEmptyListOfVoid()});
  274. pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  275. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::List);
  276. const auto& result2 = static_cast<const TListLiteral&>(*pgm);
  277. UNIT_ASSERT_EQUAL(result2.GetItemsCount(), 0);
  278. pgmReturn = pgmBuilder.Extend({
  279. pgmBuilder.NewEmptyListOfVoid(),
  280. pgmBuilder.AsList(MakeVoidCallable(pgmBuilder)),
  281. pgmBuilder.NewEmptyListOfVoid()});
  282. pgm = LiteralPropagationOptimization(pgmReturn, env, true).GetNode();
  283. UNIT_ASSERT_EQUAL(pgm->GetType()->GetKind(), TType::EKind::Callable);
  284. }
  285. }
  286. }
  287. }