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.
This commit is contained in:
parent
502e9aefdc
commit
523adeb111
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$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);
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
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;
|
||||||
p++;
|
/* INSERT: skip oid and space */
|
||||||
/* INSERT: skip oid */
|
while (*p && *p != ' ')
|
||||||
while (*p != ' ' && *p)
|
|
||||||
p++;
|
p++;
|
||||||
|
if (*p == 0)
|
||||||
|
goto interpret_error; /* no space? */
|
||||||
|
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)
|
|
||||||
{
|
{
|
||||||
pqInternalNotice(&res->noticeHooks,
|
if (!isdigit((unsigned char) *c))
|
||||||
"could not interpret result from server: %s",
|
goto interpret_error;
|
||||||
res->cmdStatus);
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
if (c == p)
|
||||||
|
goto interpret_error;
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
|
interpret_error:
|
||||||
|
pqInternalNotice(&res->noticeHooks,
|
||||||
|
"could not interpret result from server: %s",
|
||||||
|
res->cmdStatus);
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user