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

📄 pltcl.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 5 页
字号:
pltcl_quote(ClientData cdata, Tcl_Interp *interp,			int argc, char *argv[]){	char	   *tmp;	char	   *cp1;	char	   *cp2;	/************************************************************	 * Check call syntax	 ************************************************************/	if (argc != 2)	{		Tcl_SetResult(interp, "syntax error - 'quote string'", TCL_VOLATILE);		return TCL_ERROR;	}	/************************************************************	 * Allocate space for the maximum the string can	 * grow to and initialize pointers	 ************************************************************/	tmp = palloc(strlen(argv[1]) * 2 + 1);	cp1 = argv[1];	cp2 = tmp;	/************************************************************	 * Walk through string and double every quote and backslash	 ************************************************************/	while (*cp1)	{		if (*cp1 == '\'')			*cp2++ = '\'';		else		{			if (*cp1 == '\\')				*cp2++ = '\\';		}		*cp2++ = *cp1++;	}	/************************************************************	 * Terminate the string and set it as result	 ************************************************************/	*cp2 = '\0';	Tcl_SetResult(interp, tmp, TCL_VOLATILE);	pfree(tmp);	return TCL_OK;}/********************************************************************** * pltcl_SPI_exec()		- The builtin SPI_exec command *				  for the safe interpreter **********************************************************************/static intpltcl_SPI_exec(ClientData cdata, Tcl_Interp *interp,			   int argc, char *argv[]){	int			spi_rc;	char		buf[64];	int			count = 0;	char	   *arrayname = NULL;	int			query_idx;	int			i;	int			loop_rc;	int			ntuples;	HeapTuple  *tuples;	TupleDesc	tupdesc = NULL;	sigjmp_buf	save_restart;	char	   *usage = "syntax error - 'SPI_exec "	"?-count n? "	"?-array name? query ?loop body?";	/************************************************************	 * Don't do anything if we are already in restart mode	 ************************************************************/	if (pltcl_restart_in_progress)		return TCL_ERROR;	/************************************************************	 * Check the call syntax and get the count option	 ************************************************************/	if (argc < 2)	{		Tcl_SetResult(interp, usage, TCL_VOLATILE);		return TCL_ERROR;	}	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], "-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;	}	query_idx = i;	if (query_idx >= argc)	{		Tcl_SetResult(interp, usage, TCL_VOLATILE);		return TCL_ERROR;	}	/************************************************************	 * 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));		pltcl_restart_in_progress = 1;		Tcl_SetResult(interp, "Transaction abort", TCL_VOLATILE);		return TCL_ERROR;	}	/************************************************************	 * Execute the query and handle return codes	 ************************************************************/	spi_rc = SPI_exec(argv[query_idx], count);	memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));	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;	}	/************************************************************	 * Again prepare for elog(ERROR)	 ************************************************************/	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 (argc == query_idx + 1)	{		if (ntuples > 0)			pltcl_set_tuple_values(interp, arrayname, 0, tuples[0], tupdesc);		sprintf(buf, "%d", ntuples);		Tcl_SetResult(interp, buf, TCL_VOLATILE);		memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));		return TCL_OK;	}	/************************************************************	 * There is a loop body - process all tuples and evaluate	 * the body on each	 ************************************************************/	query_idx++;	for (i = 0; i < ntuples; i++)	{		pltcl_set_tuple_values(interp, arrayname, i, tuples[i], tupdesc);		loop_rc = Tcl_Eval(interp, argv[query_idx]);		if (loop_rc == TCL_OK)			continue;		if (loop_rc == TCL_CONTINUE)			continue;		if (loop_rc == TCL_RETURN)		{			memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));			return TCL_RETURN;		}		if (loop_rc == TCL_BREAK)			break;		memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));		return TCL_ERROR;	}	/************************************************************	 * Finally return the number of tuples	 ************************************************************/	memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));	sprintf(buf, "%d", ntuples);	Tcl_SetResult(interp, buf, TCL_VOLATILE);	return TCL_OK;}/********************************************************************** * pltcl_SPI_prepare()		- Builtin support for prepared plans *				  The Tcl command SPI_prepare *				  allways saves the plan using *				  SPI_saveplan and returns a key for *				  access. There is no chance to prepare *				  and not save the plan currently. **********************************************************************/static intpltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,				  int argc, char *argv[]){	int			nargs;	char	  **args;	pltcl_query_desc *qdesc;	void	   *plan;	int			i;	HeapTuple	typeTup;	Tcl_HashEntry *hashent;	int			hashnew;	sigjmp_buf	save_restart;	/************************************************************	 * Don't do anything if we are already in restart mode	 ************************************************************/	if (pltcl_restart_in_progress)		return TCL_ERROR;	/************************************************************	 * Check the call syntax	 ************************************************************/	if (argc != 3)	{		Tcl_SetResult(interp, "syntax error - 'SPI_prepare query argtypes'",					  TCL_VOLATILE);		return TCL_ERROR;	}	/************************************************************	 * Split the argument type list	 ************************************************************/	if (Tcl_SplitList(interp, argv[2], &nargs, &args) != TCL_OK)		return TCL_ERROR;	/************************************************************	 * Allocate the new querydesc structure	 ************************************************************/	qdesc = (pltcl_query_desc *) malloc(sizeof(pltcl_query_desc));	sprintf(qdesc->qname, "%lx", (long) qdesc);	qdesc->nargs = nargs;	qdesc->argtypes = (Oid *) malloc(nargs * sizeof(Oid));	qdesc->arginfuncs = (FmgrInfo *) malloc(nargs * sizeof(FmgrInfo));	qdesc->argtypelems = (Oid *) malloc(nargs * sizeof(Oid));	qdesc->argvalues = (Datum *) malloc(nargs * sizeof(Datum));	qdesc->arglen = (int *) malloc(nargs * sizeof(int));	/************************************************************	 * 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));		pltcl_restart_in_progress = 1;		free(qdesc->argtypes);		free(qdesc->arginfuncs);		free(qdesc->argtypelems);		free(qdesc->argvalues);		free(qdesc->arglen);		free(qdesc);		ckfree(args);		return TCL_ERROR;	}	/************************************************************	 * Lookup the argument types by name in the system cache	 * and remember the required information for input conversion	 ************************************************************/	for (i = 0; i < nargs; i++)	{		typeTup = SearchSysCacheTuple(TYPNAME,									  PointerGetDatum(args[i]),									  0, 0, 0);		if (!HeapTupleIsValid(typeTup))			elog(ERROR, "pltcl: Cache lookup of type %s failed", args[i]);		qdesc->argtypes[i] = typeTup->t_data->t_oid;		fmgr_info(((Form_pg_type) GETSTRUCT(typeTup))->typinput,				  &(qdesc->arginfuncs[i]));		qdesc->argtypelems[i] = ((Form_pg_type) GETSTRUCT(typeTup))->typelem;		qdesc->argvalues[i] = (Datum) NULL;		qdesc->arglen[i] = (int) (((Form_pg_type) GETSTRUCT(typeTup))->typlen);	}	/************************************************************	 * Prepare the plan and check for errors	 ************************************************************/	plan = SPI_prepare(argv[1], nargs, qdesc->argtypes);	if (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;			case SPI_ERROR_COPY:				reason = "SPI_ERROR_COPY";				break;			case SPI_ERROR_CURSOR:				reason = "SPI_ERROR_CURSOR";				break;			case SPI_ERROR_TRANSACTION:				reason = "SPI_ERROR_TRANSACTION";				break;			case SPI_ERROR_OPUNKNOWN:				reason = "SPI_ERROR_OPUNKNOWN";				break;			default:				sprintf(buf, "unknown RC %d", SPI_result);				reason = buf;

⌨️ 快捷键说明

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