mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Factor out duplicate code for computing values of PLpgSQL_datum items.
This is to help localize the changes needed for adding a new kind of PLpgSQL_datum (like, say, an array element...)
This commit is contained in:
		@@ -3,7 +3,7 @@
 | 
				
			|||||||
 *			  procedural language
 | 
					 *			  procedural language
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.54 2003/01/31 00:31:53 tgl Exp $
 | 
					 *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.55 2003/03/25 00:34:23 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	  This software is copyrighted by Jan Wieck - Hamburg.
 | 
					 *	  This software is copyrighted by Jan Wieck - Hamburg.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -696,7 +696,7 @@ plpgsql_parse_dblword(char *word)
 | 
				
			|||||||
				new = malloc(sizeof(PLpgSQL_recfield));
 | 
									new = malloc(sizeof(PLpgSQL_recfield));
 | 
				
			||||||
				new->dtype = PLPGSQL_DTYPE_RECFIELD;
 | 
									new->dtype = PLPGSQL_DTYPE_RECFIELD;
 | 
				
			||||||
				new->fieldname = strdup(cp[1]);
 | 
									new->fieldname = strdup(cp[1]);
 | 
				
			||||||
				new->recno = ns->itemno;
 | 
									new->recparentno = ns->itemno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				plpgsql_adddatum((PLpgSQL_datum *) new);
 | 
									plpgsql_adddatum((PLpgSQL_datum *) new);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -799,7 +799,7 @@ plpgsql_parse_tripword(char *word)
 | 
				
			|||||||
				new = malloc(sizeof(PLpgSQL_recfield));
 | 
									new = malloc(sizeof(PLpgSQL_recfield));
 | 
				
			||||||
				new->dtype = PLPGSQL_DTYPE_RECFIELD;
 | 
									new->dtype = PLPGSQL_DTYPE_RECFIELD;
 | 
				
			||||||
				new->fieldname = strdup(cp[2]);
 | 
									new->fieldname = strdup(cp[2]);
 | 
				
			||||||
				new->recno = ns->itemno;
 | 
									new->recparentno = ns->itemno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				plpgsql_adddatum((PLpgSQL_datum *) new);
 | 
									plpgsql_adddatum((PLpgSQL_datum *) new);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@
 | 
				
			|||||||
 *			  procedural language
 | 
					 *			  procedural language
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.81 2003/03/09 02:19:13 tgl Exp $
 | 
					 *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.82 2003/03/25 00:34:23 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	  This software is copyrighted by Jan Wieck - Hamburg.
 | 
					 *	  This software is copyrighted by Jan Wieck - Hamburg.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -130,6 +130,12 @@ static void exec_assign_expr(PLpgSQL_execstate * estate,
 | 
				
			|||||||
static void exec_assign_value(PLpgSQL_execstate * estate,
 | 
					static void exec_assign_value(PLpgSQL_execstate * estate,
 | 
				
			||||||
				  PLpgSQL_datum * target,
 | 
									  PLpgSQL_datum * target,
 | 
				
			||||||
				  Datum value, Oid valtype, bool *isNull);
 | 
									  Datum value, Oid valtype, bool *isNull);
 | 
				
			||||||
 | 
					static void exec_eval_datum(PLpgSQL_execstate *estate,
 | 
				
			||||||
 | 
												PLpgSQL_datum *datum,
 | 
				
			||||||
 | 
												Oid expectedtypeid,
 | 
				
			||||||
 | 
												Oid *typeid,
 | 
				
			||||||
 | 
												Datum *value,
 | 
				
			||||||
 | 
												bool *isnull);
 | 
				
			||||||
static Datum exec_eval_expr(PLpgSQL_execstate * estate,
 | 
					static Datum exec_eval_expr(PLpgSQL_execstate * estate,
 | 
				
			||||||
			   PLpgSQL_expr * expr,
 | 
								   PLpgSQL_expr * expr,
 | 
				
			||||||
			   bool *isNull,
 | 
								   bool *isNull,
 | 
				
			||||||
@@ -1766,6 +1772,9 @@ exec_init_tuple_store(PLpgSQL_execstate * estate)
 | 
				
			|||||||
static int
 | 
					static int
 | 
				
			||||||
exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt)
 | 
					exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						Oid			paramtypeid;
 | 
				
			||||||
 | 
						Datum		paramvalue;
 | 
				
			||||||
 | 
						bool		paramisnull;
 | 
				
			||||||
	HeapTuple	typetup;
 | 
						HeapTuple	typetup;
 | 
				
			||||||
	Form_pg_type typeStruct;
 | 
						Form_pg_type typeStruct;
 | 
				
			||||||
	FmgrInfo	finfo_output;
 | 
						FmgrInfo	finfo_output;
 | 
				
			||||||
@@ -1774,10 +1783,6 @@ exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt)
 | 
				
			|||||||
	char		c[2] = {0, 0};
 | 
						char		c[2] = {0, 0};
 | 
				
			||||||
	char	   *cp;
 | 
						char	   *cp;
 | 
				
			||||||
	PLpgSQL_dstring ds;
 | 
						PLpgSQL_dstring ds;
 | 
				
			||||||
	PLpgSQL_var *var;
 | 
					 | 
				
			||||||
	PLpgSQL_rec *rec;
 | 
					 | 
				
			||||||
	PLpgSQL_recfield *recfield;
 | 
					 | 
				
			||||||
	int			fno;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	plpgsql_dstring_init(&ds);
 | 
						plpgsql_dstring_init(&ds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1804,83 +1809,31 @@ exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt)
 | 
				
			|||||||
				plpgsql_dstring_append(&ds, c);
 | 
									plpgsql_dstring_append(&ds, c);
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			switch (estate->datums[stmt->params[pidx]]->dtype)
 | 
								exec_eval_datum(estate, estate->datums[stmt->params[pidx]],
 | 
				
			||||||
 | 
												InvalidOid,
 | 
				
			||||||
 | 
												¶mtypeid, ¶mvalue, ¶misnull);
 | 
				
			||||||
 | 
								if (paramisnull)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				case PLPGSQL_DTYPE_VAR:
 | 
					 | 
				
			||||||
					var = (PLpgSQL_var *)
 | 
					 | 
				
			||||||
						(estate->datums[stmt->params[pidx]]);
 | 
					 | 
				
			||||||
					if (var->isnull)
 | 
					 | 
				
			||||||
				extval = "<NULL>";
 | 
									extval = "<NULL>";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				typetup = SearchSysCache(TYPEOID,
 | 
									typetup = SearchSysCache(TYPEOID,
 | 
				
			||||||
								 ObjectIdGetDatum(var->datatype->typoid),
 | 
															 ObjectIdGetDatum(paramtypeid),
 | 
				
			||||||
										 0, 0, 0);
 | 
															 0, 0, 0);
 | 
				
			||||||
				if (!HeapTupleIsValid(typetup))
 | 
									if (!HeapTupleIsValid(typetup))
 | 
				
			||||||
					elog(ERROR, "cache lookup for type %u failed",
 | 
										elog(ERROR, "cache lookup for type %u failed",
 | 
				
			||||||
								 var->datatype->typoid);
 | 
											 paramtypeid);
 | 
				
			||||||
				typeStruct = (Form_pg_type) GETSTRUCT(typetup);
 | 
									typeStruct = (Form_pg_type) GETSTRUCT(typetup);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				fmgr_info(typeStruct->typoutput, &finfo_output);
 | 
									fmgr_info(typeStruct->typoutput, &finfo_output);
 | 
				
			||||||
				extval = DatumGetCString(FunctionCall3(&finfo_output,
 | 
									extval = DatumGetCString(FunctionCall3(&finfo_output,
 | 
				
			||||||
															   var->value,
 | 
																		   paramvalue,
 | 
				
			||||||
													   ObjectIdGetDatum(typeStruct->typelem),
 | 
																		   ObjectIdGetDatum(typeStruct->typelem),
 | 
				
			||||||
							   Int32GetDatum(var->datatype->atttypmod)));
 | 
																		   Int32GetDatum(-1)));
 | 
				
			||||||
				ReleaseSysCache(typetup);
 | 
									ReleaseSysCache(typetup);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			plpgsql_dstring_append(&ds, extval);
 | 
								plpgsql_dstring_append(&ds, extval);
 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case PLPGSQL_DTYPE_RECFIELD:
 | 
					 | 
				
			||||||
					recfield = (PLpgSQL_recfield *)
 | 
					 | 
				
			||||||
						(estate->datums[stmt->params[pidx]]);
 | 
					 | 
				
			||||||
					rec = (PLpgSQL_rec *)
 | 
					 | 
				
			||||||
						(estate->datums[recfield->recno]);
 | 
					 | 
				
			||||||
					if (!HeapTupleIsValid(rec->tup))
 | 
					 | 
				
			||||||
						extval = "<NULL>";
 | 
					 | 
				
			||||||
					else
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
 | 
					 | 
				
			||||||
						if (fno == SPI_ERROR_NOATTRIBUTE)
 | 
					 | 
				
			||||||
							elog(ERROR, "record \"%s\" has no field named \"%s\"", rec->refname, recfield->fieldname);
 | 
					 | 
				
			||||||
						extval = SPI_getvalue(rec->tup, rec->tupdesc, fno);
 | 
					 | 
				
			||||||
						if (extval == NULL)
 | 
					 | 
				
			||||||
							extval = "<NULL>";
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					plpgsql_dstring_append(&ds, extval);
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				case PLPGSQL_DTYPE_TRIGARG:
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						PLpgSQL_trigarg *trigarg;
 | 
					 | 
				
			||||||
						int			value;
 | 
					 | 
				
			||||||
						Oid			valtype;
 | 
					 | 
				
			||||||
						bool		valisnull = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						trigarg = (PLpgSQL_trigarg *)
 | 
					 | 
				
			||||||
							(estate->datums[stmt->params[pidx]]);
 | 
					 | 
				
			||||||
						value = (int) exec_eval_expr(estate, trigarg->argnum,
 | 
					 | 
				
			||||||
												   &valisnull, &valtype);
 | 
					 | 
				
			||||||
						exec_eval_cleanup(estate);
 | 
					 | 
				
			||||||
						if (valisnull)
 | 
					 | 
				
			||||||
							extval = "<INDEX_IS_NULL>";
 | 
					 | 
				
			||||||
						else
 | 
					 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
							if (value < 0 || value >= estate->trig_nargs)
 | 
					 | 
				
			||||||
								extval = "<OUT_OF_RANGE>";
 | 
					 | 
				
			||||||
							else
 | 
					 | 
				
			||||||
								extval = DatumGetCString(DirectFunctionCall1(textout,
 | 
					 | 
				
			||||||
											  estate->trig_argv[value]));
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
						plpgsql_dstring_append(&ds, extval);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				default:
 | 
					 | 
				
			||||||
					c[0] = '?';
 | 
					 | 
				
			||||||
					plpgsql_dstring_append(&ds, c);
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			pidx++;
 | 
								pidx++;
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -1985,11 +1938,7 @@ static void
 | 
				
			|||||||
exec_prepare_plan(PLpgSQL_execstate * estate,
 | 
					exec_prepare_plan(PLpgSQL_execstate * estate,
 | 
				
			||||||
				  PLpgSQL_expr * expr)
 | 
									  PLpgSQL_expr * expr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	PLpgSQL_var *var;
 | 
					 | 
				
			||||||
	PLpgSQL_rec *rec;
 | 
					 | 
				
			||||||
	PLpgSQL_recfield *recfield;
 | 
					 | 
				
			||||||
	int			i;
 | 
						int			i;
 | 
				
			||||||
	int			fno;
 | 
					 | 
				
			||||||
	_SPI_plan  *spi_plan;
 | 
						_SPI_plan  *spi_plan;
 | 
				
			||||||
	void	   *plan;
 | 
						void	   *plan;
 | 
				
			||||||
	Oid		   *argtypes;
 | 
						Oid		   *argtypes;
 | 
				
			||||||
@@ -2004,33 +1953,12 @@ exec_prepare_plan(PLpgSQL_execstate * estate,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < expr->nparams; i++)
 | 
						for (i = 0; i < expr->nparams; i++)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		switch (estate->datums[expr->params[i]]->dtype)
 | 
							Datum	paramval;
 | 
				
			||||||
		{
 | 
							bool	paramisnull;
 | 
				
			||||||
			case PLPGSQL_DTYPE_VAR:
 | 
					 | 
				
			||||||
				var = (PLpgSQL_var *) (estate->datums[expr->params[i]]);
 | 
					 | 
				
			||||||
				argtypes[i] = var->datatype->typoid;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			case PLPGSQL_DTYPE_RECFIELD:
 | 
							exec_eval_datum(estate, estate->datums[expr->params[i]],
 | 
				
			||||||
				recfield = (PLpgSQL_recfield *) (estate->datums[expr->params[i]]);
 | 
											InvalidOid,
 | 
				
			||||||
				rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
 | 
											&argtypes[i], ¶mval, ¶misnull);
 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (!HeapTupleIsValid(rec->tup))
 | 
					 | 
				
			||||||
					elog(ERROR, "record \"%s\" is unassigned yet", rec->refname);
 | 
					 | 
				
			||||||
				fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
 | 
					 | 
				
			||||||
				if (fno == SPI_ERROR_NOATTRIBUTE)
 | 
					 | 
				
			||||||
					elog(ERROR, "record \"%s\" has no field named \"%s\"", rec->refname, recfield->fieldname);
 | 
					 | 
				
			||||||
				argtypes[i] = SPI_gettypeid(rec->tupdesc, fno);
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			case PLPGSQL_DTYPE_TRIGARG:
 | 
					 | 
				
			||||||
				argtypes[i] = (Oid) TEXTOID;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				elog(ERROR, "unknown parameter dtype %d in exec_run_select()",
 | 
					 | 
				
			||||||
					 estate->datums[expr->params[i]]->dtype);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
@@ -2059,19 +1987,11 @@ static int
 | 
				
			|||||||
exec_stmt_execsql(PLpgSQL_execstate * estate,
 | 
					exec_stmt_execsql(PLpgSQL_execstate * estate,
 | 
				
			||||||
				  PLpgSQL_stmt_execsql * stmt)
 | 
									  PLpgSQL_stmt_execsql * stmt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	PLpgSQL_var *var;
 | 
					 | 
				
			||||||
	PLpgSQL_rec *rec;
 | 
					 | 
				
			||||||
	PLpgSQL_recfield *recfield;
 | 
					 | 
				
			||||||
	PLpgSQL_trigarg *trigarg;
 | 
					 | 
				
			||||||
	int			tgargno;
 | 
					 | 
				
			||||||
	Oid			tgargoid;
 | 
					 | 
				
			||||||
	int			fno;
 | 
					 | 
				
			||||||
	int			i;
 | 
						int			i;
 | 
				
			||||||
	Datum	   *values;
 | 
						Datum	   *values;
 | 
				
			||||||
	char	   *nulls;
 | 
						char	   *nulls;
 | 
				
			||||||
	int			rc;
 | 
						int			rc;
 | 
				
			||||||
	PLpgSQL_expr *expr = stmt->sqlstmt;
 | 
						PLpgSQL_expr *expr = stmt->sqlstmt;
 | 
				
			||||||
	bool		isnull;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * On the first call for this expression generate the plan
 | 
						 * On the first call for this expression generate the plan
 | 
				
			||||||
@@ -2087,59 +2007,17 @@ exec_stmt_execsql(PLpgSQL_execstate * estate,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < expr->nparams; i++)
 | 
						for (i = 0; i < expr->nparams; i++)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		switch (estate->datums[expr->params[i]]->dtype)
 | 
							PLpgSQL_datum *datum = estate->datums[expr->params[i]];
 | 
				
			||||||
		{
 | 
							Oid			paramtypeid;
 | 
				
			||||||
			case PLPGSQL_DTYPE_VAR:
 | 
							bool		paramisnull;
 | 
				
			||||||
				var = (PLpgSQL_var *) (estate->datums[expr->params[i]]);
 | 
					
 | 
				
			||||||
				values[i] = var->value;
 | 
							exec_eval_datum(estate, datum, expr->plan_argtypes[i],
 | 
				
			||||||
				if (var->isnull)
 | 
											¶mtypeid, &values[i], ¶misnull);
 | 
				
			||||||
 | 
							if (paramisnull)
 | 
				
			||||||
			nulls[i] = 'n';
 | 
								nulls[i] = 'n';
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			nulls[i] = ' ';
 | 
								nulls[i] = ' ';
 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			case PLPGSQL_DTYPE_RECFIELD:
 | 
					 | 
				
			||||||
				recfield = (PLpgSQL_recfield *) (estate->datums[expr->params[i]]);
 | 
					 | 
				
			||||||
				rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (!HeapTupleIsValid(rec->tup))
 | 
					 | 
				
			||||||
					elog(ERROR, "record \"%s\" is unassigned yet", rec->refname);
 | 
					 | 
				
			||||||
				fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
 | 
					 | 
				
			||||||
				if (fno == SPI_ERROR_NOATTRIBUTE)
 | 
					 | 
				
			||||||
					elog(ERROR, "record \"%s\" has no field named \"%s\"", rec->refname, recfield->fieldname);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (expr->plan_argtypes[i] != SPI_gettypeid(rec->tupdesc, fno))
 | 
					 | 
				
			||||||
					elog(ERROR, "type of %s.%s doesn't match that when preparing the plan", rec->refname, recfield->fieldname);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				values[i] = SPI_getbinval(rec->tup, rec->tupdesc, fno, &isnull);
 | 
					 | 
				
			||||||
				if (isnull)
 | 
					 | 
				
			||||||
					nulls[i] = 'n';
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
					nulls[i] = ' ';
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			case PLPGSQL_DTYPE_TRIGARG:
 | 
					 | 
				
			||||||
				trigarg = (PLpgSQL_trigarg *) (estate->datums[expr->params[i]]);
 | 
					 | 
				
			||||||
				tgargno = (int) exec_eval_expr(estate, trigarg->argnum,
 | 
					 | 
				
			||||||
											   &isnull, &tgargoid);
 | 
					 | 
				
			||||||
				exec_eval_cleanup(estate);
 | 
					 | 
				
			||||||
				if (isnull || tgargno < 0 || tgargno >= estate->trig_nargs)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					values[i] = 0;
 | 
					 | 
				
			||||||
					nulls[i] = 'n';
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					values[i] = estate->trig_argv[tgargno];
 | 
					 | 
				
			||||||
					nulls[i] = ' ';
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				elog(ERROR, "unknown parameter dtype %d in exec_stmt_execsql()", estate->datums[expr->params[i]]->dtype);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nulls[i] = '\0';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Execute the plan
 | 
						 * Execute the plan
 | 
				
			||||||
@@ -2485,17 +2363,9 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
 | 
				
			|||||||
	char	   *curname = NULL;
 | 
						char	   *curname = NULL;
 | 
				
			||||||
	PLpgSQL_expr *query = NULL;
 | 
						PLpgSQL_expr *query = NULL;
 | 
				
			||||||
	Portal		portal;
 | 
						Portal		portal;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	PLpgSQL_var *var;
 | 
					 | 
				
			||||||
	PLpgSQL_rec *rec;
 | 
					 | 
				
			||||||
	PLpgSQL_recfield *recfield;
 | 
					 | 
				
			||||||
	PLpgSQL_trigarg *trigarg;
 | 
					 | 
				
			||||||
	int			tgargno;
 | 
					 | 
				
			||||||
	Oid			tgargoid;
 | 
					 | 
				
			||||||
	int			i;
 | 
						int			i;
 | 
				
			||||||
	Datum	   *values;
 | 
						Datum	   *values;
 | 
				
			||||||
	char	   *nulls;
 | 
						char	   *nulls;
 | 
				
			||||||
	int			fno;
 | 
					 | 
				
			||||||
	bool		isnull;
 | 
						bool		isnull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2654,60 +2524,17 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < query->nparams; i++)
 | 
						for (i = 0; i < query->nparams; i++)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		switch (estate->datums[query->params[i]]->dtype)
 | 
							PLpgSQL_datum *datum = estate->datums[query->params[i]];
 | 
				
			||||||
		{
 | 
							Oid			paramtypeid;
 | 
				
			||||||
			case PLPGSQL_DTYPE_VAR:
 | 
							bool		paramisnull;
 | 
				
			||||||
				var = (PLpgSQL_var *) (estate->datums[query->params[i]]);
 | 
					
 | 
				
			||||||
				values[i] = var->value;
 | 
							exec_eval_datum(estate, datum, query->plan_argtypes[i],
 | 
				
			||||||
				if (var->isnull)
 | 
											¶mtypeid, &values[i], ¶misnull);
 | 
				
			||||||
 | 
							if (paramisnull)
 | 
				
			||||||
			nulls[i] = 'n';
 | 
								nulls[i] = 'n';
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			nulls[i] = ' ';
 | 
								nulls[i] = ' ';
 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			case PLPGSQL_DTYPE_RECFIELD:
 | 
					 | 
				
			||||||
				recfield = (PLpgSQL_recfield *) (estate->datums[query->params[i]]);
 | 
					 | 
				
			||||||
				rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (!HeapTupleIsValid(rec->tup))
 | 
					 | 
				
			||||||
					elog(ERROR, "record \"%s\" is unassigned yet", rec->refname);
 | 
					 | 
				
			||||||
				fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
 | 
					 | 
				
			||||||
				if (fno == SPI_ERROR_NOATTRIBUTE)
 | 
					 | 
				
			||||||
					elog(ERROR, "record \"%s\" has no field named \"%s\"", rec->refname, recfield->fieldname);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (query->plan_argtypes[i] != SPI_gettypeid(rec->tupdesc, fno))
 | 
					 | 
				
			||||||
					elog(ERROR, "type of %s.%s doesn't match that when preparing the plan", rec->refname, recfield->fieldname);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				values[i] = SPI_getbinval(rec->tup, rec->tupdesc, fno, &isnull);
 | 
					 | 
				
			||||||
				if (isnull)
 | 
					 | 
				
			||||||
					nulls[i] = 'n';
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
					nulls[i] = ' ';
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			case PLPGSQL_DTYPE_TRIGARG:
 | 
					 | 
				
			||||||
				trigarg = (PLpgSQL_trigarg *) (estate->datums[query->params[i]]);
 | 
					 | 
				
			||||||
				tgargno = (int) exec_eval_expr(estate, trigarg->argnum,
 | 
					 | 
				
			||||||
											   &isnull, &tgargoid);
 | 
					 | 
				
			||||||
				exec_eval_cleanup(estate);
 | 
					 | 
				
			||||||
				if (isnull || tgargno < 0 || tgargno >= estate->trig_nargs)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					values[i] = 0;
 | 
					 | 
				
			||||||
					nulls[i] = 'n';
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					values[i] = estate->trig_argv[tgargno];
 | 
					 | 
				
			||||||
					nulls[i] = ' ';
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				elog(ERROR, "unknown parameter dtype %d in exec_stmt_open()",
 | 
					 | 
				
			||||||
					 estate->datums[query->params[i]]->dtype);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nulls[i] = '\0';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* ----------
 | 
						/* ----------
 | 
				
			||||||
	 * Open the cursor
 | 
						 * Open the cursor
 | 
				
			||||||
@@ -2892,7 +2719,7 @@ exec_assign_value(PLpgSQL_execstate * estate,
 | 
				
			|||||||
		case PLPGSQL_DTYPE_VAR:
 | 
							case PLPGSQL_DTYPE_VAR:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
			 * Target field is a variable
 | 
								 * Target is a variable
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			var = (PLpgSQL_var *) target;
 | 
								var = (PLpgSQL_var *) target;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2936,10 +2763,10 @@ exec_assign_value(PLpgSQL_execstate * estate,
 | 
				
			|||||||
		case PLPGSQL_DTYPE_RECFIELD:
 | 
							case PLPGSQL_DTYPE_RECFIELD:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
			 * Target field is a record
 | 
								 * Target is a field of a record
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			recfield = (PLpgSQL_recfield *) target;
 | 
								recfield = (PLpgSQL_recfield *) target;
 | 
				
			||||||
			rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
 | 
								rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
			 * Check that there is already a tuple in the record. We need
 | 
								 * Check that there is already a tuple in the record. We need
 | 
				
			||||||
@@ -3035,6 +2862,89 @@ exec_assign_value(PLpgSQL_execstate * estate,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * exec_eval_datum				Get current value of a PLpgSQL_datum
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The type oid, value in Datum format, and null flag are returned.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If expectedtypeid isn't InvalidOid, it is checked against the actual type.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This obviously only handles scalar datums (not whole records or rows);
 | 
				
			||||||
 | 
					 * at present it doesn't need to handle PLpgSQL_expr datums, either.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * NOTE: caller must not modify the returned value, since it points right
 | 
				
			||||||
 | 
					 * at the stored value in the case of pass-by-reference datatypes.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					exec_eval_datum(PLpgSQL_execstate *estate,
 | 
				
			||||||
 | 
									PLpgSQL_datum *datum,
 | 
				
			||||||
 | 
									Oid expectedtypeid,
 | 
				
			||||||
 | 
									Oid *typeid,
 | 
				
			||||||
 | 
									Datum *value,
 | 
				
			||||||
 | 
									bool *isnull)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PLpgSQL_var *var;
 | 
				
			||||||
 | 
						PLpgSQL_rec *rec;
 | 
				
			||||||
 | 
						PLpgSQL_recfield *recfield;
 | 
				
			||||||
 | 
						PLpgSQL_trigarg *trigarg;
 | 
				
			||||||
 | 
						int			tgargno;
 | 
				
			||||||
 | 
						Oid			tgargoid;
 | 
				
			||||||
 | 
						int			fno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (datum->dtype)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							case PLPGSQL_DTYPE_VAR:
 | 
				
			||||||
 | 
								var = (PLpgSQL_var *) datum;
 | 
				
			||||||
 | 
								*typeid = var->datatype->typoid;
 | 
				
			||||||
 | 
								*value = var->value;
 | 
				
			||||||
 | 
								*isnull = var->isnull;
 | 
				
			||||||
 | 
								if (expectedtypeid != InvalidOid && expectedtypeid != *typeid)
 | 
				
			||||||
 | 
									elog(ERROR, "type of %s doesn't match that when preparing the plan",
 | 
				
			||||||
 | 
										 var->refname);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case PLPGSQL_DTYPE_RECFIELD:
 | 
				
			||||||
 | 
								recfield = (PLpgSQL_recfield *) datum;
 | 
				
			||||||
 | 
								rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
 | 
				
			||||||
 | 
								if (!HeapTupleIsValid(rec->tup))
 | 
				
			||||||
 | 
									elog(ERROR, "record \"%s\" is unassigned yet", rec->refname);
 | 
				
			||||||
 | 
								fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
 | 
				
			||||||
 | 
								if (fno == SPI_ERROR_NOATTRIBUTE)
 | 
				
			||||||
 | 
									elog(ERROR, "record \"%s\" has no field named \"%s\"",
 | 
				
			||||||
 | 
										 rec->refname, recfield->fieldname);
 | 
				
			||||||
 | 
								*typeid = SPI_gettypeid(rec->tupdesc, fno);
 | 
				
			||||||
 | 
								*value = SPI_getbinval(rec->tup, rec->tupdesc, fno, isnull);
 | 
				
			||||||
 | 
								if (expectedtypeid != InvalidOid && expectedtypeid != *typeid)
 | 
				
			||||||
 | 
									elog(ERROR, "type of %s.%s doesn't match that when preparing the plan",
 | 
				
			||||||
 | 
										 rec->refname, recfield->fieldname);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case PLPGSQL_DTYPE_TRIGARG:
 | 
				
			||||||
 | 
								trigarg = (PLpgSQL_trigarg *) datum;
 | 
				
			||||||
 | 
								*typeid = TEXTOID;
 | 
				
			||||||
 | 
								tgargno = (int) exec_eval_expr(estate, trigarg->argnum,
 | 
				
			||||||
 | 
															   isnull, &tgargoid);
 | 
				
			||||||
 | 
								exec_eval_cleanup(estate);
 | 
				
			||||||
 | 
								if (*isnull || tgargno < 0 || tgargno >= estate->trig_nargs)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									*value = (Datum) 0;
 | 
				
			||||||
 | 
									*isnull = true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									*value = estate->trig_argv[tgargno];
 | 
				
			||||||
 | 
									*isnull = false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (expectedtypeid != InvalidOid && expectedtypeid != *typeid)
 | 
				
			||||||
 | 
									elog(ERROR, "type of tgargv[%d] doesn't match that when preparing the plan",
 | 
				
			||||||
 | 
										 tgargno);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								elog(ERROR, "unknown datum dtype %d in exec_eval_datum()",
 | 
				
			||||||
 | 
									 datum->dtype);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ----------
 | 
					/* ----------
 | 
				
			||||||
 * exec_eval_expr			Evaluate an expression and return
 | 
					 * exec_eval_expr			Evaluate an expression and return
 | 
				
			||||||
@@ -3103,18 +3013,10 @@ static int
 | 
				
			|||||||
exec_run_select(PLpgSQL_execstate * estate,
 | 
					exec_run_select(PLpgSQL_execstate * estate,
 | 
				
			||||||
				PLpgSQL_expr * expr, int maxtuples, Portal *portalP)
 | 
									PLpgSQL_expr * expr, int maxtuples, Portal *portalP)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	PLpgSQL_var *var;
 | 
					 | 
				
			||||||
	PLpgSQL_rec *rec;
 | 
					 | 
				
			||||||
	PLpgSQL_recfield *recfield;
 | 
					 | 
				
			||||||
	PLpgSQL_trigarg *trigarg;
 | 
					 | 
				
			||||||
	int			tgargno;
 | 
					 | 
				
			||||||
	Oid			tgargoid;
 | 
					 | 
				
			||||||
	int			i;
 | 
						int			i;
 | 
				
			||||||
	Datum	   *values;
 | 
						Datum	   *values;
 | 
				
			||||||
	char	   *nulls;
 | 
						char	   *nulls;
 | 
				
			||||||
	int			rc;
 | 
						int			rc;
 | 
				
			||||||
	int			fno;
 | 
					 | 
				
			||||||
	bool		isnull;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * On the first call for this expression generate the plan
 | 
						 * On the first call for this expression generate the plan
 | 
				
			||||||
@@ -3130,60 +3032,17 @@ exec_run_select(PLpgSQL_execstate * estate,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < expr->nparams; i++)
 | 
						for (i = 0; i < expr->nparams; i++)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		switch (estate->datums[expr->params[i]]->dtype)
 | 
							PLpgSQL_datum *datum = estate->datums[expr->params[i]];
 | 
				
			||||||
		{
 | 
							Oid			paramtypeid;
 | 
				
			||||||
			case PLPGSQL_DTYPE_VAR:
 | 
							bool		paramisnull;
 | 
				
			||||||
				var = (PLpgSQL_var *) (estate->datums[expr->params[i]]);
 | 
					
 | 
				
			||||||
				values[i] = var->value;
 | 
							exec_eval_datum(estate, datum, expr->plan_argtypes[i],
 | 
				
			||||||
				if (var->isnull)
 | 
											¶mtypeid, &values[i], ¶misnull);
 | 
				
			||||||
 | 
							if (paramisnull)
 | 
				
			||||||
			nulls[i] = 'n';
 | 
								nulls[i] = 'n';
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			nulls[i] = ' ';
 | 
								nulls[i] = ' ';
 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			case PLPGSQL_DTYPE_RECFIELD:
 | 
					 | 
				
			||||||
				recfield = (PLpgSQL_recfield *) (estate->datums[expr->params[i]]);
 | 
					 | 
				
			||||||
				rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (!HeapTupleIsValid(rec->tup))
 | 
					 | 
				
			||||||
					elog(ERROR, "record \"%s\" is unassigned yet", rec->refname);
 | 
					 | 
				
			||||||
				fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
 | 
					 | 
				
			||||||
				if (fno == SPI_ERROR_NOATTRIBUTE)
 | 
					 | 
				
			||||||
					elog(ERROR, "record \"%s\" has no field named \"%s\"", rec->refname, recfield->fieldname);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (expr->plan_argtypes[i] != SPI_gettypeid(rec->tupdesc, fno))
 | 
					 | 
				
			||||||
					elog(ERROR, "type of %s.%s doesn't match that when preparing the plan", rec->refname, recfield->fieldname);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				values[i] = SPI_getbinval(rec->tup, rec->tupdesc, fno, &isnull);
 | 
					 | 
				
			||||||
				if (isnull)
 | 
					 | 
				
			||||||
					nulls[i] = 'n';
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
					nulls[i] = ' ';
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			case PLPGSQL_DTYPE_TRIGARG:
 | 
					 | 
				
			||||||
				trigarg = (PLpgSQL_trigarg *) (estate->datums[expr->params[i]]);
 | 
					 | 
				
			||||||
				tgargno = (int) exec_eval_expr(estate, trigarg->argnum,
 | 
					 | 
				
			||||||
											   &isnull, &tgargoid);
 | 
					 | 
				
			||||||
				exec_eval_cleanup(estate);
 | 
					 | 
				
			||||||
				if (isnull || tgargno < 0 || tgargno >= estate->trig_nargs)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					values[i] = 0;
 | 
					 | 
				
			||||||
					nulls[i] = 'n';
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					values[i] = estate->trig_argv[tgargno];
 | 
					 | 
				
			||||||
					nulls[i] = ' ';
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				elog(ERROR, "unknown parameter dtype %d in exec_eval_expr()",
 | 
					 | 
				
			||||||
					 estate->datums[expr->params[i]]->dtype);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nulls[i] = '\0';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If a portal was requested, put the query into the portal
 | 
						 * If a portal was requested, put the query into the portal
 | 
				
			||||||
@@ -3231,15 +3090,7 @@ exec_eval_simple_expr(PLpgSQL_execstate * estate,
 | 
				
			|||||||
					  Oid *rettype)
 | 
										  Oid *rettype)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	Datum		retval;
 | 
						Datum		retval;
 | 
				
			||||||
	PLpgSQL_var *var;
 | 
					 | 
				
			||||||
	PLpgSQL_rec *rec;
 | 
					 | 
				
			||||||
	PLpgSQL_recfield *recfield;
 | 
					 | 
				
			||||||
	PLpgSQL_trigarg *trigarg;
 | 
					 | 
				
			||||||
	int			tgargno;
 | 
					 | 
				
			||||||
	Oid			tgargoid;
 | 
					 | 
				
			||||||
	int			fno;
 | 
					 | 
				
			||||||
	int			i;
 | 
						int			i;
 | 
				
			||||||
	bool		isnull;
 | 
					 | 
				
			||||||
	ExprContext *econtext;
 | 
						ExprContext *econtext;
 | 
				
			||||||
	ParamListInfo paramLI;
 | 
						ParamListInfo paramLI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -3264,54 +3115,13 @@ exec_eval_simple_expr(PLpgSQL_execstate * estate,
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	for (i = 0; i < expr->nparams; i++, paramLI++)
 | 
						for (i = 0; i < expr->nparams; i++, paramLI++)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							PLpgSQL_datum *datum = estate->datums[expr->params[i]];
 | 
				
			||||||
 | 
							Oid			paramtypeid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		paramLI->kind = PARAM_NUM;
 | 
							paramLI->kind = PARAM_NUM;
 | 
				
			||||||
		paramLI->id = i + 1;
 | 
							paramLI->id = i + 1;
 | 
				
			||||||
 | 
							exec_eval_datum(estate, datum, expr->plan_argtypes[i],
 | 
				
			||||||
		switch (estate->datums[expr->params[i]]->dtype)
 | 
											¶mtypeid, ¶mLI->value, ¶mLI->isnull);
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			case PLPGSQL_DTYPE_VAR:
 | 
					 | 
				
			||||||
				var = (PLpgSQL_var *) (estate->datums[expr->params[i]]);
 | 
					 | 
				
			||||||
				paramLI->isnull = var->isnull;
 | 
					 | 
				
			||||||
				paramLI->value = var->value;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			case PLPGSQL_DTYPE_RECFIELD:
 | 
					 | 
				
			||||||
				recfield = (PLpgSQL_recfield *) (estate->datums[expr->params[i]]);
 | 
					 | 
				
			||||||
				rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (!HeapTupleIsValid(rec->tup))
 | 
					 | 
				
			||||||
					elog(ERROR, "record \"%s\" is unassigned yet", rec->refname);
 | 
					 | 
				
			||||||
				fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
 | 
					 | 
				
			||||||
				if (fno == SPI_ERROR_NOATTRIBUTE)
 | 
					 | 
				
			||||||
					elog(ERROR, "record \"%s\" has no field named \"%s\"", rec->refname, recfield->fieldname);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (expr->plan_argtypes[i] != SPI_gettypeid(rec->tupdesc, fno))
 | 
					 | 
				
			||||||
					elog(ERROR, "type of %s.%s doesn't match that when preparing the plan", rec->refname, recfield->fieldname);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				paramLI->value = SPI_getbinval(rec->tup, rec->tupdesc, fno, &isnull);
 | 
					 | 
				
			||||||
				paramLI->isnull = isnull;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			case PLPGSQL_DTYPE_TRIGARG:
 | 
					 | 
				
			||||||
				trigarg = (PLpgSQL_trigarg *) (estate->datums[expr->params[i]]);
 | 
					 | 
				
			||||||
				tgargno = (int) exec_eval_expr(estate, trigarg->argnum,
 | 
					 | 
				
			||||||
											   &isnull, &tgargoid);
 | 
					 | 
				
			||||||
				exec_eval_cleanup(estate);
 | 
					 | 
				
			||||||
				if (isnull || tgargno < 0 || tgargno >= estate->trig_nargs)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					paramLI->value = 0;
 | 
					 | 
				
			||||||
					paramLI->isnull = TRUE;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					paramLI->value = estate->trig_argv[tgargno];
 | 
					 | 
				
			||||||
					paramLI->isnull = FALSE;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				elog(ERROR, "unknown parameter dtype %d in exec_eval_simple_expr()", estate->datums[expr->params[i]]->dtype);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	paramLI->kind = PARAM_INVALID;
 | 
						paramLI->kind = PARAM_INVALID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@
 | 
				
			|||||||
 *			  procedural language
 | 
					 *			  procedural language
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.23 2002/09/05 00:43:07 tgl Exp $
 | 
					 *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.24 2003/03/25 00:34:23 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	  This software is copyrighted by Jan Wieck - Hamburg.
 | 
					 *	  This software is copyrighted by Jan Wieck - Hamburg.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -1019,7 +1019,9 @@ plpgsql_dumptree(PLpgSQL_function * func)
 | 
				
			|||||||
				printf("REC %s\n", ((PLpgSQL_rec *) d)->refname);
 | 
									printf("REC %s\n", ((PLpgSQL_rec *) d)->refname);
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			case PLPGSQL_DTYPE_RECFIELD:
 | 
								case PLPGSQL_DTYPE_RECFIELD:
 | 
				
			||||||
				printf("RECFIELD %-16s of REC %d\n", ((PLpgSQL_recfield *) d)->fieldname, ((PLpgSQL_recfield *) d)->recno);
 | 
									printf("RECFIELD %-16s of REC %d\n",
 | 
				
			||||||
 | 
										   ((PLpgSQL_recfield *) d)->fieldname,
 | 
				
			||||||
 | 
										   ((PLpgSQL_recfield *) d)->recparentno);
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			case PLPGSQL_DTYPE_TRIGARG:
 | 
								case PLPGSQL_DTYPE_TRIGARG:
 | 
				
			||||||
				printf("TRIGARG ");
 | 
									printf("TRIGARG ");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@
 | 
				
			|||||||
 *			  procedural language
 | 
					 *			  procedural language
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.31 2002/12/15 16:17:59 tgl Exp $
 | 
					 *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.32 2003/03/25 00:34:24 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	  This software is copyrighted by Jan Wieck - Hamburg.
 | 
					 *	  This software is copyrighted by Jan Wieck - Hamburg.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -152,6 +152,10 @@ typedef struct
 | 
				
			|||||||
}	PLpgSQL_type;
 | 
					}	PLpgSQL_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * PLpgSQL_datum is the common supertype for PLpgSQL_expr, PLpgSQL_var,
 | 
				
			||||||
 | 
					 * PLpgSQL_row, PLpgSQL_rec, PLpgSQL_recfield, PLpgSQL_trigarg
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct
 | 
					typedef struct
 | 
				
			||||||
{								/* Generic datum array item		*/
 | 
					{								/* Generic datum array item		*/
 | 
				
			||||||
	int			dtype;
 | 
						int			dtype;
 | 
				
			||||||
@@ -209,7 +213,7 @@ typedef struct
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct
 | 
					typedef struct
 | 
				
			||||||
{								/* Record of undefined structure	*/
 | 
					{								/* Record of non-fixed structure */
 | 
				
			||||||
	int			dtype;
 | 
						int			dtype;
 | 
				
			||||||
	int			recno;
 | 
						int			recno;
 | 
				
			||||||
	char	   *refname;
 | 
						char	   *refname;
 | 
				
			||||||
@@ -227,7 +231,7 @@ typedef struct
 | 
				
			|||||||
	int			dtype;
 | 
						int			dtype;
 | 
				
			||||||
	int			rfno;
 | 
						int			rfno;
 | 
				
			||||||
	char	   *fieldname;
 | 
						char	   *fieldname;
 | 
				
			||||||
	int			recno;
 | 
						int			recparentno;	/* recno of parent record */
 | 
				
			||||||
}	PLpgSQL_recfield;
 | 
					}	PLpgSQL_recfield;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user