Thread: rewriting values with before trigger

rewriting values with before trigger

From
Robert Treat
Date:
Is there a way to use triggers to rewrite data before determining if the
data for that field is valid?

postgres=# create table foo (
postgres(# bar timestamptz
postgres(# );
CREATE
postgres=# create or replace function test() returns opaque as '
postgres'# begin
postgres'# NEW.bar := NULL;
postgres'# return NEW;
postgres'# end;
postgres'# ' language 'plpgsql';
CREATE
postgres=# create trigger baz before insert on foo for each row execute
procedure test();
CREATE
postgres=# insert into foo values (now());
INSERT 411474706 1
postgres=# select * from foo;
 bar
-----

(1 row)

postgres=# insert into foo values ('');
ERROR:  Bad timestamp external representation ''

Is there anyway to do be able to change the '' into NULL before data
validity is checked with a trigger?

(FWIW this is 7.2, if this would actually work in 7.3 please lmk)


TIA,
Robert Treat


Re: rewriting values with before trigger

From
Josh Berkus
Date:
Robert,

> Is there anyway to do be able to change the '' into NULL before data
> validity is checked with a trigger?

What about using a RULE instead?

--
Josh Berkus
Aglio Database Solutions
San Francisco


Re: [GENERAL] rewriting values with before trigger

From
Robert Treat
Date:
On Thu, 2003-04-24 at 12:39, Josh Berkus wrote:
> Robert,
>
> > Is there anyway to do be able to change the '' into NULL before data
> > validity is checked with a trigger?
>
> What about using a RULE instead?
>

RULE's follow this same behavior, erroring out if the data is not a
valid timestamp. (At least I've not been able to write a rule that
doesn't follow this) In fact you actually can't create the rule if you
have a where clause that isn't a proper matching datatype.

I seem to recall a solution for folks who need '' to represent 0 in int
fields was to use triggers or rules, but I guess that really isn't
possible :-(

Robert Treat




Re: [GENERAL] rewriting values with before trigger

From
Robert Treat
Date:
On Thu, 2003-04-24 at 15:10, Dennis Gearon wrote:
> I have no idea how the transport of a value of '' happens in the parser if it's expecing a NULL/INT value, if it
wouldeven make it to the trigger stage <shrug>. 
>

:-) Thats the problem, it doesn't.

Robert Treat


Re: [GENERAL] rewriting values with before trigger

From
Robert Treat
Date:
On Thu, 2003-04-24 at 15:35, Dennis Gearon wrote:
> Well,
>     does ''::INT do anything valuable?

    not in 7.3+, and given my original problem involves timestamps, not in
7.2 either.

>     change column to a string, convert to INTS on the way out, STRINGS on the way in?
>     use an external language to make transitions.
>

yeah, I've thought of some other crazy ways to get around this, but the
problem is due to a bug in the application side. I was hoping I could
write a quick hack (like adding a rule/trigger) to get around this until
the app was fixed, but I'm not going to make my side a kludge when it
isn't one now.


Robert Treat


Re: [GENERAL] rewriting values with before trigger

From
Tom Lane
Date:
Robert Treat <xzilla@users.sourceforge.net> writes:
> yeah, I've thought of some other crazy ways to get around this, but the
> problem is due to a bug in the application side. I was hoping I could
> write a quick hack (like adding a rule/trigger) to get around this until
> the app was fixed, but I'm not going to make my side a kludge when it
> isn't one now.

The only way I can see to do it is to make a view that has 'text'
datatypes in place of real ones, with an ON INSERT rule that invokes
your conversion functions and then inserts the result to the real table.
Dunno if that's too high on your kluge meter.

            regards, tom lane


Re: [GENERAL] rewriting values with before trigger

From
Robert Treat
Date:
On Thursday 24 April 2003 08:28 pm, elein wrote:
> I don't think this is a bug at all.
> Argument creation has to come before the execution
> of the function.  That in this case the argument is a row type
> doesn't matter.  It has nothing to do with the content of the
> function and everything to do with creating the row NEW.
> How can you possibly assign a value to NEW.bar if NEW as
> a whole does not exist?
>

You misunderstood. I don't think it's a bug in postgresql,  it's a bug in the
application that is hitting against my database. When it doesn't have a value
for the timestamp field, it either needs to drop it from the insert statment
or convert it to null; not send a ''

> What are you really trying to do here?  Maybe setting the
> table column's default to NULL will achieve what you want.
>

I have an application that is inserting information into a table periodically.
Sometimes it passes in timestamps for certain fields, but sometimes it
doesn't have any timestamp information. When it doesn't have information, it
should send NULL. Unfortunatly the app writers wrote it to send ''. Default's
don't work because the app is trying to post data, it's just not a valid
datatype.  Luckily in this instance I can tell the app guys they have to fix
thier app instead of having to muck up the database.

Robert Treat


Re: [GENERAL] rewriting values with before trigger

From
Josh Berkus
Date:
Robert,

> You misunderstood. I don't think it's a bug in postgresql,  it's a bug in
the
> application that is hitting against my database. When it doesn't have a
value
> for the timestamp field, it either needs to drop it from the insert statment
> or convert it to null; not send a ''

Incidentally, this sort of problem is why most of my apps are based on "push"
data functions.    i.e., instead of the client calling:
INSERT INTO foo VALUES ( id, bar1, bar2, bar3 );
it calls
SELECT df_modify_foo ( id, bar1, bar2, bar3 );

Data-push functions allow me to do a whole array of validation and custom
error message return that would be impractical with triggers.   It also
allows me to build security checks in to the back-end, via:

SELECT df_modify_foo ( user_id, session_key, id, bar1, bar2, bar3 )

... allowing me to check all of the following things:
Does the user have a valid session?
Does the user have rights to foo?
Does the user have a lock on foo?
Is this a new foo record, or a modified one?
etc.

--
-Josh Berkus
 Aglio Database Solutions
 San Francisco


Re: [GENERAL] rewriting values with before trigger

From
elein
Date:
I don't think this is a bug at all.
Argument creation has to come before the execution
of the function.  That in this case the argument is a row type
doesn't matter.  It has nothing to do with the content of the
function and everything to do with creating the row NEW.
How can you possibly assign a value to NEW.bar if NEW as
a whole does not exist?

What are you really trying to do here?  Maybe setting the
table column's default to NULL will achieve what you want.

elein

On Thursday 24 April 2003 12:49, Robert Treat wrote:
> On Thu, 2003-04-24 at 15:35, Dennis Gearon wrote:
> > Well,
> >     does ''::INT do anything valuable?
>
>     not in 7.3+, and given my original problem involves timestamps, not in
> 7.2 either.
>
> >     change column to a string, convert to INTS on the way out, STRINGS on
> > the way in? use an external language to make transitions.
>
> yeah, I've thought of some other crazy ways to get around this, but the
> problem is due to a bug in the application side. I was hoping I could
> write a quick hack (like adding a rule/trigger) to get around this until
> the app was fixed, but I'm not going to make my side a kludge when it
> isn't one now.
>
>
> Robert Treat
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Don't 'kill -9' the postmaster

--
----------------------------------------------------------------------------------------
elein@varlena.com     Database Consulting     www.varlena.com
              I have always depended on the [QA] of strangers.


Re: [GENERAL] rewriting values with before trigger

From
"Nigel J. Andrews"
Date:
On 24 Apr 2003, Robert Treat wrote:

> Is there a way to use triggers to rewrite data before determining if the
> data for that field is valid?
>
> ...
>
> postgres=# insert into foo values ('');
> ERROR:  Bad timestamp external representation ''
>
> Is there anyway to do be able to change the '' into NULL before data
> validity is checked with a trigger?
>
> (FWIW this is 7.2, if this would actually work in 7.3 please lmk)

Just so you know 7.3 is the same. I've just been doing something similar,
i.e. wanting to get untyped values into a before trigger but then it's
eminently sensible for that to not be possible.

I hadn't really considered rules but then the process I wanted done was way to
complicated for one of those.

Fortunately the design is such that I could just move the code I would have
written in the trigger into the access function that the middle layer is
supposed to use.


--
Nigel J. Andrews


Re: [GENERAL] rewriting values with before trigger

From
Dennis Gearon
Date:
Well,
    does ''::INT do anything valuable?
    change column to a string, convert to INTS on the way out, STRINGS on the way in?
    use an external language to make transitions.

Robert Treat wrote:
> On Thu, 2003-04-24 at 15:10, Dennis Gearon wrote:
>
>>I have no idea how the transport of a value of '' happens in the parser if it's expecing a NULL/INT value, if it
wouldeven make it to the trigger stage <shrug>. 
>>
>
>
> :-) Thats the problem, it doesn't.
>
> Robert Treat
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/docs/faqs/FAQ.html
>


Re: [GENERAL] rewriting values with before trigger

From
Dennis Gearon
Date:
I **LIKE** your kind of thinking :-)

Don't mess up the data.

Don't mess up the schema.

It hurts or causes LOTS of labor later on.

Robert Treat wrote:
> On Thu, 2003-04-24 at 15:35, Dennis Gearon wrote:
>
>>Well,
>>    does ''::INT do anything valuable?
>
>
>     not in 7.3+, and given my original problem involves timestamps, not in
> 7.2 either.
>
>
>>    change column to a string, convert to INTS on the way out, STRINGS on the way in?
>>    use an external language to make transitions.
>>
>
>
> yeah, I've thought of some other crazy ways to get around this, but the
> problem is due to a bug in the application side. I was hoping I could
> write a quick hack (like adding a rule/trigger) to get around this until
> the app was fixed, but I'm not going to make my side a kludge when it
> isn't one now.
>
>
> Robert Treat
>
>
>


Re: [GENERAL] rewriting values with before trigger

From
Dennis Gearon
Date:
How about putting the data validity and conversion routine in ONE trigger?

OR, deliberately name your triggers with alphanumerical prefixes that forces them to fire in a certain order, and
makingthe trigger that does the conversion fire first? 

I have no idea how the transport of a value of '' happens in the parser if it's expecing a NULL/INT value, if it would
evenmake it to the trigger stage <shrug>. 

Robert Treat wrote:
> On Thu, 2003-04-24 at 12:39, Josh Berkus wrote:
>
>>Robert,
>>
>>
>>>Is there anyway to do be able to change the '' into NULL before data
>>>validity is checked with a trigger?
>>
>>What about using a RULE instead?
>>
>
>
> RULE's follow this same behavior, erroring out if the data is not a
> valid timestamp. (At least I've not been able to write a rule that
> doesn't follow this) In fact you actually can't create the rule if you
> have a where clause that isn't a proper matching datatype.
>
> I seem to recall a solution for folks who need '' to represent 0 in int
> fields was to use triggers or rules, but I guess that really isn't
> possible :-(
>
> Robert Treat
>
>
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/docs/faqs/FAQ.html
>


Re: [GENERAL] rewriting values with before trigger

From
elein
Date:
OK.  I understand what you mean.  I was really focussing
on the engine handling rather than the application behaviour.

elein

On Thursday 24 April 2003 21:03, Robert Treat wrote:
> On Thursday 24 April 2003 08:28 pm, elein wrote:
> > I don't think this is a bug at all.
> > Argument creation has to come before the execution
> > of the function.  That in this case the argument is a row type
> > doesn't matter.  It has nothing to do with the content of the
> > function and everything to do with creating the row NEW.
> > How can you possibly assign a value to NEW.bar if NEW as
> > a whole does not exist?
>
> You misunderstood. I don't think it's a bug in postgresql,  it's a bug in
> the application that is hitting against my database. When it doesn't have a
> value for the timestamp field, it either needs to drop it from the insert
> statment or convert it to null; not send a ''
>
> > What are you really trying to do here?  Maybe setting the
> > table column's default to NULL will achieve what you want.
>
> I have an application that is inserting information into a table
> periodically. Sometimes it passes in timestamps for certain fields, but
> sometimes it doesn't have any timestamp information. When it doesn't have
> information, it should send NULL. Unfortunatly the app writers wrote it to
> send ''. Default's don't work because the app is trying to post data, it's
> just not a valid datatype.  Luckily in this instance I can tell the app
> guys they have to fix thier app instead of having to muck up the database.
>
> Robert Treat

--
----------------------------------------------------------------------------------------
elein@varlena.com     Database Consulting     www.varlena.com
              I have always depended on the [QA] of strangers.


Re: [GENERAL] rewriting values with before trigger

From
Dennis Gearon
Date:
It's a lot of work to write the functions, but it is the best way to keep the db intact.

Josh Berkus wrote:
> Robert,
>
>
>>You misunderstood. I don't think it's a bug in postgresql,  it's a bug in
>
> the
>
>>application that is hitting against my database. When it doesn't have a
>
> value
>
>>for the timestamp field, it either needs to drop it from the insert statment
>>or convert it to null; not send a ''
>
>
> Incidentally, this sort of problem is why most of my apps are based on "push"
> data functions.    i.e., instead of the client calling:
> INSERT INTO foo VALUES ( id, bar1, bar2, bar3 );
> it calls
> SELECT df_modify_foo ( id, bar1, bar2, bar3 );
>
> Data-push functions allow me to do a whole array of validation and custom
> error message return that would be impractical with triggers.   It also
> allows me to build security checks in to the back-end, via:
>
> SELECT df_modify_foo ( user_id, session_key, id, bar1, bar2, bar3 )
>
> ... allowing me to check all of the following things:
> Does the user have a valid session?
> Does the user have rights to foo?
> Does the user have a lock on foo?
> Is this a new foo record, or a modified one?
> etc.
>