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

📄 pltcl.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 5 页
字号:
							  "foreach v $args {\n"							  "  incr i\n"							  "  set $i $v\n"							  "}\n"							  "unset i v\n\n", -1);		}		/************************************************************		 * Add user's function definition to proc body		 ************************************************************/		proc_source = DatumGetCString(DirectFunctionCall1(textout,								  PointerGetDatum(&procStruct->prosrc)));		UTF_BEGIN;		Tcl_DStringAppend(&proc_internal_body, UTF_E2U(proc_source), -1);		UTF_END;		pfree(proc_source);		Tcl_DStringAppendElement(&proc_internal_def,								 Tcl_DStringValue(&proc_internal_body));		Tcl_DStringFree(&proc_internal_body);		/************************************************************		 * Create the procedure in the interpreter		 ************************************************************/		tcl_rc = Tcl_GlobalEval(interp,								Tcl_DStringValue(&proc_internal_def));		Tcl_DStringFree(&proc_internal_def);		if (tcl_rc != TCL_OK)		{			free(prodesc->proname);			free(prodesc);			elog(ERROR, "could not create internal procedure \"%s\": %s",				 internal_proname, interp->result);		}		/************************************************************		 * Add the proc description block to the hashtable		 ************************************************************/		hashent = Tcl_CreateHashEntry(pltcl_proc_hash,									  prodesc->proname, &hashnew);		Tcl_SetHashValue(hashent, (ClientData) prodesc);	}	ReleaseSysCache(procTup);	return prodesc;}/********************************************************************** * pltcl_elog()		- elog() support for PLTcl **********************************************************************/static intpltcl_elog(ClientData cdata, Tcl_Interp *interp,		   int argc, CONST84 char *argv[]){	volatile int level;	sigjmp_buf	save_restart;	/************************************************************	 * Suppress messages during the restart process	 ************************************************************/	if (pltcl_restart_in_progress)		return TCL_ERROR;	if (argc != 3)	{		Tcl_SetResult(interp, "syntax error - 'elog level msg'",					  TCL_VOLATILE);		return TCL_ERROR;	}	if (strcmp(argv[1], "DEBUG") == 0)		level = DEBUG2;	else if (strcmp(argv[1], "LOG") == 0)		level = LOG;	else if (strcmp(argv[1], "INFO") == 0)		level = INFO;	else if (strcmp(argv[1], "NOTICE") == 0)		level = NOTICE;	else if (strcmp(argv[1], "WARNING") == 0)		level = WARNING;	else if (strcmp(argv[1], "ERROR") == 0)		level = ERROR;	else if (strcmp(argv[1], "FATAL") == 0)		level = FATAL;	else	{		Tcl_AppendResult(interp, "Unknown elog level '", argv[1],						 "'", NULL);		return TCL_ERROR;	}	/************************************************************	 * Catch the longjmp from elog() and begin a controlled	 * return though all interpreter levels if it happens	 ************************************************************/	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;		return TCL_ERROR;	}	/************************************************************	 * Call elog(), restore the original restart address	 * and return to the caller (if no longjmp)	 ************************************************************/	UTF_BEGIN;	elog(level, "%s", UTF_U2E(argv[2]));	UTF_END;	memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));	return TCL_OK;}/********************************************************************** * pltcl_quote()	- quote literal strings that are to *			  be used in SPI_exec query strings **********************************************************************/static intpltcl_quote(ClientData cdata, Tcl_Interp *interp,			int argc, CONST84 char *argv[]){	char	   *tmp;	const 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_argisnull()	- determine if a specific argument is NULL **********************************************************************/static intpltcl_argisnull(ClientData cdata, Tcl_Interp *interp,				int argc, CONST84 char *argv[]){	int			argno;	FunctionCallInfo fcinfo = pltcl_current_fcinfo;	/************************************************************	 * Check call syntax	 ************************************************************/	if (argc != 2)	{		Tcl_SetResult(interp, "syntax error - 'argisnull argno'", TCL_VOLATILE);		return TCL_ERROR;	}	/************************************************************	 * Check that we're called as a normal function	 ************************************************************/	if (fcinfo == NULL)	{		Tcl_SetResult(interp, "argisnull cannot be used in triggers",					  TCL_VOLATILE);		return TCL_ERROR;	}	/************************************************************	 * Get the argument number	 ************************************************************/	if (Tcl_GetInt(interp, argv[1], &argno) != TCL_OK)		return TCL_ERROR;	/************************************************************	 * Check that the argno is valid	 ************************************************************/	argno--;	if (argno < 0 || argno >= fcinfo->nargs)	{		Tcl_SetResult(interp, "argno out of range", TCL_VOLATILE);		return TCL_ERROR;	}	/************************************************************	 * Get the requested NULL state	 ************************************************************/	if (PG_ARGISNULL(argno))		Tcl_SetResult(interp, "1", TCL_VOLATILE);	else		Tcl_SetResult(interp, "0", TCL_VOLATILE);	return TCL_OK;}/********************************************************************** * pltcl_returnnull()	- Cause a NULL return from a function **********************************************************************/static intpltcl_returnnull(ClientData cdata, Tcl_Interp *interp,				 int argc, CONST84 char *argv[]){	FunctionCallInfo fcinfo = pltcl_current_fcinfo;	/************************************************************	 * Check call syntax	 ************************************************************/	if (argc != 1)	{		Tcl_SetResult(interp, "syntax error - 'return_null'", TCL_VOLATILE);		return TCL_ERROR;	}	/************************************************************	 * Check that we're called as a normal function	 ************************************************************/	if (fcinfo == NULL)	{		Tcl_SetResult(interp, "return_null cannot be used in triggers",					  TCL_VOLATILE);		return TCL_ERROR;	}	/************************************************************	 * Set the NULL return flag and cause Tcl to return from the	 * procedure.	 ************************************************************/	fcinfo->isnull = true;	return TCL_RETURN;}/********************************************************************** * pltcl_SPI_exec()		- The builtin SPI_exec command *				  for the Tcl interpreter **********************************************************************/static intpltcl_SPI_exec(ClientData cdata, Tcl_Interp *interp,			   int argc, CONST84 char *argv[]){	int			spi_rc;	char		buf[64];	int			count = 0;	CONST84 char *volatile arrayname = NULL;	volatile int query_idx;	int			i;	int			loop_rc;	int			ntuples;	HeapTuple  *volatile tuples;	volatile TupleDesc tupdesc = NULL;	SPITupleTable *tuptable;	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	 ************************************************************/	UTF_BEGIN;	spi_rc = SPI_exec(UTF_U2E(argv[query_idx]), count);	UTF_END;	memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));	switch (spi_rc)	{		case SPI_OK_UTILITY:			Tcl_SetResult(interp, "0", TCL_VOLATILE);			SPI_freetuptable(SPI_tuptable);			return TCL_OK;		case SPI_OK_SELINTO:		case SPI_OK_INSERT:		case SPI_OK_DELETE:		case SPI_OK_UPDATE:			snprintf(buf, sizeof(buf), "%d", SPI_processed);			Tcl_SetResult(interp, buf, TCL_VOLATILE);			SPI_freetuptable(SPI_tuptable);			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,

⌨️ 快捷键说明

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