#pragma once #include #include #include #include #include #include namespace NKikimr { namespace NMiniKQL { using TFunctionPtr = NUdf::TUnboxedValuePod (*)(const NUdf::TUnboxedValuePod* args); struct TFunctionParamMetadata { enum EFlags : ui16 { FlagIsNullable = 0x01, }; TFunctionParamMetadata() = default; TFunctionParamMetadata(NUdf::TDataTypeId schemeType, ui32 flags) : SchemeType(schemeType) , Flags(flags) {} bool IsNullable() const { return Flags & FlagIsNullable; } NUdf::TDataTypeId SchemeType = 0; ui16 Flags = 0; }; struct TFunctionDescriptor { TFunctionDescriptor() = default; TFunctionDescriptor(const TFunctionParamMetadata* resultAndArgs, TFunctionPtr function, void* generator = nullptr) : ResultAndArgs(resultAndArgs) , Function(function) , Generator(generator) {} const TFunctionParamMetadata* ResultAndArgs = nullptr; // ends with SchemeType zero TFunctionPtr Function = nullptr; void *Generator = nullptr; }; using TFunctionParamMetadataList = std::vector; using TArgType = std::pair; // type with optional flag using TDescriptionList = std::vector; using TFunctionsMap = std::unordered_map; class TKernel; class TKernelFamily { public: const arrow::compute::FunctionOptions* FunctionOptions; TKernelFamily(const arrow::compute::FunctionOptions* functionOptions = nullptr) : FunctionOptions(functionOptions) {} virtual ~TKernelFamily() = default; virtual const TKernel* FindKernel(const NUdf::TDataTypeId* argTypes, size_t argTypesCount, NUdf::TDataTypeId returnType) const = 0; virtual TVector GetAllKernels() const = 0; }; class TKernel { public: enum class ENullMode { Default, AlwaysNull, AlwaysNotNull }; const TKernelFamily& Family; const std::vector ArgTypes; const NUdf::TDataTypeId ReturnType; const ENullMode NullMode; TKernel(const TKernelFamily& family, const std::vector& argTypes, NUdf::TDataTypeId returnType, ENullMode nullMode) : Family(family) , ArgTypes(argTypes) , ReturnType(returnType) , NullMode(nullMode) { } virtual const arrow::compute::ScalarKernel& GetArrowKernel() const = 0; virtual std::shared_ptr MakeArrowKernel(const TVector& argTypes, TType* resultType) const = 0; virtual bool IsPolymorphic() const = 0; virtual ~TKernel() = default; }; using TKernelMapKey = std::pair, NUdf::TDataTypeId>; struct TTypeHasher { std::size_t operator()(const TKernelMapKey& s) const noexcept { size_t r = 0; for (const auto& x : s.first) { r = CombineHashes(r, x); } r = CombineHashes(r, s.second); return r; } }; using TKernelMap = std::unordered_map, TTypeHasher>; using TKernelFamilyMap = std::unordered_map>; class TKernelFamilyBase : public TKernelFamily { public: TKernelFamilyBase(const arrow::compute::FunctionOptions* functionOptions = nullptr); const TKernel* FindKernel(const NUdf::TDataTypeId* argTypes, size_t argTypesCount, NUdf::TDataTypeId returnType) const final; TVector GetAllKernels() const final; void Adopt(const std::vector& argTypes, NUdf::TDataTypeId returnType, std::unique_ptr&& kernel); private: TKernelMap KernelMap; }; class IBuiltinFunctionRegistry: public TThrRefBase, private TNonCopyable { public: typedef TIntrusivePtr TPtr; virtual ui64 GetMetadataEtag() const = 0; virtual void PrintInfoTo(IOutputStream& out) const = 0; virtual void Register(const std::string_view& name, const TFunctionDescriptor& description) = 0; virtual bool HasBuiltin(const std::string_view& name) const = 0; virtual void RegisterAll(TFunctionsMap&& functions, TFunctionParamMetadataList&& arguments) = 0; virtual const TFunctionsMap& GetFunctions() const = 0; virtual TFunctionDescriptor GetBuiltin(const std::string_view& name, const std::pair* argTypes, size_t argTypesCount) const = 0; virtual const TKernel* FindKernel(const std::string_view& name, const NUdf::TDataTypeId* argTypes, size_t argTypesCount, NUdf::TDataTypeId returnType) const = 0; virtual void RegisterKernelFamily(const std::string_view& name, std::unique_ptr&& family) = 0; virtual TVector> GetAllKernelFamilies() const = 0; }; } }