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);
59 int *ndims,
int *dims,
int cur_depth,
123 return arg->func(
arg,
val, isnull,
false);
173 if (
arg->typoid == RECORDOID &&
arg->typmod < 0)
174 arg->u.tuple.recdesc = desc;
177 if (
arg->u.tuple.natts != desc->
natts)
179 if (
arg->u.tuple.atts)
193 if (attr->attisdropped)
196 if (att->
typoid == attr->atttypid && att->
typmod == attr->atttypmod)
200 attr->atttypid, attr->atttypmod,
223 if (
arg->typoid == RECORDOID &&
arg->typmod < 0)
224 arg->u.tuple.recdesc = desc;
227 if (
arg->u.tuple.natts != desc->
natts)
229 if (
arg->u.tuple.atts)
243 if (attr->attisdropped)
246 if (att->
typoid == attr->atttypid && att->
typmod == attr->atttypmod)
250 attr->atttypid, attr->atttypmod,
280 if (
arg->u.tuple.recdesc &&
281 arg->u.tuple.recdesc->tdtypmod !=
arg->typmod)
282 arg->u.tuple.recdesc = NULL;
308 arg->typoid = typeOid;
309 arg->typmod = typmod;
310 arg->mcxt = arg_mcxt;
317 if (typeOid != RECORDOID)
328 typtype = TYPTYPE_COMPOSITE;
330 arg->typbyval =
false;
332 arg->typalign = TYPALIGN_DOUBLE;
342 if (typtype == TYPTYPE_DOMAIN)
346 arg->u.domain.domain_info = NULL;
356 IsTrueArrayType(typentry))
377 else if (typtype == TYPTYPE_COMPOSITE)
382 arg->u.tuple.recdesc = NULL;
383 arg->u.tuple.typentry = typentry;
385 arg->u.tuple.atts = NULL;
386 arg->u.tuple.natts = 0;
431 arg->typoid = typeOid;
432 arg->typmod = typmod;
433 arg->mcxt = arg_mcxt;
440 if (typeOid != RECORDOID)
451 typtype = TYPTYPE_COMPOSITE;
453 arg->typbyval =
false;
455 arg->typalign = TYPALIGN_DOUBLE;
465 if (typtype == TYPTYPE_DOMAIN)
474 IsTrueArrayType(typentry))
492 else if (typtype == TYPTYPE_COMPOSITE)
497 arg->u.tuple.recdesc = NULL;
498 arg->u.tuple.typentry = typentry;
500 arg->u.tuple.atts = NULL;
501 arg->u.tuple.natts = 0;
579 PyObject *decimal_module;
581 decimal_module = PyImport_ImportModule(
"cdecimal");
585 decimal_module = PyImport_ImportModule(
"decimal");
588 PLy_elog(
ERROR,
"could not import a module for Decimal constructor");
598 PLy_elog(
ERROR,
"conversion from numeric to Decimal failed");
634 return PyBytes_FromStringAndSize(
str,
size);
678 return PyList_New(0);
703 &dataptr, &bitmap, &bitmask);
708 char **dataptr_p,
bits8 **bitmap_p,
int *bitmask_p)
713 list = PyList_New(dims[dim]);
720 for (
i = 0;
i < dims[dim];
i++)
725 dataptr_p, bitmap_p, bitmask_p);
726 PyList_SET_ITEM(
list,
i, sublist);
735 char *dataptr = *dataptr_p;
736 bits8 *bitmap = *bitmap_p;
737 int bitmask = *bitmask_p;
739 for (
i = 0;
i < dims[dim];
i++)
742 if (bitmap && (*bitmap & bitmask) == 0)
745 PyList_SET_ITEM(
list,
i, Py_None);
752 PyList_SET_ITEM(
list,
i, elm->
func(elm, itemvalue));
761 if (bitmask == 0x100 )
769 *dataptr_p = dataptr;
771 *bitmask_p = bitmask;
817 PyObject *
volatile dict;
830 for (
i = 0;
i <
arg->u.tuple.natts;
i++)
839 if (attr->attisdropped)
842 if (attr->attgenerated)
845 if (!include_generated)
853 PyDict_SetItemString(dict,
key, Py_None);
857 PyDict_SetItemString(dict,
key,
value);
880 bool *isnull,
bool inarray)
898 bool *isnull,
bool inarray)
900 PyObject *
volatile plrv_so = NULL;
910 plrv_so = PyObject_Bytes(plrv);
912 PLy_elog(
ERROR,
"could not create bytes representation of Python object");
916 char *plrv_sc = PyBytes_AsString(plrv_so);
917 size_t len = PyBytes_Size(plrv_so);
942 bool *isnull,
bool inarray)
958 if (PyUnicode_Check(plrv))
967 if (
arg->typoid != RECORDOID)
971 Assert(desc ==
arg->u.tuple.typentry->tupDesc);
973 if (
arg->u.tuple.tupdescid !=
arg->u.tuple.typentry->tupDesc_identifier)
977 arg->u.tuple.tupdescid =
arg->u.tuple.typentry->tupDesc_identifier;
982 desc =
arg->u.tuple.recdesc;
986 arg->u.tuple.recdesc = desc;
1002 if (PySequence_Check(plrv))
1005 else if (PyMapping_Check(plrv))
1031 if (PyUnicode_Check(plrv))
1033 else if (PyFloat_Check(plrv))
1036 PyObject *s = PyObject_Repr(plrv);
1043 PyObject *s = PyObject_Str(plrv);
1049 PLy_elog(
ERROR,
"could not create string representation of Python object");
1051 plrv_sc =
pstrdup(PyBytes_AsString(plrv_bo));
1052 plen = PyBytes_Size(plrv_bo);
1053 slen = strlen(plrv_sc);
1055 Py_XDECREF(plrv_bo);
1059 (
errcode(ERRCODE_DATATYPE_MISMATCH),
1060 errmsg(
"could not convert Python object into cstring: Python string representation appears to contain null bytes")));
1061 else if (slen > plen)
1062 elog(
ERROR,
"could not convert Python object into cstring: Python string longer than reported length");
1075 bool *isnull,
bool inarray)
1079 if (plrv == Py_None)
1090 arg->u.scalar.typioparam,
1100 bool *isnull,
bool inarray)
1105 result = base->
func(base, plrv, isnull, inarray);
1107 &
arg->u.domain.domain_info,
arg->mcxt);
1117 bool *isnull,
bool inarray)
1119 if (plrv == Py_None)
1134 bool *isnull,
bool inarray)
1141 if (plrv == Py_None)
1154 if (!PySequence_Check(plrv))
1156 (
errcode(ERRCODE_DATATYPE_MISMATCH),
1157 errmsg(
"return value of function with array return type is not a Python sequence")));
1160 memset(dims, 0,
sizeof(dims));
1161 dims[0] = PySequence_Length(plrv);
1170 arg->u.array.elmbasetype);
1176 for (
int i = 0;
i < ndims;
i++)
1194 int *ndims,
int *dims,
int cur_depth,
1198 int len = PySequence_Length(obj);
1202 PLy_elog(
ERROR,
"could not determine sequence length for function return value");
1204 for (
i = 0;
i <
len;
i++)
1207 PyObject *subobj = PySequence_GetItem(obj,
i);
1213 if (PyList_Check(subobj))
1216 if (
i == 0 && *ndims == cur_depth)
1219 if (*astatep != NULL)
1221 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1222 errmsg(
"multidimensional arrays must have array expressions with matching dimensions")));
1226 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1227 errmsg(
"number of array dimensions exceeds the maximum allowed (%d)",
1230 dims[*ndims] = PySequence_Length(subobj);
1233 else if (cur_depth >= *ndims ||
1234 PySequence_Length(subobj) != dims[cur_depth])
1236 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1237 errmsg(
"multidimensional arrays must have array expressions with matching dimensions")));
1241 ndims, dims, cur_depth + 1,
1250 if (*ndims != cur_depth)
1252 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1253 errmsg(
"multidimensional arrays must have array expressions with matching dimensions")));
1256 dat = elm->
func(elm, subobj, &isnull,
true);
1259 if (*astatep == NULL)
1324 while (*ptr && isspace((
unsigned char) *ptr))
1328 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1329 errmsg(
"malformed record literal: \"%s\"",
str),
1331 errhint(
"To return a composite type in an array, return the composite type as a Python tuple, e.g., \"[('foo',)]\".")));
1350 Assert(PyMapping_Check(mapping));
1358 PyObject *
volatile value;
1362 if (attr->attisdropped)
1371 att = &
arg->u.tuple.atts[
i];
1374 value = PyMapping_GetItemString(mapping,
key);
1377 (
errcode(ERRCODE_UNDEFINED_COLUMN),
1378 errmsg(
"key \"%s\" not found in mapping",
key),
1379 errhint(
"To return null in a column, "
1380 "add the value None to the mapping with the key named after the column.")));
1416 Assert(PySequence_Check(sequence));
1429 if (PySequence_Length(sequence) !=
idx)
1431 (
errcode(ERRCODE_DATATYPE_MISMATCH),
1432 errmsg(
"length of returned sequence did not match number of columns in row")));
1440 PyObject *
volatile value;
1451 att = &
arg->u.tuple.atts[
i];
1454 value = PySequence_GetItem(sequence,
idx);
1498 PyObject *
volatile value;
1502 if (attr->attisdropped)
1511 att = &
arg->u.tuple.atts[
i];
1514 value = PyObject_GetAttrString(
object,
key);
1529 (
errcode(ERRCODE_UNDEFINED_COLUMN),
1530 errmsg(
"attribute \"%s\" does not exist in Python object",
key),
1532 errhint(
"To return a composite type in an array, return the composite type as a Python tuple, e.g., \"[('foo',)]\".") :
1533 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)
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
ArrayType * construct_empty_array(Oid elmtype)
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Datum numeric_out(PG_FUNCTION_ARGS)
static Datum values[MAXATTR]
#define Assert(condition)
#define OidIsValid(objectId)
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, const Datum *values, const 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
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)
void * MemoryContextAllocZero(MemoryContext context, Size size)
char * pstrdup(const char *in)
void pfree(void *pointer)
MemoryContext CurrentMemoryContext
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)
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)
static PyObject * PLyLong_FromInt64(PLyDatumToOb *arg, Datum d)
PyObject * PLy_input_from_tuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc, bool include_generated)
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)
PyObject * PLy_input_convert(PLyDatumToOb *arg, Datum val)
static Datum PLyObject_ToBytea(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
char * PLyObject_AsString(PyObject *plrv)
static PyObject * PLyDict_FromComposite(PLyDatumToOb *arg, Datum d)
static Datum PLyObject_ToScalar(PLyObToDatum *arg, PyObject *plrv, bool *isnull, bool inarray)
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 void PLySequence_ToArray_recurse(PyObject *obj, ArrayBuildState **astatep, int *ndims, int *dims, int cur_depth, PLyObToDatum *elm, Oid elmbasetype)
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 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)
static bool DatumGetBool(Datum X)
static int64 DatumGetInt64(Datum X)
static Datum PointerGetDatum(const void *X)
static float4 DatumGetFloat4(Datum X)
static Oid DatumGetObjectId(Datum X)
static Datum BoolGetDatum(bool X)
static float8 DatumGetFloat8(Datum X)
static char * DatumGetCString(Datum X)
static Pointer DatumGetPointer(Datum X)
static int16 DatumGetInt16(Datum X)
static int32 DatumGetInt32(Datum X)
static pg_noinline void Size size
void check_stack_depth(void)
#define ReleaseTupleDesc(tupdesc)
#define PinTupleDesc(tupdesc)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int 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)