Commit 523adeb1 authored by Tom Lane's avatar Tom Lane

Teach PQcmdTuples() that a COPY command tag might contain a row count,

and tighten up its sanity checking of the tag as a safety measure.
Volkan Yazici.
parent 502e9aef
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.204 2006/03/01 00:23:21 momjian Exp $ $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.205 2006/03/03 20:57:32 tgl Exp $
--> -->
<chapter id="libpq"> <chapter id="libpq">
...@@ -2127,12 +2127,13 @@ char *PQcmdTuples(PGresult *res); ...@@ -2127,12 +2127,13 @@ char *PQcmdTuples(PGresult *res);
affected by the <acronym>SQL</> statement that generated the affected by the <acronym>SQL</> statement that generated the
<structname>PGresult</>. This function can only be used <structname>PGresult</>. This function can only be used
following the execution of an <command>INSERT</>, following the execution of an <command>INSERT</>,
<command>UPDATE</>, <command>DELETE</>, <command>MOVE</>, or <command>UPDATE</>, <command>DELETE</>, <command>MOVE</>,
<command>FETCH</> statement, or an <command>EXECUTE</> of a <command>FETCH</>, or <command>COPY</> statement,
prepared query that contains a <command>INSERT</>, or an <command>EXECUTE</> of a
prepared query that contains an <command>INSERT</>,
<command>UPDATE</>, or <command>DELETE</> statement. If the <command>UPDATE</>, or <command>DELETE</> statement. If the
command that generated the <structname>PGresult</> was command that generated the <structname>PGresult</> was
anything else, <function>PQcmdTuples</> returns the empty anything else, <function>PQcmdTuples</> returns an empty
string. The caller should not free the return value string. The caller should not free the return value
directly. It will be freed when the associated directly. It will be freed when the associated
<structname>PGresult</> handle is passed to <structname>PGresult</> handle is passed to
......
...@@ -8,13 +8,12 @@ ...@@ -8,13 +8,12 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.179 2006/01/25 20:44:32 tgl Exp $ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.180 2006/03/03 20:57:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include <errno.h>
#include <ctype.h> #include <ctype.h>
#include <fcntl.h> #include <fcntl.h>
...@@ -2168,8 +2167,8 @@ PQoidValue(const PGresult *res) ...@@ -2168,8 +2167,8 @@ PQoidValue(const PGresult *res)
/* /*
* PQcmdTuples - * PQcmdTuples -
* If the last command was an INSERT/UPDATE/DELETE/MOVE/FETCH, return a * If the last command was INSERT/UPDATE/DELETE/MOVE/FETCH/COPY, return
* string containing the number of inserted/affected tuples. If not, * a string containing the number of inserted/affected tuples. If not,
* return "". * return "".
* *
* XXX: this should probably return an int * XXX: this should probably return an int
...@@ -2177,40 +2176,48 @@ PQoidValue(const PGresult *res) ...@@ -2177,40 +2176,48 @@ PQoidValue(const PGresult *res)
char * char *
PQcmdTuples(PGresult *res) PQcmdTuples(PGresult *res)
{ {
char *p; char *p, *c;
if (!res) if (!res)
return ""; return "";
if (strncmp(res->cmdStatus, "INSERT ", 7) == 0) if (strncmp(res->cmdStatus, "INSERT ", 7) == 0)
{ {
p = res->cmdStatus + 6; p = res->cmdStatus + 7;
/* INSERT: skip oid and space */
while (*p && *p != ' ')
p++; p++;
/* INSERT: skip oid */ if (*p == 0)
while (*p != ' ' && *p) goto interpret_error; /* no space? */
p++; p++;
} }
else if (strncmp(res->cmdStatus, "DELETE ", 7) == 0 || else if (strncmp(res->cmdStatus, "DELETE ", 7) == 0 ||
strncmp(res->cmdStatus, "UPDATE ", 7) == 0) strncmp(res->cmdStatus, "UPDATE ", 7) == 0)
p = res->cmdStatus + 6; p = res->cmdStatus + 7;
else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0) else if (strncmp(res->cmdStatus, "FETCH ", 6) == 0)
p = res->cmdStatus + 6;
else if (strncmp(res->cmdStatus, "MOVE ", 5) == 0 ||
strncmp(res->cmdStatus, "COPY ", 5) == 0)
p = res->cmdStatus + 5; p = res->cmdStatus + 5;
else if (strncmp(res->cmdStatus, "MOVE ", 5) == 0)
p = res->cmdStatus + 4;
else else
return ""; return "";
p++; /* check that we have an integer (at least one digit, nothing else) */
for (c = p; *c; c++)
if (*p == 0)
{ {
if (!isdigit((unsigned char) *c))
goto interpret_error;
}
if (c == p)
goto interpret_error;
return p;
interpret_error:
pqInternalNotice(&res->noticeHooks, pqInternalNotice(&res->noticeHooks,
"could not interpret result from server: %s", "could not interpret result from server: %s",
res->cmdStatus); res->cmdStatus);
return ""; return "";
}
return p;
} }
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment