Обсуждение: Problem with triggers

Поиск
Список
Период
Сортировка

Problem with triggers

От
Sid
Дата:
Hi,

I am writing trigger function for validating values inserted into table. The goal is to print user friendly messages when inserted value is wrong.
When I check for null values everything works as expected:
Inside trigger I have lines:
if (new.tvalue is null) then
            RAISE EXCEPTION 'error message';
end if;
This one works ok.

But when I try to do something like that:

if length(new.tvalue) > 20 then
      RAISE EXCEPTION 'error message - too long';
end if;

then I get just information from database that given field value is to long (of course only when I try insert too long value).

In fact even if I put RAISE EXCEPTION as first line inside trigger it does not work.
All I get is ERROR: value to long......



Trigger declaration looks as follows:
CREATE TRIGGER bir_validate
  BEFORE INSERT OR UPDATE
  ON portal.documentation
  FOR EACH ROW
  EXECUTE PROCEDURE portal.dynamic_trigger_validate();

Postgres 8.4.4 on Windows 7 32bit

My question is: why do I get information about too long value before trigger fires?
Can I change this behavior?


--
Best regards
Sid

Re: Problem with triggers

От
Adrian Klaver
Дата:
On 06/15/2010 02:01 PM, Sid wrote:
> Hi,
>
> I am writing trigger function for validating values inserted into table. The
> goal is to print user friendly messages when inserted value is wrong.
> When I check for null values everything works as expected:
> Inside trigger I have lines:
> if (new.tvalue is null) then
>              RAISE EXCEPTION 'error message';
> end if;
> This one works ok.
>
> But when I try to do something like that:
>
> if length(new.tvalue)>  20 then
>        RAISE EXCEPTION 'error message - too long';
> end if;
>
> then I get just information from database that given field value is to long
> (of course only when I try insert too long value).
>
> In fact even if I put RAISE EXCEPTION as first line inside trigger it does
> not work.
> All I get is ERROR: value to long......
>
>
>
> Trigger declaration looks as follows:
> CREATE TRIGGER bir_validate
>    BEFORE INSERT OR UPDATE
>    ON portal.documentation
>    FOR EACH ROW
>    EXECUTE PROCEDURE portal.dynamic_trigger_validate();
>
> Postgres 8.4.4 on Windows 7 32bit
>
> My question is: why do I get information about too long value before trigger
> fires?
> Can I change this behavior?
>
>

The database is beating you to the validation. Basically you are trying
to override the built in validation. To make this work you will need to
let the field be longer than you want i.e varchar with no length
argument and then let your trigger handle the validations.

--
Adrian Klaver
adrian.klaver@gmail.com

Re: Problem with triggers

От
Tom Lane
Дата:
Adrian Klaver <adrian.klaver@gmail.com> writes:
> On 06/15/2010 02:01 PM, Sid wrote:
>> I am writing trigger function for validating values inserted into table. The
>> goal is to print user friendly messages when inserted value is wrong.

>> My question is: why do I get information about too long value before trigger
>> fires?

> The database is beating you to the validation.

People try this every few months :-(, but it's basically a dead-end idea.
A large majority of the things you might want to report an error for are
going to be rejected by the datatype input functions for the column
datatypes --- for example, you're not going to be able to "print a user
friendly message" on a bad timestamp, because that will be noticed long
before any trigger gets to fire.

You can either decide that the built-in error messages aren't so awful
after all, or do your data validation on the client side.

Or I guess you could lobotomize the database completely by making all
your fields be unlimited-length varchar so that there's no interesting
checking to be done.  But you really, really don't want to go there.

            regards, tom lane

Re: Problem with triggers

От
Adrian von Bidder
Дата:
Heyho!

On Wednesday 16 June 2010 00.56:14 Adrian Klaver wrote:
> > My question is: why do I get information about too long value before
> > trigger fires?
> > Can I change this behavior?

I firmly feel friendly error messages like this firmly beong into the
application and not into the DB.  Next thing you'll want translated messages
as well, and your triggers become so complex that you don't wnat to maintain
them ...

> The database is beating you to the validation.

With triggers.  A question to the experts: Couldn't this, in theory, be
implememnted within the rules system?  From what I understand they are run
right after the query is parsed; I'd expect data validation to come a bit
later.  Not sure if this is right.

cheers
-- vbi


--
Or is it?

Вложения

Re: Problem with triggers

От
Sid
Дата:


2010/6/16 Tom Lane <tgl@sss.pgh.pa.us>
Adrian Klaver <adrian.klaver@gmail.com> writes:
> On 06/15/2010 02:01 PM, Sid wrote:
>> I am writing trigger function for validating values inserted into table. The
>> goal is to print user friendly messages when inserted value is wrong.

>> My question is: why do I get information about too long value before trigger
>> fires?

> The database is beating you to the validation.

People try this every few months :-(, but it's basically a dead-end idea. 
I tried to search for this problem, but I failed :(. I spend few hours trying to find what is
wrong with my code.....

A large majority of the things you might want to report an error for are
going to be rejected by the datatype input functions for the column
datatypes --- for example, you're not going to be able to "print a user
friendly message" on a bad timestamp, because that will be noticed long
before any trigger gets to fire.
I didn't think about that, 

You can either decide that the built-in error messages aren't so awful
after all, or do your data validation on the client side.
Yes, I'll probably do this that way.
 
Or I guess you could lobotomize the database completely by making all
your fields be unlimited-length varchar so that there's no interesting
checking to be done.  But you really, really don't want to go there.
No. This solution is too ugly even for me :)
 

                       regards, tom lane

Thank you for your explanation, Tom


--
Best regards
Sid

Re: Problem with triggers

От
Sid
Дата:


2010/6/16 Adrian von Bidder <avbidder@fortytwo.ch>
Heyho!

On Wednesday 16 June 2010 00.56:14 Adrian Klaver wrote:
> > My question is: why do I get information about too long value before
> > trigger fires?
> > Can I change this behavior?

I firmly feel friendly error messages like this firmly beong into the
application and not into the DB.  Next thing you'll want translated messages
as well, and your triggers become so complex that you don't wnat to maintain
them ...

My plan was to keep as much as possible of the application logic on the database side.
Triggers were not so complex, because I used one trigger function for many tables (http://wiki.postgresql.org/wiki/PL/pgSQL_Dynamic_Triggers),so printing user friendly information about null values was just one line.

 
> The database is beating you to the validation.

With triggers.  A question to the experts: Couldn't this, in theory, be
implememnted within the rules system?  From what I understand they are run
right after the query is parsed; I'd expect data validation to come a bit
later.  Not sure if this is right.

cheers
-- vbi


--
Best regards
Sid

Re: Problem with triggers

От
Tom Lane
Дата:
Adrian von Bidder <avbidder@fortytwo.ch> writes:
> On Wednesday 16 June 2010 00.56:14 Adrian Klaver wrote:
>> The database is beating you to the validation.

> With triggers.  A question to the experts: Couldn't this, in theory, be
> implememnted within the rules system?

No, it's pretty much the same problem.  If you've got something like
    INSERT INTO foo VALUES('bar');
the literal is already going to have been fed to the appropriate input
function long before any rule would be considered.

If you're really desperate to do this type of checking on the database
side, you could consider having your app call a stored procedure instead
of trying to touch the table directly.  For example,

    CREATE FUNCTION insert_into_foo(text, text, text) ...

    SELECT insert_into_foo('bar', 'baz', ...);

The function would then try to cast its input strings to the appropriate
types, and could catch errors and replace them with its own messages.

Mind you, I remain far from convinced that you're going to improve on
the built-in error messages this way.

            regards, tom lane

Dynamic triggers

От
"Rob Richardson"
Дата:
Sid posted a link to a Wiki example of a dynamic trigger: http://wiki.postgresql.org/wiki/PL/pgSQL_Dynamic_Triggers.  The link shows a trigger, but it doesn't say anything about what its purpose is or what a dynamic trigger is supposed to be good for.  What is it good for?
 
Thank you!
 
RobR

Re: Dynamic triggers

От
Adrian Klaver
Дата:
On Wednesday 16 June 2010 5:29:39 am Rob Richardson wrote:
> Sid posted a link to a Wiki example of a dynamic trigger:
> http://wiki.postgresql.org/wiki/PL/pgSQL_Dynamic_Triggers
> <http://wiki.postgresql.org/wiki/PL/pgSQL_Dynamic_Triggers> .  The link
> shows a trigger, but it doesn't say anything about what its purpose is
> or what a dynamic trigger is supposed to be good for.  What is it good
> for?
>
> Thank you!
>
> RobR

The dynamic part is the EXECUTE statement. It allows you to build a query on the
fly. More importantly it overrides the default behavior of caching the plan the
first time a function is run in a session. See below for more detail:

http://www.postgresql.org/docs/8.4/interactive/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN
http://www.postgresql.org/docs/8.4/interactive/plpgsql-implementation.html#PLPGSQL-PLAN-CACHING

--
Adrian Klaver
adrian.klaver@gmail.com