Merge branch 'gcc-python-plugin' into devel

This commit is contained in:
Daniele Varrazzo 2012-03-05 02:48:11 +00:00
commit b8c75d9de0
29 changed files with 570 additions and 448 deletions

4
NEWS
View File

@ -15,6 +15,10 @@ What's new in psycopg 2.4.5
Regression introduced in 2.4.4 (ticket #100).
- Added support for 'inet' arrays.
- Fixed 'commit()' concurrency problem (ticket #103).
- Codebase cleaned up using the GCC Python plugin's static analysis
tool, which has revealed several unchecked return values, possible
NULL dereferences, reference counting problems. Many thanks to David
Malcolm for the useful tool and the assistance provided using it.
What's new in psycopg 2.4.4

View File

@ -65,6 +65,13 @@ binary_quote(binaryObject *self)
int got_view = 0;
#endif
/* Allow Binary(None) to work */
if (self->wrapped == Py_None) {
Py_INCREF(psyco_null);
rv = psyco_null;
goto exit;
}
/* if we got a plain string or a buffer we escape it and save the buffer */
#if HAS_MEMORYVIEW
@ -93,7 +100,7 @@ binary_quote(binaryObject *self)
/* escape and build quoted buffer */
to = (char *)binary_escape((unsigned char*)buffer, (size_t) buffer_len,
to = (char *)binary_escape((unsigned char*)buffer, (size_t)buffer_len,
&len, self->conn ? ((connectionObject*)self->conn)->pgconn : NULL);
if (to == NULL) {
PyErr_NoMemory();
@ -113,12 +120,6 @@ exit:
if (got_view) { PyBuffer_Release(&view); }
#endif
/* Allow Binary(None) to work */
if (self->wrapped == Py_None) {
Py_INCREF(psyco_null);
rv = psyco_null;
}
/* if the wrapped object is not bytes or a buffer, this is an error */
if (!rv && !PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError, "can't escape %s to binary",
@ -149,16 +150,14 @@ binary_str(binaryObject *self)
static PyObject *
binary_prepare(binaryObject *self, PyObject *args)
{
connectionObject *conn;
PyObject *conn;
if (!PyArg_ParseTuple(args, "O", &conn))
if (!PyArg_ParseTuple(args, "O!", &connectionType, &conn))
return NULL;
Py_XDECREF(self->conn);
if (conn) {
self->conn = (PyObject*)conn;
Py_INCREF(self->conn);
}
self->conn = conn;
Py_INCREF(self->conn);
Py_INCREF(Py_None);
return Py_None;

View File

@ -427,6 +427,10 @@ psyco_DateFromTicks(PyObject *self, PyObject *args)
Py_DECREF(args);
}
}
else {
PyErr_SetString(InterfaceError, "failed localtime call");
}
return res;
}
@ -451,6 +455,10 @@ psyco_TimeFromTicks(PyObject *self, PyObject *args)
Py_DECREF(args);
}
}
else {
PyErr_SetString(InterfaceError, "failed localtime call");
}
return res;
}
@ -473,6 +481,9 @@ psyco_TimestampFromTicks(PyObject *self, PyObject *args)
tm.tm_hour, tm.tm_min, (double)tm.tm_sec + ticks,
pyPsycopgTzLOCAL);
}
else {
PyErr_SetString(InterfaceError, "failed localtime call");
}
return res;
}

View File

@ -98,9 +98,9 @@ list_getquoted(listObject *self, PyObject *args)
static PyObject *
list_prepare(listObject *self, PyObject *args)
{
connectionObject *conn;
PyObject *conn;
if (!PyArg_ParseTuple(args, "O", &conn))
if (!PyArg_ParseTuple(args, "O!", &connectionType, &conn))
return NULL;
/* note that we don't copy the encoding from the connection, but take a
@ -109,7 +109,7 @@ list_prepare(listObject *self, PyObject *args)
work even without a connection to the backend. */
Py_CLEAR(self->connection);
Py_INCREF(conn);
self->connection = (PyObject*)conn;
self->connection = conn;
Py_INCREF(Py_None);
return Py_None;

View File

@ -35,7 +35,7 @@
/* qstring_quote - do the quote process on plain and unicode strings */
static PyObject *
BORROWED static PyObject *
qstring_quote(qstringObject *self)
{
PyObject *str;
@ -124,24 +124,22 @@ qstring_str(qstringObject *self)
static PyObject *
qstring_prepare(qstringObject *self, PyObject *args)
{
connectionObject *conn;
PyObject *conn;
if (!PyArg_ParseTuple(args, "O", &conn))
if (!PyArg_ParseTuple(args, "O!", &connectionType, &conn))
return NULL;
/* we bother copying the encoding only if the wrapped string is unicode,
we don't need the encoding if that's not the case */
if (PyUnicode_Check(self->wrapped)) {
if (self->encoding) free(self->encoding);
self->encoding = strdup(conn->codec);
Dprintf("qstring_prepare: set encoding to %s", conn->codec);
self->encoding = strdup(((connectionObject *)conn)->codec);
Dprintf("qstring_prepare: set encoding to %s", self->encoding);
}
Py_CLEAR(self->conn);
if (conn) {
Py_INCREF(conn);
self->conn = (PyObject*)conn;
}
Py_INCREF(conn);
self->conn = conn;
Py_INCREF(Py_None);
return Py_None;

View File

@ -86,7 +86,7 @@
/* Helpers for formatstring */
Py_LOCAL_INLINE(PyObject *)
BORROWED Py_LOCAL_INLINE(PyObject *)
getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx)
{
Py_ssize_t argidx = *p_argidx;

View File

@ -160,4 +160,33 @@ static double round(double num)
#define isinf(x) (!finite((x)) && (x)==(x))
#endif
/* decorators for the gcc cpychecker plugin */
#if defined(WITH_CPYCHECKER_RETURNS_BORROWED_REF_ATTRIBUTE)
#define BORROWED \
__attribute__((cpychecker_returns_borrowed_ref))
#else
#define BORROWED
#endif
#if defined(WITH_CPYCHECKER_STEALS_REFERENCE_TO_ARG_ATTRIBUTE)
#define STEALS(n) \
__attribute__((cpychecker_steals_reference_to_arg(n)))
#else
#define STEALS(n)
#endif
#if defined(WITH_CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION_ATTRIBUTE)
#define RAISES_NEG \
__attribute__((cpychecker_negative_result_sets_exception))
#else
#define RAISES_NEG
#endif
#if defined(WITH_CPYCHECKER_SETS_EXCEPTION_ATTRIBUTE)
#define RAISES \
__attribute__((cpychecker_sets_exception))
#else
#define RAISES
#endif
#endif /* !defined(PSYCOPG_CONFIG_H) */

View File

@ -131,27 +131,27 @@ typedef struct {
/* C-callable functions in connection_int.c and connection_ext.c */
HIDDEN PyObject *conn_text_from_chars(connectionObject *pgconn, const char *str);
HIDDEN int conn_get_standard_conforming_strings(PGconn *pgconn);
HIDDEN int conn_get_isolation_level(connectionObject *self);
RAISES_NEG HIDDEN int conn_get_isolation_level(connectionObject *self);
HIDDEN int conn_get_protocol_version(PGconn *pgconn);
HIDDEN int conn_get_server_version(PGconn *pgconn);
HIDDEN PGcancel *conn_get_cancel(PGconn *pgconn);
HIDDEN void conn_notice_process(connectionObject *self);
HIDDEN void conn_notice_clean(connectionObject *self);
HIDDEN void conn_notifies_process(connectionObject *self);
HIDDEN int conn_setup(connectionObject *self, PGconn *pgconn);
RAISES_NEG HIDDEN int conn_setup(connectionObject *self, PGconn *pgconn);
HIDDEN int conn_connect(connectionObject *self, long int async);
HIDDEN void conn_close(connectionObject *self);
HIDDEN int conn_commit(connectionObject *self);
HIDDEN int conn_rollback(connectionObject *self);
HIDDEN int conn_set_session(connectionObject *self, const char *isolevel,
RAISES_NEG HIDDEN int conn_commit(connectionObject *self);
RAISES_NEG HIDDEN int conn_rollback(connectionObject *self);
RAISES_NEG HIDDEN int conn_set_session(connectionObject *self, const char *isolevel,
const char *readonly, const char *deferrable,
int autocommit);
HIDDEN int conn_set_autocommit(connectionObject *self, int value);
HIDDEN int conn_switch_isolation_level(connectionObject *self, int level);
HIDDEN int conn_set_client_encoding(connectionObject *self, const char *enc);
RAISES_NEG HIDDEN int conn_switch_isolation_level(connectionObject *self, int level);
RAISES_NEG HIDDEN int conn_set_client_encoding(connectionObject *self, const char *enc);
HIDDEN int conn_poll(connectionObject *self);
HIDDEN int conn_tpc_begin(connectionObject *self, XidObject *xid);
HIDDEN int conn_tpc_command(connectionObject *self,
RAISES_NEG HIDDEN int conn_tpc_begin(connectionObject *self, XidObject *xid);
RAISES_NEG HIDDEN int conn_tpc_command(connectionObject *self,
const char *cmd, XidObject *xid);
HIDDEN PyObject *conn_tpc_recover(connectionObject *self);

View File

@ -120,8 +120,16 @@ conn_notice_process(connectionObject *self)
/* Respect the order in which notices were produced,
because in notice_list they are reversed (see ticket #9) */
PyList_Insert(self->notice_list, nnotices, msg);
Py_DECREF(msg);
if (msg) {
PyList_Insert(self->notice_list, nnotices, msg);
Py_DECREF(msg);
}
else {
/* We don't really have a way to report errors, so gulp it.
* The function should only fail for out of memory, so we are
* likely going to die anyway. */
PyErr_Clear();
}
notice = notice->next;
}
@ -242,19 +250,20 @@ conn_get_standard_conforming_strings(PGconn *pgconn)
/* Remove irrelevant chars from encoding name and turn it uppercase.
*
* Return a buffer allocated on Python heap,
* NULL and set an exception on error.
* Return a buffer allocated on Python heap into 'clean' and return 0 on
* success, otherwise return -1 and set an exception.
*/
static char *
clean_encoding_name(const char *enc)
RAISES_NEG static int
clear_encoding_name(const char *enc, char **clean)
{
const char *i = enc;
char *rv, *j;
char *j, *buf;
int rv = -1;
/* convert to upper case and remove '-' and '_' from string */
if (!(j = rv = PyMem_Malloc(strlen(enc) + 1))) {
if (!(j = buf = PyMem_Malloc(strlen(enc) + 1))) {
PyErr_NoMemory();
return NULL;
goto exit;
}
while (*i) {
@ -267,25 +276,28 @@ clean_encoding_name(const char *enc)
}
*j = '\0';
Dprintf("clean_encoding_name: %s -> %s", enc, rv);
Dprintf("clear_encoding_name: %s -> %s", enc, buf);
*clean = buf;
rv = 0;
exit:
return rv;
}
/* Convert a PostgreSQL encoding to a Python codec.
*
* Return a new copy of the codec name allocated on the Python heap,
* NULL with exception in case of error.
* Set 'codec' to a new copy of the codec name allocated on the Python heap.
* Return 0 in case of success, else -1 and set an exception.
*
* 'enc' should be already normalized (uppercase, no - or _).
*/
static char *
conn_encoding_to_codec(const char *enc)
RAISES_NEG static int
conn_encoding_to_codec(const char *enc, char **codec)
{
char *tmp;
Py_ssize_t size;
PyObject *pyenc = NULL;
char *rv = NULL;
int rv = -1;
/* Find the Py codec name from the PG encoding */
if (!(pyenc = PyDict_GetItemString(psycoEncodings, enc))) {
@ -305,7 +317,7 @@ conn_encoding_to_codec(const char *enc)
}
/* have our own copy of the python codec name */
rv = psycopg_strdup(tmp, size);
rv = psycopg_strdup(codec, tmp, size);
exit:
Py_XDECREF(pyenc);
@ -320,7 +332,7 @@ exit:
*
* Return 0 on success, else nonzero.
*/
static int
RAISES_NEG static int
conn_read_encoding(connectionObject *self, PGconn *pgconn)
{
char *enc = NULL, *codec = NULL;
@ -335,12 +347,12 @@ conn_read_encoding(connectionObject *self, PGconn *pgconn)
goto exit;
}
if (!(enc = clean_encoding_name(tmp))) {
if (0 > clear_encoding_name(tmp, &enc)) {
goto exit;
}
/* Look for this encoding in Python codecs. */
if (!(codec = conn_encoding_to_codec(enc))) {
if (0 > conn_encoding_to_codec(enc, &codec)) {
goto exit;
}
@ -362,7 +374,7 @@ exit:
}
int
RAISES_NEG int
conn_get_isolation_level(connectionObject *self)
{
PGresult *pgres = NULL;
@ -456,7 +468,7 @@ conn_is_datestyle_ok(PGconn *pgconn)
/* conn_setup - setup and read basic information about the connection */
int
RAISES_NEG int
conn_setup(connectionObject *self, PGconn *pgconn)
{
PGresult *pgres = NULL;
@ -470,7 +482,7 @@ conn_setup(connectionObject *self, PGconn *pgconn)
return -1;
}
if (conn_read_encoding(self, pgconn)) {
if (0 > conn_read_encoding(self, pgconn)) {
return -1;
}
@ -484,7 +496,7 @@ conn_setup(connectionObject *self, PGconn *pgconn)
pthread_mutex_lock(&self->lock);
Py_BLOCK_THREADS;
if (psyco_green() && (pq_set_non_blocking(self, 1, 1) != 0)) {
if (psyco_green() && (0 > pq_set_non_blocking(self, 1))) {
return -1;
}
@ -762,7 +774,7 @@ _conn_poll_setup_async(connectionObject *self)
switch (self->status) {
case CONN_STATUS_CONNECTING:
/* Set the connection to nonblocking now. */
if (pq_set_non_blocking(self, 1, 1) != 0) {
if (pq_set_non_blocking(self, 1) != 0) {
break;
}
@ -773,7 +785,7 @@ _conn_poll_setup_async(connectionObject *self)
PyErr_SetString(InterfaceError, "only protocol 3 supported");
break;
}
if (conn_read_encoding(self, self->pgconn)) {
if (0 > conn_read_encoding(self, self->pgconn)) {
break;
}
self->cancel = conn_get_cancel(self->pgconn);
@ -942,7 +954,7 @@ conn_close(connectionObject *self)
/* conn_commit - commit on a connection */
int
RAISES_NEG int
conn_commit(connectionObject *self)
{
int res;
@ -953,7 +965,7 @@ conn_commit(connectionObject *self)
/* conn_rollback - rollback a connection */
int
RAISES_NEG int
conn_rollback(connectionObject *self)
{
int res;
@ -962,7 +974,7 @@ conn_rollback(connectionObject *self)
return res;
}
int
RAISES_NEG int
conn_set_session(connectionObject *self,
const char *isolevel, const char *readonly, const char *deferrable,
int autocommit)
@ -1035,7 +1047,7 @@ conn_set_autocommit(connectionObject *self, int value)
/* conn_switch_isolation_level - switch isolation level on the connection */
int
RAISES_NEG int
conn_switch_isolation_level(connectionObject *self, int level)
{
PGresult *pgres = NULL;
@ -1117,12 +1129,12 @@ endlock:
/* conn_set_client_encoding - switch client encoding on connection */
int
RAISES_NEG int
conn_set_client_encoding(connectionObject *self, const char *enc)
{
PGresult *pgres = NULL;
char *error = NULL;
int res = 1;
int res = -1;
char *codec = NULL;
char *clean_enc = NULL;
@ -1131,8 +1143,8 @@ conn_set_client_encoding(connectionObject *self, const char *enc)
if (strcmp(self->encoding, enc) == 0) return 0;
/* We must know what python codec this encoding is. */
if (!(clean_enc = clean_encoding_name(enc))) { goto exit; }
if (!(codec = conn_encoding_to_codec(clean_enc))) { goto exit; }
if (0 > clear_encoding_name(enc, &clean_enc)) { goto exit; }
if (0 > conn_encoding_to_codec(clean_enc, &codec)) { goto exit; }
Py_BEGIN_ALLOW_THREADS;
pthread_mutex_lock(&self->lock);
@ -1190,7 +1202,7 @@ exit:
* in regular transactions, as PostgreSQL won't even know we are in a TPC
* until PREPARE. */
int
RAISES_NEG int
conn_tpc_begin(connectionObject *self, XidObject *xid)
{
PGresult *pgres = NULL;
@ -1224,7 +1236,7 @@ conn_tpc_begin(connectionObject *self, XidObject *xid)
* The function doesn't change the connection state as it can be used
* for many commands and for recovered transactions. */
int
RAISES_NEG int
conn_tpc_command(connectionObject *self, const char *cmd, XidObject *xid)
{
PGresult *pgres = NULL;

View File

@ -526,7 +526,7 @@ psyco_conn_set_session(connectionObject *self, PyObject *args, PyObject *kwargs)
if (-1 == c_autocommit) { return NULL; }
}
if (0 != conn_set_session(self,
if (0 > conn_set_session(self,
c_isolevel, c_readonly, c_deferrable, c_autocommit)) {
return NULL;
}
@ -548,7 +548,7 @@ psyco_conn_autocommit_get(connectionObject *self)
return ret;
}
static PyObject *
BORROWED static PyObject *
_psyco_conn_autocommit_set_checks(connectionObject *self)
{
/* wrapper to use the EXC_IF macros.
@ -635,7 +635,7 @@ psyco_conn_set_client_encoding(connectionObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s", &enc)) return NULL;
if (conn_set_client_encoding(self, enc) == 0) {
if (conn_set_client_encoding(self, enc) >= 0) {
Py_INCREF(Py_None);
rv = Py_None;
}
@ -699,8 +699,8 @@ psyco_conn_get_parameter_status(connectionObject *self, PyObject *args)
static PyObject *
psyco_conn_lobject(connectionObject *self, PyObject *args, PyObject *keywds)
{
Oid oid=InvalidOid, new_oid=InvalidOid;
char *new_file = NULL;
int oid = (int)InvalidOid, new_oid = (int)InvalidOid;
const char *new_file = NULL;
const char *smode = "";
PyObject *factory = (PyObject *)&lobjectType;
PyObject *obj;
@ -752,7 +752,7 @@ psyco_conn_lobject(connectionObject *self, PyObject *args, PyObject *keywds)
"get_backend_pid() -- Get backend process id."
static PyObject *
psyco_conn_get_backend_pid(connectionObject *self)
psyco_conn_get_backend_pid(connectionObject *self, PyObject *args)
{
EXC_IF_CONN_CLOSED(self);
@ -765,7 +765,7 @@ psyco_conn_get_backend_pid(connectionObject *self)
"reset() -- Reset current connection to defaults."
static PyObject *
psyco_conn_reset(connectionObject *self)
psyco_conn_reset(connectionObject *self, PyObject *args)
{
int res;
@ -793,7 +793,7 @@ psyco_conn_get_exception(PyObject *self, void *closure)
}
static PyObject *
psyco_conn_poll(connectionObject *self)
psyco_conn_poll(connectionObject *self, PyObject *args)
{
int res;
@ -815,7 +815,7 @@ psyco_conn_poll(connectionObject *self)
"fileno() -> int -- Return file descriptor associated to database connection."
static PyObject *
psyco_conn_fileno(connectionObject *self)
psyco_conn_fileno(connectionObject *self, PyObject *args)
{
long int socket;
@ -834,7 +834,7 @@ psyco_conn_fileno(connectionObject *self)
"executing an asynchronous operation."
static PyObject *
psyco_conn_isexecuting(connectionObject *self)
psyco_conn_isexecuting(connectionObject *self, PyObject *args)
{
/* synchronous connections will always return False */
if (self->async == 0) {
@ -866,7 +866,7 @@ psyco_conn_isexecuting(connectionObject *self)
"cancel() -- cancel the current operation"
static PyObject *
psyco_conn_cancel(connectionObject *self)
psyco_conn_cancel(connectionObject *self, PyObject *args)
{
char errbuf[256];

View File

@ -85,7 +85,7 @@ struct cursorObject {
/* C-callable functions in cursor_int.c and cursor_ext.c */
HIDDEN PyObject *curs_get_cast(cursorObject *self, PyObject *oid);
BORROWED HIDDEN PyObject *curs_get_cast(cursorObject *self, PyObject *oid);
HIDDEN void curs_reset(cursorObject *self);
/* exception-raising macros */

View File

@ -38,7 +38,7 @@
* Return a borrowed reference.
*/
PyObject *
BORROWED PyObject *
curs_get_cast(cursorObject *self, PyObject *oid)
{
PyObject *cast;

View File

@ -79,7 +79,7 @@ exit:
/* mogrify a query string and build argument array or dict */
static int
RAISES_NEG static int
_mogrify(PyObject *var, PyObject *fmt, cursorObject *curs, PyObject **new)
{
PyObject *key, *value, *n;
@ -221,7 +221,10 @@ _mogrify(PyObject *var, PyObject *fmt, cursorObject *curs, PyObject **new)
}
if (n == NULL) {
n = PyTuple_New(PyObject_Length(var));
if (!(n = PyTuple_New(PyObject_Length(var)))) {
Py_DECREF(value);
return -1;
}
}
/* let's have d point just after the '%' */
@ -360,11 +363,12 @@ _psyco_curs_merge_query_args(cursorObject *self,
#define psyco_curs_execute_doc \
"execute(query, vars=None) -- Execute query with bound vars."
static int
RAISES_NEG static int
_psyco_curs_execute(cursorObject *self,
PyObject *operation, PyObject *vars, long int async)
{
int res = 0;
int res = -1;
int tmp;
PyObject *fquery, *cvt = NULL;
operation = _psyco_curs_validate_sql_basic(self, operation);
@ -372,7 +376,7 @@ _psyco_curs_execute(cursorObject *self,
/* Any failure from here forward should 'goto fail' rather than 'return 0'
directly. */
if (operation == NULL) { goto fail; }
if (operation == NULL) { goto exit; }
IFCLEARPGRES(self->pgres);
@ -389,12 +393,12 @@ _psyco_curs_execute(cursorObject *self,
if (vars && vars != Py_None)
{
if(_mogrify(vars, operation, self, &cvt) == -1) { goto fail; }
if (0 > _mogrify(vars, operation, self, &cvt)) { goto exit; }
}
if (vars && cvt) {
if (!(fquery = _psyco_curs_merge_query_args(self, operation, cvt))) {
goto fail;
goto exit;
}
if (self->name != NULL) {
@ -428,25 +432,20 @@ _psyco_curs_execute(cursorObject *self,
/* At this point, the SQL statement must be str, not unicode */
res = pq_execute(self, Bytes_AS_STRING(self->query), async);
Dprintf("psyco_curs_execute: res = %d, pgres = %p", res, self->pgres);
if (res == -1) { goto fail; }
tmp = pq_execute(self, Bytes_AS_STRING(self->query), async);
Dprintf("psyco_curs_execute: res = %d, pgres = %p", tmp, self->pgres);
if (tmp < 0) { goto exit; }
res = 1; /* Success */
goto cleanup;
res = 0; /* Success */
fail:
res = 0;
/* Fall through to cleanup */
cleanup:
/* Py_XDECREF(operation) is safe because the original reference passed
by the caller was overwritten with either NULL or a new
reference */
Py_XDECREF(operation);
exit:
/* Py_XDECREF(operation) is safe because the original reference passed
by the caller was overwritten with either NULL or a new
reference */
Py_XDECREF(operation);
Py_XDECREF(cvt);
Py_XDECREF(cvt);
return res;
return res;
}
static PyObject *
@ -480,13 +479,13 @@ psyco_curs_execute(cursorObject *self, PyObject *args, PyObject *kwargs)
EXC_IF_ASYNC_IN_PROGRESS(self, execute);
EXC_IF_TPC_PREPARED(self->conn, execute);
if (_psyco_curs_execute(self, operation, vars, self->conn->async)) {
Py_INCREF(Py_None);
return Py_None;
}
else {
if (0 > _psyco_curs_execute(self, operation, vars, self->conn->async)) {
return NULL;
}
/* success */
Py_INCREF(Py_None);
return Py_None;
}
#define psyco_curs_executemany_doc \
@ -525,7 +524,7 @@ psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs)
}
while ((v = PyIter_Next(vars)) != NULL) {
if (_psyco_curs_execute(self, operation, v, 0) == 0) {
if (0 > _psyco_curs_execute(self, operation, v, 0)) {
Py_DECREF(v);
Py_XDECREF(iter);
return NULL;
@ -572,7 +571,7 @@ _psyco_curs_mogrify(cursorObject *self,
if (vars && vars != Py_None)
{
if (_mogrify(vars, operation, self, &cvt) == -1) {
if (0 > _mogrify(vars, operation, self, &cvt)) {
goto cleanup;
}
}
@ -648,7 +647,7 @@ psyco_curs_cast(cursorObject *self, PyObject *args)
"default) or using the sequence factory previously set in the\n" \
"`row_factory` attribute. Return `!None` when no more data is available.\n"
static int
RAISES_NEG static int
_psyco_curs_prefetch(cursorObject *self)
{
int i = 0;
@ -665,13 +664,14 @@ _psyco_curs_prefetch(cursorObject *self)
return i;
}
static PyObject *
RAISES_NEG static int
_psyco_curs_buildrow_fill(cursorObject *self, PyObject *res,
int row, int n, int istuple)
{
int i, len, err;
const char *str;
PyObject *val;
int rv = -1;
for (i=0; i < n; i++) {
if (PQgetisnull(self->pgres, row, i)) {
@ -686,59 +686,59 @@ _psyco_curs_buildrow_fill(cursorObject *self, PyObject *res,
Dprintf("_psyco_curs_buildrow: row %ld, element %d, len %d",
self->row, i, len);
val = typecast_cast(PyTuple_GET_ITEM(self->casts, i), str, len,
(PyObject*)self);
if (!(val = typecast_cast(PyTuple_GET_ITEM(self->casts, i), str, len,
(PyObject*)self))) {
goto exit;
}
if (val) {
Dprintf("_psyco_curs_buildrow: val->refcnt = "
FORMAT_CODE_PY_SSIZE_T,
Py_REFCNT(val)
);
if (istuple) {
PyTuple_SET_ITEM(res, i, val);
}
else {
err = PySequence_SetItem(res, i, val);
Py_DECREF(val);
if (err == -1) {
Py_DECREF(res);
res = NULL;
break;
}
}
Dprintf("_psyco_curs_buildrow: val->refcnt = "
FORMAT_CODE_PY_SSIZE_T,
Py_REFCNT(val)
);
if (istuple) {
PyTuple_SET_ITEM(res, i, val);
}
else {
/* an error occurred in the type system, we return NULL to raise
an exception. the typecast code should already have set the
exception type and text */
Py_DECREF(res);
res = NULL;
break;
err = PySequence_SetItem(res, i, val);
Py_DECREF(val);
if (err == -1) { goto exit; }
}
}
return res;
rv = 0;
exit:
return rv;
}
static PyObject *
_psyco_curs_buildrow(cursorObject *self, int row)
{
int n;
int istuple;
PyObject *t = NULL;
PyObject *rv = NULL;
n = PQnfields(self->pgres);
return _psyco_curs_buildrow_fill(self, PyTuple_New(n), row, n, 1);
}
istuple = (self->tuple_factory == Py_None);
static PyObject *
_psyco_curs_buildrow_with_factory(cursorObject *self, int row)
{
int n;
PyObject *res;
if (istuple) {
t = PyTuple_New(n);
}
else {
t = PyObject_CallFunctionObjArgs(self->tuple_factory, self, NULL);
}
if (!t) { goto exit; }
n = PQnfields(self->pgres);
if (!(res = PyObject_CallFunctionObjArgs(self->tuple_factory, self, NULL)))
return NULL;
if (0 <= _psyco_curs_buildrow_fill(self, t, row, n, istuple)) {
rv = t;
t = NULL;
}
exit:
Py_XDECREF(t);
return rv;
return _psyco_curs_buildrow_fill(self, res, row, n, 0);
}
static PyObject *
@ -770,11 +770,7 @@ psyco_curs_fetchone(cursorObject *self, PyObject *args)
return Py_None;
}
if (self->tuple_factory == Py_None)
res = _psyco_curs_buildrow(self, self->row);
else
res = _psyco_curs_buildrow_with_factory(self, self->row);
res = _psyco_curs_buildrow(self, self->row);
self->row++; /* move the counter to next line */
/* if the query was async aggresively free pgres, to allow
@ -821,11 +817,7 @@ psyco_curs_next_named(cursorObject *self)
return NULL;
}
if (self->tuple_factory == Py_None)
res = _psyco_curs_buildrow(self, self->row);
else
res = _psyco_curs_buildrow_with_factory(self, self->row);
res = _psyco_curs_buildrow(self, self->row);
self->row++; /* move the counter to next line */
/* if the query was async aggresively free pgres, to allow
@ -852,7 +844,9 @@ static PyObject *
psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords)
{
int i;
PyObject *list, *res;
PyObject *list = NULL;
PyObject *row = NULL;
PyObject *rv = NULL;
PyObject *pysize = NULL;
long int size = self->arraysize;
@ -883,8 +877,8 @@ psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords)
EXC_IF_TPC_PREPARED(self->conn, fetchone);
PyOS_snprintf(buffer, 127, "FETCH FORWARD %d FROM \"%s\"",
(int)size, self->name);
if (pq_execute(self, buffer, 0) == -1) return NULL;
if (_psyco_curs_prefetch(self) < 0) return NULL;
if (pq_execute(self, buffer, 0) == -1) { goto exit; }
if (_psyco_curs_prefetch(self) < 0) { goto exit; }
}
/* make sure size is not > than the available number of rows */
@ -895,26 +889,21 @@ psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords)
Dprintf("psyco_curs_fetchmany: size = %ld", size);
if (size <= 0) {
return PyList_New(0);
rv = PyList_New(0);
goto exit;
}
list = PyList_New(size);
if (!(list = PyList_New(size))) { goto exit; }
for (i = 0; i < size; i++) {
if (self->tuple_factory == Py_None)
res = _psyco_curs_buildrow(self, self->row);
else
res = _psyco_curs_buildrow_with_factory(self, self->row);
row = _psyco_curs_buildrow(self, self->row);
self->row++;
if (res == NULL) {
Py_DECREF(list);
return NULL;
}
if (row == NULL) { goto exit; }
PyList_SET_ITEM(list, i, res);
PyList_SET_ITEM(list, i, row);
}
row = NULL;
/* if the query was async aggresively free pgres, to allow
successive requests to reallocate it */
@ -923,7 +912,15 @@ psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords)
&& PyWeakref_GetObject(self->conn->async_cursor) == (PyObject*)self)
IFCLEARPGRES(self->pgres);
return list;
/* success */
rv = list;
list = NULL;
exit:
Py_XDECREF(list);
Py_XDECREF(row);
return rv;
}
@ -940,7 +937,9 @@ static PyObject *
psyco_curs_fetchall(cursorObject *self, PyObject *args)
{
int i, size;
PyObject *list, *res;
PyObject *list = NULL;
PyObject *row = NULL;
PyObject *rv = NULL;
EXC_IF_CURS_CLOSED(self);
if (_psyco_curs_prefetch(self) < 0) return NULL;
@ -953,33 +952,27 @@ psyco_curs_fetchall(cursorObject *self, PyObject *args)
EXC_IF_ASYNC_IN_PROGRESS(self, fetchall);
EXC_IF_TPC_PREPARED(self->conn, fetchall);
PyOS_snprintf(buffer, 127, "FETCH FORWARD ALL FROM \"%s\"", self->name);
if (pq_execute(self, buffer, 0) == -1) return NULL;
if (_psyco_curs_prefetch(self) < 0) return NULL;
if (pq_execute(self, buffer, 0) == -1) { goto exit; }
if (_psyco_curs_prefetch(self) < 0) { goto exit; }
}
size = self->rowcount - self->row;
if (size <= 0) {
return PyList_New(0);
rv = PyList_New(0);
goto exit;
}
list = PyList_New(size);
if (!(list = PyList_New(size))) { goto exit; }
for (i = 0; i < size; i++) {
if (self->tuple_factory == Py_None)
res = _psyco_curs_buildrow(self, self->row);
else
res = _psyco_curs_buildrow_with_factory(self, self->row);
row = _psyco_curs_buildrow(self, self->row);
self->row++;
if (row == NULL) { goto exit; }
if (res == NULL) {
Py_DECREF(list);
return NULL;
}
PyList_SET_ITEM(list, i, res);
PyList_SET_ITEM(list, i, row);
}
row = NULL;
/* if the query was async aggresively free pgres, to allow
successive requests to reallocate it */
@ -988,7 +981,15 @@ psyco_curs_fetchall(cursorObject *self, PyObject *args)
&& PyWeakref_GetObject(self->conn->async_cursor) == (PyObject*)self)
IFCLEARPGRES(self->pgres);
return list;
/* success */
rv = list;
list = NULL;
exit:
Py_XDECREF(list);
Py_XDECREF(row);
return rv;
}
@ -998,7 +999,7 @@ psyco_curs_fetchall(cursorObject *self, PyObject *args)
"callproc(procname, parameters=None) -- Execute stored procedure."
static PyObject *
psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs)
psyco_curs_callproc(cursorObject *self, PyObject *args)
{
const char *procname = NULL;
char *sql = NULL;
@ -1010,7 +1011,7 @@ psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs)
if (!PyArg_ParseTuple(args, "s#|O",
&procname, &procname_len, &parameters
))
{ return NULL; }
{ goto exit; }
EXC_IF_CURS_CLOSED(self);
EXC_IF_ASYNC_IN_PROGRESS(self, callproc);
@ -1019,10 +1020,10 @@ psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs)
if (self->name != NULL) {
psyco_set_error(ProgrammingError, self,
"can't call .callproc() on named cursors", NULL, NULL);
return NULL;
goto exit;
}
if(parameters != Py_None) {
if (parameters != Py_None) {
nparameters = PyObject_Length(parameters);
if (nparameters < 0) nparameters = 0;
}
@ -1031,7 +1032,8 @@ psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs)
sl = procname_len + 17 + nparameters*3 - (nparameters ? 1 : 0);
sql = (char*)PyMem_Malloc(sl);
if (sql == NULL) {
return PyErr_NoMemory();
PyErr_NoMemory();
goto exit;
}
sprintf(sql, "SELECT * FROM %s(", procname);
@ -1041,15 +1043,16 @@ psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs)
sql[sl-2] = ')';
sql[sl-1] = '\0';
operation = Bytes_FromString(sql);
PyMem_Free((void*)sql);
if (!(operation = Bytes_FromString(sql))) { goto exit; }
if (_psyco_curs_execute(self, operation, parameters, self->conn->async)) {
if (0 <= _psyco_curs_execute(self, operation, parameters, self->conn->async)) {
Py_INCREF(parameters);
res = parameters;
}
Py_DECREF(operation);
exit:
Py_XDECREF(operation);
PyMem_Free((void*)sql);
return res;
}
@ -1206,6 +1209,7 @@ static char *_psyco_curs_copy_columns(PyObject *columns)
}
if (NULL == (columnlist = PyMem_Malloc(bufsize))) {
Py_DECREF(coliter);
PyErr_NoMemory();
goto error;
}
@ -1262,8 +1266,8 @@ exit:
#define psyco_curs_copy_from_doc \
"copy_from(file, table, sep='\\t', null='\\\\N', size=8192, columns=None) -- Copy table from file."
static int
_psyco_curs_has_read_check(PyObject* o, void* var)
STEALS(1) static int
_psyco_curs_has_read_check(PyObject *o, PyObject **var)
{
if (PyObject_HasAttrString(o, "readline")
&& PyObject_HasAttrString(o, "read")) {
@ -1273,7 +1277,7 @@ _psyco_curs_has_read_check(PyObject* o, void* var)
* which could invoke the garbage collector. We thus need an
* INCREF/DECREF pair if we store this pointer in a GC object, such as
* a cursorObject */
*((PyObject**)var) = o;
*var = o;
return 1;
}
else {
@ -1348,7 +1352,7 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
Py_INCREF(file);
self->copyfile = file;
if (pq_execute(self, query, 0) == 1) {
if (pq_execute(self, query, 0) >= 0) {
res = Py_None;
Py_INCREF(Py_None);
}
@ -1369,11 +1373,11 @@ exit:
#define psyco_curs_copy_to_doc \
"copy_to(file, table, sep='\\t', null='\\\\N', columns=None) -- Copy table to file."
static int
_psyco_curs_has_write_check(PyObject* o, void* var)
STEALS(1) static int
_psyco_curs_has_write_check(PyObject *o, PyObject **var)
{
if (PyObject_HasAttrString(o, "write")) {
*((PyObject**)var) = o;
*var = o;
return 1;
}
else {
@ -1444,7 +1448,7 @@ psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
Py_INCREF(file);
self->copyfile = file;
if (pq_execute(self, query, 0) == 1) {
if (pq_execute(self, query, 0) >= 0) {
res = Py_None;
Py_INCREF(Py_None);
}
@ -1518,7 +1522,7 @@ psyco_curs_copy_expert(cursorObject *self, PyObject *args, PyObject *kwargs)
self->copyfile = file;
/* At this point, the SQL statement must be str, not unicode */
if (pq_execute(self, Bytes_AS_STRING(sql), 0) == 1) {
if (pq_execute(self, Bytes_AS_STRING(sql), 0) >= 0) {
res = Py_None;
Py_INCREF(res);
}

View File

@ -51,19 +51,19 @@ typedef struct {
/* functions exported from lobject_int.c */
HIDDEN int lobject_open(lobjectObject *self, connectionObject *conn,
Oid oid, const char *smode, Oid new_oid,
const char *new_file);
HIDDEN int lobject_unlink(lobjectObject *self);
HIDDEN int lobject_export(lobjectObject *self, const char *filename);
RAISES_NEG HIDDEN int lobject_open(lobjectObject *self, connectionObject *conn,
Oid oid, const char *smode, Oid new_oid,
const char *new_file);
RAISES_NEG HIDDEN int lobject_unlink(lobjectObject *self);
RAISES_NEG HIDDEN int lobject_export(lobjectObject *self, const char *filename);
HIDDEN Py_ssize_t lobject_read(lobjectObject *self, char *buf, size_t len);
HIDDEN Py_ssize_t lobject_write(lobjectObject *self, const char *buf,
RAISES_NEG HIDDEN Py_ssize_t lobject_read(lobjectObject *self, char *buf, size_t len);
RAISES_NEG HIDDEN Py_ssize_t lobject_write(lobjectObject *self, const char *buf,
size_t len);
HIDDEN int lobject_seek(lobjectObject *self, int pos, int whence);
HIDDEN int lobject_tell(lobjectObject *self);
HIDDEN int lobject_truncate(lobjectObject *self, size_t len);
HIDDEN int lobject_close(lobjectObject *self);
RAISES_NEG HIDDEN int lobject_seek(lobjectObject *self, int pos, int whence);
RAISES_NEG HIDDEN int lobject_tell(lobjectObject *self);
RAISES_NEG HIDDEN int lobject_truncate(lobjectObject *self, size_t len);
RAISES_NEG HIDDEN int lobject_close(lobjectObject *self);
#define lobject_is_closed(self) \
((self)->fd < 0 || !(self)->conn || (self)->conn->closed)

View File

@ -50,7 +50,7 @@ collect_error(connectionObject *conn, char **error)
*
* Valid mode are [r|w|rw|n][t|b]
*/
static int
RAISES_NEG static int
_lobject_parse_mode(const char *mode)
{
int rv = 0;
@ -147,7 +147,7 @@ _lobject_unparse_mode(int mode)
/* lobject_open - create a new/open an existing lo */
int
RAISES_NEG int
lobject_open(lobjectObject *self, connectionObject *conn,
Oid oid, const char *smode, Oid new_oid, const char *new_file)
{
@ -237,7 +237,7 @@ lobject_open(lobjectObject *self, connectionObject *conn,
/* lobject_close - close an existing lo */
static int
RAISES_NEG static int
lobject_close_locked(lobjectObject *self, char **error)
{
int retvalue;
@ -270,7 +270,7 @@ lobject_close_locked(lobjectObject *self, char **error)
return retvalue;
}
int
RAISES_NEG int
lobject_close(lobjectObject *self)
{
PGresult *pgres = NULL;
@ -292,7 +292,7 @@ lobject_close(lobjectObject *self)
/* lobject_unlink - remove an lo from database */
int
RAISES_NEG int
lobject_unlink(lobjectObject *self)
{
PGresult *pgres = NULL;
@ -326,7 +326,7 @@ lobject_unlink(lobjectObject *self)
/* lobject_write - write bytes to a lo */
Py_ssize_t
RAISES_NEG Py_ssize_t
lobject_write(lobjectObject *self, const char *buf, size_t len)
{
Py_ssize_t written;
@ -353,7 +353,7 @@ lobject_write(lobjectObject *self, const char *buf, size_t len)
/* lobject_read - read bytes from a lo */
Py_ssize_t
RAISES_NEG Py_ssize_t
lobject_read(lobjectObject *self, char *buf, size_t len)
{
Py_ssize_t n_read;
@ -377,7 +377,7 @@ lobject_read(lobjectObject *self, char *buf, size_t len)
/* lobject_seek - move the current position in the lo */
int
RAISES_NEG int
lobject_seek(lobjectObject *self, int pos, int whence)
{
PGresult *pgres = NULL;
@ -405,7 +405,7 @@ lobject_seek(lobjectObject *self, int pos, int whence)
/* lobject_tell - tell the current position in the lo */
int
RAISES_NEG int
lobject_tell(lobjectObject *self)
{
PGresult *pgres = NULL;
@ -432,7 +432,7 @@ lobject_tell(lobjectObject *self)
/* lobject_export - export to a local file */
int
RAISES_NEG int
lobject_export(lobjectObject *self, const char *filename)
{
PGresult *pgres = NULL;
@ -461,7 +461,7 @@ lobject_export(lobjectObject *self, const char *filename)
#if PG_VERSION_HEX >= 0x080300
int
RAISES_NEG int
lobject_truncate(lobjectObject *self, size_t len)
{
int retvalue;

View File

@ -373,7 +373,7 @@ lobject_dealloc(PyObject* obj)
static int
lobject_init(PyObject *obj, PyObject *args, PyObject *kwds)
{
Oid oid=InvalidOid, new_oid=InvalidOid;
int oid = (int)InvalidOid, new_oid = (int)InvalidOid;
const char *smode = "";
const char *new_file = NULL;
PyObject *conn;
@ -383,7 +383,7 @@ lobject_init(PyObject *obj, PyObject *args, PyObject *kwds)
return -1;
return lobject_setup((lobjectObject *)obj,
(connectionObject *)conn, oid, smode, new_oid, new_file);
(connectionObject *)conn, (Oid)oid, smode, (Oid)new_oid, new_file);
}
static PyObject *

View File

@ -52,29 +52,35 @@ microprotocols_init(PyObject *dict)
}
/* microprotocols_add - add a reverse type-caster to the dictionary */
/* microprotocols_add - add a reverse type-caster to the dictionary
*
* Return 0 on success, else -1 and set an exception.
*/
int
microprotocols_add(PyTypeObject *type, PyObject *proto, PyObject *cast)
{
PyObject *key;
PyObject *key = NULL;
int rv = -1;
if (proto == NULL) proto = (PyObject*)&isqlquoteType;
Dprintf("microprotocols_add: cast %p for (%s, ?)", cast, type->tp_name);
key = PyTuple_Pack(2, (PyObject*)type, proto);
PyDict_SetItem(psyco_adapters, key, cast);
Py_DECREF(key);
if (!(key = PyTuple_Pack(2, (PyObject*)type, proto))) { goto exit; }
if (0 != PyDict_SetItem(psyco_adapters, key, cast)) { goto exit; }
return 0;
rv = 0;
exit:
Py_XDECREF(key);
return rv;
}
/* Check if one of `obj` superclasses has an adapter for `proto`.
*
* If it does, return a *borrowed reference* to the adapter, else NULL.
* If it does, return a *borrowed reference* to the adapter, else to None.
*/
static PyObject *
BORROWED static PyObject *
_get_superclass_adapter(PyObject *obj, PyObject *proto)
{
PyTypeObject *type;
@ -89,14 +95,14 @@ _get_superclass_adapter(PyObject *obj, PyObject *proto)
#endif
type->tp_mro)) {
/* has no mro */
return NULL;
return Py_None;
}
/* Walk the mro from the most specific subclass. */
mro = type->tp_mro;
for (i = 1, ii = PyTuple_GET_SIZE(mro); i < ii; ++i) {
st = PyTuple_GET_ITEM(mro, i);
key = PyTuple_Pack(2, st, proto);
if (!(key = PyTuple_Pack(2, st, proto))) { return NULL; }
adapter = PyDict_GetItem(psyco_adapters, key);
Py_DECREF(key);
@ -119,7 +125,7 @@ _get_superclass_adapter(PyObject *obj, PyObject *proto)
return adapter;
}
}
return NULL;
return Py_None;
}
@ -139,7 +145,7 @@ microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
Py_TYPE(obj)->tp_name);
/* look for an adapter in the registry */
key = PyTuple_Pack(2, Py_TYPE(obj), proto);
if (!(key = PyTuple_Pack(2, Py_TYPE(obj), proto))) { return NULL; }
adapter = PyDict_GetItem(psyco_adapters, key);
Py_DECREF(key);
if (adapter) {
@ -148,7 +154,10 @@ microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
}
/* Check if a superclass can be adapted and use the same adapter. */
if (NULL != (adapter = _get_superclass_adapter(obj, proto))) {
if (!(adapter = _get_superclass_adapter(obj, proto))) {
return NULL;
}
if (Py_None != adapter) {
adapted = PyObject_CallFunctionObjArgs(adapter, obj, NULL);
return adapted;
}

View File

@ -64,7 +64,7 @@ strip_severity(const char *msg)
code. A list of error codes can be found at:
http://www.postgresql.org/docs/current/static/errcodes-appendix.html */
static PyObject *
BORROWED static PyObject *
exception_from_sqlstate(const char *sqlstate)
{
switch (sqlstate[0]) {
@ -151,7 +151,7 @@ exception_from_sqlstate(const char *sqlstate)
This function should be called while holding the GIL. */
static void
RAISES static void
pq_raise(connectionObject *conn, cursorObject *curs, PGresult *pgres)
{
PyObject *exc = NULL;
@ -164,7 +164,7 @@ pq_raise(connectionObject *conn, cursorObject *curs, PGresult *pgres)
"psycopg went psycotic and raised a null error");
return;
}
/* if the connection has somehow beed broken, we mark the connection
object as closed but requiring cleanup */
if (conn->pgconn != NULL && PQstatus(conn->pgconn) == CONNECTION_BAD)
@ -249,7 +249,9 @@ pq_clear_critical(connectionObject *conn)
}
}
static PyObject *
/* return -1 if the exception is set (i.e. if conn->critical is set),
* else 0 */
RAISES_NEG static int
pq_resolve_critical(connectionObject *conn, int close)
{
Dprintf("pq_resolve_critical: resolving %s", conn->critical);
@ -264,11 +266,13 @@ pq_resolve_critical(connectionObject *conn, int close)
/* we don't want to destroy this connection but just close it */
if (close == 1) conn_close(conn);
/* remember to clear the critical! */
pq_clear_critical(conn);
pq_clear_critical(conn);
return -1;
}
return NULL;
return 0;
}
/* pq_clear_async - clear the effects of a previous async query
@ -300,19 +304,16 @@ pq_clear_async(connectionObject *conn)
Accepted arg values are 1 (nonblocking) and 0 (blocking).
Return 0 if everything ok, else nonzero.
In case of error, if pyerr is nonzero, set a Python exception.
Return 0 if everything ok, else < 0 and set an exception.
*/
int
pq_set_non_blocking(connectionObject *conn, int arg, int pyerr)
RAISES_NEG int
pq_set_non_blocking(connectionObject *conn, int arg)
{
int ret = PQsetnonblocking(conn->pgconn, arg);
if (0 != ret) {
Dprintf("PQsetnonblocking(%d) FAILED", arg);
if (pyerr) {
PyErr_SetString(OperationalError, "PQsetnonblocking() failed");
}
PyErr_SetString(OperationalError, "PQsetnonblocking() failed");
ret = -1;
}
return ret;
}
@ -382,7 +383,7 @@ cleanup:
This function should be called while holding the global interpreter
lock.
*/
void
RAISES void
pq_complete_error(connectionObject *conn, PGresult **pgres, char **error)
{
Dprintf("pq_complete_error: pgconn = %p, pgres = %p, error = %s",
@ -476,7 +477,7 @@ pq_commit(connectionObject *conn)
return retvalue;
}
int
RAISES_NEG int
pq_abort_locked(connectionObject *conn, PGresult **pgres, char **error,
PyThreadState **tstate)
{
@ -503,7 +504,7 @@ pq_abort_locked(connectionObject *conn, PGresult **pgres, char **error,
This function should be called while holding the global interpreter
lock. */
int
RAISES_NEG int
pq_abort(connectionObject *conn)
{
int retvalue = -1;
@ -540,7 +541,7 @@ pq_abort(connectionObject *conn)
connection without holding the global interpreter lock.
*/
int
RAISES_NEG int
pq_reset_locked(connectionObject *conn, PGresult **pgres, char **error,
PyThreadState **tstate)
{
@ -832,7 +833,7 @@ pq_flush(connectionObject *conn)
this fucntion locks the connection object
this function call Py_*_ALLOW_THREADS macros */
int
RAISES_NEG int
pq_execute(cursorObject *curs, const char *query, int async)
{
PGresult *pgres = NULL;
@ -842,8 +843,7 @@ pq_execute(cursorObject *curs, const char *query, int async)
/* if the status of the connection is critical raise an exception and
definitely close the connection */
if (curs->conn->critical) {
pq_resolve_critical(curs->conn, 1);
return -1;
return pq_resolve_critical(curs->conn, 1);
}
/* check status of connection, raise error if not OK */
@ -938,12 +938,13 @@ pq_execute(cursorObject *curs, const char *query, int async)
to respect the old DBAPI-2.0 compatible behaviour */
if (async == 0) {
Dprintf("pq_execute: entering syncronous DBAPI compatibility mode");
if (pq_fetch(curs) == -1) return -1;
if (pq_fetch(curs) < 0) return -1;
}
else {
PyObject *tmp;
curs->conn->async_status = async_status;
curs->conn->async_cursor = PyWeakref_NewRef((PyObject *)curs, NULL);
if (!curs->conn->async_cursor) {
curs->conn->async_cursor = tmp = PyWeakref_NewRef((PyObject *)curs, NULL);
if (!tmp) {
/* weakref creation failed */
return -1;
}
@ -1012,7 +1013,7 @@ pq_get_last_result(connectionObject *conn)
1 - result from backend (possibly data is ready)
*/
static int
RAISES_NEG static int
_pq_fetch_tuples(cursorObject *curs)
{
int i, *dsize = NULL;
@ -1412,8 +1413,7 @@ pq_fetch(cursorObject *curs)
Dprintf("pq_fetch: got a NULL pgres, checking for critical");
pq_set_critical(curs->conn);
if (curs->conn->critical) {
pq_resolve_critical(curs->conn);
return -1;
return pq_resolve_critical(curs->conn);
}
else {
return 0;
@ -1489,13 +1489,7 @@ pq_fetch(cursorObject *curs)
raise the exception but we avoid to close the connection) */
Dprintf("pq_fetch: fetching done; check for critical errors");
if (curs->conn->critical) {
if (ex == -1) {
pq_resolve_critical(curs->conn, 1);
}
else {
pq_resolve_critical(curs->conn, 0);
}
return -1;
return pq_resolve_critical(curs->conn, ex == -1 ? 1 : 0);
}
return ex;

View File

@ -35,18 +35,18 @@
/* exported functions */
HIDDEN PGresult *pq_get_last_result(connectionObject *conn);
HIDDEN int pq_fetch(cursorObject *curs);
HIDDEN int pq_execute(cursorObject *curs, const char *query, int async);
RAISES_NEG HIDDEN int pq_fetch(cursorObject *curs);
RAISES_NEG HIDDEN int pq_execute(cursorObject *curs, const char *query, int async);
HIDDEN int pq_send_query(connectionObject *conn, const char *query);
HIDDEN int pq_begin_locked(connectionObject *conn, PGresult **pgres,
char **error, PyThreadState **tstate);
HIDDEN int pq_commit(connectionObject *conn);
HIDDEN int pq_abort_locked(connectionObject *conn, PGresult **pgres,
RAISES_NEG HIDDEN int pq_abort_locked(connectionObject *conn, PGresult **pgres,
char **error, PyThreadState **tstate);
HIDDEN int pq_abort(connectionObject *conn);
RAISES_NEG HIDDEN int pq_abort(connectionObject *conn);
HIDDEN int pq_reset_locked(connectionObject *conn, PGresult **pgres,
char **error, PyThreadState **tstate);
HIDDEN int pq_reset(connectionObject *conn);
RAISES_NEG HIDDEN int pq_reset(connectionObject *conn);
HIDDEN char *pq_get_guc_locked(connectionObject *conn, const char *param,
PGresult **pgres,
char **error, PyThreadState **tstate);
@ -61,7 +61,7 @@ HIDDEN int pq_is_busy(connectionObject *conn);
HIDDEN int pq_is_busy_locked(connectionObject *conn);
HIDDEN int pq_flush(connectionObject *conn);
HIDDEN void pq_clear_async(connectionObject *conn);
HIDDEN int pq_set_non_blocking(connectionObject *conn, int arg, int pyerr);
RAISES_NEG HIDDEN int pq_set_non_blocking(connectionObject *conn, int arg);
HIDDEN void pq_set_critical(connectionObject *conn, const char *msg);
@ -69,7 +69,7 @@ HIDDEN int pq_execute_command_locked(connectionObject *conn,
const char *query,
PGresult **pgres, char **error,
PyThreadState **tstate);
HIDDEN void pq_complete_error(connectionObject *conn, PGresult **pgres,
RAISES HIDDEN void pq_complete_error(connectionObject *conn, PGresult **pgres,
char **error);
#endif /* !defined(PSYCOPG_PQPATH_H) */

View File

@ -120,17 +120,19 @@ HIDDEN PyObject *psyco_GetDecimalType(void);
typedef struct cursorObject cursorObject;
/* some utility functions */
HIDDEN void psyco_set_error(PyObject *exc, cursorObject *curs, const char *msg,
RAISES HIDDEN void psyco_set_error(PyObject *exc, cursorObject *curs, const char *msg,
const char *pgerror, const char *pgcode);
HIDDEN char *psycopg_escape_string(PyObject *conn,
const char *from, Py_ssize_t len, char *to, Py_ssize_t *tolen);
HIDDEN char *psycopg_escape_identifier_easy(const char *from, Py_ssize_t len);
HIDDEN char *psycopg_strdup(const char *from, Py_ssize_t len);
HIDDEN PyObject * psycopg_ensure_bytes(PyObject *obj);
HIDDEN PyObject * psycopg_ensure_text(PyObject *obj);
HIDDEN int psycopg_strdup(char **to, const char *from, Py_ssize_t len);
HIDDEN int psycopg_is_text_file(PyObject *f);
STEALS(1) HIDDEN PyObject * psycopg_ensure_bytes(PyObject *obj);
STEALS(1) HIDDEN PyObject * psycopg_ensure_text(PyObject *obj);
/* Exceptions docstrings */
#define Error_doc \
"Base class for error exceptions."

View File

@ -143,14 +143,6 @@ psyco_connect(PyObject *self, PyObject *args, PyObject *keywds)
" * `name`: Name for the new type\n" \
" * `baseobj`: Adapter to perform type conversion of a single array item."
static void
_psyco_register_type_set(PyObject **dict, PyObject *type)
{
if (*dict == NULL)
*dict = PyDict_New();
typecast_add(type, *dict, 0);
}
static PyObject *
psyco_register_type(PyObject *self, PyObject *args)
{
@ -162,10 +154,16 @@ psyco_register_type(PyObject *self, PyObject *args)
if (obj != NULL && obj != Py_None) {
if (PyObject_TypeCheck(obj, &cursorType)) {
_psyco_register_type_set(&(((cursorObject*)obj)->string_types), type);
PyObject **dict = &(((cursorObject*)obj)->string_types);
if (*dict == NULL) {
if (!(*dict = PyDict_New())) { return NULL; }
}
if (0 > typecast_add(type, *dict, 0)) { return NULL; }
}
else if (PyObject_TypeCheck(obj, &connectionType)) {
typecast_add(type, ((connectionObject*)obj)->string_types, 0);
if (0 > typecast_add(type, ((connectionObject*)obj)->string_types, 0)) {
return NULL;
}
}
else {
PyErr_SetString(PyExc_TypeError,
@ -174,7 +172,7 @@ psyco_register_type(PyObject *self, PyObject *args)
}
}
else {
typecast_add(type, NULL, 0);
if (0 > typecast_add(type, NULL, 0)) { return NULL; }
}
Py_INCREF(Py_None);
@ -182,66 +180,108 @@ psyco_register_type(PyObject *self, PyObject *args)
}
/* default adapters */
static void
/* Initialize the default adapters map
*
* Return 0 on success, else -1 and set an exception.
*/
static int
psyco_adapters_init(PyObject *mod)
{
PyObject *call;
PyObject *call = NULL;
int rv = -1;
microprotocols_add(&PyFloat_Type, NULL, (PyObject*)&pfloatType);
if (0 != microprotocols_add(&PyFloat_Type, NULL, (PyObject*)&pfloatType)) {
goto exit;
}
#if PY_MAJOR_VERSION < 3
microprotocols_add(&PyInt_Type, NULL, (PyObject*)&pintType);
if (0 != microprotocols_add(&PyInt_Type, NULL, (PyObject*)&pintType)) {
goto exit;
}
#endif
microprotocols_add(&PyLong_Type, NULL, (PyObject*)&pintType);
microprotocols_add(&PyBool_Type, NULL, (PyObject*)&pbooleanType);
if (0 != microprotocols_add(&PyLong_Type, NULL, (PyObject*)&pintType)) {
goto exit;
}
if (0 != microprotocols_add(&PyBool_Type, NULL, (PyObject*)&pbooleanType)) {
goto exit;
}
/* strings */
#if PY_MAJOR_VERSION < 3
microprotocols_add(&PyString_Type, NULL, (PyObject*)&qstringType);
if (0 != microprotocols_add(&PyString_Type, NULL, (PyObject*)&qstringType)) {
goto exit;
}
#endif
microprotocols_add(&PyUnicode_Type, NULL, (PyObject*)&qstringType);
if (0 != microprotocols_add(&PyUnicode_Type, NULL, (PyObject*)&qstringType)) {
goto exit;
}
/* binary */
#if PY_MAJOR_VERSION < 3
microprotocols_add(&PyBuffer_Type, NULL, (PyObject*)&binaryType);
if (0 != microprotocols_add(&PyBuffer_Type, NULL, (PyObject*)&binaryType)) {
goto exit;
}
#else
microprotocols_add(&PyBytes_Type, NULL, (PyObject*)&binaryType);
if (0 != microprotocols_add(&PyBytes_Type, NULL, (PyObject*)&binaryType)) {
goto exit;
}
#endif
#if PY_MAJOR_VERSION >= 3 || PY_MINOR_VERSION >= 6
microprotocols_add(&PyByteArray_Type, NULL, (PyObject*)&binaryType);
if (0 != microprotocols_add(&PyByteArray_Type, NULL, (PyObject*)&binaryType)) {
goto exit;
}
#endif
#if PY_MAJOR_VERSION >= 3 || PY_MINOR_VERSION >= 7
microprotocols_add(&PyMemoryView_Type, NULL, (PyObject*)&binaryType);
if (0 != microprotocols_add(&PyMemoryView_Type, NULL, (PyObject*)&binaryType)) {
goto exit;
}
#endif
microprotocols_add(&PyList_Type, NULL, (PyObject*)&listType);
if (0 != microprotocols_add(&PyList_Type, NULL, (PyObject*)&listType)) {
goto exit;
}
/* the module has already been initialized, so we can obtain the callable
objects directly from its dictionary :) */
call = PyMapping_GetItemString(mod, "DateFromPy");
microprotocols_add(PyDateTimeAPI->DateType, NULL, call);
call = PyMapping_GetItemString(mod, "TimeFromPy");
microprotocols_add(PyDateTimeAPI->TimeType, NULL, call);
call = PyMapping_GetItemString(mod, "TimestampFromPy");
microprotocols_add(PyDateTimeAPI->DateTimeType, NULL, call);
call = PyMapping_GetItemString(mod, "IntervalFromPy");
microprotocols_add(PyDateTimeAPI->DeltaType, NULL, call);
if (!(call = PyMapping_GetItemString(mod, "DateFromPy"))) { goto exit; }
if (0 != microprotocols_add(PyDateTimeAPI->DateType, NULL, call)) { goto exit; }
Py_CLEAR(call);
if (!(call = PyMapping_GetItemString(mod, "TimeFromPy"))) { goto exit; }
if (0 != microprotocols_add(PyDateTimeAPI->TimeType, NULL, call)) { goto exit; }
Py_CLEAR(call);
if (!(call = PyMapping_GetItemString(mod, "TimestampFromPy"))) { goto exit; }
if (0 != microprotocols_add(PyDateTimeAPI->DateTimeType, NULL, call)) { goto exit; }
Py_CLEAR(call);
if (!(call = PyMapping_GetItemString(mod, "IntervalFromPy"))) { goto exit; }
if (0 != microprotocols_add(PyDateTimeAPI->DeltaType, NULL, call)) { goto exit; }
Py_CLEAR(call);
#ifdef HAVE_MXDATETIME
/* as above, we use the callable objects from the psycopg module */
if (NULL != (call = PyMapping_GetItemString(mod, "TimestampFromMx"))) {
microprotocols_add(mxDateTime.DateTime_Type, NULL, call);
if (0 != microprotocols_add(mxDateTime.DateTime_Type, NULL, call)) { goto exit; }
Py_CLEAR(call);
/* if we found the above, we have this too. */
call = PyMapping_GetItemString(mod, "TimeFromMx");
microprotocols_add(mxDateTime.DateTimeDelta_Type, NULL, call);
if (!(call = PyMapping_GetItemString(mod, "TimeFromMx"))) { goto exit; }
if (0 != microprotocols_add(mxDateTime.DateTimeDelta_Type, NULL, call)) { goto exit; }
Py_CLEAR(call);
}
else {
PyErr_Clear();
}
#endif
/* Success! */
rv = 0;
exit:
Py_XDECREF(call);
return rv;
}
/* psyco_encodings_fill
@ -326,15 +366,27 @@ static encodingPair encodings[] = {
{NULL, NULL}
};
static void psyco_encodings_fill(PyObject *dict)
/* Initialize the encodings table.
*
* Return 0 on success, else -1 and set an exception.
*/
static int psyco_encodings_fill(PyObject *dict)
{
PyObject *value = NULL;
encodingPair *enc;
int rv = -1;
for (enc = encodings; enc->pgenc != NULL; enc++) {
PyObject *value = Text_FromUTF8(enc->pyenc);
PyDict_SetItemString(dict, enc->pgenc, value);
Py_DECREF(value);
if (!(value = Text_FromUTF8(enc->pyenc))) { goto exit; }
if (0 != PyDict_SetItemString(dict, enc->pgenc, value)) { goto exit; }
Py_CLEAR(value);
}
rv = 0;
exit:
Py_XDECREF(value);
return rv;
}
/* psyco_errors_init, psyco_errors_fill (callable from C)
@ -440,21 +492,22 @@ psyco_errors_init(void)
live in _psycopg */
int i;
PyObject *dict;
PyObject *dict = NULL;
PyObject *base;
PyObject *str;
PyObject *descr;
PyObject *str = NULL;
PyObject *descr = NULL;
int rv = -1;
static PyMethodDef psyco_error_reduce_ex_def =
{"__reduce_ex__", psyco_error_reduce_ex, METH_VARARGS, "pickle helper"};
for (i=0; exctable[i].name; i++) {
dict = PyDict_New();
if (!(dict = PyDict_New())) { goto exit; }
if (exctable[i].docstr) {
str = Text_FromUTF8(exctable[i].docstr);
PyDict_SetItemString(dict, "__doc__", str);
if (!(str = Text_FromUTF8(exctable[i].docstr))) { goto exit; }
if (0 != PyDict_SetItemString(dict, "__doc__", str)) { goto exit; }
Py_CLEAR(str);
}
if (exctable[i].base == 0) {
@ -468,7 +521,11 @@ psyco_errors_init(void)
else
base = *exctable[i].base;
*exctable[i].exc = PyErr_NewException(exctable[i].name, base, dict);
if (!(*exctable[i].exc = PyErr_NewException(
exctable[i].name, base, dict))) {
goto exit;
}
Py_CLEAR(dict);
}
/* Make pgerror, pgcode and cursor default to None on psycopg
@ -492,60 +549,56 @@ psyco_errors_init(void)
psyco_error_reduce_ex_def.ml_name, descr)) {
goto exit;
}
Py_DECREF(descr);
#endif
rv = 0;
exit:
Py_XDECREF(descr);
Py_XDECREF(str);
Py_XDECREF(dict);
return rv;
}
void
psyco_errors_fill(PyObject *dict)
{
PyDict_SetItemString(dict, "Error", Error);
PyDict_SetItemString(dict, "Warning", Warning);
PyDict_SetItemString(dict, "InterfaceError", InterfaceError);
PyDict_SetItemString(dict, "DatabaseError", DatabaseError);
PyDict_SetItemString(dict, "InternalError", InternalError);
PyDict_SetItemString(dict, "OperationalError", OperationalError);
PyDict_SetItemString(dict, "ProgrammingError", ProgrammingError);
PyDict_SetItemString(dict, "IntegrityError", IntegrityError);
PyDict_SetItemString(dict, "DataError", DataError);
PyDict_SetItemString(dict, "NotSupportedError", NotSupportedError);
#ifdef PSYCOPG_EXTENSIONS
PyDict_SetItemString(dict, "QueryCanceledError", QueryCanceledError);
PyDict_SetItemString(dict, "TransactionRollbackError",
TransactionRollbackError);
#endif
int i;
char *name;
for (i = 0; exctable[i].name; i++) {
if (NULL == exctable[i].exc) { continue; }
/* the name is the part after the last dot */
name = strrchr(exctable[i].name, '.');
name = name ? name + 1 : exctable[i].name;
PyDict_SetItemString(dict, name, *exctable[i].exc);
}
}
void
psyco_errors_set(PyObject *type)
{
PyObject_SetAttrString(type, "Error", Error);
PyObject_SetAttrString(type, "Warning", Warning);
PyObject_SetAttrString(type, "InterfaceError", InterfaceError);
PyObject_SetAttrString(type, "DatabaseError", DatabaseError);
PyObject_SetAttrString(type, "InternalError", InternalError);
PyObject_SetAttrString(type, "OperationalError", OperationalError);
PyObject_SetAttrString(type, "ProgrammingError", ProgrammingError);
PyObject_SetAttrString(type, "IntegrityError", IntegrityError);
PyObject_SetAttrString(type, "DataError", DataError);
PyObject_SetAttrString(type, "NotSupportedError", NotSupportedError);
#ifdef PSYCOPG_EXTENSIONS
PyObject_SetAttrString(type, "QueryCanceledError", QueryCanceledError);
PyObject_SetAttrString(type, "TransactionRollbackError",
TransactionRollbackError);
#endif
int i;
char *name;
for (i = 0; exctable[i].name; i++) {
if (NULL == exctable[i].exc) { continue; }
/* the name is the part after the last dot */
name = strrchr(exctable[i].name, '.');
name = name ? name + 1 : exctable[i].name;
PyObject_SetAttrString(type, name, *exctable[i].exc);
}
}
/* psyco_error_new
/* psyco_set_error
Create a new error of the given type with extra attributes. */
void
RAISES void
psyco_set_error(PyObject *exc, cursorObject *curs, const char *msg,
const char *pgerror, const char *pgcode)
{
@ -574,15 +627,17 @@ psyco_set_error(PyObject *exc, cursorObject *curs, const char *msg,
}
if (pgerror) {
t = conn_text_from_chars(conn, pgerror);
PyObject_SetAttrString(err, "pgerror", t);
Py_DECREF(t);
if ((t = conn_text_from_chars(conn, pgerror))) {
PyObject_SetAttrString(err, "pgerror", t);
Py_DECREF(t);
}
}
if (pgcode) {
t = conn_text_from_chars(conn, pgcode);
PyObject_SetAttrString(err, "pgcode", t);
Py_DECREF(t);
if ((t = conn_text_from_chars(conn, pgcode))) {
PyObject_SetAttrString(err, "pgcode", t);
Py_DECREF(t);
}
}
PyErr_SetObject(exc, err);
@ -649,7 +704,7 @@ psyco_GetDecimalType(void)
}
/* Store the object from future uses. */
if (can_cache && !cachedType) {
if (can_cache && !cachedType && decimalType) {
Py_INCREF(decimalType);
cachedType = decimalType;
}
@ -673,15 +728,11 @@ psyco_make_description_type(void)
/* Try to import collections.namedtuple */
if (!(coll = PyImport_ImportModule("collections"))) {
Dprintf("psyco_make_description_type: collections import failed");
PyErr_Clear();
rv = Py_None;
goto exit;
goto error;
}
if (!(nt = PyObject_GetAttrString(coll, "namedtuple"))) {
Dprintf("psyco_make_description_type: no collections.namedtuple");
PyErr_Clear();
rv = Py_None;
goto exit;
goto error;
}
/* Build the namedtuple */
@ -693,6 +744,13 @@ exit:
Py_XDECREF(nt);
return rv;
error:
/* controlled error: we will fall back to regular tuples. Return None. */
PyErr_Clear();
rv = Py_None;
Py_INCREF(rv);
goto exit;
}
@ -905,10 +963,10 @@ INIT_MODULE(_psycopg)(void)
#endif
/* other mixed initializations of module-level variables */
psycoEncodings = PyDict_New();
psyco_encodings_fill(psycoEncodings);
if (!(psycoEncodings = PyDict_New())) { goto exit; }
if (0 != psyco_encodings_fill(psycoEncodings)) { goto exit; }
psyco_null = Bytes_FromString("NULL");
psyco_DescriptionType = psyco_make_description_type();
if (!(psyco_DescriptionType = psyco_make_description_type())) { goto exit; }
/* set some module's parameters */
PyModule_AddStringConstant(module, "__version__", PSYCOPG_VERSION);
@ -941,11 +999,11 @@ INIT_MODULE(_psycopg)(void)
}
#endif
/* initialize default set of typecasters */
typecast_init(dict);
if (0 != typecast_init(dict)) { goto exit; }
/* initialize microprotocols layer */
microprotocols_init(dict);
psyco_adapters_init(dict);
if (0 != psyco_adapters_init(dict)) { goto exit; }
/* create a standard set of exceptions and add them to the module's dict */
if (0 != psyco_errors_init()) { goto exit; }

View File

@ -250,34 +250,28 @@ PyObject *psyco_default_binary_cast;
/* typecast_init - initialize the dictionary and create default types */
int
RAISES_NEG int
typecast_init(PyObject *dict)
{
int i;
int rv = -1;
typecastObject *t = NULL;
/* create type dictionary and put it in module namespace */
psyco_types = PyDict_New();
psyco_binary_types = PyDict_New();
if (!psyco_types || !psyco_binary_types) {
Py_XDECREF(psyco_types);
Py_XDECREF(psyco_binary_types);
return -1;
}
if (!(psyco_types = PyDict_New())) { goto exit; }
PyDict_SetItemString(dict, "string_types", psyco_types);
if (!(psyco_binary_types = PyDict_New())) { goto exit; }
PyDict_SetItemString(dict, "binary_types", psyco_binary_types);
/* insert the cast types into the 'types' dictionary and register them in
the module dictionary */
for (i = 0; typecast_builtins[i].name != NULL; i++) {
typecastObject *t;
Dprintf("typecast_init: initializing %s", typecast_builtins[i].name);
t = (typecastObject *)typecast_from_c(&(typecast_builtins[i]), dict);
if (t == NULL) return -1;
if (typecast_add((PyObject *)t, NULL, 0) != 0) return -1;
if (t == NULL) { goto exit; }
if (typecast_add((PyObject *)t, NULL, 0) < 0) { goto exit; }
PyDict_SetItem(dict, t->name, (PyObject *)t);
@ -285,6 +279,8 @@ typecast_init(PyObject *dict)
if (typecast_builtins[i].values == typecast_BINARY_types) {
psyco_default_binary_cast = (PyObject *)t;
}
Py_DECREF((PyObject *)t);
t = NULL;
}
/* create and save a default cast object (but does not register it) */
@ -294,29 +290,35 @@ typecast_init(PyObject *dict)
#ifdef HAVE_MXDATETIME
if (0 == psyco_typecast_mxdatetime_init()) {
for (i = 0; typecast_mxdatetime[i].name != NULL; i++) {
typecastObject *t;
Dprintf("typecast_init: initializing %s", typecast_mxdatetime[i].name);
t = (typecastObject *)typecast_from_c(&(typecast_mxdatetime[i]), dict);
if (t == NULL) return -1;
if (t == NULL) { goto exit; }
PyDict_SetItem(dict, t->name, (PyObject *)t);
Py_DECREF((PyObject *)t);
t = NULL;
}
}
#endif
if (psyco_typecast_datetime_init()) { return -1; }
if (0 > psyco_typecast_datetime_init()) { goto exit; }
for (i = 0; typecast_pydatetime[i].name != NULL; i++) {
typecastObject *t;
Dprintf("typecast_init: initializing %s", typecast_pydatetime[i].name);
t = (typecastObject *)typecast_from_c(&(typecast_pydatetime[i]), dict);
if (t == NULL) return -1;
if (t == NULL) { goto exit; }
PyDict_SetItem(dict, t->name, (PyObject *)t);
Py_DECREF((PyObject *)t);
t = NULL;
}
return 0;
rv = 0;
exit:
Py_XDECREF((PyObject *)t);
return rv;
}
/* typecast_add - add a type object to the dictionary */
int
RAISES_NEG int
typecast_add(PyObject *obj, PyObject *dict, int binary)
{
PyObject *val;
@ -466,7 +468,7 @@ typecast_repr(PyObject *self)
static PyObject *
typecast_call(PyObject *obj, PyObject *args, PyObject *kwargs)
{
char *string;
const char *string;
Py_ssize_t length;
PyObject *cursor;

View File

@ -71,8 +71,8 @@ extern HIDDEN PyObject *psyco_default_binary_cast;
/** exported functions **/
/* used by module.c to init the type system and register types */
HIDDEN int typecast_init(PyObject *dict);
HIDDEN int typecast_add(PyObject *obj, PyObject *dict, int binary);
RAISES_NEG HIDDEN int typecast_init(PyObject *dict);
RAISES_NEG HIDDEN int typecast_add(PyObject *obj, PyObject *dict, int binary);
/* the C callable typecastObject creator function */
HIDDEN PyObject *typecast_from_c(typecastObject_initlist *type, PyObject *d);

View File

@ -166,7 +166,7 @@ typecast_array_tokenize(const char *str, Py_ssize_t strlength,
return res;
}
static int
RAISES_NEG static int
typecast_array_scan(const char *str, Py_ssize_t strlength,
PyObject *curs, PyObject *base, PyObject *array)
{
@ -199,7 +199,7 @@ typecast_array_scan(const char *str, Py_ssize_t strlength,
/* before anything else we free the memory */
if (state == ASCAN_QUOTED) PyMem_Free(token);
if (obj == NULL) return 0;
if (obj == NULL) return -1;
PyList_Append(array, obj);
Py_DECREF(obj);
@ -207,25 +207,25 @@ typecast_array_scan(const char *str, Py_ssize_t strlength,
else if (state == ASCAN_BEGIN) {
PyObject *sub = PyList_New(0);
if (sub == NULL) return 0;
if (sub == NULL) return -1;
PyList_Append(array, sub);
Py_DECREF(sub);
if (stack_index == MAX_DIMENSIONS)
return 0;
return -1;
stack[stack_index++] = array;
array = sub;
}
else if (state == ASCAN_ERROR) {
return 0;
return -1;
}
else if (state == ASCAN_END) {
if (--stack_index < 0)
return 0;
return -1;
array = stack[stack_index];
}
@ -233,7 +233,7 @@ typecast_array_scan(const char *str, Py_ssize_t strlength,
break;
}
return 1;
return 0;
}
@ -260,12 +260,11 @@ typecast_GENERIC_ARRAY_cast(const char *str, Py_ssize_t len, PyObject *curs)
Dprintf("typecast_GENERIC_ARRAY_cast: str = '%s',"
" len = " FORMAT_CODE_PY_SSIZE_T, str, len);
obj = PyList_New(0);
if (!(obj = PyList_New(0))) { return NULL; }
/* scan the array skipping the first level of {} */
if (typecast_array_scan(&str[1], len-2, curs, base, obj) == 0) {
Py_DECREF(obj);
obj = NULL;
if (typecast_array_scan(&str[1], len-2, curs, base, obj) < 0) {
Py_CLEAR(obj);
}
return obj;

View File

@ -65,7 +65,7 @@ typecast_FLOAT_cast(const char *s, Py_ssize_t len, PyObject *curs)
PyObject *str = NULL, *flo = NULL;
if (s == NULL) {Py_INCREF(Py_None); return Py_None;}
str = Text_FromUTF8AndSize(s, len);
if (!(str = Text_FromUTF8AndSize(s, len))) { return NULL; }
#if PY_MAJOR_VERSION < 3
flo = PyFloat_FromString(str, NULL);
#else

View File

@ -26,7 +26,7 @@
#include <math.h>
#include "datetime.h"
static int
RAISES_NEG static int
psyco_typecast_datetime_init(void)
{
Dprintf("psyco_typecast_datetime_init: datetime init");
@ -239,7 +239,7 @@ typecast_PYINTERVAL_cast(const char *str, Py_ssize_t len, PyObject *curs)
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
v = v*10 + (double)*str - (double)'0';
v = v * 10.0 + (double)(*str - '0');
if (part == 6){
denominator *= 10;
}

View File

@ -142,7 +142,7 @@ typecast_MXINTERVAL_cast(const char *str, Py_ssize_t len, PyObject *curs)
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
v = v*10 + (double)*str - (double)'0';
v = v * 10.0 + (double)(*str - '0');
Dprintf("typecast_MXINTERVAL_cast: v = %f", v);
if (part == 6){
denominator *= 10;

View File

@ -113,20 +113,19 @@ psycopg_escape_identifier_easy(const char *from, Py_ssize_t len)
* Allocate a new buffer on the Python heap containing the new string.
* 'len' is optional: if 0 the length is calculated.
*
* Return NULL and set an exception in case of error.
* Store the return in 'to' and return 0 in case of success, else return -1
* and raise an exception.
*/
char *
psycopg_strdup(const char *from, Py_ssize_t len)
RAISES_NEG int
psycopg_strdup(char **to, const char *from, Py_ssize_t len)
{
char *rv;
if (!len) { len = strlen(from); }
if (!(rv = PyMem_Malloc(len + 1))) {
if (!(*to = PyMem_Malloc(len + 1))) {
PyErr_NoMemory();
return NULL;
return -1;
}
strcpy(rv, from);
return rv;
strcpy(*to, from);
return 0;
}
/* Ensure a Python object is a bytes string.
@ -139,7 +138,7 @@ psycopg_strdup(const char *from, Py_ssize_t len)
*
* It is safe to call the function on NULL.
*/
PyObject *
STEALS(1) PyObject *
psycopg_ensure_bytes(PyObject *obj)
{
PyObject *rv = NULL;
@ -169,7 +168,7 @@ psycopg_ensure_bytes(PyObject *obj)
* The function is ref neutral: steals a ref from obj and adds one to the
* return value. It is safe to call it on NULL.
*/
PyObject *
STEALS(1) PyObject *
psycopg_ensure_text(PyObject *obj)
{
#if PY_MAJOR_VERSION < 3

View File

@ -78,7 +78,9 @@ static PyMemberDef xid_members[] = {
static PyObject *
xid_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
XidObject *self = (XidObject *)type->tp_alloc(type, 0);
XidObject *self;
if (!(self = (XidObject *)type->tp_alloc(type, 0))) { return NULL; }
Py_INCREF(Py_None);
self->format_id = Py_None;
@ -486,7 +488,7 @@ exit:
*
* Return a borrowed reference. */
static PyObject *
BORROWED static PyObject *
_xid_get_parse_regex(void) {
static PyObject *rv;