mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-02-07 12:50:32 +03:00
Merge remote-tracking branch 'origin/code-cleanup'
This commit is contained in:
commit
4246fdf809
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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."
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
125
psycopg/utils.c
125
psycopg/utils.c
|
@ -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
61
psycopg/utils.h
Normal 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) */
|
2
setup.py
2
setup.py
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue
Block a user