Dropped internal escape identifier function

Using libpq one as now it's guaranteed to be present.
This commit is contained in:
Daniele Varrazzo 2016-12-26 02:37:36 +01:00
parent 17698c4815
commit a53b39efe8
4 changed files with 47 additions and 45 deletions

View File

@ -80,6 +80,7 @@ struct cursorObject {
char *qattr; /* quoting attr, used when quoting strings */ char *qattr; /* quoting attr, used when quoting strings */
char *notice; /* a notice from the backend */ char *notice; /* a notice from the backend */
char *name; /* this cursor name */ char *name; /* this cursor name */
char *qname; /* this cursor name, quoted */
PyObject *string_types; /* a set of typecasters for string types */ PyObject *string_types; /* a set of typecasters for string types */
PyObject *binary_types; /* a set of typecasters for binary types */ PyObject *binary_types; /* a set of typecasters for binary types */

View File

@ -55,7 +55,7 @@ psyco_curs_close(cursorObject *self)
goto exit; goto exit;
} }
if (self->name != NULL) { if (self->qname != NULL) {
char buffer[128]; char buffer[128];
PGTransactionStatusType status; PGTransactionStatusType status;
@ -68,7 +68,7 @@ psyco_curs_close(cursorObject *self)
if (!(status == PQTRANS_UNKNOWN || status == PQTRANS_INERROR)) { if (!(status == PQTRANS_UNKNOWN || status == PQTRANS_INERROR)) {
EXC_IF_NO_MARK(self); 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; if (pq_execute(self, buffer, 0, 0, 1) == -1) return NULL;
} }
else { else {
@ -422,10 +422,10 @@ _psyco_curs_execute(cursorObject *self,
goto exit; goto exit;
} }
if (self->name != NULL) { if (self->qname != NULL) {
self->query = Bytes_FromFormat( self->query = Bytes_FromFormat(
"DECLARE \"%s\" %sCURSOR %s HOLD FOR %s", "DECLARE %s %sCURSOR %s HOLD FOR %s",
self->name, self->qname,
scroll, scroll,
self->withhold ? "WITH" : "WITHOUT", self->withhold ? "WITH" : "WITHOUT",
Bytes_AS_STRING(fquery)); Bytes_AS_STRING(fquery));
@ -436,10 +436,10 @@ _psyco_curs_execute(cursorObject *self,
} }
} }
else { else {
if (self->name != NULL) { if (self->qname != NULL) {
self->query = Bytes_FromFormat( self->query = Bytes_FromFormat(
"DECLARE \"%s\" %sCURSOR %s HOLD FOR %s", "DECLARE %s %sCURSOR %s HOLD FOR %s",
self->name, self->qname,
scroll, scroll,
self->withhold ? "WITH" : "WITHOUT", self->withhold ? "WITH" : "WITHOUT",
Bytes_AS_STRING(operation)); Bytes_AS_STRING(operation));
@ -768,13 +768,13 @@ psyco_curs_fetchone(cursorObject *self)
if (_psyco_curs_prefetch(self) < 0) return NULL; if (_psyco_curs_prefetch(self) < 0) return NULL;
EXC_IF_NO_TUPLES(self); EXC_IF_NO_TUPLES(self);
if (self->name != NULL) { if (self->qname != NULL) {
char buffer[128]; char buffer[128];
EXC_IF_NO_MARK(self); EXC_IF_NO_MARK(self);
EXC_IF_ASYNC_IN_PROGRESS(self, fetchone); EXC_IF_ASYNC_IN_PROGRESS(self, fetchone);
EXC_IF_TPC_PREPARED(self->conn, 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 (pq_execute(self, buffer, 0, 0, self->withhold) == -1) return NULL;
if (_psyco_curs_prefetch(self) < 0) 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) { if (self->row >= self->rowcount) {
char buffer[128]; char buffer[128];
PyOS_snprintf(buffer, 127, "FETCH FORWARD %ld FROM \"%s\"", PyOS_snprintf(buffer, 127, "FETCH FORWARD %ld FROM %s",
self->itersize, self->name); self->itersize, self->qname);
if (pq_execute(self, buffer, 0, 0, self->withhold) == -1) return NULL; if (pq_execute(self, buffer, 0, 0, self->withhold) == -1) return NULL;
if (_psyco_curs_prefetch(self) < 0) 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; if (_psyco_curs_prefetch(self) < 0) return NULL;
EXC_IF_NO_TUPLES(self); EXC_IF_NO_TUPLES(self);
if (self->name != NULL) { if (self->qname != NULL) {
char buffer[128]; char buffer[128];
EXC_IF_NO_MARK(self); EXC_IF_NO_MARK(self);
EXC_IF_ASYNC_IN_PROGRESS(self, fetchmany); EXC_IF_ASYNC_IN_PROGRESS(self, fetchmany);
EXC_IF_TPC_PREPARED(self->conn, fetchone); EXC_IF_TPC_PREPARED(self->conn, fetchone);
PyOS_snprintf(buffer, 127, "FETCH FORWARD %d FROM \"%s\"", PyOS_snprintf(buffer, 127, "FETCH FORWARD %d FROM %s",
(int)size, self->name); (int)size, self->qname);
if (pq_execute(self, buffer, 0, 0, self->withhold) == -1) { goto exit; } if (pq_execute(self, buffer, 0, 0, self->withhold) == -1) { goto exit; }
if (_psyco_curs_prefetch(self) < 0) { 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; if (_psyco_curs_prefetch(self) < 0) return NULL;
EXC_IF_NO_TUPLES(self); EXC_IF_NO_TUPLES(self);
if (self->name != NULL) { if (self->qname != NULL) {
char buffer[128]; char buffer[128];
EXC_IF_NO_MARK(self); EXC_IF_NO_MARK(self);
EXC_IF_ASYNC_IN_PROGRESS(self, fetchall); EXC_IF_ASYNC_IN_PROGRESS(self, fetchall);
EXC_IF_TPC_PREPARED(self->conn, 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 (pq_execute(self, buffer, 0, 0, self->withhold) == -1) { goto exit; }
if (_psyco_curs_prefetch(self) < 0) { 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 /* 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 our own calculations to scroll; else we just delegate the scrolling
to the MOVE SQL statement */ to the MOVE SQL statement */
if (self->name == NULL) { if (self->qname == NULL) {
if (strcmp(mode, "relative") == 0) { if (strcmp(mode, "relative") == 0) {
newpos = self->row + value; newpos = self->row + value;
} else if (strcmp( mode, "absolute") == 0) { } 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); EXC_IF_TPC_PREPARED(self->conn, scroll);
if (strcmp(mode, "absolute") == 0) { if (strcmp(mode, "absolute") == 0) {
PyOS_snprintf(buffer, 127, "MOVE ABSOLUTE %d FROM \"%s\"", PyOS_snprintf(buffer, 127, "MOVE ABSOLUTE %d FROM %s",
value, self->name); value, self->qname);
} }
else { 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 (pq_execute(self, buffer, 0, 0, self->withhold) == -1) return NULL;
if (_psyco_curs_prefetch(self) < 0) 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); Dprintf("cursor_setup: parameters: name = %s, conn = %p", name, conn);
if (name) { 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; return -1;
} }
} }
@ -1891,6 +1894,7 @@ cursor_dealloc(PyObject* obj)
cursor_clear(self); cursor_clear(self);
PyMem_Free(self->name); PyMem_Free(self->name);
PQfreemem(self->qname);
CLEARPGRES(self->pgres); CLEARPGRES(self->pgres);

View File

@ -128,7 +128,8 @@ RAISES HIDDEN PyObject *psyco_set_error(PyObject *exc, cursorObject *curs, const
HIDDEN char *psycopg_escape_string(connectionObject *conn, HIDDEN char *psycopg_escape_string(connectionObject *conn,
const char *from, Py_ssize_t len, char *to, Py_ssize_t *tolen); 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_strdup(char **to, const char *from, Py_ssize_t len);
HIDDEN int psycopg_is_text_file(PyObject *f); HIDDEN int psycopg_is_text_file(PyObject *f);

View File

@ -90,40 +90,36 @@ psycopg_escape_string(connectionObject *conn, const char *from, Py_ssize_t len,
return to; 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. * 'len' is optional: if 0 the length is calculated.
* *
* The returned string doesn't include quotes. * Return a string allocated by Postgres: free it using PQfreemem
* * In case of error set a Python exception.
* 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.
*/ */
char * 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; char *rv = NULL;
const char *src;
char *dst;
if (!len) { len = strlen(from); } if (!conn || !conn->pgconn) {
if (!(rv = PyMem_New(char, 1 + 2 * len))) { PyErr_SetString(InterfaceError, "connection not valid");
PyErr_NoMemory(); goto exit;
return NULL;
} }
/* The only thing to do is double quotes */ if (!len) { len = strlen(str); }
for (src = from, dst = rv; *src; ++src, ++dst) {
*dst = *src; rv = PQescapeIdentifier(conn->pgconn, str, len);
if ('"' == *src) { if (!rv) {
*++dst = '"'; 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; return rv;
} }