/* ----------------------------------------------------------------------- *//** * * @file AnyType_proto.hpp * *//* ----------------------------------------------------------------------- */ #ifndef MADLIB_POSTGRES_ANYTYPE_PROTO_HPP #define MADLIB_POSTGRES_ANYTYPE_PROTO_HPP namespace madlib { namespace dbconnector { namespace postgres { struct SystemInformation; /** * @brief Proxy for PostgreSQL objects * * AnyType objects are used by user-defined code to both retrieve and return * values from the backend. * * The content of an AnyType object is specified by mContent. It can be: * - Null * - A scalar value, which is just a PostgreSQL Datum * - A function composite value, which is a virtual composite value consisting * of all function arguments * - A native composite value, which is a PostgreSQL HeapTupleHeader * - A return composite value, which is a vector of AnyType objects */ class AnyType { public: AnyType(); template AnyType(const T& inValue, bool inForceLazyConversionToDatum = false); template T getAs() const; AnyType operator[](uint16_t inID) const; uint16_t numFields() const; bool isNull() const; bool isComposite() const; AnyType& operator<<(const AnyType& inValue); // FIXME: A temporary workaround for UDF to get/set user_fctx, a better // solution is desired which complies with the design principles of DB // abstraction layer. // For some analytic algorithms (e.g. LDA), a stateful function would be // very useful which allows to carry some states accross invocations within // a query. Alternatively, one can achieve similar functionaltiy using a // windowed aggregator, but this may suffer from severe performance // degradation. void * getUserFuncContext(); void setUserFuncContext(void * user_fctx); MemoryContext getCacheMemoryContext(); protected: /** * @brief RAII class to temporarily change \c sLazyConversionToDatum */ class LazyConversionToDatumOverride { public: LazyConversionToDatumOverride(bool inLazyConversionToDatum); ~LazyConversionToDatumOverride(); protected: bool mOriginalValue; }; static bool sLazyConversionToDatum; static bool lazyConversionToDatum(); // UDF and FunctionHandle access getAsDatum(), which is not part of the // public API friend class UDF; friend class FunctionHandle; /** * @brief Type of the value of the current AnyType object */ enum ContentType { Null, Scalar, FunctionComposite, NativeComposite, ReturnComposite }; AnyType(FunctionCallInfo inFnCallInfo); AnyType(SystemInformation* inSysInfo, HeapTupleHeader inTuple, Datum inDatum, Oid inTypeID); AnyType(SystemInformation* inSysInfo, Datum inDatum, Oid inTypeID, bool inIsMutable); void consistencyCheck() const; Datum getAsDatum(FunctionCallInfo inFCInfo, Oid inTargetTypeID = InvalidOid) const; class Placeholder; ContentType mContentType; boost::any mContent; std::function mToDatumFn; Datum mDatum; FunctionCallInfo fcinfo; SystemInformation* mSysInfo; HeapTupleHeader mTupleHeader; std::vector mChildren; Oid mTypeID; const char* mTypeName; bool mIsMutable; }; AnyType Null(); /** * @brief Cast that extract the proper type from AnyType but leaves other types * unaffected * * Sometimes it is desirable to write generic code that works on both an * \c AnyType object as well as a value with a concrete type. For instance, a * \c FunctionHandle always returns an \c AnyType object. In generatic code, * however, a \c FunctionHandle might as well be replaced by just call a * "normal" functor or a C++ function pointer, both of which typically return * concrete types (e.g., double). * * In generic code, we could write AnyType_cast(func()) so that * if the template parameter \c Function is \c AnyType, we have an explicit * conversion to \c double, and if \c Function is just a function pointer, the * return value of func() passes unchanged. */ template inline T AnyType_cast(const AnyType& inValue) { return inValue.getAs(); } template inline const T& AnyType_cast(const T& inValue) { return inValue; } template inline T& AnyType_cast(T& inValue) { return inValue; } } // namespace postgres } // namespace dbconnector } // namespace madlib #endif // defined(MADLIB_POSTGRES_ANYTYPE_PROTO_HPP)