20 #include "utils/fmgroids.h" 38 char **dataptr_p,
bits8 **bitmap_p,
int *bitmask_p);
44 bool *isnull,
bool inarray);
46 bool *isnull,
bool inarray);
48 bool *isnull,
bool inarray);
50 bool *isnull,
bool inarray);
52 bool *isnull,
bool inarray);
54 bool *isnull,
bool inarray);
56 bool *isnull,
bool inarray);
58 int *dims,
int ndim,
int dim,
59 Datum *elems,
bool *nulls,
int *currelem);
102 result = arg->
func(arg, val);
122 return arg->
func(arg, val, isnull,
false);
187 for (i = 0; i < desc->
natts; i++)
192 if (attr->attisdropped)
195 if (att->
typoid == attr->atttypid && att->
typmod == attr->atttypmod)
199 attr->atttypid, attr->atttypmod,
237 for (i = 0; i < desc->
natts; i++)
242 if (attr->attisdropped)
245 if (att->
typoid == attr->atttypid && att->
typmod == attr->atttypmod)
249 attr->atttypid, attr->atttypmod,
309 arg->
mcxt = arg_mcxt;
316 if (typeOid != RECORDOID)
327 typtype = TYPTYPE_COMPOSITE;
341 if (typtype == TYPTYPE_DOMAIN)
355 IsTrueArrayType(typentry))
376 else if (typtype == TYPTYPE_COMPOSITE)
432 arg->
mcxt = arg_mcxt;
439 if (typeOid != RECORDOID)
450 typtype = TYPTYPE_COMPOSITE;
464 if (typtype == TYPTYPE_DOMAIN)
473 IsTrueArrayType(typentry))
491 else if (typtype == TYPTYPE_COMPOSITE)
576 if (!decimal_constructor)
578 PyObject *decimal_module;
580 decimal_module = PyImport_ImportModule(
"cdecimal");
584 decimal_module = PyImport_ImportModule(
"decimal");
587 PLy_elog(
ERROR,
"could not import a module for Decimal constructor");
589 decimal_constructor = PyObject_GetAttrString(decimal_module,
"Decimal");
590 if (!decimal_constructor)
595 pyvalue = PyObject_CallFunction(decimal_constructor,
"s", str);
597 PLy_elog(
ERROR,
"conversion from numeric to Decimal failed");
633 return PyBytes_FromStringAndSize(str, size);
644 PyObject *r = PyString_FromString(x);
677 return PyList_New(0);
702 &dataptr, &bitmap, &bitmask);
707 char **dataptr_p,
bits8 **bitmap_p,
int *bitmask_p)
712 list = PyList_New(dims[dim]);
719 for (i = 0; i < dims[dim]; i++)
724 dataptr_p, bitmap_p, bitmask_p);
725 PyList_SET_ITEM(list, i, sublist);
734 char *dataptr = *dataptr_p;
735 bits8 *bitmap = *bitmap_p;
736 int bitmask = *bitmask_p;
738 for (i = 0; i < dims[dim]; i++)
741 if (bitmap && (*bitmap & bitmask) == 0)
744 PyList_SET_ITEM(list, i, Py_None);
751 PyList_SET_ITEM(list, i, elm->
func(elm, itemvalue));
760 if (bitmask == 0x100 )
768 *dataptr_p = dataptr;
770 *bitmask_p = bitmask;
816 PyObject *
volatile dict;
838 if (attr->attisdropped)
841 if (attr->attgenerated)
844 if (!include_generated)
852 PyDict_SetItemString(dict, key, Py_None);
855 value = att->
func(att, vattr);
856 PyDict_SetItemString(dict, key, value);
879 bool *isnull,
bool inarray)
897 bool *isnull,
bool inarray)
899 PyObject *
volatile plrv_so = NULL;
909 plrv_so = PyObject_Bytes(plrv);
911 PLy_elog(
ERROR,
"could not create bytes representation of Python object");
915 char *plrv_sc = PyBytes_AsString(plrv_so);
916 size_t len = PyBytes_Size(plrv_so);
921 memcpy(
VARDATA(result), plrv_sc, len);
941 bool *isnull,
bool inarray)
957 if (PyString_Check(plrv) || PyUnicode_Check(plrv))
966 if (arg->
typoid != RECORDOID)
1001 if (PySequence_Check(plrv))
1004 else if (PyMapping_Check(plrv))
1030 if (PyUnicode_Check(plrv))
1032 else if (PyFloat_Check(plrv))
1035 #if PY_MAJOR_VERSION >= 3 1036 PyObject *s = PyObject_Repr(plrv);
1041 plrv_bo = PyObject_Repr(plrv);
1046 #if PY_MAJOR_VERSION >= 3 1047 PyObject *s = PyObject_Str(plrv);
1052 plrv_bo = PyObject_Str(plrv);
1056 PLy_elog(
ERROR,
"could not create string representation of Python object");
1058 plrv_sc =
pstrdup(PyBytes_AsString(plrv_bo));
1059 plen = PyBytes_Size(plrv_bo);
1060 slen = strlen(plrv_sc);
1062 Py_XDECREF(plrv_bo);
1066 (
errcode(ERRCODE_DATATYPE_MISMATCH),
1067 errmsg(
"could not convert Python object into cstring: Python string representation appears to contain null bytes")));
1068 else if (slen > plen)
1069 elog(
ERROR,
"could not convert Python object into cstring: Python string longer than reported length");
1082 bool *isnull,
bool inarray)
1086 if (plrv == Py_None)
1107 bool *isnull,
bool inarray)
1112 result = base->
func(base, plrv, isnull, inarray);
1124 bool *isnull,
bool inarray)
1126 if (plrv == Py_None)
1141 bool *isnull,
bool inarray)
1152 PyObject *pyptr = plrv;
1155 if (plrv == Py_None)
1172 if (!PyList_Check(pyptr))
1177 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1178 errmsg(
"number of array dimensions exceeds the maximum allowed (%d)",
1181 dims[ndim] = PySequence_Length(pyptr);
1183 PLy_elog(
ERROR,
"could not determine sequence length for function return value");
1187 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1188 errmsg(
"array size exceeds the maximum allowed")));
1193 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1194 errmsg(
"array size exceeds the maximum allowed")));
1196 if (dims[ndim] == 0)
1204 next = PySequence_GetItem(pyptr, 0);
1219 if (!PySequence_Check(plrv))
1221 (
errcode(ERRCODE_DATATYPE_MISMATCH),
1222 errmsg(
"return value of function with array return type is not a Python sequence")));
1225 len = dims[0] = PySequence_Length(plrv);
1233 nulls =
palloc(
sizeof(
bool) * len);
1237 elems, nulls, &currelem);
1239 for (i = 0; i < ndim; i++)
1261 int *dims,
int ndim,
int dim,
1262 Datum *elems,
bool *nulls,
int *currelem)
1266 if (PySequence_Length(list) != dims[dim])
1268 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1269 errmsg(
"wrong length of inner sequence: has length %d, but %d was expected",
1270 (
int) PySequence_Length(list), dims[dim]),
1271 (
errdetail(
"To construct a multidimensional array, the inner sequences must all have the same length."))));
1275 for (i = 0; i < dims[dim]; i++)
1277 PyObject *sublist = PySequence_GetItem(list, i);
1280 elems, nulls, currelem);
1281 Py_XDECREF(sublist);
1286 for (i = 0; i < dims[dim]; i++)
1288 PyObject *obj = PySequence_GetItem(list, i);
1290 elems[*currelem] = elm->
func(elm, obj, &nulls[*currelem],
true);
1345 while (*ptr && isspace((
unsigned char) *ptr))
1349 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1350 errmsg(
"malformed record literal: \"%s\"", str),
1352 errhint(
"To return a composite type in an array, return the composite type as a Python tuple, e.g., \"[('foo',)]\".")));
1371 Assert(PyMapping_Check(mapping));
1376 for (i = 0; i < desc->
natts; ++
i)
1379 PyObject *
volatile value;
1383 if (attr->attisdropped)
1395 value = PyMapping_GetItemString(mapping, key);
1398 (
errcode(ERRCODE_UNDEFINED_COLUMN),
1399 errmsg(
"key \"%s\" not found in mapping", key),
1400 errhint(
"To return null in a column, " 1401 "add the value None to the mapping with the key named after the column.")));
1403 values[
i] = att->
func(att, value, &nulls[i],
false);
1437 Assert(PySequence_Check(sequence));
1445 for (i = 0; i < desc->
natts; i++)
1450 if (PySequence_Length(sequence) != idx)
1452 (
errcode(ERRCODE_DATATYPE_MISMATCH),
1453 errmsg(
"length of returned sequence did not match number of columns in row")));
1459 for (i = 0; i < desc->
natts; ++
i)
1461 PyObject *
volatile value;
1475 value = PySequence_GetItem(sequence, idx);
1478 values[
i] = att->
func(att, value, &nulls[i],
false);
1516 for (i = 0; i < desc->
natts; ++
i)
1519 PyObject *
volatile value;
1523 if (attr->attisdropped)
1535 value = PyObject_GetAttrString(
object, key);
1550 (
errcode(ERRCODE_UNDEFINED_COLUMN),
1551 errmsg(
"attribute \"%s\" does not exist in Python object", key),
1553 errhint(
"To return a composite type in an array, return the composite type as a Python tuple, e.g., \"[('foo',)]\".") :
1554 errhint(
"To return null in a column, let the returned object have an attribute named after column with value None.")));
1557 values[
i] = att->
func(att, value, &nulls[i],
false);
Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
static PyObject * PLyLong_FromInt64(PLyDatumToOb *arg, Datum d)
static PyObject * PLyInt_FromInt32(PLyDatumToOb *arg, Datum d)
Datum PLy_output_convert(PLyObToDatum *arg, PyObject *val, bool *isnull)
int errhint(const char *fmt,...)
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
#define att_align_nominal(cur_offset, attalign)
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
static PyObject * PLyBool_FromBool(PLyDatumToOb *arg, Datum d)
#define PointerGetDatum(X)
#define TupleDescAttr(tupdesc, i)
#define DatumGetObjectId(X)
char * pstrdup(const char *in)
Datum numeric_out(PG_FUNCTION_ARGS)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
TypeCacheEntry * typentry
int errcode(int sqlerrcode)
Datum idx(PG_FUNCTION_ARGS)
#define DatumGetByteaPP(X)
void MemoryContextReset(MemoryContext context)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
#define DirectFunctionCall1(func, arg1)
void heap_freetuple(HeapTuple htup)
PLyExecutionContext * PLy_current_execution_context(void)
#define OidIsValid(objectId)
PLyObToTransform transform
#define INVALID_TUPLEDESC_IDENTIFIER
#define DatumGetHeapTupleHeader(X)
static PyObject * PLyString_FromScalar(PLyDatumToOb *arg, Datum d)
static PyObject * PLyDict_FromComposite(PLyDatumToOb *arg, Datum d)
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
#define HeapTupleHeaderGetTypMod(tup)
static Datum PLyObject_ToScalar(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
static PyObject * PLyInt_FromInt16(PLyDatumToOb *arg, Datum d)
void pfree(void *pointer)
static float4 DatumGetFloat4(Datum X)
static PyObject * decimal_constructor
#define DatumGetCString(X)
void PLy_output_setup_record(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
static PyObject * PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d)
char * PLyObject_AsString(PyObject *plrv)
static PyObject * PLyDict_FromTuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc, bool include_generated)
PLyTransformToOb transform
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
static PyObject * PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d)
static PyObject * PLyBytes_FromBytea(PLyDatumToOb *arg, Datum d)
void PLy_input_setup_tuple(PLyDatumToOb *arg, TupleDesc desc, PLyProcedure *proc)
void check_stack_depth(void)
static Datum PLyObject_ToDomain(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
static Datum PLyObject_ToBool(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
int errdetail(const char *fmt,...)
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
FormData_pg_attribute * Form_pg_attribute
static Datum PLyGenericObject_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *object, bool inarray)
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
#define att_addlength_pointer(cur_offset, attlen, attptr)
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
static PyObject * PLyDecimal_FromNumeric(PLyDatumToOb *arg, Datum d)
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
static Datum PLyObject_ToComposite(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
#define TYPECACHE_DOMAIN_BASE_INFO
TypeCacheEntry * typentry
#define heap_getattr(tup, attnum, tupleDesc, isnull)
#define DatumGetFloat8(X)
#define HeapTupleHeaderGetTypeId(tup)
void domain_check(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt)
void PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
void * MemoryContextAllocZero(MemoryContext context, Size size)
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
static Datum PLyString_ToComposite(PLyObToDatum *arg, PyObject *string, bool inarray)
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
#define ereport(elevel,...)
PyObject * PLy_input_convert(PLyDatumToOb *arg, Datum val)
static PyObject * PLyList_FromArray(PLyDatumToOb *arg, Datum d)
#define Assert(condition)
static PyObject * PLyLong_FromOid(PLyDatumToOb *arg, Datum d)
PyObject * PLy_input_from_tuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc, bool include_generated)
uint64 tupDesc_identifier
union PLyObToDatum::@165 u
PyObject * PLyUnicode_Bytes(PyObject *unicode)
Oid get_transform_tosql(Oid typid, Oid langid, List *trftypes)
static Datum PLyObject_ToTransform(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
#define DatumGetPointer(X)
#define PinTupleDesc(tupdesc)
static Datum values[MAXATTR]
void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
static PyObject * PLyObject_FromTransform(PLyDatumToOb *arg, Datum d)
#define VARSIZE_ANY_EXHDR(PTR)
int errmsg(const char *fmt,...)
#define fetch_att(T, attbyval, attlen)
static Datum PLySequence_ToArray(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
#define FunctionCall1(flinfo, arg1)
static PyObject * PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim, char **dataptr_p, bits8 **bitmap_p, int *bitmask_p)
#define SET_VARSIZE(PTR, len)
static Datum PLyObject_ToBytea(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
static Datum PLySequence_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *sequence)
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
#define ReleaseTupleDesc(tupdesc)
static void PLySequence_ToArray_recurse(PLyObToDatum *elm, PyObject *list, int *dims, int ndim, int dim, Datum *elems, bool *nulls, int *currelem)
Oid getBaseType(Oid typid)
static Datum PLyMapping_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *mapping)
#define ARR_NULLBITMAP(a)
MemoryContext PLy_get_scratch_context(PLyExecutionContext *context)
union PLyDatumToOb::@164 u
#define HeapTupleHeaderGetDatumLength(tup)
#define DatumGetArrayTypeP(X)