mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 00:02:46 -05:00
Using the Python Limited API would allow building PL/Python against any Python 3.x version and using another Python 3.x version at run time. This commit does not activate that, but it prepares the code to only use APIs supported by the Limited API. Implementation details: - Convert static types to heap types (https://docs.python.org/3/howto/isolating-extensions.html#heap-types). - Replace PyRun_String() with component functions. - Replace PyList_SET_ITEM() with PyList_SetItem(). Reviewed-by: Jakob Egger <jakob@eggerapps.at> Discussion: https://www.postgresql.org/message-id/flat/ee410de1-1e0b-4770-b125-eeefd4726a24@eisentraut.org
273 lines
5.6 KiB
C
273 lines
5.6 KiB
C
/*
|
|
* the PLyResult class
|
|
*
|
|
* src/pl/plpython/plpy_resultobject.c
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "plpy_elog.h"
|
|
#include "plpy_resultobject.h"
|
|
#include "plpython.h"
|
|
|
|
static void PLy_result_dealloc(PLyResultObject *self);
|
|
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);
|
|
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);
|
|
static PyObject *PLy_result_str(PyObject *arg);
|
|
static PyObject *PLy_result_subscript(PyObject *arg, PyObject *item);
|
|
static int PLy_result_ass_subscript(PyObject *arg, PyObject *item, PyObject *value);
|
|
|
|
static char PLy_result_doc[] = "Results of a PostgreSQL query";
|
|
|
|
static PyMethodDef PLy_result_methods[] = {
|
|
{"colnames", PLy_result_colnames, METH_NOARGS, NULL},
|
|
{"coltypes", PLy_result_coltypes, METH_NOARGS, NULL},
|
|
{"coltypmods", PLy_result_coltypmods, METH_NOARGS, NULL},
|
|
{"nrows", PLy_result_nrows, METH_VARARGS, NULL},
|
|
{"status", PLy_result_status, METH_VARARGS, NULL},
|
|
{NULL, NULL, 0, NULL}
|
|
};
|
|
|
|
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,
|
|
};
|
|
|
|
static PyTypeObject *PLy_ResultType;
|
|
|
|
void
|
|
PLy_result_init_type(void)
|
|
{
|
|
PLy_ResultType = (PyTypeObject *) PyType_FromSpec(&PLyResult_spec);
|
|
if (!PLy_ResultType)
|
|
elog(ERROR, "could not initialize PLy_ResultType");
|
|
}
|
|
|
|
PyObject *
|
|
PLy_result_new(void)
|
|
{
|
|
PLyResultObject *ob;
|
|
|
|
if ((ob = PyObject_New(PLyResultObject, PLy_ResultType)) == NULL)
|
|
return NULL;
|
|
|
|
/* ob->tuples = NULL; */
|
|
|
|
Py_INCREF(Py_None);
|
|
ob->status = Py_None;
|
|
ob->nrows = PyLong_FromLong(-1);
|
|
ob->rows = PyList_New(0);
|
|
ob->tupdesc = NULL;
|
|
if (!ob->rows)
|
|
{
|
|
Py_DECREF(ob);
|
|
return NULL;
|
|
}
|
|
|
|
return (PyObject *) ob;
|
|
}
|
|
|
|
static void
|
|
PLy_result_dealloc(PLyResultObject *self)
|
|
{
|
|
PyTypeObject *tp = Py_TYPE(self);
|
|
|
|
Py_XDECREF(self->nrows);
|
|
Py_XDECREF(self->rows);
|
|
Py_XDECREF(self->status);
|
|
if (self->tupdesc)
|
|
{
|
|
FreeTupleDesc(self->tupdesc);
|
|
self->tupdesc = NULL;
|
|
}
|
|
|
|
PyObject_Free(self);
|
|
Py_DECREF(tp);
|
|
}
|
|
|
|
static PyObject *
|
|
PLy_result_colnames(PyObject *self, PyObject *unused)
|
|
{
|
|
PLyResultObject *ob = (PLyResultObject *) self;
|
|
PyObject *list;
|
|
int i;
|
|
|
|
if (!ob->tupdesc)
|
|
{
|
|
PLy_exception_set(PLy_exc_error, "command did not produce a result set");
|
|
return NULL;
|
|
}
|
|
|
|
list = PyList_New(ob->tupdesc->natts);
|
|
if (!list)
|
|
return NULL;
|
|
for (i = 0; i < ob->tupdesc->natts; i++)
|
|
{
|
|
Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
|
|
|
|
PyList_SetItem(list, i, PLyUnicode_FromString(NameStr(attr->attname)));
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
static PyObject *
|
|
PLy_result_coltypes(PyObject *self, PyObject *unused)
|
|
{
|
|
PLyResultObject *ob = (PLyResultObject *) self;
|
|
PyObject *list;
|
|
int i;
|
|
|
|
if (!ob->tupdesc)
|
|
{
|
|
PLy_exception_set(PLy_exc_error, "command did not produce a result set");
|
|
return NULL;
|
|
}
|
|
|
|
list = PyList_New(ob->tupdesc->natts);
|
|
if (!list)
|
|
return NULL;
|
|
for (i = 0; i < ob->tupdesc->natts; i++)
|
|
{
|
|
Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
|
|
|
|
PyList_SetItem(list, i, PyLong_FromLong(attr->atttypid));
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
static PyObject *
|
|
PLy_result_coltypmods(PyObject *self, PyObject *unused)
|
|
{
|
|
PLyResultObject *ob = (PLyResultObject *) self;
|
|
PyObject *list;
|
|
int i;
|
|
|
|
if (!ob->tupdesc)
|
|
{
|
|
PLy_exception_set(PLy_exc_error, "command did not produce a result set");
|
|
return NULL;
|
|
}
|
|
|
|
list = PyList_New(ob->tupdesc->natts);
|
|
if (!list)
|
|
return NULL;
|
|
for (i = 0; i < ob->tupdesc->natts; i++)
|
|
{
|
|
Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
|
|
|
|
PyList_SetItem(list, i, PyLong_FromLong(attr->atttypmod));
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
static PyObject *
|
|
PLy_result_str(PyObject *arg)
|
|
{
|
|
PLyResultObject *ob = (PLyResultObject *) arg;
|
|
|
|
return PyUnicode_FromFormat("<%s status=%S nrows=%S rows=%S>",
|
|
"PLyResult",
|
|
ob->status,
|
|
ob->nrows,
|
|
ob->rows);
|
|
}
|
|
|
|
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);
|
|
}
|