mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-01-31 09:24:07 +03:00
parent
b3b225a9da
commit
f99a8de6d0
|
@ -39,6 +39,10 @@ typedef struct {
|
|||
PyObject *scale;
|
||||
PyObject *null_ok;
|
||||
|
||||
/* Extensions to the DBAPI */
|
||||
PyObject *table_oid;
|
||||
PyObject *table_column;
|
||||
|
||||
} columnObject;
|
||||
|
||||
#endif /* PSYCOPG_COLUMN_H */
|
||||
|
|
|
@ -62,7 +62,15 @@ static const char scale_doc[] =
|
|||
"None for other types.";
|
||||
|
||||
static const char null_ok_doc[] =
|
||||
"Always none.\n\n";
|
||||
"Always none.";
|
||||
|
||||
static const char table_oid_doc[] =
|
||||
"The OID of the table from which the column was fetched.\n\n"
|
||||
"None if not available";
|
||||
|
||||
static const char table_column_doc[] =
|
||||
"The number (within its table) of the column making up the result\n\n"
|
||||
"None if not available. Note that PostgreSQL column numbers start at 1";
|
||||
|
||||
|
||||
static PyMemberDef column_members[] = {
|
||||
|
@ -73,6 +81,8 @@ static PyMemberDef column_members[] = {
|
|||
{ "precision", T_OBJECT, offsetof(columnObject, precision), READONLY, (char *)precision_doc },
|
||||
{ "scale", T_OBJECT, offsetof(columnObject, scale), READONLY, (char *)scale_doc },
|
||||
{ "null_ok", T_OBJECT, offsetof(columnObject, null_ok), READONLY, (char *)null_ok_doc },
|
||||
{ "table_oid", T_OBJECT, offsetof(columnObject, table_oid), READONLY, (char *)table_oid_doc },
|
||||
{ "table_column", T_OBJECT, offsetof(columnObject, table_column), READONLY, (char *)table_column_doc },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -89,12 +99,12 @@ column_init(columnObject *self, PyObject *args, PyObject *kwargs)
|
|||
{
|
||||
static char *kwlist[] = {
|
||||
"name", "type_code", "display_size", "internal_size",
|
||||
"precision", "scale", "null_ok", NULL};
|
||||
"precision", "scale", "null_ok", "table_oid", "table_column", NULL};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOOOOO", kwlist,
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOOOOOOO", kwlist,
|
||||
&self->name, &self->type_code, &self->display_size,
|
||||
&self->internal_size, &self->precision, &self->scale,
|
||||
&self->null_ok)) {
|
||||
&self->null_ok, &self->table_oid, &self->table_column)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -112,6 +122,8 @@ column_dealloc(columnObject *self)
|
|||
Py_CLEAR(self->precision);
|
||||
Py_CLEAR(self->scale);
|
||||
Py_CLEAR(self->null_ok);
|
||||
Py_CLEAR(self->table_oid);
|
||||
Py_CLEAR(self->table_column);
|
||||
|
||||
Py_TYPE(self)->tp_free((PyObject *)self);
|
||||
}
|
||||
|
@ -294,6 +306,16 @@ column_setstate(columnObject *self, PyObject *state)
|
|||
self->null_ok = PyTuple_GET_ITEM(state, 6);
|
||||
Py_INCREF(self->null_ok);
|
||||
}
|
||||
if (size > 7) {
|
||||
Py_CLEAR(self->table_oid);
|
||||
self->table_oid = PyTuple_GET_ITEM(state, 7);
|
||||
Py_INCREF(self->table_oid);
|
||||
}
|
||||
if (size > 8) {
|
||||
Py_CLEAR(self->table_column);
|
||||
self->table_column = PyTuple_GET_ITEM(state, 8);
|
||||
Py_INCREF(self->table_column);
|
||||
}
|
||||
|
||||
exit:
|
||||
rv = Py_None;
|
||||
|
|
|
@ -1207,6 +1207,8 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
Oid ftype = PQftype(curs->pgres, i);
|
||||
int fsize = PQfsize(curs->pgres, i);
|
||||
int fmod = PQfmod(curs->pgres, i);
|
||||
Oid ftable = PQftable(curs->pgres, i);
|
||||
int ftablecol = PQftablecol(curs->pgres, i);
|
||||
|
||||
columnObject *column = NULL;
|
||||
PyObject *type = NULL;
|
||||
|
@ -1299,7 +1301,18 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
column->scale = tmp;
|
||||
}
|
||||
|
||||
/* 6/ FIXME: null_ok??? */
|
||||
/* table_oid, table_column */
|
||||
if (ftable != InvalidOid) {
|
||||
PyObject *tmp;
|
||||
if (!(tmp = PyInt_FromLong((long)ftable))) { goto err_for; }
|
||||
column->table_oid = tmp;
|
||||
}
|
||||
|
||||
if (ftablecol > 0) {
|
||||
PyObject *tmp;
|
||||
if (!(tmp = PyInt_FromLong((long)ftablecol))) { goto err_for; }
|
||||
column->table_column = tmp;
|
||||
}
|
||||
|
||||
PyTuple_SET_ITEM(description, i, (PyObject *)column);
|
||||
column = NULL;
|
||||
|
|
|
@ -377,7 +377,7 @@ class CursorTests(ConnectingTestCase):
|
|||
for i, rec in enumerate(curs):
|
||||
self.assertEqual(i + 1, curs.rownumber)
|
||||
|
||||
def test_namedtuple_description(self):
|
||||
def test_description_attribs(self):
|
||||
curs = self.conn.cursor()
|
||||
curs.execute("""select
|
||||
3.14::decimal(10,2) as pi,
|
||||
|
@ -412,6 +412,27 @@ class CursorTests(ConnectingTestCase):
|
|||
self.assertEqual(c.precision, None)
|
||||
self.assertEqual(c.scale, None)
|
||||
|
||||
def test_description_extra_attribs(self):
|
||||
curs = self.conn.cursor()
|
||||
curs.execute("""
|
||||
create table testcol (
|
||||
pi decimal(10,2),
|
||||
hi text)
|
||||
""")
|
||||
curs.execute("select oid from pg_class where relname = %s", ('testcol',))
|
||||
oid = curs.fetchone()[0]
|
||||
|
||||
curs.execute("insert into testcol values (3.14, 'hello')")
|
||||
curs.execute("select hi, pi, 42 from testcol")
|
||||
self.assertEqual(curs.description[0].table_oid, oid)
|
||||
self.assertEqual(curs.description[0].table_column, 2)
|
||||
|
||||
self.assertEqual(curs.description[1].table_oid, oid)
|
||||
self.assertEqual(curs.description[1].table_column, 1)
|
||||
|
||||
self.assertEqual(curs.description[2].table_oid, None)
|
||||
self.assertEqual(curs.description[2].table_column, None)
|
||||
|
||||
def test_pickle_description(self):
|
||||
curs = self.conn.cursor()
|
||||
curs.execute('SELECT 1 AS foo')
|
||||
|
|
Loading…
Reference in New Issue
Block a user