mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-22 17:06:33 +03:00
Merge branch 'drop-display-size'
This commit is contained in:
commit
3f20f7934a
1
NEWS
1
NEWS
|
@ -38,6 +38,7 @@ Other changes:
|
||||||
- Dropped deprecated `!register_tstz_w_secs()` (was previously a no-op).
|
- Dropped deprecated `!register_tstz_w_secs()` (was previously a no-op).
|
||||||
- Dropped deprecated `!PersistentConnectionPool`. This pool class was mostly
|
- Dropped deprecated `!PersistentConnectionPool`. This pool class was mostly
|
||||||
designed to interact with Zope. Use `!ZPsycopgDA.pool` instead.
|
designed to interact with Zope. Use `!ZPsycopgDA.pool` instead.
|
||||||
|
- Dropped `!PSYCOPG_DISPLAY_SIZE` build parameter.
|
||||||
- No longer use 2to3 during installation for Python 2 & 3 compatability. All
|
- No longer use 2to3 during installation for Python 2 & 3 compatability. All
|
||||||
source files are now compatible with Python 2 & 3 as is.
|
source files are now compatible with Python 2 & 3 as is.
|
||||||
- The `!psycopg2.test` package is no longer installed by ``python setup.py
|
- The `!psycopg2.test` package is no longer installed by ``python setup.py
|
||||||
|
|
|
@ -216,10 +216,12 @@ introspection etc.
|
||||||
|
|
||||||
.. attribute:: display_size
|
.. attribute:: display_size
|
||||||
|
|
||||||
The actual length of the column in bytes. Obtaining this value is
|
Supposed to be the actual length of the column in bytes. Obtaining
|
||||||
computationally intensive, so it is always `!None` unless the
|
this value is computationally intensive, so it is always `!None`.
|
||||||
:envvar:`PSYCOPG_DISPLAY_SIZE` parameter is set at compile time. See
|
|
||||||
also PQgetlength_.
|
.. versionchanged:: 2.8
|
||||||
|
It was previously possible to obtain this value using a compiler
|
||||||
|
flag at builtin.
|
||||||
|
|
||||||
.. attribute:: internal_size
|
.. attribute:: internal_size
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,7 @@ static const char type_code_doc[] =
|
||||||
|
|
||||||
static const char display_size_doc[] =
|
static const char display_size_doc[] =
|
||||||
"The actual length of the column in bytes.\n\n"
|
"The actual length of the column in bytes.\n\n"
|
||||||
"Obtaining this value is computationally intensive, so it is always None\n"
|
"Obtaining this value is computationally intensive, so it is always None";
|
||||||
"unless the PSYCOPG_DISPLAY_SIZE parameter is set at compile time.";
|
|
||||||
|
|
||||||
static const char internal_size_doc[] =
|
static const char internal_size_doc[] =
|
||||||
"The size in bytes of the column associated to this column on the server.\n\n"
|
"The size in bytes of the column associated to this column on the server.\n\n"
|
||||||
|
|
294
psycopg/pqpath.c
294
psycopg/pqpath.c
|
@ -1229,12 +1229,147 @@ pq_get_last_result(connectionObject *conn)
|
||||||
1 - result from backend (possibly data is ready)
|
1 - result from backend (possibly data is ready)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_get_cast(cursorObject *curs, PGresult *pgres, int i)
|
||||||
|
{
|
||||||
|
/* fill the right cast function by accessing three different dictionaries:
|
||||||
|
- the per-cursor dictionary, if available (can be NULL or None)
|
||||||
|
- the per-connection dictionary (always exists but can be null)
|
||||||
|
- the global dictionary (at module level)
|
||||||
|
if we get no defined cast use the default one */
|
||||||
|
PyObject *type = NULL;
|
||||||
|
PyObject *cast = NULL;
|
||||||
|
PyObject *rv = NULL;
|
||||||
|
|
||||||
|
Oid ftype = PQftype(pgres, i);
|
||||||
|
if (!(type = PyInt_FromLong(ftype))) { goto exit; }
|
||||||
|
|
||||||
|
Dprintf("_pq_fetch_tuples: looking for cast %d:", ftype);
|
||||||
|
if (!(cast = curs_get_cast(curs, type))) { goto exit; }
|
||||||
|
|
||||||
|
/* else if we got binary tuples and if we got a field that
|
||||||
|
is binary use the default cast
|
||||||
|
FIXME: what the hell am I trying to do here? This just can't work..
|
||||||
|
*/
|
||||||
|
if (cast == psyco_default_binary_cast && PQbinaryTuples(pgres)) {
|
||||||
|
Dprintf("_pq_fetch_tuples: Binary cursor and "
|
||||||
|
"binary field: %i using default cast", ftype);
|
||||||
|
cast = psyco_default_cast;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dprintf("_pq_fetch_tuples: using cast at %p for type %d", cast, ftype);
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
Py_INCREF(cast);
|
||||||
|
rv = cast;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
Py_XDECREF(type);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_make_column(connectionObject *conn, PGresult *pgres, int i)
|
||||||
|
{
|
||||||
|
Oid ftype = PQftype(pgres, i);
|
||||||
|
int fsize = PQfsize(pgres, i);
|
||||||
|
int fmod = PQfmod(pgres, i);
|
||||||
|
Oid ftable = PQftable(pgres, i);
|
||||||
|
int ftablecol = PQftablecol(pgres, i);
|
||||||
|
|
||||||
|
columnObject *column = NULL;
|
||||||
|
PyObject *rv = NULL;
|
||||||
|
|
||||||
|
if (!(column = (columnObject *)PyObject_CallObject(
|
||||||
|
(PyObject *)&columnType, NULL))) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fill the type and name fields */
|
||||||
|
{
|
||||||
|
PyObject *tmp;
|
||||||
|
if (!(tmp = PyInt_FromLong(ftype))) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
column->type_code = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
PyObject *tmp;
|
||||||
|
if (!(tmp = conn_text_from_chars(conn, PQfname(pgres, i)))) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
column->name = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* display size is the maximum size of this field result tuples. */
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
column->display_size = Py_None;
|
||||||
|
|
||||||
|
/* size on the backend */
|
||||||
|
if (fmod > 0) {
|
||||||
|
fmod = fmod - sizeof(int);
|
||||||
|
}
|
||||||
|
if (fsize == -1) {
|
||||||
|
if (ftype == NUMERICOID) {
|
||||||
|
PyObject *tmp;
|
||||||
|
if (!(tmp = PyInt_FromLong((fmod >> 16)))) { goto exit; }
|
||||||
|
column->internal_size = tmp;
|
||||||
|
}
|
||||||
|
else { /* If variable length record, return maximum size */
|
||||||
|
PyObject *tmp;
|
||||||
|
if (!(tmp = PyInt_FromLong(fmod))) { goto exit; }
|
||||||
|
column->internal_size = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyObject *tmp;
|
||||||
|
if (!(tmp = PyInt_FromLong(fsize))) { goto exit; }
|
||||||
|
column->internal_size = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* scale and precision */
|
||||||
|
if (ftype == NUMERICOID) {
|
||||||
|
PyObject *tmp;
|
||||||
|
|
||||||
|
if (!(tmp = PyInt_FromLong((fmod >> 16) & 0xFFFF))) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
column->precision = tmp;
|
||||||
|
|
||||||
|
if (!(tmp = PyInt_FromLong(fmod & 0xFFFF))) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
column->scale = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* table_oid, table_column */
|
||||||
|
if (ftable != InvalidOid) {
|
||||||
|
PyObject *tmp;
|
||||||
|
if (!(tmp = PyInt_FromLong((long)ftable))) { goto exit; }
|
||||||
|
column->table_oid = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftablecol > 0) {
|
||||||
|
PyObject *tmp;
|
||||||
|
if (!(tmp = PyInt_FromLong((long)ftablecol))) { goto exit; }
|
||||||
|
column->table_column = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
rv = (PyObject *)column;
|
||||||
|
column = NULL;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
Py_XDECREF(column);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
RAISES_NEG static int
|
RAISES_NEG static int
|
||||||
_pq_fetch_tuples(cursorObject *curs)
|
_pq_fetch_tuples(cursorObject *curs)
|
||||||
{
|
{
|
||||||
int i, *dsize = NULL;
|
int i;
|
||||||
int pgnfields;
|
int pgnfields;
|
||||||
int pgbintuples;
|
|
||||||
int rv = -1;
|
int rv = -1;
|
||||||
PyObject *description = NULL;
|
PyObject *description = NULL;
|
||||||
PyObject *casts = NULL;
|
PyObject *casts = NULL;
|
||||||
|
@ -1244,7 +1379,6 @@ _pq_fetch_tuples(cursorObject *curs)
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
|
|
||||||
pgnfields = PQnfields(curs->pgres);
|
pgnfields = PQnfields(curs->pgres);
|
||||||
pgbintuples = PQbinaryTuples(curs->pgres);
|
|
||||||
|
|
||||||
curs->notuples = 0;
|
curs->notuples = 0;
|
||||||
|
|
||||||
|
@ -1255,158 +1389,31 @@ _pq_fetch_tuples(cursorObject *curs)
|
||||||
if (!(casts = PyTuple_New(pgnfields))) { goto exit; }
|
if (!(casts = PyTuple_New(pgnfields))) { goto exit; }
|
||||||
curs->columns = pgnfields;
|
curs->columns = pgnfields;
|
||||||
|
|
||||||
/* calculate the display size for each column (cpu intensive, can be
|
/* calculate each field's parameters and typecasters */
|
||||||
switched off at configuration time) */
|
|
||||||
#ifdef PSYCOPG_DISPLAY_SIZE
|
|
||||||
if (!(dsize = PyMem_New(int, pgnfields))) {
|
|
||||||
PyErr_NoMemory();
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
|
||||||
if (dsize != NULL) {
|
|
||||||
int j, len;
|
|
||||||
for (i=0; i < pgnfields; i++) {
|
|
||||||
dsize[i] = -1;
|
|
||||||
}
|
|
||||||
for (j = 0; j < curs->rowcount; j++) {
|
|
||||||
for (i = 0; i < pgnfields; i++) {
|
|
||||||
len = PQgetlength(curs->pgres, j, i);
|
|
||||||
if (len > dsize[i]) dsize[i] = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Py_END_ALLOW_THREADS;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* calculate various parameters and typecasters */
|
|
||||||
for (i = 0; i < pgnfields; i++) {
|
for (i = 0; i < pgnfields; i++) {
|
||||||
Oid ftype = PQftype(curs->pgres, i);
|
PyObject *column = NULL;
|
||||||
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;
|
|
||||||
PyObject *cast = NULL;
|
PyObject *cast = NULL;
|
||||||
|
|
||||||
if (!(column = (columnObject *)PyObject_CallObject(
|
if (!(column = _make_column(curs->conn, curs->pgres, i))) {
|
||||||
(PyObject *)&columnType, NULL))) {
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fill the right cast function by accessing three different dictionaries:
|
|
||||||
- the per-cursor dictionary, if available (can be NULL or None)
|
|
||||||
- the per-connection dictionary (always exists but can be null)
|
|
||||||
- the global dictionary (at module level)
|
|
||||||
if we get no defined cast use the default one */
|
|
||||||
|
|
||||||
if (!(type = PyInt_FromLong(ftype))) {
|
|
||||||
goto err_for;
|
|
||||||
}
|
|
||||||
Dprintf("_pq_fetch_tuples: looking for cast %d:", ftype);
|
|
||||||
cast = curs_get_cast(curs, type);
|
|
||||||
|
|
||||||
/* else if we got binary tuples and if we got a field that
|
|
||||||
is binary use the default cast
|
|
||||||
FIXME: what the hell am I trying to do here? This just can't work..
|
|
||||||
*/
|
|
||||||
if (pgbintuples && cast == psyco_default_binary_cast) {
|
|
||||||
Dprintf("_pq_fetch_tuples: Binary cursor and "
|
|
||||||
"binary field: %i using default cast",
|
|
||||||
PQftype(curs->pgres,i));
|
|
||||||
cast = psyco_default_cast;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dprintf("_pq_fetch_tuples: using cast at %p for type %d",
|
|
||||||
cast, PQftype(curs->pgres,i));
|
|
||||||
Py_INCREF(cast);
|
|
||||||
PyTuple_SET_ITEM(casts, i, cast);
|
|
||||||
|
|
||||||
/* 1/ fill the other fields */
|
|
||||||
{
|
|
||||||
PyObject *tmp;
|
|
||||||
if (!(tmp = conn_text_from_chars(
|
|
||||||
curs->conn, PQfname(curs->pgres, i)))) {
|
|
||||||
goto err_for;
|
|
||||||
}
|
|
||||||
column->name = tmp;
|
|
||||||
}
|
|
||||||
column->type_code = type;
|
|
||||||
type = NULL;
|
|
||||||
|
|
||||||
/* 2/ display size is the maximum size of this field result tuples. */
|
|
||||||
if (dsize && dsize[i] >= 0) {
|
|
||||||
PyObject *tmp;
|
|
||||||
if (!(tmp = PyInt_FromLong(dsize[i]))) { goto err_for; }
|
|
||||||
column->display_size = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 3/ size on the backend */
|
|
||||||
if (fmod > 0) fmod = fmod - sizeof(int);
|
|
||||||
if (fsize == -1) {
|
|
||||||
if (ftype == NUMERICOID) {
|
|
||||||
PyObject *tmp;
|
|
||||||
if (!(tmp = PyInt_FromLong((fmod >> 16)))) { goto err_for; }
|
|
||||||
column->internal_size = tmp;
|
|
||||||
}
|
|
||||||
else { /* If variable length record, return maximum size */
|
|
||||||
PyObject *tmp;
|
|
||||||
if (!(tmp = PyInt_FromLong(fmod))) { goto err_for; }
|
|
||||||
column->internal_size = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PyObject *tmp;
|
|
||||||
if (!(tmp = PyInt_FromLong(fsize))) { goto err_for; }
|
|
||||||
column->internal_size = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 4,5/ scale and precision */
|
|
||||||
if (ftype == NUMERICOID) {
|
|
||||||
PyObject *tmp;
|
|
||||||
|
|
||||||
if (!(tmp = PyInt_FromLong((fmod >> 16) & 0xFFFF))) {
|
|
||||||
goto err_for;
|
|
||||||
}
|
|
||||||
column->precision = tmp;
|
|
||||||
|
|
||||||
if (!(tmp = PyInt_FromLong(fmod & 0xFFFF))) {
|
|
||||||
goto err_for;
|
|
||||||
}
|
|
||||||
column->scale = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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);
|
PyTuple_SET_ITEM(description, i, (PyObject *)column);
|
||||||
column = NULL;
|
|
||||||
|
|
||||||
continue;
|
if (!(cast = _get_cast(curs, curs->pgres, i))) {
|
||||||
|
goto exit;
|
||||||
err_for:
|
}
|
||||||
Py_XDECREF(type);
|
PyTuple_SET_ITEM(casts, i, cast);
|
||||||
Py_XDECREF(column);
|
|
||||||
goto exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
curs->description = description; description = NULL;
|
curs->description = description;
|
||||||
curs->casts = casts; casts = NULL;
|
description = NULL;
|
||||||
|
|
||||||
|
curs->casts = casts;
|
||||||
|
casts = NULL;
|
||||||
|
|
||||||
rv = 0;
|
rv = 0;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
PyMem_Free(dsize);
|
|
||||||
Py_XDECREF(description);
|
Py_XDECREF(description);
|
||||||
Py_XDECREF(casts);
|
Py_XDECREF(casts);
|
||||||
|
|
||||||
|
@ -1417,6 +1424,7 @@ exit:
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_read_rowcount(cursorObject *curs)
|
_read_rowcount(cursorObject *curs)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
[build_ext]
|
[build_ext]
|
||||||
define=
|
|
||||||
|
|
||||||
# PSYCOPG_DISPLAY_SIZE enable display size calculation (a little slower)
|
|
||||||
# HAVE_PQFREEMEM should be defined on PostgreSQL >= 7.4
|
|
||||||
# PSYCOPG_DEBUG can be added to enable verbose debug information
|
# PSYCOPG_DEBUG can be added to enable verbose debug information
|
||||||
|
define=
|
||||||
|
|
||||||
# "pg_config" is required to locate PostgreSQL headers and libraries needed to
|
# "pg_config" is required to locate PostgreSQL headers and libraries needed to
|
||||||
# build psycopg2. If pg_config is not in the path or is installed under a
|
# build psycopg2. If pg_config is not in the path or is installed under a
|
||||||
|
|
Loading…
Reference in New Issue
Block a user