From 263f428213b92d1e98514cf316c357c6c03b7c17 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Mon, 13 Dec 2021 05:55:10 +0100 Subject: [PATCH] CONPY-184 Display status of connection, cursor and pool class in string representation. If an object (cursor, class, connection pool) was closed, the string representation (tp_repr) now shows the status of the object. Example: >>> import mariadb >>> connection=mariadb.connect() >>> connection >>> connection.close() >>> connection --- include/mariadb_python.h | 9 +++++---- mariadb/connectionpool.py | 11 +++++++++-- mariadb/connections.py | 1 + mariadb/mariadb_connection.c | 22 +++++++++++++++++++++- mariadb/mariadb_cursor.c | 22 +++++++++++++++++----- 5 files changed, 53 insertions(+), 12 deletions(-) diff --git a/include/mariadb_python.h b/include/mariadb_python.h index a25d4e5..16f5c57 100755 --- a/include/mariadb_python.h +++ b/include/mariadb_python.h @@ -181,9 +181,9 @@ typedef struct { enum enum_tpc_state tpc_state; char xid[150]; /* large enough, to hold 2 * MAX_TPC_XID size + integer value */ PyObject *dsn; /* always null */ + const char *host; /* const char *tls_cipher; const char *tls_version; - const char *host; const char *unix_socket; int port; const char *charset; @@ -195,6 +195,7 @@ typedef struct { PyThreadState *thread_state; unsigned long thread_id; char *server_info; + uint8_t closed; } MrdbConnection; typedef struct { @@ -265,7 +266,7 @@ typedef struct { uint8_t is_prepared; char is_buffered; uint8_t fetched; - uint8_t is_closed; + uint8_t closed; uint8_t reprepare; PyThreadState *thread_state; enum enum_paramstyle paramstyle; @@ -434,9 +435,9 @@ MrdbParser_parse(MrdbParser *p, uint8_t is_batch, char *errmsg, size_t errmsg_le } #define MARIADB_CHECK_STMT(cursor)\ - if (!cursor->connection->mysql || cursor->is_closed)\ + if (!cursor->connection->mysql || cursor->closed)\ {\ - (cursor)->is_closed= 1;\ + (cursor)->closed= 1;\ mariadb_throw_exception(cursor->stmt, Mariadb_ProgrammingError, 1,\ "Invalid cursor or not connected");\ } diff --git a/mariadb/connectionpool.py b/mariadb/connectionpool.py index cf9b81b..8098aa0 100644 --- a/mariadb/connectionpool.py +++ b/mariadb/connectionpool.py @@ -24,7 +24,7 @@ POOL_IDLE_TIMEOUT = 1800 class ConnectionPool(object): - r""" + """ Class defining a pool of database connections MariaDB Connector/Python supports simple connection pooling. @@ -39,7 +39,7 @@ class ConnectionPool(object): * pool_name (str) -- Name of connection pool - * pool_size (int)=5 -- Size of pool. If not specified default value of 5 will be used. Maximum allowed number is 64. + * pool_size (int)=5 -- Size of pool. If not specified default value of 5 will be used. Maximum allowed number is 64. * pool_reset_connection (bool)=True -- Will reset the connection before returning it to the pool. Default value is True. """ @@ -63,6 +63,7 @@ def __init__(self, *args, **kwargs): self._pool_args = {} self._conn_args = {} self._lock_pool = _thread.RLock() + self.__closed= 0 key_words= ["pool_name", "pool_size", "pool_reset_connection"] @@ -115,6 +116,12 @@ def __init__(self, *args, **kwargs): # store connection pool in _CONNECTION_POOLS mariadb._CONNECTION_POOLS[self._pool_args["name"]]= self + def __repr__(self): + if (self.__closed): + return "" % (hex(id(self)),) + else: + return "" % (self.pool_name, hex(id(self))) + def add_connection(self, connection= None): """ Adds a connection object to the connection pool. diff --git a/mariadb/connections.py b/mariadb/connections.py index 5b92805..e082612 100644 --- a/mariadb/connections.py +++ b/mariadb/connections.py @@ -50,6 +50,7 @@ def __init__(self, *args, **kwargs): self.__last_used = 0 self.tpc_state= TPC_STATE.NONE self._xid= None + self.__closed= None autocommit= kwargs.pop("autocommit", False) self._converter= kwargs.pop("converter", None) diff --git a/mariadb/mariadb_connection.c b/mariadb/mariadb_connection.c index 00133df..1d30028 100644 --- a/mariadb/mariadb_connection.c +++ b/mariadb/mariadb_connection.c @@ -159,6 +159,11 @@ PyMemberDef MrdbConnection_Members[] = offsetof(MrdbConnection, dsn), READONLY, "Data source name (dsn)"}, + {"_closed", + T_BOOL, + offsetof(MrdbConnection, closed), + READONLY, + "Indicates if connection was closed"}, {NULL} /* always last */ }; @@ -307,6 +312,7 @@ MrdbConnection_Initialize(MrdbConnection *self, } self->thread_id= mysql_thread_id(self->mysql); + mariadb_get_infov(self->mysql, MARIADB_CONNECTION_HOST, &self->host); has_error= 0; end: @@ -332,6 +338,19 @@ static int MrdbConnection_traverse( return 0; } +static PyObject *MrdbConnection_repr(MrdbConnection *self) +{ + char cobj_repr[384]; + + if (!self->closed) + snprintf(cobj_repr, 384, "", + self->host, self); + else + snprintf(cobj_repr, 384, "", + self); + return PyUnicode_FromString(cobj_repr); +} + PyTypeObject MrdbConnection_Type = { PyVarObject_HEAD_INIT(NULL, 0) "mariadb.connection", @@ -342,7 +361,7 @@ PyTypeObject MrdbConnection_Type = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* PyAsyncMethods* */ - 0, /* tp_repr */ + (reprfunc)MrdbConnection_repr, /* tp_repr */ /* Method suites for standard classes */ @@ -467,6 +486,7 @@ PyObject *MrdbConnection_close(MrdbConnection *self) mysql_close(self->mysql); Py_END_ALLOW_THREADS self->mysql= NULL; + self->closed= 1; Py_RETURN_NONE; } diff --git a/mariadb/mariadb_cursor.c b/mariadb/mariadb_cursor.c index 70d9563..d8f7f2a 100644 --- a/mariadb/mariadb_cursor.c +++ b/mariadb/mariadb_cursor.c @@ -318,6 +318,18 @@ static int MrdbCursor_traverse( return 0; } +static PyObject *MrdbCursor_repr(MrdbCursor *self) +{ + char cobj_repr[384]; + + if (!self->closed) + snprintf(cobj_repr, 384, "", self); + else + snprintf(cobj_repr, 384, "", + self); + return PyUnicode_FromString(cobj_repr); +} + PyTypeObject MrdbCursor_Type = { PyVarObject_HEAD_INIT(NULL, 0) @@ -329,7 +341,7 @@ PyTypeObject MrdbCursor_Type = 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* PyAsyncMethods * */ - 0, /* tp_repr */ + (reprfunc)MrdbCursor_repr, /* tp_repr */ /* Method suites for standard classes */ @@ -503,7 +515,7 @@ static void ma_set_result_column_value(MrdbCursor *self, PyObject *row, uint32_t static void ma_cursor_close(MrdbCursor *self) { - if (!self->is_closed) + if (!self->closed) { MrdbCursor_clear_result(self); if (!self->parseinfo.is_text && self->stmt) @@ -524,11 +536,11 @@ void ma_cursor_close(MrdbCursor *self) } MrdbCursor_clearparseinfo(&self->parseinfo); - self->is_closed= 1; + self->closed= 1; } } - static +static PyObject * MrdbCursor_close(MrdbCursor *self) { ma_cursor_close(self); @@ -949,7 +961,7 @@ MrdbCursor_iternext(PyObject *self) static PyObject *MrdbCursor_closed(MrdbCursor *self) { - if (self->is_closed || self->connection->mysql == NULL) + if (self->closed || self->connection->mysql == NULL) Py_RETURN_TRUE; Py_RETURN_FALSE; }