From: | Brook Milligan <brook(at)trillium(dot)NMSU(dot)Edu> |
---|---|
To: | hackers(at)postgreSQL(dot)org |
Subject: | trigger functions and access to datatypes |
Date: | 1999-06-14 21:32:11 |
Message-ID: | 199906142132.PAA20191@trillium.nmsu.edu |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | 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't process 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 fired after 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;
}
From | Date | Subject | |
---|---|---|---|
Next Message | Bruce Momjian | 1999-06-14 21:53:25 | Re: [PORTS] Patch for m68k architecture (fwd) |
Previous Message | Tom Lane | 1999-06-14 20:57:53 | Re: [HACKERS] Docs done? |