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)
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
ArrayType * construct_empty_array(Oid elmtype)
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)
char * pstrdup(const char *in)
void pfree(void *pointer)
void * MemoryContextAllocZero(MemoryContext context, Size size)
MemoryContext CurrentMemoryContext
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 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)
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)
MemoryContextSwitchTo(old_ctx)
static pg_noinline void Size size
#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)