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

📄 pl_exec.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 5 页
字号:
	exec_eval_cleanup(estate);	return PLPGSQL_RC_OK;}/* ---------- * exec_stmt_getdiag					Put internal PG information into *										specified variables. * ---------- */static intexec_stmt_getdiag(PLpgSQL_execstate * estate, PLpgSQL_stmt_getdiag * stmt){	int			i;	PLpgSQL_datum *var;	bool		isnull = false;	for (i = 0; i < stmt->ndtitems; i++)	{		PLpgSQL_diag_item *dtitem = &stmt->dtitems[i];		if (dtitem->target <= 0)			continue;		var = (estate->datums[dtitem->target]);		if (var == NULL)			continue;		switch (dtitem->item)		{			case PLPGSQL_GETDIAG_ROW_COUNT:				exec_assign_value(estate, var,								  UInt32GetDatum(estate->eval_processed),								  INT4OID, &isnull);				break;			case PLPGSQL_GETDIAG_RESULT_OID:				exec_assign_value(estate, var,								  ObjectIdGetDatum(estate->eval_lastoid),								  OIDOID, &isnull);				break;			default:				elog(ERROR, "unrecognized attribute request: %d",					 dtitem->item);		}	}	return PLPGSQL_RC_OK;}/* ---------- * exec_stmt_if				Evaluate a bool expression and *					execute the true or false body *					conditionally. * ---------- */static intexec_stmt_if(PLpgSQL_execstate * estate, PLpgSQL_stmt_if * stmt){	bool		value;	bool		isnull = false;	value = exec_eval_boolean(estate, stmt->cond, &isnull);	exec_eval_cleanup(estate);	if (!isnull && value)	{		if (stmt->true_body != NULL)			return exec_stmts(estate, stmt->true_body);	}	else	{		if (stmt->false_body != NULL)			return exec_stmts(estate, stmt->false_body);	}	return PLPGSQL_RC_OK;}/* ---------- * exec_stmt_loop			Loop over statements until *					an exit occurs. * ---------- */static intexec_stmt_loop(PLpgSQL_execstate * estate, PLpgSQL_stmt_loop * stmt){	int			rc;	for (;;)	{		rc = exec_stmts(estate, stmt->body);		switch (rc)		{			case PLPGSQL_RC_OK:				break;			case PLPGSQL_RC_EXIT:				if (estate->exitlabel == NULL)					return PLPGSQL_RC_OK;				if (stmt->label == NULL)					return PLPGSQL_RC_EXIT;				if (strcmp(stmt->label, estate->exitlabel))					return PLPGSQL_RC_EXIT;				estate->exitlabel = NULL;				return PLPGSQL_RC_OK;			case PLPGSQL_RC_RETURN:				return PLPGSQL_RC_RETURN;			default:				elog(ERROR, "unrecognized rc: %d", rc);		}	}	return PLPGSQL_RC_OK;}/* ---------- * exec_stmt_while			Loop over statements as long *					as an expression evaluates to *					true or an exit occurs. * ---------- */static intexec_stmt_while(PLpgSQL_execstate * estate, PLpgSQL_stmt_while * stmt){	bool		value;	bool		isnull = false;	int			rc;	for (;;)	{		value = exec_eval_boolean(estate, stmt->cond, &isnull);		exec_eval_cleanup(estate);		if (isnull || !value)			break;		rc = exec_stmts(estate, stmt->body);		switch (rc)		{			case PLPGSQL_RC_OK:				break;			case PLPGSQL_RC_EXIT:				if (estate->exitlabel == NULL)					return PLPGSQL_RC_OK;				if (stmt->label == NULL)					return PLPGSQL_RC_EXIT;				if (strcmp(stmt->label, estate->exitlabel))					return PLPGSQL_RC_EXIT;				estate->exitlabel = NULL;				return PLPGSQL_RC_OK;			case PLPGSQL_RC_RETURN:				return PLPGSQL_RC_RETURN;			default:				elog(ERROR, "unrecognized rc: %d", rc);		}	}	return PLPGSQL_RC_OK;}/* ---------- * exec_stmt_fori			Iterate an integer variable *					from a lower to an upper value. *					Loop can be left with exit. * ---------- */static intexec_stmt_fori(PLpgSQL_execstate * estate, PLpgSQL_stmt_fori * stmt){	PLpgSQL_var *var;	Datum		value;	Oid			valtype;	bool		isnull = false;	bool		found = false;	int			rc = PLPGSQL_RC_OK;	var = (PLpgSQL_var *) (estate->datums[stmt->var->varno]);	/*	 * Get the value of the lower bound into the loop var	 */	value = exec_eval_expr(estate, stmt->lower, &isnull, &valtype);	value = exec_cast_value(value, valtype, var->datatype->typoid,							&(var->datatype->typinput),							var->datatype->typelem,							var->datatype->atttypmod, &isnull);	if (isnull)		ereport(ERROR,				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),				 errmsg("lower bound of FOR loop cannot be NULL")));	var->value = value;	var->isnull = false;	exec_eval_cleanup(estate);	/*	 * Get the value of the upper bound	 */	value = exec_eval_expr(estate, stmt->upper, &isnull, &valtype);	value = exec_cast_value(value, valtype, var->datatype->typoid,							&(var->datatype->typinput),							var->datatype->typelem,							var->datatype->atttypmod, &isnull);	if (isnull)		ereport(ERROR,				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),				 errmsg("upper bound of FOR loop cannot be NULL")));	exec_eval_cleanup(estate);	/*	 * Now do the loop	 */	for (;;)	{		/*		 * Check bounds		 */		if (stmt->reverse)		{			if ((int4) (var->value) < (int4) value)				break;		}		else		{			if ((int4) (var->value) > (int4) value)				break;		}		found = true;			/* looped at least once */		/*		 * Execute the statements		 */		rc = exec_stmts(estate, stmt->body);		if (rc == PLPGSQL_RC_RETURN)			break;				/* return from function */		else if (rc == PLPGSQL_RC_EXIT)		{			if (estate->exitlabel == NULL)				/* unlabelled exit, finish the current loop */				rc = PLPGSQL_RC_OK;			else if (stmt->label != NULL &&					 strcmp(stmt->label, estate->exitlabel) == 0)			{				/* labelled exit, matches the current stmt's label */				estate->exitlabel = NULL;				rc = PLPGSQL_RC_OK;			}			/*			 * otherwise, we processed a labelled exit that does not match			 * the current statement's label, if any: return RC_EXIT so			 * that the EXIT continues to recurse upward.			 */			break;		}		/*		 * Increase/decrease loop var		 */		if (stmt->reverse)			var->value--;		else			var->value++;	}	/*	 * Set the FOUND variable to indicate the result of executing the loop	 * (namely, whether we looped one or more times). This must be set	 * here so that it does not interfere with the value of the FOUND	 * variable inside the loop processing itself.	 */	exec_set_found(estate, found);	return rc;}/* ---------- * exec_stmt_fors			Execute a query, assign each *					tuple to a record or row and *					execute a group of statements *					for it. * ---------- */static intexec_stmt_fors(PLpgSQL_execstate * estate, PLpgSQL_stmt_fors * stmt){	PLpgSQL_rec *rec = NULL;	PLpgSQL_row *row = NULL;	SPITupleTable *tuptab;	Portal		portal;	bool		found = false;	int			rc = PLPGSQL_RC_OK;	int			i;	int			n;	/*	 * Determine if we assign to a record or a row	 */	if (stmt->rec != NULL)		rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->recno]);	else if (stmt->row != NULL)		row = (PLpgSQL_row *) (estate->datums[stmt->row->rowno]);	else		elog(ERROR, "unsupported target");	/*	 * Open the implicit cursor for the statement and fetch the initial 10	 * rows.	 */	exec_run_select(estate, stmt->query, 0, &portal);	SPI_cursor_fetch(portal, true, 10);	tuptab = SPI_tuptable;	n = SPI_processed;	/*	 * If the query didn't return any rows, set the target to NULL and	 * return with FOUND = false.	 */	if (n == 0)		exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);	else		found = true;			/* processed at least one tuple */	/*	 * Now do the loop	 */	while (n > 0)	{		for (i = 0; i < n; i++)		{			/*			 * Assign the tuple to the target			 */			exec_move_row(estate, rec, row, tuptab->vals[i], tuptab->tupdesc);			/*			 * Execute the statements			 */			rc = exec_stmts(estate, stmt->body);			if (rc != PLPGSQL_RC_OK)			{				/*				 * We're aborting the loop, so cleanup and set FOUND.				 * (This code should match the code after the loop.)				 */				SPI_freetuptable(tuptab);				SPI_cursor_close(portal);				exec_set_found(estate, found);				if (rc == PLPGSQL_RC_EXIT)				{					if (estate->exitlabel == NULL)						/* unlabelled exit, finish the current loop */						rc = PLPGSQL_RC_OK;					else if (stmt->label != NULL &&							 strcmp(stmt->label, estate->exitlabel) == 0)					{						/* labelled exit, matches the current stmt's label */						estate->exitlabel = NULL;						rc = PLPGSQL_RC_OK;					}					/*					 * otherwise, we processed a labelled exit that does					 * not match the current statement's label, if any:					 * return RC_EXIT so that the EXIT continues to					 * recurse upward.					 */				}				return rc;			}		}		SPI_freetuptable(tuptab);		/*		 * Fetch the next 50 tuples		 */		SPI_cursor_fetch(portal, true, 50);		n = SPI_processed;		tuptab = SPI_tuptable;	}	/*	 * Release last group of tuples	 */	SPI_freetuptable(tuptab);	/*	 * Close the implicit cursor	 */	SPI_cursor_close(portal);	/*	 * Set the FOUND variable to indicate the result of executing the loop	 * (namely, whether we looped one or more times). This must be set	 * here so that it does not interfere with the value of the FOUND	 * variable inside the loop processing itself.	 */	exec_set_found(estate, found);	return rc;}/* ---------- * exec_stmt_select			Run a query and assign the first *					row to a record or rowtype. * ---------- */static intexec_stmt_select(PLpgSQL_execstate * estate, PLpgSQL_stmt_select * stmt){	PLpgSQL_rec *rec = NULL;	PLpgSQL_row *row = NULL;	SPITupleTable *tuptab;	uint32		n;	/*	 * Initialize the global found variable to false	 */	exec_set_found(estate, false);	/*	 * Determine if we assign to a record or a row	 */	if (stmt->rec != NULL)		rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->recno]);	else if (stmt->row != NULL)		row = (PLpgSQL_row *) (estate->datums[stmt->row->rowno]);	else		elog(ERROR, "unsupported target");	/*	 * Run the query	 */	exec_run_select(estate, stmt->query, 1, NULL);	tuptab = estate->eval_tuptable;	n = estate->eval_processed;	/*	 * If the query didn't return any row, set the target to NULL and	 * return.	 */	if (n == 0)	{		exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);		exec_eval_cleanup(estate);		return PLPGSQL_RC_OK;	}	/*	 * Put the result into the target and set found to true	 */	exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);	exec_set_found(estate, true);	exec_eval_cleanup(estate);	return PLPGSQL_RC_OK;}/* ---------- * exec_stmt_exit			Start exiting loop(s) or blocks * ---------- */static intexec_stmt_exit(PLpgSQL_execstate * estate, PLpgSQL_stmt_exit * stmt){	/*	 * If the exit has a condition, check that it's true	 */	if (stmt->cond != NULL)	{		bool		value;		bool		isnull = false;		value = exec_eval_boolean(estate, stmt->cond, &isnull);		exec_eval_cleanup(estate);		if (isnull || !value)			return PLPGSQL_RC_OK;	}	estate->exitlabel = stmt->label;	return PLPGSQL_RC_EXIT;}/* ---------- * exec_stmt_return			Evaluate an expression and start *					returning from the function. * ---------- */static intexec_stmt_return(PLpgSQL_execstate * estate, PLpgSQL_stmt_return * stmt){	/*	 * If processing a set-returning PL/PgSQL function, the final RETURN	 * indicates that the function is finished producing tuples.  The rest	 * of the work will be done at the top level.	 */	if (estate->retisset)		return PLPGSQL_RC_RETURN;	if (estate->retistuple)	{		/* initialize for null result tuple */

⌨️ 快捷键说明

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