]> granicus.if.org Git - postgresql/commitdiff
Trigger function for inserting user names.
authorVadim B. Mikheev <vadim4o@yahoo.com>
Fri, 17 Oct 1997 09:55:34 +0000 (09:55 +0000)
committerVadim B. Mikheev <vadim4o@yahoo.com>
Fri, 17 Oct 1997 09:55:34 +0000 (09:55 +0000)
Install compiled functions into $(LIBDIR)/contrib.
(Thanks to Brook Milligan <brook@trillium.NMSU.Edu>)

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';