Skip to content

Commit c59077d

Browse files
Jan WieckJan Wieck
authored andcommitted
GET DIAGNOSTICS statement to PL/pgSQL to access SPI_processed
and SPI_return values. Patch from Philip Warner. Jan
1 parent 4bfb75a commit c59077d

File tree

5 files changed

+236
-9
lines changed

5 files changed

+236
-9
lines changed

src/pl/plpgsql/src/gram.y

Lines changed: 106 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* procedural language
55
*
66
* IDENTIFICATION
7-
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.11 2000/08/31 13:26:15 wieck Exp $
7+
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.12 2000/09/05 09:02:18 wieck Exp $
88
*
99
* This software is copyrighted by Jan Wieck - Hamburg.
1010
*
@@ -113,12 +113,15 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
113113
%type <stmt> stmt_assign, stmt_if, stmt_loop, stmt_while, stmt_exit
114114
%type <stmt> stmt_return, stmt_raise, stmt_execsql, stmt_fori
115115
%type <stmt> stmt_fors, stmt_select, stmt_perform
116-
%type <stmt> stmt_dynexecute, stmt_dynfors
116+
%type <stmt> stmt_dynexecute, stmt_dynfors, stmt_getdiag
117117

118118
%type <dtlist> raise_params
119119
%type <ival> raise_level, raise_param
120120
%type <str> raise_msg
121121

122+
%type <dtlist> getdiag_items, getdiag_targets
123+
%type <ival> getdiag_item, getdiag_target
124+
122125
%type <ival> lno
123126

124127
/*
@@ -131,6 +134,7 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
131134
%token K_DEBUG
132135
%token K_DECLARE
133136
%token K_DEFAULT
137+
%token K_DIAGNOSTICS
134138
%token K_DOTDOT
135139
%token K_ELSE
136140
%token K_END
@@ -139,6 +143,7 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
139143
%token K_EXIT
140144
%token K_FOR
141145
%token K_FROM
146+
%token K_GET
142147
%token K_IF
143148
%token K_IN
144149
%token K_INTO
@@ -147,9 +152,11 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
147152
%token K_NOTICE
148153
%token K_NULL
149154
%token K_PERFORM
155+
%token K_PROCESSED
150156
%token K_RAISE
151157
%token K_RECORD
152158
%token K_RENAME
159+
%token K_RESULT
153160
%token K_RETURN
154161
%token K_REVERSE
155162
%token K_SELECT
@@ -371,7 +378,7 @@ decl_rowtype : T_ROW
371378

372379
decl_varname : T_WORD
373380
{
374-
$$.name = strdup(yytext);
381+
$$.name = plpgsql_tolower(strdup(yytext));
375382
$$.lineno = yylineno;
376383
}
377384
;
@@ -576,6 +583,8 @@ proc_stmt : pl_block
576583
{ $$ = $1; }
577584
| stmt_perform
578585
{ $$ = $1; }
586+
| stmt_getdiag
587+
{ $$ = $1; }
579588
;
580589

581590
stmt_perform : K_PERFORM lno expr_until_semi
@@ -610,6 +619,100 @@ stmt_assign : assign_var lno K_ASSIGN expr_until_semi
610619
}
611620
;
612621

622+
stmt_getdiag : K_GET K_DIAGNOSTICS lno K_SELECT getdiag_items K_INTO getdiag_targets ';'
623+
{
624+
PLpgSQL_stmt_getdiag *new;
625+
626+
new = malloc(sizeof(PLpgSQL_stmt_getdiag));
627+
memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
628+
629+
new->cmd_type = PLPGSQL_STMT_GETDIAG;
630+
new->lineno = $3;
631+
new->nitems = $5.nused;
632+
new->items = malloc(sizeof(int) * $5.nused);
633+
new->ntargets = $7.nused;
634+
new->targets = malloc(sizeof(int) * $7.nused);
635+
memcpy(new->items, $5.dtnums, sizeof(int) * $5.nused);
636+
memcpy(new->targets, $7.dtnums, sizeof(int) * $7.nused);
637+
638+
if (new->nitems != new->ntargets) {
639+
plpgsql_error_lineno = new->lineno;
640+
plpgsql_comperrinfo();
641+
elog(ERROR, "number of diagnostic items does not match target list");
642+
};
643+
644+
$$ = (PLpgSQL_stmt *)new;
645+
}
646+
;
647+
648+
getdiag_items : getdiag_items ',' getdiag_item
649+
{
650+
if ($1.nused == $1.nalloc) {
651+
$1.nalloc *= 2;
652+
$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
653+
}
654+
$1.dtnums[$1.nused++] = $3;
655+
656+
$$.nalloc = $1.nalloc;
657+
$$.nused = $1.nused;
658+
$$.dtnums = $1.dtnums;
659+
}
660+
| getdiag_item
661+
{
662+
$$.nalloc = 1;
663+
$$.nused = 1;
664+
$$.dtnums = palloc(sizeof(int) * $$.nalloc);
665+
$$.dtnums[0] = $1;
666+
}
667+
;
668+
669+
getdiag_item : K_PROCESSED
670+
{
671+
$$ = PLPGSQL_GETDIAG_PROCESSED;
672+
}
673+
| K_RESULT
674+
{
675+
$$ = PLPGSQL_GETDIAG_RESULT;
676+
}
677+
;
678+
679+
getdiag_targets : getdiag_targets ',' getdiag_target
680+
{
681+
if ($1.nused == $1.nalloc) {
682+
$1.nalloc *= 2;
683+
$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
684+
}
685+
$1.dtnums[$1.nused++] = $3;
686+
687+
$$.nalloc = $1.nalloc;
688+
$$.nused = $1.nused;
689+
$$.dtnums = $1.dtnums;
690+
}
691+
| getdiag_target
692+
{
693+
$$.nalloc = 1;
694+
$$.nused = 1;
695+
$$.dtnums = palloc(sizeof(int) * $$.nalloc);
696+
$$.dtnums[0] = $1;
697+
}
698+
;
699+
700+
701+
getdiag_target : T_VARIABLE
702+
{
703+
if (yylval.var->isconst) {
704+
plpgsql_comperrinfo();
705+
elog(ERROR, "%s is declared CONSTANT; can not receive diagnostics", yylval.var->refname);
706+
}
707+
$$ = yylval.var->varno;
708+
}
709+
| T_RECFIELD
710+
{
711+
$$ = yylval.recfield->rfno;
712+
}
713+
;
714+
715+
613716
assign_var : T_VARIABLE
614717
{
615718
if (yylval.var->isconst) {

src/pl/plpgsql/src/pl_exec.c

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.29 2000/08/31 13:26:16 wieck Exp $
6+
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.30 2000/09/05 09:02:18 wieck Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -80,6 +80,8 @@ static int exec_stmt(PLpgSQL_execstate * estate,
8080
PLpgSQL_stmt * stmt);
8181
static int exec_stmt_assign(PLpgSQL_execstate * estate,
8282
PLpgSQL_stmt_assign * stmt);
83+
static int exec_stmt_getdiag(PLpgSQL_execstate * estate,
84+
PLpgSQL_stmt_getdiag * stmt);
8385
static int exec_stmt_if(PLpgSQL_execstate * estate,
8486
PLpgSQL_stmt_if * stmt);
8587
static int exec_stmt_loop(PLpgSQL_execstate * estate,
@@ -193,6 +195,9 @@ plpgsql_exec_function(PLpgSQL_function * func, FunctionCallInfo fcinfo)
193195
case PLPGSQL_STMT_ASSIGN:
194196
stmttype = "assignment";
195197
break;
198+
case PLPGSQL_STMT_GETDIAG:
199+
stmttype = "get diagnostics";
200+
break;
196201
case PLPGSQL_STMT_IF:
197202
stmttype = "if";
198203
break;
@@ -502,6 +507,9 @@ plpgsql_exec_trigger(PLpgSQL_function * func,
502507
case PLPGSQL_STMT_ASSIGN:
503508
stmttype = "assignment";
504509
break;
510+
case PLPGSQL_STMT_GETDIAG:
511+
stmttype = "get diagnostics";
512+
break;
505513
case PLPGSQL_STMT_IF:
506514
stmttype = "if";
507515
break;
@@ -971,6 +979,10 @@ exec_stmt(PLpgSQL_execstate * estate, PLpgSQL_stmt * stmt)
971979
rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt);
972980
break;
973981

982+
case PLPGSQL_STMT_GETDIAG:
983+
rc = exec_stmt_getdiag(estate, (PLpgSQL_stmt_getdiag *) stmt);
984+
break;
985+
974986
case PLPGSQL_STMT_IF:
975987
rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt);
976988
break;
@@ -1047,6 +1059,49 @@ exec_stmt_assign(PLpgSQL_execstate * estate, PLpgSQL_stmt_assign * stmt)
10471059
return PLPGSQL_RC_OK;
10481060
}
10491061

1062+
/* ----------
1063+
* exec_stmt_getdiag Put internal PG information into
1064+
* specified variables.
1065+
* ----------
1066+
*/
1067+
static int
1068+
exec_stmt_getdiag(PLpgSQL_execstate * estate, PLpgSQL_stmt_getdiag * stmt)
1069+
{
1070+
int i;
1071+
PLpgSQL_datum *var;
1072+
HeapTuple typeTup;
1073+
bool isnull = false;
1074+
1075+
for ( i=0 ; i < stmt->nitems ; i++)
1076+
{
1077+
if ((stmt->targets[i] <= 0))
1078+
break;
1079+
1080+
var = (estate->datums[stmt->targets[i]]);
1081+
1082+
if (var == NULL)
1083+
break;
1084+
1085+
switch (stmt->items[i])
1086+
{
1087+
case PLPGSQL_GETDIAG_PROCESSED:
1088+
1089+
exec_assign_value(estate, var, (Datum)SPI_processed, INT4OID, &isnull);
1090+
break;
1091+
1092+
case PLPGSQL_GETDIAG_RESULT:
1093+
1094+
exec_assign_value(estate, var, (Datum)SPI_result, INT4OID, &isnull);
1095+
break;
1096+
1097+
default:
1098+
1099+
elog(ERROR, "unknown attribute request %d in get_diagnostic", stmt->items[i]);
1100+
};
1101+
};
1102+
1103+
return PLPGSQL_RC_OK;
1104+
}
10501105

10511106
/* ----------
10521107
* exec_stmt_if Evaluate a bool expression and

src/pl/plpgsql/src/pl_funcs.c

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.7 2000/08/31 13:26:16 wieck Exp $
6+
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.8 2000/09/05 09:02:18 wieck Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -390,6 +390,7 @@ static void dump_raise(PLpgSQL_stmt_raise * stmt);
390390
static void dump_execsql(PLpgSQL_stmt_execsql * stmt);
391391
static void dump_dynexecute(PLpgSQL_stmt_dynexecute * stmt);
392392
static void dump_dynfors(PLpgSQL_stmt_dynfors * stmt);
393+
static void dump_getdiag(PLpgSQL_stmt_getdiag * stmt);
393394
static void dump_expr(PLpgSQL_expr * expr);
394395

395396

@@ -450,6 +451,9 @@ dump_stmt(PLpgSQL_stmt * stmt)
450451
case PLPGSQL_STMT_DYNFORS:
451452
dump_dynfors((PLpgSQL_stmt_dynfors *) stmt);
452453
break;
454+
case PLPGSQL_STMT_GETDIAG:
455+
dump_getdiag((PLpgSQL_stmt_getdiag *) stmt);
456+
break;
453457
default:
454458
elog(ERROR, "plpgsql_dump: unknown cmd_type %d\n", stmt->cmd_type);
455459
break;
@@ -637,7 +641,7 @@ dump_return(PLpgSQL_stmt_return * stmt)
637641
{
638642
dump_ind();
639643
printf("RETURN ");
640-
if (stmt->retrecno >= 0)
644+
if (stmt->retrecno > 0)
641645
printf("record %d", stmt->retrecno);
642646
else
643647
{
@@ -698,6 +702,45 @@ dump_dynfors(PLpgSQL_stmt_dynfors * stmt)
698702
printf(" ENDFORS\n");
699703
}
700704

705+
static void
706+
dump_getdiag(PLpgSQL_stmt_getdiag * stmt)
707+
{
708+
int i;
709+
710+
dump_ind();
711+
printf("GET DIAGNOSTICS SELECT ");
712+
for (i = 0; i < stmt->nitems; i++)
713+
{
714+
if (i != 0)
715+
printf(", ");
716+
717+
switch (stmt->items[i])
718+
{
719+
case PLPGSQL_GETDIAG_PROCESSED:
720+
printf("PROCESSED");
721+
break;
722+
723+
case PLPGSQL_GETDIAG_RESULT:
724+
printf("RESULT");
725+
break;
726+
727+
default:
728+
printf("???");
729+
break;
730+
}
731+
}
732+
printf(" INTO ");
733+
for (i = 0; i < stmt->ntargets; i++)
734+
{
735+
if (i != 0)
736+
printf(", ");
737+
738+
printf("{var %d}", stmt->targets[i]);
739+
}
740+
741+
printf("\n");
742+
}
743+
701744
static void
702745
dump_expr(PLpgSQL_expr * expr)
703746
{

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy