summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--psycopg/cursor.h1
-rw-r--r--psycopg/cursor_type.c48
-rw-r--r--psycopg/psycopg.h3
-rw-r--r--psycopg/utils.c40
4 files changed, 47 insertions, 45 deletions
diff --git a/psycopg/cursor.h b/psycopg/cursor.h
index e291d45..3c94fe3 100644
--- a/psycopg/cursor.h
+++ b/psycopg/cursor.h
@@ -80,6 +80,7 @@ struct cursorObject {
char *qattr; /* quoting attr, used when quoting strings */
char *notice; /* a notice from the backend */
char *name; /* this cursor name */
+ char *qname; /* this cursor name, quoted */
PyObject *string_types; /* a set of typecasters for string types */
PyObject *binary_types; /* a set of typecasters for binary types */
diff --git a/psycopg/cursor_type.c b/psycopg/cursor_type.c
index fe79bbf..6b66217 100644
--- a/psycopg/cursor_type.c
+++ b/psycopg/cursor_type.c
@@ -55,7 +55,7 @@ psyco_curs_close(cursorObject *self)
goto exit;
}
- if (self->name != NULL) {
+ if (self->qname != NULL) {
char buffer[128];
PGTransactionStatusType status;
@@ -68,7 +68,7 @@ psyco_curs_close(cursorObject *self)
if (!(status == PQTRANS_UNKNOWN || status == PQTRANS_INERROR)) {
EXC_IF_NO_MARK(self);
- PyOS_snprintf(buffer, 127, "CLOSE \"%s\"", self->name);
+ PyOS_snprintf(buffer, 127, "CLOSE %s", self->qname);
if (pq_execute(self, buffer, 0, 0, 1) == -1) return NULL;
}
else {
@@ -422,10 +422,10 @@ _psyco_curs_execute(cursorObject *self,
goto exit;
}
- if (self->name != NULL) {
+ if (self->qname != NULL) {
self->query = Bytes_FromFormat(
- "DECLARE \"%s\" %sCURSOR %s HOLD FOR %s",
- self->name,
+ "DECLARE %s %sCURSOR %s HOLD FOR %s",
+ self->qname,
scroll,
self->withhold ? "WITH" : "WITHOUT",
Bytes_AS_STRING(fquery));
@@ -436,10 +436,10 @@ _psyco_curs_execute(cursorObject *self,
}
}
else {
- if (self->name != NULL) {
+ if (self->qname != NULL) {
self->query = Bytes_FromFormat(
- "DECLARE \"%s\" %sCURSOR %s HOLD FOR %s",
- self->name,
+ "DECLARE %s %sCURSOR %s HOLD FOR %s",
+ self->qname,
scroll,
self->withhold ? "WITH" : "WITHOUT",
Bytes_AS_STRING(operation));
@@ -768,13 +768,13 @@ psyco_curs_fetchone(cursorObject *self)
if (_psyco_curs_prefetch(self) < 0) return NULL;
EXC_IF_NO_TUPLES(self);
- if (self->name != NULL) {
+ if (self->qname != NULL) {
char buffer[128];
EXC_IF_NO_MARK(self);
EXC_IF_ASYNC_IN_PROGRESS(self, fetchone);
EXC_IF_TPC_PREPARED(self->conn, fetchone);
- PyOS_snprintf(buffer, 127, "FETCH FORWARD 1 FROM \"%s\"", self->name);
+ PyOS_snprintf(buffer, 127, "FETCH FORWARD 1 FROM %s", self->qname);
if (pq_execute(self, buffer, 0, 0, self->withhold) == -1) return NULL;
if (_psyco_curs_prefetch(self) < 0) return NULL;
}
@@ -823,8 +823,8 @@ psyco_curs_next_named(cursorObject *self)
if (self->row >= self->rowcount) {
char buffer[128];
- PyOS_snprintf(buffer, 127, "FETCH FORWARD %ld FROM \"%s\"",
- self->itersize, self->name);
+ PyOS_snprintf(buffer, 127, "FETCH FORWARD %ld FROM %s",
+ self->itersize, self->qname);
if (pq_execute(self, buffer, 0, 0, self->withhold) == -1) return NULL;
if (_psyco_curs_prefetch(self) < 0) return NULL;
}
@@ -886,14 +886,14 @@ 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) {
+ if (self->qname != NULL) {
char buffer[128];
EXC_IF_NO_MARK(self);
EXC_IF_ASYNC_IN_PROGRESS(self, fetchmany);
EXC_IF_TPC_PREPARED(self->conn, fetchone);
- PyOS_snprintf(buffer, 127, "FETCH FORWARD %d FROM \"%s\"",
- (int)size, self->name);
+ PyOS_snprintf(buffer, 127, "FETCH FORWARD %d FROM %s",
+ (int)size, self->qname);
if (pq_execute(self, buffer, 0, 0, self->withhold) == -1) { goto exit; }
if (_psyco_curs_prefetch(self) < 0) { goto exit; }
}
@@ -962,13 +962,13 @@ psyco_curs_fetchall(cursorObject *self)
if (_psyco_curs_prefetch(self) < 0) return NULL;
EXC_IF_NO_TUPLES(self);
- if (self->name != NULL) {
+ if (self->qname != NULL) {
char buffer[128];
EXC_IF_NO_MARK(self);
EXC_IF_ASYNC_IN_PROGRESS(self, fetchall);
EXC_IF_TPC_PREPARED(self->conn, fetchall);
- PyOS_snprintf(buffer, 127, "FETCH FORWARD ALL FROM \"%s\"", self->name);
+ PyOS_snprintf(buffer, 127, "FETCH FORWARD ALL FROM %s", self->qname);
if (pq_execute(self, buffer, 0, 0, self->withhold) == -1) { goto exit; }
if (_psyco_curs_prefetch(self) < 0) { goto exit; }
}
@@ -1153,7 +1153,7 @@ psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
/* 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 (self->qname == NULL) {
if (strcmp(mode, "relative") == 0) {
newpos = self->row + value;
} else if (strcmp( mode, "absolute") == 0) {
@@ -1181,11 +1181,11 @@ psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
EXC_IF_TPC_PREPARED(self->conn, scroll);
if (strcmp(mode, "absolute") == 0) {
- PyOS_snprintf(buffer, 127, "MOVE ABSOLUTE %d FROM \"%s\"",
- value, self->name);
+ PyOS_snprintf(buffer, 127, "MOVE ABSOLUTE %d FROM %s",
+ value, self->qname);
}
else {
- PyOS_snprintf(buffer, 127, "MOVE %d FROM \"%s\"", value, self->name);
+ PyOS_snprintf(buffer, 127, "MOVE %d FROM %s", value, self->qname);
}
if (pq_execute(self, buffer, 0, 0, self->withhold) == -1) return NULL;
if (_psyco_curs_prefetch(self) < 0) return NULL;
@@ -1815,7 +1815,10 @@ cursor_setup(cursorObject *self, connectionObject *conn, const char *name)
Dprintf("cursor_setup: parameters: name = %s, conn = %p", name, conn);
if (name) {
- if (!(self->name = psycopg_escape_identifier_easy(name, 0))) {
+ if (0 > psycopg_strdup(&self->name, name, 0)) {
+ return -1;
+ }
+ if (!(self->qname = psycopg_escape_identifier(conn, name, 0))) {
return -1;
}
}
@@ -1891,6 +1894,7 @@ cursor_dealloc(PyObject* obj)
cursor_clear(self);
PyMem_Free(self->name);
+ PQfreemem(self->qname);
CLEARPGRES(self->pgres);
diff --git a/psycopg/psycopg.h b/psycopg/psycopg.h
index 82b4293..438d763 100644
--- a/psycopg/psycopg.h
+++ b/psycopg/psycopg.h
@@ -128,7 +128,8 @@ RAISES HIDDEN PyObject *psyco_set_error(PyObject *exc, cursorObject *curs, const
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_easy(const char *from, Py_ssize_t len);
+HIDDEN char *psycopg_escape_identifier(connectionObject *conn,
+ const char *str, size_t len);
HIDDEN int psycopg_strdup(char **to, const char *from, Py_ssize_t len);
HIDDEN int psycopg_is_text_file(PyObject *f);
diff --git a/psycopg/utils.c b/psycopg/utils.c
index 631b839..c518cc5 100644
--- a/psycopg/utils.c
+++ b/psycopg/utils.c
@@ -90,40 +90,36 @@ psycopg_escape_string(connectionObject *conn, const char *from, Py_ssize_t len,
return to;
}
-/* Escape a string to build a valid PostgreSQL identifier.
+/* Escape a string for inclusion in a query as identifier.
*
- * Allocate a new buffer on the Python heap containing the new string.
* 'len' is optional: if 0 the length is calculated.
*
- * The returned string doesn't include quotes.
- *
- * WARNING: this function is not so safe to allow untrusted input: it does no
- * check for multibyte chars. Such a function should be built on
- * PQescapeIdentifier, which is only available from PostgreSQL 9.0.
+ * Return a string allocated by Postgres: free it using PQfreemem
+ * In case of error set a Python exception.
*/
char *
-psycopg_escape_identifier_easy(const char *from, Py_ssize_t len)
+psycopg_escape_identifier(connectionObject *conn, const char *str, size_t len)
{
- char *rv;
- const char *src;
- char *dst;
+ char *rv = NULL;
- if (!len) { len = strlen(from); }
- if (!(rv = PyMem_New(char, 1 + 2 * len))) {
- PyErr_NoMemory();
- return NULL;
+ if (!conn || !conn->pgconn) {
+ PyErr_SetString(InterfaceError, "connection not valid");
+ goto exit;
}
- /* The only thing to do is double quotes */
- for (src = from, dst = rv; *src; ++src, ++dst) {
- *dst = *src;
- if ('"' == *src) {
- *++dst = '"';
+ if (!len) { len = strlen(str); }
+
+ rv = PQescapeIdentifier(conn->pgconn, str, len);
+ if (!rv) {
+ char *msg;
+ msg = PQerrorMessage(conn->pgconn);
+ if (!msg || !msg[0]) {
+ msg = "no message provided";
}
+ PyErr_Format(InterfaceError, "failed to escape identifier: %s", msg);
}
- *dst = '\0';
-
+exit:
return rv;
}