Thread: Throw error and ErrorContext question.
Hi, Regarding the function parameter ref TODO: I am trying to catch and copy an error to be re-thrown later. I have the following questions: 1. Is the catch part in the following safe? 2. How do I re-throw the copied error when I am not in ErrorContext anymore? I cannot use ReThrowError because of Assert. 3. If I have to use something like: ereport(ERROR,mysaved_error->message ... mysaved_error->detail ...... ); then how do I FreeErrorData(mysaved_error) after calling the ereport above? First: .... MemoryContext parseMemCtx = CurrentMemoryContext; .... Then: /* Try to identify as a once-qualified column */ PG_TRY(); {node = qualifiedNameToVar(pstate, NULL, name1, name2, true, cref->location);/* status set to 0 or 1 */qualified_status= (node != NULL); } PG_CATCH(); {/* copy this error for later use */errorMemCtx = CurrentMemoryContext;MemoryContextSwitchTo(parseMemCtx);qualifiedErrData= CopyErrorData();FlushErrorState();MemoryContextSwitchTo(errorMemCtx); /* status is set to error */qualified_status = 2; } PG_END_TRY(); ------------------------------------------------ Gevik Babakhani PostgreSQL NL http://www.postgresql.nl TrueSoftware BV http://www.truesoftware.nl ------------------------------------------------
"Gevik Babakhani" <pgdev@xs4all.nl> writes: > I am trying to catch and copy an error to be re-thrown later. This is certainly not the right way to go about solving your problem. If you need to refactor some of the column lookup routines to make this patch work, then do so, but don't try to make an already-thrown error not be an error. (One good reason for that is that you don't really know what error you are catching --- it might be a report of some low-level problem such as out-of-memory, for instance.) The pattern you might want to follow is adding a noError boolean parameter to functions you want to be able to get failure returns back from. regards, tom lane
Thank you Tom. I have considered a noError boolean too. but please considered the following: step 1: call qualifiedNameToVar(noError = true), which generates an error but gets suppressed by noError parameter. step 2: process function parameter name for funct1.param1, check "funct1" == <the name of the current function>, which "funct1" is unknown/ambiguous (the name of the current function was "func" for example). In the case above I thought I somehow re-throw the error that was originally generated at step 1. Regards, Gevik. ------------------------------------------------ Gevik Babakhani PostgreSQL NL http://www.postgresql.nl TrueSoftware BV http://www.truesoftware.nl ------------------------------------------------ > -----Original Message----- > From: pgsql-hackers-owner@postgresql.org > [mailto:pgsql-hackers-owner@postgresql.org] On Behalf Of Tom Lane > Sent: Thursday, November 08, 2007 12:25 AM > To: Gevik Babakhani > Cc: pgsql-hackers@postgresql.org > Subject: Re: [HACKERS] Throw error and ErrorContext question. > > "Gevik Babakhani" <pgdev@xs4all.nl> writes: > > I am trying to catch and copy an error to be re-thrown later. > > This is certainly not the right way to go about solving your problem. > If you need to refactor some of the column lookup routines to > make this patch work, then do so, but don't try to make an > already-thrown error not be an error. (One good reason for > that is that you don't really know what error you are > catching --- it might be a report of some low-level problem > such as out-of-memory, for instance.) > > The pattern you might want to follow is adding a noError > boolean parameter to functions you want to be able to get > failure returns back from. > > regards, tom lane > > ---------------------------(end of > broadcast)--------------------------- > TIP 6: explain analyze is your friend >
"Gevik Babakhani" <pgdev@xs4all.nl> writes: > I have considered a noError boolean too. > but please considered the following: > step 1: call qualifiedNameToVar(noError = true), which generates an error > but gets suppressed by noError parameter. > step 2: process function parameter name for > funct1.param1, check "funct1" == <the name of the current function>, > which "funct1" is unknown/ambiguous (the name of the current function was > "func" for example). > In the case above I thought I somehow re-throw the error that > was originally generated at step 1. Yeah, you'd throw the same error number and message as that routine would have thrown, but matching that is not rocket science ;-). I don't see any value in trying to have only one instance of the ereport() call instead of two --- it's going to cost you *more* lines of code and *more* intellectual complexity to try to trap and re-throw the error than it will cost to just have two identical ereport() calls. Although quite frankly I don't see any need to be touching qualifiedNameToVar at all. It's already defined to return NULL if it doesn't find the name anyplace in the query, which seems to me to be what you want anyway. The only non-internal error it might raise is "ambiguous name" which is fine. That's an error condition, and the possibility that there is a function variable visible at an outer name scoping level doesn't make it not an error. The place where you need to be refactoring is probably in or around the transformWholeRowRef/ParseFuncOrColumn sequence. One thing that we need to think about is what is the priority of function-variable matching compared to implicit RTE creation. I'm inclined to think we should allow function variables to go first... regards, tom lane
Hello Tom, I have a solution by adding two parameters (skip_error and skipped_sqlerrorcode) to qualifiedNameToVar,transformWholeRowRef,addImplicitRTE,warnAutoRange. It still needs a bit of refining before I can send the patch for full review. When in context of parsing functions for refname.colname: If refname is unknown, skip_error=true makes sure the error is skipped. I use skipped_sqlerrorcode to record what went wrong in qualifiedNameToVar and transformWholeRowRef. The effect is that de default behavior, including implicit RTE is kept. For example, when parsing the function below: 1. qualifiedNameToVar skips the error for the unknown refx and sets skipped_sqlerrorcode. 2. transformWholeRowRef also skips the error for the unknown refx and sets skipped_sqlerrorcode. 3. at this point the callabck also returns with error, because refx is not the function's name (myfunc) So I think an error like "missing FROM-clause entry for table "refx" would be appropriate here In normal circumstance qualifiedNameToVar would have reported the same. create function myfunc(par1 integer) $$ select refx.par1 from tbl1 a where a.field1 = 1; $$ language sql; I am working on all possible test scenarios I can think of to be sure the implementations is working correctly. Regards, Gevik. ------------------------------------------------ Gevik Babakhani PostgreSQL NL http://www.postgresql.nl TrueSoftware BV http://www.truesoftware.nl ------------------------------------------------ > -----Original Message----- > From: Tom Lane [mailto:tgl@sss.pgh.pa.us] > Sent: Thursday, November 08, 2007 2:32 AM > To: Gevik Babakhani > Cc: pgsql-hackers@postgresql.org > Subject: Re: [HACKERS] Throw error and ErrorContext question. > > "Gevik Babakhani" <pgdev@xs4all.nl> writes: > > I have considered a noError boolean too. > > > but please considered the following: > > > step 1: call qualifiedNameToVar(noError = true), which generates an > > error but gets suppressed by noError parameter. > > > step 2: process function parameter name for funct1.param1, check > > "funct1" == <the name of the current function>, which "funct1" is > > unknown/ambiguous (the name of the current function was "func" for > > example). > > > In the case above I thought I somehow re-throw the error that was > > originally generated at step 1. > > Yeah, you'd throw the same error number and message as that > routine would have thrown, but matching that is not rocket > science ;-). > I don't see any value in trying to have only one instance of the > ereport() call instead of two --- it's going to cost you > *more* lines of code and *more* intellectual complexity to > try to trap and re-throw the error than it will cost to just > have two identical > ereport() calls. > > Although quite frankly I don't see any need to be touching > qualifiedNameToVar at all. It's already defined to return > NULL if it doesn't find the name anyplace in the query, which > seems to me to be what you want anyway. The only > non-internal error it might raise is "ambiguous name" which > is fine. That's an error condition, and the possibility that > there is a function variable visible at an outer name scoping > level doesn't make it not an error. > > The place where you need to be refactoring is probably in or > around the transformWholeRowRef/ParseFuncOrColumn sequence. > > One thing that we need to think about is what is the priority > of function-variable matching compared to implicit RTE > creation. I'm inclined to think we should allow function > variables to go first... > > regards, tom lane >