2011-12-18 14:14:16 -05:00
|
|
|
/*
|
|
|
|
|
* the PLyResult class
|
|
|
|
|
*
|
|
|
|
|
* src/pl/plpython/plpy_resultobject.c
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
2012-04-15 13:23:08 -04:00
|
|
|
#include "plpy_elog.h"
|
2019-11-24 21:38:57 -05:00
|
|
|
#include "plpy_resultobject.h"
|
2025-04-27 11:43:02 -04:00
|
|
|
#include "plpy_util.h"
|
2011-12-18 14:14:16 -05:00
|
|
|
|
2025-03-12 03:49:37 -04:00
|
|
|
static void PLy_result_dealloc(PLyResultObject *self);
|
2012-01-30 14:38:52 -05:00
|
|
|
static PyObject *PLy_result_colnames(PyObject *self, PyObject *unused);
|
|
|
|
|
static PyObject *PLy_result_coltypes(PyObject *self, PyObject *unused);
|
|
|
|
|
static PyObject *PLy_result_coltypmods(PyObject *self, PyObject *unused);
|
2011-12-29 15:55:49 -05:00
|
|
|
static PyObject *PLy_result_nrows(PyObject *self, PyObject *args);
|
|
|
|
|
static PyObject *PLy_result_status(PyObject *self, PyObject *args);
|
|
|
|
|
static Py_ssize_t PLy_result_length(PyObject *arg);
|
|
|
|
|
static PyObject *PLy_result_item(PyObject *arg, Py_ssize_t idx);
|
2013-02-03 00:31:01 -05:00
|
|
|
static PyObject *PLy_result_str(PyObject *arg);
|
2012-05-10 13:38:17 -04:00
|
|
|
static PyObject *PLy_result_subscript(PyObject *arg, PyObject *item);
|
2023-04-13 13:15:20 -04:00
|
|
|
static int PLy_result_ass_subscript(PyObject *arg, PyObject *item, PyObject *value);
|
2011-12-18 14:14:16 -05:00
|
|
|
|
2020-05-21 11:31:16 -04:00
|
|
|
static char PLy_result_doc[] = "Results of a PostgreSQL query";
|
2011-12-18 14:14:16 -05:00
|
|
|
|
|
|
|
|
static PyMethodDef PLy_result_methods[] = {
|
2012-01-30 14:38:52 -05:00
|
|
|
{"colnames", PLy_result_colnames, METH_NOARGS, NULL},
|
|
|
|
|
{"coltypes", PLy_result_coltypes, METH_NOARGS, NULL},
|
|
|
|
|
{"coltypmods", PLy_result_coltypmods, METH_NOARGS, NULL},
|
2011-12-18 14:14:16 -05:00
|
|
|
{"nrows", PLy_result_nrows, METH_VARARGS, NULL},
|
|
|
|
|
{"status", PLy_result_status, METH_VARARGS, NULL},
|
|
|
|
|
{NULL, NULL, 0, NULL}
|
|
|
|
|
};
|
|
|
|
|
|
2025-03-12 03:49:37 -04:00
|
|
|
static PyType_Slot PLyResult_slots[] =
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
Py_tp_dealloc, PLy_result_dealloc
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Py_sq_length, PLy_result_length
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Py_sq_item, PLy_result_item
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Py_mp_length, PLy_result_length
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Py_mp_subscript, PLy_result_subscript
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Py_mp_ass_subscript, PLy_result_ass_subscript
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Py_tp_str, PLy_result_str
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Py_tp_doc, (char *) PLy_result_doc
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Py_tp_methods, PLy_result_methods
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
0, NULL
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static PyType_Spec PLyResult_spec =
|
|
|
|
|
{
|
|
|
|
|
.name = "PLyResult",
|
|
|
|
|
.basicsize = sizeof(PLyResultObject),
|
|
|
|
|
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
|
|
|
|
.slots = PLyResult_slots,
|
2011-12-18 14:14:16 -05:00
|
|
|
};
|
|
|
|
|
|
2025-03-12 03:49:37 -04:00
|
|
|
static PyTypeObject *PLy_ResultType;
|
|
|
|
|
|
2011-12-18 14:14:16 -05:00
|
|
|
void
|
|
|
|
|
PLy_result_init_type(void)
|
|
|
|
|
{
|
2025-03-12 03:49:37 -04:00
|
|
|
PLy_ResultType = (PyTypeObject *) PyType_FromSpec(&PLyResult_spec);
|
|
|
|
|
if (!PLy_ResultType)
|
2011-12-18 14:14:16 -05:00
|
|
|
elog(ERROR, "could not initialize PLy_ResultType");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyObject *
|
|
|
|
|
PLy_result_new(void)
|
|
|
|
|
{
|
|
|
|
|
PLyResultObject *ob;
|
|
|
|
|
|
2025-03-12 03:49:37 -04:00
|
|
|
if ((ob = PyObject_New(PLyResultObject, PLy_ResultType)) == NULL)
|
2011-12-18 14:14:16 -05:00
|
|
|
return NULL;
|
2025-03-12 03:49:37 -04:00
|
|
|
#if PY_VERSION_HEX < 0x03080000
|
|
|
|
|
/* Workaround for Python issue 35810; no longer necessary in Python 3.8 */
|
|
|
|
|
Py_INCREF(PLy_ResultType);
|
|
|
|
|
#endif
|
2011-12-18 14:14:16 -05:00
|
|
|
|
|
|
|
|
/* ob->tuples = NULL; */
|
|
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
|
ob->status = Py_None;
|
2022-03-07 21:30:28 -05:00
|
|
|
ob->nrows = PyLong_FromLong(-1);
|
2011-12-18 14:14:16 -05:00
|
|
|
ob->rows = PyList_New(0);
|
2012-01-30 14:38:52 -05:00
|
|
|
ob->tupdesc = NULL;
|
2017-10-31 10:49:36 -04:00
|
|
|
if (!ob->rows)
|
|
|
|
|
{
|
|
|
|
|
Py_DECREF(ob);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2011-12-18 14:14:16 -05:00
|
|
|
|
|
|
|
|
return (PyObject *) ob;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2025-03-12 03:49:37 -04:00
|
|
|
PLy_result_dealloc(PLyResultObject *self)
|
2011-12-18 14:14:16 -05:00
|
|
|
{
|
2025-03-12 03:49:37 -04:00
|
|
|
#if PY_VERSION_HEX >= 0x03080000
|
|
|
|
|
PyTypeObject *tp = Py_TYPE(self);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
Py_XDECREF(self->nrows);
|
|
|
|
|
Py_XDECREF(self->rows);
|
|
|
|
|
Py_XDECREF(self->status);
|
|
|
|
|
if (self->tupdesc)
|
2012-01-30 14:38:52 -05:00
|
|
|
{
|
2025-03-12 03:49:37 -04:00
|
|
|
FreeTupleDesc(self->tupdesc);
|
|
|
|
|
self->tupdesc = NULL;
|
2012-01-30 14:38:52 -05:00
|
|
|
}
|
2011-12-18 14:14:16 -05:00
|
|
|
|
2025-03-12 03:49:37 -04:00
|
|
|
PyObject_Free(self);
|
|
|
|
|
#if PY_VERSION_HEX >= 0x03080000
|
|
|
|
|
/* This was not needed before Python 3.8 (Python issue 35810) */
|
|
|
|
|
Py_DECREF(tp);
|
|
|
|
|
#endif
|
2011-12-18 14:14:16 -05:00
|
|
|
}
|
|
|
|
|
|
2012-01-30 14:38:52 -05:00
|
|
|
static PyObject *
|
|
|
|
|
PLy_result_colnames(PyObject *self, PyObject *unused)
|
|
|
|
|
{
|
|
|
|
|
PLyResultObject *ob = (PLyResultObject *) self;
|
|
|
|
|
PyObject *list;
|
|
|
|
|
int i;
|
|
|
|
|
|
2012-04-15 13:23:08 -04:00
|
|
|
if (!ob->tupdesc)
|
|
|
|
|
{
|
|
|
|
|
PLy_exception_set(PLy_exc_error, "command did not produce a result set");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-30 14:38:52 -05:00
|
|
|
list = PyList_New(ob->tupdesc->natts);
|
2017-10-31 10:49:36 -04:00
|
|
|
if (!list)
|
|
|
|
|
return NULL;
|
2012-01-30 14:38:52 -05:00
|
|
|
for (i = 0; i < ob->tupdesc->natts; i++)
|
2017-08-20 14:19:07 -04:00
|
|
|
{
|
|
|
|
|
Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
|
|
|
|
|
|
2025-03-12 03:49:37 -04:00
|
|
|
PyList_SetItem(list, i, PLyUnicode_FromString(NameStr(attr->attname)));
|
2017-08-20 14:19:07 -04:00
|
|
|
}
|
2012-01-30 14:38:52 -05:00
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
PLy_result_coltypes(PyObject *self, PyObject *unused)
|
|
|
|
|
{
|
|
|
|
|
PLyResultObject *ob = (PLyResultObject *) self;
|
|
|
|
|
PyObject *list;
|
|
|
|
|
int i;
|
|
|
|
|
|
2012-04-15 13:23:08 -04:00
|
|
|
if (!ob->tupdesc)
|
|
|
|
|
{
|
|
|
|
|
PLy_exception_set(PLy_exc_error, "command did not produce a result set");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-30 14:38:52 -05:00
|
|
|
list = PyList_New(ob->tupdesc->natts);
|
2017-10-31 10:49:36 -04:00
|
|
|
if (!list)
|
|
|
|
|
return NULL;
|
2012-01-30 14:38:52 -05:00
|
|
|
for (i = 0; i < ob->tupdesc->natts; i++)
|
2017-08-20 14:19:07 -04:00
|
|
|
{
|
|
|
|
|
Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
|
|
|
|
|
|
2025-03-12 03:49:37 -04:00
|
|
|
PyList_SetItem(list, i, PyLong_FromLong(attr->atttypid));
|
2017-08-20 14:19:07 -04:00
|
|
|
}
|
2012-01-30 14:38:52 -05:00
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
PLy_result_coltypmods(PyObject *self, PyObject *unused)
|
|
|
|
|
{
|
|
|
|
|
PLyResultObject *ob = (PLyResultObject *) self;
|
|
|
|
|
PyObject *list;
|
|
|
|
|
int i;
|
|
|
|
|
|
2012-04-15 13:23:08 -04:00
|
|
|
if (!ob->tupdesc)
|
|
|
|
|
{
|
|
|
|
|
PLy_exception_set(PLy_exc_error, "command did not produce a result set");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-30 14:38:52 -05:00
|
|
|
list = PyList_New(ob->tupdesc->natts);
|
2017-10-31 10:49:36 -04:00
|
|
|
if (!list)
|
|
|
|
|
return NULL;
|
2012-01-30 14:38:52 -05:00
|
|
|
for (i = 0; i < ob->tupdesc->natts; i++)
|
2017-08-20 14:19:07 -04:00
|
|
|
{
|
|
|
|
|
Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
|
|
|
|
|
|
2025-03-12 03:49:37 -04:00
|
|
|
PyList_SetItem(list, i, PyLong_FromLong(attr->atttypmod));
|
2017-08-20 14:19:07 -04:00
|
|
|
}
|
2012-01-30 14:38:52 -05:00
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-18 14:14:16 -05:00
|
|
|
static PyObject *
|
|
|
|
|
PLy_result_nrows(PyObject *self, PyObject *args)
|
|
|
|
|
{
|
|
|
|
|
PLyResultObject *ob = (PLyResultObject *) self;
|
|
|
|
|
|
|
|
|
|
Py_INCREF(ob->nrows);
|
|
|
|
|
return ob->nrows;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
PLy_result_status(PyObject *self, PyObject *args)
|
|
|
|
|
{
|
|
|
|
|
PLyResultObject *ob = (PLyResultObject *) self;
|
|
|
|
|
|
|
|
|
|
Py_INCREF(ob->status);
|
|
|
|
|
return ob->status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Py_ssize_t
|
|
|
|
|
PLy_result_length(PyObject *arg)
|
|
|
|
|
{
|
|
|
|
|
PLyResultObject *ob = (PLyResultObject *) arg;
|
|
|
|
|
|
|
|
|
|
return PyList_Size(ob->rows);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
PLy_result_item(PyObject *arg, Py_ssize_t idx)
|
|
|
|
|
{
|
|
|
|
|
PyObject *rv;
|
|
|
|
|
PLyResultObject *ob = (PLyResultObject *) arg;
|
|
|
|
|
|
|
|
|
|
rv = PyList_GetItem(ob->rows, idx);
|
|
|
|
|
if (rv != NULL)
|
|
|
|
|
Py_INCREF(rv);
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-03 00:31:01 -05:00
|
|
|
static PyObject *
|
|
|
|
|
PLy_result_str(PyObject *arg)
|
|
|
|
|
{
|
|
|
|
|
PLyResultObject *ob = (PLyResultObject *) arg;
|
|
|
|
|
|
|
|
|
|
return PyUnicode_FromFormat("<%s status=%S nrows=%S rows=%S>",
|
2025-03-12 03:49:37 -04:00
|
|
|
"PLyResult",
|
2013-02-03 00:31:01 -05:00
|
|
|
ob->status,
|
|
|
|
|
ob->nrows,
|
|
|
|
|
ob->rows);
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-10 13:38:17 -04:00
|
|
|
static PyObject *
|
|
|
|
|
PLy_result_subscript(PyObject *arg, PyObject *item)
|
|
|
|
|
{
|
|
|
|
|
PLyResultObject *ob = (PLyResultObject *) arg;
|
|
|
|
|
|
|
|
|
|
return PyObject_GetItem(ob->rows, item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
PLy_result_ass_subscript(PyObject *arg, PyObject *item, PyObject *value)
|
|
|
|
|
{
|
|
|
|
|
PLyResultObject *ob = (PLyResultObject *) arg;
|
|
|
|
|
|
|
|
|
|
return PyObject_SetItem(ob->rows, item, value);
|
|
|
|
|
}
|