mirror of
https://github.com/postgres/postgres.git
synced 2025-05-25 00:04:05 -04:00
Avoid code duplication in \crosstabview.
In commit 6f0d6a507 I added a duplicate copy of psqlscanslash's identifier downcasing code, but actually it's not hard to split that out as a callable subroutine and avoid the duplication.
This commit is contained in:
parent
4039c736eb
commit
9603a32594
@ -12,6 +12,7 @@
|
||||
#include "common.h"
|
||||
#include "crosstabview.h"
|
||||
#include "pqexpbuffer.h"
|
||||
#include "psqlscanslash.h"
|
||||
#include "settings.h"
|
||||
|
||||
|
||||
@ -648,39 +649,14 @@ indexOfColumn(char *arg, const PGresult *res)
|
||||
}
|
||||
else
|
||||
{
|
||||
bool inquotes = false;
|
||||
char *cp = arg;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Dequote and downcase the column name. By checking for all-digits
|
||||
* before doing this, we can ensure that a quoted name is treated as a
|
||||
* name even if it's all digits. This transformation should match
|
||||
* what psqlscanslash.l does in OT_SQLID mode. (XXX ideally we would
|
||||
* let the lexer do this, but then we couldn't tell if the name was
|
||||
* quoted.)
|
||||
* name even if it's all digits.
|
||||
*/
|
||||
while (*cp)
|
||||
{
|
||||
if (*cp == '"')
|
||||
{
|
||||
if (inquotes && cp[1] == '"')
|
||||
{
|
||||
/* Keep the first quote, remove the second */
|
||||
cp++;
|
||||
}
|
||||
inquotes = !inquotes;
|
||||
/* Collapse out quote at *cp */
|
||||
memmove(cp, cp + 1, strlen(cp));
|
||||
/* do not advance cp */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!inquotes)
|
||||
*cp = pg_tolower((unsigned char) *cp);
|
||||
cp += PQmblen(cp, pset.encoding);
|
||||
}
|
||||
}
|
||||
dequote_downcase_identifier(arg, true, pset.encoding);
|
||||
|
||||
/* Now look for match(es) among res' column names */
|
||||
idx = -1;
|
||||
|
@ -32,4 +32,6 @@ extern char *psql_scan_slash_option(PsqlScanState state,
|
||||
|
||||
extern void psql_scan_slash_command_end(PsqlScanState state);
|
||||
|
||||
extern void dequote_downcase_identifier(char *str, bool downcase, int encoding);
|
||||
|
||||
#endif /* PSQLSCANSLASH_H */
|
||||
|
@ -566,42 +566,15 @@ psql_scan_slash_option(PsqlScanState state,
|
||||
|
||||
/*
|
||||
* If SQL identifier processing was requested, then we strip out
|
||||
* excess double quotes and downcase unquoted letters.
|
||||
* Doubled double-quotes become output double-quotes, per spec.
|
||||
*
|
||||
* Note that a string like FOO"BAR"BAZ will be converted to
|
||||
* fooBARbaz; this is somewhat inconsistent with the SQL spec,
|
||||
* which would have us parse it as several identifiers. But
|
||||
* for psql's purposes, we want a string like "foo"."bar" to
|
||||
* be treated as one option, so there's little choice.
|
||||
* excess double quotes and optionally downcase unquoted letters.
|
||||
*/
|
||||
if (type == OT_SQLID || type == OT_SQLIDHACK)
|
||||
{
|
||||
bool inquotes = false;
|
||||
char *cp = mybuf.data;
|
||||
|
||||
while (*cp)
|
||||
{
|
||||
if (*cp == '"')
|
||||
{
|
||||
if (inquotes && cp[1] == '"')
|
||||
{
|
||||
/* Keep the first quote, remove the second */
|
||||
cp++;
|
||||
}
|
||||
inquotes = !inquotes;
|
||||
/* Collapse out quote at *cp */
|
||||
memmove(cp, cp + 1, strlen(cp));
|
||||
mybuf.len--;
|
||||
/* do not advance cp */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!inquotes && type == OT_SQLID)
|
||||
*cp = pg_tolower((unsigned char) *cp);
|
||||
cp += PQmblen(cp, state->encoding);
|
||||
}
|
||||
}
|
||||
dequote_downcase_identifier(mybuf.data,
|
||||
(type != OT_SQLIDHACK),
|
||||
state->encoding);
|
||||
/* update mybuf.len for possible shortening */
|
||||
mybuf.len = strlen(mybuf.data);
|
||||
}
|
||||
break;
|
||||
case xslashquote:
|
||||
@ -667,6 +640,51 @@ psql_scan_slash_command_end(PsqlScanState state)
|
||||
psql_scan_reselect_sql_lexer(state);
|
||||
}
|
||||
|
||||
/*
|
||||
* De-quote and optionally downcase a SQL identifier.
|
||||
*
|
||||
* The string at *str is modified in-place; it can become shorter,
|
||||
* but not longer.
|
||||
*
|
||||
* If downcase is true then non-quoted letters are folded to lower case.
|
||||
* Ideally this behavior will match the backend's downcase_identifier();
|
||||
* but note that it could differ if LC_CTYPE is different in the frontend.
|
||||
*
|
||||
* Note that a string like FOO"BAR"BAZ will be converted to fooBARbaz;
|
||||
* this is somewhat inconsistent with the SQL spec, which would have us
|
||||
* parse it as several identifiers. But for psql's purposes, we want a
|
||||
* string like "foo"."bar" to be treated as one option, so there's little
|
||||
* choice; this routine doesn't get to change the token boundaries.
|
||||
*/
|
||||
void
|
||||
dequote_downcase_identifier(char *str, bool downcase, int encoding)
|
||||
{
|
||||
bool inquotes = false;
|
||||
char *cp = str;
|
||||
|
||||
while (*cp)
|
||||
{
|
||||
if (*cp == '"')
|
||||
{
|
||||
if (inquotes && cp[1] == '"')
|
||||
{
|
||||
/* Keep the first quote, remove the second */
|
||||
cp++;
|
||||
}
|
||||
inquotes = !inquotes;
|
||||
/* Collapse out quote at *cp */
|
||||
memmove(cp, cp + 1, strlen(cp));
|
||||
/* do not advance cp */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (downcase && !inquotes)
|
||||
*cp = pg_tolower((unsigned char) *cp);
|
||||
cp += PQmblen(cp, encoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate a backticked substring of a slash command's argument.
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user