I thought of something I'd overlooked in my original proposal for error- handling upgrades: what about reporting where an error occurs in a PL function?
Currently, plpgsql has a hack that prints a separate WARNING giving the error location, but this is pretty darn ugly. It should be part of the error report message to begin with. I can see how to create a mechanism that gathers the data (details below if you care), but I'm not too sure how it should be reported to the client --- ie, what's the protocol message? This seems nonobvious because (a) the appropriate info might vary depending on the PL language involved, and (b) when there are several nested PL functions, we probably want to include the whole stack trace. Here is an example of what you get right now: regression=# create function foo (int, int) returns int as ' regression'# begin regression'# return $1 / $2; regression'# end' language plpgsql; CREATE FUNCTION regression=# select foo(10,0); WARNING: Error occurred while executing PL/pgSQL function foo WARNING: line 2 at return ERROR: division by zero regression=# create function bar (int, int) returns int as ' regression'# begin regression'# return foo($1,$2); regression'# end' language plpgsql; CREATE FUNCTION regression=# select bar(10,0); WARNING: Error occurred while executing PL/pgSQL function foo WARNING: line 2 at return ERROR: division by zero regression=# Note the lack of any info about bar() in the second case --- this seems like a bad omission. I am visualizing some display on the order of ERROR: division by zero WHERE: PL/pgSQL function foo, line 2 at return WHERE: PL/pgSQL function bar, line 2 at return but I'm not sure exactly how it should look, nor about the protocol-message representation. Should the 'where' entries be sent as repeated instances of a single field type? (This seems unpleasant; I'd prefer not to place any semantic significance on the ordering of fields within an error message, yet we'd certainly have to do so if we repeat a field to represent a call stack.) The alternative is to put all the call stack levels into a single field, which seems to mean multiple lines in that field, which goes against the notion that we should avoid attaching any semantic meaning to the formatting of the contents of a text field. In any case, we probably can't use any representation more specific than a text string for each entry in the call stack, because of the likelihood that the contents will vary across PLs. Any thoughts about how to handle all this? And what should we call this field, anyway? As for actually collecting the info, I'm thinking of a stack of "error context" records, say typedef struct ErrorContext { struct ErrorContext *previous; void (*callback) (void *arg); void *arg; } ErrorContext; extern ErrorContext *error_context_stack; Any given PL would push an item onto this stack at function entry, and pop it off again at function return. (No palloc is needed: the record is just a local variable in the PL handler.) If an error needs to be reported, after errstart() sets up the error parameter collection structure it traverses the error_context_stack chain and calls each callback with the specified arg (which the callback can use to access the PL's info about the current function). The callback can then use the usual optional-error-info-addition routines to add information to the error parameters, something like errfunclocation("PL/pgSQL function %s, line %d at %s", funcstate->name, funcstate->lineno, ...); We'd have to define errfunclocation to do the Right Thing when called multiple times in a single error report, but that seems easy. regards, tom lane ---------------------------(end of broadcast)--------------------------- TIP 2: you can get off all lists at once with the unregister command (send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])