mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-22 08:56:34 +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 `!PersistentConnectionPool`. This pool class was mostly
|
||||
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
|
||||
source files are now compatible with Python 2 & 3 as is.
|
||||
- The `!psycopg2.test` package is no longer installed by ``python setup.py
|
||||
|
|
|
@ -216,10 +216,12 @@ introspection etc.
|
|||
|
||||
.. attribute:: display_size
|
||||
|
||||
The actual length of the column in bytes. Obtaining this value is
|
||||
computationally intensive, so it is always `!None` unless the
|
||||
:envvar:`PSYCOPG_DISPLAY_SIZE` parameter is set at compile time. See
|
||||
also PQgetlength_.
|
||||
Supposed to be the actual length of the column in bytes. Obtaining
|
||||
this value is computationally intensive, so it is always `!None`.
|
||||
|
||||
.. versionchanged:: 2.8
|
||||
It was previously possible to obtain this value using a compiler
|
||||
flag at builtin.
|
||||
|
||||
.. attribute:: internal_size
|
||||
|
||||
|
|
|
@ -46,8 +46,7 @@ static const char type_code_doc[] =
|
|||
|
||||
static const char display_size_doc[] =
|
||||
"The actual length of the column in bytes.\n\n"
|
||||
"Obtaining this value is computationally intensive, so it is always None\n"
|
||||
"unless the PSYCOPG_DISPLAY_SIZE parameter is set at compile time.";
|
||||
"Obtaining this value is computationally intensive, so it is always None";
|
||||
|
||||
static const char internal_size_doc[] =
|
||||
"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)
|
||||
*/
|
||||
|
||||
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
|
||||
_pq_fetch_tuples(cursorObject *curs)
|
||||
{
|
||||
int i, *dsize = NULL;
|
||||
int i;
|
||||
int pgnfields;
|
||||
int pgbintuples;
|
||||
int rv = -1;
|
||||
PyObject *description = NULL;
|
||||
PyObject *casts = NULL;
|
||||
|
@ -1244,7 +1379,6 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
Py_END_ALLOW_THREADS;
|
||||
|
||||
pgnfields = PQnfields(curs->pgres);
|
||||
pgbintuples = PQbinaryTuples(curs->pgres);
|
||||
|
||||
curs->notuples = 0;
|
||||
|
||||
|
@ -1255,158 +1389,31 @@ _pq_fetch_tuples(cursorObject *curs)
|
|||
if (!(casts = PyTuple_New(pgnfields))) { goto exit; }
|
||||
curs->columns = pgnfields;
|
||||
|
||||
/* calculate the display size for each column (cpu intensive, can be
|
||||
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 */
|
||||
/* calculate each field's parameters and typecasters */
|
||||
for (i = 0; i < pgnfields; i++) {
|
||||
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;
|
||||
PyObject *column = NULL;
|
||||
PyObject *cast = NULL;
|
||||
|
||||
if (!(column = (columnObject *)PyObject_CallObject(
|
||||
(PyObject *)&columnType, NULL))) {
|
||||
if (!(column = _make_column(curs->conn, curs->pgres, i))) {
|
||||
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);
|
||||
column = NULL;
|
||||
|
||||
continue;
|
||||
|
||||
err_for:
|
||||
Py_XDECREF(type);
|
||||
Py_XDECREF(column);
|
||||
goto exit;
|
||||
if (!(cast = _get_cast(curs, curs->pgres, i))) {
|
||||
goto exit;
|
||||
}
|
||||
PyTuple_SET_ITEM(casts, i, cast);
|
||||
}
|
||||
|
||||
curs->description = description; description = NULL;
|
||||
curs->casts = casts; casts = NULL;
|
||||
curs->description = description;
|
||||
description = NULL;
|
||||
|
||||
curs->casts = casts;
|
||||
casts = NULL;
|
||||
|
||||
rv = 0;
|
||||
|
||||
exit:
|
||||
PyMem_Free(dsize);
|
||||
Py_XDECREF(description);
|
||||
Py_XDECREF(casts);
|
||||
|
||||
|
@ -1417,6 +1424,7 @@ exit:
|
|||
return rv;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_read_rowcount(cursorObject *curs)
|
||||
{
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
[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
|
||||
define=
|
||||
|
||||
# "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
|
||||
|
|
Loading…
Reference in New Issue
Block a user