Trigger function for inserting user names.
authorVadim B. Mikheev
Fri, 17 Oct 1997 09:55:34 +0000 (09:55 +0000)
committerVadim B. Mikheev
Fri, 17 Oct 1997 09:55:34 +0000 (09:55 +0000)
Install compiled functions into $(LIBDIR)/contrib.
(Thanks to Brook Milligan )

contrib/spi/Makefile
contrib/spi/README
contrib/spi/insert_username.c [new file with mode: 0644]
contrib/spi/insert_username.example [new file with mode: 0644]
contrib/spi/insert_username.source [new file with mode: 0644]

index 7082762992d6ffba7f0839cf19d0d16f3ec1b2c8..4a0721439b4616acfb577a637e3908e1bd2bab81 100644 (file)
@@ -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: 
index 5d332cb585d1c9209507b83bdb75b9d283e8378a..dfcdf603d2a7042ab3cdca61bd1f5e2f197aff5c 100644 (file)
@@ -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 (file)
index 0000000..92889c9
--- /dev/null
@@ -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 (file)
index 0000000..41e69bc
--- /dev/null
@@ -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 (file)
index 0000000..573d9ab
--- /dev/null
@@ -0,0 +1,6 @@
+DROP FUNCTION insert_username();
+
+CREATE FUNCTION insert_username() 
+   RETURNS opaque 
+   AS '_OBJWD_/insert_username_DLSUFFIX_'
+   LANGUAGE 'c';