? libplpgsql.sl.1 Index: gram.y =================================================================== RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v retrieving revision 1.97 diff -c -r1.97 gram.y *** gram.y 1 Feb 2007 19:10:29 -0000 1.97 --- gram.y 8 Feb 2007 01:06:24 -0000 *************** *** 272,278 **** $$.label = $1; $$.n_initvars = 0; $$.initvarnos = NULL; - plpgsql_add_initdatums(NULL); } | opt_block_label decl_start { --- 272,277 ---- *************** *** 280,286 **** $$.label = $1; $$.n_initvars = 0; $$.initvarnos = NULL; - plpgsql_add_initdatums(NULL); } | opt_block_label decl_start decl_stmts { --- 279,284 ---- *************** *** 289,300 **** --- 287,302 ---- $$.label = $3; else $$.label = $1; + /* Remember variables declared in decl_stmts */ $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos)); } ; decl_start : K_DECLARE { + /* Forget any variables created before block */ + plpgsql_add_initdatums(NULL); + /* Make variable names be local to block */ plpgsql_ns_setlocal(true); } ; *************** *** 990,998 **** -1), true); - /* put the for-variable into the local block */ - plpgsql_add_initdatums(NULL); - new = palloc0(sizeof(PLpgSQL_stmt_fori)); new->cmd_type = PLPGSQL_STMT_FORI; new->lineno = $1; --- 992,997 ---- Index: pl_comp.c =================================================================== RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v retrieving revision 1.111 diff -c -r1.111 pl_comp.c *** pl_comp.c 1 Feb 2007 19:10:29 -0000 1.111 --- pl_comp.c 8 Feb 2007 01:06:24 -0000 *************** *** 667,677 **** function->found_varno = var->dno; /* - * Forget about the above created variables - */ - plpgsql_add_initdatums(NULL); - - /* * Now parse the function's text */ parse_rc = plpgsql_yyparse(); --- 667,672 ---- *************** *** 1893,1903 **** /* ---------- ! * plpgsql_add_initdatums Put all datum entries created ! * since the last call into the ! * finishing code block so the ! * block knows which variables to ! * reinitialize when entered. * ---------- */ int --- 1888,1904 ---- /* ---------- ! * plpgsql_add_initdatums Make an array of the datum numbers of ! * all the simple VAR datums created since the last call ! * to this function. ! * ! * If varnos is NULL, we just forget any datum entries created since the ! * last call. ! * ! * This is used around a DECLARE section to create a list of the VARs ! * that have to be initialized at block entry. Note that VARs can also ! * be created elsewhere than DECLARE, eg by a FOR-loop, but it is then ! * the responsibility of special-purpose code to initialize them. * ---------- */ int Index: pl_exec.c =================================================================== RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v retrieving revision 1.187 diff -c -r1.187 pl_exec.c *** pl_exec.c 1 Feb 2007 19:22:07 -0000 1.187 --- pl_exec.c 8 Feb 2007 01:06:25 -0000 *************** *** 885,927 **** { PLpgSQL_var *var = (PLpgSQL_var *) (estate->datums[n]); free_var(var); ! if (!var->isconst || var->isnull) { ! if (var->default_val == NULL) { ! /* Initially it contains a NULL */ ! var->value = (Datum) 0; ! var->isnull = true; ! /* ! * If needed, give the datatype a chance to reject ! * NULLs, by assigning a NULL to the variable. ! * We claim the value is of type UNKNOWN, not the ! * var's datatype, else coercion will be skipped. ! * (Do this before the notnull check to be ! * consistent with exec_assign_value.) ! */ ! if (!var->datatype->typinput.fn_strict) ! { ! bool valIsNull = true; ! ! exec_assign_value(estate, ! (PLpgSQL_datum *) var, ! (Datum) 0, ! UNKNOWNOID, ! &valIsNull); ! } ! if (var->notnull) ! ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("variable \"%s\" declared NOT NULL cannot default to NULL", var->refname))); ! } ! else ! { ! exec_assign_expr(estate, (PLpgSQL_datum *) var, ! var->default_val); ! } } } break; --- 885,927 ---- { PLpgSQL_var *var = (PLpgSQL_var *) (estate->datums[n]); + /* free any old value, in case re-entering block */ free_var(var); ! ! /* Initially it contains a NULL */ ! var->value = (Datum) 0; ! var->isnull = true; ! ! if (var->default_val == NULL) { ! /* ! * If needed, give the datatype a chance to reject ! * NULLs, by assigning a NULL to the variable. ! * We claim the value is of type UNKNOWN, not the ! * var's datatype, else coercion will be skipped. ! * (Do this before the notnull check to be ! * consistent with exec_assign_value.) ! */ ! if (!var->datatype->typinput.fn_strict) { ! bool valIsNull = true; ! ! exec_assign_value(estate, ! (PLpgSQL_datum *) var, ! (Datum) 0, ! UNKNOWNOID, ! &valIsNull); ! } ! if (var->notnull) ! ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("variable \"%s\" declared NOT NULL cannot default to NULL", var->refname))); ! } ! else ! { ! exec_assign_expr(estate, (PLpgSQL_datum *) var, ! var->default_val); } } break; *************** *** 1065,1071 **** --- 1065,1073 ---- rc = exec_stmts(estate, exception->action); free_var(state_var); + state_var->value = (Datum) 0; free_var(errm_var); + errm_var->value = (Datum) 0; break; } } *************** *** 4867,4872 **** --- 4869,4880 ---- } } + /* + * free_var --- pfree any pass-by-reference value of the variable. + * + * This should always be followed by some assignment to var->value, + * as it leaves a dangling pointer. + */ static void free_var(PLpgSQL_var *var) {