simple_udf.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. #include <util/generic/bt_exception.h>
  2. #include <util/generic/hash.h>
  3. #include <util/string/cast.h>
  4. #include <yql/essentials/public/udf/udf_helpers.h>
  5. #include <yql/essentials/public/udf/udf_value_builder.h>
  6. using namespace NKikimr;
  7. using namespace NUdf;
  8. namespace {
  9. SIMPLE_UDF(TCrash, ui64(char*)) {
  10. Y_UNUSED(valueBuilder);
  11. Y_UNUSED(args);
  12. int *ptr = nullptr;
  13. *ptr = 1;
  14. return TUnboxedValuePod(0);
  15. }
  16. void Throws(const TString& msg) {
  17. ythrow TWithBackTrace<yexception>() << msg;
  18. }
  19. SIMPLE_UDF(TException, ui64(char*)) {
  20. Y_UNUSED(valueBuilder);
  21. TString msg(args[0].AsStringRef());
  22. Throws(msg);
  23. return TUnboxedValuePod(0);
  24. }
  25. SIMPLE_UDF(TReturnNull, char*(char*)) {
  26. Y_UNUSED(valueBuilder);
  27. Y_UNUSED(args);
  28. return TUnboxedValuePod(NULL);
  29. }
  30. SIMPLE_UDF(TReturnVoid, void(char*)) {
  31. Y_UNUSED(valueBuilder);
  32. Y_UNUSED(args);
  33. return TUnboxedValuePod::Void();
  34. }
  35. SIMPLE_UDF(TReturnEmpty, TOptional<char*>(char*)) {
  36. Y_UNUSED(valueBuilder);
  37. Y_UNUSED(args);
  38. return TUnboxedValuePod();
  39. }
  40. SIMPLE_UDF(TReturnBrokenInt, ui32()) {
  41. Y_UNUSED(args);
  42. return valueBuilder->NewString("Bunny");
  43. }
  44. SIMPLE_UDF(TEcho, char*(TOptional<char*>)) {
  45. if (args[0]) {
  46. return valueBuilder->NewString(args[0].AsStringRef());
  47. } else {
  48. return valueBuilder->NewString("<empty optional>");
  49. }
  50. }
  51. SIMPLE_UDF_WITH_OPTIONAL_ARGS(TEchoWithPrefix, char*(char*,TOptional<char*>), 1) {
  52. if (!args[1])
  53. return TUnboxedValuePod(args[0]);
  54. return valueBuilder->ConcatStrings(args[1], args[0]);
  55. }
  56. SIMPLE_UDF_RUN(TEchoWithRunPrefix, char*(char*), TOptional<char*>) {
  57. if (!RunConfig)
  58. return TUnboxedValuePod(args[0]);
  59. return valueBuilder->PrependString(RunConfig.AsStringRef(), args[0]);
  60. }
  61. SIMPLE_UDF(TConst, char*()) {
  62. Y_UNUSED(args);
  63. return valueBuilder->NewString(TStringBuf("Constant response"));
  64. }
  65. SIMPLE_UDF(TConcat, char*(char*, char*)) {
  66. return valueBuilder->ConcatStrings(args[0], args[1]);
  67. }
  68. SIMPLE_UDF(TRepeat, char*(char*, ui64)) {
  69. TString orig(args[0].AsStringRef());
  70. ui64 times = args[1].Get<ui64>();
  71. TString res = "";
  72. for (ui64 i = 0; i < times; i++) {
  73. res += orig;
  74. }
  75. return valueBuilder->NewString(res);
  76. }
  77. SIMPLE_UDF(TSleep, ui64(ui64)) {
  78. Y_UNUSED(valueBuilder);
  79. ui64 time = args[0].Get<ui64>();
  80. usleep(time);
  81. return TUnboxedValuePod(static_cast<ui64>(0));
  82. }
  83. using TComplexReturnTypeSignature = TDict<char*, ui32>(char*);
  84. SIMPLE_UDF(TComplexReturnType, TComplexReturnTypeSignature) {
  85. const TStringBuf s = args[0].AsStringRef();
  86. THashMap<TString, ui32> stat;
  87. for(auto c: s) {
  88. ++stat[TString{c}];
  89. }
  90. auto dictBuilder = valueBuilder->NewDict(ReturnType_, 0);
  91. for(const auto& [k, v]: stat) {
  92. dictBuilder->Add(valueBuilder->NewString(k), TUnboxedValuePod{v});
  93. }
  94. return dictBuilder->Build();
  95. }
  96. extern const char c[] = "C";
  97. extern const char d[] = "D";
  98. using TNamedC = TNamedArg<ui32, c>;
  99. using TNamedD = TNamedArg<ui32, d>;
  100. SIMPLE_UDF_WITH_OPTIONAL_ARGS(TNamedArgs, char*(ui32, TOptional<ui32>, TNamedC, TNamedD), 3) {
  101. TString res;
  102. res += "A=" + ToString(args[0].Get<ui32>());
  103. res += " B=" + (args[1] ? ToString(args[1].Get<ui32>()) : "none");
  104. res += " C=" + (args[2] ? ToString(args[2].Get<ui32>()) : "none");
  105. res += " D=" + (args[3] ? ToString(args[3].Get<ui32>()) : "none");
  106. return valueBuilder->NewString(res);
  107. }
  108. UDF(TIncrement, builder.Args(2)->
  109. Add<ui32>().Name("Arg1").Flags(ICallablePayload::TArgumentFlags::AutoMap)
  110. .Add(builder.SimpleType<TOptional<ui32>>()).Name("Arg2")
  111. .Done().Returns<ui32>().OptionalArgs(1);) {
  112. Y_UNUSED(valueBuilder);
  113. return TUnboxedValuePod(args[0].Get<ui32>() + args[1].GetOrDefault<ui32>(1));
  114. }
  115. UDF(TIncrementOpt, builder.Args(2)->
  116. Add<ui32>().Name("Arg1").Flags(ICallablePayload::TArgumentFlags::AutoMap)
  117. .Add(builder.SimpleType<TOptional<ui32>>()).Name("Arg2")
  118. .Done().Returns(builder.SimpleType<TOptional<ui32>>()).OptionalArgs(1);) {
  119. Y_UNUSED(valueBuilder);
  120. if (const ui32 by = args[1].GetOrDefault<ui32>(0)) {
  121. return TUnboxedValuePod(args[0].Get<ui32>() + by);
  122. }
  123. else {
  124. return TUnboxedValuePod();
  125. }
  126. }
  127. UDF_IMPL(TIncrementWithCounters,
  128. builder.Args(1)->Add<ui32>().Done().Returns<ui32>();
  129. ,
  130. mutable ::NKikimr::NUdf::TCounter Counter_;
  131. mutable ::NKikimr::NUdf::TScopedProbe Scope_;
  132. ,
  133. Counter_ = builder.GetCounter("IncrementWithCounters_Calls", true);
  134. Scope_ = builder.GetScopedProbe("IncrementWithCounters_Time");
  135. ,
  136. ""
  137. ,
  138. ""
  139. ,
  140. void
  141. ) {
  142. Y_UNUSED(valueBuilder);
  143. Counter_.Inc();
  144. with_lock(Scope_) {
  145. return TUnboxedValuePod(args[0].Get<ui32>() + 1);
  146. }
  147. }
  148. class TGenericAsStruct : public TBoxedValue {
  149. public:
  150. typedef bool TTypeAwareMarker;
  151. TUnboxedValue Run(const IValueBuilder* valueBuilder, const TUnboxedValuePod* args) const final {
  152. TUnboxedValue* items = nullptr;
  153. auto result = valueBuilder->NewArray(Argc, items);
  154. for (size_t i = 0; i < Argc; ++i) {
  155. items[i] = std::move(args[i]);
  156. }
  157. return result;
  158. }
  159. static const TStringRef& Name() {
  160. static auto name = TStringRef::Of("GenericAsStruct");
  161. return name;
  162. }
  163. TGenericAsStruct(size_t argc)
  164. : Argc(argc)
  165. {}
  166. static bool DeclareSignature(const TStringRef& name, TType* userType, IFunctionTypeInfoBuilder& builder, bool typesOnly) {
  167. if (Name() == name) {
  168. if (!userType) {
  169. builder.SetError("Missing user type.");
  170. return true;
  171. }
  172. builder.UserType(userType);
  173. const auto typeHelper = builder.TypeInfoHelper();
  174. const auto userTypeInspector = TTupleTypeInspector(*typeHelper, userType);
  175. if (!userTypeInspector || userTypeInspector.GetElementsCount() < 1) {
  176. builder.SetError("Invalid user type.");
  177. return true;
  178. }
  179. const auto argsTypeTuple = userTypeInspector.GetElementType(0);
  180. const auto argsTypeInspector = TTupleTypeInspector(*typeHelper, argsTypeTuple);
  181. if (!argsTypeInspector) {
  182. builder.SetError("Invalid user type - expected tuple.");
  183. return true;
  184. }
  185. const size_t argsCount = argsTypeInspector.GetElementsCount();
  186. auto argBuilder = builder.Args(argsCount);
  187. auto structBuilder = builder.Struct(argsCount);
  188. for (size_t i = 0; i < argsCount; ++i) {
  189. auto argType = argsTypeInspector.GetElementType(i);
  190. argBuilder->Add(argType);
  191. TString name = TStringBuilder() << "arg_" << i;
  192. structBuilder->AddField(name, argType, nullptr);
  193. }
  194. argBuilder->Done().Returns(builder.Optional()->Item(structBuilder->Build()).Build());
  195. if (!typesOnly) {
  196. builder.Implementation(new TGenericAsStruct(argsCount));
  197. }
  198. return true;
  199. }
  200. else {
  201. return false;
  202. }
  203. }
  204. private:
  205. const size_t Argc;
  206. };
  207. SIMPLE_MODULE(TSimpleUdfModule,
  208. TCrash,
  209. TException,
  210. TReturnNull,
  211. TReturnVoid,
  212. TReturnEmpty,
  213. TReturnBrokenInt,
  214. TEcho,
  215. TEchoWithPrefix,
  216. TEchoWithRunPrefix,
  217. TConst,
  218. TConcat,
  219. TRepeat,
  220. TSleep,
  221. TComplexReturnType,
  222. TNamedArgs,
  223. TIncrement,
  224. TIncrementOpt,
  225. TIncrementWithCounters,
  226. TGenericAsStruct
  227. )
  228. } // namespace
  229. REGISTER_MODULES(TSimpleUdfModule)