diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2022-12-27 12:00:31 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2022-12-27 12:00:31 -0500 |
commit | 78212f21011449f0374831323655baa7c00f3680 (patch) | |
tree | 6ff1d8ba1c89999920225d8f6bfa2d8567a24d77 /src/backend/utils/adt/tsvector_parser.c | |
parent | eb8312a22a84c33fc405ae9b497113973f552f90 (diff) | |
download | postgresql-78212f21011449f0374831323655baa7c00f3680.tar.gz postgresql-78212f21011449f0374831323655baa7c00f3680.zip |
Convert tsqueryin and tsvectorin to report errors softly.
This is slightly tedious because the adjustments cascade through
a couple of levels of subroutines, but it's not very hard.
I chose to avoid changing function signatures more than absolutely
necessary, by passing the escontext pointer in existing structs
where possible.
tsquery's nuisance NOTICEs about empty queries are suppressed in
soft-error mode, since they're not errors and we surely don't want
them to be shown to the user anyway. Maybe that whole behavior
should be reconsidered.
Discussion: https://postgr.es/m/3824377.1672076822@sss.pgh.pa.us
Diffstat (limited to 'src/backend/utils/adt/tsvector_parser.c')
-rw-r--r-- | src/backend/utils/adt/tsvector_parser.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/src/backend/utils/adt/tsvector_parser.c b/src/backend/utils/adt/tsvector_parser.c index e2460d393ab..eeea93e622a 100644 --- a/src/backend/utils/adt/tsvector_parser.c +++ b/src/backend/utils/adt/tsvector_parser.c @@ -20,9 +20,19 @@ /* * Private state of tsvector parser. Note that tsquery also uses this code to - * parse its input, hence the boolean flags. The two flags are both true or - * both false in current usage, but we keep them separate for clarity. + * parse its input, hence the boolean flags. The oprisdelim and is_tsquery + * flags are both true or both false in current usage, but we keep them + * separate for clarity. + * + * If oprisdelim is set, the following characters are treated as delimiters + * (in addition to whitespace): ! | & ( ) + * * is_tsquery affects *only* the content of error messages. + * + * is_web can be true to further modify tsquery parsing. + * + * If escontext is an ErrorSaveContext node, then soft errors can be + * captured there rather than being thrown. */ struct TSVectorParseStateData { @@ -34,16 +44,17 @@ struct TSVectorParseStateData bool oprisdelim; /* treat ! | * ( ) as delimiters? */ bool is_tsquery; /* say "tsquery" not "tsvector" in errors? */ bool is_web; /* we're in websearch_to_tsquery() */ + Node *escontext; /* for soft error reporting */ }; /* - * Initializes parser for the input string. If oprisdelim is set, the - * following characters are treated as delimiters in addition to whitespace: - * ! | & ( ) + * Initializes a parser state object for the given input string. + * A bitmask of flags (see ts_utils.h) and an error context object + * can be provided as well. */ TSVectorParseState -init_tsvector_parser(char *input, int flags) +init_tsvector_parser(char *input, int flags, Node *escontext) { TSVectorParseState state; @@ -56,12 +67,15 @@ init_tsvector_parser(char *input, int flags) state->oprisdelim = (flags & P_TSV_OPR_IS_DELIM) != 0; state->is_tsquery = (flags & P_TSV_IS_TSQUERY) != 0; state->is_web = (flags & P_TSV_IS_WEB) != 0; + state->escontext = escontext; return state; } /* * Reinitializes parser to parse 'input', instead of previous input. + * + * Note that bufstart (the string reported in errors) is not changed. */ void reset_tsvector_parser(TSVectorParseState state, char *input) @@ -122,23 +136,26 @@ do { \ #define WAITPOSDELIM 7 #define WAITCHARCMPLX 8 -#define PRSSYNTAXERROR prssyntaxerror(state) +#define PRSSYNTAXERROR return prssyntaxerror(state) -static void +static bool prssyntaxerror(TSVectorParseState state) { - ereport(ERROR, + errsave(state->escontext, (errcode(ERRCODE_SYNTAX_ERROR), state->is_tsquery ? errmsg("syntax error in tsquery: \"%s\"", state->bufstart) : errmsg("syntax error in tsvector: \"%s\"", state->bufstart))); + /* In soft error situation, return false as convenience for caller */ + return false; } /* * Get next token from string being parsed. Returns true if successful, - * false if end of input string is reached. On success, these output - * parameters are filled in: + * false if end of input string is reached or soft error. + * + * On success, these output parameters are filled in: * * *strval pointer to token * *lenval length of *strval @@ -149,7 +166,11 @@ prssyntaxerror(TSVectorParseState state) * *poslen number of elements in *pos_ptr * *endptr scan resumption point * - * Pass NULL for unwanted output parameters. + * Pass NULL for any unwanted output parameters. + * + * If state->escontext is an ErrorSaveContext, then caller must check + * SOFT_ERROR_OCCURRED() to determine whether a "false" result means + * error or normal end-of-string. */ bool gettoken_tsvector(TSVectorParseState state, @@ -195,7 +216,7 @@ gettoken_tsvector(TSVectorParseState state, else if (statecode == WAITNEXTCHAR) { if (*(state->prsbuf) == '\0') - ereport(ERROR, + ereturn(state->escontext, false, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("there is no escaped character: \"%s\"", state->bufstart))); @@ -313,7 +334,7 @@ gettoken_tsvector(TSVectorParseState state, WEP_SETPOS(pos[npos - 1], LIMITPOS(atoi(state->prsbuf))); /* we cannot get here in tsquery, so no need for 2 errmsgs */ if (WEP_GETPOS(pos[npos - 1]) == 0) - ereport(ERROR, + ereturn(state->escontext, false, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("wrong position info in tsvector: \"%s\"", state->bufstart))); |