Throw error and ErrorContext question.

Started by Gevik Babakhaniabout 18 years ago5 messages
#1Gevik Babakhani
pgdev@xs4all.nl

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
------------------------------------------------

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Gevik Babakhani (#1)
Re: 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

#3Gevik Babakhani
pgdev@xs4all.nl
In reply to: Tom Lane (#2)
Re: Throw error and ErrorContext question.

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
------------------------------------------------

Show quoted text

-----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

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Gevik Babakhani (#3)
Re: 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

#5Gevik Babakhani
pgdev@xs4all.nl
In reply to: Tom Lane (#4)
Re: Throw error and ErrorContext question.

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
------------------------------------------------

Show quoted text

-----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