mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-02-07 21:00:33 +03:00
Merge branch 'connection-info'
This commit is contained in:
commit
0236c68da9
3
NEWS
3
NEWS
|
@ -12,7 +12,8 @@ New features:
|
|||
- Added `~psycopg2.extensions.Column.table_oid` and
|
||||
`~psycopg2.extensions.Column.table_column` attributes on `cursor.description`
|
||||
items (:ticket:`#661`).
|
||||
- Added `connection.host` property (:ticket:`#726`).
|
||||
- Added `connection.info` object to retrieve various PostgreSQL connection
|
||||
information (:ticket:`#726`).
|
||||
- `~psycopg2.sql.Identifier` can represent qualified names in SQL composition
|
||||
(:ticket:`#732`).
|
||||
- `!str()` on `~psycopg2.extras.Range` produces a human-readable representation
|
||||
|
|
|
@ -342,6 +342,9 @@ The ``connection`` class
|
|||
obscured.
|
||||
|
||||
|
||||
|
||||
.. rubric:: Transaction control methods and attributes.
|
||||
|
||||
.. index::
|
||||
pair: Transaction; Autocommit
|
||||
pair: Transaction; Isolation level
|
||||
|
@ -600,62 +603,16 @@ The ``connection`` class
|
|||
|
||||
|
||||
.. index::
|
||||
pair: Backend; Host
|
||||
pair: Connection; Info
|
||||
|
||||
.. attribute:: host
|
||||
.. attribute:: info
|
||||
|
||||
The server host name of the active connection.
|
||||
|
||||
This can be a host name, an IP address, or a directory path if the
|
||||
connection is via Unix socket. (The path case can be distinguished
|
||||
because it will always be an absolute path, beginning with ``/``.)
|
||||
|
||||
.. seealso:: libpq docs for `PQhost()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQHOST
|
||||
A `~psycopg2.extensions.ConnectionInfo` object exposing information
|
||||
about the native libpq connection.
|
||||
|
||||
.. versionadded:: 2.8.0
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Backend; PID
|
||||
|
||||
.. method:: get_backend_pid()
|
||||
|
||||
Returns the process ID (PID) of the backend server process handling
|
||||
this connection.
|
||||
|
||||
Note that the PID belongs to a process executing on the database
|
||||
server host, not the local host!
|
||||
|
||||
.. seealso:: libpq docs for `PQbackendPID()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQBACKENDPID
|
||||
|
||||
.. versionadded:: 2.0.8
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Server; Parameters
|
||||
|
||||
.. method:: get_parameter_status(parameter)
|
||||
|
||||
Look up a current parameter setting of the server.
|
||||
|
||||
Potential values for ``parameter`` are: ``server_version``,
|
||||
``server_encoding``, ``client_encoding``, ``is_superuser``,
|
||||
``session_authorization``, ``DateStyle``, ``TimeZone``,
|
||||
``integer_datetimes``, and ``standard_conforming_strings``.
|
||||
|
||||
If server did not report requested parameter, return `!None`.
|
||||
|
||||
.. seealso:: libpq docs for `PQparameterStatus()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQPARAMETERSTATUS
|
||||
|
||||
.. versionadded:: 2.0.12
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Connection; Parameters
|
||||
|
||||
|
@ -679,56 +636,6 @@ The ``connection`` class
|
|||
.. versionadded:: 2.7
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Transaction; Status
|
||||
|
||||
.. method:: get_transaction_status()
|
||||
|
||||
Return the current session transaction status as an integer. Symbolic
|
||||
constants for the values are defined in the module
|
||||
`psycopg2.extensions`: see :ref:`transaction-status-constants`
|
||||
for the available values.
|
||||
|
||||
.. seealso:: libpq docs for `PQtransactionStatus()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQTRANSACTIONSTATUS
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Protocol; Version
|
||||
|
||||
.. attribute:: protocol_version
|
||||
|
||||
A read-only integer representing frontend/backend protocol being used.
|
||||
Currently Psycopg supports only protocol 3, which allows connection
|
||||
to PostgreSQL server from version 7.4. Psycopg versions previous than
|
||||
2.3 support both protocols 2 and 3.
|
||||
|
||||
.. seealso:: libpq docs for `PQprotocolVersion()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQPROTOCOLVERSION
|
||||
|
||||
.. versionadded:: 2.0.12
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Server; Version
|
||||
|
||||
.. attribute:: server_version
|
||||
|
||||
A read-only integer representing the backend version.
|
||||
|
||||
The number is formed by converting the major, minor, and revision
|
||||
numbers into two-decimal-digit numbers and appending them together.
|
||||
For example, version 8.1.5 will be returned as ``80105``.
|
||||
|
||||
.. seealso:: libpq docs for `PQserverVersion()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQSERVERVERSION
|
||||
|
||||
.. versionadded:: 2.0.12
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Connection; Status
|
||||
|
||||
|
@ -786,6 +693,7 @@ The ``connection`` class
|
|||
support.
|
||||
|
||||
|
||||
|
||||
.. rubric:: Methods related to asynchronous support.
|
||||
|
||||
.. versionadded:: 2.2.0
|
||||
|
@ -832,6 +740,119 @@ The ``connection`` class
|
|||
Return `!True` if the connection is executing an asynchronous operation.
|
||||
|
||||
|
||||
|
||||
.. rubric:: informative methods of the native connection
|
||||
|
||||
.. note::
|
||||
|
||||
These methods are better accessed using the `~connection.info`
|
||||
attributes and may be dropped in future versions.
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Transaction; Status
|
||||
|
||||
.. method:: get_transaction_status()
|
||||
|
||||
Also available as `~connection.info`\ `!.`\
|
||||
`~psycopg2.extensions.ConnectionInfo.transaction_status`.
|
||||
|
||||
Return the current session transaction status as an integer. Symbolic
|
||||
constants for the values are defined in the module
|
||||
`psycopg2.extensions`: see :ref:`transaction-status-constants`
|
||||
for the available values.
|
||||
|
||||
.. seealso:: libpq docs for `PQtransactionStatus()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQTRANSACTIONSTATUS
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Protocol; Version
|
||||
|
||||
.. attribute:: protocol_version
|
||||
|
||||
Also available as `~connection.info`\ `!.`\
|
||||
`~psycopg2.extensions.ConnectionInfo.protocol_version`.
|
||||
|
||||
A read-only integer representing frontend/backend protocol being used.
|
||||
Currently Psycopg supports only protocol 3, which allows connection
|
||||
to PostgreSQL server from version 7.4. Psycopg versions previous than
|
||||
2.3 support both protocols 2 and 3.
|
||||
|
||||
.. seealso:: libpq docs for `PQprotocolVersion()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQPROTOCOLVERSION
|
||||
|
||||
.. versionadded:: 2.0.12
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Server; Version
|
||||
|
||||
.. attribute:: server_version
|
||||
|
||||
Also available as `~connection.info`\ `!.`\
|
||||
`~psycopg2.extensions.ConnectionInfo.server_version`.
|
||||
|
||||
A read-only integer representing the backend version.
|
||||
|
||||
The number is formed by converting the major, minor, and revision
|
||||
numbers into two-decimal-digit numbers and appending them together.
|
||||
For example, version 8.1.5 will be returned as ``80105``.
|
||||
|
||||
.. seealso:: libpq docs for `PQserverVersion()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQSERVERVERSION
|
||||
|
||||
.. versionadded:: 2.0.12
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Backend; PID
|
||||
|
||||
.. method:: get_backend_pid()
|
||||
|
||||
Also available as `~connection.info`\ `!.`\
|
||||
`~psycopg2.extensions.ConnectionInfo.backend_pid`.
|
||||
|
||||
Returns the process ID (PID) of the backend server process handling
|
||||
this connection.
|
||||
|
||||
Note that the PID belongs to a process executing on the database
|
||||
server host, not the local host!
|
||||
|
||||
.. seealso:: libpq docs for `PQbackendPID()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQBACKENDPID
|
||||
|
||||
.. versionadded:: 2.0.8
|
||||
|
||||
|
||||
.. index::
|
||||
pair: Server; Parameters
|
||||
|
||||
.. method:: get_parameter_status(parameter)
|
||||
|
||||
Also available as `~connection.info`\ `!.`\
|
||||
`~psycopg2.extensions.ConnectionInfo.parameter_status()`.
|
||||
|
||||
Look up a current parameter setting of the server.
|
||||
|
||||
Potential values for ``parameter`` are: ``server_version``,
|
||||
``server_encoding``, ``client_encoding``, ``is_superuser``,
|
||||
``session_authorization``, ``DateStyle``, ``TimeZone``,
|
||||
``integer_datetimes``, and ``standard_conforming_strings``.
|
||||
|
||||
If server did not report requested parameter, return `!None`.
|
||||
|
||||
.. seealso:: libpq docs for `PQparameterStatus()`__ for details.
|
||||
|
||||
.. __: https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQPARAMETERSTATUS
|
||||
|
||||
.. versionadded:: 2.0.12
|
||||
|
||||
|
||||
.. testcode::
|
||||
:hide:
|
||||
|
||||
|
|
|
@ -154,7 +154,46 @@ introspection etc.
|
|||
Close the object and remove it from the database.
|
||||
|
||||
|
||||
.. class:: Column
|
||||
|
||||
.. autoclass:: ConnectionInfo(connection)
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
.. autoattribute:: dbname
|
||||
.. autoattribute:: user
|
||||
.. autoattribute:: password
|
||||
.. autoattribute:: host
|
||||
.. autoattribute:: port
|
||||
.. autoattribute:: options
|
||||
.. autoattribute:: status
|
||||
.. autoattribute:: transaction_status
|
||||
.. automethod:: parameter_status(name)
|
||||
|
||||
.. autoattribute:: protocol_version
|
||||
|
||||
Currently Psycopg supports only protocol 3, which allows connection
|
||||
to PostgreSQL server from version 7.4. Psycopg versions previous than
|
||||
2.3 support both protocols 2 and 3.
|
||||
|
||||
.. autoattribute:: server_version
|
||||
|
||||
The number is formed by converting the major, minor, and revision
|
||||
numbers into two-decimal-digit numbers and appending them together.
|
||||
After PostgreSQL 10 the minor version was dropped, so the second group
|
||||
of digits is always ``00``. For example, version 9.3.5 will be
|
||||
returned as ``90305``, version 10.2 as ``100002``.
|
||||
|
||||
.. autoattribute:: error_message
|
||||
.. autoattribute:: socket
|
||||
.. autoattribute:: backend_pid
|
||||
.. autoattribute:: needs_password
|
||||
.. autoattribute:: used_password
|
||||
.. autoattribute:: ssl_in_use
|
||||
.. automethod:: ssl_attribute(name)
|
||||
.. autoattribute:: ssl_attribute_names
|
||||
|
||||
|
||||
.. class:: Column(\*args, \*\*kwargs)
|
||||
|
||||
Description of one result column, exposed as items of the
|
||||
`cursor.description` sequence.
|
||||
|
@ -788,7 +827,7 @@ Transaction status constants
|
|||
----------------------------
|
||||
|
||||
These values represent the possible status of a transaction: the current value
|
||||
can be read using the `connection.get_transaction_status()` method.
|
||||
can be read using the `connection.info.transaction_status` property.
|
||||
|
||||
.. data:: TRANSACTION_STATUS_IDLE
|
||||
|
||||
|
|
|
@ -117,9 +117,10 @@ The module interface respects the standard defined in the |DBAPI|_.
|
|||
|
||||
Integer constant reporting the version of the ``libpq`` library this
|
||||
``psycopg2`` module was compiled with (in the same format of
|
||||
`~connection.server_version`). If this value is greater or equal than
|
||||
``90100`` then you may query the version of the actually loaded library
|
||||
using the `~psycopg2.extensions.libpq_version()` function.
|
||||
`~psycopg2.extensions.ConnectionInfo.server_version`). If this value is
|
||||
greater or equal than ``90100`` then you may query the version of the
|
||||
actually loaded library using the `~psycopg2.extensions.libpq_version()`
|
||||
function.
|
||||
|
||||
|
||||
.. index::
|
||||
|
|
|
@ -185,7 +185,7 @@ def _get_json_oids(conn_or_curs, name='json'):
|
|||
conn_status = conn.status
|
||||
|
||||
# column typarray not available before PG 8.3
|
||||
typarray = conn.server_version >= 80300 and "typarray" or "NULL"
|
||||
typarray = conn.info.server_version >= 80300 and "typarray" or "NULL"
|
||||
|
||||
# get the oid for the hstore
|
||||
curs.execute(
|
||||
|
|
|
@ -352,9 +352,9 @@ class RangeCaster(object):
|
|||
from psycopg2.extras import _solve_conn_curs
|
||||
conn, curs = _solve_conn_curs(conn_or_curs)
|
||||
|
||||
if conn.server_version < 90200:
|
||||
if conn.info.server_version < 90200:
|
||||
raise ProgrammingError("range types not available in version %s"
|
||||
% conn.server_version)
|
||||
% conn.info.server_version)
|
||||
|
||||
# Store the transaction status of the connection to revert it after use
|
||||
conn_status = conn.status
|
||||
|
|
|
@ -61,7 +61,7 @@ from psycopg2._psycopg import ( # noqa
|
|||
adapt, adapters, encodings, connection, cursor,
|
||||
lobject, Xid, libpq_version, parse_dsn, quote_ident,
|
||||
string_types, binary_types, new_type, new_array_type, register_type,
|
||||
ISQLQuote, Notify, Diagnostics, Column,
|
||||
ISQLQuote, Notify, Diagnostics, Column, ConnectionInfo,
|
||||
QueryCanceledError, TransactionRollbackError,
|
||||
set_wait_callback, get_wait_callback, encrypt_password, )
|
||||
|
||||
|
|
|
@ -806,7 +806,7 @@ class HstoreAdapter(object):
|
|||
self.conn = conn
|
||||
|
||||
# use an old-style getquoted implementation if required
|
||||
if conn.server_version < 90000:
|
||||
if conn.info.server_version < 90000:
|
||||
self.getquoted = self._getquoted_8
|
||||
|
||||
def _getquoted_8(self):
|
||||
|
@ -911,7 +911,7 @@ class HstoreAdapter(object):
|
|||
conn_status = conn.status
|
||||
|
||||
# column typarray not available before PG 8.3
|
||||
typarray = conn.server_version >= 80300 and "typarray" or "NULL"
|
||||
typarray = conn.info.server_version >= 80300 and "typarray" or "NULL"
|
||||
|
||||
rv0, rv1 = [], []
|
||||
|
||||
|
@ -1097,7 +1097,7 @@ class CompositeCaster(object):
|
|||
schema = 'public'
|
||||
|
||||
# column typarray not available before PG 8.3
|
||||
typarray = conn.server_version >= 80300 and "typarray" or "NULL"
|
||||
typarray = conn.info.server_version >= 80300 and "typarray" or "NULL"
|
||||
|
||||
# get the type oid and attributes
|
||||
curs.execute("""\
|
||||
|
|
|
@ -105,7 +105,7 @@ class AbstractConnectionPool(object):
|
|||
# Return the connection into a consistent state before putting
|
||||
# it back into the pool
|
||||
if not conn.closed:
|
||||
status = conn.get_transaction_status()
|
||||
status = conn.info.transaction_status
|
||||
if status == _ext.TRANSACTION_STATUS_UNKNOWN:
|
||||
# server connection lost
|
||||
conn.close()
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "psycopg/connection.h"
|
||||
#include "psycopg/cursor.h"
|
||||
#include "psycopg/pqpath.h"
|
||||
#include "psycopg/conninfo.h"
|
||||
#include "psycopg/lobject.h"
|
||||
#include "psycopg/green.h"
|
||||
#include "psycopg/xid.h"
|
||||
|
@ -994,25 +995,20 @@ psyco_conn_get_backend_pid(connectionObject *self)
|
|||
return PyInt_FromLong((long)PQbackendPID(self->pgconn));
|
||||
}
|
||||
|
||||
/* get the current host */
|
||||
|
||||
#define psyco_conn_host_get_doc \
|
||||
"host -- Get the host name."
|
||||
/* get info about the connection */
|
||||
|
||||
#define psyco_conn_info_get_doc \
|
||||
"info -- Get connection info."
|
||||
|
||||
static PyObject *
|
||||
psyco_conn_host_get(connectionObject *self)
|
||||
psyco_conn_info_get(connectionObject *self)
|
||||
{
|
||||
const char *val = NULL;
|
||||
|
||||
EXC_IF_CONN_CLOSED(self);
|
||||
|
||||
val = PQhost(self->pgconn);
|
||||
if (!val) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return conn_text_from_chars(self, val);
|
||||
return PyObject_CallFunctionObjArgs(
|
||||
(PyObject *)&connInfoType, (PyObject *)self, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* reset the currect connection */
|
||||
|
||||
#define psyco_conn_reset_doc \
|
||||
|
@ -1264,9 +1260,9 @@ static struct PyGetSetDef connectionObject_getsets[] = {
|
|||
(getter)psyco_conn_deferrable_get,
|
||||
(setter)psyco_conn_deferrable_set,
|
||||
psyco_conn_deferrable_doc },
|
||||
{ "host",
|
||||
(getter)psyco_conn_host_get, NULL,
|
||||
psyco_conn_host_get_doc },
|
||||
{ "info",
|
||||
(getter)psyco_conn_info_get, NULL,
|
||||
psyco_conn_info_get_doc },
|
||||
{NULL}
|
||||
};
|
||||
#undef EXCEPTION_GETTER
|
||||
|
|
40
psycopg/conninfo.h
Normal file
40
psycopg/conninfo.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/* connection.h - definition for the psycopg ConnectionInfo type
|
||||
*
|
||||
* Copyright (C) 2018 Daniele Varrazzo <daniele.varrazzo@gmail.com>
|
||||
*
|
||||
* This file is part of psycopg.
|
||||
*
|
||||
* psycopg2 is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link this program with the OpenSSL library (or with
|
||||
* modified versions of OpenSSL that use the same license as OpenSSL),
|
||||
* and distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU Lesser General Public License in all respects for
|
||||
* all of the code used other than OpenSSL.
|
||||
*
|
||||
* psycopg2 is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*/
|
||||
|
||||
#ifndef PSYCOPG_CONNINFO_H
|
||||
#define PSYCOPG_CONNINFO_H 1
|
||||
|
||||
#include "psycopg/connection.h"
|
||||
|
||||
extern HIDDEN PyTypeObject connInfoType;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
|
||||
connectionObject *conn;
|
||||
|
||||
} connInfoObject;
|
||||
|
||||
#endif /* PSYCOPG_CONNINFO_H */
|
614
psycopg/conninfo_type.c
Normal file
614
psycopg/conninfo_type.c
Normal file
|
@ -0,0 +1,614 @@
|
|||
/* conninfo_type.c - present information about the libpq connection
|
||||
*
|
||||
* Copyright (C) 2018 Daniele Varrazzo <daniele.varrazzo@gmail.com>
|
||||
*
|
||||
* This file is part of psycopg.
|
||||
*
|
||||
* psycopg2 is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link this program with the OpenSSL library (or with
|
||||
* modified versions of OpenSSL that use the same license as OpenSSL),
|
||||
* and distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU Lesser General Public License in all respects for
|
||||
* all of the code used other than OpenSSL.
|
||||
*
|
||||
* psycopg2 is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*/
|
||||
|
||||
#define PSYCOPG_MODULE
|
||||
#include "psycopg/psycopg.h"
|
||||
|
||||
#include "psycopg/conninfo.h"
|
||||
|
||||
|
||||
static const char connInfoType_doc[] =
|
||||
"Details about the native PostgreSQL database connection.\n"
|
||||
"\n"
|
||||
"This class exposes several `informative functions`__ about the status\n"
|
||||
"of the libpq connection.\n"
|
||||
"\n"
|
||||
"Objects of this class are exposed as the `connection.info` attribute.\n"
|
||||
"\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html";
|
||||
|
||||
|
||||
static const char dbname_doc[] =
|
||||
"The database name of the connection.\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQdb()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQDB";
|
||||
|
||||
static PyObject *
|
||||
dbname_get(connInfoObject *self)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
val = PQdb(self->conn->pgconn);
|
||||
if (!val) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return conn_text_from_chars(self->conn, val);
|
||||
}
|
||||
|
||||
|
||||
static const char user_doc[] =
|
||||
"The user name of the connection.\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQuser()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQUSER";
|
||||
|
||||
static PyObject *
|
||||
user_get(connInfoObject *self)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
val = PQuser(self->conn->pgconn);
|
||||
if (!val) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return conn_text_from_chars(self->conn, val);
|
||||
}
|
||||
|
||||
|
||||
static const char password_doc[] =
|
||||
"The password of the connection.\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQpass()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQPASS";
|
||||
|
||||
static PyObject *
|
||||
password_get(connInfoObject *self)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
val = PQpass(self->conn->pgconn);
|
||||
if (!val) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return conn_text_from_chars(self->conn, val);
|
||||
}
|
||||
|
||||
|
||||
static const char host_doc[] =
|
||||
"The server host name of the connection.\n"
|
||||
"\n"
|
||||
"This can be a host name, an IP address, or a directory path if the\n"
|
||||
"connection is via Unix socket. (The path case can be distinguished\n"
|
||||
"because it will always be an absolute path, beginning with ``/``.)\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQhost()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQHOST";
|
||||
|
||||
static PyObject *
|
||||
host_get(connInfoObject *self)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
val = PQhost(self->conn->pgconn);
|
||||
if (!val) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return conn_text_from_chars(self->conn, val);
|
||||
}
|
||||
|
||||
|
||||
static const char port_doc[] =
|
||||
"The port of the connection.\n"
|
||||
"\n"
|
||||
":type: `!int`\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQport()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQPORT";
|
||||
|
||||
static PyObject *
|
||||
port_get(connInfoObject *self)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
val = PQport(self->conn->pgconn);
|
||||
if (!val || !val[0]) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return PyInt_FromString((char *)val, NULL, 10);
|
||||
}
|
||||
|
||||
|
||||
static const char options_doc[] =
|
||||
"The command-line options passed in the the connection request.\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQoptions()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQOPTIONS";
|
||||
|
||||
static PyObject *
|
||||
options_get(connInfoObject *self)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
val = PQoptions(self->conn->pgconn);
|
||||
if (!val) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return conn_text_from_chars(self->conn, val);
|
||||
}
|
||||
|
||||
|
||||
static const char status_doc[] =
|
||||
"The status of the connection.\n"
|
||||
"\n"
|
||||
":type: `!int`\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQstatus()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQSTATUS";
|
||||
|
||||
static PyObject *
|
||||
status_get(connInfoObject *self)
|
||||
{
|
||||
ConnStatusType val;
|
||||
|
||||
val = PQstatus(self->conn->pgconn);
|
||||
return PyInt_FromLong((long)val);
|
||||
}
|
||||
|
||||
|
||||
static const char transaction_status_doc[] =
|
||||
"The current in-transaction status of the connection.\n"
|
||||
"\n"
|
||||
"Symbolic constants for the values are defined in the module\n"
|
||||
"`psycopg2.extensions`: see :ref:`transaction-status-constants` for the\n"
|
||||
"available values.\n"
|
||||
"\n"
|
||||
":type: `!int`\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQtransactionStatus()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQTRANSACTIONSTATUS";
|
||||
|
||||
static PyObject *
|
||||
transaction_status_get(connInfoObject *self)
|
||||
{
|
||||
PGTransactionStatusType val;
|
||||
|
||||
val = PQtransactionStatus(self->conn->pgconn);
|
||||
return PyInt_FromLong((long)val);
|
||||
}
|
||||
|
||||
|
||||
static const char parameter_status_doc[] =
|
||||
"Looks up a current parameter setting of the server.\n"
|
||||
"\n"
|
||||
":param name: The name of the parameter to return.\n"
|
||||
":type name: `!str`\n"
|
||||
":return: The parameter value, `!None` if the parameter is unknown.\n"
|
||||
":rtype: `!str`\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQparameterStatus()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQPARAMETERSTATUS";
|
||||
|
||||
static PyObject *
|
||||
parameter_status(connInfoObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = {"name", NULL};
|
||||
const char *name;
|
||||
const char *val;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
val = PQparameterStatus(self->conn->pgconn, name);
|
||||
|
||||
if (!val) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
else {
|
||||
return conn_text_from_chars(self->conn, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char protocol_version_doc[] =
|
||||
"The frontend/backend protocol being used.\n"
|
||||
"\n"
|
||||
":type: `!int`\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQprotocolVersion()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQPROTOCOLVERSION";
|
||||
|
||||
static PyObject *
|
||||
protocol_version_get(connInfoObject *self)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = PQprotocolVersion(self->conn->pgconn);
|
||||
return PyInt_FromLong((long)val);
|
||||
}
|
||||
|
||||
|
||||
static const char server_version_doc[] =
|
||||
"Returns an integer representing the server version.\n"
|
||||
"\n"
|
||||
":type: `!int`\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQserverVersion()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQSERVERVERSION";
|
||||
|
||||
static PyObject *
|
||||
server_version_get(connInfoObject *self)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = PQserverVersion(self->conn->pgconn);
|
||||
return PyInt_FromLong((long)val);
|
||||
}
|
||||
|
||||
|
||||
static const char error_message_doc[] =
|
||||
"The error message most recently generated by an operation on the connection.\n"
|
||||
"\n"
|
||||
"`!None` if there is no current message.\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQerrorMessage()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQERRORMESSAGE";
|
||||
|
||||
static PyObject *
|
||||
error_message_get(connInfoObject *self)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
val = PQerrorMessage(self->conn->pgconn);
|
||||
if (!val || !val[0]) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return conn_text_from_chars(self->conn, val);
|
||||
}
|
||||
|
||||
|
||||
static const char socket_doc[] =
|
||||
"The file descriptor number of the connection socket to the server.\n"
|
||||
"\n"
|
||||
":type: `!int`\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQsocket()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQSOCKET";
|
||||
|
||||
static PyObject *
|
||||
socket_get(connInfoObject *self)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = PQsocket(self->conn->pgconn);
|
||||
return PyInt_FromLong((long)val);
|
||||
}
|
||||
|
||||
|
||||
static const char backend_pid_doc[] =
|
||||
"The process ID (PID) of the backend process handling this connection.\n"
|
||||
"\n"
|
||||
":type: `!int`\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQbackendPID()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQBACKENDPID";
|
||||
|
||||
static PyObject *
|
||||
backend_pid_get(connInfoObject *self)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = PQbackendPID(self->conn->pgconn);
|
||||
return PyInt_FromLong((long)val);
|
||||
}
|
||||
|
||||
|
||||
static const char needs_password_doc[] =
|
||||
"The connection authentication method required a password, but none was available.\n"
|
||||
"\n"
|
||||
":type: `!bool`\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQconnectionNeedsPassword()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQCONNECTIONNEEDSPASSWORD";
|
||||
|
||||
static PyObject *
|
||||
needs_password_get(connInfoObject *self)
|
||||
{
|
||||
PyObject *rv;
|
||||
|
||||
rv = PQconnectionNeedsPassword(self->conn->pgconn) ? Py_True : Py_False;
|
||||
Py_INCREF(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static const char used_password_doc[] =
|
||||
"The connection authentication method used a password.\n"
|
||||
"\n"
|
||||
":type: `!bool`\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQconnectionUsedPassword()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQCONNECTIONUSEDPASSWORD";
|
||||
|
||||
static PyObject *
|
||||
used_password_get(connInfoObject *self)
|
||||
{
|
||||
PyObject *rv;
|
||||
|
||||
rv = PQconnectionUsedPassword(self->conn->pgconn) ? Py_True : Py_False;
|
||||
Py_INCREF(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static const char ssl_in_use_doc[] =
|
||||
"`!True` if the connection uses SSL, `!False` if not.\n"
|
||||
"\n"
|
||||
"Only available if psycopg was built with libpq >= 9.5; raise\n"
|
||||
"`~psycopg2.NotSupportedError` otherwise.\n"
|
||||
"\n"
|
||||
":type: `!bool`\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQsslInUse()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQSSLINUSE";
|
||||
|
||||
static PyObject *
|
||||
ssl_in_use_get(connInfoObject *self)
|
||||
{
|
||||
PyObject *rv = NULL;
|
||||
|
||||
#if PG_VERSION_NUM >= 90500
|
||||
rv = PQsslInUse(self->conn->pgconn) ? Py_True : Py_False;
|
||||
Py_INCREF(rv);
|
||||
#else
|
||||
PyErr_SetString(NotSupportedError,
|
||||
"'ssl_in_use' not available in libpq < 9.5");
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static const char ssl_attribute_doc[] =
|
||||
"Returns SSL-related information about the connection.\n"
|
||||
"\n"
|
||||
":param name: The name of the attribute to return.\n"
|
||||
":type name: `!str`\n"
|
||||
":return: The attribute value, `!None` if unknown.\n"
|
||||
":rtype: `!str`\n"
|
||||
"\n"
|
||||
"Only available if psycopg was built with libpq >= 9.5; raise\n"
|
||||
"`~psycopg2.NotSupportedError` otherwise.\n"
|
||||
"\n"
|
||||
"Valid names are available in `ssl_attribute_names`.\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQsslAttribute()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQSSLATTRIBUTE";
|
||||
|
||||
static PyObject *
|
||||
ssl_attribute(connInfoObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = {"name", NULL};
|
||||
const char *name;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if PG_VERSION_NUM >= 90500
|
||||
{
|
||||
const char *val;
|
||||
|
||||
val = PQsslAttribute(self->conn->pgconn, name);
|
||||
|
||||
if (!val) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
else {
|
||||
return conn_text_from_chars(self->conn, val);
|
||||
}
|
||||
}
|
||||
#else
|
||||
PyErr_SetString(NotSupportedError,
|
||||
"'ssl_attribute()' not available in libpq < 9.5");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char ssl_attribute_names_doc[] =
|
||||
"The list of the SSL attribute names available.\n"
|
||||
"\n"
|
||||
":type: `!list` of `!str`\n"
|
||||
"\n"
|
||||
"Only available if psycopg was built with libpq >= 9.5; raise\n"
|
||||
"`~psycopg2.NotSupportedError` otherwise.\n"
|
||||
"\n"
|
||||
".. seealso:: libpq docs for `PQsslAttributeNames()`__ for details.\n"
|
||||
".. __: https://www.postgresql.org/docs/current/static/libpq-status.html"
|
||||
"#LIBPQ-PQSSLATTRIBUTENAMES";
|
||||
|
||||
static PyObject *
|
||||
ssl_attribute_names_get(connInfoObject *self)
|
||||
{
|
||||
#if PG_VERSION_NUM >= 90500
|
||||
const char* const* names;
|
||||
int i;
|
||||
PyObject *l = NULL, *s = NULL, *rv = NULL;
|
||||
|
||||
names = PQsslAttributeNames(self->conn->pgconn);
|
||||
if (!(l = PyList_New(0))) { goto exit; }
|
||||
|
||||
for (i = 0; names[i]; i++) {
|
||||
if (!(s = conn_text_from_chars(self->conn, names[i]))) { goto exit; }
|
||||
if (0 != PyList_Append(l, s)) { goto exit; }
|
||||
Py_CLEAR(s);
|
||||
}
|
||||
|
||||
rv = l;
|
||||
l = NULL;
|
||||
|
||||
exit:
|
||||
Py_XDECREF(l);
|
||||
Py_XDECREF(s);
|
||||
return rv;
|
||||
#else
|
||||
PyErr_SetString(NotSupportedError,
|
||||
"'ssl_attribute_names not available in libpq < 9.5");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static struct PyGetSetDef connInfoObject_getsets[] = {
|
||||
{ "dbname", (getter)dbname_get, NULL, (char *)dbname_doc },
|
||||
{ "user", (getter)user_get, NULL, (char *)user_doc },
|
||||
{ "password", (getter)password_get, NULL, (char *)password_doc },
|
||||
{ "host", (getter)host_get, NULL, (char *)host_doc },
|
||||
{ "port", (getter)port_get, NULL, (char *)port_doc },
|
||||
{ "options", (getter)options_get, NULL, (char *)options_doc },
|
||||
{ "status", (getter)status_get, NULL, (char *)status_doc },
|
||||
{ "transaction_status", (getter)transaction_status_get, NULL,
|
||||
(char *)transaction_status_doc },
|
||||
{ "protocol_version", (getter)protocol_version_get, NULL,
|
||||
(char *)protocol_version_doc },
|
||||
{ "server_version", (getter)server_version_get, NULL,
|
||||
(char *)server_version_doc },
|
||||
{ "error_message", (getter)error_message_get, NULL,
|
||||
(char *)error_message_doc },
|
||||
{ "socket", (getter)socket_get, NULL, (char *)socket_doc },
|
||||
{ "backend_pid", (getter)backend_pid_get, NULL, (char *)backend_pid_doc },
|
||||
{ "used_password", (getter)used_password_get, NULL,
|
||||
(char *)used_password_doc },
|
||||
{ "needs_password", (getter)needs_password_get, NULL,
|
||||
(char *)needs_password_doc },
|
||||
{ "ssl_in_use", (getter)ssl_in_use_get, NULL,
|
||||
(char *)ssl_in_use_doc },
|
||||
{ "ssl_attribute_names", (getter)ssl_attribute_names_get, NULL,
|
||||
(char *)ssl_attribute_names_doc },
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static struct PyMethodDef connInfoObject_methods[] = {
|
||||
{"ssl_attribute", (PyCFunction)ssl_attribute,
|
||||
METH_VARARGS|METH_KEYWORDS, ssl_attribute_doc},
|
||||
{"parameter_status", (PyCFunction)parameter_status,
|
||||
METH_VARARGS|METH_KEYWORDS, parameter_status_doc},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
/* initialization and finalization methods */
|
||||
|
||||
static PyObject *
|
||||
conninfo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
return type->tp_alloc(type, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
conninfo_init(connInfoObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *conn = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O", &conn))
|
||||
return -1;
|
||||
|
||||
if (!PyObject_TypeCheck(conn, &connectionType)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"The argument must be a psycopg2 connection");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Py_INCREF(conn);
|
||||
self->conn = (connectionObject *)conn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
conninfo_dealloc(connInfoObject* self)
|
||||
{
|
||||
Py_CLEAR(self->conn);
|
||||
Py_TYPE(self)->tp_free((PyObject *)self);
|
||||
}
|
||||
|
||||
|
||||
/* object type */
|
||||
|
||||
PyTypeObject connInfoType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"psycopg2.extensions.ConnectionInfo",
|
||||
sizeof(connInfoObject), 0,
|
||||
(destructor)conninfo_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash */
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
||||
connInfoType_doc, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
connInfoObject_methods, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
connInfoObject_getsets, /*tp_getset*/
|
||||
0, /*tp_base*/
|
||||
0, /*tp_dict*/
|
||||
0, /*tp_descr_get*/
|
||||
0, /*tp_descr_set*/
|
||||
0, /*tp_dictoffset*/
|
||||
(initproc)conninfo_init, /*tp_init*/
|
||||
0, /*tp_alloc*/
|
||||
conninfo_new, /*tp_new*/
|
||||
};
|
|
@ -40,7 +40,7 @@ static const char notify_doc[] =
|
|||
static const char pid_doc[] =
|
||||
"The ID of the backend process that sent the notification.\n\n"
|
||||
"Note: if the sending session was handled by Psycopg, you can use\n"
|
||||
"`~connection.get_backend_pid()` to know its PID.";
|
||||
"`~connection.info.backend_pid` to know its PID.";
|
||||
|
||||
static const char channel_doc[] =
|
||||
"The name of the channel to which the notification was sent.";
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "psycopg/microprotocols.h"
|
||||
#include "psycopg/microprotocols_proto.h"
|
||||
#include "psycopg/error.h"
|
||||
#include "psycopg/conninfo.h"
|
||||
#include "psycopg/diagnostics.h"
|
||||
|
||||
#include "psycopg/adapter_qstring.h"
|
||||
|
@ -995,6 +996,9 @@ INIT_MODULE(_psycopg)(void)
|
|||
errorType.tp_base = (PyTypeObject *)PyExc_StandardError;
|
||||
if (PyType_Ready(&errorType) == -1) goto exit;
|
||||
|
||||
Py_TYPE(&connInfoType) = &PyType_Type;
|
||||
if (PyType_Ready(&connInfoType) == -1) goto exit;
|
||||
|
||||
Py_TYPE(&diagnosticsType) = &PyType_Type;
|
||||
if (PyType_Ready(&diagnosticsType) == -1) goto exit;
|
||||
|
||||
|
@ -1084,6 +1088,7 @@ INIT_MODULE(_psycopg)(void)
|
|||
PyModule_AddObject(module, "Column", (PyObject*)&columnType);
|
||||
PyModule_AddObject(module, "Notify", (PyObject*)¬ifyType);
|
||||
PyModule_AddObject(module, "Xid", (PyObject*)&xidType);
|
||||
PyModule_AddObject(module, "ConnectionInfo", (PyObject*)&connInfoType);
|
||||
PyModule_AddObject(module, "Diagnostics", (PyObject*)&diagnosticsType);
|
||||
PyModule_AddObject(module, "AsIs", (PyObject*)&asisType);
|
||||
PyModule_AddObject(module, "Binary", (PyObject*)&binaryType);
|
||||
|
|
|
@ -78,6 +78,7 @@ typedef unsigned long Py_uhash_t;
|
|||
#define PyInt_Check PyLong_Check
|
||||
#define PyInt_AsLong PyLong_AsLong
|
||||
#define PyInt_FromLong PyLong_FromLong
|
||||
#define PyInt_FromString PyLong_FromString
|
||||
#define PyInt_FromSsize_t PyLong_FromSsize_t
|
||||
#define PyExc_StandardError PyExc_Exception
|
||||
#define PyString_FromFormat PyUnicode_FromFormat
|
||||
|
|
4
setup.py
4
setup.py
|
@ -490,7 +490,7 @@ sources = [
|
|||
'replication_connection_type.c',
|
||||
'replication_cursor_type.c',
|
||||
'replication_message_type.c',
|
||||
'diagnostics_type.c', 'error_type.c',
|
||||
'diagnostics_type.c', 'error_type.c', 'conninfo_type.c',
|
||||
'lobject_int.c', 'lobject_type.c',
|
||||
'notify_type.c', 'xid_type.c',
|
||||
|
||||
|
@ -508,7 +508,7 @@ depends = [
|
|||
'replication_connection.h',
|
||||
'replication_cursor.h',
|
||||
'replication_message.h',
|
||||
'notify.h', 'pqpath.h', 'xid.h', 'column.h',
|
||||
'notify.h', 'pqpath.h', 'xid.h', 'column.h', 'conninfo.h',
|
||||
'libpq_support.h', 'win32_support.h',
|
||||
|
||||
'adapter_asis.h', 'adapter_binary.h', 'adapter_datetime.h',
|
||||
|
|
|
@ -192,7 +192,7 @@ class AsyncTests(ConnectingTestCase):
|
|||
self.assertTrue(self.conn.isexecuting())
|
||||
|
||||
# getting transaction status works
|
||||
self.assertEquals(self.conn.get_transaction_status(),
|
||||
self.assertEquals(self.conn.info.transaction_status,
|
||||
ext.TRANSACTION_STATUS_ACTIVE)
|
||||
self.assertTrue(self.conn.isexecuting())
|
||||
|
||||
|
@ -359,7 +359,7 @@ class AsyncTests(ConnectingTestCase):
|
|||
|
||||
self.assertEquals(self.sync_conn.notifies, [])
|
||||
|
||||
pid = self.conn.get_backend_pid()
|
||||
pid = self.conn.info.backend_pid
|
||||
for _ in range(5):
|
||||
self.wait(self.sync_conn)
|
||||
if not self.sync_conn.notifies:
|
||||
|
@ -418,7 +418,7 @@ class AsyncTests(ConnectingTestCase):
|
|||
def test_notices(self):
|
||||
del self.conn.notices[:]
|
||||
cur = self.conn.cursor()
|
||||
if self.conn.server_version >= 90300:
|
||||
if self.conn.info.server_version >= 90300:
|
||||
cur.execute("set client_min_messages=debug1")
|
||||
self.wait(cur)
|
||||
cur.execute("create temp table chatty (id serial primary key);")
|
||||
|
|
|
@ -87,13 +87,13 @@ class ConnectionTests(ConnectingTestCase):
|
|||
conn.autocommit = True
|
||||
conn.isolation_level = 'serializable'
|
||||
conn.readonly = True
|
||||
if self.conn.server_version >= 90100:
|
||||
if self.conn.info.server_version >= 90100:
|
||||
conn.deferrable = False
|
||||
|
||||
self.assert_(conn.autocommit)
|
||||
self.assertEqual(conn.isolation_level, ext.ISOLATION_LEVEL_SERIALIZABLE)
|
||||
self.assert_(conn.readonly is True)
|
||||
if self.conn.server_version >= 90100:
|
||||
if self.conn.info.server_version >= 90100:
|
||||
self.assert_(conn.deferrable is False)
|
||||
|
||||
conn.reset()
|
||||
|
@ -101,13 +101,13 @@ class ConnectionTests(ConnectingTestCase):
|
|||
self.assert_(not conn.autocommit)
|
||||
self.assertEqual(conn.isolation_level, ext.ISOLATION_LEVEL_DEFAULT)
|
||||
self.assert_(conn.readonly is None)
|
||||
if self.conn.server_version >= 90100:
|
||||
if self.conn.info.server_version >= 90100:
|
||||
self.assert_(conn.deferrable is None)
|
||||
|
||||
def test_notices(self):
|
||||
conn = self.conn
|
||||
cur = conn.cursor()
|
||||
if self.conn.server_version >= 90300:
|
||||
if self.conn.info.server_version >= 90300:
|
||||
cur.execute("set client_min_messages=debug1")
|
||||
cur.execute("create temp table chatty (id serial primary key);")
|
||||
self.assertEqual("CREATE TABLE", cur.statusmessage)
|
||||
|
@ -116,7 +116,7 @@ class ConnectionTests(ConnectingTestCase):
|
|||
def test_notices_consistent_order(self):
|
||||
conn = self.conn
|
||||
cur = conn.cursor()
|
||||
if self.conn.server_version >= 90300:
|
||||
if self.conn.info.server_version >= 90300:
|
||||
cur.execute("set client_min_messages=debug1")
|
||||
cur.execute("""
|
||||
create temp table table1 (id serial);
|
||||
|
@ -136,7 +136,7 @@ class ConnectionTests(ConnectingTestCase):
|
|||
def test_notices_limited(self):
|
||||
conn = self.conn
|
||||
cur = conn.cursor()
|
||||
if self.conn.server_version >= 90300:
|
||||
if self.conn.info.server_version >= 90300:
|
||||
cur.execute("set client_min_messages=debug1")
|
||||
for i in range(0, 100, 10):
|
||||
sql = " ".join(["create temp table table%d (id serial);" % j
|
||||
|
@ -153,7 +153,7 @@ class ConnectionTests(ConnectingTestCase):
|
|||
conn = self.conn
|
||||
self.conn.notices = deque()
|
||||
cur = conn.cursor()
|
||||
if self.conn.server_version >= 90300:
|
||||
if self.conn.info.server_version >= 90300:
|
||||
cur.execute("set client_min_messages=debug1")
|
||||
|
||||
cur.execute("""
|
||||
|
@ -183,7 +183,7 @@ class ConnectionTests(ConnectingTestCase):
|
|||
conn = self.conn
|
||||
self.conn.notices = None # will make an error swallowes ok
|
||||
cur = conn.cursor()
|
||||
if self.conn.server_version >= 90300:
|
||||
if self.conn.info.server_version >= 90300:
|
||||
cur.execute("set client_min_messages=debug1")
|
||||
|
||||
cur.execute("create temp table table1 (id serial);")
|
||||
|
@ -199,7 +199,7 @@ class ConnectionTests(ConnectingTestCase):
|
|||
|
||||
def test_tpc_unsupported(self):
|
||||
cnn = self.conn
|
||||
if cnn.server_version >= 80100:
|
||||
if cnn.info.server_version >= 80100:
|
||||
return self.skipTest("tpc is supported")
|
||||
|
||||
self.assertRaises(psycopg2.NotSupportedError,
|
||||
|
@ -533,7 +533,7 @@ class IsolationLevelsTestCase(ConnectingTestCase):
|
|||
conn.set_isolation_level(level)
|
||||
|
||||
# the only values available on prehistoric PG versions
|
||||
if conn.server_version < 80000:
|
||||
if conn.info.server_version < 80000:
|
||||
if level in (
|
||||
ext.ISOLATION_LEVEL_READ_UNCOMMITTED,
|
||||
ext.ISOLATION_LEVEL_REPEATABLE_READ):
|
||||
|
@ -589,35 +589,35 @@ class IsolationLevelsTestCase(ConnectingTestCase):
|
|||
cur = conn.cursor()
|
||||
|
||||
self.assertEqual(ext.TRANSACTION_STATUS_IDLE,
|
||||
conn.get_transaction_status())
|
||||
conn.info.transaction_status)
|
||||
cur.execute("insert into isolevel values (10);")
|
||||
self.assertEqual(ext.TRANSACTION_STATUS_INTRANS,
|
||||
conn.get_transaction_status())
|
||||
conn.info.transaction_status)
|
||||
|
||||
conn.set_isolation_level(
|
||||
psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE)
|
||||
self.assertEqual(psycopg2.extensions.TRANSACTION_STATUS_IDLE,
|
||||
conn.get_transaction_status())
|
||||
conn.info.transaction_status)
|
||||
cur.execute("select count(*) from isolevel;")
|
||||
self.assertEqual(0, cur.fetchone()[0])
|
||||
|
||||
cur.execute("insert into isolevel values (10);")
|
||||
self.assertEqual(psycopg2.extensions.TRANSACTION_STATUS_INTRANS,
|
||||
conn.get_transaction_status())
|
||||
conn.info.transaction_status)
|
||||
conn.set_isolation_level(
|
||||
psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
self.assertEqual(psycopg2.extensions.TRANSACTION_STATUS_IDLE,
|
||||
conn.get_transaction_status())
|
||||
conn.info.transaction_status)
|
||||
cur.execute("select count(*) from isolevel;")
|
||||
self.assertEqual(0, cur.fetchone()[0])
|
||||
|
||||
cur.execute("insert into isolevel values (10);")
|
||||
self.assertEqual(psycopg2.extensions.TRANSACTION_STATUS_IDLE,
|
||||
conn.get_transaction_status())
|
||||
conn.info.transaction_status)
|
||||
conn.set_isolation_level(
|
||||
psycopg2.extensions.ISOLATION_LEVEL_READ_COMMITTED)
|
||||
self.assertEqual(psycopg2.extensions.TRANSACTION_STATUS_IDLE,
|
||||
conn.get_transaction_status())
|
||||
conn.info.transaction_status)
|
||||
cur.execute("select count(*) from isolevel;")
|
||||
self.assertEqual(1, cur.fetchone()[0])
|
||||
self.assertEqual(conn.isolation_level,
|
||||
|
@ -713,7 +713,7 @@ class IsolationLevelsTestCase(ConnectingTestCase):
|
|||
|
||||
self.conn.isolation_level = ext.ISOLATION_LEVEL_REPEATABLE_READ
|
||||
cur.execute("SHOW transaction_isolation;")
|
||||
if self.conn.server_version > 80000:
|
||||
if self.conn.info.server_version > 80000:
|
||||
self.assertEqual(self.conn.isolation_level,
|
||||
ext.ISOLATION_LEVEL_REPEATABLE_READ)
|
||||
self.assertEqual(cur.fetchone()[0], 'repeatable read')
|
||||
|
@ -732,7 +732,7 @@ class IsolationLevelsTestCase(ConnectingTestCase):
|
|||
|
||||
self.conn.isolation_level = ext.ISOLATION_LEVEL_READ_UNCOMMITTED
|
||||
cur.execute("SHOW transaction_isolation;")
|
||||
if self.conn.server_version > 80000:
|
||||
if self.conn.info.server_version > 80000:
|
||||
self.assertEqual(self.conn.isolation_level,
|
||||
ext.ISOLATION_LEVEL_READ_UNCOMMITTED)
|
||||
self.assertEqual(cur.fetchone()[0], 'read uncommitted')
|
||||
|
@ -761,7 +761,7 @@ class IsolationLevelsTestCase(ConnectingTestCase):
|
|||
|
||||
self.conn.isolation_level = "repeatable read"
|
||||
cur.execute("SHOW transaction_isolation;")
|
||||
if self.conn.server_version > 80000:
|
||||
if self.conn.info.server_version > 80000:
|
||||
self.assertEqual(self.conn.isolation_level,
|
||||
ext.ISOLATION_LEVEL_REPEATABLE_READ)
|
||||
self.assertEqual(cur.fetchone()[0], 'repeatable read')
|
||||
|
@ -780,7 +780,7 @@ class IsolationLevelsTestCase(ConnectingTestCase):
|
|||
|
||||
self.conn.isolation_level = "read uncommitted"
|
||||
cur.execute("SHOW transaction_isolation;")
|
||||
if self.conn.server_version > 80000:
|
||||
if self.conn.info.server_version > 80000:
|
||||
self.assertEqual(self.conn.isolation_level,
|
||||
ext.ISOLATION_LEVEL_READ_UNCOMMITTED)
|
||||
self.assertEqual(cur.fetchone()[0], 'read uncommitted')
|
||||
|
@ -1211,7 +1211,7 @@ class TransactionControlTests(ConnectingTestCase):
|
|||
self.conn.set_session(
|
||||
ext.ISOLATION_LEVEL_REPEATABLE_READ)
|
||||
cur.execute("SHOW transaction_isolation;")
|
||||
if self.conn.server_version > 80000:
|
||||
if self.conn.info.server_version > 80000:
|
||||
self.assertEqual(cur.fetchone()[0], 'repeatable read')
|
||||
else:
|
||||
self.assertEqual(cur.fetchone()[0], 'serializable')
|
||||
|
@ -1226,7 +1226,7 @@ class TransactionControlTests(ConnectingTestCase):
|
|||
self.conn.set_session(
|
||||
isolation_level=ext.ISOLATION_LEVEL_READ_UNCOMMITTED)
|
||||
cur.execute("SHOW transaction_isolation;")
|
||||
if self.conn.server_version > 80000:
|
||||
if self.conn.info.server_version > 80000:
|
||||
self.assertEqual(cur.fetchone()[0], 'read uncommitted')
|
||||
else:
|
||||
self.assertEqual(cur.fetchone()[0], 'read committed')
|
||||
|
@ -1241,7 +1241,7 @@ class TransactionControlTests(ConnectingTestCase):
|
|||
|
||||
self.conn.set_session("repeatable read")
|
||||
cur.execute("SHOW transaction_isolation;")
|
||||
if self.conn.server_version > 80000:
|
||||
if self.conn.info.server_version > 80000:
|
||||
self.assertEqual(cur.fetchone()[0], 'repeatable read')
|
||||
else:
|
||||
self.assertEqual(cur.fetchone()[0], 'serializable')
|
||||
|
@ -1254,7 +1254,7 @@ class TransactionControlTests(ConnectingTestCase):
|
|||
|
||||
self.conn.set_session("read uncommitted")
|
||||
cur.execute("SHOW transaction_isolation;")
|
||||
if self.conn.server_version > 80000:
|
||||
if self.conn.info.server_version > 80000:
|
||||
self.assertEqual(cur.fetchone()[0], 'read uncommitted')
|
||||
else:
|
||||
self.assertEqual(cur.fetchone()[0], 'read committed')
|
||||
|
@ -1510,42 +1510,42 @@ class AutocommitTests(ConnectingTestCase):
|
|||
def test_default_no_autocommit(self):
|
||||
self.assert_(not self.conn.autocommit)
|
||||
self.assertEqual(self.conn.status, ext.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
ext.TRANSACTION_STATUS_IDLE)
|
||||
|
||||
cur = self.conn.cursor()
|
||||
cur.execute('select 1;')
|
||||
self.assertEqual(self.conn.status, ext.STATUS_BEGIN)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
ext.TRANSACTION_STATUS_INTRANS)
|
||||
|
||||
self.conn.rollback()
|
||||
self.assertEqual(self.conn.status, ext.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
ext.TRANSACTION_STATUS_IDLE)
|
||||
|
||||
def test_set_autocommit(self):
|
||||
self.conn.autocommit = True
|
||||
self.assert_(self.conn.autocommit)
|
||||
self.assertEqual(self.conn.status, ext.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
ext.TRANSACTION_STATUS_IDLE)
|
||||
|
||||
cur = self.conn.cursor()
|
||||
cur.execute('select 1;')
|
||||
self.assertEqual(self.conn.status, ext.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
ext.TRANSACTION_STATUS_IDLE)
|
||||
|
||||
self.conn.autocommit = False
|
||||
self.assert_(not self.conn.autocommit)
|
||||
self.assertEqual(self.conn.status, ext.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
ext.TRANSACTION_STATUS_IDLE)
|
||||
|
||||
cur.execute('select 1;')
|
||||
self.assertEqual(self.conn.status, ext.STATUS_BEGIN)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
ext.TRANSACTION_STATUS_INTRANS)
|
||||
|
||||
def test_set_intrans_error(self):
|
||||
|
@ -1558,24 +1558,24 @@ class AutocommitTests(ConnectingTestCase):
|
|||
self.conn.set_session(autocommit=True)
|
||||
self.assert_(self.conn.autocommit)
|
||||
self.assertEqual(self.conn.status, ext.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
ext.TRANSACTION_STATUS_IDLE)
|
||||
|
||||
cur = self.conn.cursor()
|
||||
cur.execute('select 1;')
|
||||
self.assertEqual(self.conn.status, ext.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
ext.TRANSACTION_STATUS_IDLE)
|
||||
|
||||
self.conn.set_session(autocommit=False)
|
||||
self.assert_(not self.conn.autocommit)
|
||||
self.assertEqual(self.conn.status, ext.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
ext.TRANSACTION_STATUS_IDLE)
|
||||
|
||||
cur.execute('select 1;')
|
||||
self.assertEqual(self.conn.status, ext.STATUS_BEGIN)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
ext.TRANSACTION_STATUS_INTRANS)
|
||||
self.conn.rollback()
|
||||
|
||||
|
@ -1583,7 +1583,7 @@ class AutocommitTests(ConnectingTestCase):
|
|||
self.assert_(self.conn.autocommit)
|
||||
cur.execute('select 1;')
|
||||
self.assertEqual(self.conn.status, ext.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
ext.TRANSACTION_STATUS_IDLE)
|
||||
cur.execute("SHOW transaction_isolation;")
|
||||
self.assertEqual(cur.fetchone()[0], 'serializable')
|
||||
|
@ -1690,17 +1690,156 @@ while True:
|
|||
self.assert_(not err, err)
|
||||
|
||||
|
||||
class TestConnectionProps(ConnectingTestCase):
|
||||
class TestConnectionInfo(ConnectingTestCase):
|
||||
def setUp(self):
|
||||
ConnectingTestCase.setUp(self)
|
||||
|
||||
class BrokenConn(psycopg2.extensions.connection):
|
||||
def __init__(self, *args, **kwargs):
|
||||
# don't call superclass
|
||||
pass
|
||||
|
||||
# A "broken" connection
|
||||
self.bconn = self.connect(connection_factory=BrokenConn)
|
||||
|
||||
def test_dbname(self):
|
||||
self.assert_(isinstance(self.conn.info.dbname, str))
|
||||
self.assert_(self.bconn.info.dbname is None)
|
||||
|
||||
def test_user(self):
|
||||
cur = self.conn.cursor()
|
||||
cur.execute("select user")
|
||||
self.assertEqual(self.conn.info.user, cur.fetchone()[0])
|
||||
self.assert_(self.bconn.info.user is None)
|
||||
|
||||
def test_password(self):
|
||||
self.assert_(isinstance(self.conn.info.password, str))
|
||||
self.assert_(self.bconn.info.password is None)
|
||||
|
||||
def test_host(self):
|
||||
self.assertFalse(self.conn.closed)
|
||||
expected = dbhost if dbhost else "/"
|
||||
self.assertIn(expected, self.conn.host)
|
||||
self.assertIn(expected, self.conn.info.host)
|
||||
self.assert_(self.bconn.info.host is None)
|
||||
|
||||
def test_host_readonly(self):
|
||||
self.assertFalse(self.conn.closed)
|
||||
with self.assertRaises(AttributeError):
|
||||
self.conn.host = 'override'
|
||||
self.conn.info.host = 'override'
|
||||
|
||||
def test_port(self):
|
||||
self.assert_(isinstance(self.conn.info.port, int))
|
||||
self.assert_(self.bconn.info.port is None)
|
||||
|
||||
def test_options(self):
|
||||
self.assert_(isinstance(self.conn.info.options, str))
|
||||
self.assert_(self.bconn.info.options is None)
|
||||
|
||||
def test_status(self):
|
||||
self.assertEqual(self.conn.info.status, 0)
|
||||
self.assertEqual(self.bconn.info.status, 1)
|
||||
|
||||
def test_transaction_status(self):
|
||||
self.assertEqual(self.conn.info.transaction_status, 0)
|
||||
cur = self.conn.cursor()
|
||||
cur.execute("select 1")
|
||||
self.assertEqual(self.conn.info.transaction_status, 2)
|
||||
self.assertEqual(self.bconn.info.transaction_status, 4)
|
||||
|
||||
def test_parameter_status(self):
|
||||
cur = self.conn.cursor()
|
||||
try:
|
||||
cur.execute("show server_version")
|
||||
except psycopg2.DatabaseError:
|
||||
self.assertIsInstance(
|
||||
self.conn.info.parameter_status('server_version'), str)
|
||||
else:
|
||||
self.assertEqual(
|
||||
self.conn.info.parameter_status('server_version'),
|
||||
cur.fetchone()[0])
|
||||
|
||||
self.assertIsNone(self.conn.info.parameter_status('wat'))
|
||||
self.assertIsNone(self.bconn.info.parameter_status('server_version'))
|
||||
|
||||
def test_protocol_version(self):
|
||||
self.assertEqual(self.conn.info.protocol_version, 3)
|
||||
self.assertEqual(self.bconn.info.protocol_version, 0)
|
||||
|
||||
def test_server_version(self):
|
||||
cur = self.conn.cursor()
|
||||
try:
|
||||
cur.execute("show server_version_num")
|
||||
except psycopg2.DatabaseError:
|
||||
self.assert_(isinstance(self.conn.info.server_version, int))
|
||||
else:
|
||||
self.assertEqual(
|
||||
self.conn.info.server_version, int(cur.fetchone()[0]))
|
||||
|
||||
self.assertEqual(self.bconn.info.server_version, 0)
|
||||
|
||||
def test_error_message(self):
|
||||
self.assertIsNone(self.conn.info.error_message)
|
||||
self.assertIsNotNone(self.bconn.info.error_message)
|
||||
|
||||
cur = self.conn.cursor()
|
||||
try:
|
||||
cur.execute("select 1 from nosuchtable")
|
||||
except psycopg2.DatabaseError:
|
||||
pass
|
||||
|
||||
self.assert_('nosuchtable' in self.conn.info.error_message)
|
||||
|
||||
def test_socket(self):
|
||||
self.assert_(self.conn.info.socket >= 0)
|
||||
self.assert_(self.bconn.info.socket < 0)
|
||||
|
||||
def test_backend_pid(self):
|
||||
cur = self.conn.cursor()
|
||||
try:
|
||||
cur.execute("select pg_backend_pid()")
|
||||
except psycopg2.DatabaseError:
|
||||
self.assert_(self.conn.info.backend_pid > 0)
|
||||
else:
|
||||
self.assertEqual(
|
||||
self.conn.info.backend_pid, int(cur.fetchone()[0]))
|
||||
|
||||
self.assert_(self.bconn.info.backend_pid == 0)
|
||||
|
||||
def test_needs_password(self):
|
||||
self.assertIs(self.conn.info.needs_password, False)
|
||||
self.assertIs(self.bconn.info.needs_password, False)
|
||||
|
||||
def test_used_password(self):
|
||||
self.assertIsInstance(self.conn.info.used_password, bool)
|
||||
self.assertIs(self.bconn.info.used_password, False)
|
||||
|
||||
@skip_before_libpq(9, 5)
|
||||
def test_ssl_in_use(self):
|
||||
self.assertIsInstance(self.conn.info.ssl_in_use, bool)
|
||||
self.assertIs(self.bconn.info.ssl_in_use, False)
|
||||
|
||||
@skip_after_libpq(9, 5)
|
||||
def test_ssl_not_supported(self):
|
||||
with self.assertRaises(psycopg2.NotSupportedError):
|
||||
self.conn.info.ssl_in_use
|
||||
with self.assertRaises(psycopg2.NotSupportedError):
|
||||
self.conn.info.ssl_attribute_names
|
||||
with self.assertRaises(psycopg2.NotSupportedError):
|
||||
self.conn.info.ssl_attribute('wat')
|
||||
|
||||
@skip_before_libpq(9, 5)
|
||||
def test_ssl_attribute(self):
|
||||
attribs = self.conn.info.ssl_attribute_names
|
||||
self.assert_(attribs)
|
||||
if self.conn.info.ssl_in_use:
|
||||
for attrib in attribs:
|
||||
self.assertIsInstance(self.conn.info.ssl_attribute(attrib), str)
|
||||
else:
|
||||
for attrib in attribs:
|
||||
self.assertIsNone(self.conn.info.ssl_attribute(attrib))
|
||||
|
||||
self.assertIsNone(self.conn.info.ssl_attribute('wat'))
|
||||
|
||||
for attrib in attribs:
|
||||
self.assertIsNone(self.bconn.info.ssl_attribute(attrib))
|
||||
|
||||
|
||||
def test_suite():
|
||||
|
|
|
@ -229,22 +229,22 @@ class CursorTests(ConnectingTestCase):
|
|||
curs.execute("select data from withhold order by data")
|
||||
self.assertEqual(curs.fetchone(), (10,))
|
||||
self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_BEGIN)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
psycopg2.extensions.TRANSACTION_STATUS_INTRANS)
|
||||
|
||||
self.conn.commit()
|
||||
self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
psycopg2.extensions.TRANSACTION_STATUS_IDLE)
|
||||
|
||||
self.assertEqual(curs.fetchone(), (20,))
|
||||
self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
psycopg2.extensions.TRANSACTION_STATUS_IDLE)
|
||||
|
||||
curs.close()
|
||||
self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
psycopg2.extensions.TRANSACTION_STATUS_IDLE)
|
||||
|
||||
def test_withhold_autocommit(self):
|
||||
|
@ -256,17 +256,17 @@ class CursorTests(ConnectingTestCase):
|
|||
|
||||
self.assertEqual(curs.fetchone(), (10,))
|
||||
self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
psycopg2.extensions.TRANSACTION_STATUS_IDLE)
|
||||
|
||||
self.conn.commit()
|
||||
self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
psycopg2.extensions.TRANSACTION_STATUS_IDLE)
|
||||
|
||||
curs.close()
|
||||
self.assertEqual(self.conn.status, psycopg2.extensions.STATUS_READY)
|
||||
self.assertEqual(self.conn.get_transaction_status(),
|
||||
self.assertEqual(self.conn.info.transaction_status,
|
||||
psycopg2.extensions.TRANSACTION_STATUS_IDLE)
|
||||
|
||||
def test_scrollable(self):
|
||||
|
|
|
@ -37,7 +37,7 @@ from .testutils import (decorate_all_tests, skip_if_tpc_disabled,
|
|||
def skip_if_no_lo(f):
|
||||
@wraps(f)
|
||||
def skip_if_no_lo_(self):
|
||||
if self.conn.server_version < 80100:
|
||||
if self.conn.info.server_version < 80100:
|
||||
return self.skipTest("large objects only supported from PG 8.1")
|
||||
else:
|
||||
return f(self)
|
||||
|
@ -403,7 +403,7 @@ decorate_all_tests(LargeObjectTests, skip_if_no_lo, skip_lo_if_green)
|
|||
def skip_if_no_truncate(f):
|
||||
@wraps(f)
|
||||
def skip_if_no_truncate_(self):
|
||||
if self.conn.server_version < 80300:
|
||||
if self.conn.info.server_version < 80300:
|
||||
return self.skipTest(
|
||||
"the server doesn't support large object truncate")
|
||||
|
||||
|
@ -459,9 +459,9 @@ decorate_all_tests(LargeObjectTruncateTests,
|
|||
|
||||
def _has_lo64(conn):
|
||||
"""Return (bool, msg) about the lo64 support"""
|
||||
if conn.server_version < 90300:
|
||||
if conn.info.server_version < 90300:
|
||||
return (False, "server version %s doesn't support the lo64 API"
|
||||
% conn.server_version)
|
||||
% conn.info.server_version)
|
||||
|
||||
if 'lo64' not in psycopg2.__version__:
|
||||
return False, "this psycopg build doesn't support the lo64 API"
|
||||
|
|
|
@ -61,7 +61,7 @@ import %(module)s as psycopg2
|
|||
import %(module)s.extensions as ext
|
||||
conn = psycopg2.connect(%(dsn)r)
|
||||
conn.set_isolation_level(ext.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
print(conn.get_backend_pid())
|
||||
print(conn.info.backend_pid)
|
||||
curs = conn.cursor()
|
||||
curs.execute("NOTIFY " %(name)r %(payload)r)
|
||||
curs.close()
|
||||
|
@ -147,9 +147,9 @@ conn.close()
|
|||
|
||||
@slow
|
||||
def test_notify_payload(self):
|
||||
if self.conn.server_version < 90000:
|
||||
if self.conn.info.server_version < 90000:
|
||||
return self.skipTest("server version %s doesn't support notify payload"
|
||||
% self.conn.server_version)
|
||||
% self.conn.info.server_version)
|
||||
self.autocommit(self.conn)
|
||||
self.listen('foo')
|
||||
pid = int(self.notify('foo', payload="Hello, world!").communicate()[0])
|
||||
|
|
|
@ -90,7 +90,7 @@ class QuotingTestCase(ConnectingTestCase):
|
|||
else:
|
||||
res = curs.fetchone()[0].tobytes()
|
||||
|
||||
if res[0] in (b'x', ord(b'x')) and self.conn.server_version >= 90000:
|
||||
if res[0] in (b'x', ord(b'x')) and self.conn.info.server_version >= 90000:
|
||||
return self.skipTest(
|
||||
"bytea broken with server >= 9.0, libpq < 9")
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ def skip_if_no_hstore(f):
|
|||
|
||||
class HstoreTestCase(ConnectingTestCase):
|
||||
def test_adapt_8(self):
|
||||
if self.conn.server_version >= 90000:
|
||||
if self.conn.info.server_version >= 90000:
|
||||
return self.skipTest("skipping dict adaptation with PG pre-9 syntax")
|
||||
|
||||
from psycopg2.extras import HstoreAdapter
|
||||
|
@ -163,7 +163,7 @@ class HstoreTestCase(ConnectingTestCase):
|
|||
self.assertQuotedEqual(ii[3], b"('d' => '" + encc + b"')")
|
||||
|
||||
def test_adapt_9(self):
|
||||
if self.conn.server_version < 90000:
|
||||
if self.conn.info.server_version < 90000:
|
||||
return self.skipTest("skipping dict adaptation with PG 9 syntax")
|
||||
|
||||
from psycopg2.extras import HstoreAdapter
|
||||
|
@ -448,10 +448,10 @@ class HstoreTestCase(ConnectingTestCase):
|
|||
def skip_if_no_composite(f):
|
||||
@wraps(f)
|
||||
def skip_if_no_composite_(self):
|
||||
if self.conn.server_version < 80000:
|
||||
if self.conn.info.server_version < 80000:
|
||||
return self.skipTest(
|
||||
"server version %s doesn't support composite types"
|
||||
% self.conn.server_version)
|
||||
% self.conn.info.server_version)
|
||||
|
||||
return f(self)
|
||||
|
||||
|
@ -1436,10 +1436,10 @@ class RangeTestCase(unittest.TestCase):
|
|||
def skip_if_no_range(f):
|
||||
@wraps(f)
|
||||
def skip_if_no_range_(self):
|
||||
if self.conn.server_version < 90200:
|
||||
if self.conn.info.server_version < 90200:
|
||||
return self.skipTest(
|
||||
"server version %s doesn't support range types"
|
||||
% self.conn.server_version)
|
||||
% self.conn.info.server_version)
|
||||
|
||||
return f(self)
|
||||
|
||||
|
|
|
@ -234,9 +234,9 @@ def skip_before_postgres(*ver):
|
|||
def skip_before_postgres_(f):
|
||||
@wraps(f)
|
||||
def skip_before_postgres__(self):
|
||||
if self.conn.server_version < int("%d%02d%02d" % ver):
|
||||
if self.conn.info.server_version < int("%d%02d%02d" % ver):
|
||||
return self.skipTest("skipped because PostgreSQL %s"
|
||||
% self.conn.server_version)
|
||||
% self.conn.info.server_version)
|
||||
else:
|
||||
return f(self)
|
||||
|
||||
|
@ -251,9 +251,9 @@ def skip_after_postgres(*ver):
|
|||
def skip_after_postgres_(f):
|
||||
@wraps(f)
|
||||
def skip_after_postgres__(self):
|
||||
if self.conn.server_version >= int("%d%02d%02d" % ver):
|
||||
if self.conn.info.server_version >= int("%d%02d%02d" % ver):
|
||||
return self.skipTest("skipped because PostgreSQL %s"
|
||||
% self.conn.server_version)
|
||||
% self.conn.info.server_version)
|
||||
else:
|
||||
return f(self)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user