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);
122 return arg->func(
arg,
val, isnull,
false);
172 if (
arg->typoid == RECORDOID &&
arg->typmod < 0)
173 arg->u.tuple.recdesc = desc;
176 if (
arg->u.tuple.natts != desc->
natts)
178 if (
arg->u.tuple.atts)
192 if (attr->attisdropped)
195 if (att->
typoid == attr->atttypid && att->
typmod == attr->atttypmod)
199 attr->atttypid, attr->atttypmod,
222 if (
arg->typoid == RECORDOID &&
arg->typmod < 0)
223 arg->u.tuple.recdesc = desc;
226 if (
arg->u.tuple.natts != desc->
natts)
228 if (
arg->u.tuple.atts)
242 if (attr->attisdropped)
245 if (att->
typoid == attr->atttypid && att->
typmod == attr->atttypmod)
249 attr->atttypid, attr->atttypmod,
279 if (
arg->u.tuple.recdesc &&
280 arg->u.tuple.recdesc->tdtypmod !=
arg->typmod)
281 arg->u.tuple.recdesc = NULL;
307 arg->typoid = typeOid;
308 arg->typmod = typmod;
309 arg->mcxt = arg_mcxt;
316 if (typeOid != RECORDOID)
327 typtype = TYPTYPE_COMPOSITE;
329 arg->typbyval =
false;
331 arg->typalign = TYPALIGN_DOUBLE;
341 if (typtype == TYPTYPE_DOMAIN)
345 arg->u.domain.domain_info = NULL;
355 IsTrueArrayType(typentry))
376 else if (typtype == TYPTYPE_COMPOSITE)
381 arg->u.tuple.recdesc = NULL;
382 arg->u.tuple.typentry = typentry;
384 arg->u.tuple.atts = NULL;
385 arg->u.tuple.natts = 0;
430 arg->typoid = typeOid;
431 arg->typmod = typmod;
432 arg->mcxt = arg_mcxt;
439 if (typeOid != RECORDOID)
450 typtype = TYPTYPE_COMPOSITE;
452 arg->typbyval =
false;
454 arg->typalign = TYPALIGN_DOUBLE;
464 if (typtype == TYPTYPE_DOMAIN)
473 IsTrueArrayType(typentry))
491 else if (typtype == TYPTYPE_COMPOSITE)
496 arg->u.tuple.recdesc = NULL;
497 arg->u.tuple.typentry = typentry;
499 arg->u.tuple.atts = NULL;
500 arg->u.tuple.natts = 0;
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");
597 PLy_elog(
ERROR,
"conversion from numeric to Decimal failed");
633 return PyBytes_FromStringAndSize(
str, size);
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;
829 for (
i = 0;
i <
arg->u.tuple.natts;
i++)
838 if (attr->attisdropped)
841 if (attr->attgenerated)
844 if (!include_generated)
852 PyDict_SetItemString(dict,
key, Py_None);
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);
941 bool *isnull,
bool inarray)
957 if (PyUnicode_Check(plrv))
966 if (
arg->typoid != RECORDOID)
970 Assert(desc ==
arg->u.tuple.typentry->tupDesc);
972 if (
arg->u.tuple.tupdescid !=
arg->u.tuple.typentry->tupDesc_identifier)
976 arg->u.tuple.tupdescid =
arg->u.tuple.typentry->tupDesc_identifier;
981 desc =
arg->u.tuple.recdesc;
985 arg->u.tuple.recdesc = desc;
1001 if (PySequence_Check(plrv))
1004 else if (PyMapping_Check(plrv))
1030 if (PyUnicode_Check(plrv))
1032 else if (PyFloat_Check(plrv))
1035 PyObject *s = PyObject_Repr(plrv);
1042 PyObject *s = PyObject_Str(plrv);
1048 PLy_elog(
ERROR,
"could not create string representation of Python object");
1050 plrv_sc =
pstrdup(PyBytes_AsString(plrv_bo));
1051 plen = PyBytes_Size(plrv_bo);
1052 slen = strlen(plrv_sc);
1054 Py_XDECREF(plrv_bo);
1058 (
errcode(ERRCODE_DATATYPE_MISMATCH),
1059 errmsg(
"could not convert Python object into cstring: Python string representation appears to contain null bytes")));
1060 else if (slen > plen)
1061 elog(
ERROR,
"could not convert Python object into cstring: Python string longer than reported length");
1074 bool *isnull,
bool inarray)
1078 if (plrv == Py_None)
1089 arg->u.scalar.typioparam,
1099 bool *isnull,
bool inarray)
1104 result = base->
func(base, plrv, isnull, inarray);
1106 &
arg->u.domain.domain_info,
arg->mcxt);
1116 bool *isnull,
bool inarray)
1118 if (plrv == Py_None)
1133 bool *isnull,
bool inarray)
1144 PyObject *pyptr = plrv;
1147 if (plrv == Py_None)
1164 if (!PyList_Check(pyptr))
1169 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1170 errmsg(
"number of array dimensions exceeds the maximum allowed (%d)",
1173 dims[ndim] = PySequence_Length(pyptr);
1175 PLy_elog(
ERROR,
"could not determine sequence length for function return value");
1179 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1180 errmsg(
"array size exceeds the maximum allowed")));
1185 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1186 errmsg(
"array size exceeds the maximum allowed")));
1188 if (dims[ndim] == 0)
1196 next = PySequence_GetItem(pyptr, 0);
1211 if (!PySequence_Check(plrv))
1213 (
errcode(ERRCODE_DATATYPE_MISMATCH),
1214 errmsg(
"return value of function with array return type is not a Python sequence")));
1217 len = dims[0] = PySequence_Length(plrv);
1229 elems, nulls, &currelem);
1231 for (
i = 0;
i < ndim;
i++)
1239 arg->u.array.elmbasetype,
1240 arg->u.array.elm->typlen,
1241 arg->u.array.elm->typbyval,
1242 arg->u.array.elm->typalign);
1253 int *dims,
int ndim,
int dim,
1254 Datum *elems,
bool *nulls,
int *currelem)
1258 if (PySequence_Length(
list) != dims[dim])
1260 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1261 errmsg(
"wrong length of inner sequence: has length %d, but %d was expected",
1262 (
int) PySequence_Length(
list), dims[dim]),
1263 (
errdetail(
"To construct a multidimensional array, the inner sequences must all have the same length."))));
1267 for (
i = 0;
i < dims[dim];
i++)
1269 PyObject *sublist = PySequence_GetItem(
list,
i);
1272 elems, nulls, currelem);
1273 Py_XDECREF(sublist);
1278 for (
i = 0;
i < dims[dim];
i++)
1280 PyObject *obj = PySequence_GetItem(
list,
i);
1282 elems[*currelem] = elm->
func(elm, obj, &nulls[*currelem],
true);
1337 while (*ptr && isspace((
unsigned char) *ptr))
1341 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1342 errmsg(
"malformed record literal: \"%s\"",
str),
1344 errhint(
"To return a composite type in an array, return the composite type as a Python tuple, e.g., \"[('foo',)]\".")));
1363 Assert(PyMapping_Check(mapping));
1371 PyObject *
volatile value;
1375 if (attr->attisdropped)
1384 att = &
arg->u.tuple.atts[
i];
1387 value = PyMapping_GetItemString(mapping,
key);
1390 (
errcode(ERRCODE_UNDEFINED_COLUMN),
1391 errmsg(
"key \"%s\" not found in mapping",
key),
1392 errhint(
"To return null in a column, "
1393 "add the value None to the mapping with the key named after the column.")));
1429 Assert(PySequence_Check(sequence));
1442 if (PySequence_Length(sequence) !=
idx)
1444 (
errcode(ERRCODE_DATATYPE_MISMATCH),
1445 errmsg(
"length of returned sequence did not match number of columns in row")));
1453 PyObject *
volatile value;
1464 att = &
arg->u.tuple.atts[
i];
1467 value = PySequence_GetItem(sequence,
idx);
1511 PyObject *
volatile value;
1515 if (attr->attisdropped)
1524 att = &
arg->u.tuple.atts[
i];
1527 value = PyObject_GetAttrString(
object,
key);
1542 (
errcode(ERRCODE_UNDEFINED_COLUMN),
1543 errmsg(
"attribute \"%s\" does not exist in Python object",
key),
1545 errhint(
"To return a composite type in an array, return the composite type as a Python tuple, e.g., \"[('foo',)]\".") :
1546 errhint(
"To return null in a column, let the returned object have an attribute named after column with value None.")));
Datum idx(PG_FUNCTION_ARGS)
#define ARR_NULLBITMAP(a)
#define DatumGetArrayTypeP(X)
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Datum numeric_out(PG_FUNCTION_ARGS)
static Datum values[MAXATTR]
#define OidIsValid(objectId)
elog(ERROR, "%s: %s", p2, msg)
void domain_check(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
#define DatumGetHeapTupleHeader(X)
#define DatumGetByteaPP(X)
#define DirectFunctionCall1(func, arg1)
#define FunctionCall1(flinfo, arg1)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
void heap_freetuple(HeapTuple htup)
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
#define HeapTupleHeaderGetTypMod(tup)
#define HeapTupleHeaderGetTypeId(tup)
#define HeapTupleHeaderGetDatumLength(tup)
static PyObject * decimal_constructor
Assert(fmt[strlen(fmt) - 1] !='\n')
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Oid get_transform_tosql(Oid typid, Oid langid, List *trftypes)
Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
Oid getBaseType(Oid typid)
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
void MemoryContextReset(MemoryContext context)
char * pstrdup(const char *in)
void pfree(void *pointer)
void * MemoryContextAllocZero(MemoryContext context, Size size)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
FormData_pg_attribute * Form_pg_attribute
PLyExecutionContext * PLy_current_execution_context(void)
MemoryContext PLy_get_scratch_context(PLyExecutionContext *context)
static PyObject * PLyLong_FromInt16(PLyDatumToOb *arg, Datum d)
PyObject * PLy_input_from_tuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc, bool include_generated)
void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
char * PLyObject_AsString(PyObject *plrv)
static PyObject * PLyLong_FromInt64(PLyDatumToOb *arg, Datum d)
static PyObject * PLyDict_FromTuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc, bool include_generated)
static Datum PLyMapping_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *mapping)
static Datum PLyObject_ToBool(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
void PLy_input_setup_tuple(PLyDatumToOb *arg, TupleDesc desc, PLyProcedure *proc)
static Datum PLyObject_ToBytea(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
static PyObject * PLyDict_FromComposite(PLyDatumToOb *arg, Datum d)
static Datum PLyObject_ToScalar(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
PyObject * PLy_input_convert(PLyDatumToOb *arg, Datum val)
static Datum PLyObject_ToTransform(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
static PyObject * PLyLong_FromInt32(PLyDatumToOb *arg, Datum d)
static PyObject * PLyBool_FromBool(PLyDatumToOb *arg, Datum d)
void PLy_output_setup_record(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
static PyObject * PLyUnicode_FromScalar(PLyDatumToOb *arg, Datum d)
static PyObject * PLyObject_FromTransform(PLyDatumToOb *arg, Datum d)
static PyObject * PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d)
static PyObject * PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim, char **dataptr_p, bits8 **bitmap_p, int *bitmask_p)
static Datum PLyObject_ToComposite(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
static PyObject * PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d)
static PyObject * PLyLong_FromOid(PLyDatumToOb *arg, Datum d)
static Datum PLySequence_ToArray(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
static PyObject * PLyList_FromArray(PLyDatumToOb *arg, Datum d)
static Datum PLySequence_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *sequence)
static PyObject * PLyBytes_FromBytea(PLyDatumToOb *arg, Datum d)
static Datum PLyUnicode_ToComposite(PLyObToDatum *arg, PyObject *string, bool inarray)
void PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
Datum PLy_output_convert(PLyObToDatum *arg, PyObject *val, bool *isnull)
static Datum PLyObject_ToDomain(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
static void PLySequence_ToArray_recurse(PLyObToDatum *elm, PyObject *list, int *dims, int ndim, int dim, Datum *elems, bool *nulls, int *currelem)
static PyObject * PLyDecimal_FromNumeric(PLyDatumToOb *arg, Datum d)
static Datum PLyGenericObject_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *object, bool inarray)
PyObject * PLyUnicode_Bytes(PyObject *unicode)
PyObject * PLyUnicode_FromString(const char *s)
void check_stack_depth(void)
static bool DatumGetBool(Datum X)
static int64 DatumGetInt64(Datum X)
static Datum PointerGetDatum(const void *X)
static char * DatumGetCString(Datum X)
static float4 DatumGetFloat4(Datum X)
static Oid DatumGetObjectId(Datum X)
static Datum BoolGetDatum(bool X)
static float8 DatumGetFloat8(Datum X)
static Pointer DatumGetPointer(Datum X)
static int16 DatumGetInt16(Datum X)
static int32 DatumGetInt32(Datum X)
#define ReleaseTupleDesc(tupdesc)
#define PinTupleDesc(tupdesc)
#define TupleDescAttr(tupdesc, i)
#define att_align_nominal(cur_offset, attalign)
#define att_addlength_pointer(cur_offset, attlen, attptr)
static Datum fetch_att(const void *T, bool attbyval, int attlen)
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
#define INVALID_TUPLEDESC_IDENTIFIER
#define TYPECACHE_DOMAIN_BASE_INFO
#define SET_VARSIZE(PTR, len)
#define VARSIZE_ANY_EXHDR(PTR)