⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 regress.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 2 页
字号:
	{		xid = &fd17a_xid;		level = &fd17a_level;		recursion = &fd17a_recursion;		when = "AFTER ";	}	if (!TransactionIdIsCurrentTransactionId(*xid))	{		*xid = GetCurrentTransactionId();		*level = 0;		*recursion = true;	}	if (*level == 17)	{		*recursion = false;		return PointerGetDatum(tuple);	}	if (!(*recursion))		return PointerGetDatum(tuple);	(*level)++;	SPI_connect();	fieldval = SPI_getvalue(tuple, tupdesc, 1);	fieldtype = SPI_gettype(tupdesc, 1);	query = (char *) palloc(100 + NAMEDATALEN * 3 +							strlen(fieldval) + strlen(fieldtype));	sprintf(query, "insert into %s select * from %s where %s = '%s'::%s",			SPI_getrelname(rel), SPI_getrelname(rel),			SPI_fname(tupdesc, 1),			fieldval, fieldtype);	if ((ret = SPI_exec(query, 0)) < 0)		elog(ERROR, "funny_dup17 (fired %s) on level %3d: SPI_exec (insert ...) returned %d",			 when, *level, ret);	inserted = SPI_processed;	sprintf(query, "select count (*) from %s where %s = '%s'::%s",			SPI_getrelname(rel),			SPI_fname(tupdesc, 1),			fieldval, fieldtype);	if ((ret = SPI_exec(query, 0)) < 0)		elog(ERROR, "funny_dup17 (fired %s) on level %3d: SPI_exec (select ...) returned %d",			 when, *level, ret);	if (SPI_processed > 0)	{		selected = DatumGetInt32(DirectFunctionCall1(int4in,											CStringGetDatum(SPI_getvalue(												   SPI_tuptable->vals[0],												   SPI_tuptable->tupdesc,																		 1																	))));	}	elog(DEBUG4, "funny_dup17 (fired %s) on level %3d: %d/%d tuples inserted/selected",		 when, *level, inserted, selected);	SPI_finish();	(*level)--;	if (*level == 0)		*xid = InvalidTransactionId;	return PointerGetDatum(tuple);}extern Datum ttdummy(PG_FUNCTION_ARGS);extern Datum set_ttdummy(PG_FUNCTION_ARGS);#define TTDUMMY_INFINITY	999999static void *splan = NULL;static bool ttoff = false;PG_FUNCTION_INFO_V1(ttdummy);Datumttdummy(PG_FUNCTION_ARGS){	TriggerData *trigdata = (TriggerData *) fcinfo->context;	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 (!CALLED_AS_TRIGGER(fcinfo))		elog(ERROR, "ttdummy: not fired by trigger manager");	if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))		elog(ERROR, "ttdummy: can't process STATEMENT events");	if (TRIGGER_FIRED_AFTER(trigdata->tg_event))		elog(ERROR, "ttdummy: must be fired before event");	if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))		elog(ERROR, "ttdummy: can't process INSERT event");	if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))		newtuple = trigdata->tg_newtuple;	trigtuple = trigdata->tg_trigtuple;	rel = trigdata->tg_relation;	relname = SPI_getrelname(rel);	/* check if TT is OFF for this relation */	if (ttoff)					/* OFF - nothing to do */	{		pfree(relname);		return PointerGetDatum((newtuple != NULL) ? newtuple : trigtuple);	}	trigger = trigdata->tg_trigger;	if (trigger->tgnargs != 2)		elog(ERROR, "ttdummy (%s): invalid (!= 2) number of arguments %d",			 relname, trigger->tgnargs);	args = trigger->tgargs;	tupdesc = rel->rd_att;	natts = tupdesc->natts;	for (i = 0; i < 2; i++)	{		attnum[i] = SPI_fnumber(tupdesc, args[i]);		if (attnum[i] < 0)			elog(ERROR, "ttdummy (%s): there is no attribute %s", relname, args[i]);		if (SPI_gettypeid(tupdesc, attnum[i]) != INT4OID)			elog(ERROR, "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(ERROR, "ttdummy (%s): %s must be NOT NULL", relname, args[0]);	oldoff = SPI_getbinval(trigtuple, tupdesc, attnum[1], &isnull);	if (isnull)		elog(ERROR, "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(ERROR, "ttdummy (%s): %s must be NOT NULL", relname, args[0]);		newoff = SPI_getbinval(newtuple, tupdesc, attnum[1], &isnull);		if (isnull)			elog(ERROR, "ttdummy (%s): %s must be NOT NULL", relname, args[1]);		if (oldon != newon || oldoff != newoff)			elog(ERROR, "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 PointerGetDatum(NULL);		}	}	else if (oldoff != TTDUMMY_INFINITY)		/* DELETE */	{		pfree(relname);		return PointerGetDatum(NULL);	}	{		text	   *seqname = DatumGetTextP(DirectFunctionCall1(textin,										CStringGetDatum("ttdummy_seq")));		newoff = DirectFunctionCall1(nextval,									 PointerGetDatum(seqname));		/* nextval now returns int64; coerce down to int32 */		newoff = Int32GetDatum((int32) DatumGetInt64(newoff));		pfree(seqname);	}	/* Connect to SPI manager */	if ((ret = SPI_connect()) < 0)		elog(ERROR, "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	   *query;		/* allocate space in preparation */		ctypes = (Oid *) palloc(natts * sizeof(Oid));		query = (char *) palloc(100 + 16 * natts);		/*		 * Construct query: INSERT INTO _relation_ VALUES ($1, ...)		 */		sprintf(query, "INSERT INTO %s VALUES (", relname);		for (i = 1; i <= natts; i++)		{			sprintf(query + strlen(query), "$%d%s",					i, (i < natts) ? ", " : ")");			ctypes[i - 1] = SPI_gettypeid(tupdesc, i);		}		/* Prepare plan for query */		pplan = SPI_prepare(query, natts, ctypes);		if (pplan == NULL)			elog(ERROR, "ttdummy (%s): SPI_prepare returned %d", relname, SPI_result);		pplan = SPI_saveplan(pplan);		if (pplan == NULL)			elog(ERROR, "ttdummy (%s): SPI_saveplan returned %d", relname, SPI_result);		splan = pplan;	}	ret = SPI_execp(splan, cvals, cnulls, 0);	if (ret < 0)		elog(ERROR, "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_freetuple(tmptuple);	}	else/* DELETE */		rettuple = trigtuple;	SPI_finish();				/* don't forget say Bye to SPI mgr */	pfree(relname);	return PointerGetDatum(rettuple);}PG_FUNCTION_INFO_V1(set_ttdummy);Datumset_ttdummy(PG_FUNCTION_ARGS){	int32		on = PG_GETARG_INT32(0);	if (ttoff)					/* OFF currently */	{		if (on == 0)			PG_RETURN_INT32(0);		/* turn ON */		ttoff = false;		PG_RETURN_INT32(0);	}	/* ON currently */	if (on != 0)		PG_RETURN_INT32(1);	/* turn OFF */	ttoff = true;	PG_RETURN_INT32(1);}/* * Type int44 has no real-world use, but the regression tests use it. * It's a four-element vector of int4's. *//* *		int44in			- converts "num num ..." to internal form * *		Note: Fills any missing positions with zeroes. */PG_FUNCTION_INFO_V1(int44in);Datumint44in(PG_FUNCTION_ARGS){	char	   *input_string = PG_GETARG_CSTRING(0);	int32	   *result = (int32 *) palloc(4 * sizeof(int32));	int			i;	i = sscanf(input_string,			   "%d, %d, %d, %d",			   &result[0],			   &result[1],			   &result[2],			   &result[3]);	while (i < 4)		result[i++] = 0;	PG_RETURN_POINTER(result);}/* *		int44out		- converts internal form to "num num ..." */PG_FUNCTION_INFO_V1(int44out);Datumint44out(PG_FUNCTION_ARGS){	int32	   *an_array = (int32 *) PG_GETARG_POINTER(0);	char	   *result = (char *) palloc(16 * 4);		/* Allow 14 digits +														 * sign */	int			i;	char	   *walk;	walk = result;	for (i = 0; i < 4; i++)	{		pg_ltoa(an_array[i], walk);		while (*++walk != '\0')			;		*walk++ = ' ';	}	*--walk = '\0';	PG_RETURN_CSTRING(result);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -