@@ -39,11 +39,13 @@ extern const char StartOfQuarterUDF[] = "StartOfQuarter";
39
39
extern const char StartOfMonthUDF[] = " StartOfMonth" ;
40
40
extern const char StartOfWeekUDF[] = " StartOfWeek" ;
41
41
extern const char StartOfDayUDF[] = " StartOfDay" ;
42
+ extern const char StartOfUDF[] = " StartOf" ;
42
43
extern const char EndOfYearUDF[] = " EndOfYear" ;
43
44
extern const char EndOfQuarterUDF[] = " EndOfQuarter" ;
44
45
extern const char EndOfMonthUDF[] = " EndOfMonth" ;
45
46
extern const char EndOfWeekUDF[] = " EndOfWeek" ;
46
47
extern const char EndOfDayUDF[] = " EndOfDay" ;
48
+ extern const char EndOfUDF[] = " EndOf" ;
47
49
extern const char ShiftYearsUDF[] = " ShiftYears" ;
48
50
extern const char ShiftQuartersUDF[] = " ShiftQuarters" ;
49
51
extern const char ShiftMonthsUDF[] = " ShiftMonths" ;
@@ -2123,7 +2125,8 @@ class TBoundaryOf: public ::NYql::NUdf::TBoxedValue {
2123
2125
return storage;
2124
2126
}
2125
2127
2126
- TMaybe<TTMStorage> StartOf (TTMStorage storage, ui64 interval, const IValueBuilder& valueBuilder) {
2128
+ template <typename TStorage>
2129
+ TMaybe<TStorage> StartOf (TStorage storage, ui64 interval, const IValueBuilder& valueBuilder) {
2127
2130
if (interval >= 86400000000ull ) {
2128
2131
// treat as StartOfDay
2129
2132
SetStartOfDay (storage);
@@ -2140,7 +2143,8 @@ class TBoundaryOf: public ::NYql::NUdf::TBoxedValue {
2140
2143
return storage;
2141
2144
}
2142
2145
2143
- TMaybe<TTMStorage> EndOf (TTMStorage storage, ui64 interval, const IValueBuilder& valueBuilder) {
2146
+ template <typename TStorage>
2147
+ TMaybe<TStorage> EndOf (TStorage storage, ui64 interval, const IValueBuilder& valueBuilder) {
2144
2148
if (interval >= 86400000000ull ) {
2145
2149
// treat as EndOfDay
2146
2150
SetEndOfDay (storage);
@@ -2168,7 +2172,7 @@ class TBoundaryOf: public ::NYql::NUdf::TBoxedValue {
2168
2172
return ;
2169
2173
}
2170
2174
2171
- if (auto res = (UseEnd ? EndOf : StartOf)(storage, interval, *valueBuilder)) {
2175
+ if (auto res = (UseEnd ? EndOf<TTMStorage> : StartOf<TTMStorage> )(storage, interval, *valueBuilder)) {
2172
2176
storage = res.GetRef ();
2173
2177
sink (arg1);
2174
2178
} else {
@@ -2177,33 +2181,141 @@ class TBoundaryOf: public ::NYql::NUdf::TBoxedValue {
2177
2181
}
2178
2182
};
2179
2183
2180
- BEGIN_SIMPLE_STRICT_ARROW_UDF (TStartOf, TOptional<TResource<TMResourceName>>(TAutoMap<TResource<TMResourceName>>, TAutoMap<TInterval>)) {
2184
+ template <const char * TResourceName, auto Core>
2185
+ TUnboxedValue SimpleDatetimeToIntervalUdf (const IValueBuilder* valueBuilder, const TUnboxedValuePod* args) {
2181
2186
auto result = args[0 ];
2182
2187
ui64 interval = std::abs (args[1 ].Get <i64 >());
2183
2188
if (interval == 0 ) {
2184
2189
return result;
2185
2190
}
2186
- if (auto res = StartOf (Reference (result), interval, *valueBuilder)) {
2187
- Reference (result) = res.GetRef ();
2191
+ auto & storage = Reference<TResourceName>(result);
2192
+ if (auto res = Core (storage, interval, *valueBuilder)) {
2193
+ storage = res.GetRef ();
2188
2194
return result;
2189
2195
}
2190
2196
return TUnboxedValuePod{};
2191
2197
}
2192
- END_SIMPLE_ARROW_UDF (TStartOf, TStartEndOfBinaryKernelExec<false >::Do);
2193
2198
2194
- BEGIN_SIMPLE_STRICT_ARROW_UDF (TEndOf, TOptional<TResource<TMResourceName>>(TAutoMap<TResource<TMResourceName>>, TAutoMap<TInterval>)) {
2195
- auto result = args[0 ];
2196
- ui64 interval = std::abs (args[1 ].Get <i64 >());
2197
- if (interval == 0 ) {
2198
- return result;
2199
+ template <const char * TUdfName, auto Boundary, auto WBoundary>
2200
+ class TBoundaryOfInterval : public ::NYql::NUdf::TBoxedValue {
2201
+ public:
2202
+ typedef bool TTypeAwareMarker;
2203
+ static const TStringRef& Name () {
2204
+ static auto name = TStringRef (TUdfName, std::strlen (TUdfName));
2205
+ return name;
2206
+ }
2207
+
2208
+ static bool DeclareSignature (
2209
+ const ::NYql::NUdf::TStringRef& name,
2210
+ ::NYql::NUdf::TType* userType,
2211
+ ::NYql::NUdf::IFunctionTypeInfoBuilder& builder,
2212
+ bool typesOnly)
2213
+ {
2214
+ if (Name () != name) {
2215
+ return false ;
2199
2216
}
2200
- if (auto res = EndOf (Reference (result), interval, *valueBuilder)) {
2201
- Reference (result) = res.GetRef ();
2202
- return result;
2217
+
2218
+ if (!userType) {
2219
+ builder.SetError (" User type is missing" );
2220
+ return true ;
2203
2221
}
2204
- return TUnboxedValuePod{};
2222
+
2223
+ builder.UserType (userType);
2224
+
2225
+ const auto typeInfoHelper = builder.TypeInfoHelper ();
2226
+ TTupleTypeInspector tuple (*typeInfoHelper, userType);
2227
+ Y_ENSURE (tuple, " Tuple with args and options tuples expected" );
2228
+ Y_ENSURE (tuple.GetElementsCount () > 0 ,
2229
+ " Tuple has to contain positional arguments" );
2230
+
2231
+ TTupleTypeInspector argsTuple (*typeInfoHelper, tuple.GetElementType (0 ));
2232
+ Y_ENSURE (argsTuple, " Tuple with args expected" );
2233
+ if (argsTuple.GetElementsCount () != 2 ) {
2234
+ builder.SetError (" Single argument expected" );
2235
+ return true ;
2236
+ }
2237
+
2238
+ auto argType = argsTuple.GetElementType (0 );
2239
+
2240
+ if (const auto optType = TOptionalTypeInspector (*typeInfoHelper, argType)) {
2241
+ argType = optType.GetItemType ();
2242
+ }
2243
+
2244
+ TResourceTypeInspector resource (*typeInfoHelper, argType);
2245
+ if (!resource) {
2246
+ TDataTypeInspector data (*typeInfoHelper, argType);
2247
+ if (!data) {
2248
+ SetInvalidTypeError (builder, typeInfoHelper, argType);
2249
+ return true ;
2250
+ }
2251
+
2252
+ const auto features = NUdf::GetDataTypeInfo (NUdf::GetDataSlot (data.GetTypeId ())).Features ;
2253
+ if (features & NUdf::BigDateType) {
2254
+ BuildSignature<TM64ResourceName, WBoundary>(builder, typesOnly);
2255
+ return true ;
2256
+ }
2257
+ if (features & (NUdf::DateType | NUdf::TzDateType)) {
2258
+ BuildSignature<TMResourceName, Boundary>(builder, typesOnly);
2259
+ return true ;
2260
+ }
2261
+
2262
+ SetInvalidTypeError (builder, typeInfoHelper, argType);
2263
+ return true ;
2264
+ }
2265
+
2266
+ if (resource.GetTag () == TStringRef::Of (TM64ResourceName)) {
2267
+ BuildSignature<TM64ResourceName, WBoundary>(builder, typesOnly);
2268
+ return true ;
2269
+ }
2270
+
2271
+ if (resource.GetTag () == TStringRef::Of (TMResourceName)) {
2272
+ BuildSignature<TMResourceName, Boundary>(builder, typesOnly);
2273
+ return true ;
2274
+ }
2275
+
2276
+ ::TStringBuilder sb;
2277
+ sb << " Unexpected Resource tag: got '" << resource.GetTag () << " '" ;
2278
+ builder.SetError (sb);
2279
+ return true ;
2205
2280
}
2206
- END_SIMPLE_ARROW_UDF (TEndOf, TStartEndOfBinaryKernelExec<true >::Do);
2281
+ private:
2282
+ template <auto Func>
2283
+ class TImpl : public TBoxedValue {
2284
+ public:
2285
+ TUnboxedValue Run (const IValueBuilder* valueBuilder, const TUnboxedValuePod* args) const final {
2286
+ try {
2287
+ return Func (valueBuilder, args);
2288
+ } catch (const std::exception&) {
2289
+ TStringBuilder sb;
2290
+ sb << CurrentExceptionMessage ();
2291
+ sb << Endl << " [" << TStringBuf (Name ()) << " ]" ;
2292
+ UdfTerminate (sb.c_str ());
2293
+ }
2294
+ }
2295
+ };
2296
+
2297
+ static void SetInvalidTypeError (NUdf::IFunctionTypeInfoBuilder& builder,
2298
+ ITypeInfoHelper::TPtr typeInfoHelper, const TType* argType)
2299
+ {
2300
+ ::TStringBuilder sb;
2301
+ sb << " Invalid argument type: got " ;
2302
+ TTypePrinter (*typeInfoHelper, argType).Out (sb.Out );
2303
+ sb << " , but Resource<" << TMResourceName <<" > or Resource<"
2304
+ << TM64ResourceName << " > expected" ;
2305
+ builder.SetError (sb);
2306
+ }
2307
+
2308
+ template <const char * TResourceName, auto Func>
2309
+ static void BuildSignature (NUdf::IFunctionTypeInfoBuilder& builder, bool typesOnly) {
2310
+ builder.Returns <TOptional<TResource<TResourceName>>>();
2311
+ builder.Args ()->Add <TAutoMap<TResource<TResourceName>>>()
2312
+ .template Add <TAutoMap<std::conditional_t <TResourceName == TMResourceName, TInterval, TInterval64>>>();
2313
+ builder.IsStrict ();
2314
+ if (!typesOnly) {
2315
+ builder.Implementation (new TImpl<Func>());
2316
+ }
2317
+ }
2318
+ };
2207
2319
2208
2320
struct TTimeOfDayKernelExec : TUnaryKernelExec<TTimeOfDayKernelExec, TReaderTraits::TResource<false >, TFixedSizeArrayBuilder<TDataType<TInterval>::TLayout, false >> {
2209
2321
template <typename TSink>
@@ -2214,13 +2326,126 @@ class TBoundaryOf: public ::NYql::NUdf::TBoxedValue {
2214
2326
}
2215
2327
};
2216
2328
2217
- const auto timeOfDayKernelExecDo = TTimeOfDayKernelExec::Do;
2218
- BEGIN_SIMPLE_STRICT_ARROW_UDF (TTimeOfDay, TInterval(TAutoMap<TResource<TMResourceName>>)) {
2219
- Y_UNUSED (valueBuilder);
2220
- auto & storage = Reference (args[0 ]);
2221
- return TUnboxedValuePod ((i64 )storage.ToTimeOfDay ());
2329
+ class TTimeOfDay : public ::NYql::NUdf::TBoxedValue {
2330
+ public:
2331
+ typedef bool TTypeAwareMarker;
2332
+ static const ::NYql::NUdf::TStringRef& Name () {
2333
+ static auto name = TStringRef::Of (" TimeOfDay" );
2334
+ return name;
2335
+ }
2336
+
2337
+ static bool DeclareSignature (
2338
+ const ::NYql::NUdf::TStringRef& name,
2339
+ ::NYql::NUdf::TType* userType,
2340
+ ::NYql::NUdf::IFunctionTypeInfoBuilder& builder,
2341
+ bool typesOnly)
2342
+ {
2343
+ if (Name () != name) {
2344
+ return false ;
2345
+ }
2346
+
2347
+ if (!userType) {
2348
+ builder.SetError (" User type is missing" );
2349
+ return true ;
2350
+ }
2351
+
2352
+ builder.UserType (userType);
2353
+
2354
+ const auto typeInfoHelper = builder.TypeInfoHelper ();
2355
+ TTupleTypeInspector tuple (*typeInfoHelper, userType);
2356
+ Y_ENSURE (tuple, " Tuple with args and options tuples expected" );
2357
+ Y_ENSURE (tuple.GetElementsCount () > 0 ,
2358
+ " Tuple has to contain positional arguments" );
2359
+
2360
+ TTupleTypeInspector argsTuple (*typeInfoHelper, tuple.GetElementType (0 ));
2361
+ Y_ENSURE (argsTuple, " Tuple with args expected" );
2362
+ if (argsTuple.GetElementsCount () != 1 ) {
2363
+ builder.SetError (" Single argument expected" );
2364
+ return true ;
2365
+ }
2366
+
2367
+ auto argType = argsTuple.GetElementType (0 );
2368
+
2369
+ if (const auto optType = TOptionalTypeInspector (*typeInfoHelper, argType)) {
2370
+ argType = optType.GetItemType ();
2371
+ }
2372
+
2373
+ TResourceTypeInspector resource (*typeInfoHelper, argType);
2374
+ if (!resource) {
2375
+ TDataTypeInspector data (*typeInfoHelper, argType);
2376
+ if (!data) {
2377
+ SetInvalidTypeError (builder, typeInfoHelper, argType);
2378
+ return true ;
2379
+ }
2380
+
2381
+ const auto features = NUdf::GetDataTypeInfo (NUdf::GetDataSlot (data.GetTypeId ())).Features ;
2382
+ if (features & NUdf::BigDateType) {
2383
+ BuildSignature<TM64ResourceName>(builder, typesOnly);
2384
+ return true ;
2385
+ }
2386
+ if (features & (NUdf::DateType | NUdf::TzDateType)) {
2387
+ BuildSignature<TMResourceName>(builder, typesOnly);
2388
+ return true ;
2389
+ }
2390
+
2391
+ SetInvalidTypeError (builder, typeInfoHelper, argType);
2392
+ return true ;
2393
+ }
2394
+
2395
+ if (resource.GetTag () == TStringRef::Of (TM64ResourceName)) {
2396
+ BuildSignature<TM64ResourceName>(builder, typesOnly);
2397
+ return true ;
2398
+ }
2399
+
2400
+ if (resource.GetTag () == TStringRef::Of (TMResourceName)) {
2401
+ BuildSignature<TMResourceName>(builder, typesOnly);
2402
+ return true ;
2403
+ }
2404
+
2405
+ ::TStringBuilder sb;
2406
+ sb << " Unexpected Resource tag: got '" << resource.GetTag () << " '" ;
2407
+ builder.SetError (sb);
2408
+ return true ;
2409
+ }
2410
+ private:
2411
+ template <const char * TResourceName>
2412
+ class TImpl : public TBoxedValue {
2413
+ public:
2414
+ TUnboxedValue Run (const IValueBuilder* valueBuilder, const TUnboxedValuePod* args) const final {
2415
+ try {
2416
+ Y_UNUSED (valueBuilder);
2417
+ auto & storage = Reference<TResourceName>(args[0 ]);
2418
+ return TUnboxedValuePod ((i64 )storage.ToTimeOfDay ());
2419
+ } catch (const std::exception&) {
2420
+ TStringBuilder sb;
2421
+ sb << CurrentExceptionMessage ();
2422
+ sb << Endl << " [" << TStringBuf (Name ()) << " ]" ;
2423
+ UdfTerminate (sb.c_str ());
2424
+ }
2425
+ }
2426
+ };
2427
+
2428
+ static void SetInvalidTypeError (NUdf::IFunctionTypeInfoBuilder& builder,
2429
+ ITypeInfoHelper::TPtr typeInfoHelper, const TType* argType)
2430
+ {
2431
+ ::TStringBuilder sb;
2432
+ sb << " Invalid argument type: got " ;
2433
+ TTypePrinter (*typeInfoHelper, argType).Out (sb.Out );
2434
+ sb << " , but Resource<" << TMResourceName <<" > or Resource<"
2435
+ << TM64ResourceName << " > expected" ;
2436
+ builder.SetError (sb);
2437
+ }
2438
+
2439
+ template < const char * TResourceName>
2440
+ static void BuildSignature (NUdf::IFunctionTypeInfoBuilder& builder, bool typesOnly) {
2441
+ builder.Returns <std::conditional_t <TResourceName == TMResourceName, TInterval, TInterval64>>();
2442
+ builder.Args ()->Add <TAutoMap<TResource<TResourceName>>>();
2443
+ builder.IsStrict ();
2444
+ if (!typesOnly) {
2445
+ builder.Implementation (new TImpl<TResourceName>());
2446
+ }
2222
2447
}
2223
- END_SIMPLE_ARROW_UDF (TTimeOfDay, timeOfDayKernelExecDo) ;
2448
+ } ;
2224
2449
2225
2450
2226
2451
// Add ...
@@ -3139,7 +3364,8 @@ class TShift : public TBoxedValue {
3139
3364
SimpleDatetimeToDatetimeUdf<TM64ResourceName, StartOfWeek<TTM64Storage>>>,
3140
3365
TBoundaryOf<StartOfDayUDF, SimpleDatetimeToDatetimeUdf<TMResourceName, StartOfDay<TTMStorage>>,
3141
3366
SimpleDatetimeToDatetimeUdf<TM64ResourceName, StartOfDay<TTM64Storage>>>,
3142
- TStartOf,
3367
+ TBoundaryOfInterval<StartOfUDF, SimpleDatetimeToIntervalUdf<TMResourceName, StartOf<TTMStorage>>,
3368
+ SimpleDatetimeToIntervalUdf<TM64ResourceName, StartOf<TTM64Storage>>>,
3143
3369
TTimeOfDay,
3144
3370
3145
3371
TShift<ShiftYearsUDF, DoAddYears<TMResourceName>, DoAddYears<TM64ResourceName>>,
@@ -3156,7 +3382,8 @@ class TShift : public TBoxedValue {
3156
3382
SimpleDatetimeToDatetimeUdf<TM64ResourceName, EndOfWeek<TTM64Storage>>>,
3157
3383
TBoundaryOf<EndOfDayUDF, SimpleDatetimeToDatetimeUdf<TMResourceName, EndOfDay<TTMStorage>>,
3158
3384
SimpleDatetimeToDatetimeUdf<TM64ResourceName, EndOfDay<TTM64Storage>>>,
3159
- TEndOf,
3385
+ TBoundaryOfInterval<EndOfUDF, SimpleDatetimeToIntervalUdf<TMResourceName, EndOf<TTMStorage>>,
3386
+ SimpleDatetimeToIntervalUdf<TM64ResourceName, EndOf<TTM64Storage>>>,
3160
3387
3161
3388
TToUnits<ToSecondsUDF, ui32, 1 >,
3162
3389
TToUnits<ToMillisecondsUDF, ui64, 1000 >,
0 commit comments