trigger functions and access to datatypes - Mailing list pgsql-hackers
From | Brook Milligan |
---|---|
Subject | trigger functions and access to datatypes |
Date | |
Msg-id | 199906142132.PAA20191@trillium.nmsu.edu Whole thread Raw |
List | pgsql-hackers |
I'm trying to write some trigger functions that fill in the values of some fields with functions of other fields. Everything is fine, except that I am unsure how to create Datum representations of the new fields. Presumably I need to do something like the following: Point f (int32 i, int32 j);int32 i, j;Point p;Datum d;p = f (i, j); /* ??? - how to create/access Point? */d =PointGetDatum (&p); /* ??? - how to convert to Datum? */rettuple = SPI_modifytuple (rel, rettuple, 1, attnum, &d,NULL); But I don't know how to get at the internal representations I need. In this case I need to create a Point data type. I can use the structure in geo_decls.h fine, but is that the "correct" procedure? Once I have a Point structure created, how do I convert that to a Datum (or Datum*) for an argument to SPI_modifytuple? So that I haven't missed any details, I'm including the full version of my trigger below. Thanks for your help. Cheers, Brook =========================================================================== /** plot_corners.c** trigger for keeping corners in sync with distances*/ #include "executor/spi.h" /* this is what you need to work with SPI */ #include "commands/trigger.h" /* and triggers */ #include "utils/geo_decls.h" /* this is needed for Point type */ HeapTuple plot_corners (void); /* coordinants of corners */ typedef struct _corners { Point LL; Point LR; Point UL; Point UR; } Corners; /* calculate corner positions */ static Corners calc_corners (int n_distances, const int32 * d); #define N_DISTANCES 6 static char * distance_names [N_DISTANCES] = { "d12", "d13", "d14", "d23", "d24", "d34" }; #define N_CORNERS 4 static char * corner_names [N_CORNERS] = { "ll", "lr", "ul", "ur" }; HeapTuple plot_corners () { Relation rel; /* triggered relation */ char *relname; /* triggered relation name */ TupleDesc tupdesc; /* tuple description */ HeapTuple rettuple = NULL; /* tuple to return */ int d_attnum [N_DISTANCES]; /* distance attribute numbers */ int32 d [N_DISTANCES]; /* distances between corners */ int c_attnum [N_CORNERS]; /* corner attribute numbers */ Corners corners; /* coordinants of corners */ Datum c[N_CORNERS]; /* coordinants of corners */ bool isnull; int i; if (!CurrentTriggerData) elog (ERROR, "plot_corners: triggers are not initialized"); rel = CurrentTriggerData -> tg_relation; relname = SPI_getrelname (rel); tupdesc = rel -> rd_att; if (CurrentTriggerData -> tg_trigger -> tgnargs != 0) elog (ERROR, "plot_corners (%s): no arguments were expected", relname); if (!TRIGGER_FIRED_FOR_ROW (CurrentTriggerData -> tg_event)) elog (ERROR, "plot_corners (%s): must process ROW events",relname); if (TRIGGER_FIRED_FOR_STATEMENT (CurrentTriggerData -> tg_event)) elog (ERROR, "plot_corners (%s): can'tprocess STATEMENT events", relname); if (!TRIGGER_FIRED_BEFORE (CurrentTriggerData -> tg_event)) elog (ERROR, "plot_corners (%s): must be fired before event",relname); if (TRIGGER_FIRED_AFTER (CurrentTriggerData -> tg_event)) elog (ERROR, "plot_corners (%s): can't be firedafter event", relname); 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 if (TRIGGER_FIRED_BY_DELETE(CurrentTriggerData -> tg_event)) elog (ERROR, "plot_corners (%s): can't process DELETE events",relname); else elog (ERROR, "plot_corners (%s): unknown trigger event", relname); CurrentTriggerData = NULL; for (i = 0; i < N_DISTANCES; i++) { d_attnum [i] = SPI_fnumber (tupdesc, distance_names [i]); if (d_attnum [i]< 0)elog (ERROR, "plot_corners (%s): there is no attribute %s", relname, distance_names [i]); if (SPI_gettypeid (tupdesc,d_attnum [i]) != INT4OID)elog (ERROR, "plot_corners (%s): attribute %s must be of INT4 type", relname, distance_names[i]); d [i] = DatumGetInt32 (SPI_getbinval (rettuple, tupdesc, d_attnum [i], &isnull)); if (isnull)elog(ERROR, "plot_corners (%s): attribute %s must not be NULL", relname, distance_names [i]); } for (i = 0; i < N_CORNERS; i++) { c_attnum [i] = SPI_fnumber (tupdesc, corner_names [i]); if (c_attnum [i] < 0)elog(ERROR, "plot_corners (%s): there is no attribute %s", relname, corner_names [i]); if (SPI_gettypeid (tupdesc,c_attnum [i]) != POINTOID)elog (ERROR, "plot_corners (%s): attribute %s must be of POINT type", relname, distance_names[i]); } corners = calc_corners (N_DISTANCES, d); c [0] = PointGetDatum (&corners.LL); /* ??? - how to convert Point to Datum? */ c [1] = PointGetDatum (&corners.LR); c [2]= PointGetDatum (&corners.UL); c [3] = PointGetDatum (&corners.UR); rettuple = SPI_modifytuple (rel, rettuple, N_CORNERS, c_attnum, c, NULL); if (rettuple == NULL) elog (ERROR, "plot_corners(%s): %d returned by SPI_modifytuple", relname, SPI_result); pfree (relname); return (rettuple); } /* calculate corner positions */ Corners calc_corners (int n_distances, const int32 * d) { Corners c; c.LL.x = 0; /* ??? - how to initialize/access Point values? */ c.LL.y = 0; c.LR.x = 1; c.LR.y = 0; c.UL.x = 0; c.UL.y = 1; c.UR.x = 1; c.UR.y = 1; return c; }
pgsql-hackers by date: