165{
167 volatile int nargs;
172
174 {
175 if (!PySequence_Check(
args) || PyUnicode_Check(
args))
176 {
177 PLy_exception_set(PyExc_TypeError,
"plpy.cursor takes a sequence as its second argument");
178 return NULL;
179 }
180 nargs = PySequence_Length(
args);
181 }
182 else
183 nargs = 0;
184
186
187 if (nargs !=
plan->nargs)
188 {
189 char *sv;
190 PyObject *so = PyObject_Str(
args);
191
192 if (!so)
196 "Expected sequence of %d argument, got %d: %s",
197 "Expected sequence of %d arguments, got %d: %s",
199 plan->nargs, nargs, sv);
200 Py_DECREF(so);
201
202 return NULL;
203 }
204
206 return NULL;
207#if PY_VERSION_HEX < 0x03080000
208 /* Workaround for Python issue 35810; no longer necessary in Python 3.8 */
210#endif
211 cursor->portalname = NULL;
214 "PL/Python cursor context",
216
217 /* Initialize for converting result tuples to Python */
219 RECORDOID, -1,
221
224
226
228 {
232 char *volatile nulls;
234
235 /*
236 * Converted arguments and associated cruft will be in this context,
237 * which is local to our subtransaction.
238 */
240 "PL/Python temporary context",
243
244 if (nargs > 0)
245 {
247 nulls = (
char *)
palloc(nargs *
sizeof(
char));
248 }
249 else
250 {
252 nulls = NULL;
253 }
254
255 for (
j = 0;
j < nargs;
j++)
256 {
258 PyObject *elem;
259
260 elem = PySequence_GetItem(
args,
j);
262 {
263 bool isnull;
264
266 nulls[
j] = isnull ?
'n' :
' ';
267 }
269 {
270 Py_DECREF(elem);
271 }
273 }
274
276
279 if (portal == NULL)
280 elog(
ERROR,
"SPI_cursor_open() failed: %s",
282
284
286
289 }
291 {
293 /* Subtransaction abort will remove the tmpcontext */
295 return NULL;
296 }
298
300 return (PyObject *)
cursor;
301}
static Datum values[MAXATTR]
Assert(PointerIsAligned(start, uint64))
char * MemoryContextStrdup(MemoryContext context, const char *string)
MemoryContext TopMemoryContext
MemoryContext CurTransactionContext
MemoryContext CurrentMemoryContext
void MemoryContextDelete(MemoryContext context)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
#define ALLOCSET_SMALL_SIZES
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
void PLy_exception_set_plural(PyObject *exc, const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
PLyExecutionContext * PLy_current_execution_context(void)
void PLy_spi_subtransaction_commit(MemoryContext oldcontext, ResourceOwner oldowner)
void PLy_spi_subtransaction_abort(MemoryContext oldcontext, ResourceOwner oldowner)
void PLy_spi_subtransaction_begin(MemoryContext oldcontext, ResourceOwner oldowner)
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Datum PLy_output_convert(PLyObToDatum *arg, PyObject *val, bool *isnull)
char * PLyUnicode_AsString(PyObject *unicode)
void PinPortal(Portal portal)
ResourceOwner CurrentResourceOwner
const char * SPI_result_code_string(int code)
Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only)