mirror of
https://github.com/postgres/postgres.git
synced 2025-06-30 21:42:05 +03:00
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
This commit is contained in:
@ -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)));
|
||||
|
Reference in New Issue
Block a user