1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995 |
- #include <yql/essentials/minikql/mkql_type_ops.h>
- #include <yql/essentials/public/udf/tz/udf_tz.h>
- #include <yql/essentials/public/udf/udf_helpers.h>
- #include <yql/essentials/minikql/datetime/datetime.h>
- #include <yql/essentials/minikql/datetime/datetime64.h>
- #include <yql/essentials/public/udf/arrow/udf_arrow_helpers.h>
- #include <util/datetime/base.h>
- using namespace NKikimr;
- using namespace NUdf;
- using namespace NYql::DateTime;
- extern const char SplitUDF[] = "Split";
- extern const char ToSecondsUDF[] = "ToSeconds";
- extern const char ToMillisecondsUDF[] = "ToMilliseconds";
- extern const char ToMicrosecondsUDF[] = "ToMicroseconds";
- extern const char GetYearUDF[] = "GetYear";
- extern const char GetDayOfYearUDF[] = "GetDayOfYear";
- extern const char GetMonthUDF[] = "GetMonth";
- extern const char GetMonthNameUDF[] = "GetMonthName";
- extern const char GetWeekOfYearUDF[] = "GetWeekOfYear";
- extern const char GetWeekOfYearIso8601UDF[] = "GetWeekOfYearIso8601";
- extern const char GetDayOfMonthUDF[] = "GetDayOfMonth";
- extern const char GetDayOfWeekUDF[] = "GetDayOfWeek";
- extern const char GetDayOfWeekNameUDF[] = "GetDayOfWeekName";
- extern const char GetTimezoneIdUDF[] = "GetTimezoneId";
- extern const char GetTimezoneNameUDF[] = "GetTimezoneName";
- extern const char GetHourUDF[] = "GetHour";
- extern const char GetMinuteUDF[] = "GetMinute";
- extern const char GetSecondUDF[] = "GetSecond";
- extern const char GetMillisecondOfSecondUDF[] = "GetMillisecondOfSecond";
- extern const char GetMicrosecondOfSecondUDF[] = "GetMicrosecondOfSecond";
- extern const char StartOfYearUDF[] = "StartOfYear";
- extern const char StartOfQuarterUDF[] = "StartOfQuarter";
- extern const char StartOfMonthUDF[] = "StartOfMonth";
- extern const char StartOfWeekUDF[] = "StartOfWeek";
- extern const char StartOfDayUDF[] = "StartOfDay";
- extern const char EndOfYearUDF[] = "EndOfYear";
- extern const char EndOfQuarterUDF[] = "EndOfQuarter";
- extern const char EndOfMonthUDF[] = "EndOfMonth";
- extern const char EndOfWeekUDF[] = "EndOfWeek";
- extern const char EndOfDayUDF[] = "EndOfDay";
- extern const char ShiftYearsUDF[] = "ShiftYears";
- extern const char ShiftQuartersUDF[] = "ShiftQuarters";
- extern const char ShiftMonthsUDF[] = "ShiftMonths";
- extern const char TMResourceName[] = "DateTime2.TM";
- extern const char TM64ResourceName[] = "DateTime2.TM64";
- const auto UsecondsInDay = 86400000000ll;
- const auto UsecondsInHour = 3600000000ll;
- const auto UsecondsInMinute = 60000000ll;
- const auto UsecondsInSecond = 1000000ll;
- const auto UsecondsInMilliseconds = 1000ll;
- template <const char* TFuncName, typename TResult, ui32 ScaleAfterSeconds>
- class TToUnits {
- public:
- typedef bool TTypeAwareMarker;
- using TSignedResult = typename std::make_signed<TResult>::type;
- static TResult DateCore(ui16 value) {
- return value * ui32(86400) * TResult(ScaleAfterSeconds);
- }
- template<typename TTzDate>
- static TResult TzBlockCore(TBlockItem tzDate);
- template<>
- static TResult TzBlockCore<TTzDate>(TBlockItem tzDate) {
- return DateCore(tzDate.Get<ui16>());
- }
- template<>
- static TResult TzBlockCore<TTzDatetime>(TBlockItem tzDate) {
- return DatetimeCore(tzDate.Get<ui32>());
- }
- template<>
- static TResult TzBlockCore<TTzTimestamp>(TBlockItem tzDate) {
- return TimestampCore(tzDate.Get<ui64>());
- }
- static TResult DatetimeCore(ui32 value) {
- return value * TResult(ScaleAfterSeconds);
- }
- static TResult TimestampCore(ui64 value) {
- return TResult(value / (1000000u / ScaleAfterSeconds));
- }
- static TSignedResult IntervalCore(i64 value) {
- return TSignedResult(value / (1000000u / ScaleAfterSeconds));
- }
- static const TStringRef& Name() {
- static auto name = TStringRef(TFuncName, std::strlen(TFuncName));
- return name;
- }
- template<typename TTzDate, typename TOutput>
- static auto MakeTzBlockExec() {
- using TReader = TTzDateBlockReader<TTzDate, /*Nullable*/ false>;
- return UnaryPreallocatedReaderExecImpl<TReader, TOutput, TzBlockCore<TTzDate>>;
- }
- static bool DeclareSignature(
- const TStringRef& name,
- TType* userType,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly)
- {
- if (Name() != name) {
- return false;
- }
- try {
- auto typeInfoHelper = builder.TypeInfoHelper();
- TTupleTypeInspector tuple(*typeInfoHelper, userType);
- Y_ENSURE(tuple);
- Y_ENSURE(tuple.GetElementsCount() > 0);
- TTupleTypeInspector argsTuple(*typeInfoHelper, tuple.GetElementType(0));
- Y_ENSURE(argsTuple);
- if (argsTuple.GetElementsCount() != 1) {
- builder.SetError("Expected one argument");
- return true;
- }
- auto argType = argsTuple.GetElementType(0);
- TVector<const TType*> argBlockTypes;
- argBlockTypes.push_back(argType);
- TBlockTypeInspector block(*typeInfoHelper, argType);
- if (block) {
- Y_ENSURE(!block.IsScalar());
- argType = block.GetItemType();
- }
- bool isOptional = false;
- if (auto opt = TOptionalTypeInspector(*typeInfoHelper, argType)) {
- argType = opt.GetItemType();
- isOptional = true;
- }
- TDataTypeInspector data(*typeInfoHelper, argType);
- if (!data) {
- builder.SetError("Expected data type");
- return true;
- }
- auto typeId = data.GetTypeId();
- if (!(typeId == TDataType<TDate>::Id || typeId == TDataType<TTzDate>::Id ||
- typeId == TDataType<TDatetime>::Id || typeId == TDataType<TTzDatetime>::Id ||
- typeId == TDataType<TTimestamp>::Id || typeId == TDataType<TTzTimestamp>::Id ||
- typeId == TDataType<TInterval>::Id)) {
- builder.SetError(TStringBuilder() << "Type " << GetDataTypeInfo(GetDataSlot(typeId)).Name << " is not supported");
- }
- builder.Args()->Add(argsTuple.GetElementType(0)).Done();
- const TType* retType;
- if (typeId != TDataType<TInterval>::Id) {
- retType = builder.SimpleType<TResult>();
- } else {
- retType = builder.SimpleType<TSignedResult>();
- }
- if (isOptional) {
- retType = builder.Optional()->Item(retType).Build();
- }
- auto outputType = retType;
- if (block) {
- retType = builder.Block(block.IsScalar())->Item(retType).Build();
- }
- builder.Returns(retType);
- builder.SupportsBlocks();
- builder.IsStrict();
- builder.UserType(userType);
- if (!typesOnly) {
- if (typeId == TDataType<TDate>::Id || typeId == TDataType<TTzDate>::Id) {
- if (block) {
- const auto exec = (typeId == TDataType<TTzDate>::Id)
- ? MakeTzBlockExec<TTzDate, TResult>()
- : UnaryPreallocatedExecImpl<ui16, TResult, DateCore>;
- builder.Implementation(new TSimpleArrowUdfImpl(argBlockTypes, outputType, block.IsScalar(),
- exec, builder, TString(name), arrow::compute::NullHandling::INTERSECTION));
- } else {
- builder.Implementation(new TUnaryOverOptionalImpl<ui16, TResult, DateCore>());
- }
- }
- if (typeId == TDataType<TDatetime>::Id || typeId == TDataType<TTzDatetime>::Id) {
- if (block) {
- const auto exec = (typeId == TDataType<TTzDatetime>::Id)
- ? MakeTzBlockExec<TTzDatetime, TResult>()
- : UnaryPreallocatedExecImpl<ui32, TResult, DatetimeCore>;
- builder.Implementation(new TSimpleArrowUdfImpl(argBlockTypes, outputType, block.IsScalar(),
- exec, builder, TString(name), arrow::compute::NullHandling::INTERSECTION));
- } else {
- builder.Implementation(new TUnaryOverOptionalImpl<ui32, TResult, DatetimeCore>());
- }
- }
- if (typeId == TDataType<TTimestamp>::Id || typeId == TDataType<TTzTimestamp>::Id) {
- if (block) {
- const auto exec = (typeId == TDataType<TTzTimestamp>::Id)
- ? MakeTzBlockExec<TTzTimestamp, TResult>()
- : UnaryPreallocatedExecImpl<ui64, TResult, TimestampCore>;
- builder.Implementation(new TSimpleArrowUdfImpl(argBlockTypes, outputType, block.IsScalar(),
- exec, builder, TString(name), arrow::compute::NullHandling::INTERSECTION));
- } else {
- builder.Implementation(new TUnaryOverOptionalImpl<ui64, TResult, TimestampCore>());
- }
- }
- if (typeId == TDataType<TInterval>::Id) {
- if (block) {
- builder.Implementation(new TSimpleArrowUdfImpl(argBlockTypes, outputType, block.IsScalar(),
- UnaryPreallocatedExecImpl<i64, TSignedResult, IntervalCore>, builder, TString(name), arrow::compute::NullHandling::INTERSECTION));
- } else {
- builder.Implementation(new TUnaryOverOptionalImpl<i64, TSignedResult, IntervalCore>());
- }
- }
- }
- } catch (const std::exception& e) {
- builder.SetError(TStringBuf(e.what()));
- }
- return true;
- }
- };
- template <const char* TFuncName, typename TFieldStorage,
- TFieldStorage (*Accessor)(const TUnboxedValuePod&),
- TFieldStorage (*WAccessor)(const TUnboxedValuePod&),
- ui32 Divisor, ui32 Scale, ui32 Limit, bool Fractional>
- struct TGetTimeComponent {
- typedef bool TTypeAwareMarker;
- static const TStringRef& Name() {
- static auto name = TStringRef(TFuncName, std::strlen(TFuncName));
- return name;
- }
- static bool DeclareSignature(
- const TStringRef& name,
- TType* userType,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly)
- {
- if (Name() != name) {
- return false;
- }
- if (!userType) {
- builder.SetError("User type is missing");
- return true;
- }
- builder.UserType(userType);
- const auto typeInfoHelper = builder.TypeInfoHelper();
- TTupleTypeInspector tuple(*typeInfoHelper, userType);
- Y_ENSURE(tuple, "Tuple with args and options tuples expected");
- Y_ENSURE(tuple.GetElementsCount() > 0,
- "Tuple has to contain positional arguments");
- TTupleTypeInspector argsTuple(*typeInfoHelper, tuple.GetElementType(0));
- Y_ENSURE(argsTuple, "Tuple with args expected");
- if (argsTuple.GetElementsCount() != 1) {
- builder.SetError("Single argument expected");
- return true;
- }
- auto argType = argsTuple.GetElementType(0);
- TVector<const TType*> argBlockTypes;
- argBlockTypes.push_back(argType);
- TBlockTypeInspector block(*typeInfoHelper, argType);
- if (block) {
- Y_ENSURE(!block.IsScalar());
- argType = block.GetItemType();
- }
- bool isOptional = false;
- if (auto opt = TOptionalTypeInspector(*typeInfoHelper, argType)) {
- argType = opt.GetItemType();
- isOptional = true;
- }
- TResourceTypeInspector resource(*typeInfoHelper, argType);
- if (!resource) {
- TDataTypeInspector data(*typeInfoHelper, argType);
- if (!data) {
- builder.SetError("Data type expected");
- return true;
- }
- const auto features = NUdf::GetDataTypeInfo(NUdf::GetDataSlot(data.GetTypeId())).Features;
- if (features & NUdf::BigDateType) {
- BuildSignature<TFieldStorage, TM64ResourceName, WAccessor>(builder, typesOnly);
- return true;
- }
- if (features & NUdf::TzDateType) {
- BuildSignature<TFieldStorage, TMResourceName, Accessor>(builder, typesOnly);
- return true;
- }
- if (features & NUdf::DateType) {
- builder.Args()->Add(argsTuple.GetElementType(0)).Done();
- const TType* retType = builder.SimpleType<TFieldStorage>();
- if (isOptional) {
- retType = builder.Optional()->Item(retType).Build();
- }
- auto outputType = retType;
- if (block) {
- retType = builder.Block(block.IsScalar())->Item(retType).Build();
- }
- builder.Returns(retType);
- builder.SupportsBlocks();
- builder.IsStrict();
- if (!typesOnly) {
- const auto typeId = data.GetTypeId();
- if (typeId == TDataType<TDate>::Id) {
- if (block) {
- builder.Implementation(new TSimpleArrowUdfImpl(argBlockTypes, outputType, block.IsScalar(),
- UnaryPreallocatedExecImpl<ui16, TFieldStorage, Core<ui16, true, false>>, builder, TString(name), arrow::compute::NullHandling::INTERSECTION));
- } else {
- builder.Implementation(new TUnaryOverOptionalImpl<ui16, TFieldStorage, Core<ui16, true, false>>());
- }
- }
- if (typeId == TDataType<TDatetime>::Id) {
- if (block) {
- builder.Implementation(new TSimpleArrowUdfImpl(argBlockTypes, outputType, block.IsScalar(),
- UnaryPreallocatedExecImpl<ui32, TFieldStorage, Core<ui32, false, false>>, builder, TString(name), arrow::compute::NullHandling::INTERSECTION));
- } else {
- builder.Implementation(new TUnaryOverOptionalImpl<ui32, TFieldStorage, Core<ui32, false, false>>());
- }
- }
- if (typeId == TDataType<TTimestamp>::Id) {
- if (block) {
- builder.Implementation(new TSimpleArrowUdfImpl(argBlockTypes, outputType, block.IsScalar(),
- UnaryPreallocatedExecImpl<ui64, TFieldStorage, Core<ui64, false, true>>, builder, TString(name), arrow::compute::NullHandling::INTERSECTION));
- } else {
- builder.Implementation(new TUnaryOverOptionalImpl<ui64, TFieldStorage, Core<ui64, false, true>>());
- }
- }
- }
- return true;
- }
- ::TStringBuilder sb;
- sb << "Invalid argument type: got ";
- TTypePrinter(*typeInfoHelper, argType).Out(sb.Out);
- sb << ", but Resource<" << TMResourceName <<"> or Resource<"
- << TM64ResourceName << "> expected";
- builder.SetError(sb);
- return true;
- }
- Y_ENSURE(!block);
- if (resource.GetTag() == TStringRef::Of(TM64ResourceName)) {
- BuildSignature<TFieldStorage, TM64ResourceName, WAccessor>(builder, typesOnly);
- return true;
- }
- if (resource.GetTag() == TStringRef::Of(TMResourceName)) {
- BuildSignature<TFieldStorage, TMResourceName, Accessor>(builder, typesOnly);
- return true;
- }
- builder.SetError("Unexpected Resource tag");
- return true;
- }
- private:
- template <typename TInput, bool AlwaysZero, bool InputFractional>
- static TFieldStorage Core(TInput val) {
- if constexpr (AlwaysZero) {
- return 0;
- }
- if constexpr (InputFractional) {
- if constexpr (Fractional) {
- return (val / Scale) % Limit;
- } else {
- return (val / 1000000u / Scale) % Limit;
- }
- } else {
- if constexpr (Fractional) {
- return 0;
- } else {
- return (val / Scale) % Limit;
- }
- }
- }
- template<typename TResult, TResult (*Func)(const TUnboxedValuePod&)>
- class TImpl : public TBoxedValue {
- public:
- TUnboxedValue Run(const IValueBuilder* valueBuilder, const TUnboxedValuePod* args) const final {
- Y_UNUSED(valueBuilder);
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- return TUnboxedValuePod((TResult(Func(args[0])) / Divisor));
- }
- };
- template<typename TResult, const char* TResourceName, TResult (*Func)(const TUnboxedValuePod&)>
- static void BuildSignature(NUdf::IFunctionTypeInfoBuilder& builder, bool typesOnly) {
- builder.Returns<TResult>();
- builder.Args()->Add<TAutoMap<TResource<TResourceName>>>();
- builder.IsStrict();
- if (!typesOnly) {
- builder.Implementation(new TImpl<TResult, Func>());
- }
- }
- };
- namespace {
- // FIXME: The default value for TResourceName allows to omit
- // explicit specialization in functions that still doesn't support
- // big datetime types. Should be removed in future.
- template<const char* TResourceName = TMResourceName, typename TValue,
- typename TStorage = std::conditional_t<TResourceName == TMResourceName,
- TTMStorage, TTM64Storage>>
- const TStorage& Reference(const TValue& value) {
- return *reinterpret_cast<const TStorage*>(value.GetRawPtr());
- }
- // FIXME: The default value for TResourceName allows to omit
- // explicit specialization in functions that still doesn't support
- // big datetime types. Should be removed in future.
- template<const char* TResourceName = TMResourceName, typename TValue,
- typename TStorage = std::conditional_t<TResourceName == TMResourceName,
- TTMStorage, TTM64Storage>>
- TStorage& Reference(TValue& value) {
- return *reinterpret_cast<TStorage*>(value.GetRawPtr());
- }
- template<const char* TResourceName>
- TUnboxedValuePod DoAddMonths(const TUnboxedValuePod& date, i64 months, const NUdf::IDateBuilder& builder) {
- auto result = date;
- auto& storage = Reference<TResourceName>(result);
- if (!NYql::DateTime::DoAddMonths(storage, months, builder)) {
- return TUnboxedValuePod{};
- }
- return result;
- }
- template<const char* TResourceName>
- TUnboxedValuePod DoAddQuarters(const TUnboxedValuePod& date, i64 quarters, const NUdf::IDateBuilder& builder) {
- return DoAddMonths<TResourceName>(date, quarters * 3ll, builder);
- }
- template<const char* TResourceName>
- TUnboxedValuePod DoAddYears(const TUnboxedValuePod& date, i64 years, const NUdf::IDateBuilder& builder) {
- auto result = date;
- auto& storage = Reference<TResourceName>(result);
- if (!NYql::DateTime::DoAddYears(storage, years, builder)) {
- return TUnboxedValuePod{};
- }
- return result;
- }
- // FIXME: The default value for TResourceName allows to omit
- // explicit specialization in functions that still doesn't support
- // big datetime types. Should be removed in future.
- #define ACCESSORS_POLY(field, type, wtype) \
- template<const char* TResourceName = TMResourceName, typename TValue, \
- typename rtype = std::conditional_t<TResourceName == TMResourceName, \
- type, wtype>> \
- inline rtype Get##field(const TValue& tm) { \
- return (rtype)Reference<TResourceName>(tm).field; \
- } \
- template<const char* TResourceName = TMResourceName, typename TValue, \
- typename itype = std::conditional_t<TResourceName == TMResourceName, \
- type, wtype>> \
- inline void Set##field(TValue& tm, itype value) { \
- Reference<TResourceName>(tm).field = value; \
- } \
- #define ACCESSORS(field, type) \
- ACCESSORS_POLY(field, type, type)
- ACCESSORS_POLY(Year, ui16, i32)
- ACCESSORS(DayOfYear, ui16)
- ACCESSORS(WeekOfYear, ui8)
- ACCESSORS(WeekOfYearIso8601, ui8)
- ACCESSORS(DayOfWeek, ui8)
- ACCESSORS(Month, ui8)
- ACCESSORS(Day, ui8)
- ACCESSORS(Hour, ui8)
- ACCESSORS(Minute, ui8)
- ACCESSORS(Second, ui8)
- ACCESSORS(Microsecond, ui32)
- ACCESSORS(TimezoneId, ui16)
- #undef ACCESSORS
- #undef ACCESSORS_POLY
- // FIXME: The default value for TResourceName allows to omit
- // explicit specialization in functions that still doesn't support
- // big datetime types. Should be removed in future.
- template<const char* TResourceName = TMResourceName>
- inline bool ValidateYear(std::conditional_t<TResourceName == TMResourceName, ui16, i32> year) {
- if constexpr (TResourceName == TMResourceName) {
- return year >= NUdf::MIN_YEAR || year < NUdf::MAX_YEAR;
- } else {
- return year >= NUdf::MIN_YEAR32 || year < NUdf::MAX_YEAR32;
- }
- }
- inline bool ValidateMonth(ui8 month) {
- return month >= 1 && month <= 12;
- }
- inline bool ValidateDay(ui8 day) {
- return day >= 1 && day <= 31;
- }
- inline bool ValidateHour(ui8 hour) {
- return hour < 24;
- }
- inline bool ValidateMinute(ui8 minute) {
- return minute < 60;
- }
- inline bool ValidateSecond(ui8 second) {
- return second < 60;
- }
- inline bool ValidateMicrosecond(ui32 microsecond) {
- return microsecond < 1000000;
- }
- inline bool ValidateTimezoneId(ui16 timezoneId) {
- const auto& zones = NUdf::GetTimezones();
- return timezoneId < zones.size() && !zones[timezoneId].empty();
- }
- inline bool ValidateMonthShortName(const std::string_view& monthName, ui8& month) {
- static constexpr auto cmp = [](const std::string_view& a, const std::string_view& b) {
- int cmp = strnicmp(a.data(), b.data(), std::min(a.size(), b.size()));
- if (cmp == 0)
- return a.size() < b.size();
- return cmp < 0;
- };
- static const std::map<std::string_view, ui8, decltype(cmp)> mp = {
- {"jan", 1},
- {"feb", 2},
- {"mar", 3},
- {"apr", 4},
- {"may", 5},
- {"jun", 6},
- {"jul", 7},
- {"aug", 8},
- {"sep", 9},
- {"oct", 10},
- {"nov", 11},
- {"dec", 12}
- };
- const auto& it = mp.find(monthName);
- if (it != mp.end()) {
- month = it -> second;
- return true;
- }
- return false;
- }
- inline bool ValidateMonthFullName(const std::string_view& monthName, ui8& month) {
- static constexpr auto cmp = [](const std::string_view& a, const std::string_view& b) {
- int cmp = strnicmp(a.data(), b.data(), std::min(a.size(), b.size()));
- if (cmp == 0)
- return a.size() < b.size();
- return cmp < 0;
- };
- static const std::map<std::string_view, ui8, decltype(cmp)> mp = {
- {"january", 1},
- {"february", 2},
- {"march", 3},
- {"april", 4},
- {"may", 5},
- {"june", 6},
- {"july", 7},
- {"august", 8},
- {"september", 9},
- {"october", 10},
- {"november", 11},
- {"december", 12}
- };
- const auto& it = mp.find(monthName);
- if (it != mp.end()) {
- month = it -> second;
- return true;
- }
- return false;
- }
- template<typename TType>
- inline bool Validate(typename TDataType<TType>::TLayout arg);
- template<>
- inline bool Validate<TTimestamp>(ui64 timestamp) {
- return timestamp < MAX_TIMESTAMP;
- }
- template<>
- inline bool Validate<TTimestamp64>(i64 timestamp) {
- return timestamp >= MIN_TIMESTAMP64 && timestamp <= MAX_TIMESTAMP64;
- }
- template<>
- inline bool Validate<TInterval>(i64 interval) {
- return interval > -i64(MAX_TIMESTAMP) && interval < i64(MAX_TIMESTAMP);
- }
- template<>
- inline bool Validate<TInterval64>(i64 interval) {
- return interval >= -MAX_INTERVAL64 && interval <= MAX_INTERVAL64;
- }
- // Split
- template<typename TUserDataType, bool Nullable>
- using TSplitArgReader = std::conditional_t<TTzDataType<TUserDataType>::Result,
- TTzDateBlockReader<TUserDataType, Nullable>,
- TFixedSizeBlockReader<typename TDataType<TUserDataType>::TLayout, Nullable>>;
- template<typename TUserDataType>
- struct TSplitKernelExec : TUnaryKernelExec<TSplitKernelExec<TUserDataType>, TSplitArgReader<TUserDataType, false>, TResourceArrayBuilder<false>> {
- static void Split(TBlockItem arg, TTMStorage& storage, const IValueBuilder& valueBuilder);
- template<typename TSink>
- static void Process(const IValueBuilder* valueBuilder, TBlockItem arg, const TSink& sink) {
- try {
- TBlockItem res {0};
- Split(arg, Reference(res), *valueBuilder);
- sink(res);
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << e.what()).data());
- }
- }
- };
- template <typename TUserDataType>
- class TSplit : public TBoxedValue {
- const TSourcePosition Pos_;
- public:
- explicit TSplit(TSourcePosition pos)
- : Pos_(pos)
- {}
- TUnboxedValue Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const override;
- static bool DeclareSignature(
- TStringRef name,
- TType* userType,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly)
- {
- const auto typeInfoHelper = builder.TypeInfoHelper();
- TTupleTypeInspector tuple(*typeInfoHelper, userType);
- Y_ENSURE(tuple);
- Y_ENSURE(tuple.GetElementsCount() > 0);
- TTupleTypeInspector argsTuple(*typeInfoHelper, tuple.GetElementType(0));
- Y_ENSURE(argsTuple);
- if (argsTuple.GetElementsCount() != 1) {
- builder.SetError("Expected one argument");
- return true;
- }
- auto argType = argsTuple.GetElementType(0);
- builder.UserType(userType);
- builder.SupportsBlocks();
- builder.IsStrict();
- TBlockTypeInspector block(*typeInfoHelper, argType);
- if (block) {
- const auto* blockArgType = builder.Block(false)->Item<TUserDataType>().Build();
- builder.Args()->Add(blockArgType).Flags(ICallablePayload::TArgumentFlags::AutoMap);
- const auto* retType = builder.Resource(TMResourceName);
- const auto* blockRetType = builder.Block(false)->Item(retType).Build();
- builder.Returns(blockRetType);
- if (!typesOnly) {
- builder.Implementation(new TSimpleArrowUdfImpl({blockArgType}, retType, block.IsScalar(),
- TSplitKernelExec<TUserDataType>::Do, builder, TString(name), arrow::compute::NullHandling::COMPUTED_NO_PREALLOCATE));
- }
- } else {
- builder.Args()->Add<TUserDataType>().Flags(ICallablePayload::TArgumentFlags::AutoMap);
- if constexpr (NUdf::TDataType<TUserDataType>::Features & NYql::NUdf::BigDateType) {
- builder.Returns(builder.Resource(TM64ResourceName));
- } else {
- builder.Returns(builder.Resource(TMResourceName));
- }
- if (!typesOnly) {
- builder.Implementation(new TSplit<TUserDataType>(builder.GetSourcePosition()));
- }
- }
- return true;
- }
- };
- template <>
- void TSplitKernelExec<TDate>::Split(TBlockItem arg, TTMStorage &storage, const IValueBuilder& builder) {
- storage.FromDate(builder.GetDateBuilder(), arg.Get<ui16>());
- }
- template <>
- void TSplitKernelExec<TDatetime>::Split(TBlockItem arg, TTMStorage &storage, const IValueBuilder& builder) {
- storage.FromDatetime(builder.GetDateBuilder(), arg.Get<ui32>());
- }
- template <>
- void TSplitKernelExec<TTimestamp>::Split(TBlockItem arg, TTMStorage &storage, const IValueBuilder& builder) {
- storage.FromTimestamp(builder.GetDateBuilder(), arg.Get<ui64>());
- }
- template <>
- void TSplitKernelExec<TTzDate>::Split(TBlockItem arg, TTMStorage &storage, const IValueBuilder& builder) {
- storage.FromDate(builder.GetDateBuilder(), arg.Get<ui16>(), arg.GetTimezoneId());
- }
- template <>
- void TSplitKernelExec<TTzDatetime>::Split(TBlockItem arg, TTMStorage &storage, const IValueBuilder& builder) {
- storage.FromDatetime(builder.GetDateBuilder(), arg.Get<ui32>(), arg.GetTimezoneId());
- }
- template <>
- void TSplitKernelExec<TTzTimestamp>::Split(TBlockItem arg, TTMStorage &storage, const IValueBuilder& builder) {
- storage.FromTimestamp(builder.GetDateBuilder(), arg.Get<ui64>(), arg.GetTimezoneId());
- }
- template <>
- void TSplitKernelExec<TDate32>::Split(TBlockItem, TTMStorage&, const IValueBuilder&) {
- ythrow yexception() << "Not implemented";
- }
- template <>
- void TSplitKernelExec<TDatetime64>::Split(TBlockItem, TTMStorage&, const IValueBuilder&) {
- ythrow yexception() << "Not implemented";
- }
- template <>
- void TSplitKernelExec<TTimestamp64>::Split(TBlockItem, TTMStorage&, const IValueBuilder&) {
- ythrow yexception() << "Not implemented";
- }
- template <>
- TUnboxedValue TSplit<TDate>::Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const
- {
- try {
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- auto& builder = valueBuilder->GetDateBuilder();
- TUnboxedValuePod result(0);
- auto& storage = Reference(result);
- storage.FromDate(builder, args[0].Get<ui16>());
- return result;
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
- }
- }
- template <>
- TUnboxedValue TSplit<TDate32>::Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const
- {
- try {
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- TUnboxedValuePod result(0);
- auto& storage = Reference<TM64ResourceName>(result);
- storage.FromDate32(valueBuilder->GetDateBuilder(), args[0].Get<i32>());
- return result;
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
- }
- }
- template <>
- TUnboxedValue TSplit<TDatetime>::Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const
- {
- try {
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- auto& builder = valueBuilder->GetDateBuilder();
- TUnboxedValuePod result(0);
- auto& storage = Reference(result);
- storage.FromDatetime(builder, args[0].Get<ui32>());
- return result;
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
- }
- }
- template <>
- TUnboxedValue TSplit<TDatetime64>::Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const
- {
- try {
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- TUnboxedValuePod result(0);
- auto& storage = Reference<TM64ResourceName>(result);
- storage.FromDatetime64(valueBuilder->GetDateBuilder(), args[0].Get<i64>());
- return result;
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
- }
- }
- template <>
- TUnboxedValue TSplit<TTimestamp>::Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const
- {
- try {
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- auto& builder = valueBuilder->GetDateBuilder();
- TUnboxedValuePod result(0);
- auto& storage = Reference(result);
- storage.FromTimestamp(builder, args[0].Get<ui64>());
- return result;
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
- }
- }
- template <>
- TUnboxedValue TSplit<TTimestamp64>::Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const
- {
- try {
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- TUnboxedValuePod result(0);
- auto& storage = Reference<TM64ResourceName>(result);
- storage.FromTimestamp64(valueBuilder->GetDateBuilder(), args[0].Get<i64>());
- return result;
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
- }
- }
- template <>
- TUnboxedValue TSplit<TTzDate>::Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const
- {
- try {
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- auto& builder = valueBuilder->GetDateBuilder();
- TUnboxedValuePod result(0);
- auto& storage = Reference(result);
- storage.FromDate(builder, args[0].Get<ui16>(), args[0].GetTimezoneId());
- return result;
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
- }
- }
- template <>
- TUnboxedValue TSplit<TTzDatetime>::Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const
- {
- try {
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- auto& builder = valueBuilder->GetDateBuilder();
- TUnboxedValuePod result(0);
- auto& storage = Reference(result);
- storage.FromDatetime(builder, args[0].Get<ui32>(), args[0].GetTimezoneId());
- return result;
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
- }
- }
- template <>
- TUnboxedValue TSplit<TTzTimestamp>::Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const
- {
- try {
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- auto& builder = valueBuilder->GetDateBuilder();
- TUnboxedValuePod result(0);
- auto& storage = Reference(result);
- storage.FromTimestamp(builder, args[0].Get<ui64>(), args[0].GetTimezoneId());
- return result;
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
- }
- }
- // Make*
- template<typename TUserDataType, bool Nullable>
- using TMakeResBuilder = std::conditional_t<TTzDataType<TUserDataType>::Result,
- TTzDateArrayBuilder<TUserDataType, Nullable>,
- TFixedSizeArrayBuilder<typename TDataType<TUserDataType>::TLayout, Nullable>>;
- template<typename TUserDataType>
- struct TMakeDateKernelExec : TUnaryKernelExec<TMakeDateKernelExec<TUserDataType>, TReaderTraits::TResource<false>, TMakeResBuilder<TUserDataType, false>> {
- static TBlockItem Make(TTMStorage& storage, const IValueBuilder& valueBuilder);
- template<typename TSink>
- static void Process(const IValueBuilder* valueBuilder, TBlockItem item, const TSink& sink) {
- auto& storage = Reference(item);
- sink(TBlockItem(Make(storage, *valueBuilder)));
- }
- };
- template<> TBlockItem TMakeDateKernelExec<TDate>::Make(TTMStorage& storage, const IValueBuilder& valueBuilder) {
- TBlockItem res(storage.ToDate(valueBuilder.GetDateBuilder(), /*local*/ false));
- return res;
- }
- template<> TBlockItem TMakeDateKernelExec<TDatetime>::Make(TTMStorage& storage, const IValueBuilder& valueBuilder) {
- TBlockItem res(storage.ToDatetime(valueBuilder.GetDateBuilder()));
- return res;
- }
- template<> TBlockItem TMakeDateKernelExec<TTimestamp>::Make(TTMStorage& storage, const IValueBuilder& valueBuilder) {
- TBlockItem res(storage.ToTimestamp(valueBuilder.GetDateBuilder()));
- return res;
- }
- template<> TBlockItem TMakeDateKernelExec<TTzDate>::Make(TTMStorage& storage, const IValueBuilder& valueBuilder) {
- TBlockItem res(storage.ToDate(valueBuilder.GetDateBuilder(), /*local*/ true));
- res.SetTimezoneId(storage.TimezoneId);
- return res;
- }
- template<> TBlockItem TMakeDateKernelExec<TTzDatetime>::Make(TTMStorage& storage, const IValueBuilder& valueBuilder) {
- TBlockItem res(storage.ToDatetime(valueBuilder.GetDateBuilder()));
- res.SetTimezoneId(storage.TimezoneId);
- return res;
- }
- template<> TBlockItem TMakeDateKernelExec<TTzTimestamp>::Make(TTMStorage& storage, const IValueBuilder& valueBuilder) {
- TBlockItem res(storage.ToTimestamp(valueBuilder.GetDateBuilder()));
- res.SetTimezoneId(storage.TimezoneId);
- return res;
- }
- BEGIN_SIMPLE_STRICT_ARROW_UDF(TMakeDate, TDate(TAutoMap<TResource<TMResourceName>>)) {
- auto& builder = valueBuilder->GetDateBuilder();
- auto& storage = Reference(args[0]);
- return TUnboxedValuePod(storage.ToDate(builder, false));
- }
- END_SIMPLE_ARROW_UDF(TMakeDate, TMakeDateKernelExec<TDate>::Do);
- BEGIN_SIMPLE_STRICT_ARROW_UDF(TMakeDatetime, TDatetime(TAutoMap<TResource<TMResourceName>>)) {
- auto& builder = valueBuilder->GetDateBuilder();
- auto& storage = Reference(args[0]);
- return TUnboxedValuePod(storage.ToDatetime(builder));
- }
- END_SIMPLE_ARROW_UDF(TMakeDatetime, TMakeDateKernelExec<TDatetime>::Do);
- BEGIN_SIMPLE_STRICT_ARROW_UDF(TMakeTimestamp, TTimestamp(TAutoMap<TResource<TMResourceName>>)) {
- auto& builder = valueBuilder->GetDateBuilder();
- auto& storage = Reference(args[0]);
- return TUnboxedValuePod(storage.ToTimestamp(builder));
- }
- END_SIMPLE_ARROW_UDF(TMakeTimestamp, TMakeDateKernelExec<TTimestamp>::Do);
- BEGIN_SIMPLE_STRICT_ARROW_UDF(TMakeTzDate, TTzDate(TAutoMap<TResource<TMResourceName>>)) {
- auto& builder = valueBuilder->GetDateBuilder();
- auto& storage = Reference(args[0]);
- try {
- TUnboxedValuePod result(storage.ToDate(builder, true));
- result.SetTimezoneId(storage.TimezoneId);
- return result;
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << "Timestamp "
- << storage.ToString()
- << " cannot be casted to TzDate"
- ).data());
- }
- }
- END_SIMPLE_ARROW_UDF(TMakeTzDate, TMakeDateKernelExec<TTzDate>::Do);
- BEGIN_SIMPLE_STRICT_ARROW_UDF(TMakeTzDatetime, TTzDatetime(TAutoMap<TResource<TMResourceName>>)) {
- auto& builder = valueBuilder->GetDateBuilder();
- auto& storage = Reference(args[0]);
- TUnboxedValuePod result(storage.ToDatetime(builder));
- result.SetTimezoneId(storage.TimezoneId);
- return result;
- }
- END_SIMPLE_ARROW_UDF(TMakeTzDatetime, TMakeDateKernelExec<TTzDatetime>::Do);
- BEGIN_SIMPLE_STRICT_ARROW_UDF(TMakeTzTimestamp, TTzTimestamp(TAutoMap<TResource<TMResourceName>>)) {
- auto& builder = valueBuilder->GetDateBuilder();
- auto& storage = Reference(args[0]);
- TUnboxedValuePod result(storage.ToTimestamp(builder));
- result.SetTimezoneId(storage.TimezoneId);
- return result;
- }
- END_SIMPLE_ARROW_UDF(TMakeTzTimestamp, TMakeDateKernelExec<TTzTimestamp>::Do);
- SIMPLE_STRICT_UDF(TConvert, TResource<TM64ResourceName>(TAutoMap<TResource<TMResourceName>>)) {
- Y_UNUSED(valueBuilder);
- TUnboxedValuePod result(0);
- auto& arg = Reference(args[0]);
- auto& storage = Reference<TM64ResourceName>(result);
- storage.From(arg);
- return result;
- }
- SIMPLE_STRICT_UDF(TMakeDate32, TDate32(TAutoMap<TResource<TM64ResourceName>>)) {
- auto& storage = Reference<TM64ResourceName>(args[0]);
- return TUnboxedValuePod(storage.ToDate32(valueBuilder->GetDateBuilder()));
- }
- SIMPLE_STRICT_UDF(TMakeDatetime64, TDatetime64(TAutoMap<TResource<TM64ResourceName>>)) {
- auto& storage = Reference<TM64ResourceName>(args[0]);
- return TUnboxedValuePod(storage.ToDatetime64(valueBuilder->GetDateBuilder()));
- }
- SIMPLE_STRICT_UDF(TMakeTimestamp64, TTimestamp64(TAutoMap<TResource<TM64ResourceName>>)) {
- auto& storage = Reference<TM64ResourceName>(args[0]);
- return TUnboxedValuePod(storage.ToTimestamp64(valueBuilder->GetDateBuilder()));
- }
- // Get*
- // #define GET_METHOD(field, type) \
- // struct TGet##field##KernelExec : TUnaryKernelExec<TGet##field##KernelExec, TReaderTraits::TResource<false>, TFixedSizeArrayBuilder<type, false>> { \
- // template<typename TSink> \
- // static void Process(TBlockItem item, const IValueBuilder& valueBuilder, const TSink& sink) { \
- // Y_UNUSED(valueBuilder); \
- // sink(TBlockItem(Get##field(item))); \
- // } \
- // }; \
- // BEGIN_SIMPLE_STRICT_ARROW_UDF(TGet##field, type(TAutoMap<TResource<TMResourceName>>)) { \
- // Y_UNUSED(valueBuilder); \
- // return TUnboxedValuePod(Get##field(args[0])); \
- // } \
- // END_SIMPLE_ARROW_UDF_WITH_NULL_HANDLING(TGet##field, TGet##field##KernelExec::Do, arrow::compute::NullHandling::INTERSECTION);
- template<const char* TUdfName,
- typename TResultType, TResultType (*Accessor)(const TUnboxedValuePod&),
- typename TResultWType, TResultWType (*WAccessor)(const TUnboxedValuePod&)>
- class TGetDateComponent: public ::NYql::NUdf::TBoxedValue {
- public:
- typedef bool TTypeAwareMarker;
- static const ::NYql::NUdf::TStringRef& Name() {
- static auto name = TStringRef(TUdfName, std::strlen(TUdfName));
- return name;
- }
- static bool DeclareSignature(
- const ::NYql::NUdf::TStringRef& name,
- ::NYql::NUdf::TType* userType,
- ::NYql::NUdf::IFunctionTypeInfoBuilder& builder,
- bool typesOnly)
- {
- if (Name() != name) {
- return false;
- }
- if (!userType) {
- builder.SetError("User type is missing");
- return true;
- }
- builder.UserType(userType);
- const auto typeInfoHelper = builder.TypeInfoHelper();
- TTupleTypeInspector tuple(*typeInfoHelper, userType);
- Y_ENSURE(tuple, "Tuple with args and options tuples expected");
- Y_ENSURE(tuple.GetElementsCount() > 0,
- "Tuple has to contain positional arguments");
- TTupleTypeInspector argsTuple(*typeInfoHelper, tuple.GetElementType(0));
- Y_ENSURE(argsTuple, "Tuple with args expected");
- if (argsTuple.GetElementsCount() != 1) {
- builder.SetError("Single argument expected");
- return true;
- }
- auto argType = argsTuple.GetElementType(0);
- if (const auto optType = TOptionalTypeInspector(*typeInfoHelper, argType)) {
- argType = optType.GetItemType();
- }
- TResourceTypeInspector resource(*typeInfoHelper, argType);
- if (!resource) {
- TDataTypeInspector data(*typeInfoHelper, argType);
- if (!data) {
- builder.SetError("Data type expected");
- return true;
- }
- const auto features = NUdf::GetDataTypeInfo(NUdf::GetDataSlot(data.GetTypeId())).Features;
- if (features & NUdf::BigDateType) {
- BuildSignature<TResultWType, TM64ResourceName, WAccessor>(builder, typesOnly);
- return true;
- }
- if (features & (NUdf::DateType | NUdf::TzDateType)) {
- BuildSignature<TResultType, TMResourceName, Accessor>(builder, typesOnly);
- return true;
- }
- ::TStringBuilder sb;
- sb << "Invalid argument type: got ";
- TTypePrinter(*typeInfoHelper, argType).Out(sb.Out);
- sb << ", but Resource<" << TMResourceName <<"> or Resource<"
- << TM64ResourceName << "> expected";
- builder.SetError(sb);
- return true;
- }
- if (resource.GetTag() == TStringRef::Of(TM64ResourceName)) {
- BuildSignature<TResultWType, TM64ResourceName, WAccessor>(builder, typesOnly);
- return true;
- }
- if (resource.GetTag() == TStringRef::Of(TMResourceName)) {
- BuildSignature<TResultType, TMResourceName, Accessor>(builder, typesOnly);
- return true;
- }
- builder.SetError("Unexpected Resource tag");
- return true;
- }
- private:
- template<typename TResult, TResult (*Func)(const TUnboxedValuePod&)>
- class TImpl : public TBoxedValue {
- public:
- TUnboxedValue Run(const IValueBuilder* valueBuilder, const TUnboxedValuePod* args) const final {
- Y_UNUSED(valueBuilder);
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- return TUnboxedValuePod(TResult(Func(args[0])));
- }
- };
- template<typename TResult, const char* TResourceName, TResult (*Func)(const TUnboxedValuePod&)>
- static void BuildSignature(NUdf::IFunctionTypeInfoBuilder& builder, bool typesOnly) {
- builder.Returns<TResult>();
- builder.Args()->Add<TAutoMap<TResource<TResourceName>>>();
- builder.IsStrict();
- if (!typesOnly) {
- builder.Implementation(new TImpl<TResult, Func>());
- }
- }
- };
- // TODO: Merge this with <TGetDateComponent> class.
- template<const char* TUdfName, auto Accessor, auto WAccessor>
- class TGetDateComponentName: public ::NYql::NUdf::TBoxedValue {
- public:
- typedef bool TTypeAwareMarker;
- static const ::NYql::NUdf::TStringRef& Name() {
- static auto name = TStringRef(TUdfName, std::strlen(TUdfName));
- return name;
- }
- static bool DeclareSignature(
- const ::NYql::NUdf::TStringRef& name,
- ::NYql::NUdf::TType* userType,
- ::NYql::NUdf::IFunctionTypeInfoBuilder& builder,
- bool typesOnly)
- {
- if (Name() != name) {
- return false;
- }
- if (!userType) {
- builder.SetError("User type is missing");
- return true;
- }
- builder.UserType(userType);
- const auto typeInfoHelper = builder.TypeInfoHelper();
- TTupleTypeInspector tuple(*typeInfoHelper, userType);
- Y_ENSURE(tuple, "Tuple with args and options tuples expected");
- Y_ENSURE(tuple.GetElementsCount() > 0,
- "Tuple has to contain positional arguments");
- TTupleTypeInspector argsTuple(*typeInfoHelper, tuple.GetElementType(0));
- Y_ENSURE(argsTuple, "Tuple with args expected");
- if (argsTuple.GetElementsCount() != 1) {
- builder.SetError("Single argument expected");
- return true;
- }
- auto argType = argsTuple.GetElementType(0);
- if (const auto optType = TOptionalTypeInspector(*typeInfoHelper, argType)) {
- argType = optType.GetItemType();
- }
- TResourceTypeInspector resource(*typeInfoHelper, argType);
- if (!resource) {
- TDataTypeInspector data(*typeInfoHelper, argType);
- if (!data) {
- builder.SetError("Data type expected");
- return true;
- }
- const auto features = NUdf::GetDataTypeInfo(NUdf::GetDataSlot(data.GetTypeId())).Features;
- if (features & NUdf::BigDateType) {
- BuildSignature<TM64ResourceName, WAccessor>(builder, typesOnly);
- return true;
- }
- if (features & (NUdf::DateType | NUdf::TzDateType)) {
- BuildSignature<TMResourceName, Accessor>(builder, typesOnly);
- return true;
- }
- ::TStringBuilder sb;
- sb << "Invalid argument type: got ";
- TTypePrinter(*typeInfoHelper, argType).Out(sb.Out);
- sb << ", but Resource<" << TMResourceName <<"> or Resource<"
- << TM64ResourceName << "> expected";
- builder.SetError(sb);
- return true;
- }
- if (resource.GetTag() == TStringRef::Of(TM64ResourceName)) {
- BuildSignature<TM64ResourceName, WAccessor>(builder, typesOnly);
- return true;
- }
- if (resource.GetTag() == TStringRef::Of(TMResourceName)) {
- BuildSignature<TMResourceName, Accessor>(builder, typesOnly);
- return true;
- }
- builder.SetError("Unexpected Resource tag");
- return true;
- }
- private:
- template<auto Func>
- class TImpl : public TBoxedValue {
- public:
- TUnboxedValue Run(const IValueBuilder* valueBuilder, const TUnboxedValuePod* args) const final {
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- return Func(valueBuilder, args[0]);
- }
- };
- template<const char* TResourceName, auto Func>
- static void BuildSignature(NUdf::IFunctionTypeInfoBuilder& builder, bool typesOnly) {
- builder.Returns<char*>();
- builder.Args()->Add<TAutoMap<TResource<TResourceName>>>();
- builder.IsStrict();
- if (!typesOnly) {
- builder.Implementation(new TImpl<Func>());
- }
- }
- };
- // template<typename TValue>
- // TValue GetMonthNameValue(size_t idx) {
- // static const std::array<TValue, 12U> monthNames = {{
- // TValue::Embedded(TStringRef::Of("January")),
- // TValue::Embedded(TStringRef::Of("February")),
- // TValue::Embedded(TStringRef::Of("March")),
- // TValue::Embedded(TStringRef::Of("April")),
- // TValue::Embedded(TStringRef::Of("May")),
- // TValue::Embedded(TStringRef::Of("June")),
- // TValue::Embedded(TStringRef::Of("July")),
- // TValue::Embedded(TStringRef::Of("August")),
- // TValue::Embedded(TStringRef::Of("September")),
- // TValue::Embedded(TStringRef::Of("October")),
- // TValue::Embedded(TStringRef::Of("November")),
- // TValue::Embedded(TStringRef::Of("December"))
- // }};
- // return monthNames.at(idx);
- // }
- // struct TGetMonthNameKernelExec : TUnaryKernelExec<TGetMonthNameKernelExec, TReaderTraits::TResource<true>, TStringArrayBuilder<arrow::StringType, false>> {
- // template<typename TSink>
- // static void Process(const IValueBuilder* valueBuilder, TBlockItem item, const TSink& sink) {
- // Y_UNUSED(valueBuilder);
- // sink(GetMonthNameValue<TBlockItem>(GetMonth(item) - 1U));
- // }
- // };
- // BEGIN_SIMPLE_STRICT_ARROW_UDF(TGetMonthName, char*(TAutoMap<TResource<TMResourceName>>)) {
- // Y_UNUSED(valueBuilder);
- // return GetMonthNameValue<TUnboxedValue>(GetMonth(*args) - 1U);
- // }
- // END_SIMPLE_ARROW_UDF_WITH_NULL_HANDLING(TGetMonthName, TGetMonthNameKernelExec::Do, arrow::compute::NullHandling::INTERSECTION);
- template<const char* TResourceName>
- TUnboxedValue GetMonthName(const IValueBuilder* valueBuilder, const TUnboxedValuePod& arg) {
- Y_UNUSED(valueBuilder);
- static const std::array<TUnboxedValue, 12U> monthNames = {{
- TUnboxedValuePod::Embedded(TStringRef::Of("January")),
- TUnboxedValuePod::Embedded(TStringRef::Of("February")),
- TUnboxedValuePod::Embedded(TStringRef::Of("March")),
- TUnboxedValuePod::Embedded(TStringRef::Of("April")),
- TUnboxedValuePod::Embedded(TStringRef::Of("May")),
- TUnboxedValuePod::Embedded(TStringRef::Of("June")),
- TUnboxedValuePod::Embedded(TStringRef::Of("July")),
- TUnboxedValuePod::Embedded(TStringRef::Of("August")),
- TUnboxedValuePod::Embedded(TStringRef::Of("September")),
- TUnboxedValuePod::Embedded(TStringRef::Of("October")),
- TUnboxedValuePod::Embedded(TStringRef::Of("November")),
- TUnboxedValuePod::Embedded(TStringRef::Of("December"))
- }};
- return monthNames.at(GetMonth<TResourceName>(arg) - 1U);
- }
- // struct TGetDayOfMonthKernelExec : TUnaryKernelExec<TGetMonthNameKernelExec, TReaderTraits::TResource<false>, TFixedSizeArrayBuilder<ui8, false>> {
- // template<typename TSink>
- // static void Process(TBlockItem item, const TSink& sink) {
- // sink(GetDay(item));
- // }
- // };
- // BEGIN_SIMPLE_STRICT_ARROW_UDF(TGetDayOfMonth, ui8(TAutoMap<TResource<TMResourceName>>)) {
- // Y_UNUSED(valueBuilder);
- // return TUnboxedValuePod(GetDay(args[0]));
- // }
- // END_SIMPLE_ARROW_UDF_WITH_NULL_HANDLING(TGetDayOfMonth, TGetDayOfMonthKernelExec::Do, arrow::compute::NullHandling::INTERSECTION);
- template<const char* TResourceName>
- TUnboxedValue GetDayOfWeekName(const IValueBuilder* valueBuilder, const TUnboxedValuePod& arg) {
- Y_UNUSED(valueBuilder);
- static const std::array<TUnboxedValue, 7U> dayNames = {{
- TUnboxedValuePod::Embedded(TStringRef::Of("Monday")),
- TUnboxedValuePod::Embedded(TStringRef::Of("Tuesday")),
- TUnboxedValuePod::Embedded(TStringRef::Of("Wednesday")),
- TUnboxedValuePod::Embedded(TStringRef::Of("Thursday")),
- TUnboxedValuePod::Embedded(TStringRef::Of("Friday")),
- TUnboxedValuePod::Embedded(TStringRef::Of("Saturday")),
- TUnboxedValuePod::Embedded(TStringRef::Of("Sunday"))
- }};
- return dayNames.at(GetDayOfWeek<TResourceName>(arg) - 1U);
- }
- // struct TGetDayOfWeekNameKernelExec : TUnaryKernelExec<TGetDayOfWeekNameKernelExec, TReaderTraits::TResource<true>, TStringArrayBuilder<arrow::StringType, false>> {
- // template<typename TSink>
- // static void Process(const IValueBuilder* valueBuilder, TBlockItem item, const TSink& sink) {
- // Y_UNUSED(valueBuilder);
- // sink(GetDayNameValue<TBlockItem>(GetDayOfWeek(item) - 1U));
- // }
- // };
- // BEGIN_SIMPLE_STRICT_ARROW_UDF(TGetDayOfWeekName, char*(TAutoMap<TResource<TMResourceName>>)) {
- // Y_UNUSED(valueBuilder);
- // return GetDayNameValue<TUnboxedValuePod>(GetDayOfWeek(*args) - 1U);
- // }
- // END_SIMPLE_ARROW_UDF_WITH_NULL_HANDLING(TGetDayOfWeekName, TGetDayOfWeekNameKernelExec::Do, arrow::compute::NullHandling::INTERSECTION);
- struct TTGetTimezoneNameKernelExec : TUnaryKernelExec<TTGetTimezoneNameKernelExec, TReaderTraits::TResource<false>, TStringArrayBuilder<arrow::BinaryType, false>> {
- template<typename TSink>
- static void Process(const IValueBuilder* valueBuilder, TBlockItem item, const TSink& sink) {
- Y_UNUSED(valueBuilder);
- auto timezoneId = GetTimezoneId(item);
- if (timezoneId >= NUdf::GetTimezones().size()) {
- sink(TBlockItem{});
- } else {
- sink(TBlockItem{NUdf::GetTimezones()[timezoneId]});
- }
- }
- };
- BEGIN_SIMPLE_STRICT_ARROW_UDF(TGetTimezoneName, char*(TAutoMap<TResource<TMResourceName>>)) {
- auto timezoneId = GetTimezoneId(args[0]);
- if (timezoneId >= NUdf::GetTimezones().size()) {
- return TUnboxedValuePod();
- }
- return valueBuilder->NewString(NUdf::GetTimezones()[timezoneId]);
- }
- END_SIMPLE_ARROW_UDF(TGetTimezoneName, TTGetTimezoneNameKernelExec::Do);
- template<const char* TResourceName>
- TUnboxedValue GetTimezoneName(const IValueBuilder* valueBuilder, const TUnboxedValuePod& arg) {
- const ui16 tzId = GetTimezoneId<TResourceName>(arg);
- const auto& tzNames = NUdf::GetTimezones();
- if (tzId >= tzNames.size()) {
- return TUnboxedValuePod();
- }
- return valueBuilder->NewString(tzNames[tzId]);
- }
- // Update
- class TUpdate : public TBoxedValue {
- public:
- typedef bool TTypeAwareMarker;
- static const TStringRef& Name() {
- static auto name = TStringRef::Of("Update");
- return name;
- }
- static bool DeclareSignature(
- const TStringRef& name,
- TType* userType,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly)
- {
- if (Name() != name) {
- return false;
- }
- if (!userType) {
- builder.SetError("User type is missing");
- return true;
- }
- builder.UserType(userType);
- const auto typeInfoHelper = builder.TypeInfoHelper();
- TTupleTypeInspector tuple(*typeInfoHelper, userType);
- Y_ENSURE(tuple, "Tuple with args and options tuples expected");
- Y_ENSURE(tuple.GetElementsCount() > 0,
- "Tuple has to contain positional arguments");
- TTupleTypeInspector argsTuple(*typeInfoHelper, tuple.GetElementType(0));
- Y_ENSURE(argsTuple, "Tuple with args expected");
- if (argsTuple.GetElementsCount() == 0) {
- builder.SetError("At least one argument expected");
- return true;
- }
- auto argType = argsTuple.GetElementType(0);
- if (const auto optType = TOptionalTypeInspector(*typeInfoHelper, argType)) {
- argType = optType.GetItemType();
- }
- TResourceTypeInspector resource(*typeInfoHelper, argType);
- if (!resource) {
- TDataTypeInspector data(*typeInfoHelper, argType);
- if (!data) {
- SetInvalidTypeError(builder, typeInfoHelper, argType);
- return true;
- }
- const auto features = NUdf::GetDataTypeInfo(NUdf::GetDataSlot(data.GetTypeId())).Features;
- if (features & NUdf::BigDateType) {
- BuildSignature<TM64ResourceName>(builder, typesOnly);
- return true;
- }
- if (features & (NUdf::DateType | NUdf::TzDateType)) {
- BuildSignature<TMResourceName>(builder, typesOnly);
- return true;
- }
- SetInvalidTypeError(builder, typeInfoHelper, argType);
- return true;
- }
- if (resource.GetTag() == TStringRef::Of(TM64ResourceName)) {
- BuildSignature<TM64ResourceName>(builder, typesOnly);
- return true;
- }
- if (resource.GetTag() == TStringRef::Of(TMResourceName)) {
- BuildSignature<TMResourceName>(builder, typesOnly);
- return true;
- }
- ::TStringBuilder sb;
- sb << "Unexpected Resource tag: got '" << resource.GetTag() << "'";
- builder.SetError(sb);
- return true;
- }
- private:
- template<const char* TResourceName>
- class TImpl : public TBoxedValue {
- public:
- TUnboxedValue Run(const IValueBuilder* valueBuilder, const TUnboxedValuePod* args) const final {
- try {
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- auto result = args[0];
- if (args[1]) {
- auto year = args[1].Get<std::conditional_t<TResourceName == TMResourceName, ui16, i32>>();
- if (!ValidateYear<TResourceName>(year)) {
- return TUnboxedValuePod();
- }
- SetYear<TResourceName>(result, year);
- }
- if (args[2]) {
- auto month = args[2].Get<ui8>();
- if (!ValidateMonth(month)) {
- return TUnboxedValuePod();
- }
- SetMonth<TResourceName>(result, month);
- }
- if (args[3]) {
- auto day = args[3].Get<ui8>();
- if (!ValidateDay(day)) {
- return TUnboxedValuePod();
- }
- SetDay<TResourceName>(result, day);
- }
- if (args[4]) {
- auto hour = args[4].Get<ui8>();
- if (!ValidateHour(hour)) {
- return TUnboxedValuePod();
- }
- SetHour<TResourceName>(result, hour);
- }
- if (args[5]) {
- auto minute = args[5].Get<ui8>();
- if (!ValidateMinute(minute)) {
- return TUnboxedValuePod();
- }
- SetMinute<TResourceName>(result, minute);
- }
- if (args[6]) {
- auto second = args[6].Get<ui8>();
- if (!ValidateSecond(second)) {
- return TUnboxedValuePod();
- }
- SetSecond<TResourceName>(result, second);
- }
- if (args[7]) {
- auto microsecond = args[7].Get<ui32>();
- if (!ValidateMicrosecond(microsecond)) {
- return TUnboxedValuePod();
- }
- SetMicrosecond<TResourceName>(result, microsecond);
- }
- if (args[8]) {
- auto timezoneId = args[8].Get<ui16>();
- if (!ValidateTimezoneId(timezoneId)) {
- return TUnboxedValuePod();
- }
- SetTimezoneId<TResourceName>(result, timezoneId);
- }
- auto& builder = valueBuilder->GetDateBuilder();
- auto& storage = Reference<TResourceName>(result);
- if (!storage.Validate(builder)) {
- return TUnboxedValuePod();
- }
- return result;
- } catch (const std::exception& e) {
- TStringBuilder sb;
- sb << CurrentExceptionMessage();
- sb << Endl << "[" << TStringBuf(Name()) << "]" ;
- UdfTerminate(sb.c_str());
- }
- }
- };
- static void SetInvalidTypeError(NUdf::IFunctionTypeInfoBuilder& builder,
- ITypeInfoHelper::TPtr typeInfoHelper, const TType* argType)
- {
- ::TStringBuilder sb;
- sb << "Invalid argument type: got ";
- TTypePrinter(*typeInfoHelper, argType).Out(sb.Out);
- sb << ", but Resource<" << TMResourceName <<"> or Resource<"
- << TM64ResourceName << "> expected";
- builder.SetError(sb);
- }
- template<const char* TResourceName>
- static void BuildSignature(NUdf::IFunctionTypeInfoBuilder& builder, bool typesOnly) {
- builder.Returns<TOptional<TResource<TResourceName>>>();
- builder.OptionalArgs(8).Args()->Add<TAutoMap<TResource<TResourceName>>>()
- .template Add<TOptional<std::conditional_t<TResourceName == TMResourceName, ui16, i32>>>().Name("Year")
- .template Add<TOptional<ui8>>().Name("Month")
- .template Add<TOptional<ui8>>().Name("Day")
- .template Add<TOptional<ui8>>().Name("Hour")
- .template Add<TOptional<ui8>>().Name("Minute")
- .template Add<TOptional<ui8>>().Name("Second")
- .template Add<TOptional<ui32>>().Name("Microsecond")
- .template Add<TOptional<ui16>>().Name("TimezoneId");
- builder.IsStrict();
- if (!typesOnly) {
- builder.Implementation(new TImpl<TResourceName>());
- }
- }
- };
- // From*
- template<typename TInput, typename TOutput, i64 UsecMultiplier>
- inline TUnboxedValuePod TFromConverter(TInput arg) {
- using TLayout = TDataType<TOutput>::TLayout;
- const TLayout usec = TLayout(arg) * UsecMultiplier;
- return Validate<TOutput>(usec) ? TUnboxedValuePod(usec) : TUnboxedValuePod();
- }
- template<typename TInput, typename TOutput, i64 UsecMultiplier>
- using TFromConverterKernel = TUnaryUnsafeFixedSizeFilterKernel<TInput,
- typename TDataType<TOutput>::TLayout, [] (TInput arg) {
- using TLayout = TDataType<TOutput>::TLayout;
- const TLayout usec = TLayout(arg) * UsecMultiplier;
- return std::make_pair(usec, Validate<TOutput>(usec));
- }>;
- #define DATETIME_FROM_CONVERTER_UDF(name, retType, argType, usecMultiplier) \
- BEGIN_SIMPLE_STRICT_ARROW_UDF(T##name, TOptional<retType>(TAutoMap<argType>)) { \
- Y_UNUSED(valueBuilder); \
- return TFromConverter<argType, retType, usecMultiplier>(args[0].Get<argType>()); \
- } \
- \
- END_SIMPLE_ARROW_UDF(T##name, (TFromConverterKernel<argType, retType, usecMultiplier>::Do))
- DATETIME_FROM_CONVERTER_UDF(FromSeconds, TTimestamp, ui32, UsecondsInSecond);
- DATETIME_FROM_CONVERTER_UDF(FromMilliseconds, TTimestamp, ui64, UsecondsInMilliseconds);
- DATETIME_FROM_CONVERTER_UDF(FromMicroseconds, TTimestamp, ui64, 1);
- DATETIME_FROM_CONVERTER_UDF(FromSeconds64, TTimestamp64, i64, UsecondsInSecond);
- DATETIME_FROM_CONVERTER_UDF(FromMilliseconds64, TTimestamp64, i64, UsecondsInMilliseconds);
- DATETIME_FROM_CONVERTER_UDF(FromMicroseconds64, TTimestamp64, i64, 1);
- DATETIME_FROM_CONVERTER_UDF(IntervalFromDays, TInterval, i32, UsecondsInDay);
- DATETIME_FROM_CONVERTER_UDF(IntervalFromHours, TInterval, i32, UsecondsInHour);
- DATETIME_FROM_CONVERTER_UDF(IntervalFromMinutes, TInterval, i32, UsecondsInMinute);
- DATETIME_FROM_CONVERTER_UDF(IntervalFromSeconds, TInterval, i32, UsecondsInSecond);
- DATETIME_FROM_CONVERTER_UDF(IntervalFromMilliseconds, TInterval, i64, UsecondsInMilliseconds);
- DATETIME_FROM_CONVERTER_UDF(IntervalFromMicroseconds, TInterval, i64, 1);
- DATETIME_FROM_CONVERTER_UDF(Interval64FromDays, TInterval64, i32, UsecondsInDay);
- DATETIME_FROM_CONVERTER_UDF(Interval64FromHours, TInterval64, i64, UsecondsInHour);
- DATETIME_FROM_CONVERTER_UDF(Interval64FromMinutes, TInterval64, i64, UsecondsInMinute);
- DATETIME_FROM_CONVERTER_UDF(Interval64FromSeconds, TInterval64, i64, UsecondsInSecond);
- DATETIME_FROM_CONVERTER_UDF(Interval64FromMilliseconds, TInterval64, i64, UsecondsInMilliseconds);
- DATETIME_FROM_CONVERTER_UDF(Interval64FromMicroseconds, TInterval64, i64, 1);
- // To*
- BEGIN_SIMPLE_STRICT_ARROW_UDF(TToDays, i32(TAutoMap<TInterval>)) {
- Y_UNUSED(valueBuilder);
- return TUnboxedValuePod(i32(args[0].Get<i64>() / UsecondsInDay));
- }
- END_SIMPLE_ARROW_UDF_WITH_NULL_HANDLING(TToDays,
- (UnaryPreallocatedExecImpl<i64, i32, [] (i64 arg) { return i32(arg / UsecondsInDay); }>),
- arrow::compute::NullHandling::INTERSECTION);
- BEGIN_SIMPLE_STRICT_ARROW_UDF(TToHours, i32(TAutoMap<TInterval>)) {
- Y_UNUSED(valueBuilder);
- return TUnboxedValuePod(i32(args[0].Get<i64>() / UsecondsInHour));
- }
- END_SIMPLE_ARROW_UDF_WITH_NULL_HANDLING(TToHours,
- (UnaryPreallocatedExecImpl<i64, i32, [] (i64 arg) { return i32(arg / UsecondsInHour); }>),
- arrow::compute::NullHandling::INTERSECTION);
- BEGIN_SIMPLE_STRICT_ARROW_UDF(TToMinutes, i32(TAutoMap<TInterval>)) {
- Y_UNUSED(valueBuilder);
- return TUnboxedValuePod(i32(args[0].Get<i64>() / UsecondsInMinute));
- }
- END_SIMPLE_ARROW_UDF_WITH_NULL_HANDLING(TToMinutes,
- (UnaryPreallocatedExecImpl<i64, i32, [] (i64 arg) { return i32(arg / UsecondsInMinute); }>),
- arrow::compute::NullHandling::INTERSECTION);
- // StartOf*
- template<auto Core>
- struct TStartOfKernelExec : TUnaryKernelExec<TStartOfKernelExec<Core>, TResourceBlockReader<false>, TResourceArrayBuilder<true>> {
- template<typename TSink>
- static void Process(const IValueBuilder* valueBuilder, TBlockItem item, const TSink& sink) {
- if (auto res = Core(Reference(item), *valueBuilder)) {
- Reference(item) = res.GetRef();
- sink(item);
- } else {
- sink(TBlockItem{});
- }
- }
- };
- template<const char* TResourceName, auto Core>
- TUnboxedValue SimpleDatetimeToDatetimeUdf(const IValueBuilder* valueBuilder, const TUnboxedValuePod* args) {
- auto result = args[0];
- auto& storage = Reference<TResourceName>(result);
- if (auto res = Core(storage, *valueBuilder)) {
- storage = res.GetRef();
- return result;
- }
- return TUnboxedValuePod{};
- }
- template<const char* TUdfName, auto Boundary, auto WBoundary>
- class TBoundaryOf: public ::NYql::NUdf::TBoxedValue {
- public:
- typedef bool TTypeAwareMarker;
- static const ::NYql::NUdf::TStringRef& Name() {
- static auto name = TStringRef(TUdfName, std::strlen(TUdfName));
- return name;
- }
- static bool DeclareSignature(
- const ::NYql::NUdf::TStringRef& name,
- ::NYql::NUdf::TType* userType,
- ::NYql::NUdf::IFunctionTypeInfoBuilder& builder,
- bool typesOnly)
- {
- if (Name() != name) {
- return false;
- }
- if (!userType) {
- builder.SetError("User type is missing");
- return true;
- }
- builder.UserType(userType);
- const auto typeInfoHelper = builder.TypeInfoHelper();
- TTupleTypeInspector tuple(*typeInfoHelper, userType);
- Y_ENSURE(tuple, "Tuple with args and options tuples expected");
- Y_ENSURE(tuple.GetElementsCount() > 0,
- "Tuple has to contain positional arguments");
- TTupleTypeInspector argsTuple(*typeInfoHelper, tuple.GetElementType(0));
- Y_ENSURE(argsTuple, "Tuple with args expected");
- if (argsTuple.GetElementsCount() != 1) {
- builder.SetError("Single argument expected");
- return true;
- }
- auto argType = argsTuple.GetElementType(0);
- if (const auto optType = TOptionalTypeInspector(*typeInfoHelper, argType)) {
- argType = optType.GetItemType();
- }
- TResourceTypeInspector resource(*typeInfoHelper, argType);
- if (!resource) {
- TDataTypeInspector data(*typeInfoHelper, argType);
- if (!data) {
- SetInvalidTypeError(builder, typeInfoHelper, argType);
- return true;
- }
- const auto features = NUdf::GetDataTypeInfo(NUdf::GetDataSlot(data.GetTypeId())).Features;
- if (features & NUdf::BigDateType) {
- BuildSignature<TM64ResourceName, WBoundary>(builder, typesOnly);
- return true;
- }
- if (features & (NUdf::DateType | NUdf::TzDateType)) {
- BuildSignature<TMResourceName, Boundary>(builder, typesOnly);
- return true;
- }
- SetInvalidTypeError(builder, typeInfoHelper, argType);
- return true;
- }
- if (resource.GetTag() == TStringRef::Of(TM64ResourceName)) {
- BuildSignature<TM64ResourceName, WBoundary>(builder, typesOnly);
- return true;
- }
- if (resource.GetTag() == TStringRef::Of(TMResourceName)) {
- BuildSignature<TMResourceName, Boundary>(builder, typesOnly);
- return true;
- }
- ::TStringBuilder sb;
- sb << "Unexpected Resource tag: got '" << resource.GetTag() << "'";
- builder.SetError(sb);
- return true;
- }
- private:
- template<auto Func>
- class TImpl : public TBoxedValue {
- public:
- TUnboxedValue Run(const IValueBuilder* valueBuilder, const TUnboxedValuePod* args) const final {
- try {
- return Func(valueBuilder, args);
- } catch (const std::exception&) {
- TStringBuilder sb;
- sb << CurrentExceptionMessage();
- sb << Endl << "[" << TStringBuf(Name()) << "]" ;
- UdfTerminate(sb.c_str());
- }
- }
- };
- static void SetInvalidTypeError(NUdf::IFunctionTypeInfoBuilder& builder,
- ITypeInfoHelper::TPtr typeInfoHelper, const TType* argType)
- {
- ::TStringBuilder sb;
- sb << "Invalid argument type: got ";
- TTypePrinter(*typeInfoHelper, argType).Out(sb.Out);
- sb << ", but Resource<" << TMResourceName <<"> or Resource<"
- << TM64ResourceName << "> expected";
- builder.SetError(sb);
- }
- template< const char* TResourceName, auto Func>
- static void BuildSignature(NUdf::IFunctionTypeInfoBuilder& builder, bool typesOnly) {
- builder.Returns<TOptional<TResource<TResourceName>>>();
- builder.Args()->Add<TAutoMap<TResource<TResourceName>>>();
- builder.IsStrict();
- if (!typesOnly) {
- builder.Implementation(new TImpl<Func>());
- }
- }
- };
- template<typename TStorage>
- void SetStartOfDay(TStorage& storage) {
- storage.Hour = 0;
- storage.Minute = 0;
- storage.Second = 0;
- storage.Microsecond = 0;
- }
- template<typename TStorage>
- void SetEndOfDay(TStorage& storage) {
- storage.Hour = 23;
- storage.Minute = 59;
- storage.Second = 59;
- storage.Microsecond = 999999;
- }
- template<typename TStorage>
- TMaybe<TStorage> StartOfYear(TStorage storage, const IValueBuilder& valueBuilder) {
- storage.Month = 1;
- storage.Day = 1;
- SetStartOfDay(storage);
- if (!storage.Validate(valueBuilder.GetDateBuilder())) {
- return {};
- }
- return storage;
- }
- template<typename TStorage>
- TMaybe<TStorage> EndOfYear(TStorage storage, const IValueBuilder& valueBuilder) {
- storage.Month = 12;
- storage.Day = 31;
- SetEndOfDay(storage);
- if (!storage.Validate(valueBuilder.GetDateBuilder())) {
- return {};
- }
- return storage;
- }
- template<typename TStorage>
- TMaybe<TStorage> StartOfQuarter(TStorage storage, const IValueBuilder& valueBuilder) {
- storage.Month = (storage.Month - 1) / 3 * 3 + 1;
- storage.Day = 1;
- SetStartOfDay(storage);
- if (!storage.Validate(valueBuilder.GetDateBuilder())) {
- return {};
- }
- return storage;
- }
- template<typename TStorage>
- TMaybe<TStorage> EndOfQuarter(TStorage storage, const IValueBuilder& valueBuilder) {
- storage.Month = ((storage.Month - 1) / 3 + 1) * 3;
- storage.Day = NMiniKQL::GetMonthLength(storage.Month, NMiniKQL::IsLeapYear(storage.Year));
- SetEndOfDay(storage);
- if (!storage.Validate(valueBuilder.GetDateBuilder())) {
- return {};
- }
- return storage;
- }
- template<typename TStorage>
- TMaybe<TStorage> StartOfMonth(TStorage storage, const IValueBuilder& valueBuilder) {
- storage.Day = 1;
- SetStartOfDay(storage);
- if (!storage.Validate(valueBuilder.GetDateBuilder())) {
- return {};
- }
- return storage;
- }
- template<typename TStorage>
- TMaybe<TStorage> EndOfMonth(TStorage storage, const IValueBuilder& valueBuilder) {
- storage.Day = NMiniKQL::GetMonthLength(storage.Month, NMiniKQL::IsLeapYear(storage.Year));
- SetEndOfDay(storage);
- if (!storage.Validate(valueBuilder.GetDateBuilder())) {
- return {};
- }
- return storage;
- }
- template<typename TStorage>
- TMaybe<TStorage> StartOfWeek(TStorage storage, const IValueBuilder& valueBuilder) {
- const ui32 shift = 86400u * (storage.DayOfWeek - 1u);
- if constexpr (std::is_same_v<TStorage, TTMStorage>) {
- if (shift > storage.ToDatetime(valueBuilder.GetDateBuilder())) {
- return {};
- }
- storage.FromDatetime(valueBuilder.GetDateBuilder(), storage.ToDatetime(valueBuilder.GetDateBuilder()) - shift, storage.TimezoneId);
- } else {
- if (shift > storage.ToDatetime64(valueBuilder.GetDateBuilder())) {
- return {};
- }
- storage.FromDatetime64(valueBuilder.GetDateBuilder(), storage.ToDatetime64(valueBuilder.GetDateBuilder()) - shift, storage.TimezoneId);
- }
- SetStartOfDay(storage);
- if (!storage.Validate(valueBuilder.GetDateBuilder())) {
- return {};
- }
- return storage;
- }
- template<typename TStorage>
- TMaybe<TStorage> EndOfWeek(TStorage storage, const IValueBuilder& valueBuilder) {
- const ui32 shift = 86400u * (7u - storage.DayOfWeek);
- if constexpr (std::is_same_v<TStorage, TTMStorage>) {
- auto dt = storage.ToDatetime(valueBuilder.GetDateBuilder());
- if (NUdf::MAX_DATETIME - shift <= dt) {
- return {};
- }
- storage.FromDatetime(valueBuilder.GetDateBuilder(), dt + shift, storage.TimezoneId);
- } else {
- auto dt = storage.ToDatetime64(valueBuilder.GetDateBuilder());
- if (NUdf::MAX_DATETIME64 - shift <= dt) {
- return {};
- }
- storage.FromDatetime64(valueBuilder.GetDateBuilder(), dt + shift, storage.TimezoneId);
- }
- SetEndOfDay(storage);
- if (!storage.Validate(valueBuilder.GetDateBuilder())) {
- return {};
- }
- return storage;
- }
- template<typename TStorage>
- TMaybe<TStorage> StartOfDay(TStorage storage, const IValueBuilder& valueBuilder) {
- SetStartOfDay(storage);
- auto& builder = valueBuilder.GetDateBuilder();
- if (!storage.Validate(builder)) {
- return {};
- }
- return storage;
- }
- template<typename TStorage>
- TMaybe<TStorage> EndOfDay(TStorage storage, const IValueBuilder& valueBuilder) {
- SetEndOfDay(storage);
- auto& builder = valueBuilder.GetDateBuilder();
- if (!storage.Validate(builder)) {
- return {};
- }
- return storage;
- }
- TMaybe<TTMStorage> StartOf(TTMStorage storage, ui64 interval, const IValueBuilder& valueBuilder) {
- if (interval >= 86400000000ull) {
- // treat as StartOfDay
- SetStartOfDay(storage);
- } else {
- auto current = storage.ToTimeOfDay();
- auto rounded = current / interval * interval;
- storage.FromTimeOfDay(rounded);
- }
- auto& builder = valueBuilder.GetDateBuilder();
- if (!storage.Validate(builder)) {
- return {};
- }
- return storage;
- }
- TMaybe<TTMStorage> EndOf(TTMStorage storage, ui64 interval, const IValueBuilder& valueBuilder) {
- if (interval >= 86400000000ull) {
- // treat as EndOfDay
- SetEndOfDay(storage);
- } else {
- auto current = storage.ToTimeOfDay();
- auto rounded = current / interval * interval + interval - 1;
- storage.FromTimeOfDay(rounded);
- }
- auto& builder = valueBuilder.GetDateBuilder();
- if (!storage.Validate(builder)) {
- return {};
- }
- return storage;
- }
- template<bool UseEnd>
- struct TStartEndOfBinaryKernelExec : TBinaryKernelExec<TStartEndOfBinaryKernelExec<UseEnd>> {
- template<typename TSink>
- static void Process(const IValueBuilder* valueBuilder, TBlockItem arg1, TBlockItem arg2, const TSink& sink) {
- auto& storage = Reference(arg1);
- ui64 interval = std::abs(arg2.Get<i64>());
- if (interval == 0) {
- sink(arg1);
- return;
- }
- if (auto res = (UseEnd ? EndOf : StartOf)(storage, interval, *valueBuilder)) {
- storage = res.GetRef();
- sink(arg1);
- } else {
- sink(TBlockItem{});
- }
- }
- };
- BEGIN_SIMPLE_STRICT_ARROW_UDF(TStartOf, TOptional<TResource<TMResourceName>>(TAutoMap<TResource<TMResourceName>>, TAutoMap<TInterval>)) {
- auto result = args[0];
- ui64 interval = std::abs(args[1].Get<i64>());
- if (interval == 0) {
- return result;
- }
- if (auto res = StartOf(Reference(result), interval, *valueBuilder)) {
- Reference(result) = res.GetRef();
- return result;
- }
- return TUnboxedValuePod{};
- }
- END_SIMPLE_ARROW_UDF(TStartOf, TStartEndOfBinaryKernelExec<false>::Do);
- BEGIN_SIMPLE_STRICT_ARROW_UDF(TEndOf, TOptional<TResource<TMResourceName>>(TAutoMap<TResource<TMResourceName>>, TAutoMap<TInterval>)) {
- auto result = args[0];
- ui64 interval = std::abs(args[1].Get<i64>());
- if (interval == 0) {
- return result;
- }
- if (auto res = EndOf(Reference(result), interval, *valueBuilder)) {
- Reference(result) = res.GetRef();
- return result;
- }
- return TUnboxedValuePod{};
- }
- END_SIMPLE_ARROW_UDF(TEndOf, TStartEndOfBinaryKernelExec<true>::Do);
- struct TTimeOfDayKernelExec : TUnaryKernelExec<TTimeOfDayKernelExec, TReaderTraits::TResource<false>, TFixedSizeArrayBuilder<TDataType<TInterval>::TLayout, false>> {
- template<typename TSink>
- static void Process(const IValueBuilder* valueBuilder, TBlockItem item, const TSink& sink) {
- Y_UNUSED(valueBuilder);
- auto& storage = Reference(item);
- sink(TBlockItem{(TDataType<TInterval>::TLayout)storage.ToTimeOfDay()});
- }
- };
- const auto timeOfDayKernelExecDo = TTimeOfDayKernelExec::Do;
- BEGIN_SIMPLE_STRICT_ARROW_UDF(TTimeOfDay, TInterval(TAutoMap<TResource<TMResourceName>>)) {
- Y_UNUSED(valueBuilder);
- auto& storage = Reference(args[0]);
- return TUnboxedValuePod((i64)storage.ToTimeOfDay());
- }
- END_SIMPLE_ARROW_UDF(TTimeOfDay, timeOfDayKernelExecDo);
- // Add ...
- template<auto Core>
- struct TAddKernelExec : TBinaryKernelExec<TAddKernelExec<Core>> {
- template<typename TSink>
- static void Process(const IValueBuilder* valueBuilder, TBlockItem date, TBlockItem arg, const TSink& sink) {
- sink(Core(date, arg.Get<i32>(), valueBuilder->GetDateBuilder()));
- }
- };
- template<const char* TUdfName, auto Shifter, auto WShifter>
- class TShift : public TBoxedValue {
- public:
- typedef bool TTypeAwareMarker;
- static const TStringRef& Name() {
- static auto name = TStringRef(TUdfName, std::strlen(TUdfName));
- return name;
- }
- static bool DeclareSignature(
- const TStringRef& name,
- TType* userType,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly)
- {
- if (Name() != name) {
- return false;
- }
- if (!userType) {
- builder.SetError("User type is missing");
- return true;
- }
- builder.UserType(userType);
- const auto typeInfoHelper = builder.TypeInfoHelper();
- TTupleTypeInspector tuple(*typeInfoHelper, userType);
- Y_ENSURE(tuple, "Tuple with args and options tuples expected");
- Y_ENSURE(tuple.GetElementsCount() > 0,
- "Tuple has to contain positional arguments");
- TTupleTypeInspector argsTuple(*typeInfoHelper, tuple.GetElementType(0));
- Y_ENSURE(argsTuple, "Tuple with args expected");
- if (argsTuple.GetElementsCount() != 2) {
- builder.SetError("Only two arguments expected");
- return true;
- }
- auto argType = argsTuple.GetElementType(0);
- if (const auto optType = TOptionalTypeInspector(*typeInfoHelper, argType)) {
- argType = optType.GetItemType();
- }
- TResourceTypeInspector resource(*typeInfoHelper, argType);
- if (!resource) {
- TDataTypeInspector data(*typeInfoHelper, argType);
- if (!data) {
- SetInvalidTypeError(builder, typeInfoHelper, argType);
- return true;
- }
- const auto features = NUdf::GetDataTypeInfo(NUdf::GetDataSlot(data.GetTypeId())).Features;
- if (features & NUdf::BigDateType) {
- BuildSignature<TM64ResourceName, WShifter>(builder, typesOnly);
- return true;
- }
- if (features & (NUdf::DateType | NUdf::TzDateType)) {
- BuildSignature<TMResourceName, Shifter>(builder, typesOnly);
- return true;
- }
- SetInvalidTypeError(builder, typeInfoHelper, argType);
- return true;
- }
- if (resource.GetTag() == TStringRef::Of(TM64ResourceName)) {
- BuildSignature<TM64ResourceName, WShifter>(builder, typesOnly);
- return true;
- }
- if (resource.GetTag() == TStringRef::Of(TMResourceName)) {
- BuildSignature<TMResourceName, Shifter>(builder, typesOnly);
- return true;
- }
- ::TStringBuilder sb;
- sb << "Unexpected Resource tag: got '" << resource.GetTag() << "'";
- builder.SetError(sb);
- return true;
- }
- private:
- template<auto ShiftHanler>
- class TImpl : public TBoxedValue {
- public:
- TUnboxedValue Run(const IValueBuilder* valueBuilder, const TUnboxedValuePod* args) const final {
- return ShiftHanler(args[0], args[1].Get<i32>(), valueBuilder->GetDateBuilder());
- }
- };
- static void SetInvalidTypeError(NUdf::IFunctionTypeInfoBuilder& builder,
- ITypeInfoHelper::TPtr typeInfoHelper, const TType* argType)
- {
- ::TStringBuilder sb;
- sb << "Invalid argument type: got ";
- TTypePrinter(*typeInfoHelper, argType).Out(sb.Out);
- sb << ", but Resource<" << TMResourceName <<"> or Resource<"
- << TM64ResourceName << "> expected";
- builder.SetError(sb);
- }
- template<const char* TResourceName, auto ShiftHandler>
- static void BuildSignature(NUdf::IFunctionTypeInfoBuilder& builder, bool typesOnly) {
- builder.Returns<TOptional<TResource<TResourceName>>>();
- builder.Args()->Add<TAutoMap<TResource<TResourceName>>>().template Add<i32>();
- builder.IsStrict();
- if (!typesOnly) {
- builder.Implementation(new TImpl<ShiftHandler>());
- }
- }
- };
- template<size_t Digits, bool Exacly = true>
- struct PrintNDigits;
- template<bool Exacly>
- struct PrintNDigits<0U, Exacly> {
- static constexpr ui32 Miltiplier = 1U;
- template <typename T>
- static constexpr size_t Do(T, char*) { return 0U; }
- };
- template<size_t Digits, bool Exacly>
- struct PrintNDigits {
- using TNextPrint = PrintNDigits<Digits - 1U, Exacly>;
- static constexpr ui32 Miltiplier = TNextPrint::Miltiplier * 10U;
- template <typename T>
- static constexpr size_t Do(T in, char* out) {
- in %= Miltiplier;
- if (Exacly || in) {
- *out = "0123456789"[in / TNextPrint::Miltiplier];
- return 1U + TNextPrint::Do(in, ++out);
- }
- return 0U;
- }
- };
- // Format
- class TFormat : public TBoxedValue {
- public:
- explicit TFormat(TSourcePosition pos)
- : Pos_(pos)
- {}
- static const TStringRef& Name() {
- static auto name = TStringRef::Of("Format");
- return name;
- }
- static bool DeclareSignature(
- const TStringRef& name,
- TType*,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly)
- {
- if (Name() != name) {
- return false;
- }
- auto resourceType = builder.Resource(TMResourceName);
- auto stringType = builder.SimpleType<char*>();
- auto boolType = builder.SimpleType<bool>();
- auto optionalBoolType = builder.Optional()->Item(boolType).Build();
- auto args = builder.Args();
- args->Add(stringType);
- args->Add(optionalBoolType).Name("AlwaysWriteFractionalSeconds");
- args->Done();
- builder.OptionalArgs(1);
- builder.Returns(
- builder.Callable(1)
- ->Returns(stringType)
- .Arg(resourceType)
- .Flags(ICallablePayload::TArgumentFlags::AutoMap)
- .Build()
- );
- if (!typesOnly) {
- builder.Implementation(new TFormat(builder.GetSourcePosition()));
- }
- return true;
- }
- private:
- using TPrintersList = std::vector<std::function<size_t(char*, const TUnboxedValuePod&, const IDateBuilder&)>>;
- struct TDataPrinter {
- const std::string_view Data;
- size_t operator()(char* out, const TUnboxedValuePod&, const IDateBuilder&) const {
- std::memcpy(out, Data.data(), Data.size());
- return Data.size();
- }
- };
- TUnboxedValue Run(const IValueBuilder*, const TUnboxedValuePod* args) const final try {
- bool alwaysWriteFractionalSeconds = false;
- if (auto val = args[1]) {
- alwaysWriteFractionalSeconds = val.Get<bool>();
- }
- return TUnboxedValuePod(new TImpl(Pos_, args[0], alwaysWriteFractionalSeconds));
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
- }
- class TImpl : public TBoxedValue {
- public:
- TUnboxedValue Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const override
- {
- try {
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- const auto value = args[0];
- auto& builder = valueBuilder->GetDateBuilder();
- auto result = valueBuilder->NewStringNotFilled(ReservedSize_);
- auto pos = result.AsStringRef().Data();
- ui32 size = 0U;
- for (const auto& printer : Printers_) {
- if (const auto plus = printer(pos, value, builder)) {
- size += plus;
- pos += plus;
- }
- }
- if (size < ReservedSize_) {
- result = valueBuilder->SubString(result.Release(), 0U, size);
- }
- return result;
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
- }
- }
- TImpl(TSourcePosition pos, TUnboxedValue format, bool alwaysWriteFractionalSeconds)
- : Pos_(pos)
- , Format_(format)
- {
- const std::string_view formatView(Format_.AsStringRef());
- auto dataStart = formatView.begin();
- size_t dataSize = 0U;
- for (auto ptr = formatView.begin(); formatView.end() != ptr; ++ptr) {
- if (*ptr != '%') {
- ++dataSize;
- continue;
- }
- if (dataSize) {
- Printers_.emplace_back(TDataPrinter{std::string_view(&*dataStart, dataSize)});
- ReservedSize_ += dataSize;
- dataSize = 0U;
- }
- if (formatView.end() == ++ptr) {
- ythrow yexception() << "format string ends with single %%";
- }
- switch (*ptr) {
- case '%': {
- static constexpr size_t size = 1;
- Printers_.emplace_back([](char* out, const TUnboxedValuePod&, const IDateBuilder&) {
- *out = '%';
- return size;
- });
- ReservedSize_ += size;
- break;
- }
- case 'Y': {
- static constexpr size_t size = 4;
- Printers_.emplace_back([](char* out, const TUnboxedValuePod& value, const IDateBuilder&) {
- return PrintNDigits<size>::Do(GetYear(value), out);
- });
- ReservedSize_ += size;
- break;
- }
- case 'm': {
- static constexpr size_t size = 2;
- Printers_.emplace_back([](char* out, const TUnboxedValuePod& value, const IDateBuilder&) {
- return PrintNDigits<size>::Do(GetMonth(value), out);
- });
- ReservedSize_ += size;
- break;
- }
- case 'd': {
- static constexpr size_t size = 2;
- Printers_.emplace_back([](char* out, const TUnboxedValuePod& value, const IDateBuilder&) {
- return PrintNDigits<size>::Do(GetDay(value), out);
- });
- ReservedSize_ += size;
- break;
- }
- case 'H': {
- static constexpr size_t size = 2;
- Printers_.emplace_back([](char* out, const TUnboxedValuePod& value, const IDateBuilder&) {
- return PrintNDigits<size>::Do(GetHour(value), out);
- });
- ReservedSize_ += size;
- break;
- }
- case 'M': {
- static constexpr size_t size = 2;
- Printers_.emplace_back([](char* out, const TUnboxedValuePod& value, const IDateBuilder&) {
- return PrintNDigits<size>::Do(GetMinute(value), out);
- });
- ReservedSize_ += size;
- break;
- }
- case 'S':
- Printers_.emplace_back([alwaysWriteFractionalSeconds](char* out, const TUnboxedValuePod& value, const IDateBuilder&) {
- constexpr size_t size = 2;
- if (const auto microsecond = GetMicrosecond(value); microsecond || alwaysWriteFractionalSeconds) {
- out += PrintNDigits<size>::Do(GetSecond(value), out);
- *out++ = '.';
- constexpr size_t msize = 6;
- auto addSz = alwaysWriteFractionalSeconds ?
- PrintNDigits<msize, true>::Do(microsecond, out) :
- PrintNDigits<msize, false>::Do(microsecond, out);
- return size + 1U + addSz;
- }
- return PrintNDigits<size>::Do(GetSecond(value), out);
- });
- ReservedSize_ += 9;
- break;
- case 'z': {
- static constexpr size_t size = 5;
- Printers_.emplace_back([](char* out, const TUnboxedValuePod& value, const IDateBuilder& builder) {
- auto timezoneId = GetTimezoneId(value);
- if (TTMStorage::IsUniversal(timezoneId)) {
- std::memcpy(out, "+0000", size);
- return size;
- }
- i32 shift;
- if (!builder.GetTimezoneShift(GetYear(value), GetMonth(value), GetDay(value),
- GetHour(value), GetMinute(value), GetSecond(value), timezoneId, shift))
- {
- std::memcpy(out, "+0000", size);
- return size;
- }
- *out++ = shift > 0 ? '+' : '-';
- shift = std::abs(shift);
- out += PrintNDigits<2U>::Do(shift / 60U, out);
- out += PrintNDigits<2U>::Do(shift % 60U, out);
- return size;
- });
- ReservedSize_ += size;
- break;
- }
- case 'Z':
- Printers_.emplace_back([](char* out, const TUnboxedValuePod& value, const IDateBuilder&) {
- const auto timezoneId = GetTimezoneId(value);
- const auto tzName = NUdf::GetTimezones()[timezoneId];
- std::memcpy(out, tzName.data(), std::min(tzName.size(), MAX_TIMEZONE_NAME_LEN));
- return tzName.size();
- });
- ReservedSize_ += MAX_TIMEZONE_NAME_LEN;
- break;
- case 'b': {
- static constexpr size_t size = 3;
- Printers_.emplace_back([](char* out, const TUnboxedValuePod& value, const IDateBuilder&) {
- static constexpr std::string_view mp[] {
- "Jan",
- "Feb",
- "Mar",
- "Apr",
- "May",
- "Jun",
- "Jul",
- "Aug",
- "Sep",
- "Oct",
- "Nov",
- "Dec"
- };
- auto month = GetMonth(value);
- Y_ENSURE(month > 0 && month <= sizeof(mp) / sizeof(mp[0]), "Invalid month value");
- std::memcpy(out, mp[month - 1].data(), size);
- return size;
- });
- ReservedSize_ += size;
- break;
- }
- case 'B': {
- Printers_.emplace_back([](char* out, const TUnboxedValuePod& value, const IDateBuilder&) {
- static constexpr std::string_view mp[] {
- "January",
- "February",
- "March",
- "April",
- "May",
- "June",
- "July",
- "August",
- "September",
- "October",
- "November",
- "December"
- };
- auto month = GetMonth(value);
- Y_ENSURE(month > 0 && month <= sizeof(mp) / sizeof(mp[0]), "Invalid month value");
- const std::string_view monthFullName = mp[month - 1];
- std::memcpy(out, monthFullName.data(), monthFullName.size());
- return monthFullName.size();
- });
- ReservedSize_ += 9U; // MAX_MONTH_FULL_NAME_LEN
- break;
- }
- default:
- ythrow yexception() << "invalid format character: " << *ptr;
- }
- dataStart = ptr + 1U;
- }
- if (dataSize) {
- Printers_.emplace_back(TDataPrinter{std::string_view(dataStart, dataSize)});
- ReservedSize_ += dataSize;
- }
- }
- private:
- const TSourcePosition Pos_;
- TUnboxedValue Format_;
- TPrintersList Printers_{};
- size_t ReservedSize_ = 0;
- };
- const TSourcePosition Pos_;
- };
- template<size_t Digits>
- struct ParseExaclyNDigits;
- template<>
- struct ParseExaclyNDigits<0U> {
- template <typename T>
- static constexpr bool Do(std::string_view::const_iterator&, T&) {
- return true;
- }
- };
- template<size_t Digits>
- struct ParseExaclyNDigits {
- template <typename T>
- static constexpr bool Do(std::string_view::const_iterator& it, T& out) {
- const auto d = *it;
- if (!std::isdigit(d)) {
- return false;
- }
- out *= 10U;
- out += d - '0';
- return ParseExaclyNDigits<Digits - 1U>::Do(++it, out);
- }
- };
- // Parse
- class TParse : public TBoxedValue {
- public:
- class TFactory : public TBoxedValue {
- public:
- explicit TFactory(TSourcePosition pos)
- : Pos_(pos)
- {}
- private:
- TUnboxedValue Run(const IValueBuilder*, const TUnboxedValuePod* args) const final try {
- return TUnboxedValuePod(new TParse(args[0], Pos_));
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
- }
- const TSourcePosition Pos_;
- };
- static const TStringRef& Name() {
- static auto name = TStringRef::Of("Parse");
- return name;
- }
- static bool DeclareSignature(
- const TStringRef& name,
- TType*,
- IFunctionTypeInfoBuilder& builder,
- bool typesOnly)
- {
- if (Name() != name) {
- return false;
- }
- auto resourceType = builder.Resource(TMResourceName);
- auto optionalResourceType = builder.Optional()->Item(resourceType).Build();
- builder.Args()->Add<char*>().Flags(ICallablePayload::TArgumentFlags::AutoMap)
- .Add(builder.Optional()->Item<ui16>())
- .Done()
- .OptionalArgs(1);
- builder.RunConfig<char*>().Returns(optionalResourceType);
- if (!typesOnly) {
- builder.Implementation(new TParse::TFactory(builder.GetSourcePosition()));
- }
- return true;
- }
- private:
- const TSourcePosition Pos_;
- const TUnboxedValue Format_;
- std::vector<std::function<bool(std::string_view::const_iterator& it, size_t, TUnboxedValuePod&, const IDateBuilder&)>> Scanners_;
- struct TDataScanner {
- const std::string_view Data_;
- bool operator()(std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod&, const IDateBuilder&) const {
- if (limit < Data_.size() || !std::equal(Data_.begin(), Data_.end(), it)) {
- return false;
- }
- std::advance(it, Data_.size());
- return true;
- }
- };
- TUnboxedValue Run(
- const IValueBuilder* valueBuilder,
- const TUnboxedValuePod* args) const override
- {
- try {
- EMPTY_RESULT_ON_EMPTY_ARG(0);
- const std::string_view buffer = args[0].AsStringRef();
- TUnboxedValuePod result(0);
- auto& storage = Reference(result);
- storage.MakeDefault();
- auto& builder = valueBuilder->GetDateBuilder();
- auto it = buffer.begin();
- for (const auto& scanner : Scanners_) {
- if (!scanner(it, std::distance(it, buffer.end()), result, builder)) {
- return TUnboxedValuePod();
- }
- }
- if (buffer.end() != it || !storage.Validate(builder)) {
- return TUnboxedValuePod();
- }
- return result;
- } catch (const std::exception& e) {
- UdfTerminate((TStringBuilder() << Pos_ << " " << e.what()).data());
- }
- }
- TParse(const TUnboxedValuePod& runConfig, TSourcePosition pos)
- : Pos_(pos)
- , Format_(runConfig)
- {
- const std::string_view formatView(Format_.AsStringRef());
- auto dataStart = formatView.begin();
- size_t dataSize = 0U;
- for (auto ptr = formatView.begin(); formatView.end() != ptr; ++ptr) {
- if (*ptr != '%') {
- ++dataSize;
- continue;
- }
- if (dataSize) {
- Scanners_.emplace_back(TDataScanner{std::string_view(&*dataStart, dataSize)});
- dataSize = 0;
- }
- if (++ptr == formatView.end()) {
- ythrow yexception() << "format string ends with single %%";
- }
- switch (*ptr) {
- case '%':
- Scanners_.emplace_back([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod&, const IDateBuilder&) {
- return limit > 0U && *it++ == '%';
- });
- break;
- case 'Y': {
- static constexpr size_t size = 4;
- Scanners_.emplace_back([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder&) {
- ui32 year = 0U;
- if (limit < size || !ParseExaclyNDigits<size>::Do(it, year) || !ValidateYear(year)) {
- return false;
- }
- SetYear(result, year);
- return true;
- });
- break;
- }
- case 'm': {
- static constexpr size_t size = 2;
- Scanners_.emplace_back([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder&) {
- ui32 month = 0U;
- if (limit < size || !ParseExaclyNDigits<size>::Do(it, month) || !ValidateMonth(month)) {
- return false;
- }
- SetMonth(result, month);
- return true;
- });
- break;
- }
- case 'd': {
- static constexpr size_t size = 2;
- Scanners_.emplace_back([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder&) {
- ui32 day = 0U;
- if (limit < size || !ParseExaclyNDigits<size>::Do(it, day) || !ValidateDay(day)) {
- return false;
- }
- SetDay(result, day);
- return true;
- });
- break;
- }
- case 'H': {
- static constexpr size_t size = 2;
- Scanners_.emplace_back([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder&) {
- ui32 hour = 0U;
- if (limit < size || !ParseExaclyNDigits<size>::Do(it, hour) || !ValidateHour(hour)) {
- return false;
- }
- SetHour(result, hour);
- return true;
- });
- break;
- }
- case 'M': {
- static constexpr size_t size = 2;
- Scanners_.emplace_back([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder&) {
- ui32 minute = 0U;
- if (limit < size || !ParseExaclyNDigits<size>::Do(it, minute) || !ValidateMinute(minute)) {
- return false;
- }
- SetMinute(result, minute);
- return true;
- });
- break;
- }
- case 'S': {
- static constexpr size_t size = 2;
- Scanners_.emplace_back([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder&) {
- ui32 second = 0U;
- if (limit < size || !ParseExaclyNDigits<size>::Do(it, second) || !ValidateSecond(second)) {
- return false;
- }
- SetSecond(result, second);
- limit -= size;
- if (!limit || *it != '.') {
- return true;
- }
- ++it;
- --limit;
- ui32 usec = 0U;
- size_t digits = 6U;
- for (; limit; --limit) {
- const auto c = *it;
- if (!digits || !std::isdigit(c)) {
- break;
- }
- usec *= 10U;
- usec += c - '0';
- ++it;
- --digits;
- }
- for (; !digits && limit && std::isdigit(*it); --limit, ++it);
- while (digits--) {
- usec *= 10U;
- }
- SetMicrosecond(result, usec);
- return true;
- });
- break;
- }
- case 'Z':
- Scanners_.emplace_back([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder& builder) {
- const auto start = it;
- while (limit > 0 && (std::isalnum(*it) || *it == '/' || *it == '_' || *it == '-' || *it == '+')) {
- ++it;
- --limit;
- }
- const auto size = std::distance(start, it);
- ui32 timezoneId;
- if (!builder.FindTimezoneId(TStringRef(&*start, size), timezoneId)) {
- return false;
- }
- SetTimezoneId(result, timezoneId);
- return true;
- });
- break;
- case 'b': {
- static constexpr size_t size = 3;
- Scanners_.emplace_back([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder&) {
- const auto start = it;
- size_t cnt = 0U;
- while (limit > 0 && cnt < size && std::isalpha(*it)) {
- ++it;
- ++cnt;
- --limit;
- }
- const std::string_view monthName{start, cnt};
- ui8 month = 0U;
- if (cnt < size || !ValidateMonthShortName(monthName, month)) {
- return false;
- }
- SetMonth(result, month);
- return true;
- });
- break;
- }
- case 'B': {
- Scanners_.emplace_back([](std::string_view::const_iterator& it, size_t limit, TUnboxedValuePod& result, const IDateBuilder&) {
- const auto start = it;
- size_t cnt = 0U;
- while (limit > 0 && std::isalpha(*it)) {
- ++it;
- ++cnt;
- --limit;
- }
- const std::string_view monthName{start, cnt};
- ui8 month = 0U;
- if (!ValidateMonthFullName(monthName, month)) {
- return false;
- }
- SetMonth(result, month);
- return true;
- });
- break;
- }
- default:
- ythrow yexception() << "invalid format character: " << *ptr;
- }
- dataStart = ptr + 1U;
- }
- if (dataSize) {
- Scanners_.emplace_back(TDataScanner{std::string_view(&*dataStart, dataSize)});
- }
- }
- };
- #define PARSE_SPECIFIC_FORMAT(format) \
- SIMPLE_STRICT_UDF(TParse##format, TOptional<TResource<TMResourceName>>(TAutoMap<char*>)) { \
- auto str = args[0].AsStringRef(); \
- TInstant instant; \
- if (!TInstant::TryParse##format(TStringBuf(str.Data(), str.Size()), instant) || instant.Seconds() >= NUdf::MAX_DATETIME) { \
- return TUnboxedValuePod(); \
- } \
- auto& builder = valueBuilder->GetDateBuilder(); \
- TUnboxedValuePod result(0); \
- auto& storage = Reference(result); \
- storage.FromTimestamp(builder, instant.MicroSeconds()); \
- return result; \
- }
- PARSE_SPECIFIC_FORMAT(Rfc822);
- PARSE_SPECIFIC_FORMAT(Iso8601);
- PARSE_SPECIFIC_FORMAT(Http);
- PARSE_SPECIFIC_FORMAT(X509);
- SIMPLE_MODULE(TDateTime2Module,
- TUserDataTypeFuncFactory<true, true, SplitUDF, TSplit,
- TDate,
- TDatetime,
- TTimestamp,
- TTzDate,
- TTzDatetime,
- TTzTimestamp,
- TDate32,
- TDatetime64,
- TTimestamp64>,
- TMakeDate,
- TMakeDatetime,
- TMakeTimestamp,
- TMakeTzDate,
- TMakeTzDatetime,
- TMakeTzTimestamp,
- TConvert,
- TMakeDate32,
- TMakeDatetime64,
- TMakeTimestamp64,
- TGetDateComponent<GetYearUDF, ui16, GetYear<TMResourceName>, i32, GetYear<TM64ResourceName>>,
- TGetDateComponent<GetDayOfYearUDF, ui16, GetDayOfYear<TMResourceName>, ui16, GetDayOfYear<TM64ResourceName>>,
- TGetDateComponent<GetMonthUDF, ui8, GetMonth<TMResourceName>, ui8, GetMonth<TM64ResourceName>>,
- TGetDateComponentName<GetMonthNameUDF, GetMonthName<TMResourceName>, GetMonthName<TM64ResourceName>>,
- TGetDateComponent<GetWeekOfYearUDF, ui8, GetWeekOfYear<TMResourceName>, ui8, GetWeekOfYear<TM64ResourceName>>,
- TGetDateComponent<GetWeekOfYearIso8601UDF, ui8, GetWeekOfYearIso8601<TMResourceName>, ui8, GetWeekOfYearIso8601<TM64ResourceName>>,
- TGetDateComponent<GetDayOfMonthUDF, ui8, GetDay<TMResourceName>, ui8, GetDay<TM64ResourceName>>,
- TGetDateComponent<GetDayOfWeekUDF, ui8, GetDayOfWeek<TMResourceName>, ui8, GetDayOfWeek<TM64ResourceName>>,
- TGetDateComponentName<GetDayOfWeekNameUDF, GetDayOfWeekName<TMResourceName>, GetDayOfWeekName<TM64ResourceName>>,
- TGetTimeComponent<GetHourUDF, ui8, GetHour<TMResourceName>, GetHour<TM64ResourceName>, 1u, 3600u, 24u, false>,
- TGetTimeComponent<GetMinuteUDF, ui8, GetMinute<TMResourceName>, GetMinute<TM64ResourceName>, 1u, 60u, 60u, false>,
- TGetTimeComponent<GetSecondUDF, ui8, GetSecond<TMResourceName>, GetSecond<TM64ResourceName>, 1u, 1u, 60u, false>,
- TGetTimeComponent<GetMillisecondOfSecondUDF, ui32, GetMicrosecond<TMResourceName>, GetMicrosecond<TM64ResourceName>, 1000u, 1000u, 1000u, true>,
- TGetTimeComponent<GetMicrosecondOfSecondUDF, ui32, GetMicrosecond<TMResourceName>, GetMicrosecond<TM64ResourceName>, 1u, 1u, 1000000u, true>,
- TGetDateComponent<GetTimezoneIdUDF, ui16, GetTimezoneId<TMResourceName>, ui16, GetTimezoneId<TM64ResourceName>>,
- TGetDateComponentName<GetTimezoneNameUDF, GetTimezoneName<TMResourceName>, GetTimezoneName<TM64ResourceName>>,
- TUpdate,
- TFromSeconds,
- TFromMilliseconds,
- TFromMicroseconds,
- TFromSeconds64,
- TFromMilliseconds64,
- TFromMicroseconds64,
- TIntervalFromDays,
- TIntervalFromHours,
- TIntervalFromMinutes,
- TIntervalFromSeconds,
- TIntervalFromMilliseconds,
- TIntervalFromMicroseconds,
- TInterval64FromDays,
- TInterval64FromHours,
- TInterval64FromMinutes,
- TInterval64FromSeconds,
- TInterval64FromMilliseconds,
- TInterval64FromMicroseconds,
- TToDays,
- TToHours,
- TToMinutes,
- TBoundaryOf<StartOfYearUDF, SimpleDatetimeToDatetimeUdf<TMResourceName, StartOfYear<TTMStorage>>,
- SimpleDatetimeToDatetimeUdf<TM64ResourceName, StartOfYear<TTM64Storage>>>,
- TBoundaryOf<StartOfQuarterUDF, SimpleDatetimeToDatetimeUdf<TMResourceName, StartOfQuarter<TTMStorage>>,
- SimpleDatetimeToDatetimeUdf<TM64ResourceName, StartOfQuarter<TTM64Storage>>>,
- TBoundaryOf<StartOfMonthUDF, SimpleDatetimeToDatetimeUdf<TMResourceName, StartOfMonth<TTMStorage>>,
- SimpleDatetimeToDatetimeUdf<TM64ResourceName, StartOfMonth<TTM64Storage>>>,
- TBoundaryOf<StartOfWeekUDF, SimpleDatetimeToDatetimeUdf<TMResourceName, StartOfWeek<TTMStorage>>,
- SimpleDatetimeToDatetimeUdf<TM64ResourceName, StartOfWeek<TTM64Storage>>>,
- TBoundaryOf<StartOfDayUDF, SimpleDatetimeToDatetimeUdf<TMResourceName, StartOfDay<TTMStorage>>,
- SimpleDatetimeToDatetimeUdf<TM64ResourceName, StartOfDay<TTM64Storage>>>,
- TStartOf,
- TTimeOfDay,
- TShift<ShiftYearsUDF, DoAddYears<TMResourceName>, DoAddYears<TM64ResourceName>>,
- TShift<ShiftQuartersUDF, DoAddQuarters<TMResourceName>, DoAddQuarters<TM64ResourceName>>,
- TShift<ShiftMonthsUDF, DoAddMonths<TMResourceName>, DoAddMonths<TM64ResourceName>>,
- TBoundaryOf<EndOfYearUDF, SimpleDatetimeToDatetimeUdf<TMResourceName, EndOfYear<TTMStorage>>,
- SimpleDatetimeToDatetimeUdf<TM64ResourceName, EndOfYear<TTM64Storage>>>,
- TBoundaryOf<EndOfQuarterUDF, SimpleDatetimeToDatetimeUdf<TMResourceName, EndOfQuarter<TTMStorage>>,
- SimpleDatetimeToDatetimeUdf<TM64ResourceName, EndOfQuarter<TTM64Storage>>>,
- TBoundaryOf<EndOfMonthUDF, SimpleDatetimeToDatetimeUdf<TMResourceName, EndOfMonth<TTMStorage>>,
- SimpleDatetimeToDatetimeUdf<TM64ResourceName, EndOfMonth<TTM64Storage>>>,
- TBoundaryOf<EndOfWeekUDF, SimpleDatetimeToDatetimeUdf<TMResourceName, EndOfWeek<TTMStorage>>,
- SimpleDatetimeToDatetimeUdf<TM64ResourceName, EndOfWeek<TTM64Storage>>>,
- TBoundaryOf<EndOfDayUDF, SimpleDatetimeToDatetimeUdf<TMResourceName, EndOfDay<TTMStorage>>,
- SimpleDatetimeToDatetimeUdf<TM64ResourceName, EndOfDay<TTM64Storage>>>,
- TEndOf,
- TToUnits<ToSecondsUDF, ui32, 1>,
- TToUnits<ToMillisecondsUDF, ui64, 1000>,
- TToUnits<ToMicrosecondsUDF, ui64, 1000000>,
- TFormat,
- TParse,
- TParseRfc822,
- TParseIso8601,
- TParseHttp,
- TParseX509
- )
- }
- REGISTER_MODULES(TDateTime2Module)
|