mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-26 02:43:43 +03:00
Implemented named cursors.
This commit is contained in:
parent
f687f2853e
commit
ef3430d24f
24
ChangeLog
24
ChangeLog
|
@ -1,3 +1,27 @@
|
|||
2005-10-22 Federico Di Gregorio <fog@initd.org>
|
||||
|
||||
* psycopg/cursor_type.c: added support for named cursors:
|
||||
- .fetchXXX() methods now execute a FETCH if the cursor is named
|
||||
- .execute() executes a DECLARE if the cursor is named
|
||||
- .execute() fails if a named cursor is used in autocommit
|
||||
- .executemany() can't be called on named cursors
|
||||
- .scroll() executes a MOVE if the cursor is named
|
||||
- .close() executes a CLOSE if the cursor is named
|
||||
Also, a "transaction mark" was added to both the connection and the
|
||||
cursor and an exception is raised when using a named cursor unless the
|
||||
two marks correspond.
|
||||
|
||||
* psycopg/connection_int.c: snprintf->PyOS_snprintf.
|
||||
|
||||
* psycopg/psycopgmodule.c: snprintf->PyOS_snprintf.
|
||||
|
||||
* psycopg/cursor_type.c: changed self->query type from C string to
|
||||
PyObject* to better manage queries in named cursors.
|
||||
|
||||
* psycopg/psycopgmodule.c: cleaned up exception names (now the errors
|
||||
is printed as psycopg2.Error and not as the confusing
|
||||
psycopg2._psycopg.Error.)
|
||||
|
||||
2005-10-20 Federico Di Gregorio <fog@initd.org>
|
||||
|
||||
* lib/pool.py: renamed ThreadedConnectionPool to PersistentConnectionPool
|
||||
|
|
6
NEWS
6
NEWS
|
@ -1,3 +1,9 @@
|
|||
What's new in psycopg 2.0 beta 6
|
||||
--------------------------------
|
||||
|
||||
* Support for named cursors (see examples/fetch.py).
|
||||
|
||||
|
||||
What's new in psycopg 2.0 beta 5
|
||||
--------------------------------
|
||||
|
||||
|
|
|
@ -52,19 +52,28 @@ conn.commit()
|
|||
|
||||
# does some nice tricks with the transaction and postgres cursors
|
||||
# (remember to always commit or rollback before a DECLARE)
|
||||
#
|
||||
# we don't need to DECLARE ourselves, psycopg now support named
|
||||
# cursor (but we leave the code here, comments, as an example of
|
||||
# what psycopg is doing under the hood)
|
||||
#curs.execute("DECLARE crs CURSOR FOR SELECT * FROM test_fetch")
|
||||
#curs.execute("FETCH 10 FROM crs")
|
||||
#print "First 10 rows:", flatten(curs.fetchall())
|
||||
#curs.execute("MOVE -5 FROM crs")
|
||||
#print "Moved back cursor by 5 rows (to row 5.)"
|
||||
#curs.execute("FETCH 10 FROM crs")
|
||||
#print "Another 10 rows:", flatten(curs.fetchall())
|
||||
#curs.execute("FETCH 10 FROM crs")
|
||||
#print "The remaining rows:", flatten(curs.fetchall())
|
||||
|
||||
curs.execute("DECLARE crs CURSOR FOR SELECT * FROM test_fetch")
|
||||
curs.execute("FETCH 10 FROM crs")
|
||||
print "First 10 rows:", flatten(curs.fetchall())
|
||||
curs.execute("MOVE -5 FROM crs")
|
||||
ncurs = conn.cursor("crs")
|
||||
ncurs.execute("SELECT * FROM test_fetch")
|
||||
print "First 10 rows:", flatten(ncurs.fetchmany(10))
|
||||
ncurs.scroll(-5)
|
||||
print "Moved back cursor by 5 rows (to row 5.)"
|
||||
curs.execute("FETCH 10 FROM crs")
|
||||
print "Another 10 rows:", flatten(curs.fetchall())
|
||||
curs.execute("FETCH 10 FROM crs")
|
||||
print "The remaining rows:", flatten(curs.fetchall())
|
||||
|
||||
# rollback to close the transaction
|
||||
|
||||
print "Another 10 rows:", flatten(ncurs.fetchmany(10))
|
||||
print "Another one:", list(ncurs.fetchone())
|
||||
print "The remaining rows:", flatten(ncurs.fetchall())
|
||||
conn.rollback()
|
||||
|
||||
curs.execute("DROP TABLE test_fetch")
|
||||
|
|
|
@ -48,6 +48,7 @@ typedef struct {
|
|||
|
||||
long int closed; /* 2 means connection has been closed */
|
||||
long int isolation_level; /* isolation level for this connection */
|
||||
long int mark; /* number of commits/rollbacks done so far */
|
||||
int status; /* status of the connection */
|
||||
int protocol; /* protocol version */
|
||||
|
||||
|
|
|
@ -191,7 +191,8 @@ conn_commit(connectionObject *self)
|
|||
pthread_mutex_lock(&self->lock);
|
||||
|
||||
res = pq_commit(self);
|
||||
|
||||
self->mark++;
|
||||
|
||||
pthread_mutex_unlock(&self->lock);
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
|
@ -209,7 +210,8 @@ conn_rollback(connectionObject *self)
|
|||
pthread_mutex_lock(&self->lock);
|
||||
|
||||
res = pq_abort(self);
|
||||
|
||||
self->mark++;
|
||||
|
||||
pthread_mutex_unlock(&self->lock);
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
|
@ -232,7 +234,8 @@ conn_switch_isolation_level(connectionObject *self, int level)
|
|||
res = pq_abort(self);
|
||||
}
|
||||
self->isolation_level = level;
|
||||
|
||||
self->mark++;
|
||||
|
||||
Dprintf("conn_switch_isolation_level: switched to level %d", level);
|
||||
|
||||
pthread_mutex_unlock(&self->lock);
|
||||
|
@ -256,7 +259,7 @@ conn_set_client_encoding(connectionObject *self, char *enc)
|
|||
pthread_mutex_lock(&self->lock);
|
||||
|
||||
/* set encoding, no encoding string is longer than 24 bytes */
|
||||
snprintf(query, 47, "SET client_encoding = '%s'", enc);
|
||||
PyOS_snprintf(query, 47, "SET client_encoding = '%s'", enc);
|
||||
|
||||
/* abort the current transaction, to set the encoding ouside of
|
||||
transactions */
|
||||
|
|
|
@ -62,9 +62,18 @@ psyco_conn_cursor(connectionObject *self, PyObject *args, PyObject *keywds)
|
|||
Dprintf("psyco_conn_cursor: parameters: name = %s", name);
|
||||
|
||||
if (factory == NULL) factory = (PyObject *)&cursorType;
|
||||
obj = PyObject_CallFunction(factory, "O", self);
|
||||
if (name)
|
||||
obj = PyObject_CallFunction(factory, "Os", self, name);
|
||||
else
|
||||
obj = PyObject_CallFunction(factory, "O", self);
|
||||
|
||||
/* TODO: added error checking on obj (cursor) here */
|
||||
if (obj == NULL) return NULL;
|
||||
if (PyObject_IsInstance(obj, (PyObject *)&cursorType) == 0) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"cursor factory must be subclass of psycopg2._psycopg.cursor");
|
||||
Py_DECREF(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Dprintf("psyco_conn_cursor: new cursor at %p: refcnt = %d",
|
||||
obj, obj->ob_refcnt);
|
||||
|
@ -259,6 +268,7 @@ connection_setup(connectionObject *self, char *dsn)
|
|||
self->critical = NULL;
|
||||
self->async_cursor = NULL;
|
||||
self->pgconn = NULL;
|
||||
self->mark = 0;
|
||||
|
||||
pthread_mutex_init(&(self->lock), NULL);
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ typedef struct {
|
|||
long int columns; /* number of columns fetched from the db */
|
||||
long int arraysize; /* how many rows should fetchmany() return */
|
||||
long int row; /* the row counter for fetch*() operations */
|
||||
long int mark; /* transaction marker, copied from conn */
|
||||
|
||||
PyObject *description; /* read-only attribute: sequence of 7-item
|
||||
sequences.*/
|
||||
|
@ -65,9 +66,11 @@ typedef struct {
|
|||
PyObject *tuple_factory; /* factory for result tuples */
|
||||
PyObject *tzinfo_factory; /* factory for tzinfo objects */
|
||||
|
||||
PyObject *query; /* last query executed */
|
||||
|
||||
char *qattr; /* quoting attr, used when quoting strings */
|
||||
char *notice; /* a notice from the backend */
|
||||
char *query; /* last query executed */
|
||||
char *name; /* this cursor name */
|
||||
|
||||
PyObject *string_types; /* a set of typecasters for string types */
|
||||
PyObject *binary_types; /* a set of typecasters for binary types */
|
||||
|
@ -83,10 +86,16 @@ if ((self)->closed || ((self)->conn && (self)->conn->closed)) { \
|
|||
PyErr_SetString(InterfaceError, "cursor already closed"); \
|
||||
return NULL; }
|
||||
|
||||
#define EXC_IF_NO_TUPLES(self) if ((self)->notuples) { \
|
||||
#define EXC_IF_NO_TUPLES(self) \
|
||||
if ((self)->notuples && (self)->name == NULL) { \
|
||||
PyErr_SetString(ProgrammingError, "no results to fetch"); \
|
||||
return NULL; }
|
||||
|
||||
#define EXC_IF_NO_MARK(self) \
|
||||
if ((self)->mark != (self)->conn->mark) { \
|
||||
PyErr_SetString(ProgrammingError, "named cursor isn't valid anymore"); \
|
||||
return NULL; }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* You should have received a copy of the GNU General Public Likcense
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
@ -51,6 +51,14 @@ psyco_curs_close(cursorObject *self, PyObject *args)
|
|||
if (!PyArg_ParseTuple(args, "")) return NULL;
|
||||
|
||||
EXC_IF_CURS_CLOSED(self);
|
||||
|
||||
if (self->name != NULL) {
|
||||
char buffer[128];
|
||||
|
||||
EXC_IF_NO_MARK(self);
|
||||
PyOS_snprintf(buffer, 127, "CLOSE %s", self->name);
|
||||
if (pq_execute(self, buffer, 0) == -1) return NULL;
|
||||
}
|
||||
|
||||
self->closed = 1;
|
||||
Dprintf("psyco_curs_close: cursor at %p closed", self);
|
||||
|
@ -276,7 +284,7 @@ _psyco_curs_execute(cursorObject *self,
|
|||
IFCLEARPGRES(self->pgres);
|
||||
|
||||
if (self->query) {
|
||||
free(self->query);
|
||||
Py_DECREF(self->query);
|
||||
self->query = NULL;
|
||||
}
|
||||
|
||||
|
@ -284,25 +292,7 @@ _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), so:
|
||||
|
||||
1. if the bound variable is None the format string is changed into a %s
|
||||
(just like now) and the variable substituted with the "NULL" string;
|
||||
|
||||
2. if a bound variable has the .sqlquote method, we suppose it is able
|
||||
to do the required quoting by itself: we call the method and
|
||||
substitute the result in the sequence/dictionary. if the result of
|
||||
calling .sqlquote is not a string object or the format string is not
|
||||
%s we raise an error;
|
||||
|
||||
3. if a bound variable does not have the .sqlquote method AND the
|
||||
format string is %s str() is called on the variable and the result
|
||||
wrapped in a psycopg.QuotedString object;
|
||||
|
||||
4. if the format string is not %s we suppose the object is capable to
|
||||
format itself accordingly, so we don't touch it.
|
||||
|
||||
let's go... */
|
||||
the right thing (i.e., what the user expects) */
|
||||
|
||||
if (vars && vars != Py_None)
|
||||
{
|
||||
|
@ -363,18 +353,33 @@ _psyco_curs_execute(cursorObject *self,
|
|||
Py_XDECREF(uoperation);
|
||||
return 0;
|
||||
}
|
||||
self->query = strdup(PyString_AS_STRING(fquery));
|
||||
|
||||
Dprintf("psyco_curs_execute: cvt->refcnt = %d, fquery->refcnt = %d",
|
||||
cvt->ob_refcnt, fquery->ob_refcnt);
|
||||
Py_DECREF(fquery);
|
||||
|
||||
if (self->name != NULL) {
|
||||
self->query = PyString_FromFormat(
|
||||
"DECLARE %s CURSOR WITHOUT HOLD FOR %s",
|
||||
self->name, PyString_AS_STRING(fquery));
|
||||
Py_DECREF(fquery);
|
||||
}
|
||||
else {
|
||||
self->query = fquery;
|
||||
}
|
||||
|
||||
Dprintf("psyco_curs_execute: cvt->refcnt = %d", cvt->ob_refcnt);
|
||||
Py_DECREF(cvt);
|
||||
}
|
||||
else {
|
||||
self->query = strdup(PyString_AS_STRING(operation));
|
||||
if (self->name != NULL) {
|
||||
self->query = PyString_FromFormat(
|
||||
"DECLARE %s CURSOR WITHOUT HOLD FOR %s",
|
||||
self->name, PyString_AS_STRING(operation));
|
||||
}
|
||||
else {
|
||||
Py_INCREF(operation);
|
||||
self->query = operation;
|
||||
}
|
||||
}
|
||||
|
||||
res = pq_execute(self, self->query, async);
|
||||
|
||||
res = pq_execute(self, PyString_AS_STRING(self->query), async);
|
||||
|
||||
Dprintf("psyco_curs_execute: res = %d, pgres = %p", res, self->pgres);
|
||||
|
||||
|
@ -396,6 +401,24 @@ psyco_curs_execute(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (self->name != NULL) {
|
||||
if (self->query != Py_None) {
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"can't call .execute() on named cursors more than once");
|
||||
return NULL;
|
||||
}
|
||||
if (self->conn->isolation_level == 0) {
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"can't use a named cursor outside of transactions");
|
||||
return NULL;
|
||||
}
|
||||
if (self->conn->mark != self->mark) {
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"named cursor isn't valid anymore");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
EXC_IF_CURS_CLOSED(self);
|
||||
|
||||
if (_psyco_curs_execute(self, operation, vars, async)) {
|
||||
|
@ -424,6 +447,12 @@ psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
}
|
||||
|
||||
EXC_IF_CURS_CLOSED(self);
|
||||
|
||||
if (self->name != NULL) {
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"can't call .executemany() on named cursors");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyIter_Check(vars)) {
|
||||
vars = iter = PyObject_GetIter(vars);
|
||||
|
@ -643,7 +672,6 @@ _psyco_curs_buildrow_with_factory(cursorObject *self, int row)
|
|||
return _psyco_curs_buildrow_fill(self, res, row, n, 0);
|
||||
}
|
||||
|
||||
|
||||
PyObject *
|
||||
psyco_curs_fetchone(cursorObject *self, PyObject *args)
|
||||
{
|
||||
|
@ -655,6 +683,15 @@ psyco_curs_fetchone(cursorObject *self, PyObject *args)
|
|||
if (_psyco_curs_prefetch(self) < 0) return NULL;
|
||||
EXC_IF_NO_TUPLES(self);
|
||||
|
||||
if (self->name != NULL) {
|
||||
char buffer[128];
|
||||
|
||||
EXC_IF_NO_MARK(self);
|
||||
PyOS_snprintf(buffer, 127, "FETCH FORWARD 1 FROM %s", self->name);
|
||||
if (pq_execute(self, buffer, 0) == -1) return NULL;
|
||||
if (_psyco_curs_prefetch(self) < 0) return NULL;
|
||||
}
|
||||
|
||||
Dprintf("psyco_curs_fetchone: fetching row %ld", self->row);
|
||||
Dprintf("psyco_curs_fetchone: rowcount = %ld", self->rowcount);
|
||||
|
||||
|
@ -706,6 +743,16 @@ psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords)
|
|||
if (_psyco_curs_prefetch(self) < 0) return NULL;
|
||||
EXC_IF_NO_TUPLES(self);
|
||||
|
||||
if (self->name != NULL) {
|
||||
char buffer[128];
|
||||
|
||||
EXC_IF_NO_MARK(self);
|
||||
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;
|
||||
}
|
||||
|
||||
/* make sure size is not > than the available number of rows */
|
||||
if (size > self->rowcount - self->row || size < 0) {
|
||||
size = self->rowcount - self->row;
|
||||
|
@ -767,6 +814,15 @@ psyco_curs_fetchall(cursorObject *self, PyObject *args)
|
|||
EXC_IF_CURS_CLOSED(self);
|
||||
if (_psyco_curs_prefetch(self) < 0) return NULL;
|
||||
EXC_IF_NO_TUPLES(self);
|
||||
|
||||
if (self->name != NULL) {
|
||||
char buffer[128];
|
||||
|
||||
EXC_IF_NO_MARK(self);
|
||||
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;
|
||||
}
|
||||
|
||||
size = self->rowcount - self->row;
|
||||
|
||||
|
@ -823,6 +879,12 @@ psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
|
||||
EXC_IF_CURS_CLOSED(self);
|
||||
|
||||
if (self->name != NULL) {
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"can't call .executemany() on named cursors");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(parameters && parameters != Py_None) {
|
||||
nparameters = PyObject_Length(parameters);
|
||||
}
|
||||
|
@ -932,27 +994,47 @@ psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
|
|||
|
||||
EXC_IF_CURS_CLOSED(self);
|
||||
|
||||
if (strcmp(mode, "relative") == 0) {
|
||||
newpos = self->row + value;
|
||||
} else if ( strcmp( mode, "absolute") == 0) {
|
||||
newpos = value;
|
||||
} else {
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"scroll mode must be 'relative' or 'absolute'");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (newpos < 0 || newpos >= self->rowcount ) {
|
||||
PyErr_SetString(PyExc_IndexError,
|
||||
"scroll destination out of bounds");
|
||||
return NULL;
|
||||
/* if the cursor is not named we have the full result set and we can do
|
||||
our own calculations to scroll; else we just delegate the scrolling
|
||||
to the MOVE SQL statement */
|
||||
if (self->name == NULL) {
|
||||
if (strcmp(mode, "relative") == 0) {
|
||||
newpos = self->row + value;
|
||||
} else if (strcmp( mode, "absolute") == 0) {
|
||||
newpos = value;
|
||||
} else {
|
||||
PyErr_SetString(ProgrammingError,
|
||||
"scroll mode must be 'relative' or 'absolute'");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (newpos < 0 || newpos >= self->rowcount ) {
|
||||
PyErr_SetString(PyExc_IndexError,
|
||||
"scroll destination out of bounds");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->row = newpos;
|
||||
}
|
||||
|
||||
self->row = newpos;
|
||||
else {
|
||||
char buffer[128];
|
||||
|
||||
EXC_IF_NO_MARK(self);
|
||||
|
||||
if (strcmp(mode, "absolute") == 0) {
|
||||
PyOS_snprintf(buffer, 127, "MOVE ABSOLUTE %d FROM %s",
|
||||
value, self->name);
|
||||
}
|
||||
else {
|
||||
PyOS_snprintf(buffer, 127, "MOVE %d FROM %s", value, self->name);
|
||||
}
|
||||
if (pq_execute(self, buffer, 0) == -1) return NULL;
|
||||
if (_psyco_curs_prefetch(self) < 0) return NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1221,14 +1303,15 @@ static struct PyMemberDef cursorObject_members[] = {
|
|||
/* DBAPI-2.0 extensions */
|
||||
{"rownumber", T_LONG, OFFSETOF(row), RO},
|
||||
{"connection", T_OBJECT, OFFSETOF(conn), RO},
|
||||
#ifdef PSYCOPG_EXTENSIONS
|
||||
#ifdef PSYCOPG_EXTENSIONS
|
||||
{"name", T_STRING, OFFSETOF(name), RO},
|
||||
{"statusmessage", T_OBJECT, OFFSETOF(pgstatus), RO},
|
||||
{"query", T_STRING, OFFSETOF(query), RO},
|
||||
{"query", T_OBJECT, OFFSETOF(query), RO},
|
||||
{"row_factory", T_OBJECT, OFFSETOF(tuple_factory), 0},
|
||||
{"tzinfo_factory", T_OBJECT, OFFSETOF(tzinfo_factory), 0},
|
||||
{"typecaster", T_OBJECT, OFFSETOF(caster), RO},
|
||||
{"string_types", T_OBJECT, OFFSETOF(string_types), 0},
|
||||
{"binary_types", T_OBJECT, OFFSETOF(binary_types), 0},
|
||||
{"binary_types", T_OBJECT, OFFSETOF(binary_types), 0},
|
||||
#endif
|
||||
{NULL}
|
||||
};
|
||||
|
@ -1236,16 +1319,29 @@ static struct PyMemberDef cursorObject_members[] = {
|
|||
/* initialization and finalization methods */
|
||||
|
||||
static int
|
||||
cursor_setup(cursorObject *self, connectionObject *conn)
|
||||
cursor_setup(cursorObject *self, connectionObject *conn, char *name)
|
||||
{
|
||||
Dprintf("cursor_setup: init cursor object at %p, refcnt = %d",
|
||||
self, ((PyObject *)self)->ob_refcnt);
|
||||
Dprintf("cursor_setup: init cursor object at %p", self);
|
||||
Dprintf("cursor_setup: parameters: name = %s, conn = %p", name, conn);
|
||||
|
||||
if (name) {
|
||||
self->name = PyMem_Malloc(strlen(name)+1);
|
||||
if (self->name == NULL) return 1;
|
||||
strncpy(self->name, name, strlen(name)+1);
|
||||
}
|
||||
|
||||
/* FIXME: why does this raise an excpetion on the _next_ line of code?
|
||||
if (PyObject_IsInstance((PyObject*)conn,
|
||||
(PyObject *)&connectionType) == 0) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"argument 1 must be subclass of psycopg2._psycopg.connection");
|
||||
return 1;
|
||||
} */
|
||||
self->conn = conn;
|
||||
Py_INCREF((PyObject*)self->conn);
|
||||
|
||||
self->closed = 0;
|
||||
|
||||
self->mark = conn->mark;
|
||||
self->pgres = NULL;
|
||||
self->notuples = 1;
|
||||
self->arraysize = 1;
|
||||
|
@ -1254,7 +1350,6 @@ cursor_setup(cursorObject *self, connectionObject *conn)
|
|||
|
||||
self->casts = NULL;
|
||||
self->notice = NULL;
|
||||
self->query = NULL;
|
||||
|
||||
self->string_types = NULL;
|
||||
self->binary_types = NULL;
|
||||
|
@ -1265,6 +1360,8 @@ cursor_setup(cursorObject *self, connectionObject *conn)
|
|||
Py_INCREF(Py_None);
|
||||
self->tuple_factory = Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
self->query = Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
|
||||
/* default tzinfo factory */
|
||||
self->tzinfo_factory = pyPsycopgTzFixedOffsetTimezone;
|
||||
|
@ -1280,15 +1377,15 @@ cursor_dealloc(PyObject* obj)
|
|||
{
|
||||
cursorObject *self = (cursorObject *)obj;
|
||||
|
||||
|
||||
if (self->query) free(self->query);
|
||||
|
||||
Py_DECREF((PyObject*)self->conn);
|
||||
if (self->name) PyMem_Free(self->name);
|
||||
|
||||
Py_XDECREF((PyObject*)self->conn);
|
||||
Py_XDECREF(self->casts);
|
||||
Py_XDECREF(self->description);
|
||||
Py_XDECREF(self->pgstatus);
|
||||
Py_XDECREF(self->tuple_factory);
|
||||
Py_XDECREF(self->tzinfo_factory);
|
||||
Py_XDECREF(self->query);
|
||||
|
||||
IFCLEARPGRES(self->pgres);
|
||||
|
||||
|
@ -1301,16 +1398,18 @@ cursor_dealloc(PyObject* obj)
|
|||
static int
|
||||
cursor_init(PyObject *obj, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
char *name = NULL;
|
||||
PyObject *conn;
|
||||
if (!PyArg_ParseTuple(args, "O", &conn))
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O|s", &conn, &name))
|
||||
return -1;
|
||||
|
||||
return cursor_setup((cursorObject *)obj, (connectionObject *)conn);
|
||||
return cursor_setup((cursorObject *)obj, (connectionObject *)conn, name);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
cursor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
{
|
||||
return type->tp_alloc(type, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ psyco_connect(PyObject *self, PyObject *args, PyObject *keywds)
|
|||
}
|
||||
|
||||
if (iport > 0)
|
||||
snprintf(port, 16, "%d", iport);
|
||||
PyOS_snprintf(port, 16, "%d", iport);
|
||||
|
||||
if (dsn == NULL) {
|
||||
int l = 36; /* len("dbname= user= password= host= port=\0") */
|
||||
|
@ -295,26 +295,29 @@ PyObject *Error, *Warning, *InterfaceError, *DatabaseError,
|
|||
static void
|
||||
psyco_errors_init(void)
|
||||
{
|
||||
Error = PyErr_NewException("psycopg2._psycopg.Error",
|
||||
PyExc_StandardError, NULL);
|
||||
Warning = PyErr_NewException("psycopg2._psycopg.Warning",
|
||||
/* the names of the exceptions here reflect the oranization of the
|
||||
psycopg2 module and not the fact the the original error objects
|
||||
live in _psycopg */
|
||||
|
||||
Error = PyErr_NewException("psycopg2.Error", PyExc_StandardError, NULL);
|
||||
|
||||
Warning = PyErr_NewException("psycopg2.Warning",
|
||||
PyExc_StandardError,NULL);
|
||||
InterfaceError = PyErr_NewException("psycopg2._psycopg.InterfaceError",
|
||||
InterfaceError = PyErr_NewException("psycopg2.InterfaceError",
|
||||
Error, NULL);
|
||||
DatabaseError = PyErr_NewException("psycopg2._psycopg.DatabaseError",
|
||||
DatabaseError = PyErr_NewException("psycopg2.DatabaseError",
|
||||
Error, NULL);
|
||||
InternalError = PyErr_NewException("psycopg2._psycopg.InternalError",
|
||||
InternalError = PyErr_NewException("psycopg2.InternalError",
|
||||
DatabaseError, NULL);
|
||||
OperationalError = PyErr_NewException("psycopg2._psycopg.OperationalError",
|
||||
OperationalError = PyErr_NewException("psycopg2.OperationalError",
|
||||
DatabaseError, NULL);
|
||||
ProgrammingError = PyErr_NewException("psycopg2._psycopg.ProgrammingError",
|
||||
ProgrammingError = PyErr_NewException("psycopg2.ProgrammingError",
|
||||
DatabaseError, NULL);
|
||||
IntegrityError = PyErr_NewException("psycopg2._psycopg.IntegrityError",
|
||||
IntegrityError = PyErr_NewException("psycopg2.IntegrityError",
|
||||
DatabaseError,NULL);
|
||||
DataError = PyErr_NewException("psycopg2._psycopg.DataError",
|
||||
DataError = PyErr_NewException("psycopg2.DataError",
|
||||
DatabaseError, NULL);
|
||||
NotSupportedError =
|
||||
PyErr_NewException("psycopg2._psycopg.NotSupportedError",
|
||||
NotSupportedError = PyErr_NewException("psycopg2.NotSupportedError",
|
||||
DatabaseError, NULL);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user