From: Vadim B. Mikheev Date: Wed, 24 Sep 1997 08:35:10 +0000 (+0000) Subject: Added: ttdummy() - variation of timetravel() function X-Git-Tag: REL6_2~98 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=76271543aeac488c17ebf720c4ebad311c654ba8;p=postgresql Added: ttdummy() - variation of timetravel() function for regress test. --- diff --git a/src/test/regress/GNUmakefile b/src/test/regress/GNUmakefile index a4904b4119..8dbcdba58b 100644 --- a/src/test/regress/GNUmakefile +++ b/src/test/regress/GNUmakefile @@ -7,7 +7,7 @@ # # # 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) cd input; $(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 diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c index e602762df8..2e2eaa9e4f 100644 --- a/src/test/regress/regress.c +++ b/src/test/regress/regress.c @@ -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 /* faked on sunos */ @@ -411,3 +411,232 @@ funny_dup17() return (tuple); } + +#include /* 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); + +}