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

📄 pl_exec.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	foreach(s, stmts)	{		PLpgSQL_stmt *stmt = (PLpgSQL_stmt *) lfirst(s);		int			rc = exec_stmt(estate, stmt);		if (rc != PLPGSQL_RC_OK)			return rc;	}	return PLPGSQL_RC_OK;}/* ---------- * exec_stmt			Distribute one statement to the statements *				type specific execution function. * ---------- */static intexec_stmt(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt){	PLpgSQL_stmt *save_estmt;	int			rc = -1;	save_estmt = estate->err_stmt;	estate->err_stmt = stmt;	CHECK_FOR_INTERRUPTS();	switch (stmt->cmd_type)	{		case PLPGSQL_STMT_BLOCK:			rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt);			break;		case PLPGSQL_STMT_ASSIGN:			rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt);			break;		case PLPGSQL_STMT_PERFORM:			rc = exec_stmt_perform(estate, (PLpgSQL_stmt_perform *) stmt);			break;		case PLPGSQL_STMT_GETDIAG:			rc = exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag *) stmt);			break;		case PLPGSQL_STMT_IF:			rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt);			break;		case PLPGSQL_STMT_LOOP:			rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt);			break;		case PLPGSQL_STMT_WHILE:			rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt);			break;		case PLPGSQL_STMT_FORI:			rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt);			break;		case PLPGSQL_STMT_FORS:			rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt);			break;		case PLPGSQL_STMT_SELECT:			rc = exec_stmt_select(estate, (PLpgSQL_stmt_select *) stmt);			break;		case PLPGSQL_STMT_EXIT:			rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt);			break;		case PLPGSQL_STMT_RETURN:			rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt);			break;		case PLPGSQL_STMT_RETURN_NEXT:			rc = exec_stmt_return_next(estate, (PLpgSQL_stmt_return_next *) stmt);			break;		case PLPGSQL_STMT_RAISE:			rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);			break;		case PLPGSQL_STMT_EXECSQL:			rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt);			break;		case PLPGSQL_STMT_DYNEXECUTE:			rc = exec_stmt_dynexecute(estate, (PLpgSQL_stmt_dynexecute *) stmt);			break;		case PLPGSQL_STMT_DYNFORS:			rc = exec_stmt_dynfors(estate, (PLpgSQL_stmt_dynfors *) stmt);			break;		case PLPGSQL_STMT_OPEN:			rc = exec_stmt_open(estate, (PLpgSQL_stmt_open *) stmt);			break;		case PLPGSQL_STMT_FETCH:			rc = exec_stmt_fetch(estate, (PLpgSQL_stmt_fetch *) stmt);			break;		case PLPGSQL_STMT_CLOSE:			rc = exec_stmt_close(estate, (PLpgSQL_stmt_close *) stmt);			break;		default:			estate->err_stmt = save_estmt;			elog(ERROR, "unrecognized cmdtype: %d", stmt->cmd_type);	}	estate->err_stmt = save_estmt;	return rc;}/* ---------- * exec_stmt_assign			Evaluate an expression and *					put the result into a variable. * ---------- */static intexec_stmt_assign(PLpgSQL_execstate *estate, PLpgSQL_stmt_assign *stmt){	Assert(stmt->varno >= 0);	exec_assign_expr(estate, estate->datums[stmt->varno], stmt->expr);	return PLPGSQL_RC_OK;}/* ---------- * exec_stmt_perform		Evaluate query and discard result (but set *							FOUND depending on whether at least one row *							was returned). * ---------- */static intexec_stmt_perform(PLpgSQL_execstate *estate, PLpgSQL_stmt_perform *stmt){	PLpgSQL_expr *expr = stmt->expr;	(void) exec_run_select(estate, expr, 0, NULL);	exec_set_found(estate, (estate->eval_processed != 0));	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){	ListCell   *lc;	foreach(lc, stmt->diag_items)	{		PLpgSQL_diag_item *diag_item = (PLpgSQL_diag_item *) lfirst(lc);		PLpgSQL_datum *var;		bool		isnull = false;		if (diag_item->target <= 0)			continue;		var = estate->datums[diag_item->target];		if (var == NULL)			continue;		switch (diag_item->kind)		{			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",					 diag_item->kind);		}	}	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;	value = exec_eval_boolean(estate, stmt->cond, &isnull);	exec_eval_cleanup(estate);	if (!isnull && value)	{		if (stmt->true_body != NIL)			return exec_stmts(estate, stmt->true_body);	}	else	{		if (stmt->false_body != NIL)			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){	for (;;)	{		int			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) != 0)					return PLPGSQL_RC_EXIT;				estate->exitlabel = NULL;				return PLPGSQL_RC_OK;			case PLPGSQL_RC_CONTINUE:				if (estate->exitlabel == NULL)					/* anonymous continue, so re-run the loop */					break;				else if (stmt->label != NULL &&						 strcmp(stmt->label, estate->exitlabel) == 0)					/* label matches named continue, so re-run loop */					estate->exitlabel = NULL;				else					/* label doesn't match named continue, so propagate upward */					return PLPGSQL_RC_CONTINUE;				break;			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){	for (;;)	{		int			rc;		bool		value;		bool		isnull;		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_CONTINUE:				if (estate->exitlabel == NULL)					/* anonymous continue, so re-run loop */					break;				else if (stmt->label != NULL &&						 strcmp(stmt->label, estate->exitlabel) == 0)					/* label matches named continue, so re-run loop */					estate->exitlabel = NULL;				else					/* label doesn't match named continue, propagate upward */					return PLPGSQL_RC_CONTINUE;				break;			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;	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->typioparam,							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->typioparam,							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, this is a labelled exit that does not match the			 * current statement's label, if any: return RC_EXIT so that the			 * EXIT continues to propagate up the stack.			 */			break;		}		else if (rc == PLPGSQL_RC_CONTINUE)		{			if (estate->exitlabel == NULL)				/* anonymous continue, so re-run the current loop */				rc = PLPGSQL_RC_OK;			else if (stmt->label != NULL &&					 strcmp(stmt->label, estate->exitlabel) == 0)			{				/* label matches named continue, so re-run loop */				estate->exitlabel = NULL;				rc = PLPGSQL_RC_OK;			}			else			{				/*				 * otherwise, this is a named continue that does not match the				 * current statement's label, if any: return RC_CONTINUE so				 * that the CONTINUE will propagate up the stack.				 */				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;	/*

⌨️ 快捷键说明

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