diff options
author | Michael P | 2011-07-05 03:16:11 +0000 |
---|---|---|
committer | Michael P | 2011-07-06 03:40:35 +0000 |
commit | 0bbfc1e6338b5d98d6cb83fa75f2c38f527d4d4b (patch) | |
tree | 46fa412a31d08ea6e53d488ae7bc231df0b273da /contrib/spi | |
parent | 091b0e828cf0fd5bbd1f9ae58ab96fc983e55d77 (diff) | |
parent | a4bebdd92624e018108c2610fc3f2c1584b6c687 (diff) |
Merge commit 'a4bebdd92624e018108c2610fc3f2c1584b6c687' into master
This is the commit merge of Postgres-XC with the intersection of
PostgreSQL REL9_1_STABLE and master branches.
Conflicts:
COPYRIGHT
contrib/pgbench/pgbench.c
src/Makefile
src/backend/access/transam/recovery.conf.sample
src/backend/access/transam/varsup.c
src/backend/access/transam/xlog.c
src/backend/catalog/Makefile
src/backend/catalog/dependency.c
src/backend/catalog/system_views.sql
src/backend/commands/copy.c
src/backend/commands/explain.c
src/backend/commands/sequence.c
src/backend/commands/tablecmds.c
src/backend/commands/vacuum.c
src/backend/executor/nodeAgg.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/path/allpaths.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/setrefs.c
src/backend/parser/gram.y
src/backend/parser/parse_utilcmd.c
src/backend/postmaster/postmaster.c
src/backend/rewrite/rewriteHandler.c
src/backend/storage/lmgr/proc.c
src/backend/tcop/postgres.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/init/postinit.c
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/backend/utils/sort/tuplesort.c
src/bin/initdb/initdb.c
src/bin/pg_ctl/pg_ctl.c
src/bin/pg_dump/pg_dump.c
src/include/access/xlog.h
src/include/catalog/catversion.h
src/include/catalog/indexing.h
src/include/catalog/pg_aggregate.h
src/include/catalog/pg_proc.h
src/include/commands/copy.h
src/include/nodes/parsenodes.h
src/include/nodes/primnodes.h
src/include/optimizer/pathnode.h
src/include/parser/kwlist.h
src/include/storage/procarray.h
src/test/regress/expected/.gitignore
src/test/regress/expected/aggregates.out
src/test/regress/expected/alter_table.out
src/test/regress/expected/bit.out
src/test/regress/expected/box.out
src/test/regress/expected/delete.out
src/test/regress/expected/float4.out
src/test/regress/expected/float8.out
src/test/regress/expected/int2.out
src/test/regress/expected/int8.out
src/test/regress/expected/interval.out
src/test/regress/expected/numeric.out
src/test/regress/expected/point.out
src/test/regress/expected/polygon.out
src/test/regress/expected/sequence.out
src/test/regress/expected/timestamp.out
src/test/regress/expected/timestamptz.out
src/test/regress/expected/transactions.out
src/test/regress/expected/window.out
src/test/regress/input/misc.source
src/test/regress/output/create_misc_1.source
src/test/regress/output/misc.source
src/test/regress/sql/aggregates.sql
src/test/regress/sql/alter_table.sql
src/test/regress/sql/bit.sql
src/test/regress/sql/box.sql
src/test/regress/sql/delete.sql
src/test/regress/sql/domain.sql
src/test/regress/sql/float4.sql
src/test/regress/sql/float8.sql
src/test/regress/sql/int2.sql
src/test/regress/sql/int8.sql
src/test/regress/sql/interval.sql
src/test/regress/sql/lseg.sql
src/test/regress/sql/numeric.sql
src/test/regress/sql/path.sql
src/test/regress/sql/point.sql
src/test/regress/sql/polygon.sql
src/test/regress/sql/portals.sql
src/test/regress/sql/sequence.sql
src/test/regress/sql/timestamp.sql
src/test/regress/sql/timestamptz.sql
src/test/regress/sql/transactions.sql
src/test/regress/sql/window.sql
src/test/regress/sql/with.sql
Diffstat (limited to 'contrib/spi')
31 files changed, 164 insertions, 121 deletions
diff --git a/contrib/spi/Makefile b/contrib/spi/Makefile index 7a078a9b0e..0c11bfcbbd 100644 --- a/contrib/spi/Makefile +++ b/contrib/spi/Makefile @@ -1,7 +1,15 @@ -# $PostgreSQL: pgsql/contrib/spi/Makefile,v 1.29 2010/07/05 23:15:56 tgl Exp $ +# contrib/spi/Makefile MODULES = autoinc insert_username moddatetime refint timetravel -DATA_built = $(addsuffix .sql, $(MODULES)) + +EXTENSION = autoinc insert_username moddatetime refint timetravel + +DATA = autoinc--1.0.sql autoinc--unpackaged--1.0.sql \ + insert_username--1.0.sql insert_username--unpackaged--1.0.sql \ + moddatetime--1.0.sql moddatetime--unpackaged--1.0.sql \ + refint--1.0.sql refint--unpackaged--1.0.sql \ + timetravel--1.0.sql timetravel--unpackaged--1.0.sql + DOCS = $(addsuffix .example, $(MODULES)) # this is needed for the regression tests; diff --git a/contrib/spi/autoinc--1.0.sql b/contrib/spi/autoinc--1.0.sql new file mode 100644 index 0000000000..9c9df9ce0b --- /dev/null +++ b/contrib/spi/autoinc--1.0.sql @@ -0,0 +1,6 @@ +/* contrib/spi/autoinc--1.0.sql */ + +CREATE FUNCTION autoinc() +RETURNS trigger +AS 'MODULE_PATHNAME' +LANGUAGE C; diff --git a/contrib/spi/autoinc--unpackaged--1.0.sql b/contrib/spi/autoinc--unpackaged--1.0.sql new file mode 100644 index 0000000000..232e9170fc --- /dev/null +++ b/contrib/spi/autoinc--unpackaged--1.0.sql @@ -0,0 +1,3 @@ +/* contrib/spi/autoinc--unpackaged--1.0.sql */ + +ALTER EXTENSION autoinc ADD function autoinc(); diff --git a/contrib/spi/autoinc.c b/contrib/spi/autoinc.c index f79317a1b1..9b38493a33 100644 --- a/contrib/spi/autoinc.c +++ b/contrib/spi/autoinc.c @@ -1,5 +1,5 @@ /* - * $PostgreSQL: pgsql/contrib/spi/autoinc.c,v 1.17 2009/06/11 14:48:52 momjian Exp $ + * contrib/spi/autoinc.c */ #include "postgres.h" @@ -35,10 +35,10 @@ autoinc(PG_FUNCTION_ARGS) if (!CALLED_AS_TRIGGER(fcinfo)) /* internal error */ elog(ERROR, "not fired by trigger manager"); - if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event)) + if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event)) /* internal error */ - elog(ERROR, "cannot process STATEMENT events"); - if (TRIGGER_FIRED_AFTER(trigdata->tg_event)) + elog(ERROR, "must be fired for row"); + if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event)) /* internal error */ elog(ERROR, "must be fired before event"); diff --git a/contrib/spi/autoinc.control b/contrib/spi/autoinc.control new file mode 100644 index 0000000000..1d7a8e53d4 --- /dev/null +++ b/contrib/spi/autoinc.control @@ -0,0 +1,5 @@ +# autoinc extension +comment = 'functions for autoincrementing fields' +default_version = '1.0' +module_pathname = '$libdir/autoinc' +relocatable = true diff --git a/contrib/spi/autoinc.example b/contrib/spi/autoinc.example index a2f470dc2d..08880ce5fa 100644 --- a/contrib/spi/autoinc.example +++ b/contrib/spi/autoinc.example @@ -8,9 +8,9 @@ CREATE TABLE ids ( idesc text ); -CREATE TRIGGER ids_nextid +CREATE TRIGGER ids_nextid BEFORE INSERT OR UPDATE ON ids - FOR EACH ROW + FOR EACH ROW EXECUTE PROCEDURE autoinc (id, next_id); INSERT INTO ids VALUES (0, 'first (-2 ?)'); @@ -19,11 +19,11 @@ INSERT INTO ids(idesc) VALUES ('third (1 ?!)'); SELECT * FROM ids; -UPDATE ids SET id = null, idesc = 'first: -2 --> 2' +UPDATE ids SET id = null, idesc = 'first: -2 --> 2' WHERE idesc = 'first (-2 ?)'; -UPDATE ids SET id = 0, idesc = 'second: -1 --> 3' +UPDATE ids SET id = 0, idesc = 'second: -1 --> 3' WHERE id = -1; -UPDATE ids SET id = 4, idesc = 'third: 1 --> 4' +UPDATE ids SET id = 4, idesc = 'third: 1 --> 4' WHERE id = 1; SELECT * FROM ids; diff --git a/contrib/spi/autoinc.sql.in b/contrib/spi/autoinc.sql.in deleted file mode 100644 index 5daed21140..0000000000 --- a/contrib/spi/autoinc.sql.in +++ /dev/null @@ -1,9 +0,0 @@ -/* $PostgreSQL: pgsql/contrib/spi/autoinc.sql.in,v 1.7 2007/11/13 04:24:28 momjian Exp $ */ - --- Adjust this setting to control where the objects get created. -SET search_path = public; - -CREATE OR REPLACE FUNCTION autoinc() -RETURNS trigger -AS 'MODULE_PATHNAME' -LANGUAGE C; diff --git a/contrib/spi/insert_username--1.0.sql b/contrib/spi/insert_username--1.0.sql new file mode 100644 index 0000000000..bd854587e0 --- /dev/null +++ b/contrib/spi/insert_username--1.0.sql @@ -0,0 +1,6 @@ +/* contrib/spi/insert_username--1.0.sql */ + +CREATE FUNCTION insert_username() +RETURNS trigger +AS 'MODULE_PATHNAME' +LANGUAGE C; diff --git a/contrib/spi/insert_username--unpackaged--1.0.sql b/contrib/spi/insert_username--unpackaged--1.0.sql new file mode 100644 index 0000000000..f53cb690f1 --- /dev/null +++ b/contrib/spi/insert_username--unpackaged--1.0.sql @@ -0,0 +1,3 @@ +/* contrib/spi/insert_username--unpackaged--1.0.sql */ + +ALTER EXTENSION insert_username ADD function insert_username(); diff --git a/contrib/spi/insert_username.c b/contrib/spi/insert_username.c index 377284a613..18a13344cf 100644 --- a/contrib/spi/insert_username.c +++ b/contrib/spi/insert_username.c @@ -1,7 +1,7 @@ /* * insert_username.c * $Modified: Thu Oct 16 08:13:42 1997 by brook $ - * $PostgreSQL: pgsql/contrib/spi/insert_username.c,v 1.17 2009/01/07 13:44:36 tgl Exp $ + * contrib/spi/insert_username.c * * insert user name in response to a trigger * usage: insert_username (column_name) @@ -38,10 +38,10 @@ insert_username(PG_FUNCTION_ARGS) if (!CALLED_AS_TRIGGER(fcinfo)) /* internal error */ elog(ERROR, "insert_username: not fired by trigger manager"); - if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event)) + if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event)) /* internal error */ - elog(ERROR, "insert_username: cannot process STATEMENT events"); - if (TRIGGER_FIRED_AFTER(trigdata->tg_event)) + elog(ERROR, "insert_username: must be fired for row"); + if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event)) /* internal error */ elog(ERROR, "insert_username: must be fired before event"); diff --git a/contrib/spi/insert_username.control b/contrib/spi/insert_username.control new file mode 100644 index 0000000000..9d110643ee --- /dev/null +++ b/contrib/spi/insert_username.control @@ -0,0 +1,5 @@ +# insert_username extension +comment = 'functions for tracking who changed a table' +default_version = '1.0' +module_pathname = '$libdir/insert_username' +relocatable = true diff --git a/contrib/spi/insert_username.example b/contrib/spi/insert_username.example index 41e69bcbf2..2c1eeb0e0d 100644 --- a/contrib/spi/insert_username.example +++ b/contrib/spi/insert_username.example @@ -7,7 +7,7 @@ CREATE TABLE username_test ( CREATE TRIGGER insert_usernames BEFORE INSERT OR UPDATE ON username_test - FOR EACH ROW + FOR EACH ROW EXECUTE PROCEDURE insert_username (username); INSERT INTO username_test VALUES ('nothing'); @@ -18,4 +18,3 @@ INSERT INTO username_test VALUES ('tab', ' '); INSERT INTO username_test VALUES ('name', 'name'); SELECT * FROM username_test; - diff --git a/contrib/spi/insert_username.sql.in b/contrib/spi/insert_username.sql.in deleted file mode 100644 index 4d73d9b546..0000000000 --- a/contrib/spi/insert_username.sql.in +++ /dev/null @@ -1,9 +0,0 @@ -/* $PostgreSQL: pgsql/contrib/spi/insert_username.sql.in,v 1.7 2007/11/13 04:24:28 momjian Exp $ */ - --- Adjust this setting to control where the objects get created. -SET search_path = public; - -CREATE OR REPLACE FUNCTION insert_username() -RETURNS trigger -AS 'MODULE_PATHNAME' -LANGUAGE C; diff --git a/contrib/spi/moddatetime--1.0.sql b/contrib/spi/moddatetime--1.0.sql new file mode 100644 index 0000000000..97cc63289f --- /dev/null +++ b/contrib/spi/moddatetime--1.0.sql @@ -0,0 +1,6 @@ +/* contrib/spi/moddatetime--1.0.sql */ + +CREATE FUNCTION moddatetime() +RETURNS trigger +AS 'MODULE_PATHNAME' +LANGUAGE C; diff --git a/contrib/spi/moddatetime--unpackaged--1.0.sql b/contrib/spi/moddatetime--unpackaged--1.0.sql new file mode 100644 index 0000000000..f3a0a96837 --- /dev/null +++ b/contrib/spi/moddatetime--unpackaged--1.0.sql @@ -0,0 +1,3 @@ +/* contrib/spi/moddatetime--unpackaged--1.0.sql */ + +ALTER EXTENSION moddatetime ADD function moddatetime(); diff --git a/contrib/spi/moddatetime.c b/contrib/spi/moddatetime.c index 0b4d3ba351..d02560c298 100644 --- a/contrib/spi/moddatetime.c +++ b/contrib/spi/moddatetime.c @@ -1,7 +1,7 @@ /* moddatetime.c -$PostgreSQL: pgsql/contrib/spi/moddatetime.c,v 1.15 2009/01/07 13:44:36 tgl Exp $ +contrib/spi/moddatetime.c What is this? It is a function to be called from a trigger for the purpose of updating @@ -32,6 +32,7 @@ moddatetime(PG_FUNCTION_ARGS) Trigger *trigger; /* to get trigger name */ int nargs; /* # of arguments */ int attnum; /* positional number of field to change */ + Oid atttypid; /* type OID of field to change */ Datum newdt; /* The current datetime. */ char **args; /* arguments */ char *relname; /* triggered relation name */ @@ -43,17 +44,17 @@ moddatetime(PG_FUNCTION_ARGS) /* internal error */ elog(ERROR, "moddatetime: not fired by trigger manager"); - if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event)) + if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event)) /* internal error */ - elog(ERROR, "moddatetime: cannot process STATEMENT events"); + elog(ERROR, "moddatetime: must be fired for row"); - if (TRIGGER_FIRED_AFTER(trigdata->tg_event)) + if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event)) /* internal error */ elog(ERROR, "moddatetime: must be fired before event"); if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event)) /* internal error */ - elog(ERROR, "moddatetime: must be fired before event"); + elog(ERROR, "moddatetime: cannot process INSERT events"); else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) rettuple = trigdata->tg_newtuple; else @@ -75,12 +76,6 @@ moddatetime(PG_FUNCTION_ARGS) /* must be the field layout? */ tupdesc = rel->rd_att; - /* Get the current datetime. */ - newdt = DirectFunctionCall3(timestamp_in, - CStringGetDatum("now"), - ObjectIdGetDatum(InvalidOid), - Int32GetDatum(-1)); - /* * This gets the position in the tuple of the field we want. args[0] being * the name of the field to update, as passed in from the trigger. @@ -88,8 +83,8 @@ moddatetime(PG_FUNCTION_ARGS) attnum = SPI_fnumber(tupdesc, args[0]); /* - * This is were we check to see if the field we are supposed to update - * even exits. The above function must return -1 if name not found? + * This is where we check to see if the field we are supposed to update + * even exists. The above function must return -1 if name not found? */ if (attnum < 0) ereport(ERROR, @@ -98,20 +93,33 @@ moddatetime(PG_FUNCTION_ARGS) relname, args[0]))); /* - * OK, this is where we make sure the timestamp field that we are - * modifying is really a timestamp field. Hay, error checking, what a - * novel idea !-) + * Check the target field has an allowed type, and get the current + * datetime as a value of that type. */ - if (SPI_gettypeid(tupdesc, attnum) != TIMESTAMPOID) + atttypid = SPI_gettypeid(tupdesc, attnum); + if (atttypid == TIMESTAMPOID) + newdt = DirectFunctionCall3(timestamp_in, + CStringGetDatum("now"), + ObjectIdGetDatum(InvalidOid), + Int32GetDatum(-1)); + else if (atttypid == TIMESTAMPTZOID) + newdt = DirectFunctionCall3(timestamptz_in, + CStringGetDatum("now"), + ObjectIdGetDatum(InvalidOid), + Int32GetDatum(-1)); + else + { ereport(ERROR, (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION), - errmsg("attribute \"%s\" of \"%s\" must be type TIMESTAMP", + errmsg("attribute \"%s\" of \"%s\" must be type TIMESTAMP or TIMESTAMPTZ", args[0], relname))); + newdt = (Datum) 0; /* keep compiler quiet */ + } /* 1 is the number of items in the arrays attnum and newdt. attnum is the positional number of the field to be updated. newdt is the new datetime stamp. - NOTE that attnum and newdt are not arrays, but then a 1 ellement array + NOTE that attnum and newdt are not arrays, but then a 1 element array is not an array any more then they are. Thus, they can be considered a one element array. */ diff --git a/contrib/spi/moddatetime.control b/contrib/spi/moddatetime.control new file mode 100644 index 0000000000..93dfac589a --- /dev/null +++ b/contrib/spi/moddatetime.control @@ -0,0 +1,5 @@ +# moddatetime extension +comment = 'functions for tracking last modification time' +default_version = '1.0' +module_pathname = '$libdir/moddatetime' +relocatable = true diff --git a/contrib/spi/moddatetime.example b/contrib/spi/moddatetime.example index e4a713c12a..65af388214 100644 --- a/contrib/spi/moddatetime.example +++ b/contrib/spi/moddatetime.example @@ -8,7 +8,7 @@ CREATE TABLE mdt ( CREATE TRIGGER mdt_moddatetime BEFORE UPDATE ON mdt - FOR EACH ROW + FOR EACH ROW EXECUTE PROCEDURE moddatetime (moddate); INSERT INTO mdt VALUES (1, 'first'); diff --git a/contrib/spi/moddatetime.sql.in b/contrib/spi/moddatetime.sql.in deleted file mode 100644 index 793c703ac0..0000000000 --- a/contrib/spi/moddatetime.sql.in +++ /dev/null @@ -1,9 +0,0 @@ -/* $PostgreSQL: pgsql/contrib/spi/moddatetime.sql.in,v 1.7 2007/11/13 04:24:28 momjian Exp $ */ - --- Adjust this setting to control where the objects get created. -SET search_path = public; - -CREATE OR REPLACE FUNCTION moddatetime() -RETURNS trigger -AS 'MODULE_PATHNAME' -LANGUAGE C; diff --git a/contrib/spi/refint--1.0.sql b/contrib/spi/refint--1.0.sql new file mode 100644 index 0000000000..9e5d931df5 --- /dev/null +++ b/contrib/spi/refint--1.0.sql @@ -0,0 +1,11 @@ +/* contrib/spi/refint--1.0.sql */ + +CREATE FUNCTION check_primary_key() +RETURNS trigger +AS 'MODULE_PATHNAME' +LANGUAGE C; + +CREATE FUNCTION check_foreign_key() +RETURNS trigger +AS 'MODULE_PATHNAME' +LANGUAGE C; diff --git a/contrib/spi/refint--unpackaged--1.0.sql b/contrib/spi/refint--unpackaged--1.0.sql new file mode 100644 index 0000000000..54fece055a --- /dev/null +++ b/contrib/spi/refint--unpackaged--1.0.sql @@ -0,0 +1,4 @@ +/* contrib/spi/refint--unpackaged--1.0.sql */ + +ALTER EXTENSION refint ADD function check_primary_key(); +ALTER EXTENSION refint ADD function check_foreign_key(); diff --git a/contrib/spi/refint.c b/contrib/spi/refint.c index 5a446c3709..36f9ee421e 100644 --- a/contrib/spi/refint.c +++ b/contrib/spi/refint.c @@ -1,5 +1,5 @@ /* - * $PostgreSQL: pgsql/contrib/spi/refint.c,v 1.35 2009/06/11 14:48:52 momjian Exp $ + * contrib/spi/refint.c * * * refint.c -- set of functions to define referential integrity @@ -79,9 +79,9 @@ check_primary_key(PG_FUNCTION_ARGS) elog(ERROR, "check_primary_key: not fired by trigger manager"); /* Should be called for ROW trigger */ - if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event)) + if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event)) /* internal error */ - elog(ERROR, "check_primary_key: cannot process STATEMENT events"); + elog(ERROR, "check_primary_key: must be fired for row"); /* If INSERTion then must check Tuple to being inserted */ if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event)) @@ -279,9 +279,9 @@ check_foreign_key(PG_FUNCTION_ARGS) elog(ERROR, "check_foreign_key: not fired by trigger manager"); /* Should be called for ROW trigger */ - if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event)) + if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event)) /* internal error */ - elog(ERROR, "check_foreign_key: cannot process STATEMENT events"); + elog(ERROR, "check_foreign_key: must be fired for row"); /* Not should be called for INSERT */ if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event)) diff --git a/contrib/spi/refint.control b/contrib/spi/refint.control new file mode 100644 index 0000000000..cbede45784 --- /dev/null +++ b/contrib/spi/refint.control @@ -0,0 +1,5 @@ +# refint extension +comment = 'functions for implementing referential integrity (obsolete)' +default_version = '1.0' +module_pathname = '$libdir/refint' +relocatable = true diff --git a/contrib/spi/refint.example b/contrib/spi/refint.example index 1300e81654..d0ff744164 100644 --- a/contrib/spi/refint.example +++ b/contrib/spi/refint.example @@ -20,11 +20,11 @@ CREATE INDEX CI ON C (REFC); --Trigger for table A: CREATE TRIGGER AT BEFORE DELETE OR UPDATE ON A FOR EACH ROW -EXECUTE PROCEDURE +EXECUTE PROCEDURE check_foreign_key (2, 'cascade', 'ID', 'B', 'REFB', 'C', 'REFC'); /* 2 - means that check must be performed for foreign keys of 2 tables. -cascade - defines that corresponding keys must be deleted. +cascade - defines that corresponding keys must be deleted. ID - name of primary key column in triggered table (A). You may use as many columns as you need. B - name of (first) table with foreign keys. @@ -38,11 +38,11 @@ REFC - name of foreign key column in this table. --Trigger for table B: CREATE TRIGGER BT BEFORE INSERT OR UPDATE ON B FOR EACH ROW -EXECUTE PROCEDURE +EXECUTE PROCEDURE check_primary_key ('REFB', 'A', 'ID'); /* -REFB - name of foreign key column in triggered (B) table. You may use as +REFB - name of foreign key column in triggered (B) table. You may use as many columns as you need, but number of key columns in referenced table must be the same. A - referenced table name. @@ -52,7 +52,7 @@ ID - name of primary key column in referenced table. --Trigger for table C: CREATE TRIGGER CT BEFORE INSERT OR UPDATE ON C FOR EACH ROW -EXECUTE PROCEDURE +EXECUTE PROCEDURE check_primary_key ('REFC', 'A', 'ID'); -- Now try diff --git a/contrib/spi/refint.sql.in b/contrib/spi/refint.sql.in deleted file mode 100644 index 08ee7f98cf..0000000000 --- a/contrib/spi/refint.sql.in +++ /dev/null @@ -1,14 +0,0 @@ -/* $PostgreSQL: pgsql/contrib/spi/refint.sql.in,v 1.7 2007/11/13 04:24:28 momjian Exp $ */ - --- Adjust this setting to control where the objects get created. -SET search_path = public; - -CREATE OR REPLACE FUNCTION check_primary_key() -RETURNS trigger -AS 'MODULE_PATHNAME' -LANGUAGE C; - -CREATE OR REPLACE FUNCTION check_foreign_key() -RETURNS trigger -AS 'MODULE_PATHNAME' -LANGUAGE C; diff --git a/contrib/spi/timetravel--1.0.sql b/contrib/spi/timetravel--1.0.sql new file mode 100644 index 0000000000..b68cf2f247 --- /dev/null +++ b/contrib/spi/timetravel--1.0.sql @@ -0,0 +1,16 @@ +/* contrib/spi/timetravel--1.0.sql */ + +CREATE FUNCTION timetravel() +RETURNS trigger +AS 'MODULE_PATHNAME' +LANGUAGE C; + +CREATE FUNCTION set_timetravel(name, int4) +RETURNS int4 +AS 'MODULE_PATHNAME' +LANGUAGE C RETURNS NULL ON NULL INPUT; + +CREATE FUNCTION get_timetravel(name) +RETURNS int4 +AS 'MODULE_PATHNAME' +LANGUAGE C RETURNS NULL ON NULL INPUT; diff --git a/contrib/spi/timetravel--unpackaged--1.0.sql b/contrib/spi/timetravel--unpackaged--1.0.sql new file mode 100644 index 0000000000..e3716afe95 --- /dev/null +++ b/contrib/spi/timetravel--unpackaged--1.0.sql @@ -0,0 +1,5 @@ +/* contrib/spi/timetravel--unpackaged--1.0.sql */ + +ALTER EXTENSION timetravel ADD function timetravel(); +ALTER EXTENSION timetravel ADD function set_timetravel(name,integer); +ALTER EXTENSION timetravel ADD function get_timetravel(name); diff --git a/contrib/spi/timetravel.c b/contrib/spi/timetravel.c index 577767d81f..3d05cc505c 100644 --- a/contrib/spi/timetravel.c +++ b/contrib/spi/timetravel.c @@ -1,11 +1,11 @@ /* - * $PostgreSQL: pgsql/contrib/spi/timetravel.c,v 1.31 2009/06/11 14:48:52 momjian Exp $ + * contrib/spi/timetravel.c * * * timetravel.c -- function to get time travel feature * using general triggers. * - * Modified by BÖJTHE Zoltán, Hungary, mailto:urdesobt@axelero.hu + * Modified by BÖJTHE Zoltán, Hungary, mailto:urdesobt@axelero.hu */ #include "postgres.h" @@ -118,11 +118,11 @@ timetravel(PG_FUNCTION_ARGS) elog(ERROR, "timetravel: not fired by trigger manager"); /* Should be called for ROW trigger */ - if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event)) - elog(ERROR, "timetravel: cannot process STATEMENT events"); + if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event)) + elog(ERROR, "timetravel: must be fired for row"); /* Should be called BEFORE */ - if (TRIGGER_FIRED_AFTER(trigdata->tg_event)) + if (!TRIGGER_FIRED_BEFORE(trigdata->tg_event)) elog(ERROR, "timetravel: must be fired before event"); /* INSERT ? */ diff --git a/contrib/spi/timetravel.control b/contrib/spi/timetravel.control new file mode 100644 index 0000000000..9b4bb6ba04 --- /dev/null +++ b/contrib/spi/timetravel.control @@ -0,0 +1,5 @@ +# timetravel extension +comment = 'functions for implementing time travel' +default_version = '1.0' +module_pathname = '$libdir/timetravel' +relocatable = true diff --git a/contrib/spi/timetravel.example b/contrib/spi/timetravel.example index 1769e48154..35a7f65408 100644 --- a/contrib/spi/timetravel.example +++ b/contrib/spi/timetravel.example @@ -1,8 +1,8 @@ drop table tttest; create table tttest ( - price_id int4, - price_val int4, + price_id int4, + price_val int4, price_on abstime, price_off abstime ); @@ -12,17 +12,17 @@ alter table tttest add column q1 text; alter table tttest add column q2 int; alter table tttest drop column q1; -create trigger timetravel +create trigger timetravel before insert or delete or update on tttest - for each row - execute procedure + for each row + execute procedure timetravel (price_on, price_off); insert into tttest values (1, 1, null, null); insert into tttest(price_id, price_val) values (2, 2); insert into tttest(price_id, price_val,price_off) values (3, 3, 'infinity'); -insert into tttest(price_id, price_val,price_off) values (4, 4, +insert into tttest(price_id, price_val,price_off) values (4, 4, abstime('now'::timestamp - '100 days'::interval)); insert into tttest(price_id, price_val,price_on) values (3, 3, 'infinity'); -- duplicate key @@ -62,7 +62,7 @@ select set_timetravel('tttest', 1); -- turn TT ON! select get_timetravel('tttest'); -- check status -- we want to correct some date -update tttest set price_on = 'Jan-01-1990 00:00:01' where price_id = 5 and +update tttest set price_on = 'Jan-01-1990 00:00:01' where price_id = 5 and price_off <> 'infinity'; -- but this doesn't work @@ -71,11 +71,11 @@ select set_timetravel('tttest', 0); -- turn TT OFF! select get_timetravel('tttest'); -- check status -update tttest set price_on = '01-Jan-1990 00:00:01' where price_id = 5 and +update tttest set price_on = '01-Jan-1990 00:00:01' where price_id = 5 and price_off <> 'infinity'; select * from tttest; -- isn't it what we need ? -- get price for price_id == 5 as it was '10-Jan-1990' -select * from tttest where price_id = 5 and +select * from tttest where price_id = 5 and price_on <= '10-Jan-1990' and price_off > '10-Jan-1990'; diff --git a/contrib/spi/timetravel.sql.in b/contrib/spi/timetravel.sql.in deleted file mode 100644 index a78b1d52cf..0000000000 --- a/contrib/spi/timetravel.sql.in +++ /dev/null @@ -1,19 +0,0 @@ -/* $PostgreSQL: pgsql/contrib/spi/timetravel.sql.in,v 1.8 2007/11/13 04:24:28 momjian Exp $ */ - --- Adjust this setting to control where the objects get created. -SET search_path = public; - -CREATE OR REPLACE FUNCTION timetravel() -RETURNS trigger -AS 'MODULE_PATHNAME' -LANGUAGE C; - -CREATE OR REPLACE FUNCTION set_timetravel(name, int4) -RETURNS int4 -AS 'MODULE_PATHNAME' -LANGUAGE C RETURNS NULL ON NULL INPUT; - -CREATE OR REPLACE FUNCTION get_timetravel(name) -RETURNS int4 -AS 'MODULE_PATHNAME' -LANGUAGE C RETURNS NULL ON NULL INPUT; |