mirror of
https://github.com/postgres/postgres.git
synced 2025-04-29 13:56:47 +03:00
Document the always-true-but-previously-undocumented fact that PQfnumber()
will downcase the supplied field name unless it is double-quoted. Also, upgrade the routine's handling of double quotes to match the backend, in particular support doubled double quotes within quoted identifiers. Per pgsql-interfaces discussion a couple weeks ago.
This commit is contained in:
parent
b833c3d4a4
commit
fa09ee6026
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.138 2003/10/03 18:26:14 tgl Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.139 2003/10/04 21:05:20 tgl Exp $
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<chapter id="libpq">
|
<chapter id="libpq">
|
||||||
@ -1553,8 +1553,7 @@ NULL is returned if the column number is out of range.
|
|||||||
<term><function>PQfnumber</function><indexterm><primary>PQfnumber</></></term>
|
<term><function>PQfnumber</function><indexterm><primary>PQfnumber</></></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Returns the column number
|
Returns the column number associated with the given column name.
|
||||||
associated with the given column name.
|
|
||||||
<synopsis>
|
<synopsis>
|
||||||
int PQfnumber(const PGresult *res,
|
int PQfnumber(const PGresult *res,
|
||||||
const char *column_name);
|
const char *column_name);
|
||||||
@ -1564,6 +1563,24 @@ int PQfnumber(const PGresult *res,
|
|||||||
<para>
|
<para>
|
||||||
-1 is returned if the given name does not match any column.
|
-1 is returned if the given name does not match any column.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The given name is treated like an identifier in an SQL command,
|
||||||
|
that is, it is downcased unless double-quoted. For example,
|
||||||
|
given a query result generated from the SQL command
|
||||||
|
<programlisting>
|
||||||
|
select 1 as FOO, 2 as "BAR";
|
||||||
|
</programlisting>
|
||||||
|
we would have the results:
|
||||||
|
<programlisting>
|
||||||
|
PQfname(res, 0) <lineannotation>foo</lineannotation>
|
||||||
|
PQfname(res, 1) <lineannotation>BAR</lineannotation>
|
||||||
|
PQfnumber(res, "FOO") <lineannotation>0</lineannotation>
|
||||||
|
PQfnumber(res, "foo") <lineannotation>0</lineannotation>
|
||||||
|
PQfnumber(res, "BAR") <lineannotation>-1</lineannotation>
|
||||||
|
PQfnumber(res, "\"BAR\"") <lineannotation>1</lineannotation>
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.150 2003/10/03 18:26:14 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.151 2003/10/04 21:05:21 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1803,32 +1803,80 @@ PQfname(const PGresult *res, int field_num)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* returns -1 on a bad field name
|
* PQfnumber: find column number given column name
|
||||||
|
*
|
||||||
|
* The column name is parsed as if it were in a SQL statement, including
|
||||||
|
* case-folding and double-quote processing. But note a possible gotcha:
|
||||||
|
* downcasing in the frontend might follow different locale rules than
|
||||||
|
* downcasing in the backend...
|
||||||
|
*
|
||||||
|
* Returns -1 if no match. In the present backend it is also possible
|
||||||
|
* to have multiple matches, in which case the first one is found.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
PQfnumber(const PGresult *res, const char *field_name)
|
PQfnumber(const PGresult *res, const char *field_name)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
char *field_case;
|
char *field_case;
|
||||||
|
bool in_quotes;
|
||||||
|
char *iptr;
|
||||||
|
char *optr;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: it is correct to reject a zero-length input string; the proper
|
||||||
|
* input to match a zero-length field name would be "".
|
||||||
|
*/
|
||||||
if (field_name == NULL ||
|
if (field_name == NULL ||
|
||||||
field_name[0] == '\0' ||
|
field_name[0] == '\0' ||
|
||||||
res->attDescs == NULL)
|
res->attDescs == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: this code will not reject partially quoted strings, eg
|
||||||
|
* foo"BAR"foo will become fooBARfoo when it probably ought to be
|
||||||
|
* an error condition.
|
||||||
|
*/
|
||||||
field_case = strdup(field_name);
|
field_case = strdup(field_name);
|
||||||
if (*field_case == '"')
|
if (field_case == NULL)
|
||||||
|
return -1; /* grotty */
|
||||||
|
|
||||||
|
in_quotes = false;
|
||||||
|
optr = field_case;
|
||||||
|
for (iptr = field_case; *iptr; iptr++)
|
||||||
{
|
{
|
||||||
strcpy(field_case, field_case + 1);
|
char c = *iptr;
|
||||||
*(field_case + strlen(field_case) - 1) = '\0';
|
|
||||||
|
if (in_quotes)
|
||||||
|
{
|
||||||
|
if (c == '"')
|
||||||
|
{
|
||||||
|
if (iptr[1] == '"')
|
||||||
|
{
|
||||||
|
/* doubled quotes become a single quote */
|
||||||
|
*optr++ = '"';
|
||||||
|
iptr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
in_quotes = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*optr++ = c;
|
||||||
|
}
|
||||||
|
else if (c == '"')
|
||||||
|
{
|
||||||
|
in_quotes = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isupper((unsigned char) c))
|
||||||
|
c = tolower((unsigned char) c);
|
||||||
|
*optr++ = c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
*optr = '\0';
|
||||||
for (i = 0; field_case[i]; i++)
|
|
||||||
if (isupper((unsigned char) field_case[i]))
|
|
||||||
field_case[i] = tolower((unsigned char) field_case[i]);
|
|
||||||
|
|
||||||
for (i = 0; i < res->numAttributes; i++)
|
for (i = 0; i < res->numAttributes; i++)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user