postgresql/contrib/spi
Bruce Momjian 98ad3fcfaf Hi All,
I've changed the check_primary_key() function code to allow for either
the "automatic insert key rule" or "dependent insert key rule".
Previously it restricted the addtion of a child entry if the
corresponding parent entry was not there. Now if the option is
"automatic" it will add an entry in the parent too ( it will be
successful if there are no no-null fields in the parent apart from the
primary key).
The way to use it now is:
:/*
 * check_primary_key () -- check that key in tuple being
inserted/updated
 *                       references existing tuple in "primary" table.
 * Though it's called without args You have to specify referenced
 * table/keys while creating trigger:  key field names in triggered
table,
 * referenced table name, referenced key field names,type of action
[automatic|dependent]:
 * EXECUTE PROCEDURE
 * check_primary_key ('Fkey1', 'Fkey2', 'Ptable', 'Pkey1', 'Pkey2',
'[automatic|dependent]').
 */
I am attaching the new ../contrib/spi/refint.c file which will do this.
I will be glad to help in case of any problems.

- Anand.
1999-03-15 00:34:53 +00:00
..
Makefile New moddatetime contrib from Terry Mackintosh. 1998-12-12 20:20:49 +00:00
README OK, here is a diff for the README file in /usr/src/pgsql/contrib/spi/. 1998-12-14 05:13:39 +00:00
autoinc.c pgindent run before 6.3 release, with Thomas' requested changes. 1998-02-26 04:46:47 +00:00
autoinc.example General function for SERIAL/IDENTITY/AUTOINCREMENT feature. 1997-10-02 18:01:57 +00:00
autoinc.source General function for SERIAL/IDENTITY/AUTOINCREMENT feature. 1997-10-02 18:01:57 +00:00
insert_username.c pgindent run before 6.3 release, with Thomas' requested changes. 1998-02-26 04:46:47 +00:00
insert_username.example Trigger function for inserting user names. 1997-10-17 09:55:34 +00:00
insert_username.source Trigger function for inserting user names. 1997-10-17 09:55:34 +00:00
moddatetime.c New moddatetime contrib from Terry Mackintosh. 1998-12-12 20:20:49 +00:00
moddatetime.example New moddatetime contrib from Terry Mackintosh. 1998-12-12 20:20:49 +00:00
moddatetime.source New moddatetime contrib from Terry Mackintosh. 1998-12-12 20:20:49 +00:00
refint.c Hi All, 1999-03-15 00:34:53 +00:00
refint.example README for refint.c and example of using. 1997-09-12 02:41:15 +00:00
refint.source General trigger functions for referential integrity. 1997-09-11 06:51:23 +00:00
timetravel.c pgindent run before 6.3 release, with Thomas' requested changes. 1998-02-26 04:46:47 +00:00
timetravel.example General function for SERIAL/IDENTITY/AUTOINCREMENT feature. 1997-10-02 18:01:57 +00:00
timetravel.source General function for SERIAL/IDENTITY/AUTOINCREMENT feature. 1997-10-02 18:01:57 +00:00

README

Here are general trigger functions provided as workable examples
of using SPI and triggers. "General" means that functions may be
used for defining triggers for any tables but you have to specify
table/field names (as described below) while creating a trigger.

1. refint.c - functions for implementing referential integrity.

check_primary_key () is to used for foreign keys of a table.
   
   You have to create trigger (BEFORE INSERT OR UPDATE) using this 
function on a table referencing another table. You have to specify
as function arguments: triggered table column names which correspond
to foreign key, referenced table name and column names in referenced
table which correspond to primary/unique key.
   You may create as many triggers as you need - one trigger for
one reference.

check_foreign_key () is to used for primary/unique keys of a table.

   You have to create trigger (BEFORE DELETE OR UPDATE) using this
function on a table referenced by another table(s). You have to specify
as function arguments: number of references for which function has to
performe checking, action if referencing key found ('cascade' - to delete
corresponding foreign key, 'restrict' - to abort transaction if foreign keys 
exist, 'setnull' - to set foreign key referencing primary/unique key
being deleted to null), triggered table column names which correspond
to primary/unique key, referencing table name and column names corresponding
to foreign key (, ... - as many referencing tables/keys as specified
by first argument).
   Note, that NOT NULL constraint and unique index have to be defined by
youself.

   There are examples in refint.example and regression tests
(sql/triggers.sql).

   To CREATE FUNCTIONs use refint.sql (will be made by gmake from
refint.source).


2. timetravel.c - functions for implementing time travel feature.

   Old internally supported time-travel (TT) used insert/delete
transaction commit times. To get the same feature using triggers
you have to add to a table two columns of abstime type to store
date when a tuple was inserted (start_date) and changed/deleted 
(stop_date):

CREATE TABLE XXX (
	...		...
	date_on		abstime,
	date_off	abstime
	...		...
);

CREATE TRIGGER timetravel
        BEFORE INSERT OR DELETE OR UPDATE ON tttest
        FOR EACH ROW
        EXECUTE PROCEDURE
        timetravel (date_on, date_off);

   Tuples being inserted with NULLs in date_on/date_off will get current
date in date_on (name of start_date column in XXX) and INFINITY in date_off
(name of stop_date column in XXX).

   Tuples with stop_date equal INFINITY are "valid now": when trigger will
be fired for UPDATE/DELETE of a tuple with stop_date NOT equal INFINITY then
this tuple will not be changed/deleted!

   If stop_date equal INFINITY then on

UPDATE: only stop_date in tuple being updated will be changed to current
date and new tuple with new data (coming from SET ... in UPDATE) will be
inserted. Start_date in this new tuple will be setted to current date and
stop_date - to INFINITY.

DELETE: new tuple will be inserted with stop_date setted to current date
(and with the same data in other columns as in tuple being deleted).

   NOTE:
1. To get tuples "valid now" you have to add _stop_date_ = 'infinity'
   to WHERE. Internally supported TT allowed to avoid this...
   Fixed rewriting RULEs could help here...
   As work arround you may use VIEWs...
2. You can't change start/stop date columns with UPDATE! 
   Use set_timetravel (below) if you need in this.

   FUNCTIONs:

timetravel() is general trigger function.

   You have to create trigger BEFORE (!!!) INSERT OR UPDATE OR DELETE using
this function on a time-traveled table. You have to specify two arguments:
name of start_date column and name of stop_date column in triggered table.

set_timetravel() allows you turn time-travel ON/OFF for a table:

   set_timetravel('XXX', 1) will turn TT ON for table XXX (and report
old status).
   set_timetravel('XXX', 0) will turn TT OFF for table XXX (-"-).

Turning TT OFF allows you do with a table ALL what you want!

   There is example in timetravel.example.

   To CREATE FUNCTIONs use timetravel.sql (will be made by gmake from
timetravel.source).


3. autoinc.c - function for implementing AUTOINCREMENT/IDENTITY feature.

   You have to create BEFORE INSERT OR UPDATE trigger using function
autoinc(). You have to specify as function arguments: column name
(of int4 type) for which you want to get this feature and name of
SEQUENCE from which next value has to be fetched when NULL or 0
value is being inserted into column (, ... - you are able to specify
as many column/sequence pairs as you need).

   There is example in autoinc.example.

   To CREATE FUNCTION use autoinc.sql (will be made by gmake from
autoinc.source).


4. insert_username.c - function for inserting user names.

   You have to create BEFORE INSERT OR UPDATE trigger using the function
insert_username(). You have to specify as a function argument: the column
name (of text type) in which user names will be inserted.  Note that user
names will be inserted irregardless of the initial value of the field, so
that users cannot bypass this functionality by simply defining the field to
be NOT NULL.

   There is an example in insert_username.example.

   To CREATE FUNCTION use insert_username.sql (will be made by gmake from
insert_username.source).


5. moddatetime.c - function for maintaining a modification datetime stamp.

   You have to create a BEFORE UPDATE trigger using the function moddatetime().
One argument must be given, that is the name of the field that is of type 
datetime that is to be used as the modification time stamp.

   There is an example in moddatetime.example.
	
   To CREATE FUNCTION use moddatetime.sql ( will be made by gmake from 
moddatetime.source).