static PyObject * PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status) { PLyResultObject *result; volatile MemoryContext oldcontext; result = (PLyResultObject *) PLy_result_new(); Py_DECREF(result->status); result->status = PyInt_FromLong(status); if (status > 0 && tuptable == NULL) { Py_DECREF(result->nrows); result->nrows = PyInt_FromLong(rows); } else if (status > 0 && tuptable != NULL) { PLyTypeInfo args; int i; Py_DECREF(result->nrows); result->nrows = PyInt_FromLong(rows); PLy_typeinfo_init(&args); oldcontext = CurrentMemoryContext; PG_TRY(); { if (rows) { Py_DECREF(result->rows); result->rows = PyList_New(rows); PLy_input_tuple_funcs(&args, tuptable->tupdesc); for (i = 0; i < rows; i++) { PyObject *row = PLyDict_FromTuple(&args, tuptable->vals[i], tuptable->tupdesc); PyList_SetItem(result->rows, i, row); } } } PG_CATCH(); { MemoryContextSwitchTo(oldcontext); if (!PyErr_Occurred()) PLy_exception_set(PLy_exc_error, "unrecognized error in PLy_spi_execute_fetch_result"); PLy_typeinfo_dealloc(&args); SPI_freetuptable(tuptable); Py_DECREF(result); return NULL; } PG_END_TRY(); PLy_typeinfo_dealloc(&args); SPI_freetuptable(tuptable); } return (PyObject *) result; }
static PyObject * PLy_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 rows, int status) { PLyResultObject *result; volatile MemoryContext oldcontext; result = (PLyResultObject *) PLy_result_new(); Py_DECREF(result->status); result->status = PyInt_FromLong(status); if (status > 0 && tuptable == NULL) { Py_DECREF(result->nrows); result->nrows = (rows > (uint64) LONG_MAX) ? PyFloat_FromDouble((double) rows) : PyInt_FromLong((long) rows); } else if (status > 0 && tuptable != NULL) { PLyTypeInfo args; MemoryContext cxt; Py_DECREF(result->nrows); result->nrows = (rows > (uint64) LONG_MAX) ? PyFloat_FromDouble((double) rows) : PyInt_FromLong((long) rows); cxt = AllocSetContextCreate(CurrentMemoryContext, "PL/Python temp context", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); PLy_typeinfo_init(&args, cxt); oldcontext = CurrentMemoryContext; PG_TRY(); { MemoryContext oldcontext2; if (rows) { uint64 i; /* * PyList_New() and PyList_SetItem() use Py_ssize_t for list * size and list indices; so we cannot support a result larger * than PY_SSIZE_T_MAX. */ if (rows > (uint64) PY_SSIZE_T_MAX) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("query result has too many rows to fit in a Python list"))); Py_DECREF(result->rows); result->rows = PyList_New(rows); PLy_input_tuple_funcs(&args, tuptable->tupdesc); for (i = 0; i < rows; i++) { PyObject *row = PLyDict_FromTuple(&args, tuptable->vals[i], tuptable->tupdesc); PyList_SetItem(result->rows, i, row); } } /* * Save tuple descriptor for later use by result set metadata * functions. Save it in TopMemoryContext so that it survives * outside of an SPI context. We trust that PLy_result_dealloc() * will clean it up when the time is right. (Do this as late as * possible, to minimize the number of ways the tupdesc could get * leaked due to errors.) */ oldcontext2 = MemoryContextSwitchTo(TopMemoryContext); result->tupdesc = CreateTupleDescCopy(tuptable->tupdesc); MemoryContextSwitchTo(oldcontext2); } PG_CATCH(); { MemoryContextSwitchTo(oldcontext); MemoryContextDelete(cxt); Py_DECREF(result); PG_RE_THROW(); } PG_END_TRY(); MemoryContextDelete(cxt); SPI_freetuptable(tuptable); } return (PyObject *) result; }
static PyObject * PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status) { PLyResultObject *result; volatile MemoryContext oldcontext; result = (PLyResultObject *) PLy_result_new(); Py_DECREF(result->status); result->status = PyInt_FromLong(status); if (status > 0 && tuptable == NULL) { Py_DECREF(result->nrows); result->nrows = PyInt_FromLong(rows); } else if (status > 0 && tuptable != NULL) { PLyTypeInfo args; int i; Py_DECREF(result->nrows); result->nrows = PyInt_FromLong(rows); PLy_typeinfo_init(&args); oldcontext = CurrentMemoryContext; PG_TRY(); { MemoryContext oldcontext2; /* * Save tuple descriptor for later use by result set metadata * functions. Save it in TopMemoryContext so that it survives * outside of an SPI context. We trust that PLy_result_dealloc() * will clean it up when the time is right. */ oldcontext2 = MemoryContextSwitchTo(TopMemoryContext); result->tupdesc = CreateTupleDescCopy(tuptable->tupdesc); MemoryContextSwitchTo(oldcontext2); if (rows) { Py_DECREF(result->rows); result->rows = PyList_New(rows); PLy_input_tuple_funcs(&args, tuptable->tupdesc); for (i = 0; i < rows; i++) { PyObject *row = PLyDict_FromTuple(&args, tuptable->vals[i], tuptable->tupdesc); PyList_SetItem(result->rows, i, row); } } } PG_CATCH(); { MemoryContextSwitchTo(oldcontext); if (!PyErr_Occurred()) PLy_exception_set(PLy_exc_error, "unrecognized error in PLy_spi_execute_fetch_result"); PLy_typeinfo_dealloc(&args); SPI_freetuptable(tuptable); Py_DECREF(result); return NULL; } PG_END_TRY(); PLy_typeinfo_dealloc(&args); SPI_freetuptable(tuptable); } return (PyObject *) result; }
static PyObject * PLy_cursor_fetch(PyObject *self, PyObject *args) { PLyCursorObject *cursor; int count; PLyResultObject *ret; volatile MemoryContext oldcontext; volatile ResourceOwner oldowner; Portal portal; if (!PyArg_ParseTuple(args, "i", &count)) return NULL; cursor = (PLyCursorObject *) self; if (cursor->closed) { PLy_exception_set(PyExc_ValueError, "fetch from a closed cursor"); return NULL; } portal = GetPortalByName(cursor->portalname); if (!PortalIsValid(portal)) { PLy_exception_set(PyExc_ValueError, "iterating a cursor in an aborted subtransaction"); return NULL; } ret = (PLyResultObject *) PLy_result_new(); if (ret == NULL) return NULL; oldcontext = CurrentMemoryContext; oldowner = CurrentResourceOwner; PLy_spi_subtransaction_begin(oldcontext, oldowner); PG_TRY(); { SPI_cursor_fetch(portal, true, count); if (cursor->result.is_rowtype != 1) PLy_input_tuple_funcs(&cursor->result, SPI_tuptable->tupdesc); Py_DECREF(ret->status); ret->status = PyInt_FromLong(SPI_OK_FETCH); Py_DECREF(ret->nrows); ret->nrows = PyInt_FromLong(SPI_processed); if (SPI_processed != 0) { int i; Py_DECREF(ret->rows); ret->rows = PyList_New(SPI_processed); for (i = 0; i < SPI_processed; i++) { PyObject *row = PLyDict_FromTuple(&cursor->result, SPI_tuptable->vals[i], SPI_tuptable->tupdesc); PyList_SetItem(ret->rows, i, row); } } SPI_freetuptable(SPI_tuptable); PLy_spi_subtransaction_commit(oldcontext, oldowner); } PG_CATCH(); { PLy_spi_subtransaction_abort(oldcontext, oldowner); return NULL; } PG_END_TRY(); return (PyObject *) ret; }