Hi

plpgsql generate lot of auto variables - FOUND, SQLERRM, cycle's control
variable, TG_WHEN, TG_OP, ..

Currently these variables are not protected, what can be source of
problems, mainly for not experienced users. I propose mark these variables
as constant.

-- today
postgres=# do $$ begin for i in 1..10 loop raise notice 'i=%', i; i := 20;
end loop; end; $$;
NOTICE:  i=1
NOTICE:  i=2
NOTICE:  i=3
NOTICE:  i=4
NOTICE:  i=5
NOTICE:  i=6
NOTICE:  i=7
NOTICE:  i=8
NOTICE:  i=9
NOTICE:  i=10
DO

-- after patch
postgres=# do $$ begin for i in 1..10 loop raise notice 'i=%', i; i := 20;
end loop; end; $$;
ERROR:  variable "i" is declared CONSTANT
LINE 1: ... begin for i in 1..10 loop raise notice 'i=%', i; i := 20; e...

These variables are protected in PL/SQL too.

Comments, notes?

Regards

Pavel

p.s. this is simple implementation - just for function demo. Maybe can be
better to introduce new plpgsql_variable's flag like is_protected or
similar than using isconst.
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 828ff5a288..a9b597810b 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -443,7 +443,7 @@ do_compile(FunctionCallInfo fcinfo,
 				argvariable = plpgsql_build_variable((argnames &&
 													  argnames[i][0] != '\0') ?
 													 argnames[i] : buf,
-													 0, argdtype, false);
+													 0, argdtype, false, false);
 
 				if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
 				{
@@ -579,7 +579,7 @@ do_compile(FunctionCallInfo fcinfo,
 															 -1,
 															 function->fn_input_collation,
 															 NULL),
-											  true);
+											  true, true);
 			}
 
 			ReleaseSysCache(typeTup);
@@ -614,7 +614,7 @@ do_compile(FunctionCallInfo fcinfo,
 																-1,
 																function->fn_input_collation,
 																NULL),
-										 true);
+										 true, true);
 			Assert(var->dtype == PLPGSQL_DTYPE_VAR);
 			var->dtype = PLPGSQL_DTYPE_PROMISE;
 			((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NAME;
@@ -625,7 +625,7 @@ do_compile(FunctionCallInfo fcinfo,
 																-1,
 																function->fn_input_collation,
 																NULL),
-										 true);
+										 true, true);
 			Assert(var->dtype == PLPGSQL_DTYPE_VAR);
 			var->dtype = PLPGSQL_DTYPE_PROMISE;
 			((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_WHEN;
@@ -636,7 +636,7 @@ do_compile(FunctionCallInfo fcinfo,
 																-1,
 																function->fn_input_collation,
 																NULL),
-										 true);
+										 true, true);
 			Assert(var->dtype == PLPGSQL_DTYPE_VAR);
 			var->dtype = PLPGSQL_DTYPE_PROMISE;
 			((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_LEVEL;
@@ -647,7 +647,7 @@ do_compile(FunctionCallInfo fcinfo,
 																-1,
 																function->fn_input_collation,
 																NULL),
-										 true);
+										 true, true);
 			Assert(var->dtype == PLPGSQL_DTYPE_VAR);
 			var->dtype = PLPGSQL_DTYPE_PROMISE;
 			((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_OP;
@@ -658,7 +658,7 @@ do_compile(FunctionCallInfo fcinfo,
 																-1,
 																InvalidOid,
 																NULL),
-										 true);
+										 true, true);
 			Assert(var->dtype == PLPGSQL_DTYPE_VAR);
 			var->dtype = PLPGSQL_DTYPE_PROMISE;
 			((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_RELID;
@@ -669,7 +669,7 @@ do_compile(FunctionCallInfo fcinfo,
 																-1,
 																function->fn_input_collation,
 																NULL),
-										 true);
+										 true, true);
 			Assert(var->dtype == PLPGSQL_DTYPE_VAR);
 			var->dtype = PLPGSQL_DTYPE_PROMISE;
 			((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
@@ -680,7 +680,7 @@ do_compile(FunctionCallInfo fcinfo,
 																-1,
 																function->fn_input_collation,
 																NULL),
-										 true);
+										 true, true);
 			Assert(var->dtype == PLPGSQL_DTYPE_VAR);
 			var->dtype = PLPGSQL_DTYPE_PROMISE;
 			((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
@@ -691,7 +691,7 @@ do_compile(FunctionCallInfo fcinfo,
 																-1,
 																function->fn_input_collation,
 																NULL),
-										 true);
+										 true, true);
 			Assert(var->dtype == PLPGSQL_DTYPE_VAR);
 			var->dtype = PLPGSQL_DTYPE_PROMISE;
 			((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_SCHEMA;
@@ -702,7 +702,7 @@ do_compile(FunctionCallInfo fcinfo,
 																-1,
 																InvalidOid,
 																NULL),
-										 true);
+										 true, true);
 			Assert(var->dtype == PLPGSQL_DTYPE_VAR);
 			var->dtype = PLPGSQL_DTYPE_PROMISE;
 			((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NARGS;
@@ -713,7 +713,7 @@ do_compile(FunctionCallInfo fcinfo,
 																-1,
 																function->fn_input_collation,
 																NULL),
-										 true);
+										 true, true);
 			Assert(var->dtype == PLPGSQL_DTYPE_VAR);
 			var->dtype = PLPGSQL_DTYPE_PROMISE;
 			((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_ARGV;
@@ -739,7 +739,7 @@ do_compile(FunctionCallInfo fcinfo,
 																-1,
 																function->fn_input_collation,
 																NULL),
-										 true);
+										 true, true);
 			Assert(var->dtype == PLPGSQL_DTYPE_VAR);
 			var->dtype = PLPGSQL_DTYPE_PROMISE;
 			((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_EVENT;
@@ -750,7 +750,7 @@ do_compile(FunctionCallInfo fcinfo,
 																-1,
 																function->fn_input_collation,
 																NULL),
-										 true);
+										 true, true);
 			Assert(var->dtype == PLPGSQL_DTYPE_VAR);
 			var->dtype = PLPGSQL_DTYPE_PROMISE;
 			((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TAG;
@@ -774,7 +774,7 @@ do_compile(FunctionCallInfo fcinfo,
 														-1,
 														InvalidOid,
 														NULL),
-								 true);
+								 true, true);
 	function->found_varno = var->dno;
 
 	/*
@@ -929,7 +929,7 @@ plpgsql_compile_inline(char *proc_source)
 														-1,
 														InvalidOid,
 														NULL),
-								 true);
+								 true, true);
 	function->found_varno = var->dno;
 
 	/*
@@ -1843,7 +1843,7 @@ plpgsql_parse_cwordrowtype(List *idents)
  */
 PLpgSQL_variable *
 plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,
-					   bool add2namespace)
+					   bool add2namespace, bool isconst)
 {
 	PLpgSQL_variable *result;
 
@@ -1898,6 +1898,8 @@ plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,
 			break;
 	}
 
+	result->isconst = isconst;
+
 	return result;
 }
 
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
index 6778d0e771..89a4c07e19 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -513,8 +513,7 @@ decl_statement	: decl_varname decl_const decl_datatype decl_collate decl_notnull
 						}
 
 						var = plpgsql_build_variable($1.name, $1.lineno,
-													 $3, true);
-						var->isconst = $2;
+													 $3, true, $2);
 						var->notnull = $5;
 						var->default_val = $6;
 
@@ -553,7 +552,7 @@ decl_statement	: decl_varname decl_const decl_datatype decl_collate decl_notnull
 																		  -1,
 																		  InvalidOid,
 																		  NULL),
-												   true);
+												   true, false);
 
 						curname_def = palloc0(sizeof(PLpgSQL_expr));
 
@@ -655,7 +654,7 @@ decl_cursor_arg : decl_varname decl_datatype
 					{
 						$$ = (PLpgSQL_datum *)
 							plpgsql_build_variable($1.name, $1.lineno,
-												   $2, true);
+												   $2, true, false);
 					}
 				;
 
@@ -1507,7 +1506,7 @@ for_control		: for_variable K_IN
 																				  -1,
 																				  InvalidOid,
 																				  NULL),
-														   true);
+														   true, true);
 
 								new = palloc0(sizeof(PLpgSQL_stmt_fori));
 								new->cmd_type = PLPGSQL_STMT_FORI;
@@ -2321,7 +2320,7 @@ exception_sect	:
 																			-1,
 																			plpgsql_curr_compile->fn_input_collation,
 																			NULL),
-													 true);
+													 true, true);
 						var->isconst = true;
 						new->sqlstate_varno = var->dno;
 
@@ -2330,7 +2329,7 @@ exception_sect	:
 																			-1,
 																			plpgsql_curr_compile->fn_input_collation,
 																			NULL),
-													 true);
+													 true, true);
 						var->isconst = true;
 						new->sqlerrm_varno = var->dno;
 
@@ -4089,7 +4088,7 @@ make_case(int location, PLpgSQL_expr *t_expr,
 														  -1,
 														  InvalidOid,
 														  NULL),
-								   true);
+								   true, true);
 		new->t_varno = t_var->dno;
 
 		foreach(l, case_when_list)
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 1af2595e34..bfeca5dcf0 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -1254,7 +1254,8 @@ extern PLpgSQL_type *plpgsql_build_datatype(Oid typeOid, int32 typmod,
 											TypeName *origtypname);
 extern PLpgSQL_variable *plpgsql_build_variable(const char *refname, int lineno,
 												PLpgSQL_type *dtype,
-												bool add2namespace);
+												bool add2namespace,
+												bool isconst);
 extern PLpgSQL_rec *plpgsql_build_record(const char *refname, int lineno,
 										 PLpgSQL_type *dtype, Oid rectypeid,
 										 bool add2namespace);

Reply via email to