aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_node.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2008-09-01 20:42:46 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2008-09-01 20:42:46 +0000
commitb153c0920960a6059b67969469166fb29c0105d7 (patch)
tree4e7100ecdca88746c369ae2a6a43468925f3194d /src/backend/parser/parse_node.c
parent9ac4299163247645c6e391f5f65735c6cb78ccb9 (diff)
downloadpostgresql-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.c72
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;