diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2008-09-01 20:42:46 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2008-09-01 20:42:46 +0000 |
commit | b153c0920960a6059b67969469166fb29c0105d7 (patch) | |
tree | 4e7100ecdca88746c369ae2a6a43468925f3194d /src/backend/parser/parse_node.c | |
parent | 9ac4299163247645c6e391f5f65735c6cb78ccb9 (diff) | |
download | postgresql-b153c0920960a6059b67969469166fb29c0105d7.tar.gz postgresql-b153c0920960a6059b67969469166fb29c0105d7.zip |
Add a bunch of new error location reports to parse-analysis error messages.
There are still some weak spots around JOIN USING and relation alias lists,
but most errors reported within backend/parser/ now have locations.
Diffstat (limited to 'src/backend/parser/parse_node.c')
-rw-r--r-- | src/backend/parser/parse_node.c | 72 |
1 files changed, 69 insertions, 3 deletions
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index 1760e492854..532dbe319dd 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.102 2008/08/28 23:09:47 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.103 2008/09/01 20:42:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,6 +29,9 @@ #include "utils/varbit.h" +static void pcb_error_callback(void *arg); + + /* * make_parsestate * Allocate and initialize a new ParseState. @@ -113,6 +116,62 @@ parser_errposition(ParseState *pstate, int location) /* + * setup_parser_errposition_callback + * Arrange for non-parser errors to report an error position + * + * Sometimes the parser calls functions that aren't part of the parser + * subsystem and can't reasonably be passed a ParseState; yet we would + * like any errors thrown in those functions to be tagged with a parse + * error location. Use this function to set up an error context stack + * entry that will accomplish that. Usage pattern: + * + * declare a local variable "ParseCallbackState pcbstate" + * ... + * setup_parser_errposition_callback(&pcbstate, pstate, location); + * call function that might throw error; + * cancel_parser_errposition_callback(&pcbstate); + */ +void +setup_parser_errposition_callback(ParseCallbackState *pcbstate, + ParseState *pstate, int location) +{ + /* Setup error traceback support for ereport() */ + pcbstate->pstate = pstate; + pcbstate->location = location; + pcbstate->errcontext.callback = pcb_error_callback; + pcbstate->errcontext.arg = (void *) pcbstate; + pcbstate->errcontext.previous = error_context_stack; + error_context_stack = &pcbstate->errcontext; +} + +/* + * Cancel a previously-set-up errposition callback. + */ +void +cancel_parser_errposition_callback(ParseCallbackState *pcbstate) +{ + /* Pop the error context stack */ + error_context_stack = pcbstate->errcontext.previous; +} + +/* + * Error context callback for inserting parser error location. + * + * Note that this will be called for *any* error occurring while the + * callback is installed. We avoid inserting an irrelevant error location + * if the error is a query cancel --- are there any other important cases? + */ +static void +pcb_error_callback(void *arg) +{ + ParseCallbackState *pcbstate = (ParseCallbackState *) arg; + + if (geterrcode() != ERRCODE_QUERY_CANCELED) + (void) parser_errposition(pcbstate->pstate, pcbstate->location); +} + + +/* * make_var * Build a Var node for an attribute identified by RTE and attrno */ @@ -344,14 +403,15 @@ transformArraySubscripts(ParseState *pstate, * too many examples that fail if we try. */ Const * -make_const(Value *value, int location) +make_const(ParseState *pstate, Value *value, int location) { + Const *con; Datum val; int64 val64; Oid typeid; int typelen; bool typebyval; - Const *con; + ParseCallbackState pcbstate; switch (nodeTag(value)) { @@ -392,10 +452,13 @@ make_const(Value *value, int location) } else { + /* arrange to report location if numeric_in() fails */ + setup_parser_errposition_callback(&pcbstate, pstate, location); val = DirectFunctionCall3(numeric_in, CStringGetDatum(strVal(value)), ObjectIdGetDatum(InvalidOid), Int32GetDatum(-1)); + cancel_parser_errposition_callback(&pcbstate); typeid = NUMERICOID; typelen = -1; /* variable len */ @@ -417,10 +480,13 @@ make_const(Value *value, int location) break; case T_BitString: + /* arrange to report location if bit_in() fails */ + setup_parser_errposition_callback(&pcbstate, pstate, location); val = DirectFunctionCall3(bit_in, CStringGetDatum(strVal(value)), ObjectIdGetDatum(InvalidOid), Int32GetDatum(-1)); + cancel_parser_errposition_callback(&pcbstate); typeid = BITOID; typelen = -1; typebyval = false; |