mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-24 18:55:04 +08:00
Trigger function for inserting user names.
Install compiled functions into $(LIBDIR)/contrib. (Thanks to Brook Milligan <brook@trillium.NMSU.Edu>)
This commit is contained in:
parent
962c8bd66d
commit
629e895101
@ -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:
|
||||
|
@ -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).
|
||||
|
77
contrib/spi/insert_username.c
Normal file
77
contrib/spi/insert_username.c
Normal file
@ -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);
|
||||
}
|
21
contrib/spi/insert_username.example
Normal file
21
contrib/spi/insert_username.example
Normal file
@ -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;
|
||||
|
6
contrib/spi/insert_username.source
Normal file
6
contrib/spi/insert_username.source
Normal file
@ -0,0 +1,6 @@
|
||||
DROP FUNCTION insert_username();
|
||||
|
||||
CREATE FUNCTION insert_username()
|
||||
RETURNS opaque
|
||||
AS '_OBJWD_/insert_username_DLSUFFIX_'
|
||||
LANGUAGE 'c';
|
Loading…
Reference in New Issue
Block a user