blob: 45d66332a5f353e8f7bfcd2b84c4fa5a17c060b2 [file] [log] [blame]
/* ----------------------------------------------------------------------- *//**
*
* @file Compatibility.hpp
*
*//* ----------------------------------------------------------------------- */
#ifndef MADLIB_POSTGRES_COMPATIBILITY_HPP
#define MADLIB_POSTGRES_COMPATIBILITY_HPP
extern "C" {
#include <access/tupmacs.h>
#include <utils/memutils.h>
#if PG_VERSION_NUM >= 90300
#include <access/htup_details.h>
#endif
}
namespace madlib {
namespace dbconnector {
namespace postgres {
namespace {
// No need to make these function accessible outside of the postgres namespace.
#ifndef FLOAT8ARRAYOID
#define FLOAT8ARRAYOID 1022
#endif
#ifndef INT8ARRAYOID
#define INT8ARRAYOID 1016
#endif
#ifndef PG_GET_COLLATION
// See madlib_InitFunctionCallInfoData()
#define PG_GET_COLLATION() InvalidOid
#endif
#ifndef SearchSysCache1
// See madlib_SearchSysCache1()
#define SearchSysCache1(cacheId, key1) \
SearchSysCache(cacheId, key1, 0, 0, 0)
#endif
/*
* In commit 2d4db3675fa7a2f4831b755bc98242421901042f,
* by Tom Lane <tgl@sss.pgh.pa.us> Wed, 6 Jun 2007 23:00:50 +0000,
* is_array_type was changed to type_is_array
*/
#if defined(is_array_type) && !defined(type_is_array)
#define type_is_array(x) is_array_type(x)
#endif
#if PG_VERSION_NUM < 90000
/**
* The following has existed in PostgresSQL since commit ID
* d5768dce10576c2fb1254c03fb29475d4fac6bb4, by
* Tom Lane <tgl@sss.pgh.pa.us> Mon, 8 Feb 2010 20:39:52 +0000.
*/
/* AggCheckCallContext can return one of the following codes, or 0: */
#define AGG_CONTEXT_AGGREGATE 1 /* regular aggregate */
#define AGG_CONTEXT_WINDOW 2 /* window function */
/**
* @brief Test whether we are currently in an aggregate calling context.
*
* Knowing whether we are in an aggregate calling context is useful, because it
* allows write access to the transition state of the aggregate function.
* At all other time, modifying a pass-by-reference input is strictly forbidden:
* http://developer.postgresql.org/pgdocs/postgres/xaggr.html
*
* This function is essentially a copy of AggCheckCallContext from
* backend/executor/nodeAgg.c, which is part of PostgreSQL >= 9.0.
*/
inline
int
AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext) {
if (fcinfo->context && IsA(fcinfo->context, AggState)) {
if (aggcontext)
*aggcontext = ((AggState *) fcinfo->context)->aggcontext;
return AGG_CONTEXT_AGGREGATE;
}
/* More recent versions of PostgreSQL also have a window aggregate context.
* However, these changes are not contained in the 8.4 branch (or before).
*
* Reference: See changed file src/include/nodes/execnodes.h from
* commit ec4be2ee6827b6bd85e0813c7a8993cfbb0e6fa7 from
* Fri, 12 Feb 2010 17:33:21 +0000 (17:33 +0000)
* by Tom Lane <tgl@sss.pgh.pa.us> */
/* this is just to prevent "uninitialized variable" warnings */
if (aggcontext)
*aggcontext = NULL;
return 0;
}
#endif // PG_VERSION_NUM < 90000
} // namespace
/**
* @brief construct an array of zero values.
* @note the supported types are: int2, int4, int8, float4 and float8
*
*/
static ArrayType* construct_md_array_zero
(
int ndims,
int* dims,
int* lbs,
Oid elmtype,
int elmlen,
bool elmbyval,
char elmalign
){
ArrayType *result;
size_t nbytes;
int32 dataoffset;
int i;
int nelems;
Datum theDatum = Datum(0);
(void) elmbyval;
if (ndims < 0) /* we do allow zero-dimension arrays */
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid number of dimensions: %d", ndims)));
if (ndims > MAXDIM)
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
ndims, MAXDIM)));
/* fast track for empty array */
if (ndims == 0)
return construct_empty_array(elmtype);
nelems = ArrayGetNItems(ndims, dims);
/* compute required space */
nbytes = 0;
switch (elmtype)
{
case INT2OID:
theDatum = Int16GetDatum(1);
break;
case INT4OID:
theDatum = Int32GetDatum(1);
break;
case INT8OID:
theDatum = Int64GetDatum(1);
break;
case FLOAT4OID:
theDatum = Float4GetDatum(1.0);
break;
case FLOAT8OID:
theDatum = Float8GetDatum(1.0);
break;
default:
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("the support types are INT2, INT4, INT8, FLOAT4 and FLOAT8")));
break;
}
for (i = 0; i < nelems; i++)
{
/* make sure data is not toasted */
if (elmlen == -1)
theDatum = PointerGetDatum(PG_DETOAST_DATUM(theDatum));
nbytes = att_addlength_datum(nbytes, elmlen, theDatum);
nbytes = att_align_nominal(nbytes, elmalign);
/* check for overflow of total request */
if (!AllocSizeIsValid(nbytes))
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("array size exceeds the maximum allowed (%d)",
(int) MaxAllocSize)));
}
dataoffset = 0; /* marker for no null bitmap */
nbytes += ARR_OVERHEAD_NONULLS(ndims);
result = (ArrayType *) palloc0(nbytes);
SET_VARSIZE(result, nbytes);
result->ndim = ndims;
result->dataoffset = dataoffset;
result->elemtype = elmtype;
memcpy(ARR_DIMS(result), dims, ndims * sizeof(int));
memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int));
return result;
}
/**
* @brief construct an array of zero values.
* @note the supported types are: int2, int4, int8, float4 and float8
*/
static ArrayType* construct_array_zero
(
int nelems,
Oid elmtype,
int elmlen,
bool elmbyval,
char elmalign
)
{
int dims[1];
int lbs[1];
dims[0] = nelems;
lbs[0] = 1;
return
construct_md_array_zero(
1, dims, lbs, elmtype, elmlen, elmbyval, elmalign);
}
inline ArrayType* madlib_construct_md_array
(
Datum* elems,
bool* nulls,
int ndims,
int* dims,
int* lbs,
Oid elmtype,
int elmlen,
bool elmbyval,
char elmalign
){
return
elems ?
construct_md_array(
elems, nulls, ndims, dims, lbs, elmtype, elmlen, elmbyval,
elmalign) :
construct_md_array_zero(
ndims, dims, lbs, elmtype, elmlen, elmbyval, elmalign);
}
inline ArrayType* madlib_construct_array
(
Datum* elems,
int nelems,
Oid elmtype,
int elmlen,
bool elmbyval,
char elmalign
){
return elems ?
construct_array(elems, nelems, elmtype, elmlen, elmbyval, elmalign) :
construct_array_zero(nelems, elmtype, elmlen, elmbyval, elmalign);
}
} // namespace postgres
} // namespace dbconnector
} // namespace madlib
#endif // defined(MADLIB_POSTGRES_COMPATIBILITY_HPP)