Skip to content

Commit a53b39e

Browse files
committed
Dropped internal escape identifier function
Using libpq one as now it's guaranteed to be present.
1 parent 17698c4 commit a53b39e

File tree

4 files changed

+47
-45
lines changed

4 files changed

+47
-45
lines changed

psycopg/cursor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ struct cursorObject {
8080
char *qattr; /* quoting attr, used when quoting strings */
8181
char *notice; /* a notice from the backend */
8282
char *name; /* this cursor name */
83+
char *qname; /* this cursor name, quoted */
8384

8485
PyObject *string_types; /* a set of typecasters for string types */
8586
PyObject *binary_types; /* a set of typecasters for binary types */

psycopg/cursor_type.c

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ psyco_curs_close(cursorObject *self)
5555
goto exit;
5656
}
5757

58-
if (self->name != NULL) {
58+
if (self->qname != NULL) {
5959
char buffer[128];
6060
PGTransactionStatusType status;
6161

@@ -68,7 +68,7 @@ psyco_curs_close(cursorObject *self)
6868

6969
if (!(status == PQTRANS_UNKNOWN || status == PQTRANS_INERROR)) {
7070
EXC_IF_NO_MARK(self);
71-
PyOS_snprintf(buffer, 127, "CLOSE \"%s\"", self->name);
71+
PyOS_snprintf(buffer, 127, "CLOSE %s", self->qname);
7272
if (pq_execute(self, buffer, 0, 0, 1) == -1) return NULL;
7373
}
7474
else {
@@ -422,10 +422,10 @@ _psyco_curs_execute(cursorObject *self,
422422
goto exit;
423423
}
424424

425-
if (self->name != NULL) {
425+
if (self->qname != NULL) {
426426
self->query = Bytes_FromFormat(
427-
"DECLARE \"%s\" %sCURSOR %s HOLD FOR %s",
428-
self->name,
427+
"DECLARE %s %sCURSOR %s HOLD FOR %s",
428+
self->qname,
429429
scroll,
430430
self->withhold ? "WITH" : "WITHOUT",
431431
Bytes_AS_STRING(fquery));
@@ -436,10 +436,10 @@ _psyco_curs_execute(cursorObject *self,
436436
}
437437
}
438438
else {
439-
if (self->name != NULL) {
439+
if (self->qname != NULL) {
440440
self->query = Bytes_FromFormat(
441-
"DECLARE \"%s\" %sCURSOR %s HOLD FOR %s",
442-
self->name,
441+
"DECLARE %s %sCURSOR %s HOLD FOR %s",
442+
self->qname,
443443
scroll,
444444
self->withhold ? "WITH" : "WITHOUT",
445445
Bytes_AS_STRING(operation));
@@ -768,13 +768,13 @@ psyco_curs_fetchone(cursorObject *self)
768768
if (_psyco_curs_prefetch(self) < 0) return NULL;
769769
EXC_IF_NO_TUPLES(self);
770770

771-
if (self->name != NULL) {
771+
if (self->qname != NULL) {
772772
char buffer[128];
773773

774774
EXC_IF_NO_MARK(self);
775775
EXC_IF_ASYNC_IN_PROGRESS(self, fetchone);
776776
EXC_IF_TPC_PREPARED(self->conn, fetchone);
777-
PyOS_snprintf(buffer, 127, "FETCH FORWARD 1 FROM \"%s\"", self->name);
777+
PyOS_snprintf(buffer, 127, "FETCH FORWARD 1 FROM %s", self->qname);
778778
if (pq_execute(self, buffer, 0, 0, self->withhold) == -1) return NULL;
779779
if (_psyco_curs_prefetch(self) < 0) return NULL;
780780
}
@@ -823,8 +823,8 @@ psyco_curs_next_named(cursorObject *self)
823823
if (self->row >= self->rowcount) {
824824
char buffer[128];
825825

826-
PyOS_snprintf(buffer, 127, "FETCH FORWARD %ld FROM \"%s\"",
827-
self->itersize, self->name);
826+
PyOS_snprintf(buffer, 127, "FETCH FORWARD %ld FROM %s",
827+
self->itersize, self->qname);
828828
if (pq_execute(self, buffer, 0, 0, self->withhold) == -1) return NULL;
829829
if (_psyco_curs_prefetch(self) < 0) return NULL;
830830
}
@@ -886,14 +886,14 @@ psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords)
886886
if (_psyco_curs_prefetch(self) < 0) return NULL;
887887
EXC_IF_NO_TUPLES(self);
888888

889-
if (self->name != NULL) {
889+
if (self->qname != NULL) {
890890
char buffer[128];
891891

892892
EXC_IF_NO_MARK(self);
893893
EXC_IF_ASYNC_IN_PROGRESS(self, fetchmany);
894894
EXC_IF_TPC_PREPARED(self->conn, fetchone);
895-
PyOS_snprintf(buffer, 127, "FETCH FORWARD %d FROM \"%s\"",
896-
(int)size, self->name);
895+
PyOS_snprintf(buffer, 127, "FETCH FORWARD %d FROM %s",
896+
(int)size, self->qname);
897897
if (pq_execute(self, buffer, 0, 0, self->withhold) == -1) { goto exit; }
898898
if (_psyco_curs_prefetch(self) < 0) { goto exit; }
899899
}
@@ -962,13 +962,13 @@ psyco_curs_fetchall(cursorObject *self)
962962
if (_psyco_curs_prefetch(self) < 0) return NULL;
963963
EXC_IF_NO_TUPLES(self);
964964

965-
if (self->name != NULL) {
965+
if (self->qname != NULL) {
966966
char buffer[128];
967967

968968
EXC_IF_NO_MARK(self);
969969
EXC_IF_ASYNC_IN_PROGRESS(self, fetchall);
970970
EXC_IF_TPC_PREPARED(self->conn, fetchall);
971-
PyOS_snprintf(buffer, 127, "FETCH FORWARD ALL FROM \"%s\"", self->name);
971+
PyOS_snprintf(buffer, 127, "FETCH FORWARD ALL FROM %s", self->qname);
972972
if (pq_execute(self, buffer, 0, 0, self->withhold) == -1) { goto exit; }
973973
if (_psyco_curs_prefetch(self) < 0) { goto exit; }
974974
}
@@ -1153,7 +1153,7 @@ psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
11531153
/* if the cursor is not named we have the full result set and we can do
11541154
our own calculations to scroll; else we just delegate the scrolling
11551155
to the MOVE SQL statement */
1156-
if (self->name == NULL) {
1156+
if (self->qname == NULL) {
11571157
if (strcmp(mode, "relative") == 0) {
11581158
newpos = self->row + value;
11591159
} else if (strcmp( mode, "absolute") == 0) {
@@ -1181,11 +1181,11 @@ psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs)
11811181
EXC_IF_TPC_PREPARED(self->conn, scroll);
11821182

11831183
if (strcmp(mode, "absolute") == 0) {
1184-
PyOS_snprintf(buffer, 127, "MOVE ABSOLUTE %d FROM \"%s\"",
1185-
value, self->name);
1184+
PyOS_snprintf(buffer, 127, "MOVE ABSOLUTE %d FROM %s",
1185+
value, self->qname);
11861186
}
11871187
else {
1188-
PyOS_snprintf(buffer, 127, "MOVE %d FROM \"%s\"", value, self->name);
1188+
PyOS_snprintf(buffer, 127, "MOVE %d FROM %s", value, self->qname);
11891189
}
11901190
if (pq_execute(self, buffer, 0, 0, self->withhold) == -1) return NULL;
11911191
if (_psyco_curs_prefetch(self) < 0) return NULL;
@@ -1815,7 +1815,10 @@ cursor_setup(cursorObject *self, connectionObject *conn, const char *name)
18151815
Dprintf("cursor_setup: parameters: name = %s, conn = %p", name, conn);
18161816

18171817
if (name) {
1818-
if (!(self->name = psycopg_escape_identifier_easy(name, 0))) {
1818+
if (0 > psycopg_strdup(&self->name, name, 0)) {
1819+
return -1;
1820+
}
1821+
if (!(self->qname = psycopg_escape_identifier(conn, name, 0))) {
18191822
return -1;
18201823
}
18211824
}
@@ -1891,6 +1894,7 @@ cursor_dealloc(PyObject* obj)
18911894
cursor_clear(self);
18921895

18931896
PyMem_Free(self->name);
1897+
PQfreemem(self->qname);
18941898

18951899
CLEARPGRES(self->pgres);
18961900

psycopg/psycopg.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ RAISES HIDDEN PyObject *psyco_set_error(PyObject *exc, cursorObject *curs, const
128128

129129
HIDDEN char *psycopg_escape_string(connectionObject *conn,
130130
const char *from, Py_ssize_t len, char *to, Py_ssize_t *tolen);
131-
HIDDEN char *psycopg_escape_identifier_easy(const char *from, Py_ssize_t len);
131+
HIDDEN char *psycopg_escape_identifier(connectionObject *conn,
132+
const char *str, size_t len);
132133
HIDDEN int psycopg_strdup(char **to, const char *from, Py_ssize_t len);
133134
HIDDEN int psycopg_is_text_file(PyObject *f);
134135

psycopg/utils.c

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -90,40 +90,36 @@ psycopg_escape_string(connectionObject *conn, const char *from, Py_ssize_t len,
9090
return to;
9191
}
9292

93-
/* Escape a string to build a valid PostgreSQL identifier.
93+
/* Escape a string for inclusion in a query as identifier.
9494
*
95-
* Allocate a new buffer on the Python heap containing the new string.
9695
* 'len' is optional: if 0 the length is calculated.
9796
*
98-
* The returned string doesn't include quotes.
99-
*
100-
* WARNING: this function is not so safe to allow untrusted input: it does no
101-
* check for multibyte chars. Such a function should be built on
102-
* PQescapeIdentifier, which is only available from PostgreSQL 9.0.
97+
* Return a string allocated by Postgres: free it using PQfreemem
98+
* In case of error set a Python exception.
10399
*/
104100
char *
105-
psycopg_escape_identifier_easy(const char *from, Py_ssize_t len)
101+
psycopg_escape_identifier(connectionObject *conn, const char *str, size_t len)
106102
{
107-
char *rv;
108-
const char *src;
109-
char *dst;
103+
char *rv = NULL;
110104

111-
if (!len) { len = strlen(from); }
112-
if (!(rv = PyMem_New(char, 1 + 2 * len))) {
113-
PyErr_NoMemory();
114-
return NULL;
105+
if (!conn || !conn->pgconn) {
106+
PyErr_SetString(InterfaceError, "connection not valid");
107+
goto exit;
115108
}
116109

117-
/* The only thing to do is double quotes */
118-
for (src = from, dst = rv; *src; ++src, ++dst) {
119-
*dst = *src;
120-
if ('"' == *src) {
121-
*++dst = '"';
110+
if (!len) { len = strlen(str); }
111+
112+
rv = PQescapeIdentifier(conn->pgconn, str, len);
113+
if (!rv) {
114+
char *msg;
115+
msg = PQerrorMessage(conn->pgconn);
116+
if (!msg || !msg[0]) {
117+
msg = "no message provided";
122118
}
119+
PyErr_Format(InterfaceError, "failed to escape identifier: %s", msg);
123120
}
124121

125-
*dst = '\0';
126-
122+
exit:
127123
return rv;
128124
}
129125

0 commit comments

Comments
 (0)