mirror of
https://github.com/PyMySQL/mysqlclient.git
synced 2025-08-15 19:31:54 +08:00
GC for Python 2.2+
This commit is contained in:
116
MySQLdb/_mysql.c
116
MySQLdb/_mysql.c
@ -28,7 +28,7 @@ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|||||||
PERFORMANCE OF THIS SOFTWARE.
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Python.h"
|
#include "pymemcompat.h"
|
||||||
|
|
||||||
#ifdef MS_WIN32
|
#ifdef MS_WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -42,11 +42,6 @@ PERFORMANCE OF THIS SOFTWARE.
|
|||||||
#include "mysqld_error.h"
|
#include "mysqld_error.h"
|
||||||
#include "errmsg.h"
|
#include "errmsg.h"
|
||||||
|
|
||||||
#if PY_VERSION_HEX < 0x01060000
|
|
||||||
# define PyObject_Del(x) PyMem_Free((char *) x)
|
|
||||||
# define PyObject_New(s,t) PyObject_NEW(s,t)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PY_VERSION_HEX < 0x02020000
|
#if PY_VERSION_HEX < 0x02020000
|
||||||
# define MyTuple_Resize(t,n,d) _PyTuple_Resize(t, n, d)
|
# define MyTuple_Resize(t,n,d) _PyTuple_Resize(t, n, d)
|
||||||
# define MyMember(a,b,c,d,e) {a,b,c,d}
|
# define MyMember(a,b,c,d,e) {a,b,c,d}
|
||||||
@ -206,7 +201,9 @@ _mysql_ResultObject_Initialize(
|
|||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iO", kwlist,
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iO", kwlist,
|
||||||
&conn, &use, &conv))
|
&conn, &use, &conv))
|
||||||
goto error;
|
return -1;
|
||||||
|
if (!conv) conv = PyDict_New();
|
||||||
|
if (!conv) return -1;
|
||||||
self->conn = (PyObject *) conn;
|
self->conn = (PyObject *) conn;
|
||||||
Py_INCREF(conn);
|
Py_INCREF(conn);
|
||||||
self->use = use;
|
self->use = use;
|
||||||
@ -223,12 +220,12 @@ _mysql_ResultObject_Initialize(
|
|||||||
}
|
}
|
||||||
n = mysql_num_fields(result);
|
n = mysql_num_fields(result);
|
||||||
self->nfields = n;
|
self->nfields = n;
|
||||||
if (!(self->converter = PyTuple_New(n))) goto error;
|
if (!(self->converter = PyTuple_New(n))) return -1;
|
||||||
fields = mysql_fetch_fields(result);
|
fields = mysql_fetch_fields(result);
|
||||||
for (i=0; i<n; i++) {
|
for (i=0; i<n; i++) {
|
||||||
PyObject *tmp, *fun;
|
PyObject *tmp, *fun;
|
||||||
tmp = PyInt_FromLong((long) fields[i].type);
|
tmp = PyInt_FromLong((long) fields[i].type);
|
||||||
if (!tmp) goto error;
|
if (!tmp) return -1;
|
||||||
fun = PyObject_GetItem(conv, tmp);
|
fun = PyObject_GetItem(conv, tmp);
|
||||||
Py_DECREF(tmp);
|
Py_DECREF(tmp);
|
||||||
if (!fun) {
|
if (!fun) {
|
||||||
@ -239,8 +236,32 @@ _mysql_ResultObject_Initialize(
|
|||||||
PyTuple_SET_ITEM(self->converter, i, fun);
|
PyTuple_SET_ITEM(self->converter, i, fun);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
error:
|
}
|
||||||
return -1;
|
|
||||||
|
#if PY_VERSION_HEX >= 0x02020000
|
||||||
|
static int _mysql_ResultObject_traverse(
|
||||||
|
_mysql_ResultObject *self,
|
||||||
|
visitproc visit,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
if (self->converter) {
|
||||||
|
if (!(r = visit(self->converter, arg))) return r;
|
||||||
|
}
|
||||||
|
if (self->conn)
|
||||||
|
return visit(self->conn, arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int _mysql_ResultObject_clear(
|
||||||
|
_mysql_ResultObject *self)
|
||||||
|
{
|
||||||
|
Py_XDECREF(self->converter);
|
||||||
|
self->converter = NULL;
|
||||||
|
Py_XDECREF(self->conn);
|
||||||
|
self->conn = NULL;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -276,10 +297,8 @@ _mysql_ConnectionObject_Initialize(
|
|||||||
&connect_timeout,
|
&connect_timeout,
|
||||||
&compress, &named_pipe,
|
&compress, &named_pipe,
|
||||||
&init_command, &read_default_file,
|
&init_command, &read_default_file,
|
||||||
&read_default_group)) {
|
&read_default_group))
|
||||||
Py_DECREF(self);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if (!conv)
|
if (!conv)
|
||||||
conv = PyDict_New();
|
conv = PyDict_New();
|
||||||
@ -287,9 +306,9 @@ _mysql_ConnectionObject_Initialize(
|
|||||||
else
|
else
|
||||||
Py_INCREF(conv);
|
Py_INCREF(conv);
|
||||||
#endif
|
#endif
|
||||||
self->converter = conv;
|
if (!conv)
|
||||||
if (!(self->converter))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
self->converter = conv;
|
||||||
|
|
||||||
self->open = 1;
|
self->open = 1;
|
||||||
Py_BEGIN_ALLOW_THREADS ;
|
Py_BEGIN_ALLOW_THREADS ;
|
||||||
@ -319,6 +338,12 @@ _mysql_ConnectionObject_Initialize(
|
|||||||
_mysql_Exception(self);
|
_mysql_Exception(self);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
PyType_GenericAlloc() automatically sets up GC allocation and
|
||||||
|
tracking for GC objects, at least in 2.2.1, so it does not need to
|
||||||
|
be done here. tp_dealloc still needs to call PyObject_GC_UnTrack(),
|
||||||
|
however.
|
||||||
|
*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,16 +377,35 @@ _mysql_connect(
|
|||||||
{
|
{
|
||||||
_mysql_ConnectionObject *c=NULL;
|
_mysql_ConnectionObject *c=NULL;
|
||||||
|
|
||||||
c = PyObject_New(_mysql_ConnectionObject,
|
c = MyAlloc(_mysql_ConnectionObject, _mysql_ConnectionObject_Type);
|
||||||
&_mysql_ConnectionObject_Type);
|
|
||||||
if (c == NULL) return NULL;
|
if (c == NULL) return NULL;
|
||||||
if (_mysql_ConnectionObject_Initialize(c, args, kwargs)) {
|
if (_mysql_ConnectionObject_Initialize(c, args, kwargs)) {
|
||||||
Py_DECREF(c);
|
Py_DECREF(c);
|
||||||
return NULL;
|
c = NULL;
|
||||||
}
|
}
|
||||||
return (PyObject *) c;
|
return (PyObject *) c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX >= 0x02020000
|
||||||
|
static int _mysql_ConnectionObject_traverse(
|
||||||
|
_mysql_ConnectionObject *self,
|
||||||
|
visitproc visit,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
if (self->converter)
|
||||||
|
return visit(self->converter, arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int _mysql_ConnectionObject_clear(
|
||||||
|
_mysql_ConnectionObject *self)
|
||||||
|
{
|
||||||
|
Py_XDECREF(self->converter);
|
||||||
|
self->converter = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static char _mysql_ConnectionObject_close__doc__[] =
|
static char _mysql_ConnectionObject_close__doc__[] =
|
||||||
"Close the connection. No further activity possible.";
|
"Close the connection. No further activity possible.";
|
||||||
|
|
||||||
@ -377,8 +421,7 @@ _mysql_ConnectionObject_close(
|
|||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
self->open = 0;
|
self->open = 0;
|
||||||
}
|
}
|
||||||
Py_XDECREF(self->converter);
|
_mysql_ConnectionObject_clear(self);
|
||||||
self->converter = NULL;
|
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
@ -1442,6 +1485,7 @@ _mysql_ConnectionObject_dealloc(
|
|||||||
{
|
{
|
||||||
PyObject *o;
|
PyObject *o;
|
||||||
|
|
||||||
|
PyObject_GC_UnTrack(self);
|
||||||
if (self->open) {
|
if (self->open) {
|
||||||
o = _mysql_ConnectionObject_close(self, NULL);
|
o = _mysql_ConnectionObject_close(self, NULL);
|
||||||
Py_XDECREF(o);
|
Py_XDECREF(o);
|
||||||
@ -1455,11 +1499,11 @@ _mysql_ConnectionObject_repr(
|
|||||||
{
|
{
|
||||||
char buf[300];
|
char buf[300];
|
||||||
if (self->open)
|
if (self->open)
|
||||||
sprintf(buf, "<open connection to '%.256s' at %lx>",
|
sprintf(buf, "<_mysql.connection open to '%.256s' at %lx>",
|
||||||
self->connection.host,
|
self->connection.host,
|
||||||
(long)self);
|
(long)self);
|
||||||
else
|
else
|
||||||
sprintf(buf, "<closed connection at %lx>",
|
sprintf(buf, "<_mysql.connection closed at %lx>",
|
||||||
(long)self);
|
(long)self);
|
||||||
return PyString_FromString(buf);
|
return PyString_FromString(buf);
|
||||||
}
|
}
|
||||||
@ -1514,9 +1558,9 @@ static void
|
|||||||
_mysql_ResultObject_dealloc(
|
_mysql_ResultObject_dealloc(
|
||||||
_mysql_ResultObject *self)
|
_mysql_ResultObject *self)
|
||||||
{
|
{
|
||||||
|
PyObject_GC_UnTrack((PyObject *)self);
|
||||||
mysql_free_result(self->result);
|
mysql_free_result(self->result);
|
||||||
Py_DECREF(self->conn);
|
_mysql_ResultObject_clear(self);
|
||||||
Py_XDECREF(self->converter);
|
|
||||||
MyFree(self);
|
MyFree(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1525,7 +1569,7 @@ _mysql_ResultObject_repr(
|
|||||||
_mysql_ResultObject *self)
|
_mysql_ResultObject *self)
|
||||||
{
|
{
|
||||||
char buf[300];
|
char buf[300];
|
||||||
sprintf(buf, "<result object at %lx>",
|
sprintf(buf, "<_mysql.result object at %lx>",
|
||||||
(long)self);
|
(long)self);
|
||||||
return PyString_FromString(buf);
|
return PyString_FromString(buf);
|
||||||
}
|
}
|
||||||
@ -1919,16 +1963,16 @@ PyTypeObject _mysql_ConnectionObject_Type = {
|
|||||||
#if PY_VERSION_HEX < 0x02020000
|
#if PY_VERSION_HEX < 0x02020000
|
||||||
Py_TPFLAGS_DEFAULT, /* (long) tp_flags */
|
Py_TPFLAGS_DEFAULT, /* (long) tp_flags */
|
||||||
#else
|
#else
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
|
||||||
#endif
|
#endif
|
||||||
_mysql_connect__doc__, /* (char *) tp_doc Documentation string */
|
_mysql_connect__doc__, /* (char *) tp_doc Documentation string */
|
||||||
#if PY_VERSION_HEX >= 0x02000000
|
#if PY_VERSION_HEX >= 0x02000000
|
||||||
/* Assigned meaning in release 2.0 */
|
/* Assigned meaning in release 2.0 */
|
||||||
/* call function for all accessible objects */
|
/* call function for all accessible objects */
|
||||||
0, /* (traverseproc) tp_traverse */
|
(traverseproc) _mysql_ConnectionObject_traverse, /* tp_traverse */
|
||||||
|
|
||||||
/* delete references to contained objects */
|
/* delete references to contained objects */
|
||||||
0, /* (inquiry) tp_clear */
|
(inquiry) _mysql_ConnectionObject_clear, /* tp_clear */
|
||||||
#if PY_VERSION_HEX >= 0x02010000
|
#if PY_VERSION_HEX >= 0x02010000
|
||||||
/* Assigned meaning in release 2.1 */
|
/* Assigned meaning in release 2.1 */
|
||||||
/* rich comparisons */
|
/* rich comparisons */
|
||||||
@ -1954,7 +1998,7 @@ PyTypeObject _mysql_ConnectionObject_Type = {
|
|||||||
(initproc)_mysql_ConnectionObject_Initialize, /* tp_init */
|
(initproc)_mysql_ConnectionObject_Initialize, /* tp_init */
|
||||||
(allocfunc)PyType_GenericAlloc, /* tp_alloc */
|
(allocfunc)PyType_GenericAlloc, /* tp_alloc */
|
||||||
(newfunc)PyType_GenericNew, /* tp_new */
|
(newfunc)PyType_GenericNew, /* tp_new */
|
||||||
(destructor)_PyObject_Del, /* tp_free Low-level free-memory routine */
|
(destructor)_PyObject_GC_Del, /* tp_free Low-level free-memory routine */
|
||||||
0, /* (PyObject *) tp_bases */
|
0, /* (PyObject *) tp_bases */
|
||||||
0, /* (PyObject *) tp_mro method resolution order */
|
0, /* (PyObject *) tp_mro method resolution order */
|
||||||
0, /* (PyObject *) tp_defined */
|
0, /* (PyObject *) tp_defined */
|
||||||
@ -1998,16 +2042,20 @@ PyTypeObject _mysql_ResultObject_Type = {
|
|||||||
0, /* (PyBufferProcs *) tp_as_buffer */
|
0, /* (PyBufferProcs *) tp_as_buffer */
|
||||||
|
|
||||||
/* Flags to define presence of optional/expanded features */
|
/* Flags to define presence of optional/expanded features */
|
||||||
0, /* (long) tp_flags */
|
#if PY_VERSION_HEX < 0x02020000
|
||||||
|
Py_TPFLAGS_DEFAULT, /* (long) tp_flags */
|
||||||
|
#else
|
||||||
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
|
||||||
|
#endif
|
||||||
|
|
||||||
_mysql_ResultObject__doc__, /* (char *) tp_doc Documentation string */
|
_mysql_ResultObject__doc__, /* (char *) tp_doc Documentation string */
|
||||||
#if PY_VERSION_HEX >= 0x02000000
|
#if PY_VERSION_HEX >= 0x02000000
|
||||||
/* Assigned meaning in release 2.0 */
|
/* Assigned meaning in release 2.0 */
|
||||||
/* call function for all accessible objects */
|
/* call function for all accessible objects */
|
||||||
0, /* (traverseproc) tp_traverse */
|
(traverseproc) _mysql_ResultObject_traverse, /* tp_traverse */
|
||||||
|
|
||||||
/* delete references to contained objects */
|
/* delete references to contained objects */
|
||||||
0, /* (inquiry) tp_clear */
|
(inquiry) _mysql_ResultObject_clear, /* tp_clear */
|
||||||
#if PY_VERSION_HEX >= 0x02010000
|
#if PY_VERSION_HEX >= 0x02010000
|
||||||
/* Assigned meaning in release 2.1 */
|
/* Assigned meaning in release 2.1 */
|
||||||
/* rich comparisons */
|
/* rich comparisons */
|
||||||
@ -2033,7 +2081,7 @@ PyTypeObject _mysql_ResultObject_Type = {
|
|||||||
(initproc)_mysql_ResultObject_Initialize, /* tp_init */
|
(initproc)_mysql_ResultObject_Initialize, /* tp_init */
|
||||||
(allocfunc)PyType_GenericAlloc, /* tp_alloc */
|
(allocfunc)PyType_GenericAlloc, /* tp_alloc */
|
||||||
(newfunc)PyType_GenericNew, /* tp_new */
|
(newfunc)PyType_GenericNew, /* tp_new */
|
||||||
(destructor)_PyObject_Del, /* tp_free Low-level free-memory routine */
|
(destructor)_PyObject_GC_Del, /* tp_free Low-level free-memory routine */
|
||||||
0, /* (PyObject *) tp_bases */
|
0, /* (PyObject *) tp_bases */
|
||||||
0, /* (PyObject *) tp_mro method resolution order */
|
0, /* (PyObject *) tp_mro method resolution order */
|
||||||
0, /* (PyObject *) tp_defined */
|
0, /* (PyObject *) tp_defined */
|
||||||
|
Reference in New Issue
Block a user