summaryrefslogtreecommitdiff
path: root/contrib/spi/timetravel.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/spi/timetravel.c')
-rw-r--r--contrib/spi/timetravel.c239
1 files changed, 122 insertions, 117 deletions
diff --git a/contrib/spi/timetravel.c b/contrib/spi/timetravel.c
index aa8d0a47b46..8ffa56edc75 100644
--- a/contrib/spi/timetravel.c
+++ b/contrib/spi/timetravel.c
@@ -6,11 +6,11 @@
/* Modified by B�JTHE Zolt�n, Hungary, mailto:[email protected] */
#include "executor/spi.h" /* this is what you need to work with SPI */
-#include "commands/trigger.h" /* -"- and triggers */
+#include "commands/trigger.h" /* -"- and triggers */
#include "miscadmin.h" /* for GetPgUserName() */
-#include <ctype.h> /* tolower () */
+#include <ctype.h> /* tolower () */
-#define ABSTIMEOID 702 /* it should be in pg_type.h */
+#define ABSTIMEOID 702 /* it should be in pg_type.h */
/* AbsoluteTime currabstime(void); */
Datum timetravel(PG_FUNCTION_ARGS);
@@ -28,13 +28,13 @@ static int nPlans = 0;
typedef struct _TTOffList
{
- struct _TTOffList *next;
- char name[1];
-} TTOffList;
+ struct _TTOffList *next;
+ char name[1];
+} TTOffList;
-static TTOffList TTOff = {NULL,{0}};
+static TTOffList TTOff = {NULL, {0}};
-static int findTTStatus(char *name);
+static int findTTStatus(char *name);
static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
/*
@@ -71,57 +71,57 @@ static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
PG_FUNCTION_INFO_V1(timetravel);
-Datum /* have to return HeapTuple to Executor */
+Datum /* have to return HeapTuple to Executor */
timetravel(PG_FUNCTION_ARGS)
{
- TriggerData *trigdata = (TriggerData *) fcinfo->context;
- Trigger *trigger; /* to get trigger name */
- int argc;
- char **args; /* arguments */
- int attnum[MaxAttrNum]; /* fnumbers of start/stop columns */
+ TriggerData *trigdata = (TriggerData *) fcinfo->context;
+ Trigger *trigger; /* to get trigger name */
+ int argc;
+ char **args; /* arguments */
+ int attnum[MaxAttrNum]; /* fnumbers of start/stop columns */
Datum oldtimeon,
- oldtimeoff;
+ oldtimeoff;
Datum newtimeon,
- newtimeoff,
- newuser,
- nulltext;
- Datum *cvals; /* column values */
- char *cnulls; /* column nulls */
- char *relname; /* triggered relation name */
+ newtimeoff,
+ newuser,
+ nulltext;
+ Datum *cvals; /* column values */
+ char *cnulls; /* column nulls */
+ char *relname; /* triggered relation name */
Relation rel; /* triggered relation */
HeapTuple trigtuple;
HeapTuple newtuple = NULL;
HeapTuple rettuple;
TupleDesc tupdesc; /* tuple description */
- int natts; /* # of attributes */
- EPlan *plan; /* prepared plan */
+ int natts; /* # of attributes */
+ EPlan *plan; /* prepared plan */
char ident[2 * NAMEDATALEN];
bool isnull; /* to know is some column NULL or not */
bool isinsert = false;
- int ret;
- int i;
+ int ret;
+ int i;
/*
* Some checks first...
*/
/* Called by trigger manager ? */
- if(!CALLED_AS_TRIGGER(fcinfo))
+ if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "timetravel: not fired by trigger manager");
/* Should be called for ROW trigger */
- if(TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
+ if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
elog(ERROR, "timetravel: can't process STATEMENT events");
/* Should be called BEFORE */
- if(TRIGGER_FIRED_AFTER(trigdata->tg_event))
+ if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
elog(ERROR, "timetravel: must be fired before event");
/* INSERT ? */
- if(TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
+ if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
isinsert = true;
- if(TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
+ if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
newtuple = trigdata->tg_newtuple;
trigtuple = trigdata->tg_trigtuple;
@@ -130,7 +130,7 @@ timetravel(PG_FUNCTION_ARGS)
relname = SPI_getrelname(rel);
/* check if TT is OFF for this relation */
- if(0==findTTStatus(relname))
+ if (0 == findTTStatus(relname))
{
/* OFF - nothing to do */
pfree(relname);
@@ -140,7 +140,7 @@ timetravel(PG_FUNCTION_ARGS)
trigger = trigdata->tg_trigger;
argc = trigger->tgnargs;
- if(argc != MinAttrNum && argc != MaxAttrNum)
+ if (argc != MinAttrNum && argc != MaxAttrNum)
elog(ERROR, "timetravel (%s): invalid (!= %d or %d) number of arguments %d",
relname, MinAttrNum, MaxAttrNum, trigger->tgnargs);
@@ -148,39 +148,39 @@ timetravel(PG_FUNCTION_ARGS)
tupdesc = rel->rd_att;
natts = tupdesc->natts;
- for(i = 0 ; i < MinAttrNum ; i++)
+ for (i = 0; i < MinAttrNum; i++)
{
attnum[i] = SPI_fnumber(tupdesc, args[i]);
- if(attnum[i] < 0)
+ if (attnum[i] < 0)
elog(ERROR, "timetravel (%s): there is no attribute %s", relname, args[i]);
- if(SPI_gettypeid(tupdesc, attnum[i]) != ABSTIMEOID)
+ if (SPI_gettypeid(tupdesc, attnum[i]) != ABSTIMEOID)
elog(ERROR, "timetravel (%s): attribute %s must be of abstime type",
relname, args[i]);
}
- for( ; i < argc ; i++)
+ for (; i < argc; i++)
{
attnum[i] = SPI_fnumber(tupdesc, args[i]);
- if(attnum[i] < 0)
+ if (attnum[i] < 0)
elog(ERROR, "timetravel (%s): there is no attribute %s", relname, args[i]);
- if(SPI_gettypeid(tupdesc, attnum[i]) != TEXTOID)
+ if (SPI_gettypeid(tupdesc, attnum[i]) != TEXTOID)
elog(ERROR, "timetravel (%s): attribute %s must be of text type",
relname, args[i]);
}
/* create fields containing name */
- newuser = DirectFunctionCall1(textin, CStringGetDatum(GetUserNameFromId(GetUserId())));
+ newuser = DirectFunctionCall1(textin, CStringGetDatum(GetUserNameFromId(GetUserId())));
- nulltext = (Datum)NULL;
+ nulltext = (Datum) NULL;
- if(isinsert)
- { /* INSERT */
- int chnattrs = 0;
- int chattrs[MaxAttrNum];
- Datum newvals[MaxAttrNum];
- char newnulls[MaxAttrNum];
+ if (isinsert)
+ { /* INSERT */
+ int chnattrs = 0;
+ int chattrs[MaxAttrNum];
+ Datum newvals[MaxAttrNum];
+ char newnulls[MaxAttrNum];
oldtimeon = SPI_getbinval(trigtuple, tupdesc, attnum[a_time_on], &isnull);
- if(isnull)
+ if (isnull)
{
newvals[chnattrs] = GetCurrentAbsoluteTime();
newnulls[chnattrs] = ' ';
@@ -189,10 +189,10 @@ timetravel(PG_FUNCTION_ARGS)
}
oldtimeoff = SPI_getbinval(trigtuple, tupdesc, attnum[a_time_off], &isnull);
- if(isnull)
+ if (isnull)
{
- if((chnattrs == 0 && DatumGetInt32(oldtimeon) >= NOEND_ABSTIME) ||
- (chnattrs > 0 && DatumGetInt32(newvals[a_time_on]) >= NOEND_ABSTIME))
+ if ((chnattrs == 0 && DatumGetInt32(oldtimeon) >= NOEND_ABSTIME) ||
+ (chnattrs > 0 && DatumGetInt32(newvals[a_time_on]) >= NOEND_ABSTIME))
elog(ERROR, "timetravel (%s): %s is infinity", relname, args[a_time_on]);
newvals[chnattrs] = NOEND_ABSTIME;
newnulls[chnattrs] = ' ';
@@ -201,16 +201,16 @@ timetravel(PG_FUNCTION_ARGS)
}
else
{
- if((chnattrs == 0 && DatumGetInt32(oldtimeon) > DatumGetInt32(oldtimeoff)) ||
- (chnattrs > 0 && DatumGetInt32(newvals[a_time_on]) > DatumGetInt32(oldtimeoff)))
+ if ((chnattrs == 0 && DatumGetInt32(oldtimeon) > DatumGetInt32(oldtimeoff)) ||
+ (chnattrs > 0 && DatumGetInt32(newvals[a_time_on]) > DatumGetInt32(oldtimeoff)))
elog(ERROR, "timetravel (%s): %s gt %s", relname, args[a_time_on], args[a_time_off]);
}
pfree(relname);
- if(chnattrs <= 0)
+ if (chnattrs <= 0)
return PointerGetDatum(trigtuple);
- if(argc == MaxAttrNum)
+ if (argc == MaxAttrNum)
{
/* clear update_user value */
newvals[chnattrs] = nulltext;
@@ -235,33 +235,34 @@ timetravel(PG_FUNCTION_ARGS)
/* UPDATE/DELETE: */
oldtimeon = SPI_getbinval(trigtuple, tupdesc, attnum[a_time_on], &isnull);
- if(isnull)
+ if (isnull)
elog(ERROR, "timetravel (%s): %s must be NOT NULL", relname, args[a_time_on]);
oldtimeoff = SPI_getbinval(trigtuple, tupdesc, attnum[a_time_off], &isnull);
- if(isnull)
+ if (isnull)
elog(ERROR, "timetravel (%s): %s must be NOT NULL", relname, args[a_time_off]);
/*
* If DELETE/UPDATE of tuple with stop_date neq INFINITY then say
* upper Executor to skip operation for this tuple
*/
- if(newtuple != NULL)
- { /* UPDATE */
+ if (newtuple != NULL)
+ { /* UPDATE */
newtimeon = SPI_getbinval(newtuple, tupdesc, attnum[a_time_on], &isnull);
- if(isnull)
+ if (isnull)
elog(ERROR, "timetravel (%s): %s must be NOT NULL", relname, args[a_time_on]);
newtimeoff = SPI_getbinval(newtuple, tupdesc, attnum[a_time_off], &isnull);
- if(isnull)
+ if (isnull)
elog(ERROR, "timetravel (%s): %s must be NOT NULL", relname, args[a_time_off]);
- if(oldtimeon != newtimeon || oldtimeoff != newtimeoff)
+ if (oldtimeon != newtimeon || oldtimeoff != newtimeoff)
elog(ERROR, "timetravel (%s): you can't change %s and/or %s columns (use set_timetravel)",
relname, args[a_time_on], args[a_time_off]);
}
- if(oldtimeoff != NOEND_ABSTIME)
- { /* current record is a deleted/updated record */
+ if (oldtimeoff != NOEND_ABSTIME)
+ { /* current record is a deleted/updated
+ * record */
pfree(relname);
return PointerGetDatum(NULL);
}
@@ -269,27 +270,28 @@ timetravel(PG_FUNCTION_ARGS)
newtimeoff = GetCurrentAbsoluteTime();
/* Connect to SPI manager */
- if((ret = SPI_connect()) < 0)
+ if ((ret = SPI_connect()) < 0)
elog(ERROR, "timetravel (%s): SPI_connect returned %d", relname, ret);
/* Fetch tuple values and nulls */
cvals = (Datum *) palloc(natts * sizeof(Datum));
cnulls = (char *) palloc(natts * sizeof(char));
- for(i = 0; i < natts; i++)
+ for (i = 0; i < natts; i++)
{
cvals[i] = SPI_getbinval(trigtuple, tupdesc, i + 1, &isnull);
cnulls[i] = (isnull) ? 'n' : ' ';
}
/* change date column(s) */
- cvals[attnum[a_time_off] - 1] = newtimeoff; /* stop_date eq current date */
+ cvals[attnum[a_time_off] - 1] = newtimeoff; /* stop_date eq current
+ * date */
cnulls[attnum[a_time_off] - 1] = ' ';
- if(!newtuple)
- { /* DELETE */
- if(argc == MaxAttrNum)
+ if (!newtuple)
+ { /* DELETE */
+ if (argc == MaxAttrNum)
{
- cvals[attnum[a_del_user] - 1] = newuser; /* set delete user */
+ cvals[attnum[a_del_user] - 1] = newuser; /* set delete user */
cnulls[attnum[a_del_user] - 1] = ' ';
}
}
@@ -302,11 +304,11 @@ timetravel(PG_FUNCTION_ARGS)
plan = find_plan(ident, &Plans, &nPlans);
/* if there is no plan ... */
- if(plan->splan == NULL)
+ if (plan->splan == NULL)
{
- void *pplan;
- Oid *ctypes;
- char sql[8192];
+ void *pplan;
+ Oid *ctypes;
+ char sql[8192];
/* allocate ctypes for preparation */
ctypes = (Oid *) palloc(natts * sizeof(Oid));
@@ -315,15 +317,15 @@ timetravel(PG_FUNCTION_ARGS)
* Construct query: INSERT INTO _relation_ VALUES ($1, ...)
*/
snprintf(sql, sizeof(sql), "INSERT INTO %s VALUES (", relname);
- for(i = 1; i <= natts; i++)
+ for (i = 1; i <= natts; i++)
{
ctypes[i - 1] = SPI_gettypeid(tupdesc, i);
- if(!(tupdesc->attrs[i - 1]->attisdropped)) /* skip dropped columns */
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "$%d%s",
- i, (i < natts) ? ", " : ")" );
+ if (!(tupdesc->attrs[i - 1]->attisdropped)) /* skip dropped columns */
+ snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "$%d%s",
+ i, (i < natts) ? ", " : ")");
#if 0
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "$%d /* %d */ %s",
- i, ctypes[i-1], (i < natts) ? ", " : ")" );
+ snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "$%d /* %d */ %s",
+ i, ctypes[i - 1], (i < natts) ? ", " : ")");
#endif
}
@@ -331,7 +333,7 @@ timetravel(PG_FUNCTION_ARGS)
/* Prepare plan for query */
pplan = SPI_prepare(sql, natts, ctypes);
- if(pplan == NULL)
+ if (pplan == NULL)
elog(ERROR, "timetravel (%s): SPI_prepare returned %d", relname, SPI_result);
/*
@@ -340,7 +342,7 @@ timetravel(PG_FUNCTION_ARGS)
* use.
*/
pplan = SPI_saveplan(pplan);
- if(pplan == NULL)
+ if (pplan == NULL)
elog(ERROR, "timetravel (%s): SPI_saveplan returned %d", relname, SPI_result);
plan->splan = pplan;
@@ -351,14 +353,14 @@ timetravel(PG_FUNCTION_ARGS)
*/
ret = SPI_execp(plan->splan, cvals, cnulls, 0);
- if(ret < 0)
+ if (ret < 0)
elog(ERROR, "timetravel (%s): SPI_execp returned %d", relname, ret);
/* Tuple to return to upper Executor ... */
- if(newtuple)
- { /* UPDATE */
- int chnattrs = 0;
- int chattrs[MaxAttrNum];
+ if (newtuple)
+ { /* UPDATE */
+ int chnattrs = 0;
+ int chattrs[MaxAttrNum];
Datum newvals[MaxAttrNum];
char newnulls[MaxAttrNum];
@@ -372,7 +374,7 @@ timetravel(PG_FUNCTION_ARGS)
chattrs[chnattrs] = attnum[a_time_off];
chnattrs++;
- if(argc == MaxAttrNum)
+ if (argc == MaxAttrNum)
{
/* set update_user value */
newvals[chnattrs] = newuser;
@@ -399,7 +401,8 @@ timetravel(PG_FUNCTION_ARGS)
*/
/* SPI_pfree(tmptuple); */
}
- else /* DELETE case */
+ else
+/* DELETE case */
rettuple = trigtuple;
SPI_finish(); /* don't forget say Bye to SPI mgr */
@@ -417,23 +420,24 @@ PG_FUNCTION_INFO_V1(set_timetravel);
Datum
set_timetravel(PG_FUNCTION_ARGS)
{
- Name relname = PG_GETARG_NAME(0);
- int32 on = PG_GETARG_INT32(1);
- char *rname;
- char *d;
- char *s;
+ Name relname = PG_GETARG_NAME(0);
+ int32 on = PG_GETARG_INT32(1);
+ char *rname;
+ char *d;
+ char *s;
int32 ret;
- TTOffList *p,*pp;
+ TTOffList *p,
+ *pp;
- for(pp = (p = &TTOff)->next; pp; pp=(p=pp)->next)
+ for (pp = (p = &TTOff)->next; pp; pp = (p = pp)->next)
{
- if(namestrcmp(relname, pp->name) == 0)
+ if (namestrcmp(relname, pp->name) == 0)
break;
}
- if(pp)
+ if (pp)
{
/* OFF currently */
- if(on != 0)
+ if (on != 0)
{
/* turn ON */
p->next = pp->next;
@@ -444,20 +448,20 @@ set_timetravel(PG_FUNCTION_ARGS)
else
{
/* ON currently */
- if(on == 0)
+ if (on == 0)
{
/* turn OFF */
s = rname = DatumGetCString(DirectFunctionCall1(nameout, NameGetDatum(relname)));
- if(s)
+ if (s)
{
- pp = malloc(sizeof(TTOffList)+strlen(rname));
- if(pp)
+ pp = malloc(sizeof(TTOffList) + strlen(rname));
+ if (pp)
{
pp->next = NULL;
p->next = pp;
d = pp->name;
while (*s)
- *d++ = tolower((unsigned char)*s++);
+ *d++ = tolower((unsigned char) *s++);
*d = '\0';
}
pfree(rname);
@@ -470,7 +474,7 @@ set_timetravel(PG_FUNCTION_ARGS)
/*
* get_timetravel (relname) --
- * get timetravel status for specified relation (ON/OFF)
+ * get timetravel status for specified relation (ON/OFF)
*/
PG_FUNCTION_INFO_V1(get_timetravel);
@@ -478,11 +482,11 @@ Datum
get_timetravel(PG_FUNCTION_ARGS)
{
Name relname = PG_GETARG_NAME(0);
- TTOffList *pp;
+ TTOffList *pp;
- for(pp = TTOff.next; pp; pp = pp->next)
+ for (pp = TTOff.next; pp; pp = pp->next)
{
- if(namestrcmp(relname, pp->name) == 0)
+ if (namestrcmp(relname, pp->name) == 0)
PG_RETURN_INT32(0);
}
PG_RETURN_INT32(1);
@@ -491,9 +495,10 @@ get_timetravel(PG_FUNCTION_ARGS)
static int
findTTStatus(char *name)
{
- TTOffList* pp;
- for(pp = TTOff.next; pp; pp = pp->next)
- if(strcasecmp(name, pp->name) == 0)
+ TTOffList *pp;
+
+ for (pp = TTOff.next; pp; pp = pp->next)
+ if (strcasecmp(name, pp->name) == 0)
return 0;
return 1;
}
@@ -509,17 +514,17 @@ currabstime()
static EPlan *
find_plan(char *ident, EPlan ** eplan, int *nplans)
{
- EPlan *newp;
- int i;
+ EPlan *newp;
+ int i;
- if(*nplans > 0)
+ if (*nplans > 0)
{
- for(i = 0; i < *nplans; i++)
+ for (i = 0; i < *nplans; i++)
{
- if(strcmp((*eplan)[i].ident, ident) == 0)
+ if (strcmp((*eplan)[i].ident, ident) == 0)
break;
}
- if(i != *nplans)
+ if (i != *nplans)
return (*eplan + i);
*eplan = (EPlan *) realloc(*eplan, (i + 1) * sizeof(EPlan));
newp = *eplan + i;