diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y index 99f7a1b0f6e820f615264bdbd039c15152498e05..8251d71908ef8791a2e0bc20ca242a87ef42678a 100644 --- a/src/pl/plpgsql/src/gram.y +++ b/src/pl/plpgsql/src/gram.y @@ -4,7 +4,7 @@ * procedural language * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.11 2000/08/31 13:26:15 wieck Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.12 2000/09/05 09:02:18 wieck Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -113,12 +113,15 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row); %type stmt_assign, stmt_if, stmt_loop, stmt_while, stmt_exit %type stmt_return, stmt_raise, stmt_execsql, stmt_fori %type stmt_fors, stmt_select, stmt_perform -%type stmt_dynexecute, stmt_dynfors +%type stmt_dynexecute, stmt_dynfors, stmt_getdiag %type raise_params %type raise_level, raise_param %type raise_msg +%type getdiag_items, getdiag_targets +%type getdiag_item, getdiag_target + %type lno /* @@ -131,6 +134,7 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row); %token K_DEBUG %token K_DECLARE %token K_DEFAULT +%token K_DIAGNOSTICS %token K_DOTDOT %token K_ELSE %token K_END @@ -139,6 +143,7 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row); %token K_EXIT %token K_FOR %token K_FROM +%token K_GET %token K_IF %token K_IN %token K_INTO @@ -147,9 +152,11 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row); %token K_NOTICE %token K_NULL %token K_PERFORM +%token K_PROCESSED %token K_RAISE %token K_RECORD %token K_RENAME +%token K_RESULT %token K_RETURN %token K_REVERSE %token K_SELECT @@ -371,7 +378,7 @@ decl_rowtype : T_ROW decl_varname : T_WORD { - $$.name = strdup(yytext); + $$.name = plpgsql_tolower(strdup(yytext)); $$.lineno = yylineno; } ; @@ -576,6 +583,8 @@ proc_stmt : pl_block { $$ = $1; } | stmt_perform { $$ = $1; } + | stmt_getdiag + { $$ = $1; } ; stmt_perform : K_PERFORM lno expr_until_semi @@ -610,6 +619,100 @@ stmt_assign : assign_var lno K_ASSIGN expr_until_semi } ; +stmt_getdiag : K_GET K_DIAGNOSTICS lno K_SELECT getdiag_items K_INTO getdiag_targets ';' + { + PLpgSQL_stmt_getdiag *new; + + new = malloc(sizeof(PLpgSQL_stmt_getdiag)); + memset(new, 0, sizeof(PLpgSQL_stmt_getdiag)); + + new->cmd_type = PLPGSQL_STMT_GETDIAG; + new->lineno = $3; + new->nitems = $5.nused; + new->items = malloc(sizeof(int) * $5.nused); + new->ntargets = $7.nused; + new->targets = malloc(sizeof(int) * $7.nused); + memcpy(new->items, $5.dtnums, sizeof(int) * $5.nused); + memcpy(new->targets, $7.dtnums, sizeof(int) * $7.nused); + + if (new->nitems != new->ntargets) { + plpgsql_error_lineno = new->lineno; + plpgsql_comperrinfo(); + elog(ERROR, "number of diagnostic items does not match target list"); + }; + + $$ = (PLpgSQL_stmt *)new; + } + ; + +getdiag_items : getdiag_items ',' getdiag_item + { + if ($1.nused == $1.nalloc) { + $1.nalloc *= 2; + $1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc); + } + $1.dtnums[$1.nused++] = $3; + + $$.nalloc = $1.nalloc; + $$.nused = $1.nused; + $$.dtnums = $1.dtnums; + } + | getdiag_item + { + $$.nalloc = 1; + $$.nused = 1; + $$.dtnums = palloc(sizeof(int) * $$.nalloc); + $$.dtnums[0] = $1; + } + ; + +getdiag_item : K_PROCESSED + { + $$ = PLPGSQL_GETDIAG_PROCESSED; + } + | K_RESULT + { + $$ = PLPGSQL_GETDIAG_RESULT; + } + ; + +getdiag_targets : getdiag_targets ',' getdiag_target + { + if ($1.nused == $1.nalloc) { + $1.nalloc *= 2; + $1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc); + } + $1.dtnums[$1.nused++] = $3; + + $$.nalloc = $1.nalloc; + $$.nused = $1.nused; + $$.dtnums = $1.dtnums; + } + | getdiag_target + { + $$.nalloc = 1; + $$.nused = 1; + $$.dtnums = palloc(sizeof(int) * $$.nalloc); + $$.dtnums[0] = $1; + } + ; + + +getdiag_target : T_VARIABLE + { + if (yylval.var->isconst) { + plpgsql_comperrinfo(); + elog(ERROR, "%s is declared CONSTANT; can not receive diagnostics", yylval.var->refname); + } + $$ = yylval.var->varno; + } + | T_RECFIELD + { + $$ = yylval.recfield->rfno; + } + ; + + assign_var : T_VARIABLE { if (yylval.var->isconst) { diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 7740c2790ee71d542fecaf49601c5fb618af488c..ac4208c7195a0b963199c4106f06ed9380959789 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -3,7 +3,7 @@ * procedural language * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.29 2000/08/31 13:26:16 wieck Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.30 2000/09/05 09:02:18 wieck Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -80,6 +80,8 @@ static int exec_stmt(PLpgSQL_execstate * estate, PLpgSQL_stmt * stmt); static int exec_stmt_assign(PLpgSQL_execstate * estate, PLpgSQL_stmt_assign * stmt); +static int exec_stmt_getdiag(PLpgSQL_execstate * estate, + PLpgSQL_stmt_getdiag * stmt); static int exec_stmt_if(PLpgSQL_execstate * estate, PLpgSQL_stmt_if * stmt); static int exec_stmt_loop(PLpgSQL_execstate * estate, @@ -193,6 +195,9 @@ plpgsql_exec_function(PLpgSQL_function * func, FunctionCallInfo fcinfo) case PLPGSQL_STMT_ASSIGN: stmttype = "assignment"; break; + case PLPGSQL_STMT_GETDIAG: + stmttype = "get diagnostics"; + break; case PLPGSQL_STMT_IF: stmttype = "if"; break; @@ -502,6 +507,9 @@ plpgsql_exec_trigger(PLpgSQL_function * func, case PLPGSQL_STMT_ASSIGN: stmttype = "assignment"; break; + case PLPGSQL_STMT_GETDIAG: + stmttype = "get diagnostics"; + break; case PLPGSQL_STMT_IF: stmttype = "if"; break; @@ -971,6 +979,10 @@ exec_stmt(PLpgSQL_execstate * estate, PLpgSQL_stmt * stmt) rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) 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; @@ -1047,6 +1059,49 @@ exec_stmt_assign(PLpgSQL_execstate * estate, PLpgSQL_stmt_assign * stmt) return PLPGSQL_RC_OK; } +/* ---------- + * exec_stmt_getdiag Put internal PG information into + * specified variables. + * ---------- + */ +static int +exec_stmt_getdiag(PLpgSQL_execstate * estate, PLpgSQL_stmt_getdiag * stmt) +{ + int i; + PLpgSQL_datum *var; + HeapTuple typeTup; + bool isnull = false; + + for ( i=0 ; i < stmt->nitems ; i++) + { + if ((stmt->targets[i] <= 0)) + break; + + var = (estate->datums[stmt->targets[i]]); + + if (var == NULL) + break; + + switch (stmt->items[i]) + { + case PLPGSQL_GETDIAG_PROCESSED: + + exec_assign_value(estate, var, (Datum)SPI_processed, INT4OID, &isnull); + break; + + case PLPGSQL_GETDIAG_RESULT: + + exec_assign_value(estate, var, (Datum)SPI_result, INT4OID, &isnull); + break; + + default: + + elog(ERROR, "unknown attribute request %d in get_diagnostic", stmt->items[i]); + }; + }; + + return PLPGSQL_RC_OK; +} /* ---------- * exec_stmt_if Evaluate a bool expression and diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c index dc1a2f423d6f9831dd2fecb614aac8617a41a144..d7059bf3e29ff8683606c0b2bddcdc7d87379a2c 100644 --- a/src/pl/plpgsql/src/pl_funcs.c +++ b/src/pl/plpgsql/src/pl_funcs.c @@ -3,7 +3,7 @@ * procedural language * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.7 2000/08/31 13:26:16 wieck Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.8 2000/09/05 09:02:18 wieck Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -390,6 +390,7 @@ static void dump_raise(PLpgSQL_stmt_raise * stmt); static void dump_execsql(PLpgSQL_stmt_execsql * stmt); static void dump_dynexecute(PLpgSQL_stmt_dynexecute * stmt); static void dump_dynfors(PLpgSQL_stmt_dynfors * stmt); +static void dump_getdiag(PLpgSQL_stmt_getdiag * stmt); static void dump_expr(PLpgSQL_expr * expr); @@ -450,6 +451,9 @@ dump_stmt(PLpgSQL_stmt * stmt) case PLPGSQL_STMT_DYNFORS: dump_dynfors((PLpgSQL_stmt_dynfors *) stmt); break; + case PLPGSQL_STMT_GETDIAG: + dump_getdiag((PLpgSQL_stmt_getdiag *) stmt); + break; default: elog(ERROR, "plpgsql_dump: unknown cmd_type %d\n", stmt->cmd_type); break; @@ -637,7 +641,7 @@ dump_return(PLpgSQL_stmt_return * stmt) { dump_ind(); printf("RETURN "); - if (stmt->retrecno >= 0) + if (stmt->retrecno > 0) printf("record %d", stmt->retrecno); else { @@ -698,6 +702,45 @@ dump_dynfors(PLpgSQL_stmt_dynfors * stmt) printf(" ENDFORS\n"); } +static void +dump_getdiag(PLpgSQL_stmt_getdiag * stmt) +{ + int i; + + dump_ind(); + printf("GET DIAGNOSTICS SELECT "); + for (i = 0; i < stmt->nitems; i++) + { + if (i != 0) + printf(", "); + + switch (stmt->items[i]) + { + case PLPGSQL_GETDIAG_PROCESSED: + printf("PROCESSED"); + break; + + case PLPGSQL_GETDIAG_RESULT: + printf("RESULT"); + break; + + default: + printf("???"); + break; + } + } + printf(" INTO "); + for (i = 0; i < stmt->ntargets; i++) + { + if (i != 0) + printf(", "); + + printf("{var %d}", stmt->targets[i]); + } + + printf("\n"); +} + static void dump_expr(PLpgSQL_expr * expr) { diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h index e48a56ce89303736cafe5f73f3d272532d5a4e90..e03fed063c017d7da294baf119f1074269af8376 100644 --- a/src/pl/plpgsql/src/plpgsql.h +++ b/src/pl/plpgsql/src/plpgsql.h @@ -3,7 +3,7 @@ * procedural language * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.10 2000/08/31 13:26:16 wieck Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.11 2000/09/05 09:02:18 wieck Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -93,7 +93,8 @@ enum PLPGSQL_STMT_RAISE, PLPGSQL_STMT_EXECSQL, PLPGSQL_STMT_DYNEXECUTE, - PLPGSQL_STMT_DYNFORS + PLPGSQL_STMT_DYNFORS, + PLPGSQL_STMT_GETDIAG }; @@ -108,6 +109,17 @@ enum PLPGSQL_RC_RETURN }; +/* ---------- + * GET DIAGNOSTICS system attrs + * ---------- + */ +enum +{ + PLPGSQL_GETDIAG_PROCESSED, + PLPGSQL_GETDIAG_RESULT +}; + + /********************************************************************** * Node and structure definitions **********************************************************************/ @@ -265,6 +277,16 @@ typedef struct PLpgSQL_expr *expr; } PLpgSQL_stmt_assign; +typedef struct +{ /* Get Disgnostics statement */ + int cmd_type; + int lineno; + int nitems; + int *items; + int ntargets; + int *targets; +} PLpgSQL_stmt_getdiag; + typedef struct { /* IF statement */ diff --git a/src/pl/plpgsql/src/scan.l b/src/pl/plpgsql/src/scan.l index 73b605032f126f82da082154657375a2a69eba3b..4cb7ed86157b69ac6317d83ec2b57624a7df1071 100644 --- a/src/pl/plpgsql/src/scan.l +++ b/src/pl/plpgsql/src/scan.l @@ -4,7 +4,7 @@ * procedural language * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Attic/scan.l,v 1.6 2000/08/31 13:26:16 wieck Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Attic/scan.l,v 1.7 2000/09/05 09:02:18 wieck Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -97,6 +97,7 @@ constant { return K_CONSTANT; } debug { return K_DEBUG; } declare { return K_DECLARE; } default { return K_DEFAULT; } +diagnostics { return K_DIAGNOSTICS; } else { return K_ELSE; } end { return K_END; } exception { return K_EXCEPTION; } @@ -104,6 +105,7 @@ execute { return K_EXECUTE; } exit { return K_EXIT; } for { return K_FOR; } from { return K_FROM; } +get { return K_GET; } if { return K_IF; } in { return K_IN; } into { return K_INTO; } @@ -112,9 +114,11 @@ not { return K_NOT; } notice { return K_NOTICE; } null { return K_NULL; } perform { return K_PERFORM; } +processed { return K_PROCESSED; } raise { return K_RAISE; } record { return K_RECORD; } rename { return K_RENAME; } +result { return K_RESULT; } return { return K_RETURN; } reverse { return K_REVERSE; } select { return K_SELECT; }