diff -c -r src.old/gram.y src/gram.y *** src.old/gram.y 2005-02-22 08:18:24.000000000 +0100 --- src/gram.y 2005-03-07 10:05:29.286336064 +0100 *************** *** 80,85 **** --- 80,90 ---- int n_initvars; int *initvarnos; } declhdr; + struct + { + int sqlcode_varno; + int sqlerrm_varno; + } fict_vars; List *list; PLpgSQL_type *dtype; PLpgSQL_datum *scalar; /* a VAR, RECFIELD, or TRIGARG */ *************** *** 95,101 **** PLpgSQL_nsitem *nsitem; PLpgSQL_diag_item *diagitem; } ! %type decl_sect %type decl_varname %type decl_renname --- 100,106 ---- PLpgSQL_nsitem *nsitem; PLpgSQL_diag_item *diagitem; } ! %type fict_vars_sect %type decl_sect %type decl_varname %type decl_renname *************** *** 244,268 **** | ';' ; ! pl_block : decl_sect K_BEGIN lno proc_sect exception_sect K_END { PLpgSQL_stmt_block *new; new = palloc0(sizeof(PLpgSQL_stmt_block)); new->cmd_type = PLPGSQL_STMT_BLOCK; ! new->lineno = $3; new->label = $1.label; new->n_initvars = $1.n_initvars; new->initvarnos = $1.initvarnos; ! new->body = $4; ! new->exceptions = $5; plpgsql_ns_pop(); $$ = (PLpgSQL_stmt *)new; } ; decl_sect : opt_label --- 249,288 ---- | ';' ; ! pl_block : decl_sect fict_vars_sect K_BEGIN lno proc_sect exception_sect K_END { PLpgSQL_stmt_block *new; new = palloc0(sizeof(PLpgSQL_stmt_block)); new->cmd_type = PLPGSQL_STMT_BLOCK; ! new->lineno = $4; new->label = $1.label; new->n_initvars = $1.n_initvars; new->initvarnos = $1.initvarnos; ! new->body = $5; ! new->exceptions = $6; ! ! new->sqlcode_varno = $2.sqlcode_varno; ! new->sqlerrm_varno = $2.sqlerrm_varno; plpgsql_ns_pop(); $$ = (PLpgSQL_stmt *)new; } ; + fict_vars_sect : + { + plpgsql_ns_setlocal(false); + PLpgSQL_variable *var; + var = plpgsql_build_variable(strdup("sqlcode"), 0, + plpgsql_build_datatype(TEXTOID, -1), true); + $$.sqlcode_varno = var->dno; + var = plpgsql_build_variable(strdup("sqlerrm"), 0, + plpgsql_build_datatype(TEXTOID, -1), true); + $$.sqlerrm_varno = var->dno; + plpgsql_add_initdatums(NULL); + }; decl_sect : opt_label diff -c -r src.old/pl_exec.c src/pl_exec.c *** src.old/pl_exec.c 2005-02-24 02:11:40.000000000 +0100 --- src/pl_exec.c 2005-03-07 09:53:52.630243888 +0100 *************** *** 809,814 **** --- 809,828 ---- int i; int n; + /* setup SQLCODE and SQLERRM */ + PLpgSQL_var *var; + + var = (PLpgSQL_var *) (estate->datums[block->sqlcode_varno]); + var->isnull = false; + var->freeval = false; + var->value = DirectFunctionCall1(textin, CStringGetDatum("00000")); + + var = (PLpgSQL_var *) (estate->datums[block->sqlerrm_varno]); + var->isnull = false; + var->freeval = false; + var->value = DirectFunctionCall1(textin, CStringGetDatum("Sucessful completion")); + + /* * First initialize all variables declared in this block */ *************** *** 918,923 **** --- 932,957 ---- MemoryContextSwitchTo(oldcontext); CurrentResourceOwner = oldowner; + + /* set SQLCODE and SQLERRM variables */ + /* unpack MAKE_SQLSTATE code */ + char tbuf[12]; + int ssval; + int i; + + ssval = edata->sqlerrcode; + for (i = 0; i < 5; i++) + { + tbuf[i] = PGUNSIXBIT(ssval); + ssval >>= 6; + } + tbuf[i] = '\0'; + var = (PLpgSQL_var *) (estate->datums[block->sqlcode_varno]); + var->value = DirectFunctionCall1(textin, CStringGetDatum(tbuf)); + + var = (PLpgSQL_var *) (estate->datums[block->sqlerrm_varno]); + var->value = DirectFunctionCall1(textin, CStringGetDatum(edata->message)); + /* * If AtEOSubXact_SPI() popped any SPI context of the subxact, * it will have left us in a disconnected state. We need this diff -c -r src.old/plpgsql.h src/plpgsql.h *** src.old/plpgsql.h 2005-02-22 08:18:24.000000000 +0100 --- src/plpgsql.h 2005-03-07 09:39:25.613050536 +0100 *************** *** 339,344 **** --- 339,346 ---- List *exceptions; /* List of WHEN clauses */ int n_initvars; int *initvarnos; + int sqlcode_varno; + int sqlerrm_varno; } PLpgSQL_stmt_block;