00001
00002
00003
00004
00005
00006
00007 #include "postgres.h"
00008
00009 #include "access/htup_details.h"
00010 #include "access/transam.h"
00011 #include "catalog/pg_type.h"
00012 #include "funcapi.h"
00013 #include "mb/pg_wchar.h"
00014 #include "parser/parse_type.h"
00015 #include "utils/array.h"
00016 #include "utils/builtins.h"
00017 #include "utils/lsyscache.h"
00018 #include "utils/memutils.h"
00019 #include "utils/syscache.h"
00020 #include "utils/typcache.h"
00021
00022 #include "plpython.h"
00023
00024 #include "plpy_typeio.h"
00025
00026 #include "plpy_elog.h"
00027 #include "plpy_main.h"
00028
00029
00030
00031 static void PLy_input_datum_func2(PLyDatumToOb *arg, Oid typeOid, HeapTuple typeTup);
00032 static void PLy_output_datum_func2(PLyObToDatum *arg, HeapTuple typeTup);
00033
00034
00035 static PyObject *PLyBool_FromBool(PLyDatumToOb *arg, Datum d);
00036 static PyObject *PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d);
00037 static PyObject *PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d);
00038 static PyObject *PLyFloat_FromNumeric(PLyDatumToOb *arg, Datum d);
00039 static PyObject *PLyInt_FromInt16(PLyDatumToOb *arg, Datum d);
00040 static PyObject *PLyInt_FromInt32(PLyDatumToOb *arg, Datum d);
00041 static PyObject *PLyLong_FromInt64(PLyDatumToOb *arg, Datum d);
00042 static PyObject *PLyLong_FromOid(PLyDatumToOb *arg, Datum d);
00043 static PyObject *PLyBytes_FromBytea(PLyDatumToOb *arg, Datum d);
00044 static PyObject *PLyString_FromDatum(PLyDatumToOb *arg, Datum d);
00045 static PyObject *PLyList_FromArray(PLyDatumToOb *arg, Datum d);
00046
00047
00048 static Datum PLyObject_ToBool(PLyObToDatum *arg, int32 typmod, PyObject *plrv);
00049 static Datum PLyObject_ToBytea(PLyObToDatum *arg, int32 typmod, PyObject *plrv);
00050 static Datum PLyObject_ToComposite(PLyObToDatum *arg, int32 typmod, PyObject *plrv);
00051 static Datum PLyObject_ToDatum(PLyObToDatum *arg, int32 typmod, PyObject *plrv);
00052 static Datum PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv);
00053
00054
00055 static Datum PLyString_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *string);
00056 static Datum PLyMapping_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *mapping);
00057 static Datum PLySequence_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *sequence);
00058 static Datum PLyGenericObject_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *object);
00059
00060
00061 static void perm_fmgr_info(Oid functionId, FmgrInfo *finfo);
00062
00063 void
00064 PLy_typeinfo_init(PLyTypeInfo *arg)
00065 {
00066 arg->is_rowtype = -1;
00067 arg->in.r.natts = arg->out.r.natts = 0;
00068 arg->in.r.atts = NULL;
00069 arg->out.r.atts = NULL;
00070 arg->typ_relid = InvalidOid;
00071 arg->typrel_xmin = InvalidTransactionId;
00072 ItemPointerSetInvalid(&arg->typrel_tid);
00073 }
00074
00075 void
00076 PLy_typeinfo_dealloc(PLyTypeInfo *arg)
00077 {
00078 if (arg->is_rowtype == 1)
00079 {
00080 int i;
00081
00082 for (i = 0; i < arg->in.r.natts; i++)
00083 {
00084 if (arg->in.r.atts[i].elm != NULL)
00085 PLy_free(arg->in.r.atts[i].elm);
00086 }
00087 if (arg->in.r.atts)
00088 PLy_free(arg->in.r.atts);
00089 for (i = 0; i < arg->out.r.natts; i++)
00090 {
00091 if (arg->out.r.atts[i].elm != NULL)
00092 PLy_free(arg->out.r.atts[i].elm);
00093 }
00094 if (arg->out.r.atts)
00095 PLy_free(arg->out.r.atts);
00096 }
00097 }
00098
00099
00100
00101
00102
00103 void
00104 PLy_input_datum_func(PLyTypeInfo *arg, Oid typeOid, HeapTuple typeTup)
00105 {
00106 if (arg->is_rowtype > 0)
00107 elog(ERROR, "PLyTypeInfo struct is initialized for Tuple");
00108 arg->is_rowtype = 0;
00109 PLy_input_datum_func2(&(arg->in.d), typeOid, typeTup);
00110 }
00111
00112 void
00113 PLy_output_datum_func(PLyTypeInfo *arg, HeapTuple typeTup)
00114 {
00115 if (arg->is_rowtype > 0)
00116 elog(ERROR, "PLyTypeInfo struct is initialized for a Tuple");
00117 arg->is_rowtype = 0;
00118 PLy_output_datum_func2(&(arg->out.d), typeTup);
00119 }
00120
00121 void
00122 PLy_input_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
00123 {
00124 int i;
00125
00126 if (arg->is_rowtype == 0)
00127 elog(ERROR, "PLyTypeInfo struct is initialized for a Datum");
00128 arg->is_rowtype = 1;
00129
00130 if (arg->in.r.natts != desc->natts)
00131 {
00132 if (arg->in.r.atts)
00133 PLy_free(arg->in.r.atts);
00134 arg->in.r.natts = desc->natts;
00135 arg->in.r.atts = PLy_malloc0(desc->natts * sizeof(PLyDatumToOb));
00136 }
00137
00138
00139 if (desc->tdtypmod != -1)
00140 elog(ERROR, "received unnamed record type as input");
00141
00142 Assert(OidIsValid(desc->tdtypeid));
00143
00144
00145
00146
00147
00148 if (desc->tdtypeid != RECORDOID)
00149 {
00150 HeapTuple relTup;
00151
00152
00153 arg->typ_relid = typeidTypeRelid(desc->tdtypeid);
00154 relTup = SearchSysCache1(RELOID, ObjectIdGetDatum(arg->typ_relid));
00155 if (!HeapTupleIsValid(relTup))
00156 elog(ERROR, "cache lookup failed for relation %u", arg->typ_relid);
00157
00158
00159 arg->typrel_xmin = HeapTupleHeaderGetXmin(relTup->t_data);
00160 arg->typrel_tid = relTup->t_self;
00161
00162 ReleaseSysCache(relTup);
00163 }
00164
00165 for (i = 0; i < desc->natts; i++)
00166 {
00167 HeapTuple typeTup;
00168
00169 if (desc->attrs[i]->attisdropped)
00170 continue;
00171
00172 if (arg->in.r.atts[i].typoid == desc->attrs[i]->atttypid)
00173 continue;
00174
00175 typeTup = SearchSysCache1(TYPEOID,
00176 ObjectIdGetDatum(desc->attrs[i]->atttypid));
00177 if (!HeapTupleIsValid(typeTup))
00178 elog(ERROR, "cache lookup failed for type %u",
00179 desc->attrs[i]->atttypid);
00180
00181 PLy_input_datum_func2(&(arg->in.r.atts[i]),
00182 desc->attrs[i]->atttypid,
00183 typeTup);
00184
00185 ReleaseSysCache(typeTup);
00186 }
00187 }
00188
00189 void
00190 PLy_output_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
00191 {
00192 int i;
00193
00194 if (arg->is_rowtype == 0)
00195 elog(ERROR, "PLyTypeInfo struct is initialized for a Datum");
00196 arg->is_rowtype = 1;
00197
00198 if (arg->out.r.natts != desc->natts)
00199 {
00200 if (arg->out.r.atts)
00201 PLy_free(arg->out.r.atts);
00202 arg->out.r.natts = desc->natts;
00203 arg->out.r.atts = PLy_malloc0(desc->natts * sizeof(PLyDatumToOb));
00204 }
00205
00206 Assert(OidIsValid(desc->tdtypeid));
00207
00208
00209
00210
00211
00212 if (desc->tdtypeid != RECORDOID)
00213 {
00214 HeapTuple relTup;
00215
00216
00217 arg->typ_relid = typeidTypeRelid(desc->tdtypeid);
00218 relTup = SearchSysCache1(RELOID, ObjectIdGetDatum(arg->typ_relid));
00219 if (!HeapTupleIsValid(relTup))
00220 elog(ERROR, "cache lookup failed for relation %u", arg->typ_relid);
00221
00222
00223 arg->typrel_xmin = HeapTupleHeaderGetXmin(relTup->t_data);
00224 arg->typrel_tid = relTup->t_self;
00225
00226 ReleaseSysCache(relTup);
00227 }
00228
00229 for (i = 0; i < desc->natts; i++)
00230 {
00231 HeapTuple typeTup;
00232
00233 if (desc->attrs[i]->attisdropped)
00234 continue;
00235
00236 if (arg->out.r.atts[i].typoid == desc->attrs[i]->atttypid)
00237 continue;
00238
00239 typeTup = SearchSysCache1(TYPEOID,
00240 ObjectIdGetDatum(desc->attrs[i]->atttypid));
00241 if (!HeapTupleIsValid(typeTup))
00242 elog(ERROR, "cache lookup failed for type %u",
00243 desc->attrs[i]->atttypid);
00244
00245 PLy_output_datum_func2(&(arg->out.r.atts[i]), typeTup);
00246
00247 ReleaseSysCache(typeTup);
00248 }
00249 }
00250
00251 void
00252 PLy_output_record_funcs(PLyTypeInfo *arg, TupleDesc desc)
00253 {
00254
00255
00256
00257
00258 if ((arg->is_rowtype == 1) &&
00259 (arg->out.d.typmod != -1) &&
00260 (arg->out.d.typmod == desc->tdtypmod))
00261 return;
00262
00263
00264 BlessTupleDesc(desc);
00265
00266 arg->out.d.typmod = desc->tdtypmod;
00267
00268 PLy_output_tuple_funcs(arg, desc);
00269
00270
00271
00272
00273
00274 Assert(arg->is_rowtype == 1);
00275 }
00276
00277
00278
00279
00280 PyObject *
00281 PLyDict_FromTuple(PLyTypeInfo *info, HeapTuple tuple, TupleDesc desc)
00282 {
00283 PyObject *volatile dict;
00284 PLyExecutionContext *exec_ctx = PLy_current_execution_context();
00285 MemoryContext oldcontext = CurrentMemoryContext;
00286 int i;
00287
00288 if (info->is_rowtype != 1)
00289 elog(ERROR, "PLyTypeInfo structure describes a datum");
00290
00291 dict = PyDict_New();
00292 if (dict == NULL)
00293 PLy_elog(ERROR, "could not create new dictionary");
00294
00295 PG_TRY();
00296 {
00297
00298
00299
00300
00301 MemoryContextSwitchTo(exec_ctx->scratch_ctx);
00302 for (i = 0; i < info->in.r.natts; i++)
00303 {
00304 char *key;
00305 Datum vattr;
00306 bool is_null;
00307 PyObject *value;
00308
00309 if (desc->attrs[i]->attisdropped)
00310 continue;
00311
00312 key = NameStr(desc->attrs[i]->attname);
00313 vattr = heap_getattr(tuple, (i + 1), desc, &is_null);
00314
00315 if (is_null || info->in.r.atts[i].func == NULL)
00316 PyDict_SetItemString(dict, key, Py_None);
00317 else
00318 {
00319 value = (info->in.r.atts[i].func) (&info->in.r.atts[i], vattr);
00320 PyDict_SetItemString(dict, key, value);
00321 Py_DECREF(value);
00322 }
00323 }
00324 MemoryContextSwitchTo(oldcontext);
00325 MemoryContextReset(exec_ctx->scratch_ctx);
00326 }
00327 PG_CATCH();
00328 {
00329 MemoryContextSwitchTo(oldcontext);
00330 Py_DECREF(dict);
00331 PG_RE_THROW();
00332 }
00333 PG_END_TRY();
00334
00335 return dict;
00336 }
00337
00338
00339
00340
00341
00342
00343 Datum
00344 PLyObject_ToCompositeDatum(PLyTypeInfo *info, TupleDesc desc, PyObject *plrv)
00345 {
00346 Datum datum;
00347
00348 if (PyString_Check(plrv) || PyUnicode_Check(plrv))
00349 datum = PLyString_ToComposite(info, desc, plrv);
00350 else if (PySequence_Check(plrv))
00351
00352 datum = PLySequence_ToComposite(info, desc, plrv);
00353 else if (PyMapping_Check(plrv))
00354
00355 datum = PLyMapping_ToComposite(info, desc, plrv);
00356 else
00357
00358 datum = PLyGenericObject_ToComposite(info, desc, plrv);
00359
00360 return datum;
00361 }
00362
00363 static void
00364 PLy_output_datum_func2(PLyObToDatum *arg, HeapTuple typeTup)
00365 {
00366 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
00367 Oid element_type;
00368
00369 perm_fmgr_info(typeStruct->typinput, &arg->typfunc);
00370 arg->typoid = HeapTupleGetOid(typeTup);
00371 arg->typmod = -1;
00372 arg->typioparam = getTypeIOParam(typeTup);
00373 arg->typbyval = typeStruct->typbyval;
00374
00375 element_type = get_element_type(arg->typoid);
00376
00377
00378
00379
00380
00381 switch (getBaseType(element_type ? element_type : arg->typoid))
00382 {
00383 case BOOLOID:
00384 arg->func = PLyObject_ToBool;
00385 break;
00386 case BYTEAOID:
00387 arg->func = PLyObject_ToBytea;
00388 break;
00389 default:
00390 arg->func = PLyObject_ToDatum;
00391 break;
00392 }
00393
00394
00395 if (typeStruct->typtype == TYPTYPE_COMPOSITE)
00396 {
00397 arg->func = PLyObject_ToComposite;
00398 }
00399
00400 if (element_type)
00401 {
00402 char dummy_delim;
00403 Oid funcid;
00404
00405 if (type_is_rowtype(element_type))
00406 ereport(ERROR,
00407 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00408 errmsg("PL/Python functions cannot return type %s",
00409 format_type_be(arg->typoid)),
00410 errdetail("PL/Python does not support conversion to arrays of row types.")));
00411
00412 arg->elm = PLy_malloc0(sizeof(*arg->elm));
00413 arg->elm->func = arg->func;
00414 arg->func = PLySequence_ToArray;
00415
00416 arg->elm->typoid = element_type;
00417 arg->elm->typmod = -1;
00418 get_type_io_data(element_type, IOFunc_input,
00419 &arg->elm->typlen, &arg->elm->typbyval, &arg->elm->typalign, &dummy_delim,
00420 &arg->elm->typioparam, &funcid);
00421 perm_fmgr_info(funcid, &arg->elm->typfunc);
00422 }
00423 }
00424
00425 static void
00426 PLy_input_datum_func2(PLyDatumToOb *arg, Oid typeOid, HeapTuple typeTup)
00427 {
00428 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
00429 Oid element_type = get_element_type(typeOid);
00430
00431
00432 perm_fmgr_info(typeStruct->typoutput, &arg->typfunc);
00433 arg->typoid = HeapTupleGetOid(typeTup);
00434 arg->typmod = -1;
00435 arg->typioparam = getTypeIOParam(typeTup);
00436 arg->typbyval = typeStruct->typbyval;
00437 arg->typlen = typeStruct->typlen;
00438 arg->typalign = typeStruct->typalign;
00439
00440
00441 switch (getBaseType(element_type ? element_type : typeOid))
00442 {
00443 case BOOLOID:
00444 arg->func = PLyBool_FromBool;
00445 break;
00446 case FLOAT4OID:
00447 arg->func = PLyFloat_FromFloat4;
00448 break;
00449 case FLOAT8OID:
00450 arg->func = PLyFloat_FromFloat8;
00451 break;
00452 case NUMERICOID:
00453 arg->func = PLyFloat_FromNumeric;
00454 break;
00455 case INT2OID:
00456 arg->func = PLyInt_FromInt16;
00457 break;
00458 case INT4OID:
00459 arg->func = PLyInt_FromInt32;
00460 break;
00461 case INT8OID:
00462 arg->func = PLyLong_FromInt64;
00463 break;
00464 case OIDOID:
00465 arg->func = PLyLong_FromOid;
00466 break;
00467 case BYTEAOID:
00468 arg->func = PLyBytes_FromBytea;
00469 break;
00470 default:
00471 arg->func = PLyString_FromDatum;
00472 break;
00473 }
00474
00475 if (element_type)
00476 {
00477 char dummy_delim;
00478 Oid funcid;
00479
00480 arg->elm = PLy_malloc0(sizeof(*arg->elm));
00481 arg->elm->func = arg->func;
00482 arg->func = PLyList_FromArray;
00483 arg->elm->typoid = element_type;
00484 arg->elm->typmod = -1;
00485 get_type_io_data(element_type, IOFunc_output,
00486 &arg->elm->typlen, &arg->elm->typbyval, &arg->elm->typalign, &dummy_delim,
00487 &arg->elm->typioparam, &funcid);
00488 perm_fmgr_info(funcid, &arg->elm->typfunc);
00489 }
00490 }
00491
00492 static PyObject *
00493 PLyBool_FromBool(PLyDatumToOb *arg, Datum d)
00494 {
00495
00496
00497
00498
00499
00500
00501 if (DatumGetBool(d))
00502 return PyBool_FromLong(1);
00503 return PyBool_FromLong(0);
00504 }
00505
00506 static PyObject *
00507 PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d)
00508 {
00509 return PyFloat_FromDouble(DatumGetFloat4(d));
00510 }
00511
00512 static PyObject *
00513 PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d)
00514 {
00515 return PyFloat_FromDouble(DatumGetFloat8(d));
00516 }
00517
00518 static PyObject *
00519 PLyFloat_FromNumeric(PLyDatumToOb *arg, Datum d)
00520 {
00521
00522
00523
00524
00525 Datum f = DirectFunctionCall1(numeric_float8, d);
00526 double x = DatumGetFloat8(f);
00527
00528 return PyFloat_FromDouble(x);
00529 }
00530
00531 static PyObject *
00532 PLyInt_FromInt16(PLyDatumToOb *arg, Datum d)
00533 {
00534 return PyInt_FromLong(DatumGetInt16(d));
00535 }
00536
00537 static PyObject *
00538 PLyInt_FromInt32(PLyDatumToOb *arg, Datum d)
00539 {
00540 return PyInt_FromLong(DatumGetInt32(d));
00541 }
00542
00543 static PyObject *
00544 PLyLong_FromInt64(PLyDatumToOb *arg, Datum d)
00545 {
00546
00547 if (sizeof(int64) > sizeof(long))
00548 return PyLong_FromLongLong(DatumGetInt64(d));
00549 else
00550 return PyLong_FromLong(DatumGetInt64(d));
00551 }
00552
00553 static PyObject *
00554 PLyLong_FromOid(PLyDatumToOb *arg, Datum d)
00555 {
00556 return PyLong_FromUnsignedLong(DatumGetObjectId(d));
00557 }
00558
00559 static PyObject *
00560 PLyBytes_FromBytea(PLyDatumToOb *arg, Datum d)
00561 {
00562 text *txt = DatumGetByteaP(d);
00563 char *str = VARDATA(txt);
00564 size_t size = VARSIZE(txt) - VARHDRSZ;
00565
00566 return PyBytes_FromStringAndSize(str, size);
00567 }
00568
00569 static PyObject *
00570 PLyString_FromDatum(PLyDatumToOb *arg, Datum d)
00571 {
00572 char *x = OutputFunctionCall(&arg->typfunc, d);
00573 PyObject *r = PyString_FromString(x);
00574
00575 pfree(x);
00576 return r;
00577 }
00578
00579 static PyObject *
00580 PLyList_FromArray(PLyDatumToOb *arg, Datum d)
00581 {
00582 ArrayType *array = DatumGetArrayTypeP(d);
00583 PLyDatumToOb *elm = arg->elm;
00584 PyObject *list;
00585 int length;
00586 int lbound;
00587 int i;
00588
00589 if (ARR_NDIM(array) == 0)
00590 return PyList_New(0);
00591
00592 if (ARR_NDIM(array) != 1)
00593 ereport(ERROR,
00594 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00595 errmsg("cannot convert multidimensional array to Python list"),
00596 errdetail("PL/Python only supports one-dimensional arrays.")));
00597
00598 length = ARR_DIMS(array)[0];
00599 lbound = ARR_LBOUND(array)[0];
00600 list = PyList_New(length);
00601 if (list == NULL)
00602 PLy_elog(ERROR, "could not create new Python list");
00603
00604 for (i = 0; i < length; i++)
00605 {
00606 Datum elem;
00607 bool isnull;
00608 int offset;
00609
00610 offset = lbound + i;
00611 elem = array_ref(array, 1, &offset, arg->typlen,
00612 elm->typlen, elm->typbyval, elm->typalign,
00613 &isnull);
00614 if (isnull)
00615 {
00616 Py_INCREF(Py_None);
00617 PyList_SET_ITEM(list, i, Py_None);
00618 }
00619 else
00620 PyList_SET_ITEM(list, i, elm->func(elm, elem));
00621 }
00622
00623 return list;
00624 }
00625
00626
00627
00628
00629
00630
00631
00632 static Datum
00633 PLyObject_ToBool(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
00634 {
00635 Datum rv;
00636
00637 Assert(plrv != Py_None);
00638 rv = BoolGetDatum(PyObject_IsTrue(plrv));
00639
00640 if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN)
00641 domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt);
00642
00643 return rv;
00644 }
00645
00646
00647
00648
00649
00650
00651 static Datum
00652 PLyObject_ToBytea(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
00653 {
00654 PyObject *volatile plrv_so = NULL;
00655 Datum rv;
00656
00657 Assert(plrv != Py_None);
00658
00659 plrv_so = PyObject_Bytes(plrv);
00660 if (!plrv_so)
00661 PLy_elog(ERROR, "could not create bytes representation of Python object");
00662
00663 PG_TRY();
00664 {
00665 char *plrv_sc = PyBytes_AsString(plrv_so);
00666 size_t len = PyBytes_Size(plrv_so);
00667 size_t size = len + VARHDRSZ;
00668 bytea *result = palloc(size);
00669
00670 SET_VARSIZE(result, size);
00671 memcpy(VARDATA(result), plrv_sc, len);
00672 rv = PointerGetDatum(result);
00673 }
00674 PG_CATCH();
00675 {
00676 Py_XDECREF(plrv_so);
00677 PG_RE_THROW();
00678 }
00679 PG_END_TRY();
00680
00681 Py_XDECREF(plrv_so);
00682
00683 if (get_typtype(arg->typoid) == TYPTYPE_DOMAIN)
00684 domain_check(rv, false, arg->typoid, &arg->typfunc.fn_extra, arg->typfunc.fn_mcxt);
00685
00686 return rv;
00687 }
00688
00689
00690
00691
00692
00693
00694
00695 static Datum
00696 PLyObject_ToComposite(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
00697 {
00698 Datum rv;
00699 PLyTypeInfo info;
00700 TupleDesc desc;
00701
00702 if (typmod != -1)
00703 elog(ERROR, "received unnamed record type as input");
00704
00705
00706 MemSet(&info, 0, sizeof(PLyTypeInfo));
00707 PLy_typeinfo_init(&info);
00708
00709 info.is_rowtype = 2;
00710
00711 desc = lookup_rowtype_tupdesc(arg->typoid, arg->typmod);
00712
00713
00714
00715
00716
00717
00718
00719 rv = PLyObject_ToCompositeDatum(&info, desc, plrv);
00720
00721 PLy_typeinfo_dealloc(&info);
00722
00723 return rv;
00724 }
00725
00726
00727
00728
00729
00730
00731 static Datum
00732 PLyObject_ToDatum(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
00733 {
00734 PyObject *volatile plrv_bo = NULL;
00735 Datum rv;
00736
00737 Assert(plrv != Py_None);
00738
00739 if (PyUnicode_Check(plrv))
00740 plrv_bo = PLyUnicode_Bytes(plrv);
00741 else
00742 {
00743 #if PY_MAJOR_VERSION >= 3
00744 PyObject *s = PyObject_Str(plrv);
00745
00746 plrv_bo = PLyUnicode_Bytes(s);
00747 Py_XDECREF(s);
00748 #else
00749 plrv_bo = PyObject_Str(plrv);
00750 #endif
00751 }
00752 if (!plrv_bo)
00753 PLy_elog(ERROR, "could not create string representation of Python object");
00754
00755 PG_TRY();
00756 {
00757 char *plrv_sc = PyBytes_AsString(plrv_bo);
00758 size_t plen = PyBytes_Size(plrv_bo);
00759 size_t slen = strlen(plrv_sc);
00760
00761 if (slen < plen)
00762 ereport(ERROR,
00763 (errcode(ERRCODE_DATATYPE_MISMATCH),
00764 errmsg("could not convert Python object into cstring: Python string representation appears to contain null bytes")));
00765 else if (slen > plen)
00766 elog(ERROR, "could not convert Python object into cstring: Python string longer than reported length");
00767 pg_verifymbstr(plrv_sc, slen, false);
00768 rv = InputFunctionCall(&arg->typfunc,
00769 plrv_sc,
00770 arg->typioparam,
00771 typmod);
00772 }
00773 PG_CATCH();
00774 {
00775 Py_XDECREF(plrv_bo);
00776 PG_RE_THROW();
00777 }
00778 PG_END_TRY();
00779
00780 Py_XDECREF(plrv_bo);
00781
00782 return rv;
00783 }
00784
00785 static Datum
00786 PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
00787 {
00788 ArrayType *array;
00789 int i;
00790 Datum *elems;
00791 bool *nulls;
00792 int len;
00793 int lbs;
00794
00795 Assert(plrv != Py_None);
00796
00797 if (!PySequence_Check(plrv))
00798 PLy_elog(ERROR, "return value of function with array return type is not a Python sequence");
00799
00800 len = PySequence_Length(plrv);
00801 elems = palloc(sizeof(*elems) * len);
00802 nulls = palloc(sizeof(*nulls) * len);
00803
00804 for (i = 0; i < len; i++)
00805 {
00806 PyObject *obj = PySequence_GetItem(plrv, i);
00807
00808 if (obj == Py_None)
00809 nulls[i] = true;
00810 else
00811 {
00812 nulls[i] = false;
00813
00814
00815
00816
00817
00818 elems[i] = arg->elm->func(arg->elm, -1, obj);
00819 }
00820 Py_XDECREF(obj);
00821 }
00822
00823 lbs = 1;
00824 array = construct_md_array(elems, nulls, 1, &len, &lbs,
00825 get_element_type(arg->typoid), arg->elm->typlen, arg->elm->typbyval, arg->elm->typalign);
00826 return PointerGetDatum(array);
00827 }
00828
00829
00830 static Datum
00831 PLyString_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *string)
00832 {
00833 HeapTuple typeTup;
00834
00835 typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(desc->tdtypeid));
00836 if (!HeapTupleIsValid(typeTup))
00837 elog(ERROR, "cache lookup failed for type %u", desc->tdtypeid);
00838
00839 PLy_output_datum_func2(&info->out.d, typeTup);
00840
00841 ReleaseSysCache(typeTup);
00842 ReleaseTupleDesc(desc);
00843
00844 return PLyObject_ToDatum(&info->out.d, info->out.d.typmod, string);
00845 }
00846
00847
00848 static Datum
00849 PLyMapping_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *mapping)
00850 {
00851 HeapTuple tuple;
00852 Datum *values;
00853 bool *nulls;
00854 volatile int i;
00855
00856 Assert(PyMapping_Check(mapping));
00857
00858 if (info->is_rowtype == 2)
00859 PLy_output_tuple_funcs(info, desc);
00860 Assert(info->is_rowtype == 1);
00861
00862
00863 values = palloc(sizeof(Datum) * desc->natts);
00864 nulls = palloc(sizeof(bool) * desc->natts);
00865 for (i = 0; i < desc->natts; ++i)
00866 {
00867 char *key;
00868 PyObject *volatile value;
00869 PLyObToDatum *att;
00870
00871 if (desc->attrs[i]->attisdropped)
00872 {
00873 values[i] = (Datum) 0;
00874 nulls[i] = true;
00875 continue;
00876 }
00877
00878 key = NameStr(desc->attrs[i]->attname);
00879 value = NULL;
00880 att = &info->out.r.atts[i];
00881 PG_TRY();
00882 {
00883 value = PyMapping_GetItemString(mapping, key);
00884 if (value == Py_None)
00885 {
00886 values[i] = (Datum) NULL;
00887 nulls[i] = true;
00888 }
00889 else if (value)
00890 {
00891 values[i] = (att->func) (att, -1, value);
00892 nulls[i] = false;
00893 }
00894 else
00895 ereport(ERROR,
00896 (errcode(ERRCODE_UNDEFINED_COLUMN),
00897 errmsg("key \"%s\" not found in mapping", key),
00898 errhint("To return null in a column, "
00899 "add the value None to the mapping with the key named after the column.")));
00900
00901 Py_XDECREF(value);
00902 value = NULL;
00903 }
00904 PG_CATCH();
00905 {
00906 Py_XDECREF(value);
00907 PG_RE_THROW();
00908 }
00909 PG_END_TRY();
00910 }
00911
00912 tuple = heap_form_tuple(desc, values, nulls);
00913 ReleaseTupleDesc(desc);
00914 pfree(values);
00915 pfree(nulls);
00916
00917 return HeapTupleGetDatum(tuple);
00918 }
00919
00920
00921 static Datum
00922 PLySequence_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *sequence)
00923 {
00924 HeapTuple tuple;
00925 Datum *values;
00926 bool *nulls;
00927 volatile int idx;
00928 volatile int i;
00929
00930 Assert(PySequence_Check(sequence));
00931
00932
00933
00934
00935
00936
00937 idx = 0;
00938 for (i = 0; i < desc->natts; i++)
00939 {
00940 if (!desc->attrs[i]->attisdropped)
00941 idx++;
00942 }
00943 if (PySequence_Length(sequence) != idx)
00944 ereport(ERROR,
00945 (errcode(ERRCODE_DATATYPE_MISMATCH),
00946 errmsg("length of returned sequence did not match number of columns in row")));
00947
00948 if (info->is_rowtype == 2)
00949 PLy_output_tuple_funcs(info, desc);
00950 Assert(info->is_rowtype == 1);
00951
00952
00953 values = palloc(sizeof(Datum) * desc->natts);
00954 nulls = palloc(sizeof(bool) * desc->natts);
00955 idx = 0;
00956 for (i = 0; i < desc->natts; ++i)
00957 {
00958 PyObject *volatile value;
00959 PLyObToDatum *att;
00960
00961 if (desc->attrs[i]->attisdropped)
00962 {
00963 values[i] = (Datum) 0;
00964 nulls[i] = true;
00965 continue;
00966 }
00967
00968 value = NULL;
00969 att = &info->out.r.atts[i];
00970 PG_TRY();
00971 {
00972 value = PySequence_GetItem(sequence, idx);
00973 Assert(value);
00974 if (value == Py_None)
00975 {
00976 values[i] = (Datum) NULL;
00977 nulls[i] = true;
00978 }
00979 else if (value)
00980 {
00981 values[i] = (att->func) (att, -1, value);
00982 nulls[i] = false;
00983 }
00984
00985 Py_XDECREF(value);
00986 value = NULL;
00987 }
00988 PG_CATCH();
00989 {
00990 Py_XDECREF(value);
00991 PG_RE_THROW();
00992 }
00993 PG_END_TRY();
00994
00995 idx++;
00996 }
00997
00998 tuple = heap_form_tuple(desc, values, nulls);
00999 ReleaseTupleDesc(desc);
01000 pfree(values);
01001 pfree(nulls);
01002
01003 return HeapTupleGetDatum(tuple);
01004 }
01005
01006
01007 static Datum
01008 PLyGenericObject_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *object)
01009 {
01010 HeapTuple tuple;
01011 Datum *values;
01012 bool *nulls;
01013 volatile int i;
01014
01015 if (info->is_rowtype == 2)
01016 PLy_output_tuple_funcs(info, desc);
01017 Assert(info->is_rowtype == 1);
01018
01019
01020 values = palloc(sizeof(Datum) * desc->natts);
01021 nulls = palloc(sizeof(bool) * desc->natts);
01022 for (i = 0; i < desc->natts; ++i)
01023 {
01024 char *key;
01025 PyObject *volatile value;
01026 PLyObToDatum *att;
01027
01028 if (desc->attrs[i]->attisdropped)
01029 {
01030 values[i] = (Datum) 0;
01031 nulls[i] = true;
01032 continue;
01033 }
01034
01035 key = NameStr(desc->attrs[i]->attname);
01036 value = NULL;
01037 att = &info->out.r.atts[i];
01038 PG_TRY();
01039 {
01040 value = PyObject_GetAttrString(object, key);
01041 if (value == Py_None)
01042 {
01043 values[i] = (Datum) NULL;
01044 nulls[i] = true;
01045 }
01046 else if (value)
01047 {
01048 values[i] = (att->func) (att, -1, value);
01049 nulls[i] = false;
01050 }
01051 else
01052 ereport(ERROR,
01053 (errcode(ERRCODE_UNDEFINED_COLUMN),
01054 errmsg("attribute \"%s\" does not exist in Python object", key),
01055 errhint("To return null in a column, "
01056 "let the returned object have an attribute named "
01057 "after column with value None.")));
01058
01059 Py_XDECREF(value);
01060 value = NULL;
01061 }
01062 PG_CATCH();
01063 {
01064 Py_XDECREF(value);
01065 PG_RE_THROW();
01066 }
01067 PG_END_TRY();
01068 }
01069
01070 tuple = heap_form_tuple(desc, values, nulls);
01071 ReleaseTupleDesc(desc);
01072 pfree(values);
01073 pfree(nulls);
01074
01075 return HeapTupleGetDatum(tuple);
01076 }
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089 static void
01090 perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
01091 {
01092 fmgr_info_cxt(functionId, finfo, TopMemoryContext);
01093 }