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

📄 pltcl.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 5 页
字号:
				break;		}		elog(ERROR, "pltcl: SPI_prepare() failed - %s", reason);	}	/************************************************************	 * Save the plan	 ************************************************************/	qdesc->plan = SPI_saveplan(plan);	if (qdesc->plan == NULL)	{		char		buf[128];		char	   *reason;		memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));		switch (SPI_result)		{			case SPI_ERROR_ARGUMENT:				reason = "SPI_ERROR_ARGUMENT";				break;			case SPI_ERROR_UNCONNECTED:				reason = "SPI_ERROR_UNCONNECTED";				break;			default:				sprintf(buf, "unknown RC %d", SPI_result);				reason = buf;				break;		}		elog(ERROR, "pltcl: SPI_saveplan() failed - %s", reason);	}	/************************************************************	 * Insert a hashtable entry for the plan and return	 * the key to the caller	 ************************************************************/	memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));	hashent = Tcl_CreateHashEntry(pltcl_query_hash, qdesc->qname, &hashnew);	Tcl_SetHashValue(hashent, (ClientData) qdesc);	Tcl_SetResult(interp, qdesc->qname, TCL_VOLATILE);	return TCL_OK;}/********************************************************************** * pltcl_SPI_execp()		- Execute a prepared plan **********************************************************************/static intpltcl_SPI_execp(ClientData cdata, Tcl_Interp *interp,				int argc, char *argv[]){	int			spi_rc;	char		buf[64];	int			i,				j;	int			loop_body;	Tcl_HashEntry *hashent;	pltcl_query_desc *qdesc;	char	   *nulls = NULL;	char	   *arrayname = NULL;	int			count = 0;	int			callnargs;	static char **callargs = NULL;	int			loop_rc;	int			ntuples;	HeapTuple  *tuples = NULL;	TupleDesc	tupdesc = NULL;	sigjmp_buf	save_restart;	char	   *usage = "syntax error - 'SPI_execp "	"?-nulls string? ?-count n? "	"?-array name? query ?args? ?loop body?";	/************************************************************	 * Tidy up from an earlier abort	 ************************************************************/	if (callargs != NULL)	{		ckfree(callargs);		callargs = NULL;	}	/************************************************************	 * Don't do anything if we are already in restart mode	 ************************************************************/	if (pltcl_restart_in_progress)		return TCL_ERROR;	/************************************************************	 * Get the options and check syntax	 ************************************************************/	i = 1;	while (i < argc)	{		if (strcmp(argv[i], "-array") == 0)		{			if (++i >= argc)			{				Tcl_SetResult(interp, usage, TCL_VOLATILE);				return TCL_ERROR;			}			arrayname = argv[i++];			continue;		}		if (strcmp(argv[i], "-nulls") == 0)		{			if (++i >= argc)			{				Tcl_SetResult(interp, usage, TCL_VOLATILE);				return TCL_ERROR;			}			nulls = argv[i++];			continue;		}		if (strcmp(argv[i], "-count") == 0)		{			if (++i >= argc)			{				Tcl_SetResult(interp, usage, TCL_VOLATILE);				return TCL_ERROR;			}			if (Tcl_GetInt(interp, argv[i++], &count) != TCL_OK)				return TCL_ERROR;			continue;		}		break;	}	/************************************************************	 * Check minimum call arguments	 ************************************************************/	if (i >= argc)	{		Tcl_SetResult(interp, usage, TCL_VOLATILE);		return TCL_ERROR;	}	/************************************************************	 * Get the prepared plan descriptor by it's key	 ************************************************************/	hashent = Tcl_FindHashEntry(pltcl_query_hash, argv[i++]);	if (hashent == NULL)	{		Tcl_AppendResult(interp, "invalid queryid '", argv[--i], "'", NULL);		return TCL_ERROR;	}	qdesc = (pltcl_query_desc *) Tcl_GetHashValue(hashent);	/************************************************************	 * If a nulls string is given, check for correct length	 ************************************************************/	if (nulls != NULL)	{		if (strlen(nulls) != qdesc->nargs)		{			Tcl_SetResult(interp,				   "length of nulls string doesn't match # of arguments",						  TCL_VOLATILE);			return TCL_ERROR;		}	}	/************************************************************	 * If there was a argtype list on preparation, we need	 * an argument value list now	 ************************************************************/	if (qdesc->nargs > 0)	{		if (i >= argc)		{			Tcl_SetResult(interp, "missing argument list", TCL_VOLATILE);			return TCL_ERROR;		}		/************************************************************		 * Split the argument values		 ************************************************************/		if (Tcl_SplitList(interp, argv[i++], &callnargs, &callargs) != TCL_OK)			return TCL_ERROR;		/************************************************************		 * Check that the # of arguments matches		 ************************************************************/		if (callnargs != qdesc->nargs)		{			Tcl_SetResult(interp,			"argument list length doesn't match # of arguments for query",						  TCL_VOLATILE);			if (callargs != NULL)			{				ckfree(callargs);				callargs = NULL;			}			return TCL_ERROR;		}		/************************************************************		 * Prepare to start a controlled return through all		 * interpreter levels on transaction abort during the		 * parse of the arguments		 ************************************************************/		memcpy(&save_restart, &Warn_restart, sizeof(save_restart));		if (sigsetjmp(Warn_restart, 1) != 0)		{			memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));			for (j = 0; j < callnargs; j++)			{				if (qdesc->arglen[j] < 0 &&					qdesc->argvalues[j] != (Datum) NULL)				{					pfree((char *) (qdesc->argvalues[j]));					qdesc->argvalues[j] = (Datum) NULL;				}			}			ckfree(callargs);			callargs = NULL;			pltcl_restart_in_progress = 1;			Tcl_SetResult(interp, "Transaction abort", TCL_VOLATILE);			return TCL_ERROR;		}		/************************************************************		 * Setup the value array for the SPI_execp() using		 * the type specific input functions		 ************************************************************/		for (j = 0; j < callnargs; j++)		{			qdesc->argvalues[j] = (Datum) (*fmgr_faddr(&qdesc->arginfuncs[j]))				(callargs[j],				 qdesc->argtypelems[j],				 qdesc->arglen[j]);		}		/************************************************************		 * Free the splitted argument value list		 ************************************************************/		memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));		ckfree(callargs);		callargs = NULL;	}	else		callnargs = 0;	/************************************************************	 * Remember the index of the last processed call	 * argument - a loop body for SELECT might follow	 ************************************************************/	loop_body = i;	/************************************************************	 * Prepare to start a controlled return through all	 * interpreter levels on transaction abort	 ************************************************************/	memcpy(&save_restart, &Warn_restart, sizeof(save_restart));	if (sigsetjmp(Warn_restart, 1) != 0)	{		memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));		for (j = 0; j < callnargs; j++)		{			if (qdesc->arglen[j] < 0 && qdesc->argvalues[j] != (Datum) NULL)			{				pfree((char *) (qdesc->argvalues[j]));				qdesc->argvalues[j] = (Datum) NULL;			}		}		pltcl_restart_in_progress = 1;		Tcl_SetResult(interp, "Transaction abort", TCL_VOLATILE);		return TCL_ERROR;	}	/************************************************************	 * Execute the plan	 ************************************************************/	spi_rc = SPI_execp(qdesc->plan, qdesc->argvalues, nulls, count);	memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));	/************************************************************	 * For varlena data types, free the argument values	 ************************************************************/	for (j = 0; j < callnargs; j++)	{		if (qdesc->arglen[j] < 0 && qdesc->argvalues[j] != (Datum) NULL)		{			pfree((char *) (qdesc->argvalues[j]));			qdesc->argvalues[j] = (Datum) NULL;		}	}	/************************************************************	 * Check the return code from SPI_execp()	 ************************************************************/	switch (spi_rc)	{		case SPI_OK_UTILITY:			Tcl_SetResult(interp, "0", TCL_VOLATILE);			return TCL_OK;		case SPI_OK_SELINTO:		case SPI_OK_INSERT:		case SPI_OK_DELETE:		case SPI_OK_UPDATE:			sprintf(buf, "%d", SPI_processed);			Tcl_SetResult(interp, buf, TCL_VOLATILE);			return TCL_OK;		case SPI_OK_SELECT:			break;		case SPI_ERROR_ARGUMENT:			Tcl_SetResult(interp,						  "pltcl: SPI_exec() failed - SPI_ERROR_ARGUMENT",						  TCL_VOLATILE);			return TCL_ERROR;		case SPI_ERROR_UNCONNECTED:			Tcl_SetResult(interp,					  "pltcl: SPI_exec() failed - SPI_ERROR_UNCONNECTED",						  TCL_VOLATILE);			return TCL_ERROR;		case SPI_ERROR_COPY:			Tcl_SetResult(interp,						  "pltcl: SPI_exec() failed - SPI_ERROR_COPY",						  TCL_VOLATILE);			return TCL_ERROR;		case SPI_ERROR_CURSOR:			Tcl_SetResult(interp,						  "pltcl: SPI_exec() failed - SPI_ERROR_CURSOR",						  TCL_VOLATILE);			return TCL_ERROR;		case SPI_ERROR_TRANSACTION:			Tcl_SetResult(interp,					  "pltcl: SPI_exec() failed - SPI_ERROR_TRANSACTION",						  TCL_VOLATILE);			return TCL_ERROR;		case SPI_ERROR_OPUNKNOWN:			Tcl_SetResult(interp,						"pltcl: SPI_exec() failed - SPI_ERROR_OPUNKNOWN",						  TCL_VOLATILE);			return TCL_ERROR;		default:			sprintf(buf, "%d", spi_rc);			Tcl_AppendResult(interp, "pltcl: SPI_exec() failed - ",							 "unknown RC ", buf, NULL);			return TCL_ERROR;	}	/************************************************************	 * Only SELECT queries fall through to here - remember the	 * tuples we got	 ************************************************************/	ntuples = SPI_processed;	if (ntuples > 0)	{		tuples = SPI_tuptable->vals;		tupdesc = SPI_tuptable->tupdesc;	}	/************************************************************	 * Prepare to start a controlled return through all	 * interpreter levels on transaction abort during	 * the ouput conversions of the results	 ************************************************************/	memcpy(&save_restart, &Warn_restart, sizeof(save_restart));	if (sigsetjmp(Warn_restart, 1) != 0)	{		memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));		pltcl_restart_in_progress = 1;		Tcl_SetResult(interp, "Transaction abort", TCL_VOLATILE);		return TCL_ERROR;	}	/************************************************************	 * If there is no loop body given, just set the variables	 * from the first tuple (if any) and return the number of	 * tuples selected	 ************************************************************/	if (loop_body >= argc)	{		if (ntuples > 0)			pltcl_set_tuple_values(interp, arrayname, 0, tuples[0], tupdesc);		memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));		sprintf(buf, "%d", ntuples);		Tcl_SetResult(interp, buf, TCL_VOLATILE);		return TCL_OK;	}	/************************************************************	 * There is a loop body - process all tuples and evaluate	 * the body on each	 ************************************************************/	for (i = 0; i < ntuples; i++)	{		pltcl_set_tuple_values(interp, arrayname, i, tuples[i], tupdesc);		loop_rc = Tcl_Eval(in

⌨️ 快捷键说明

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