mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-01-31 01:14:09 +03:00
Fixed refcount bug in copy_to() and copy_expert() methods too
This commit is contained in:
parent
1888bf41c0
commit
b6e710b0fc
|
@ -1343,8 +1343,6 @@ static int
|
|||
_psyco_curs_has_write_check(PyObject* o, void* var)
|
||||
{
|
||||
if (PyObject_HasAttrString(o, "write")) {
|
||||
/* It's OK to store a borrowed reference, because it is only held for
|
||||
* the duration of psyco_curs_copy_to. */
|
||||
*((PyObject**)var) = o;
|
||||
return 1;
|
||||
}
|
||||
|
@ -1430,12 +1428,15 @@ psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
Dprintf("psyco_curs_copy_to: query = %s", query);
|
||||
|
||||
self->copysize = 0;
|
||||
Py_INCREF(file);
|
||||
self->copyfile = file;
|
||||
|
||||
if (pq_execute(self, query, 0) == 1) {
|
||||
res = Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
}
|
||||
|
||||
Py_DECREF(file);
|
||||
self->copyfile = NULL;
|
||||
|
||||
exit:
|
||||
|
@ -1477,18 +1478,18 @@ psyco_curs_copy_expert(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
EXC_IF_TPC_PREPARED(self->conn, copy_expert);
|
||||
|
||||
sql = _psyco_curs_validate_sql_basic(self, sql);
|
||||
|
||||
/* Any failure from here forward should 'goto fail' rather than
|
||||
|
||||
/* Any failure from here forward should 'goto exit' rather than
|
||||
'return NULL' directly. */
|
||||
|
||||
if (sql == NULL) { goto fail; }
|
||||
|
||||
if (sql == NULL) { goto exit; }
|
||||
|
||||
/* This validation of file is rather weak, in that it doesn't enforce the
|
||||
assocation between "COPY FROM" -> "read" and "COPY TO" -> "write".
|
||||
However, the error handling in _pq_copy_[in|out] must be able to handle
|
||||
the case where the attempt to call file.read|write fails, so no harm
|
||||
done. */
|
||||
|
||||
|
||||
if ( !PyObject_HasAttrString(file, "read")
|
||||
&& !PyObject_HasAttrString(file, "write")
|
||||
)
|
||||
|
@ -1496,26 +1497,22 @@ psyco_curs_copy_expert(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
PyErr_SetString(PyExc_TypeError, "file must be a readable file-like"
|
||||
" object for COPY FROM; a writeable file-like object for COPY TO."
|
||||
);
|
||||
goto fail;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
self->copysize = bufsize;
|
||||
Py_INCREF(file);
|
||||
self->copyfile = file;
|
||||
|
||||
/* At this point, the SQL statement must be str, not unicode */
|
||||
if (pq_execute(self, Bytes_AS_STRING(sql), 0) != 1) { goto fail; }
|
||||
if (pq_execute(self, Bytes_AS_STRING(sql), 0) != 1) { goto exit; }
|
||||
|
||||
res = Py_None;
|
||||
Py_INCREF(res);
|
||||
goto cleanup;
|
||||
fail:
|
||||
if (res != NULL) {
|
||||
Py_DECREF(res);
|
||||
res = NULL;
|
||||
}
|
||||
/* Fall through to cleanup */
|
||||
cleanup:
|
||||
|
||||
exit:
|
||||
self->copyfile = NULL;
|
||||
Py_XDECREF(file);
|
||||
Py_XDECREF(sql);
|
||||
|
||||
return res;
|
||||
|
|
|
@ -42,13 +42,29 @@ cur = conn.cursor()
|
|||
gc_thread.start()
|
||||
|
||||
# Now do lots of "cursor.copy_from" calls:
|
||||
print "copy_from"
|
||||
for i in range(1000):
|
||||
f = StringIO("42\tfoo\n74\tbar\n")
|
||||
cur.copy_from(f, 'test', columns=('num', 'data'))
|
||||
# Assuming the other thread gets a chance to run during this call, expect a
|
||||
# build of python (with assertions enabled) to bail out here with:
|
||||
# python: Modules/gcmodule.c:277: visit_decref: Assertion `gc->gc.gc_refs != 0' failed.
|
||||
|
||||
|
||||
# Also exercise the copy_to code path
|
||||
print "copy_to"
|
||||
cur.execute("truncate test")
|
||||
f = StringIO("42\tfoo\n74\tbar\n")
|
||||
cur.copy_from(f, 'test', columns=('num', 'data'))
|
||||
for i in range(1000):
|
||||
f = StringIO()
|
||||
cur.copy_to(f, 'test', columns=('num', 'data'))
|
||||
|
||||
# And copy_expert too
|
||||
print "copy_expert"
|
||||
cur.execute("truncate test")
|
||||
for i in range(1000):
|
||||
f = StringIO("42\tfoo\n74\tbar\n")
|
||||
cur.copy_expert("copy test to stdout", f)
|
||||
|
||||
# Terminate the GC thread's loop:
|
||||
done = 1
|
||||
|
|
Loading…
Reference in New Issue
Block a user