Merge remote-tracking branch 'origin/code-cleanup'

This commit is contained in:
Daniele Varrazzo 2019-01-21 12:49:05 +00:00
commit 4246fdf809
19 changed files with 356 additions and 351 deletions

View File

@ -90,7 +90,9 @@ list_quote(listObject *self)
* array[array[]] is */
all_nulls = 0;
Py_CLEAR(qs[i]);
qs[i] = Bytes_FromString("ARRAY[]");
if (!(qs[i] = Bytes_FromString("ARRAY[]"))) {
goto exit;
}
}
}
else {

View File

@ -113,14 +113,14 @@ qstring_str(qstringObject *self)
static PyObject *
qstring_prepare(qstringObject *self, PyObject *args)
{
connectionObject *conn;
PyObject *conn;
if (!PyArg_ParseTuple(args, "O!", &connectionType, &conn))
return NULL;
Py_CLEAR(self->conn);
Py_INCREF(conn);
self->conn = conn;
self->conn = (connectionObject *)conn;
Py_RETURN_NONE;
}

View File

@ -79,10 +79,7 @@
#define PSYCOPG_MODULE
#include "psycopg/psycopg.h"
#ifndef Py_LOCAL_INLINE
#define Py_LOCAL_INLINE(type) static type
#endif
#include "pyport.h"
/* Helpers for formatstring */
@ -102,6 +99,19 @@ getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx)
return NULL;
}
/* wrapper around _Bytes_Resize offering normal Python call semantics */
STEALS(1)
Py_LOCAL_INLINE(PyObject *)
resize_bytes(PyObject *b, Py_ssize_t newsize) {
if (0 == _Bytes_Resize(&b, newsize)) {
return b;
}
else {
return NULL;
}
}
/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */
PyObject *
@ -114,7 +124,7 @@ Bytes_Format(PyObject *format, PyObject *args)
PyObject *result;
PyObject *dict = NULL;
if (format == NULL || !Bytes_Check(format) || args == NULL) {
PyErr_BadInternalCall();
PyErr_SetString(PyExc_SystemError, "bad argument to internal function");
return NULL;
}
fmt = Bytes_AS_STRING(format);
@ -123,7 +133,7 @@ Bytes_Format(PyObject *format, PyObject *args)
result = Bytes_FromStringAndSize((char *)NULL, reslen);
if (result == NULL)
return NULL;
res = Bytes_AsString(result);
res = Bytes_AS_STRING(result);
if (PyTuple_Check(args)) {
arglen = PyTuple_GET_SIZE(args);
argidx = 0;
@ -140,10 +150,10 @@ Bytes_Format(PyObject *format, PyObject *args)
if (--rescnt < 0) {
rescnt = fmtcnt + 100;
reslen += rescnt;
if (_Bytes_Resize(&result, reslen))
if (!(result = resize_bytes(result, reslen))) {
return NULL;
res = Bytes_AS_STRING(result)
+ reslen - rescnt;
}
res = Bytes_AS_STRING(result) + reslen - rescnt;
--rescnt;
}
*res++ = *fmt++;
@ -210,11 +220,6 @@ Bytes_Format(PyObject *format, PyObject *args)
"incomplete format");
goto error;
}
if (c != '%') {
v = getnextarg(args, arglen, &argidx);
if (v == NULL)
goto error;
}
switch (c) {
case '%':
pbuf = "%";
@ -222,6 +227,8 @@ Bytes_Format(PyObject *format, PyObject *args)
break;
case 's':
/* only bytes! */
if (!(v = getnextarg(args, arglen, &argidx)))
goto error;
if (!Bytes_CheckExact(v)) {
PyErr_Format(PyExc_ValueError,
"only bytes values expected, got %s",
@ -238,8 +245,7 @@ Bytes_Format(PyObject *format, PyObject *args)
"unsupported format character '%c' (0x%x) "
"at index " FORMAT_CODE_PY_SSIZE_T,
c, c,
(Py_ssize_t)(fmt - 1 -
Bytes_AsString(format)));
(Py_ssize_t)(fmt - 1 - Bytes_AS_STRING(format)));
goto error;
}
if (width < len)
@ -251,10 +257,14 @@ Bytes_Format(PyObject *format, PyObject *args)
if (reslen < 0) {
Py_DECREF(result);
Py_XDECREF(temp);
if (args_owned)
Py_DECREF(args);
return PyErr_NoMemory();
}
if (_Bytes_Resize(&result, reslen)) {
if (!(result = resize_bytes(result, reslen))) {
Py_XDECREF(temp);
if (args_owned)
Py_DECREF(args);
return NULL;
}
res = Bytes_AS_STRING(result)
@ -284,8 +294,9 @@ Bytes_Format(PyObject *format, PyObject *args)
if (args_owned) {
Py_DECREF(args);
}
if (_Bytes_Resize(&result, reslen - rescnt))
if (!(result = resize_bytes(result, reslen - rescnt))) {
return NULL;
}
return result;
error:

View File

@ -248,7 +248,7 @@ static PySequenceMethods column_sequence = {
static PyObject *
column_getstate(columnObject *self)
column_getstate(columnObject *self, PyObject *dummy)
{
return PyObject_CallFunctionObjArgs(
(PyObject *)&PyTuple_Type, (PyObject *)self, NULL);

View File

@ -121,10 +121,6 @@ exit:
PyObject *
conn_decode(connectionObject *self, const char *str, Py_ssize_t len)
{
PyObject *b = NULL;
PyObject *t = NULL;
PyObject *rv = NULL;
if (len < 0) { len = strlen(str); }
if (self) {
@ -132,22 +128,28 @@ conn_decode(connectionObject *self, const char *str, Py_ssize_t len)
return self->cdecoder(str, len, NULL);
}
else if (self->pydecoder) {
if (!(b = Bytes_FromStringAndSize(str, len))) { goto exit; }
PyObject *b = NULL;
PyObject *t = NULL;
PyObject *rv = NULL;
if (!(b = Bytes_FromStringAndSize(str, len))) { goto error; }
if (!(t = PyObject_CallFunctionObjArgs(self->pydecoder, b, NULL))) {
goto exit;
goto error;
}
rv = PyTuple_GetItem(t, 0);
Py_XINCREF(rv);
if (!(rv = PyTuple_GetItem(t, 0))) { goto error; }
Py_INCREF(rv); /* PyTuple_GetItem gives a borrowes one */
error:
Py_XDECREF(t);
Py_XDECREF(b);
return rv;
}
else {
return PyUnicode_FromStringAndSize(str, len);
}
}
else {
return PyUnicode_FromStringAndSize(str, len);
}
exit:
Py_XDECREF(t);
Py_XDECREF(b);
return rv;
}
/* conn_notice_callback - process notices */
@ -1079,7 +1081,16 @@ conn_poll(connectionObject *self)
/* An async query has just finished: parse the tuple in the
* target cursor. */
cursorObject *curs;
PyObject *py_curs = PyWeakref_GetObject(self->async_cursor);
PyObject *py_curs;
if (!(py_curs = PyWeakref_GetObject(self->async_cursor))) {
/* It shouldn't happen but consider it to avoid dereferencing
* a null pointer below. */
pq_clear_async(self);
PyErr_SetString(PyExc_SystemError,
"got null dereferencing cursor weakref");
res = PSYCO_POLL_ERROR;
break;
}
if (Py_None == py_curs) {
pq_clear_async(self);
PyErr_SetString(InterfaceError,

View File

@ -112,10 +112,10 @@ psyco_conn_cursor(connectionObject *self, PyObject *args, PyObject *kwargs)
goto exit;
}
if (0 != psyco_curs_withhold_set((cursorObject *)obj, withhold)) {
if (0 > psyco_curs_withhold_set((cursorObject *)obj, withhold)) {
goto exit;
}
if (0 != psyco_curs_scrollable_set((cursorObject *)obj, scrollable)) {
if (0 > psyco_curs_scrollable_set((cursorObject *)obj, scrollable)) {
goto exit;
}
@ -138,7 +138,7 @@ exit:
#define psyco_conn_close_doc "close() -- Close the connection."
static PyObject *
psyco_conn_close(connectionObject *self)
psyco_conn_close(connectionObject *self, PyObject *dummy)
{
Dprintf("psyco_conn_close: closing connection at %p", self);
conn_close(self);
@ -153,7 +153,7 @@ psyco_conn_close(connectionObject *self)
#define psyco_conn_commit_doc "commit() -- Commit all changes to database."
static PyObject *
psyco_conn_commit(connectionObject *self)
psyco_conn_commit(connectionObject *self, PyObject *dummy)
{
EXC_IF_CONN_CLOSED(self);
EXC_IF_CONN_ASYNC(self, commit);
@ -172,7 +172,7 @@ psyco_conn_commit(connectionObject *self)
"rollback() -- Roll back all changes done to database."
static PyObject *
psyco_conn_rollback(connectionObject *self)
psyco_conn_rollback(connectionObject *self, PyObject *dummy)
{
EXC_IF_CONN_CLOSED(self);
EXC_IF_CONN_ASYNC(self, rollback);
@ -245,7 +245,7 @@ exit:
"tpc_prepare() -- perform the first phase of a two-phase transaction."
static PyObject *
psyco_conn_tpc_prepare(connectionObject *self)
psyco_conn_tpc_prepare(connectionObject *self, PyObject *dummy)
{
EXC_IF_CONN_CLOSED(self);
EXC_IF_CONN_ASYNC(self, tpc_prepare);
@ -388,7 +388,7 @@ psyco_conn_tpc_rollback(connectionObject *self, PyObject *args)
"tpc_recover() -- returns a list of pending transaction IDs."
static PyObject *
psyco_conn_tpc_recover(connectionObject *self)
psyco_conn_tpc_recover(connectionObject *self, PyObject *dummy)
{
EXC_IF_CONN_CLOSED(self);
EXC_IF_CONN_ASYNC(self, tpc_recover);
@ -403,7 +403,7 @@ psyco_conn_tpc_recover(connectionObject *self)
"__enter__ -> self"
static PyObject *
psyco_conn_enter(connectionObject *self)
psyco_conn_enter(connectionObject *self, PyObject *dummy)
{
EXC_IF_CONN_CLOSED(self);
@ -828,7 +828,7 @@ psyco_conn_deferrable_set(connectionObject *self, PyObject *pyvalue)
"get_native_connection() -- Return the internal PGconn* as a Python Capsule."
static PyObject *
psyco_get_native_connection(connectionObject *self)
psyco_get_native_connection(connectionObject *self, PyObject *dummy)
{
EXC_IF_CONN_CLOSED(self);
@ -866,7 +866,7 @@ psyco_conn_set_client_encoding(connectionObject *self, PyObject *args)
"get_transaction_status() -- Get backend transaction status."
static PyObject *
psyco_conn_get_transaction_status(connectionObject *self)
psyco_conn_get_transaction_status(connectionObject *self, PyObject *dummy)
{
return PyInt_FromLong((long)PQtransactionStatus(self->pgconn));
}
@ -905,7 +905,7 @@ psyco_conn_get_parameter_status(connectionObject *self, PyObject *args)
"get_dsn_parameters() -- Get effective connection parameters.\n\n"
static PyObject *
psyco_conn_get_dsn_parameters(connectionObject *self)
psyco_conn_get_dsn_parameters(connectionObject *self, PyObject *dummy)
{
#if PG_VERSION_NUM >= 90300
PyObject *res = NULL;
@ -998,7 +998,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 *dummy)
{
EXC_IF_CONN_CLOSED(self);
@ -1025,7 +1025,7 @@ psyco_conn_info_get(connectionObject *self)
"reset() -- Reset current connection to defaults."
static PyObject *
psyco_conn_reset(connectionObject *self)
psyco_conn_reset(connectionObject *self, PyObject *dummy)
{
int res;
@ -1056,7 +1056,7 @@ psyco_conn_get_exception(PyObject *self, void *closure)
"poll() -> int -- Advance the connection or query process without blocking."
static PyObject *
psyco_conn_poll(connectionObject *self)
psyco_conn_poll(connectionObject *self, PyObject *dummy)
{
int res;
@ -1076,7 +1076,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 *dummy)
{
long int socket;
@ -1093,7 +1093,7 @@ psyco_conn_fileno(connectionObject *self)
"executing an asynchronous operation."
static PyObject *
psyco_conn_isexecuting(connectionObject *self)
psyco_conn_isexecuting(connectionObject *self, PyObject *dummy)
{
/* synchronous connections will always return False */
if (self->async == 0) {
@ -1119,7 +1119,7 @@ psyco_conn_isexecuting(connectionObject *self)
"cancel() -- cancel the current operation"
static PyObject *
psyco_conn_cancel(connectionObject *self)
psyco_conn_cancel(connectionObject *self, PyObject *dummy)
{
char errbuf[256];

View File

@ -93,8 +93,8 @@ struct cursorObject {
/* C-callable functions in cursor_int.c and cursor_type.c */
BORROWED HIDDEN PyObject *curs_get_cast(cursorObject *self, PyObject *oid);
HIDDEN void curs_reset(cursorObject *self);
HIDDEN int psyco_curs_withhold_set(cursorObject *self, PyObject *pyvalue);
HIDDEN int psyco_curs_scrollable_set(cursorObject *self, PyObject *pyvalue);
RAISES_NEG HIDDEN int psyco_curs_withhold_set(cursorObject *self, PyObject *pyvalue);
RAISES_NEG HIDDEN int psyco_curs_scrollable_set(cursorObject *self, PyObject *pyvalue);
HIDDEN PyObject *psyco_curs_validate_sql_basic(cursorObject *self, PyObject *sql);
/* exception-raising macros */

View File

@ -47,7 +47,7 @@
"close() -- Close the cursor."
static PyObject *
psyco_curs_close(cursorObject *self)
psyco_curs_close(cursorObject *self, PyObject *dummy)
{
PyObject *rv = NULL;
char *lname = NULL;
@ -372,20 +372,17 @@ _psyco_curs_merge_query_args(cursorObject *self,
RAISES_NEG static int
_psyco_curs_execute(cursorObject *self,
PyObject *operation, PyObject *vars,
PyObject *query, PyObject *vars,
long int async, int no_result)
{
int res = -1;
int tmp;
PyObject *fquery, *cvt = NULL;
const char *scroll;
PyObject *fquery = NULL, *cvt = NULL;
operation = psyco_curs_validate_sql_basic(self, operation);
/* Any failure from here forward should 'goto fail' rather than 'return 0'
directly. */
if (operation == NULL) { goto exit; }
/* query becomes NULL or refcount +1, so good to XDECREF at the end */
if (!(query = psyco_curs_validate_sql_basic(self, query))) {
goto exit;
}
CLEARPGRES(self->pgres);
Py_CLEAR(self->query);
@ -394,65 +391,56 @@ _psyco_curs_execute(cursorObject *self,
/* here we are, and we have a sequence or a dictionary filled with
objects to be substituted (bound variables). we try to be smart and do
the right thing (i.e., what the user expects) */
if (vars && vars != Py_None)
{
if (0 > _mogrify(vars, operation, self, &cvt)) { goto exit; }
if (0 > _mogrify(vars, query, self, &cvt)) { goto exit; }
}
switch (self->scrollable) {
case -1:
scroll = "";
break;
case 0:
scroll = "NO SCROLL ";
break;
case 1:
scroll = "SCROLL ";
break;
default:
PyErr_SetString(InternalError, "unexpected scrollable value");
/* Merge the query to the arguments if needed */
if (cvt) {
if (!(fquery = _psyco_curs_merge_query_args(self, query, cvt))) {
goto exit;
}
if (vars && cvt) {
if (!(fquery = _psyco_curs_merge_query_args(self, operation, cvt))) {
goto exit;
}
if (self->qname != NULL) {
self->query = Bytes_FromFormat(
"DECLARE %s %sCURSOR %s HOLD FOR %s",
self->qname,
scroll,
self->withhold ? "WITH" : "WITHOUT",
Bytes_AS_STRING(fquery));
Py_DECREF(fquery);
}
else {
self->query = fquery;
}
}
else {
if (self->qname != NULL) {
self->query = Bytes_FromFormat(
Py_INCREF(query);
fquery = query;
}
if (self->qname != NULL) {
const char *scroll;
switch (self->scrollable) {
case -1:
scroll = "";
break;
case 0:
scroll = "NO SCROLL ";
break;
case 1:
scroll = "SCROLL ";
break;
default:
PyErr_SetString(InternalError, "unexpected scrollable value");
goto exit;
}
if (!(self->query = Bytes_FromFormat(
"DECLARE %s %sCURSOR %s HOLD FOR %s",
self->qname,
scroll,
self->withhold ? "WITH" : "WITHOUT",
Bytes_AS_STRING(operation));
}
else {
/* Transfer reference ownership of the str in operation to
self->query, clearing the local variable to prevent cleanup from
DECREFing it */
self->query = operation;
operation = NULL;
Bytes_AS_STRING(fquery)))) {
goto exit;
}
if (!self->query) { goto exit; }
}
else {
/* Transfer ownership */
Py_INCREF(fquery);
self->query = fquery;
}
/* At this point, the SQL statement must be str, not unicode */
tmp = pq_execute(self, Bytes_AS_STRING(self->query), async, no_result, 0);
Dprintf("psyco_curs_execute: res = %d, pgres = %p", tmp, self->pgres);
if (tmp < 0) { goto exit; }
@ -460,10 +448,8 @@ _psyco_curs_execute(cursorObject *self,
res = 0; /* Success */
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(query);
Py_XDECREF(fquery);
Py_XDECREF(cvt);
return res;
@ -756,7 +742,7 @@ exit:
}
static PyObject *
psyco_curs_fetchone(cursorObject *self)
psyco_curs_fetchone(cursorObject *self, PyObject *dummy)
{
PyObject *res;
@ -947,7 +933,7 @@ exit:
"Return `!None` when no more data is available.\n"
static PyObject *
psyco_curs_fetchall(cursorObject *self)
psyco_curs_fetchall(cursorObject *self, PyObject *dummy)
{
int i, size;
PyObject *list = NULL;
@ -1162,7 +1148,7 @@ exit:
"sets) and will raise a NotSupportedError exception."
static PyObject *
psyco_curs_nextset(cursorObject *self)
psyco_curs_nextset(cursorObject *self, PyObject *dummy)
{
EXC_IF_CURS_CLOSED(self);
@ -1279,7 +1265,7 @@ psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
"__enter__ -> self"
static PyObject *
psyco_curs_enter(cursorObject *self)
psyco_curs_enter(cursorObject *self, PyObject *dummy)
{
Py_INCREF(self);
return (PyObject *)self;
@ -1394,27 +1380,6 @@ exit:
#define psyco_curs_copy_from_doc \
"copy_from(file, table, sep='\\t', null='\\\\N', size=8192, columns=None) -- Copy table from file."
STEALS(1) static int
_psyco_curs_has_read_check(PyObject *o, PyObject **var)
{
if (PyObject_HasAttrString(o, "readline")
&& PyObject_HasAttrString(o, "read")) {
/* This routine stores a borrowed reference. Although it is only held
* for the duration of psyco_curs_copy_from, nested invocations of
* Py_BEGIN_ALLOW_THREADS could surrender control to another thread,
* 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 */
*var = o;
return 1;
}
else {
PyErr_SetString(PyExc_TypeError,
"argument 1 must have both .read() and .readline() methods");
return 0;
}
}
static PyObject *
psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
{
@ -1436,11 +1401,15 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
Py_ssize_t bufsize = DEFAULT_COPYBUFF;
PyObject *file, *columns = NULL, *res = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"O&s|ssnO", kwlist,
_psyco_curs_has_read_check, &file, &table_name, &sep, &null, &bufsize,
&columns))
{
if (!PyArg_ParseTupleAndKeywords(
args, kwargs, "Os|ssnO", kwlist,
&file, &table_name, &sep, &null, &bufsize, &columns)) {
return NULL;
}
if (!PyObject_HasAttrString(file, "read")) {
PyErr_SetString(PyExc_TypeError,
"argument 1 must have a .read() method");
return NULL;
}
@ -1474,6 +1443,12 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs)
Dprintf("psyco_curs_copy_from: query = %s", query);
/* This routine stores a borrowed reference. Although it is only held
* for the duration of psyco_curs_copy_from, nested invocations of
* Py_BEGIN_ALLOW_THREADS could surrender control to another thread,
* 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 */
self->copysize = bufsize;
Py_INCREF(file);
self->copyfile = file;
@ -1499,20 +1474,6 @@ exit:
#define psyco_curs_copy_to_doc \
"copy_to(file, table, sep='\\t', null='\\\\N', columns=None) -- Copy table to file."
STEALS(1) static int
_psyco_curs_has_write_check(PyObject *o, PyObject **var)
{
if (PyObject_HasAttrString(o, "write")) {
*var = o;
return 1;
}
else {
PyErr_SetString(PyExc_TypeError,
"argument 1 must have a .write() method");
return 0;
}
}
static PyObject *
psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
{
@ -1530,11 +1491,17 @@ psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs)
char *quoted_null = NULL;
const char *table_name;
PyObject *file, *columns = NULL, *res = NULL;
PyObject *file = NULL, *columns = NULL, *res = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&s|ssO", kwlist,
_psyco_curs_has_write_check, &file,
&table_name, &sep, &null, &columns)) {
if (!PyArg_ParseTupleAndKeywords(
args, kwargs, "Os|ssO", kwlist,
&file, &table_name, &sep, &null, &columns)) {
return NULL;
}
if (!PyObject_HasAttrString(file, "write")) {
PyErr_SetString(PyExc_TypeError,
"argument 1 must have a .write() method");
return NULL;
}
@ -1681,7 +1648,7 @@ psyco_curs_withhold_get(cursorObject *self)
return PyBool_FromLong(self->withhold);
}
int
RAISES_NEG int
psyco_curs_withhold_set(cursorObject *self, PyObject *pyvalue)
{
int value;
@ -1726,7 +1693,7 @@ psyco_curs_scrollable_get(cursorObject *self)
return ret;
}
int
RAISES_NEG int
psyco_curs_scrollable_set(cursorObject *self, PyObject *pyvalue)
{
int value;
@ -1768,7 +1735,7 @@ cursor_next(PyObject *self)
if (NULL == ((cursorObject*)self)->name) {
/* we don't parse arguments: psyco_curs_fetchone will do that for us */
res = psyco_curs_fetchone((cursorObject*)self);
res = psyco_curs_fetchone((cursorObject*)self, NULL);
/* convert a None to NULL to signal the end of iteration */
if (res && res == Py_None) {

View File

@ -131,7 +131,7 @@ static struct PyGetSetDef error_getsets[] = {
* would require implementing __getstate__, and as of 2012 it's a little
* bit too late to care. */
static PyObject *
psyco_error_reduce(errorObject *self)
psyco_error_reduce(errorObject *self, PyObject *dummy)
{
PyObject *meth = NULL;
PyObject *tuple = NULL;

View File

@ -36,6 +36,7 @@
#include "psycopg/config.h"
#include "psycopg/python.h"
#include "psycopg/utils.h"
#ifdef __cplusplus
extern "C" {
@ -115,35 +116,6 @@ typedef struct {
char *pyenc;
} encodingPair;
/* the Decimal type, used by the DECIMAL typecaster */
HIDDEN PyObject *psyco_GetDecimalType(void);
/* forward declarations */
typedef struct cursorObject cursorObject;
typedef struct connectionObject connectionObject;
typedef struct replicationMessageObject replicationMessageObject;
/* some utility functions */
RAISES HIDDEN PyObject *psyco_set_error(PyObject *exc, cursorObject *curs, const char *msg);
HIDDEN char *psycopg_escape_string(connectionObject *conn,
const char *from, Py_ssize_t len, char *to, Py_ssize_t *tolen);
HIDDEN char *psycopg_escape_identifier(connectionObject *conn,
const char *str, Py_ssize_t len);
HIDDEN int psycopg_strdup(char **to, const char *from, Py_ssize_t len);
HIDDEN int psycopg_is_text_file(PyObject *f);
HIDDEN PyObject *psycopg_text_from_chars_safe(
const char *str, Py_ssize_t len, PyObject *decoder);
STEALS(1) HIDDEN PyObject * psycopg_ensure_bytes(PyObject *obj);
STEALS(1) HIDDEN PyObject * psycopg_ensure_text(PyObject *obj);
HIDDEN PyObject *psycopg_dict_from_conninfo_options(PQconninfoOption *options,
int include_password);
HIDDEN PyObject *psycopg_make_dsn(PyObject *dsn, PyObject *kwargs);
/* Exceptions docstrings */
#define Error_doc \
"Base class for error exceptions."

View File

@ -39,7 +39,6 @@
#include "psycopg/typecast.h"
#include "psycopg/microprotocols.h"
#include "psycopg/microprotocols_proto.h"
#include "psycopg/error.h"
#include "psycopg/conninfo.h"
#include "psycopg/diagnostics.h"
@ -396,7 +395,7 @@ exit:
#define psyco_libpq_version_doc "Query actual libpq version loaded."
static PyObject*
psyco_libpq_version(PyObject *self)
psyco_libpq_version(PyObject *self, PyObject *dummy)
{
return PyInt_FromLong(PQlibVersion());
}
@ -722,116 +721,6 @@ psyco_errors_set(PyObject *type)
}
}
/* psyco_set_error
Create a new error of the given type with extra attributes. */
/* TODO: may have been changed to BORROWED */
RAISES PyObject *
psyco_set_error(PyObject *exc, cursorObject *curs, const char *msg)
{
PyObject *pymsg;
PyObject *err = NULL;
connectionObject *conn = NULL;
if (curs) {
conn = ((cursorObject *)curs)->conn;
}
if ((pymsg = conn_text_from_chars(conn, msg))) {
err = PyObject_CallFunctionObjArgs(exc, pymsg, NULL);
Py_DECREF(pymsg);
}
else {
/* what's better than an error in an error handler in the morning?
* Anyway, some error was set, refcount is ok... get outta here. */
return NULL;
}
if (err && PyObject_TypeCheck(err, &errorType)) {
errorObject *perr = (errorObject *)err;
if (curs) {
Py_CLEAR(perr->cursor);
Py_INCREF(curs);
perr->cursor = curs;
}
}
if (err) {
PyErr_SetObject(exc, err);
Py_DECREF(err);
}
return err;
}
/* Return nonzero if the current one is the main interpreter */
static int
psyco_is_main_interp(void)
{
static PyInterpreterState *main_interp = NULL; /* Cached reference */
PyInterpreterState *interp;
if (main_interp) {
return (main_interp == PyThreadState_Get()->interp);
}
/* No cached value: cache the proper value and try again. */
interp = PyInterpreterState_Head();
while (interp->next)
interp = interp->next;
main_interp = interp;
assert (main_interp);
return psyco_is_main_interp();
}
/* psyco_GetDecimalType
Return a new reference to the adapter for decimal type.
If decimals should be used but the module import fails, fall back on
the float type.
If decimals are not to be used, return NULL.
*/
PyObject *
psyco_GetDecimalType(void)
{
static PyObject *cachedType = NULL;
PyObject *decimalType = NULL;
PyObject *decimal;
/* Use the cached object if running from the main interpreter. */
int can_cache = psyco_is_main_interp();
if (can_cache && cachedType) {
Py_INCREF(cachedType);
return cachedType;
}
/* Get a new reference to the Decimal type. */
decimal = PyImport_ImportModule("decimal");
if (decimal) {
decimalType = PyObject_GetAttrString(decimal, "Decimal");
Py_DECREF(decimal);
}
else {
PyErr_Clear();
decimalType = NULL;
}
/* Store the object from future uses. */
if (can_cache && !cachedType && decimalType) {
Py_INCREF(decimalType);
cachedType = decimalType;
}
return decimalType;
}
/** method table and module initialization **/
@ -1119,9 +1008,6 @@ INIT_MODULE(_psycopg)(void)
if (0 != psyco_errors_init()) { goto exit; }
psyco_errors_fill(dict);
replicationPhysicalConst = PyDict_GetItemString(dict, "REPLICATION_PHYSICAL");
replicationLogicalConst = PyDict_GetItemString(dict, "REPLICATION_LOGICAL");
Dprintf("initpsycopg: module initialization complete");
exit:

View File

@ -45,9 +45,6 @@ typedef struct replicationConnectionObject {
#define REPLICATION_PHYSICAL 12345678
#define REPLICATION_LOGICAL 87654321
extern HIDDEN PyObject *replicationPhysicalConst;
extern HIDDEN PyObject *replicationLogicalConst;
#ifdef __cplusplus
}
#endif

View File

@ -41,21 +41,7 @@
static PyObject *
psyco_repl_conn_get_type(replicationConnectionObject *self)
{
connectionObject *conn = &self->conn;
PyObject *res = NULL;
EXC_IF_CONN_CLOSED(conn);
if (self->type == REPLICATION_PHYSICAL) {
res = replicationPhysicalConst;
} else if (self->type == REPLICATION_LOGICAL) {
res = replicationLogicalConst;
} else {
PyErr_Format(PyExc_TypeError, "unknown replication type constant: %ld", self->type);
}
Py_XINCREF(res);
return res;
return PyInt_FromLong(self->type);
}
@ -63,15 +49,16 @@ static int
replicationConnection_init(replicationConnectionObject *self,
PyObject *args, PyObject *kwargs)
{
PyObject *dsn = NULL, *async = Py_False, *replication_type = NULL,
PyObject *dsn = NULL, *async = Py_False,
*item = NULL, *extras = NULL, *cursor = NULL,
*newdsn = NULL, *newargs = NULL, *dsnopts = NULL;
int ret = -1;
long int replication_type;
/* 'replication_type' is not actually optional, but there's no
good way to put it before 'async' in the list */
static char *kwlist[] = {"dsn", "async", "replication_type", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OO", kwlist,
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ol", kwlist,
&dsn, &async, &replication_type)) {
return ret;
}
@ -87,9 +74,7 @@ replicationConnection_init(replicationConnectionObject *self,
if (!(extras = PyImport_ImportModule("psycopg2.extras"))) { goto exit; }
if (!(cursor = PyObject_GetAttrString(extras, "ReplicationCursor"))) { goto exit; }
/* checking the object reference helps to avoid recognizing
unrelated integer constants as valid input values */
if (replication_type == replicationPhysicalConst) {
if (replication_type == REPLICATION_PHYSICAL) {
self->type = REPLICATION_PHYSICAL;
#define SET_ITEM(k, v) \
@ -100,14 +85,15 @@ replicationConnection_init(replicationConnectionObject *self,
SET_ITEM(replication, true);
SET_ITEM(dbname, replication); /* required for .pgpass lookup */
} else if (replication_type == replicationLogicalConst) {
} else if (replication_type == REPLICATION_LOGICAL) {
self->type = REPLICATION_LOGICAL;
SET_ITEM(replication, database);
#undef SET_ITEM
} else {
PyErr_SetString(PyExc_TypeError,
"replication_type must be either REPLICATION_PHYSICAL or REPLICATION_LOGICAL");
"replication_type must be either "
"REPLICATION_PHYSICAL or REPLICATION_LOGICAL");
goto exit;
}
@ -204,6 +190,3 @@ PyTypeObject replicationConnectionType = {
0, /*tp_alloc*/
0, /*tp_new*/
};
PyObject *replicationPhysicalConst;
PyObject *replicationLogicalConst;

View File

@ -140,7 +140,7 @@ psyco_repl_curs_consume_stream(replicationCursorObject *self,
"read_message() -- Try reading a replication message from the server (non-blocking)."
static PyObject *
psyco_repl_curs_read_message(replicationCursorObject *self)
psyco_repl_curs_read_message(replicationCursorObject *self, PyObject *dummy)
{
cursorObject *curs = &self->cur;
replicationMessageObject *msg = NULL;

View File

@ -58,12 +58,17 @@ replmsg_repr(replicationMessageObject *self)
static int
replmsg_init(PyObject *obj, PyObject *args, PyObject *kwargs)
{
replicationMessageObject *self = (replicationMessageObject*) obj;
PyObject *cur = NULL;
replicationMessageObject *self = (replicationMessageObject *)obj;
if (!PyArg_ParseTuple(args, "O!O", &cursorType, &self->cursor, &self->payload))
if (!PyArg_ParseTuple(
args, "O!O", &cursorType, &cur, &self->payload)) {
return -1;
Py_XINCREF(self->cursor);
Py_XINCREF(self->payload);
}
Py_INCREF(cur);
self->cursor = (cursorObject *)cur;
Py_INCREF(self->payload);
self->data_size = 0;
self->data_start = 0;
@ -76,7 +81,7 @@ replmsg_init(PyObject *obj, PyObject *args, PyObject *kwargs)
static int
replmsg_traverse(replicationMessageObject *self, visitproc visit, void *arg)
{
Py_VISIT((PyObject* )self->cursor);
Py_VISIT((PyObject *)self->cursor);
Py_VISIT(self->payload);
return 0;
}

View File

@ -148,6 +148,7 @@ typecast_DECIMAL_cast(const char *s, Py_ssize_t len, PyObject *curs)
Py_DECREF(decimalType);
}
else {
PyErr_Clear();
res = PyObject_CallFunction((PyObject*)&PyFloat_Type, "s", buffer);
}
PyMem_Free(buffer);

View File

@ -27,7 +27,9 @@
#include "psycopg/psycopg.h"
#include "psycopg/connection.h"
#include "psycopg/cursor.h"
#include "psycopg/pgtypes.h"
#include "psycopg/error.h"
#include <string.h>
#include <stdlib.h>
@ -55,9 +57,9 @@ psycopg_escape_string(connectionObject *conn, const char *from, Py_ssize_t len,
if (len < 0) {
len = strlen(from);
} else if (strchr(from, '\0') != from + len) {
PyErr_Format(PyExc_ValueError, "A string literal cannot contain NUL (0x00) characters.");
return NULL;
PyErr_Format(PyExc_ValueError,
"A string literal cannot contain NUL (0x00) characters.");
return NULL;
}
if (to == NULL) {
@ -69,11 +71,11 @@ psycopg_escape_string(connectionObject *conn, const char *from, Py_ssize_t len,
}
{
int err;
if (conn && conn->pgconn)
ql = PQescapeStringConn(conn->pgconn, to+eq+1, from, len, &err);
else
ql = PQescapeString(to+eq+1, from, len);
int err;
if (conn && conn->pgconn)
ql = PQescapeStringConn(conn->pgconn, to+eq+1, from, len, &err);
else
ql = PQescapeString(to+eq+1, from, len);
}
if (eq) {
@ -356,3 +358,110 @@ exit:
#endif
}
/* psyco_set_error
*
* Create a new error of the given type with extra attributes.
*/
RAISES BORROWED PyObject *
psyco_set_error(PyObject *exc, cursorObject *curs, const char *msg)
{
PyObject *pymsg;
PyObject *err = NULL;
connectionObject *conn = NULL;
if (curs) {
conn = ((cursorObject *)curs)->conn;
}
if ((pymsg = conn_text_from_chars(conn, msg))) {
err = PyObject_CallFunctionObjArgs(exc, pymsg, NULL);
Py_DECREF(pymsg);
}
else {
/* what's better than an error in an error handler in the morning?
* Anyway, some error was set, refcount is ok... get outta here. */
return NULL;
}
if (err && PyObject_TypeCheck(err, &errorType)) {
errorObject *perr = (errorObject *)err;
if (curs) {
Py_CLEAR(perr->cursor);
Py_INCREF(curs);
perr->cursor = curs;
}
}
if (err) {
PyErr_SetObject(exc, err);
Py_DECREF(err);
}
return err;
}
/* Return nonzero if the current one is the main interpreter */
static int
psyco_is_main_interp(void)
{
static PyInterpreterState *main_interp = NULL; /* Cached reference */
PyInterpreterState *interp;
if (main_interp) {
return (main_interp == PyThreadState_Get()->interp);
}
/* No cached value: cache the proper value and try again. */
interp = PyInterpreterState_Head();
while (interp->next)
interp = interp->next;
main_interp = interp;
assert (main_interp);
return psyco_is_main_interp();
}
/* psyco_GetDecimalType
Return a new reference to the decimal type.
The function returns a cached version of the object, but only in the main
interpreter because subinterpreters are confusing.
*/
PyObject *
psyco_GetDecimalType(void)
{
static PyObject *cachedType = NULL;
PyObject *decimalType = NULL;
PyObject *decimal;
/* Use the cached object if running from the main interpreter. */
int can_cache = psyco_is_main_interp();
if (can_cache && cachedType) {
Py_INCREF(cachedType);
return cachedType;
}
/* Get a new reference to the Decimal type. */
decimal = PyImport_ImportModule("decimal");
if (decimal) {
decimalType = PyObject_GetAttrString(decimal, "Decimal");
Py_DECREF(decimal);
}
else {
decimalType = NULL;
}
/* Store the object from future uses. */
if (can_cache && !cachedType && decimalType) {
Py_INCREF(decimalType);
cachedType = decimalType;
}
return decimalType;
}

61
psycopg/utils.h Normal file
View File

@ -0,0 +1,61 @@
/* utils.h - function definitions for utility file
*
* 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 UTILS_H
#define UTILS_H 1
/* forward declarations */
typedef struct cursorObject cursorObject;
typedef struct connectionObject connectionObject;
typedef struct replicationMessageObject replicationMessageObject;
HIDDEN char *psycopg_escape_string(
connectionObject *conn,
const char *from, Py_ssize_t len, char *to, Py_ssize_t *tolen);
HIDDEN char *psycopg_escape_identifier(
connectionObject *conn, const char *str, Py_ssize_t len);
HIDDEN int psycopg_strdup(char **to, const char *from, Py_ssize_t len);
STEALS(1) HIDDEN PyObject * psycopg_ensure_bytes(PyObject *obj);
STEALS(1) HIDDEN PyObject * psycopg_ensure_text(PyObject *obj);
HIDDEN int psycopg_is_text_file(PyObject *f);
HIDDEN PyObject *psycopg_dict_from_conninfo_options(
PQconninfoOption *options, int include_password);
HIDDEN PyObject *psycopg_make_dsn(PyObject *dsn, PyObject *kwargs);
HIDDEN PyObject *psycopg_text_from_chars_safe(
const char *str, Py_ssize_t len, PyObject *decoder);
HIDDEN RAISES BORROWED PyObject *psyco_set_error(
PyObject *exc, cursorObject *curs, const char *msg);
HIDDEN PyObject *psyco_GetDecimalType(void);
#endif /* !defined(UTILS_H) */

View File

@ -509,7 +509,7 @@ depends = [
'replication_cursor.h',
'replication_message.h',
'notify.h', 'pqpath.h', 'xid.h', 'column.h', 'conninfo.h',
'libpq_support.h', 'win32_support.h',
'libpq_support.h', 'win32_support.h', 'utils.h',
'adapter_asis.h', 'adapter_binary.h', 'adapter_datetime.h',
'adapter_list.h', 'adapter_pboolean.h', 'adapter_pdecimal.h',