提交 fa09ee60 编写于 作者: T Tom Lane

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.
上级 b833c3d4
<!--
$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">
......@@ -1553,8 +1553,7 @@ NULL is returned if the column number is out of range.
<term><function>PQfnumber</function><indexterm><primary>PQfnumber</></></term>
<listitem>
<para>
Returns the column number
associated with the given column name.
Returns the column number associated with the given column name.
<synopsis>
int PQfnumber(const PGresult *res,
const char *column_name);
......@@ -1564,6 +1563,24 @@ int PQfnumber(const PGresult *res,
<para>
-1 is returned if the given name does not match any column.
</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>
</varlistentry>
......
......@@ -8,7 +8,7 @@
*
*
* 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
PQfnumber(const PGresult *res, const char *field_name)
{
int i;
char *field_case;
bool in_quotes;
char *iptr;
char *optr;
int i;
if (!res)
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 ||
field_name[0] == '\0' ||
res->attDescs == NULL)
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);
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);
*(field_case + strlen(field_case) - 1) = '\0';
char c = *iptr;
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
for (i = 0; field_case[i]; i++)
if (isupper((unsigned char) field_case[i]))
field_case[i] = tolower((unsigned char) field_case[i]);
*optr = '\0';
for (i = 0; i < res->numAttributes; i++)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册