udf_value_builder.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. #pragma once
  2. #include "udf_ptr.h"
  3. #include "udf_types.h"
  4. #include "udf_type_builder.h"
  5. #include "udf_string.h"
  6. #include "udf_type_size_check.h"
  7. #include "udf_value.h"
  8. #include <array>
  9. struct ArrowArray;
  10. namespace NYql {
  11. namespace NUdf {
  12. class IArrowType;
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // IDictValueBuilder
  15. ///////////////////////////////////////////////////////////////////////////////
  16. struct TDictFlags {
  17. enum EDictKind: ui32 {
  18. Sorted = 0x01,
  19. Hashed = 0x02,
  20. Multi = 0x04,
  21. };
  22. };
  23. class IDictValueBuilder
  24. {
  25. public:
  26. using TPtr = TUniquePtr<IDictValueBuilder>;
  27. public:
  28. virtual ~IDictValueBuilder() = default;
  29. virtual IDictValueBuilder& Add(TUnboxedValue&& key, TUnboxedValue&& value) = 0;
  30. virtual TUnboxedValue Build() = 0;
  31. };
  32. UDF_ASSERT_TYPE_SIZE(IDictValueBuilder, 8);
  33. class IListValueBuilder {
  34. public:
  35. using TPtr = TUniquePtr<IListValueBuilder>;
  36. public:
  37. virtual ~IListValueBuilder() = default;
  38. // Destroys (moves out from) the element
  39. virtual IListValueBuilder& Add(TUnboxedValue&& element) = 0;
  40. // Destroys (moves out from) the elements
  41. virtual IListValueBuilder& AddMany(const NUdf::TUnboxedValue* elements, size_t count) = 0;
  42. virtual TUnboxedValue Build() = 0;
  43. };
  44. UDF_ASSERT_TYPE_SIZE(IListValueBuilder, 8);
  45. ///////////////////////////////////////////////////////////////////////////////
  46. // IDateBuilder
  47. ///////////////////////////////////////////////////////////////////////////////
  48. class IDateBuilder1
  49. {
  50. public:
  51. virtual ~IDateBuilder1() = default;
  52. virtual bool MakeDate(ui32 year, ui32 month, ui32 day, ui16& value) const = 0;
  53. virtual bool SplitDate(ui16 value, ui32& year, ui32& month, ui32& day) const = 0;
  54. virtual bool MakeDatetime(ui32 year, ui32 month, ui32 day, ui32 hour, ui32 minute, ui32 second, ui32& value,
  55. ui16 timezoneId = 0) const = 0;
  56. virtual bool SplitDatetime(ui32 value, ui32& year, ui32& month, ui32& day, ui32& hour, ui32& minute, ui32& second,
  57. ui16 timezoneId = 0) const = 0;
  58. // deprecated
  59. virtual bool EnrichDate(ui16 date, ui32& dayOfYear, ui32& weekOfYear, ui32& dayOfWeek) const = 0;
  60. // in minutes
  61. virtual bool GetTimezoneShift(ui32 year, ui32 month, ui32 day, ui32 hour, ui32 minute, ui32 second,
  62. ui16 timezoneId, i32& value) const = 0;
  63. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT < UDF_ABI_COMPATIBILITY_VERSION(2, 23)
  64. virtual void Unused7() const = 0;
  65. virtual void Unused8() const = 0;
  66. #else
  67. virtual bool FullSplitDate(ui16 value, ui32& year, ui32& month, ui32& day,
  68. ui32& dayOfYear, ui32& weekOfYear, ui32& dayOfWeek, ui16 timezoneId = 0) const = 0;
  69. virtual bool FullSplitDatetime(ui32 value, ui32& year, ui32& month, ui32& day, ui32& hour, ui32& minute, ui32& second,
  70. ui32& dayOfYear, ui32& weekOfYear, ui32& dayOfWeek, ui16 timezoneId = 0) const = 0;
  71. #endif
  72. };
  73. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 7)
  74. class IDateBuilder2: public IDateBuilder1
  75. {
  76. public:
  77. virtual bool FindTimezoneName(ui32 id, TStringRef& name) const = 0;
  78. virtual bool FindTimezoneId(const TStringRef& name, ui32& id) const = 0;
  79. };
  80. #endif
  81. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 24)
  82. class IDateBuilder3: public IDateBuilder2
  83. {
  84. public:
  85. virtual bool EnrichDate2(ui16 date, ui32& dayOfYear, ui32& weekOfYear, ui32& weekOfYearIso8601, ui32& dayOfWeek) const = 0;
  86. virtual bool FullSplitDate2(ui16 value, ui32& year, ui32& month, ui32& day,
  87. ui32& dayOfYear, ui32& weekOfYear, ui32& weekOfYearIso8601, ui32& dayOfWeek, ui16 timezoneId = 0) const = 0;
  88. virtual bool FullSplitDatetime2(ui32 value, ui32& year, ui32& month, ui32& day, ui32& hour, ui32& minute, ui32& second,
  89. ui32& dayOfYear, ui32& weekOfYear, ui32& weekOfYearIso8601, ui32& dayOfWeek, ui16 timezoneId = 0) const = 0;
  90. };
  91. #endif
  92. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 40)
  93. class IDateBuilder4: public IDateBuilder3
  94. {
  95. public:
  96. virtual bool SplitTzDate32(i32 date, i32& year, ui32& month, ui32& day,
  97. ui32& dayOfYear, ui32& weekOfYear, ui32& weekOfYearIso8601, ui32& dayOfWeek, ui16 timezoneId = 0) const = 0;
  98. virtual bool SplitTzDatetime64(i64 datetime, i32& year, ui32& month, ui32& day,
  99. ui32& hour, ui32& minute, ui32& second,
  100. ui32& dayOfYear, ui32& weekOfYear, ui32& weekOfYearIso8601, ui32& dayOfWeek, ui16 timezoneId = 0) const = 0;
  101. virtual bool MakeTzDate32(i32 year, ui32 month, ui32 day, i32& date, ui16 timezoneId = 0) const = 0;
  102. virtual bool MakeTzDatetime64(i32 year, ui32 month, ui32 day,
  103. ui32 hour, ui32 minute, ui32 second, i64& datetime, ui16 timezoneId = 0) const = 0;
  104. };
  105. #endif
  106. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 40)
  107. class IDateBuilder: public IDateBuilder4 {
  108. protected:
  109. IDateBuilder();
  110. };
  111. #elif UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 24)
  112. class IDateBuilder: public IDateBuilder3 {
  113. protected:
  114. IDateBuilder();
  115. };
  116. #elif UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 7)
  117. class IDateBuilder: public IDateBuilder2 {
  118. protected:
  119. IDateBuilder();
  120. };
  121. #else
  122. class IDateBuilder: public IDateBuilder1 {
  123. protected:
  124. IDateBuilder();
  125. };
  126. #endif
  127. UDF_ASSERT_TYPE_SIZE(IDateBuilder, 8);
  128. ///////////////////////////////////////////////////////////////////////////////
  129. // IPgBuilder
  130. ///////////////////////////////////////////////////////////////////////////////
  131. class IPgBuilder1 {
  132. public:
  133. virtual ~IPgBuilder1() = default;
  134. // returns Null in case of text format parsing error, error message passed via 'error' arg
  135. virtual TUnboxedValue ValueFromText(ui32 typeId, const TStringRef& value, TStringValue& error) const = 0;
  136. // returns Null in case of wire format parsing error, error message passed via 'error' arg
  137. virtual TUnboxedValue ValueFromBinary(ui32 typeId, const TStringRef& value, TStringValue& error) const = 0;
  138. // targetType is required for diagnostic only in debug mode
  139. virtual TUnboxedValue ConvertFromPg(TUnboxedValue source, ui32 sourceTypeId, const TType* targetType) const = 0;
  140. // sourceType is required for diagnostic only in debug mode
  141. virtual TUnboxedValue ConvertToPg(TUnboxedValue source, const TType* sourceType, ui32 targetTypeId) const = 0;
  142. // targetTypeId is required for diagnostic only in debug mode
  143. virtual TUnboxedValue NewString(i32 typeLen, ui32 targetTypeId, TStringRef data) const = 0;
  144. };
  145. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 31)
  146. class IPgBuilder2: public IPgBuilder1
  147. {
  148. public:
  149. virtual TStringRef AsCStringBuffer(const TUnboxedValue& value) const = 0;
  150. virtual TStringRef AsTextBuffer(const TUnboxedValue& value) const = 0;
  151. };
  152. #endif
  153. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 33)
  154. class IPgBuilder3: public IPgBuilder2
  155. {
  156. public:
  157. virtual TUnboxedValue MakeCString(const char* value) const = 0;
  158. virtual TUnboxedValue MakeText(const char* value) const = 0;
  159. };
  160. #endif
  161. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 35)
  162. class IPgBuilder4: public IPgBuilder3
  163. {
  164. public:
  165. virtual TStringRef AsFixedStringBuffer(const TUnboxedValue& value, ui32 length) const = 0;
  166. };
  167. #endif
  168. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 35)
  169. class IPgBuilder: public IPgBuilder4 {
  170. protected:
  171. IPgBuilder();
  172. };
  173. #elif UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 33)
  174. class IPgBuilder: public IPgBuilder3 {
  175. protected:
  176. IPgBuilder();
  177. };
  178. #elif UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 31)
  179. class IPgBuilder: public IPgBuilder2 {
  180. protected:
  181. IPgBuilder();
  182. };
  183. #else
  184. class IPgBuilder: public IPgBuilder1 {
  185. protected:
  186. IPgBuilder();
  187. };
  188. #endif
  189. UDF_ASSERT_TYPE_SIZE(IPgBuilder, 8);
  190. ///////////////////////////////////////////////////////////////////////////////
  191. // IValueBuilder
  192. ///////////////////////////////////////////////////////////////////////////////
  193. class IValueBuilder1
  194. {
  195. public:
  196. virtual ~IValueBuilder1() = default;
  197. virtual TUnboxedValue NewStringNotFilled(ui32 size) const = 0;
  198. virtual TUnboxedValue NewString(const TStringRef& ref) const = 0;
  199. virtual TUnboxedValue ConcatStrings(TUnboxedValuePod first, TUnboxedValuePod second) const = 0;
  200. virtual TUnboxedValue AppendString(TUnboxedValuePod value, const TStringRef& ref) const = 0;
  201. virtual TUnboxedValue PrependString(const TStringRef& ref, TUnboxedValuePod value) const = 0;
  202. virtual TUnboxedValue SubString(TUnboxedValuePod value, ui32 offset, ui32 size) const = 0;
  203. virtual IDictValueBuilder::TPtr NewDict(const TType* dictType, ui32 flags) const = 0;
  204. // Destroys (moves out from) items
  205. virtual TUnboxedValue NewList(TUnboxedValue* items, ui64 count) const = 0;
  206. virtual TUnboxedValue ReverseList(const TUnboxedValuePod& list) const = 0;
  207. virtual TUnboxedValue SkipList(const TUnboxedValuePod& list, ui64 count) const = 0;
  208. virtual TUnboxedValue TakeList(const TUnboxedValuePod& list, ui64 count) const = 0;
  209. virtual TUnboxedValue ToIndexDict(const TUnboxedValuePod& list) const = 0;
  210. /// Default representation for Tuple, Struct or List with a known size.
  211. TUnboxedValue NewArray(ui32 count, TUnboxedValue*& itemsPtr) const {
  212. return NewArray32(count, itemsPtr);
  213. }
  214. virtual TUnboxedValue NewArray32(ui32 count, TUnboxedValue*& itemsPtr) const = 0;
  215. virtual TUnboxedValue NewVariant(ui32 index, TUnboxedValue&& value) const = 0;
  216. inline TUnboxedValue NewEmptyList() const { return NewList(nullptr, 0); }
  217. };
  218. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 1)
  219. class IValueBuilder2: public IValueBuilder1 {
  220. public:
  221. virtual const IDateBuilder& GetDateBuilder() const = 0;
  222. };
  223. #endif
  224. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 14)
  225. class IValueBuilder3: public IValueBuilder2 {
  226. public:
  227. virtual bool GetSecureParam(TStringRef key, TStringRef& value) const = 0;
  228. };
  229. #endif
  230. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 17)
  231. class IValueBuilder4: public IValueBuilder3 {
  232. public:
  233. virtual const TSourcePosition* CalleePosition() const = 0;
  234. TSourcePosition WithCalleePosition(const TSourcePosition& def) const {
  235. auto callee = CalleePosition();
  236. return callee ? *callee : def;
  237. }
  238. virtual TUnboxedValue Run(const TSourcePosition& callee, const IBoxedValue& value, const TUnboxedValuePod* args) const = 0;
  239. };
  240. #endif
  241. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 19)
  242. class IValueBuilder5: public IValueBuilder4 {
  243. public:
  244. // exports one Array or Scalar to out. should be called for each chunk of ChunkedArray
  245. // returns array with one element for scalars
  246. virtual void ExportArrowBlock(TUnboxedValuePod value, ui32 chunk, ArrowArray* out) const = 0;
  247. // imports all chunks. returns Scalar, ChunkedArray if chunkCount > 1, otherwise Array
  248. // arrays should be a pointer to array of chunkCount structs
  249. // the ArrowArray struct has its contents moved to a private object held alive by the result.
  250. virtual TUnboxedValue ImportArrowBlock(ArrowArray* arrays, ui32 chunkCount, bool isScalar, const IArrowType& type) const = 0;
  251. // always returns 1 for Scalar and Array, >= 1 for ChunkedArray
  252. virtual ui32 GetArrowBlockChunks(TUnboxedValuePod value, bool& isScalar, ui64& length) const = 0;
  253. };
  254. #endif
  255. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 25)
  256. class IValueBuilder6: public IValueBuilder5 {
  257. public:
  258. virtual const IPgBuilder& GetPgBuilder() const = 0;
  259. };
  260. #endif
  261. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 27)
  262. class IValueBuilder7: public IValueBuilder6 {
  263. public:
  264. virtual TUnboxedValue NewArray64(ui64 count, TUnboxedValue*& itemsPtr) const = 0;
  265. TUnboxedValue NewArray(ui64 count, TUnboxedValue*& itemsPtr) const {
  266. return NewArray64(count, itemsPtr);
  267. }
  268. };
  269. #endif
  270. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 39)
  271. class IValueBuilder8: public IValueBuilder7 {
  272. public:
  273. virtual IListValueBuilder::TPtr NewListBuilder() const = 0;
  274. };
  275. #endif
  276. #if UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 39)
  277. class IValueBuilder: public IValueBuilder8 {
  278. protected:
  279. IValueBuilder();
  280. };
  281. #elif UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 27)
  282. class IValueBuilder: public IValueBuilder7 {
  283. protected:
  284. IValueBuilder();
  285. };
  286. #elif UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 25)
  287. class IValueBuilder: public IValueBuilder6 {
  288. protected:
  289. IValueBuilder();
  290. };
  291. #elif UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 19)
  292. class IValueBuilder: public IValueBuilder5 {
  293. protected:
  294. IValueBuilder();
  295. };
  296. #elif UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 17)
  297. class IValueBuilder: public IValueBuilder4 {
  298. protected:
  299. IValueBuilder();
  300. };
  301. #elif UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 14)
  302. class IValueBuilder: public IValueBuilder3 {
  303. protected:
  304. IValueBuilder();
  305. };
  306. #elif UDF_ABI_COMPATIBILITY_VERSION_CURRENT >= UDF_ABI_COMPATIBILITY_VERSION(2, 1)
  307. class IValueBuilder: public IValueBuilder2 {
  308. protected:
  309. IValueBuilder();
  310. };
  311. #else
  312. class IValueBuilder: public IValueBuilder1 {
  313. protected:
  314. IValueBuilder();
  315. };
  316. #endif
  317. UDF_ASSERT_TYPE_SIZE(IValueBuilder, 8);
  318. class TPlainArrayCache {
  319. private:
  320. const ui32 Size;
  321. std::array<TUnboxedValue, 2U> Cached;
  322. std::array<TUnboxedValue*, 2U> CachedItems;
  323. ui8 CacheIndex = 0U;
  324. public:
  325. TPlainArrayCache(ui32 size): Size(size) { Clear(); }
  326. TPlainArrayCache(TPlainArrayCache&&) = delete;
  327. TPlainArrayCache(const TPlainArrayCache&) = delete;
  328. TPlainArrayCache& operator=(TPlainArrayCache&&) = delete;
  329. TPlainArrayCache& operator=(const TPlainArrayCache&) = delete;
  330. void Clear() {
  331. Cached.fill(TUnboxedValue());
  332. CachedItems.fill(nullptr);
  333. }
  334. TUnboxedValue NewArray(const IValueBuilder& builder, TUnboxedValue*& items) {
  335. if (!CachedItems[CacheIndex] || !Cached[CacheIndex].UniqueBoxed()) {
  336. CacheIndex ^= 1U;
  337. if (!CachedItems[CacheIndex] || !Cached[CacheIndex].UniqueBoxed()) {
  338. Cached[CacheIndex] = builder.NewArray(Size, CachedItems[CacheIndex]);
  339. items = CachedItems[CacheIndex];
  340. return Cached[CacheIndex];
  341. }
  342. }
  343. items = CachedItems[CacheIndex];
  344. std::fill_n(items, Size, TUnboxedValue());
  345. return Cached[CacheIndex];
  346. }
  347. };
  348. } // namespace NUdf
  349. } // namespace NYql