blob: 75fce15e83cf6557ae72730f2dc338ecac908f40 [file] [log] [blame]
/* ----------------------------------------------------------------------- *//**
* @file 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 {
template <typename T> AnyType(const T& inValue,
bool inForceLazyConversionToDatum = false);
template <typename T> 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();
* @brief RAII class to temporarily change \c sLazyConversionToDatum
class LazyConversionToDatumOverride {
LazyConversionToDatumOverride(bool inLazyConversionToDatum);
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 {
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<Datum()> mToDatumFn;
Datum mDatum;
FunctionCallInfo fcinfo;
SystemInformation* mSysInfo;
HeapTupleHeader mTupleHeader;
std::vector<AnyType> 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 <tt>AnyType_cast<double>(func())</tt> 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 <tt>func()</tt> passes unchanged.
template <class T>
AnyType_cast(const AnyType& inValue) {
return inValue.getAs<T>();
template <class T>
const T&
AnyType_cast(const T& inValue) {
return inValue;
template <class T>
AnyType_cast(T& inValue) {
return inValue;
} // namespace postgres
} // namespace dbconnector
} // namespace madlib