mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Added: ttdummy() - variation of timetravel() function
for regress test.
This commit is contained in:
@ -7,7 +7,7 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
# IDENTIFICATION
|
# IDENTIFICATION
|
||||||
# $Header: /cvsroot/pgsql/src/test/regress/GNUmakefile,v 1.10 1997/09/11 09:13:27 vadim Exp $
|
# $Header: /cvsroot/pgsql/src/test/regress/GNUmakefile,v 1.11 1997/09/24 08:35:07 vadim Exp $
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ endif
|
|||||||
all: $(INFILES)
|
all: $(INFILES)
|
||||||
cd input; $(MAKE) all; cd ..
|
cd input; $(MAKE) all; cd ..
|
||||||
cd output; $(MAKE) all; cd ..
|
cd output; $(MAKE) all; cd ..
|
||||||
$(MAKE) -C ../../../contrib/spi REFINT_VERBOSE=1
|
$(MAKE) -C ../../../contrib/spi REFINT_VERBOSE=1 refint$(DLSUFFIX)
|
||||||
|
|
||||||
#
|
#
|
||||||
# run the test
|
# run the test
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.15 1997/09/18 20:22:54 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.16 1997/09/24 08:35:10 vadim Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <float.h> /* faked on sunos */
|
#include <float.h> /* faked on sunos */
|
||||||
@ -411,3 +411,232 @@ funny_dup17()
|
|||||||
|
|
||||||
return (tuple);
|
return (tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <ctype.h> /* tolower () */
|
||||||
|
|
||||||
|
HeapTuple ttdummy(void);
|
||||||
|
int32 set_ttdummy(int32 on);
|
||||||
|
|
||||||
|
extern int4 nextval(struct varlena * seqin);
|
||||||
|
|
||||||
|
#define TTDUMMY_INFINITY 999999
|
||||||
|
|
||||||
|
static void *splan = NULL;
|
||||||
|
static bool ttoff = false;
|
||||||
|
|
||||||
|
HeapTuple
|
||||||
|
ttdummy()
|
||||||
|
{
|
||||||
|
Trigger *trigger; /* to get trigger name */
|
||||||
|
char **args; /* arguments */
|
||||||
|
int attnum[2]; /* fnumbers of start/stop columns */
|
||||||
|
Datum oldon, oldoff;
|
||||||
|
Datum newon, newoff;
|
||||||
|
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 */
|
||||||
|
bool isnull; /* to know is some column NULL or not */
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!CurrentTriggerData)
|
||||||
|
elog(WARN, "ttdummy: triggers are not initialized");
|
||||||
|
if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
|
||||||
|
elog(WARN, "ttdummy: can't process STATEMENT events");
|
||||||
|
if (TRIGGER_FIRED_AFTER(CurrentTriggerData->tg_event))
|
||||||
|
elog(WARN, "ttdummy: must be fired before event");
|
||||||
|
if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event))
|
||||||
|
elog (WARN, "ttdummy: can't process INSERT event");
|
||||||
|
if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
|
||||||
|
newtuple = CurrentTriggerData->tg_newtuple;
|
||||||
|
|
||||||
|
trigtuple = CurrentTriggerData->tg_trigtuple;
|
||||||
|
|
||||||
|
rel = CurrentTriggerData->tg_relation;
|
||||||
|
relname = SPI_getrelname(rel);
|
||||||
|
|
||||||
|
/* check if TT is OFF for this relation */
|
||||||
|
if (ttoff) /* OFF - nothing to do */
|
||||||
|
{
|
||||||
|
pfree (relname);
|
||||||
|
return ((newtuple != NULL) ? newtuple : trigtuple);
|
||||||
|
}
|
||||||
|
|
||||||
|
trigger = CurrentTriggerData->tg_trigger;
|
||||||
|
|
||||||
|
if (trigger->tgnargs != 2)
|
||||||
|
elog(WARN, "ttdummy (%s): invalid (!= 2) number of arguments %d",
|
||||||
|
relname, trigger->tgnargs);
|
||||||
|
|
||||||
|
args = trigger->tgargs;
|
||||||
|
tupdesc = rel->rd_att;
|
||||||
|
natts = tupdesc->natts;
|
||||||
|
|
||||||
|
CurrentTriggerData = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++ )
|
||||||
|
{
|
||||||
|
attnum[i] = SPI_fnumber (tupdesc, args[i]);
|
||||||
|
if ( attnum[i] < 0 )
|
||||||
|
elog(WARN, "ttdummy (%s): there is no attribute %s", relname, args[i]);
|
||||||
|
if (SPI_gettypeid (tupdesc, attnum[i]) != INT4OID)
|
||||||
|
elog(WARN, "ttdummy (%s): attributes %s and %s must be of abstime type",
|
||||||
|
relname, args[0], args[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
oldon = SPI_getbinval (trigtuple, tupdesc, attnum[0], &isnull);
|
||||||
|
if (isnull)
|
||||||
|
elog(WARN, "ttdummy (%s): %s must be NOT NULL", relname, args[0]);
|
||||||
|
|
||||||
|
oldoff = SPI_getbinval (trigtuple, tupdesc, attnum[1], &isnull);
|
||||||
|
if (isnull)
|
||||||
|
elog(WARN, "ttdummy (%s): %s must be NOT NULL", relname, args[1]);
|
||||||
|
|
||||||
|
if (newtuple != NULL) /* UPDATE */
|
||||||
|
{
|
||||||
|
newon = SPI_getbinval (newtuple, tupdesc, attnum[0], &isnull);
|
||||||
|
if (isnull)
|
||||||
|
elog(WARN, "ttdummy (%s): %s must be NOT NULL", relname, args[0]);
|
||||||
|
newoff = SPI_getbinval (newtuple, tupdesc, attnum[1], &isnull);
|
||||||
|
if (isnull)
|
||||||
|
elog(WARN, "ttdummy (%s): %s must be NOT NULL", relname, args[1]);
|
||||||
|
|
||||||
|
if ( oldon != newon || oldoff != newoff )
|
||||||
|
elog (WARN, "ttdummy (%s): you can't change %s and/or %s columns (use set_ttdummy)",
|
||||||
|
relname, args[0], args[1]);
|
||||||
|
|
||||||
|
if ( newoff != TTDUMMY_INFINITY )
|
||||||
|
{
|
||||||
|
pfree (relname); /* allocated in upper executor context */
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (oldoff != TTDUMMY_INFINITY) /* DELETE */
|
||||||
|
{
|
||||||
|
pfree (relname);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
struct varlena *seqname = textin ("ttdummy_seq");
|
||||||
|
|
||||||
|
newoff = nextval (seqname);
|
||||||
|
pfree (seqname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect to SPI manager */
|
||||||
|
if ((ret = SPI_connect()) < 0)
|
||||||
|
elog(WARN, "ttdummy (%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++)
|
||||||
|
{
|
||||||
|
cvals[i] = SPI_getbinval ((newtuple != NULL) ? newtuple : trigtuple,
|
||||||
|
tupdesc, i + 1, &isnull);
|
||||||
|
cnulls[i] = (isnull) ? 'n' : ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* change date column(s) */
|
||||||
|
if (newtuple) /* UPDATE */
|
||||||
|
{
|
||||||
|
cvals[attnum[0] - 1] = newoff; /* start_date eq current date */
|
||||||
|
cnulls[attnum[0] - 1] = ' ';
|
||||||
|
cvals[attnum[1] - 1] = TTDUMMY_INFINITY; /* stop_date eq INFINITY */
|
||||||
|
cnulls[attnum[1] - 1] = ' ';
|
||||||
|
}
|
||||||
|
else /* DELETE */
|
||||||
|
{
|
||||||
|
cvals[attnum[1] - 1] = newoff; /* stop_date eq current date */
|
||||||
|
cnulls[attnum[1] - 1] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if there is no plan ... */
|
||||||
|
if (splan == NULL)
|
||||||
|
{
|
||||||
|
void *pplan;
|
||||||
|
Oid *ctypes;
|
||||||
|
char sql[8192];
|
||||||
|
|
||||||
|
/* allocate ctypes for preparation */
|
||||||
|
ctypes = (Oid *) palloc(natts * sizeof(Oid));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Construct query:
|
||||||
|
* INSERT INTO _relation_ VALUES ($1, ...)
|
||||||
|
*/
|
||||||
|
sprintf(sql, "INSERT INTO %s VALUES (", relname);
|
||||||
|
for (i = 1; i <= natts; i++)
|
||||||
|
{
|
||||||
|
sprintf(sql + strlen(sql), "$%d%s",
|
||||||
|
i, (i < natts) ? ", " : ")");
|
||||||
|
ctypes[i - 1] = SPI_gettypeid(tupdesc, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare plan for query */
|
||||||
|
pplan = SPI_prepare(sql, natts, ctypes);
|
||||||
|
if (pplan == NULL)
|
||||||
|
elog(WARN, "ttdummy (%s): SPI_prepare returned %d", relname, SPI_result);
|
||||||
|
|
||||||
|
pplan = SPI_saveplan(pplan);
|
||||||
|
if (pplan == NULL)
|
||||||
|
elog(WARN, "ttdummy (%s): SPI_saveplan returned %d", relname, SPI_result);
|
||||||
|
|
||||||
|
splan = pplan;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = SPI_execp(splan, cvals, cnulls, 0);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
elog(WARN, "ttdummy (%s): SPI_execp returned %d", relname, ret);
|
||||||
|
|
||||||
|
/* Tuple to return to upper Executor ... */
|
||||||
|
if (newtuple) /* UPDATE */
|
||||||
|
{
|
||||||
|
HeapTuple tmptuple;
|
||||||
|
|
||||||
|
tmptuple = SPI_copytuple (trigtuple);
|
||||||
|
rettuple = SPI_modifytuple (rel, tmptuple, 1, &(attnum[1]), &newoff, NULL);
|
||||||
|
SPI_pfree (tmptuple);
|
||||||
|
}
|
||||||
|
else /* DELETE */
|
||||||
|
rettuple = trigtuple;
|
||||||
|
|
||||||
|
SPI_finish(); /* don't forget say Bye to SPI mgr */
|
||||||
|
|
||||||
|
pfree (relname);
|
||||||
|
|
||||||
|
return (rettuple);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
set_ttdummy(int32 on)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (ttoff) /* OFF currently */
|
||||||
|
{
|
||||||
|
if (on == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
/* turn ON */
|
||||||
|
ttoff = false;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ON currently */
|
||||||
|
if (on != 0)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
/* turn OFF */
|
||||||
|
ttoff = true;
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user