From 629e8951017ca853d721d31f89690be2c6d48662 Mon Sep 17 00:00:00 2001 From: "Vadim B. Mikheev" Date: Fri, 17 Oct 1997 09:55:34 +0000 Subject: [PATCH] Trigger function for inserting user names. Install compiled functions into $(LIBDIR)/contrib. (Thanks to Brook Milligan ) --- contrib/spi/Makefile | 14 ++++++- contrib/spi/README | 13 +++++++ contrib/spi/insert_username.c | 77 +++++++++++++++++++++++++++++++++++++ contrib/spi/insert_username.example | 21 ++++++++++ contrib/spi/insert_username.source | 6 +++ 5 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 contrib/spi/insert_username.c create mode 100644 contrib/spi/insert_username.example create mode 100644 contrib/spi/insert_username.source diff --git a/contrib/spi/Makefile b/contrib/spi/Makefile index 7082762992..4a0721439b 100644 --- a/contrib/spi/Makefile +++ b/contrib/spi/Makefile @@ -3,6 +3,8 @@ SRCDIR= ../../src include $(SRCDIR)/Makefile.global +CONTRIBDIR=$(LIBDIR)/contrib + CFLAGS+= $(CFLAGS_SL) -I$(SRCDIR)/include ifdef REFINT_VERBOSE @@ -10,16 +12,24 @@ CFLAGS+= -DREFINT_VERBOSE endif TARGETS= refint$(DLSUFFIX) refint.sql timetravel$(DLSUFFIX) timetravel.sql \ - autoinc$(DLSUFFIX) autoinc.sql + autoinc$(DLSUFFIX) autoinc.sql \ + insert_username$(DLSUFFIX) insert_username.sql CLEANFILES+= $(TARGETS) all:: $(TARGETS) +install:: all $(CONTRIBDIR) + $(INSTALL) -c README $(CONTRIBDIR)/README.spi + for f in *.example *.sql *$(DLSUFFIX); do $(INSTALL) -c $$f $(CONTRIBDIR)/$$f; done + +$(CONTRIBDIR): + mkdir -p $(CONTRIBDIR) + %.sql: %.source rm -f $@; \ C=`pwd`; \ - sed -e "s:_OBJWD_:$$C:g" \ + sed -e "s:_OBJWD_:$(CONTRIBDIR):g" \ -e "s:_DLSUFFIX_:$(DLSUFFIX):g" < $< > $@ clean: diff --git a/contrib/spi/README b/contrib/spi/README index 5d332cb585..dfcdf603d2 100644 --- a/contrib/spi/README +++ b/contrib/spi/README @@ -122,3 +122,16 @@ as many column/sequence pairs as you need). 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). diff --git a/contrib/spi/insert_username.c b/contrib/spi/insert_username.c new file mode 100644 index 0000000000..92889c9348 --- /dev/null +++ b/contrib/spi/insert_username.c @@ -0,0 +1,77 @@ +/* + * insert_username.c + * $Modified: Thu Oct 16 08:13:42 1997 by brook $ + * + * insert user name in response to a trigger + * usage: insert_username (column_name) + */ + +#include "executor/spi.h" /* this is what you need to work with SPI */ +#include "commands/trigger.h" /* -"- and triggers */ +#include "miscadmin.h" /* for GetPgUserName() */ + +HeapTuple insert_username (void); + +HeapTuple +insert_username () +{ + Trigger *trigger; /* to get trigger name */ + int nargs; /* # of arguments */ + Datum newval; /* new value of column */ + char **args; /* arguments */ + char *relname; /* triggered relation name */ + Relation rel; /* triggered relation */ + HeapTuple rettuple = NULL; + TupleDesc tupdesc; /* tuple description */ + int attnum; + + /* sanity checks from autoinc.c */ + if (!CurrentTriggerData) + elog(WARN, "insert_username: triggers are not initialized"); + if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event)) + elog(WARN, "insert_username: can't process STATEMENT events"); + if (TRIGGER_FIRED_AFTER(CurrentTriggerData->tg_event)) + elog(WARN, "insert_username: must be fired before event"); + + if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event)) + rettuple = CurrentTriggerData->tg_trigtuple; + else if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event)) + rettuple = CurrentTriggerData->tg_newtuple; + else + elog(WARN, "insert_username: can't process DELETE events"); + + rel = CurrentTriggerData->tg_relation; + relname = SPI_getrelname(rel); + + trigger = CurrentTriggerData->tg_trigger; + + nargs = trigger->tgnargs; + if (nargs != 1) + elog(WARN, "insert_username (%s): one argument was expected", relname); + + args = trigger->tgargs; + tupdesc = rel->rd_att; + + CurrentTriggerData = NULL; + + attnum = SPI_fnumber (tupdesc, args[0]); + + if ( attnum < 0 ) + elog(WARN, "insert_username (%s): there is no attribute %s", relname, args[0]); + if (SPI_gettypeid (tupdesc, attnum) != TEXTOID) + elog(WARN, "insert_username (%s): attribute %s must be of TEXT type", + relname, args[0]); + + /* create fields containing name */ + newval = PointerGetDatum (textin (GetPgUserName ())); + + /* construct new tuple */ + rettuple = SPI_modifytuple (rel, rettuple, 1, &attnum, &newval, NULL); + if ( rettuple == NULL ) + elog (WARN, "insert_username (%s): %d returned by SPI_modifytuple", + relname, SPI_result); + + pfree (relname); + + return (rettuple); +} diff --git a/contrib/spi/insert_username.example b/contrib/spi/insert_username.example new file mode 100644 index 0000000000..41e69bcbf2 --- /dev/null +++ b/contrib/spi/insert_username.example @@ -0,0 +1,21 @@ +DROP TABLE username_test; + +CREATE TABLE username_test ( + name text, + username text not null +); + +CREATE TRIGGER insert_usernames + BEFORE INSERT OR UPDATE ON username_test + FOR EACH ROW + EXECUTE PROCEDURE insert_username (username); + +INSERT INTO username_test VALUES ('nothing'); +INSERT INTO username_test VALUES ('null', null); +INSERT INTO username_test VALUES ('empty string', ''); +INSERT INTO username_test VALUES ('space', ' '); +INSERT INTO username_test VALUES ('tab', ' '); +INSERT INTO username_test VALUES ('name', 'name'); + +SELECT * FROM username_test; + diff --git a/contrib/spi/insert_username.source b/contrib/spi/insert_username.source new file mode 100644 index 0000000000..573d9aba0a --- /dev/null +++ b/contrib/spi/insert_username.source @@ -0,0 +1,6 @@ +DROP FUNCTION insert_username(); + +CREATE FUNCTION insert_username() + RETURNS opaque + AS '_OBJWD_/insert_username_DLSUFFIX_' + LANGUAGE 'c'; -- 2.11.0