aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/tsvector_parser.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-12-27 12:00:31 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2022-12-27 12:00:31 -0500
commit78212f21011449f0374831323655baa7c00f3680 (patch)
tree6ff1d8ba1c89999920225d8f6bfa2d8567a24d77 /src/backend/utils/adt/tsvector_parser.c
parenteb8312a22a84c33fc405ae9b497113973f552f90 (diff)
downloadpostgresql-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.c49
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)));