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 "common.h"
|
||||||
#include "crosstabview.h"
|
#include "crosstabview.h"
|
||||||
#include "pqexpbuffer.h"
|
#include "pqexpbuffer.h"
|
||||||
|
#include "psqlscanslash.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
|
|
||||||
@ -648,39 +649,14 @@ indexOfColumn(char *arg, const PGresult *res)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool inquotes = false;
|
|
||||||
char *cp = arg;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dequote and downcase the column name. By checking for all-digits
|
* 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
|
* 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
|
* name even if it's all digits.
|
||||||
* 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.)
|
|
||||||
*/
|
*/
|
||||||
while (*cp)
|
dequote_downcase_identifier(arg, true, pset.encoding);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now look for match(es) among res' column names */
|
/* Now look for match(es) among res' column names */
|
||||||
idx = -1;
|
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 psql_scan_slash_command_end(PsqlScanState state);
|
||||||
|
|
||||||
|
extern void dequote_downcase_identifier(char *str, bool downcase, int encoding);
|
||||||
|
|
||||||
#endif /* PSQLSCANSLASH_H */
|
#endif /* PSQLSCANSLASH_H */
|
||||||
|
@ -566,42 +566,15 @@ psql_scan_slash_option(PsqlScanState state,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* If SQL identifier processing was requested, then we strip out
|
* If SQL identifier processing was requested, then we strip out
|
||||||
* excess double quotes and downcase unquoted letters.
|
* excess double quotes and optionally 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.
|
|
||||||
*/
|
*/
|
||||||
if (type == OT_SQLID || type == OT_SQLIDHACK)
|
if (type == OT_SQLID || type == OT_SQLIDHACK)
|
||||||
{
|
{
|
||||||
bool inquotes = false;
|
dequote_downcase_identifier(mybuf.data,
|
||||||
char *cp = mybuf.data;
|
(type != OT_SQLIDHACK),
|
||||||
|
state->encoding);
|
||||||
while (*cp)
|
/* update mybuf.len for possible shortening */
|
||||||
{
|
mybuf.len = strlen(mybuf.data);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case xslashquote:
|
case xslashquote:
|
||||||
@ -667,6 +640,51 @@ psql_scan_slash_command_end(PsqlScanState state)
|
|||||||
psql_scan_reselect_sql_lexer(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.
|
* Evaluate a backticked substring of a slash command's argument.
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user