blob: 7ae07cccc7520ba5195a28bec89791c664185a71 [file] [log] [blame]
/* ----------------------------------------------------------------------- *//**
*
* @file SystemInformation.hpp
*
*//* ----------------------------------------------------------------------- */
#ifndef MADLIB_POSTGRES_SYSTEMINFORMATION_PROTO_HPP
#define MADLIB_POSTGRES_SYSTEMINFORMATION_PROTO_HPP
#include "UDF_proto.hpp" // We need UDF::Pointer
namespace madlib {
namespace dbconnector {
namespace postgres {
/**
* @brief Cached information about PostgreSQL types
*
* For explanations, see struct FormData_pg_type defined in pg_type.h
* and struct TypeCacheEntry defined in typcache.h.
*/
struct TypeInformation {
/**
* OID and hash key. Must be the first element.
*/
Oid oid;
/**
* Type name
*/
char name[NAMEDATALEN];
/**
* For a fixed-size type, typlen is the number of bytes PostgreSQL uses to
* represent a value of this type, e.g., 4 for an int4. But for a
* variable-length type, typlen is negative. -1 indicates a "varlena" type
* (one that has a length word), -2 indicates a null-terminated C string.
*/
int16_t len;
/**
* typbyval determines whether internal Postgres routines pass a value of
* this type by value or by reference.
*/
bool byval;
/**
* pg_type.h defines the following types:
* <tt>TYPTYPE_{BASE|COMPOSITE|DOMAIN|ENUM|PSEUDO}</tt>
*/
char type;
/**
* Tuple descriptor if it's a composite type (row type). NULL if not
* composite. This is not a reference-counted TupleDesc and we rely
* on the PostgreSQL garbage collection for cleanup.
*/
TupleDesc tupdesc;
TupleDesc getTupleDesc(int32_t inTypMod = -1);
bool isCompositeType();
const char* getName();
bool isByValue();
int16_t getLen();
char getType();
};
/**
* @brief Cached information about PostgreSQL functions
*
* For explanations, see struct FmgrInfo in fmgr.h,
* struct FuncCallContext in funcapi.h, enum TypeFuncClass in funcapi.h,
* and struct FormData_pg_proc in pg_proc.h.
*/
struct FunctionInformation {
/**
* OID and hash key. Must be the first element.
*/
Oid oid;
/**
* Function pointer to C++ function. If this is non-null, the function
* is known to be implemented on top of the C++ abstraction layer. NULL
* if not or unknown. If non-NULL, we this function pointer will be
* called directly, thus circumventing any detour through the backend.
*/
UDF::Pointer cxx_func;
/**
* Holds system-catalog information that must be looked up before a
* function can be called through fmgr. We store it here, because the
* information can be reused for multiple function calls.
* An uninitialized flinfo is indicated by <tt>flinfo.fn_oid</tt> not
* being equal to \c oid.
*
* FIXME: Currently, no expression parse tree is stored. In fact, there
* is none, and we would have to artificially generate a default
* expression parse tree. This implies that function that are called
* from C++ functions currently do not support the following features:
* - Polymorphism
* - Anonymous return tuples
*/
FmgrInfo flinfo;
/**
* funcapi.h defines the following classes:
* <tt>TYPEFUNC_{SCALAR|COMPOSITE|RECORD|OTHER}</tt>
*/
TypeFuncClass funcclass;
/**
* Number of input arguments. Note that short is the data type used in
* <tt>struct FunctionCallInfoData</tt>.
*/
uint16_t nargs;
/**
* Array (of length nargs) containing the argument type IDs (excludes
* OUT parameters).
*/
Oid *argtypes;
/**
* True if we the function may have different return types.
* False if we the function will always have the same return type.
*/
bool polymorphic;
/**
* True if the function always returns null whenever any of its
* arguments are null. If this parameter is specified, the function is
* not executed when there are null arguments.
*/
bool isstrict;
/**
* True if function is to be executed with the privileges of the user
* that created it. The attribute is called SECURITY DEFINER in
* PostgreSQL.
*/
bool secdef;
/**
* OID of result type
*/
Oid rettype;
/**
* If rettype == RECORDOID but the result type is composite (but not
* polymorphic), then this will contain a tuple descriptor. NULL
* otherwise. This is not a reference-counted TupleDesc and we rely
* on the PostgreSQL garbage collection for cleanup.
*/
TupleDesc tupdesc;
/**
* Backpointer to SystemInformation
*/
SystemInformation* mSysInfo;
Oid getArgumentType(uint16_t inArgID, FmgrInfo* inFmgrInfo = NULL);
Oid getReturnType(FunctionCallInfo fcinfo);
TupleDesc getReturnTupleDesc(FunctionCallInfo fcinfo);
FmgrInfo* getFuncMgrInfo();
const char* getFullName();
};
/**
* @brief Cached information about the PostgreSQL system catalog
*
* In order to guarantee type-safety through reflection/type-introspection, the
* C++ AL has to call many PostgreSQL functions that are tagged as expensive due
* to lookups in the type cache or even in the system catalog. We therefore wrap
* all catalog lookups in this class and store the results in our own cache.
* There is one cache per entry point into the C++ AL, i.e., one per function
* that is called from the backend. If a UDF based on this AL calls another such
* UDF, the same cache is reused.
* Each cache is stored in the \c fn_extra field of struct \c FmgrInfo (or in
* the \c user_fctx field of struct \c FuncCallContext). As such, the cache only
* lives till the end of the current query (see
* <http://www.postgresql.org/docs/current/static/plhandler.html>).
*
* @note
* In order to not leave defined C++ behavior, this must be a plain-old data
* (POD) for the following reason: We store a pointer to our cached
* information in the fn_extra field of struct FmgrInfo (or in
* the user_fctx field of struct FuncCallContext). We cannot do any
* cleanup but instead rely on the PostgreSQL garbage collector.
*/
struct SystemInformation {
/**
* OID of first C++ AL function in the current execution stack.
*/
Oid entryFuncOID;
/**
* The memory context used for the hash tables.
*/
MemoryContext cacheContext;
/**
* Collation for function(s) to use. This will be set to fncollation
* of struct FunctionCallInfoData if the entry-function call (i.e., the
* first C++ AL function call in the current execution stack).
* Note: Collation support has been added to PostgreSQL with commit
* d64713df by Tom Lane <tgl@sss.pgh.pa.us>
* on Tue Apr 12 2011 23:19:24 UTC. First release: PG9.1. For version, prior
* to this, collationOID will be InvalidOid.
*/
Oid collationOID;
/**
* Hash table containing information about all accessed types
*/
HTAB *types;
/**
* Hash table containing information about all accessed functions
* (starting from the function called by the backend).
*/
HTAB *functions;
/**
* As we will put the SystemInformation instance to the pointer
* static_cast<FuncCallContext*>(inFmgrInfo->fn_extra)->user_fctx
* (retset == 1) or inFmgrInfo->fn_extra (retset == -1), we provide this
* pointer for the users to put their own context to this pointer.
*/
void *user_fctx;
static SystemInformation* get(FunctionCallInfo fcinfo);
TypeInformation* typeInformation(Oid inTypeID);
FunctionInformation* functionInformation(Oid inFuncID);
};
} // namespace postgres
} // namespace dbconnector
} // namespace madlib
#endif // defined(MADLIB_POSTGRES_SYSTEMINFORMATION_PROTO_HPP)