Re: Fwd: [SQL] Start up question about triggers

2006-06-23 Thread Forums @ Existanze
 
Hello again aaron,

Im really interested in the part where you say "generic trigger" can you
give me some tips? As to how I will go about that? I had already read the
links that Richard gave, I new I could get the values like that. So right
now I will have to create a trigger for each of my tables to create the
necessary queries, or I could do it "generically" :-)

Best Regards,
Fotis

> -Original Message-
> From: [EMAIL PROTECTED] 
> [mailto:[EMAIL PROTECTED] On Behalf Of Richard 
> Broersma Jr
> Sent: 23 June 2006 08:10
> To: Aaron Bono; pgsql-sql@postgresql.org
> Subject: Re: Fwd: [SQL] Start up question about triggers
> 
> > I did some research and can't even find a way to get meta 
> data in a trigger.
> > 
> > In a trigger, is there a way to inspect OLD and NEW to see what 
> > columns are there and see what has changed?  If so, you may not be 
> > able to grab the actual query but you could create a 
> generic trigger 
> > that reconstructs a possible update/insert/delete for any 
> table in your database.
> > 
> > Does anyone know of a good place to go get information about using 
> > meta data in a stored procedure or trigger?
> 
> yes.
> See the section "User Comments" at the very bottom of Chapter 
> 33 after "Writing Trigger Functions in C".  It is odd that a 
> PL_PGSQL example is given at the end a chapter for triggers 
> written in C.
> 
> http://www.postgresql.org/docs/8.1/interactive/trigger-example.html
> 
> Also see the entire chapter 36.10 "Trigger Procedures"
> http://www.postgresql.org/docs/8.1/interactive/plpgsql-trigger.html
> 
> Hope this is what you are looking for.
> 
> Regards,
> 
> Richard Broersma Jr.
> 
> ---(end of 
> broadcast)---
> TIP 9: In versions below 8.0, the planner will ignore your desire to
>choose an index scan if your joining column's datatypes do not
>match
> 


---(end of broadcast)---
TIP 4: Have you searched our list archives?

   http://archives.postgresql.org


Re: Fwd: [SQL] Start up question about triggers

2006-06-23 Thread George Weaver

Hi Fotis,

If you end up having to create a solution for each of the 80 tables, you may 
want to check out the following (may also give you addtional ideas for what 
you're trying to achieve):


http://www.varlena.com/GeneralBits/104.php (Logging Audit Changes with 
Composite Typed Columns).


Regards,
George


- Original Message - 
From: "Forums @ Existanze" <[EMAIL PROTECTED]>

To: 
Sent: Friday, June 23, 2006 2:15 AM
Subject: Re: Fwd: [SQL] Start up question about triggers




Hello again aaron,

Im really interested in the part where you say "generic trigger" can you
give me some tips? As to how I will go about that? I had already read the
links that Richard gave, I new I could get the values like that. So right
now I will have to create a trigger for each of my tables to create the
necessary queries, or I could do it "generically" :-)

Best Regards,
Fotis


-Original Message-
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of Richard
Broersma Jr
Sent: 23 June 2006 08:10
To: Aaron Bono; pgsql-sql@postgresql.org
Subject: Re: Fwd: [SQL] Start up question about triggers

> I did some research and can't even find a way to get meta
data in a trigger.
>
> In a trigger, is there a way to inspect OLD and NEW to see what
> columns are there and see what has changed?  If so, you may not be
> able to grab the actual query but you could create a
generic trigger
> that reconstructs a possible update/insert/delete for any
table in your database.
>
> Does anyone know of a good place to go get information about using
> meta data in a stored procedure or trigger?

yes.
See the section "User Comments" at the very bottom of Chapter
33 after "Writing Trigger Functions in C".  It is odd that a
PL_PGSQL example is given at the end a chapter for triggers
written in C.

http://www.postgresql.org/docs/8.1/interactive/trigger-example.html

Also see the entire chapter 36.10 "Trigger Procedures"
http://www.postgresql.org/docs/8.1/interactive/plpgsql-trigger.html

Hope this is what you are looking for.

Regards,

Richard Broersma Jr.

---(end of
broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
   choose an index scan if your joining column's datatypes do not
   match




---(end of broadcast)---
TIP 4: Have you searched our list archives?

  http://archives.postgresql.org





---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
  subscribe-nomail command to [EMAIL PROTECTED] so that your
  message can get through to the mailing list cleanly


Re: Fwd: [SQL] Start up question about triggers

2006-06-23 Thread Richard Broersma Jr
> Im really interested in the part where you say "generic trigger" can you
> give me some tips? As to how I will go about that? I had already read the
> links that Richard gave, I new I could get the values like that. So right
> now I will have to create a trigger for each of my tables to create the
> necessary queries, or I could do it "generically" :-)

Sorry,  I guess I haven't kept up to speed with this thread.

However, from chapter 36.10
http://www.postgresql.org/docs/8.1/interactive/plpgsql-trigger.html

Notice the variables that you have to work with in a trigger function:

TG_WHEN
Data type text; a string of either BEFORE or AFTER depending on the trigger's 
definition. 

TG_RELNAME = Data type name; the name of the table that caused the trigger 
invocation. 

TG_OP = Data type text; a string of INSERT, UPDATE, or DELETE telling for which 
operation the
trigger was fired. 

NEW
Data type RECORD; variable holding the new database row for INSERT/UPDATE 
operations in row-level
triggers. This variable is NULL in statement-level triggers. 

OLD
Data type RECORD; variable holding the old database row for UPDATE/DELETE 
operations in row-level
triggers. This variable is NULL in statement-level triggers. 

Also, notice chapter 9.19
http://www.postgresql.org/docs/8.1/interactive/functions-info.html

current_user = user name of current execution context

So with this information couldn't one (from a trigger function) insert a record 
in to a history
table with the following columns?:

Then for each column of the affect table if old.tbl_col1 != new.tbl_col1 then 
add a record to the
history as follows.

TG_WHEN : TG_RELNAME : current_user : TG_OP : old.tbl_col1
TG_WHEN : TG_RELNAME : current_user : TG_OP : old.tbl_col2
TG_WHEN : TG_RELNAME : current_user : TG_OP : old.tbl_col3
TG_WHEN : TG_RELNAME : current_user : TG_OP : old.tbl_coln

is this something like what you had in mind?

Regards,

Richard Broersma Jr.

---(end of broadcast)---
TIP 6: explain analyze is your friend


Re: Fwd: [SQL] Start up question about triggers

2006-06-23 Thread Forums @ Existanze
 Hello again,

First of all thank you all for your effort in helping me solve this problem.

George's link seems like a complete auditing framework for a database, so I
will look into that, cuase it gives you a complete view of what is going on,
and I can have undo opertaions :-)

I have to say that this was not what I was looking for, but you guys helped
realized that  it is the way to go.

Richard-
Your suggestion also makes a lot of sense and thank you for your suggestion.


What I have to point out is that no matter which solution we choose, we are
going to need to have an auditing table that represents each of our tables,
which as I mentioned are around 80 at the moment :-( so that is a lot of
extra work, but what can you do!

Image this scenario, and tell me if it wouldn't be awsome!

I have "n" number of tables each of which has different number of
columns,keys constraints and so on, and I have just ONE table with three
columns:

Logger
--
Log_id SERIAL PRIMARY KEY,
User VARCHAR(100) NOT NULL,
Query text


Then there exist a TG_QUERY parameter that we could use to get the actual
query ran by a user, so if I ran the imaginary query

INSERT INTO blah VALUES(DEFAULT,one,"23-08-3000")

I could use TG_QUERY and do

//trigger code
.
INSERT INTO Logger VALUES(DEFAULT,user,TG_QUERY)
.// end of trigger

This way I would end up with a log of the query ran on any of the tables so
theoretically

SELECT * FROM Logger ORDER BY Logger_id

Would return

Logger_id   UserQuery
-   -
2   fotis   'INSERT INTO blah VALUES(DEFAULT,one,"23-08-3000")'
4   fotis   'UPDATE seconblah SET parispo='hello' WHERE
parispo_id=50'
9   fotis   'DELETE FROM blah WHERE id=30'
12  fotis   'INSERT INTO seconblah VALUES(DEFAULT,'another')'
And so on



This way I would have all the necessary queries to restore an incomplete
database with the appropiate data from some point in time to another in the
future.


The only difference between the theoretical method and the ones already
suggested is that I will still need "n" trigger function for each of the "n"
tables, but only ONE auditing table.

Would it be much nicer :-)

Once again thank you very much for all your help,
Fotis

> -Original Message-
> From: [EMAIL PROTECTED] 
> [mailto:[EMAIL PROTECTED] On Behalf Of George Weaver
> Sent: 23 June 2006 15:38
> To: Forums @ Existanze
> Cc: pgsql-sql@postgresql.org
> Subject: Re: Fwd: [SQL] Start up question about triggers
> 
> Hi Fotis,
> 
> If you end up having to create a solution for each of the 80 
> tables, you may want to check out the following (may also 
> give you addtional ideas for what you're trying to achieve):
> 
> http://www.varlena.com/GeneralBits/104.php (Logging Audit 
> Changes with Composite Typed Columns).
> 
> Regards,
> George
> 
> 
> - Original Message -
> From: "Forums @ Existanze" <[EMAIL PROTECTED]>
> To: 
> Sent: Friday, June 23, 2006 2:15 AM
> Subject: Re: Fwd: [SQL] Start up question about triggers
> 
> 
> >
> > Hello again aaron,
> >
> > Im really interested in the part where you say "generic 
> trigger" can you
> > give me some tips? As to how I will go about that? I had 
> already read the
> > links that Richard gave, I new I could get the values like 
> that. So right
> > now I will have to create a trigger for each of my tables 
> to create the
> > necessary queries, or I could do it "generically" :-)
> >
> > Best Regards,
> > Fotis
> >
> >> -Original Message-
> >> From: [EMAIL PROTECTED]
> >> [mailto:[EMAIL PROTECTED] On Behalf Of Richard
> >> Broersma Jr
> >> Sent: 23 June 2006 08:10
> >> To: Aaron Bono; pgsql-sql@postgresql.org
> >> Subject: Re: Fwd: [SQL] Start up question about triggers
> >>
> >> > I did some research and can't even find a way to get meta
> >> data in a trigger.
> >> >
> >> > In a trigger, is there a way to inspect OLD and NEW to see what
> >> > columns are there and see what has changed?  If so, you 
> may not be
> >> > able to grab the actual query but you could create a
> >> generic trigger
> >> > that reconstructs a possible update/insert/delete for any
> >> table in your database.
> >> >
> >> > Does anyone know of a good place to go get information 
> about using
> >> > meta data in a stored procedure or trigger?
> >>
> >> yes.
> >> See the section "User Comments" at the very bottom of Chapter
> >> 33 after "Writing Trigger Functions in C".  It is odd that a
> >> PL_PGSQL example is given at the end a chapter for triggers
> >> written in C.
> >>
> >> http://www.postgresql.org/docs/8.1/interactive/trigger-example.html
> >>
> >> Also see the entire chapter 36.10 "Trigger Procedures"
> >> http://www.postgresql.org/docs/8.1/interactive/plpgsql-trigger.html
> >>
> >> Hope this is what you are looking for.
> >>
> >> Regards,
> >>
> >> Richard Broersma Jr.
> >>
> >> ---(end of
> >> broadcast)---
> >> TIP 9: In versions bel

Re: Fwd: [SQL] Start up question about triggers

2006-06-23 Thread Forums @ Existanze
 Hello again,

Just a thought! Do any of you know if this is possible?

I have a table person

CREATE TABLE person(
person_id SERIAL PRIMARY KEY,
person_name VARCHAR(100) NOT NULL,
person_lastname VARCHAR(100) NOT NULL
);

And a table audit

CREATE TABLE audit(
audit_id SERIAL PRIMARY KEY,
audit_person person NOT NULL
);

As you can see in the audit table, "audit_person" is of type "person" which
is my second table.

I have managed to save the NEW object in a trigger fuction which represent a
person. 

So issuing
INSERT INTO person VALUES(DEFAULT,'name','lastname');

WILL create a row for the  audit table as such:

SELECT * FROM audit;

Returns
Id  Person
--  --
1   (1,name,lastname)



I then delete all from person and try to do this, I know it doesn't work but
is it possible?

DELETE FROM person;

INSERT INTO person SELECT (audit_person::person) FROM audit;

If the above was possible then I could theoretically just save the new
object in the audit table for all my tables!!

Any thoughts

Best Regards,
Fotis



> -Original Message-
> From: [EMAIL PROTECTED] 
> [mailto:[EMAIL PROTECTED] On Behalf Of Forums @ 
> Existanze
> Sent: 23 June 2006 18:49
> To: pgsql-sql@postgresql.org
> Subject: Re: Fwd: [SQL] Start up question about triggers
> 
>  Hello again,
> 
> First of all thank you all for your effort in helping me 
> solve this problem.
> 
> George's link seems like a complete auditing framework for a 
> database, so I will look into that, cuase it gives you a 
> complete view of what is going on, and I can have undo opertaions :-)
> 
> I have to say that this was not what I was looking for, but 
> you guys helped realized that  it is the way to go.
> 
> Richard-
> Your suggestion also makes a lot of sense and thank you for 
> your suggestion.
> 
> 
> What I have to point out is that no matter which solution we 
> choose, we are going to need to have an auditing table that 
> represents each of our tables, which as I mentioned are 
> around 80 at the moment :-( so that is a lot of extra work, 
> but what can you do!
> 
> Image this scenario, and tell me if it wouldn't be awsome!
> 
> I have "n" number of tables each of which has different 
> number of columns,keys constraints and so on, and I have just 
> ONE table with three
> columns:
> 
> Logger
> --
> Log_id SERIAL PRIMARY KEY,
> User VARCHAR(100) NOT NULL,
> Query text
> 
> 
> Then there exist a TG_QUERY parameter that we could use to 
> get the actual query ran by a user, so if I ran the imaginary query
> 
> INSERT INTO blah VALUES(DEFAULT,one,"23-08-3000")
> 
> I could use TG_QUERY and do
> 
> //trigger code
> .
> INSERT INTO Logger VALUES(DEFAULT,user,TG_QUERY) .// end 
> of trigger
> 
> This way I would end up with a log of the query ran on any of 
> the tables so theoretically
> 
> SELECT * FROM Logger ORDER BY Logger_id
> 
> Would return
> 
> Logger_id UserQuery
> - -
> 2 fotis   'INSERT INTO blah 
> VALUES(DEFAULT,one,"23-08-3000")'
> 4 fotis   'UPDATE seconblah SET parispo='hello' WHERE
> parispo_id=50'
> 9 fotis   'DELETE FROM blah WHERE id=30'
> 12fotis   'INSERT INTO seconblah 
> VALUES(DEFAULT,'another')'
> And so on
> 
> 
> 
> This way I would have all the necessary queries to restore an 
> incomplete database with the appropiate data from some point 
> in time to another in the future.
> 
> 
> The only difference between the theoretical method and the 
> ones already suggested is that I will still need "n" trigger 
> function for each of the "n"
> tables, but only ONE auditing table.
> 
> Would it be much nicer :-)
> 
> Once again thank you very much for all your help, Fotis
> 
> > -Original Message-
> > From: [EMAIL PROTECTED]
> > [mailto:[EMAIL PROTECTED] On Behalf Of George Weaver
> > Sent: 23 June 2006 15:38
> > To: Forums @ Existanze
> > Cc: pgsql-sql@postgresql.org
> > Subject: Re: Fwd: [SQL] Start up question about triggers
> > 
> > Hi Fotis,
> > 
> > If you end up having to create a solution for each of the 
> 80 tables, 
> > you may want to check out the following (may also give you 
> addtional 
> > ideas for what you're trying to achieve):
> > 
> > http://www.varlena.com/GeneralBits/104.php (Logging Audit 
> Changes with 
> > Composite Typed Columns).
> > 
> > Regards,
> > George
> > 
> > 
> > - Original Message -
> > From: "Forums @ Existanze" <[EMAIL PROTECTED]>
> > To: 
> > Sent: Friday, June 23, 2006 2:15 AM
> > Subject: Re: Fwd: [SQL] Start up question about triggers
> > 
> > 
> > >
> > > Hello again aaron,
> > >
> > > Im really interested in the part where you say "generic
> > trigger" can you
> > > give me some tips? As to how I will go about that? I had
> > already read the
> > > links that Richard gave, I new I could get the values like
> > that. So right
> > > now I will have to create a trigger for each of my tables
> > to create the
> > 

Re: Fwd: [SQL] Start up question about triggers

2006-06-23 Thread Andrew Sullivan
On Fri, Jun 23, 2006 at 06:48:49PM +0300, Forums @ Existanze wrote:
> 
> Then there exist a TG_QUERY parameter that we could use to get the actual
> query ran by a user, so if I ran the imaginary query

Which "actual query"?  By the time the trigger fires, the query might
already have been rewritten, I think.  No?  I _think_ that even
BEFORE triggers happen after the rewriter stage is called, but
someone who has more clue will be able to correct me if I'm wrong.

A

-- 
Andrew Sullivan  | [EMAIL PROTECTED]
Everything that happens in the world happens at some place.
--Jane Jacobs 

---(end of broadcast)---
TIP 3: Have you checked our extensive FAQ?

   http://www.postgresql.org/docs/faq


Re: Fwd: [SQL] Start up question about triggers

2006-06-23 Thread Tom Lane
Andrew Sullivan <[EMAIL PROTECTED]> writes:
> On Fri, Jun 23, 2006 at 06:48:49PM +0300, Forums @ Existanze wrote:
>> Then there exist a TG_QUERY parameter that we could use to get the actual
>> query ran by a user, so if I ran the imaginary query

> Which "actual query"?  By the time the trigger fires, the query might
> already have been rewritten, I think.  No?  I _think_ that even
> BEFORE triggers happen after the rewriter stage is called, but
> someone who has more clue will be able to correct me if I'm wrong.

Even if you could get hold of the user query text, it'd be a serious
mistake to imagine that it tells you everything you need to know about
the update.  Aside from rule rewrites, previous BEFORE triggers could
have changed fields that are mentioned nowhere in the query.  The only
safe way to determine what's going on is to compare the OLD and NEW
row values.

regards, tom lane

---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
   subscribe-nomail command to [EMAIL PROTECTED] so that your
   message can get through to the mailing list cleanly


Re: Fwd: [SQL] Start up question about triggers

2006-06-23 Thread Aaron Bono
This is why I was searching for good meta data.Here is a thought.  If your trigger has the OLD and NEW, is there a way to get a list of fields from OLD and NEW?  If TG_RELNAME is the name of the table, could you just ask PostgreSQL what the columns are in that table, iterate through those columns, get the values for each of these columns out of OLD and NEW and save the old/new values?
What I really cannot find is a way to _dynamically_ in the trigger ask what COLUMNS are in OLD and NEW.  If we had:table affected (TG_RELNAME?)columns that are in the tableold values for each of these columns
new values for each of these columnsThen you could store this information into two tables:modify_table   modify_table_id   modify_dt   table_namemodify_value   modify_value_id
   modify_table_id   old_value   new_valueI wish I had more experience with stored procedures - I know what I would try to do, just not if it is possible or how to implement it.Tom makes a very good point that having the actual query is not going to help in a general sense.  If someone does an insert or update which fires a trigger that does further updates and inserts or even changes values on the fly, the inserts and updates you record will NOT reveal exactly what is going on.  Keeping the values from OLD and NEW at the very end would be much more useful.
-Aaron BonoOn 6/23/06, Tom Lane <[EMAIL PROTECTED]> wrote:
Andrew Sullivan <[EMAIL PROTECTED]> writes:> On Fri, Jun 23, 2006 at 06:48:49PM +0300, Forums @ Existanze wrote:>> Then there exist a TG_QUERY parameter that we could use to get the actual
>> query ran by a user, so if I ran the imaginary query> Which "actual query"?  By the time the trigger fires, the query might> already have been rewritten, I think.  No?  I _think_ that even
> BEFORE triggers happen after the rewriter stage is called, but> someone who has more clue will be able to correct me if I'm wrong.Even if you could get hold of the user query text, it'd be a serious
mistake to imagine that it tells you everything you need to know aboutthe update.  Aside from rule rewrites, previous BEFORE triggers couldhave changed fields that are mentioned nowhere in the query.  The only
safe way to determine what's going on is to compare the OLD and NEWrow values.regards, tom lane