00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "plpgsql.h"
00017
00018 #include "utils/memutils.h"
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 static PLpgSQL_nsitem *ns_top = NULL;
00036
00037
00038
00039
00040
00041
00042 void
00043 plpgsql_ns_init(void)
00044 {
00045 ns_top = NULL;
00046 }
00047
00048
00049
00050
00051
00052
00053 void
00054 plpgsql_ns_push(const char *label)
00055 {
00056 if (label == NULL)
00057 label = "";
00058 plpgsql_ns_additem(PLPGSQL_NSTYPE_LABEL, 0, label);
00059 }
00060
00061
00062
00063
00064
00065
00066 void
00067 plpgsql_ns_pop(void)
00068 {
00069 Assert(ns_top != NULL);
00070 while (ns_top->itemtype != PLPGSQL_NSTYPE_LABEL)
00071 ns_top = ns_top->prev;
00072 ns_top = ns_top->prev;
00073 }
00074
00075
00076
00077
00078
00079
00080 PLpgSQL_nsitem *
00081 plpgsql_ns_top(void)
00082 {
00083 return ns_top;
00084 }
00085
00086
00087
00088
00089
00090
00091 void
00092 plpgsql_ns_additem(int itemtype, int itemno, const char *name)
00093 {
00094 PLpgSQL_nsitem *nse;
00095
00096 Assert(name != NULL);
00097
00098 Assert(ns_top != NULL || itemtype == PLPGSQL_NSTYPE_LABEL);
00099
00100 nse = palloc(sizeof(PLpgSQL_nsitem) + strlen(name));
00101 nse->itemtype = itemtype;
00102 nse->itemno = itemno;
00103 nse->prev = ns_top;
00104 strcpy(nse->name, name);
00105 ns_top = nse;
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 PLpgSQL_nsitem *
00130 plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode,
00131 const char *name1, const char *name2, const char *name3,
00132 int *names_used)
00133 {
00134
00135 while (ns_cur != NULL)
00136 {
00137 PLpgSQL_nsitem *nsitem;
00138
00139
00140 for (nsitem = ns_cur;
00141 nsitem->itemtype != PLPGSQL_NSTYPE_LABEL;
00142 nsitem = nsitem->prev)
00143 {
00144 if (strcmp(nsitem->name, name1) == 0)
00145 {
00146 if (name2 == NULL ||
00147 nsitem->itemtype != PLPGSQL_NSTYPE_VAR)
00148 {
00149 if (names_used)
00150 *names_used = 1;
00151 return nsitem;
00152 }
00153 }
00154 }
00155
00156
00157 if (name2 != NULL &&
00158 strcmp(nsitem->name, name1) == 0)
00159 {
00160 for (nsitem = ns_cur;
00161 nsitem->itemtype != PLPGSQL_NSTYPE_LABEL;
00162 nsitem = nsitem->prev)
00163 {
00164 if (strcmp(nsitem->name, name2) == 0)
00165 {
00166 if (name3 == NULL ||
00167 nsitem->itemtype != PLPGSQL_NSTYPE_VAR)
00168 {
00169 if (names_used)
00170 *names_used = 2;
00171 return nsitem;
00172 }
00173 }
00174 }
00175 }
00176
00177 if (localmode)
00178 break;
00179
00180 ns_cur = nsitem->prev;
00181 }
00182
00183
00184 if (names_used)
00185 *names_used = 0;
00186 return NULL;
00187 }
00188
00189
00190
00191
00192
00193
00194 PLpgSQL_nsitem *
00195 plpgsql_ns_lookup_label(PLpgSQL_nsitem *ns_cur, const char *name)
00196 {
00197 while (ns_cur != NULL)
00198 {
00199 if (ns_cur->itemtype == PLPGSQL_NSTYPE_LABEL &&
00200 strcmp(ns_cur->name, name) == 0)
00201 return ns_cur;
00202 ns_cur = ns_cur->prev;
00203 }
00204
00205 return NULL;
00206 }
00207
00208
00209
00210
00211
00212 const char *
00213 plpgsql_stmt_typename(PLpgSQL_stmt *stmt)
00214 {
00215 switch ((enum PLpgSQL_stmt_types) stmt->cmd_type)
00216 {
00217 case PLPGSQL_STMT_BLOCK:
00218 return _("statement block");
00219 case PLPGSQL_STMT_ASSIGN:
00220 return _("assignment");
00221 case PLPGSQL_STMT_IF:
00222 return "IF";
00223 case PLPGSQL_STMT_CASE:
00224 return "CASE";
00225 case PLPGSQL_STMT_LOOP:
00226 return "LOOP";
00227 case PLPGSQL_STMT_WHILE:
00228 return "WHILE";
00229 case PLPGSQL_STMT_FORI:
00230 return _("FOR with integer loop variable");
00231 case PLPGSQL_STMT_FORS:
00232 return _("FOR over SELECT rows");
00233 case PLPGSQL_STMT_FORC:
00234 return _("FOR over cursor");
00235 case PLPGSQL_STMT_FOREACH_A:
00236 return _("FOREACH over array");
00237 case PLPGSQL_STMT_EXIT:
00238 return "EXIT";
00239 case PLPGSQL_STMT_RETURN:
00240 return "RETURN";
00241 case PLPGSQL_STMT_RETURN_NEXT:
00242 return "RETURN NEXT";
00243 case PLPGSQL_STMT_RETURN_QUERY:
00244 return "RETURN QUERY";
00245 case PLPGSQL_STMT_RAISE:
00246 return "RAISE";
00247 case PLPGSQL_STMT_EXECSQL:
00248 return _("SQL statement");
00249 case PLPGSQL_STMT_DYNEXECUTE:
00250 return _("EXECUTE statement");
00251 case PLPGSQL_STMT_DYNFORS:
00252 return _("FOR over EXECUTE statement");
00253 case PLPGSQL_STMT_GETDIAG:
00254 return "GET DIAGNOSTICS";
00255 case PLPGSQL_STMT_OPEN:
00256 return "OPEN";
00257 case PLPGSQL_STMT_FETCH:
00258 return "FETCH";
00259 case PLPGSQL_STMT_CLOSE:
00260 return "CLOSE";
00261 case PLPGSQL_STMT_PERFORM:
00262 return "PERFORM";
00263 }
00264
00265 return "unknown";
00266 }
00267
00268
00269
00270
00271 const char *
00272 plpgsql_getdiag_kindname(int kind)
00273 {
00274 switch (kind)
00275 {
00276 case PLPGSQL_GETDIAG_ROW_COUNT:
00277 return "ROW_COUNT";
00278 case PLPGSQL_GETDIAG_RESULT_OID:
00279 return "RESULT_OID";
00280 case PLPGSQL_GETDIAG_ERROR_CONTEXT:
00281 return "PG_EXCEPTION_CONTEXT";
00282 case PLPGSQL_GETDIAG_ERROR_DETAIL:
00283 return "PG_EXCEPTION_DETAIL";
00284 case PLPGSQL_GETDIAG_ERROR_HINT:
00285 return "PG_EXCEPTION_HINT";
00286 case PLPGSQL_GETDIAG_RETURNED_SQLSTATE:
00287 return "RETURNED_SQLSTATE";
00288 case PLPGSQL_GETDIAG_MESSAGE_TEXT:
00289 return "MESSAGE_TEXT";
00290 }
00291
00292 return "unknown";
00293 }
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 static void free_stmt(PLpgSQL_stmt *stmt);
00306 static void free_block(PLpgSQL_stmt_block *block);
00307 static void free_assign(PLpgSQL_stmt_assign *stmt);
00308 static void free_if(PLpgSQL_stmt_if *stmt);
00309 static void free_case(PLpgSQL_stmt_case *stmt);
00310 static void free_loop(PLpgSQL_stmt_loop *stmt);
00311 static void free_while(PLpgSQL_stmt_while *stmt);
00312 static void free_fori(PLpgSQL_stmt_fori *stmt);
00313 static void free_fors(PLpgSQL_stmt_fors *stmt);
00314 static void free_forc(PLpgSQL_stmt_forc *stmt);
00315 static void free_foreach_a(PLpgSQL_stmt_foreach_a *stmt);
00316 static void free_exit(PLpgSQL_stmt_exit *stmt);
00317 static void free_return(PLpgSQL_stmt_return *stmt);
00318 static void free_return_next(PLpgSQL_stmt_return_next *stmt);
00319 static void free_return_query(PLpgSQL_stmt_return_query *stmt);
00320 static void free_raise(PLpgSQL_stmt_raise *stmt);
00321 static void free_execsql(PLpgSQL_stmt_execsql *stmt);
00322 static void free_dynexecute(PLpgSQL_stmt_dynexecute *stmt);
00323 static void free_dynfors(PLpgSQL_stmt_dynfors *stmt);
00324 static void free_getdiag(PLpgSQL_stmt_getdiag *stmt);
00325 static void free_open(PLpgSQL_stmt_open *stmt);
00326 static void free_fetch(PLpgSQL_stmt_fetch *stmt);
00327 static void free_close(PLpgSQL_stmt_close *stmt);
00328 static void free_perform(PLpgSQL_stmt_perform *stmt);
00329 static void free_expr(PLpgSQL_expr *expr);
00330
00331
00332 static void
00333 free_stmt(PLpgSQL_stmt *stmt)
00334 {
00335 switch ((enum PLpgSQL_stmt_types) stmt->cmd_type)
00336 {
00337 case PLPGSQL_STMT_BLOCK:
00338 free_block((PLpgSQL_stmt_block *) stmt);
00339 break;
00340 case PLPGSQL_STMT_ASSIGN:
00341 free_assign((PLpgSQL_stmt_assign *) stmt);
00342 break;
00343 case PLPGSQL_STMT_IF:
00344 free_if((PLpgSQL_stmt_if *) stmt);
00345 break;
00346 case PLPGSQL_STMT_CASE:
00347 free_case((PLpgSQL_stmt_case *) stmt);
00348 break;
00349 case PLPGSQL_STMT_LOOP:
00350 free_loop((PLpgSQL_stmt_loop *) stmt);
00351 break;
00352 case PLPGSQL_STMT_WHILE:
00353 free_while((PLpgSQL_stmt_while *) stmt);
00354 break;
00355 case PLPGSQL_STMT_FORI:
00356 free_fori((PLpgSQL_stmt_fori *) stmt);
00357 break;
00358 case PLPGSQL_STMT_FORS:
00359 free_fors((PLpgSQL_stmt_fors *) stmt);
00360 break;
00361 case PLPGSQL_STMT_FORC:
00362 free_forc((PLpgSQL_stmt_forc *) stmt);
00363 break;
00364 case PLPGSQL_STMT_FOREACH_A:
00365 free_foreach_a((PLpgSQL_stmt_foreach_a *) stmt);
00366 break;
00367 case PLPGSQL_STMT_EXIT:
00368 free_exit((PLpgSQL_stmt_exit *) stmt);
00369 break;
00370 case PLPGSQL_STMT_RETURN:
00371 free_return((PLpgSQL_stmt_return *) stmt);
00372 break;
00373 case PLPGSQL_STMT_RETURN_NEXT:
00374 free_return_next((PLpgSQL_stmt_return_next *) stmt);
00375 break;
00376 case PLPGSQL_STMT_RETURN_QUERY:
00377 free_return_query((PLpgSQL_stmt_return_query *) stmt);
00378 break;
00379 case PLPGSQL_STMT_RAISE:
00380 free_raise((PLpgSQL_stmt_raise *) stmt);
00381 break;
00382 case PLPGSQL_STMT_EXECSQL:
00383 free_execsql((PLpgSQL_stmt_execsql *) stmt);
00384 break;
00385 case PLPGSQL_STMT_DYNEXECUTE:
00386 free_dynexecute((PLpgSQL_stmt_dynexecute *) stmt);
00387 break;
00388 case PLPGSQL_STMT_DYNFORS:
00389 free_dynfors((PLpgSQL_stmt_dynfors *) stmt);
00390 break;
00391 case PLPGSQL_STMT_GETDIAG:
00392 free_getdiag((PLpgSQL_stmt_getdiag *) stmt);
00393 break;
00394 case PLPGSQL_STMT_OPEN:
00395 free_open((PLpgSQL_stmt_open *) stmt);
00396 break;
00397 case PLPGSQL_STMT_FETCH:
00398 free_fetch((PLpgSQL_stmt_fetch *) stmt);
00399 break;
00400 case PLPGSQL_STMT_CLOSE:
00401 free_close((PLpgSQL_stmt_close *) stmt);
00402 break;
00403 case PLPGSQL_STMT_PERFORM:
00404 free_perform((PLpgSQL_stmt_perform *) stmt);
00405 break;
00406 default:
00407 elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
00408 break;
00409 }
00410 }
00411
00412 static void
00413 free_stmts(List *stmts)
00414 {
00415 ListCell *s;
00416
00417 foreach(s, stmts)
00418 {
00419 free_stmt((PLpgSQL_stmt *) lfirst(s));
00420 }
00421 }
00422
00423 static void
00424 free_block(PLpgSQL_stmt_block *block)
00425 {
00426 free_stmts(block->body);
00427 if (block->exceptions)
00428 {
00429 ListCell *e;
00430
00431 foreach(e, block->exceptions->exc_list)
00432 {
00433 PLpgSQL_exception *exc = (PLpgSQL_exception *) lfirst(e);
00434
00435 free_stmts(exc->action);
00436 }
00437 }
00438 }
00439
00440 static void
00441 free_assign(PLpgSQL_stmt_assign *stmt)
00442 {
00443 free_expr(stmt->expr);
00444 }
00445
00446 static void
00447 free_if(PLpgSQL_stmt_if *stmt)
00448 {
00449 ListCell *l;
00450
00451 free_expr(stmt->cond);
00452 free_stmts(stmt->then_body);
00453 foreach(l, stmt->elsif_list)
00454 {
00455 PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *) lfirst(l);
00456
00457 free_expr(elif->cond);
00458 free_stmts(elif->stmts);
00459 }
00460 free_stmts(stmt->else_body);
00461 }
00462
00463 static void
00464 free_case(PLpgSQL_stmt_case *stmt)
00465 {
00466 ListCell *l;
00467
00468 free_expr(stmt->t_expr);
00469 foreach(l, stmt->case_when_list)
00470 {
00471 PLpgSQL_case_when *cwt = (PLpgSQL_case_when *) lfirst(l);
00472
00473 free_expr(cwt->expr);
00474 free_stmts(cwt->stmts);
00475 }
00476 free_stmts(stmt->else_stmts);
00477 }
00478
00479 static void
00480 free_loop(PLpgSQL_stmt_loop *stmt)
00481 {
00482 free_stmts(stmt->body);
00483 }
00484
00485 static void
00486 free_while(PLpgSQL_stmt_while *stmt)
00487 {
00488 free_expr(stmt->cond);
00489 free_stmts(stmt->body);
00490 }
00491
00492 static void
00493 free_fori(PLpgSQL_stmt_fori *stmt)
00494 {
00495 free_expr(stmt->lower);
00496 free_expr(stmt->upper);
00497 free_expr(stmt->step);
00498 free_stmts(stmt->body);
00499 }
00500
00501 static void
00502 free_fors(PLpgSQL_stmt_fors *stmt)
00503 {
00504 free_stmts(stmt->body);
00505 free_expr(stmt->query);
00506 }
00507
00508 static void
00509 free_forc(PLpgSQL_stmt_forc *stmt)
00510 {
00511 free_stmts(stmt->body);
00512 free_expr(stmt->argquery);
00513 }
00514
00515 static void
00516 free_foreach_a(PLpgSQL_stmt_foreach_a *stmt)
00517 {
00518 free_expr(stmt->expr);
00519 free_stmts(stmt->body);
00520 }
00521
00522 static void
00523 free_open(PLpgSQL_stmt_open *stmt)
00524 {
00525 ListCell *lc;
00526
00527 free_expr(stmt->argquery);
00528 free_expr(stmt->query);
00529 free_expr(stmt->dynquery);
00530 foreach(lc, stmt->params)
00531 {
00532 free_expr((PLpgSQL_expr *) lfirst(lc));
00533 }
00534 }
00535
00536 static void
00537 free_fetch(PLpgSQL_stmt_fetch *stmt)
00538 {
00539 free_expr(stmt->expr);
00540 }
00541
00542 static void
00543 free_close(PLpgSQL_stmt_close *stmt)
00544 {
00545 }
00546
00547 static void
00548 free_perform(PLpgSQL_stmt_perform *stmt)
00549 {
00550 free_expr(stmt->expr);
00551 }
00552
00553 static void
00554 free_exit(PLpgSQL_stmt_exit *stmt)
00555 {
00556 free_expr(stmt->cond);
00557 }
00558
00559 static void
00560 free_return(PLpgSQL_stmt_return *stmt)
00561 {
00562 free_expr(stmt->expr);
00563 }
00564
00565 static void
00566 free_return_next(PLpgSQL_stmt_return_next *stmt)
00567 {
00568 free_expr(stmt->expr);
00569 }
00570
00571 static void
00572 free_return_query(PLpgSQL_stmt_return_query *stmt)
00573 {
00574 ListCell *lc;
00575
00576 free_expr(stmt->query);
00577 free_expr(stmt->dynquery);
00578 foreach(lc, stmt->params)
00579 {
00580 free_expr((PLpgSQL_expr *) lfirst(lc));
00581 }
00582 }
00583
00584 static void
00585 free_raise(PLpgSQL_stmt_raise *stmt)
00586 {
00587 ListCell *lc;
00588
00589 foreach(lc, stmt->params)
00590 {
00591 free_expr((PLpgSQL_expr *) lfirst(lc));
00592 }
00593 foreach(lc, stmt->options)
00594 {
00595 PLpgSQL_raise_option *opt = (PLpgSQL_raise_option *) lfirst(lc);
00596
00597 free_expr(opt->expr);
00598 }
00599 }
00600
00601 static void
00602 free_execsql(PLpgSQL_stmt_execsql *stmt)
00603 {
00604 free_expr(stmt->sqlstmt);
00605 }
00606
00607 static void
00608 free_dynexecute(PLpgSQL_stmt_dynexecute *stmt)
00609 {
00610 ListCell *lc;
00611
00612 free_expr(stmt->query);
00613 foreach(lc, stmt->params)
00614 {
00615 free_expr((PLpgSQL_expr *) lfirst(lc));
00616 }
00617 }
00618
00619 static void
00620 free_dynfors(PLpgSQL_stmt_dynfors *stmt)
00621 {
00622 ListCell *lc;
00623
00624 free_stmts(stmt->body);
00625 free_expr(stmt->query);
00626 foreach(lc, stmt->params)
00627 {
00628 free_expr((PLpgSQL_expr *) lfirst(lc));
00629 }
00630 }
00631
00632 static void
00633 free_getdiag(PLpgSQL_stmt_getdiag *stmt)
00634 {
00635 }
00636
00637 static void
00638 free_expr(PLpgSQL_expr *expr)
00639 {
00640 if (expr && expr->plan)
00641 {
00642 SPI_freeplan(expr->plan);
00643 expr->plan = NULL;
00644 }
00645 }
00646
00647 void
00648 plpgsql_free_function_memory(PLpgSQL_function *func)
00649 {
00650 int i;
00651
00652
00653 Assert(func->use_count == 0);
00654
00655
00656 for (i = 0; i < func->ndatums; i++)
00657 {
00658 PLpgSQL_datum *d = func->datums[i];
00659
00660 switch (d->dtype)
00661 {
00662 case PLPGSQL_DTYPE_VAR:
00663 {
00664 PLpgSQL_var *var = (PLpgSQL_var *) d;
00665
00666 free_expr(var->default_val);
00667 free_expr(var->cursor_explicit_expr);
00668 }
00669 break;
00670 case PLPGSQL_DTYPE_ROW:
00671 break;
00672 case PLPGSQL_DTYPE_REC:
00673 break;
00674 case PLPGSQL_DTYPE_RECFIELD:
00675 break;
00676 case PLPGSQL_DTYPE_ARRAYELEM:
00677 free_expr(((PLpgSQL_arrayelem *) d)->subscript);
00678 break;
00679 default:
00680 elog(ERROR, "unrecognized data type: %d", d->dtype);
00681 }
00682 }
00683 func->ndatums = 0;
00684
00685
00686 if (func->action)
00687 free_block(func->action);
00688 func->action = NULL;
00689
00690
00691
00692
00693
00694
00695 if (func->fn_cxt)
00696 MemoryContextDelete(func->fn_cxt);
00697 func->fn_cxt = NULL;
00698 }
00699
00700
00701
00702
00703
00704 static int dump_indent;
00705
00706 static void dump_ind(void);
00707 static void dump_stmt(PLpgSQL_stmt *stmt);
00708 static void dump_block(PLpgSQL_stmt_block *block);
00709 static void dump_assign(PLpgSQL_stmt_assign *stmt);
00710 static void dump_if(PLpgSQL_stmt_if *stmt);
00711 static void dump_case(PLpgSQL_stmt_case *stmt);
00712 static void dump_loop(PLpgSQL_stmt_loop *stmt);
00713 static void dump_while(PLpgSQL_stmt_while *stmt);
00714 static void dump_fori(PLpgSQL_stmt_fori *stmt);
00715 static void dump_fors(PLpgSQL_stmt_fors *stmt);
00716 static void dump_forc(PLpgSQL_stmt_forc *stmt);
00717 static void dump_foreach_a(PLpgSQL_stmt_foreach_a *stmt);
00718 static void dump_exit(PLpgSQL_stmt_exit *stmt);
00719 static void dump_return(PLpgSQL_stmt_return *stmt);
00720 static void dump_return_next(PLpgSQL_stmt_return_next *stmt);
00721 static void dump_return_query(PLpgSQL_stmt_return_query *stmt);
00722 static void dump_raise(PLpgSQL_stmt_raise *stmt);
00723 static void dump_execsql(PLpgSQL_stmt_execsql *stmt);
00724 static void dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt);
00725 static void dump_dynfors(PLpgSQL_stmt_dynfors *stmt);
00726 static void dump_getdiag(PLpgSQL_stmt_getdiag *stmt);
00727 static void dump_open(PLpgSQL_stmt_open *stmt);
00728 static void dump_fetch(PLpgSQL_stmt_fetch *stmt);
00729 static void dump_cursor_direction(PLpgSQL_stmt_fetch *stmt);
00730 static void dump_close(PLpgSQL_stmt_close *stmt);
00731 static void dump_perform(PLpgSQL_stmt_perform *stmt);
00732 static void dump_expr(PLpgSQL_expr *expr);
00733
00734
00735 static void
00736 dump_ind(void)
00737 {
00738 int i;
00739
00740 for (i = 0; i < dump_indent; i++)
00741 printf(" ");
00742 }
00743
00744 static void
00745 dump_stmt(PLpgSQL_stmt *stmt)
00746 {
00747 printf("%3d:", stmt->lineno);
00748 switch ((enum PLpgSQL_stmt_types) stmt->cmd_type)
00749 {
00750 case PLPGSQL_STMT_BLOCK:
00751 dump_block((PLpgSQL_stmt_block *) stmt);
00752 break;
00753 case PLPGSQL_STMT_ASSIGN:
00754 dump_assign((PLpgSQL_stmt_assign *) stmt);
00755 break;
00756 case PLPGSQL_STMT_IF:
00757 dump_if((PLpgSQL_stmt_if *) stmt);
00758 break;
00759 case PLPGSQL_STMT_CASE:
00760 dump_case((PLpgSQL_stmt_case *) stmt);
00761 break;
00762 case PLPGSQL_STMT_LOOP:
00763 dump_loop((PLpgSQL_stmt_loop *) stmt);
00764 break;
00765 case PLPGSQL_STMT_WHILE:
00766 dump_while((PLpgSQL_stmt_while *) stmt);
00767 break;
00768 case PLPGSQL_STMT_FORI:
00769 dump_fori((PLpgSQL_stmt_fori *) stmt);
00770 break;
00771 case PLPGSQL_STMT_FORS:
00772 dump_fors((PLpgSQL_stmt_fors *) stmt);
00773 break;
00774 case PLPGSQL_STMT_FORC:
00775 dump_forc((PLpgSQL_stmt_forc *) stmt);
00776 break;
00777 case PLPGSQL_STMT_FOREACH_A:
00778 dump_foreach_a((PLpgSQL_stmt_foreach_a *) stmt);
00779 break;
00780 case PLPGSQL_STMT_EXIT:
00781 dump_exit((PLpgSQL_stmt_exit *) stmt);
00782 break;
00783 case PLPGSQL_STMT_RETURN:
00784 dump_return((PLpgSQL_stmt_return *) stmt);
00785 break;
00786 case PLPGSQL_STMT_RETURN_NEXT:
00787 dump_return_next((PLpgSQL_stmt_return_next *) stmt);
00788 break;
00789 case PLPGSQL_STMT_RETURN_QUERY:
00790 dump_return_query((PLpgSQL_stmt_return_query *) stmt);
00791 break;
00792 case PLPGSQL_STMT_RAISE:
00793 dump_raise((PLpgSQL_stmt_raise *) stmt);
00794 break;
00795 case PLPGSQL_STMT_EXECSQL:
00796 dump_execsql((PLpgSQL_stmt_execsql *) stmt);
00797 break;
00798 case PLPGSQL_STMT_DYNEXECUTE:
00799 dump_dynexecute((PLpgSQL_stmt_dynexecute *) stmt);
00800 break;
00801 case PLPGSQL_STMT_DYNFORS:
00802 dump_dynfors((PLpgSQL_stmt_dynfors *) stmt);
00803 break;
00804 case PLPGSQL_STMT_GETDIAG:
00805 dump_getdiag((PLpgSQL_stmt_getdiag *) stmt);
00806 break;
00807 case PLPGSQL_STMT_OPEN:
00808 dump_open((PLpgSQL_stmt_open *) stmt);
00809 break;
00810 case PLPGSQL_STMT_FETCH:
00811 dump_fetch((PLpgSQL_stmt_fetch *) stmt);
00812 break;
00813 case PLPGSQL_STMT_CLOSE:
00814 dump_close((PLpgSQL_stmt_close *) stmt);
00815 break;
00816 case PLPGSQL_STMT_PERFORM:
00817 dump_perform((PLpgSQL_stmt_perform *) stmt);
00818 break;
00819 default:
00820 elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
00821 break;
00822 }
00823 }
00824
00825 static void
00826 dump_stmts(List *stmts)
00827 {
00828 ListCell *s;
00829
00830 dump_indent += 2;
00831 foreach(s, stmts)
00832 dump_stmt((PLpgSQL_stmt *) lfirst(s));
00833 dump_indent -= 2;
00834 }
00835
00836 static void
00837 dump_block(PLpgSQL_stmt_block *block)
00838 {
00839 char *name;
00840
00841 if (block->label == NULL)
00842 name = "*unnamed*";
00843 else
00844 name = block->label;
00845
00846 dump_ind();
00847 printf("BLOCK <<%s>>\n", name);
00848
00849 dump_stmts(block->body);
00850
00851 if (block->exceptions)
00852 {
00853 ListCell *e;
00854
00855 foreach(e, block->exceptions->exc_list)
00856 {
00857 PLpgSQL_exception *exc = (PLpgSQL_exception *) lfirst(e);
00858 PLpgSQL_condition *cond;
00859
00860 dump_ind();
00861 printf(" EXCEPTION WHEN ");
00862 for (cond = exc->conditions; cond; cond = cond->next)
00863 {
00864 if (cond != exc->conditions)
00865 printf(" OR ");
00866 printf("%s", cond->condname);
00867 }
00868 printf(" THEN\n");
00869 dump_stmts(exc->action);
00870 }
00871 }
00872
00873 dump_ind();
00874 printf(" END -- %s\n", name);
00875 }
00876
00877 static void
00878 dump_assign(PLpgSQL_stmt_assign *stmt)
00879 {
00880 dump_ind();
00881 printf("ASSIGN var %d := ", stmt->varno);
00882 dump_expr(stmt->expr);
00883 printf("\n");
00884 }
00885
00886 static void
00887 dump_if(PLpgSQL_stmt_if *stmt)
00888 {
00889 ListCell *l;
00890
00891 dump_ind();
00892 printf("IF ");
00893 dump_expr(stmt->cond);
00894 printf(" THEN\n");
00895 dump_stmts(stmt->then_body);
00896 foreach(l, stmt->elsif_list)
00897 {
00898 PLpgSQL_if_elsif *elif = (PLpgSQL_if_elsif *) lfirst(l);
00899
00900 dump_ind();
00901 printf(" ELSIF ");
00902 dump_expr(elif->cond);
00903 printf(" THEN\n");
00904 dump_stmts(elif->stmts);
00905 }
00906 if (stmt->else_body != NIL)
00907 {
00908 dump_ind();
00909 printf(" ELSE\n");
00910 dump_stmts(stmt->else_body);
00911 }
00912 dump_ind();
00913 printf(" ENDIF\n");
00914 }
00915
00916 static void
00917 dump_case(PLpgSQL_stmt_case *stmt)
00918 {
00919 ListCell *l;
00920
00921 dump_ind();
00922 printf("CASE %d ", stmt->t_varno);
00923 if (stmt->t_expr)
00924 dump_expr(stmt->t_expr);
00925 printf("\n");
00926 dump_indent += 6;
00927 foreach(l, stmt->case_when_list)
00928 {
00929 PLpgSQL_case_when *cwt = (PLpgSQL_case_when *) lfirst(l);
00930
00931 dump_ind();
00932 printf("WHEN ");
00933 dump_expr(cwt->expr);
00934 printf("\n");
00935 dump_ind();
00936 printf("THEN\n");
00937 dump_indent += 2;
00938 dump_stmts(cwt->stmts);
00939 dump_indent -= 2;
00940 }
00941 if (stmt->have_else)
00942 {
00943 dump_ind();
00944 printf("ELSE\n");
00945 dump_indent += 2;
00946 dump_stmts(stmt->else_stmts);
00947 dump_indent -= 2;
00948 }
00949 dump_indent -= 6;
00950 dump_ind();
00951 printf(" ENDCASE\n");
00952 }
00953
00954 static void
00955 dump_loop(PLpgSQL_stmt_loop *stmt)
00956 {
00957 dump_ind();
00958 printf("LOOP\n");
00959
00960 dump_stmts(stmt->body);
00961
00962 dump_ind();
00963 printf(" ENDLOOP\n");
00964 }
00965
00966 static void
00967 dump_while(PLpgSQL_stmt_while *stmt)
00968 {
00969 dump_ind();
00970 printf("WHILE ");
00971 dump_expr(stmt->cond);
00972 printf("\n");
00973
00974 dump_stmts(stmt->body);
00975
00976 dump_ind();
00977 printf(" ENDWHILE\n");
00978 }
00979
00980 static void
00981 dump_fori(PLpgSQL_stmt_fori *stmt)
00982 {
00983 dump_ind();
00984 printf("FORI %s %s\n", stmt->var->refname, (stmt->reverse) ? "REVERSE" : "NORMAL");
00985
00986 dump_indent += 2;
00987 dump_ind();
00988 printf(" lower = ");
00989 dump_expr(stmt->lower);
00990 printf("\n");
00991 dump_ind();
00992 printf(" upper = ");
00993 dump_expr(stmt->upper);
00994 printf("\n");
00995 if (stmt->step)
00996 {
00997 dump_ind();
00998 printf(" step = ");
00999 dump_expr(stmt->step);
01000 printf("\n");
01001 }
01002 dump_indent -= 2;
01003
01004 dump_stmts(stmt->body);
01005
01006 dump_ind();
01007 printf(" ENDFORI\n");
01008 }
01009
01010 static void
01011 dump_fors(PLpgSQL_stmt_fors *stmt)
01012 {
01013 dump_ind();
01014 printf("FORS %s ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
01015 dump_expr(stmt->query);
01016 printf("\n");
01017
01018 dump_stmts(stmt->body);
01019
01020 dump_ind();
01021 printf(" ENDFORS\n");
01022 }
01023
01024 static void
01025 dump_forc(PLpgSQL_stmt_forc *stmt)
01026 {
01027 dump_ind();
01028 printf("FORC %s ", stmt->rec->refname);
01029 printf("curvar=%d\n", stmt->curvar);
01030
01031 dump_indent += 2;
01032 if (stmt->argquery != NULL)
01033 {
01034 dump_ind();
01035 printf(" arguments = ");
01036 dump_expr(stmt->argquery);
01037 printf("\n");
01038 }
01039 dump_indent -= 2;
01040
01041 dump_stmts(stmt->body);
01042
01043 dump_ind();
01044 printf(" ENDFORC\n");
01045 }
01046
01047 static void
01048 dump_foreach_a(PLpgSQL_stmt_foreach_a *stmt)
01049 {
01050 dump_ind();
01051 printf("FOREACHA var %d ", stmt->varno);
01052 if (stmt->slice != 0)
01053 printf("SLICE %d ", stmt->slice);
01054 printf("IN ");
01055 dump_expr(stmt->expr);
01056 printf("\n");
01057
01058 dump_stmts(stmt->body);
01059
01060 dump_ind();
01061 printf(" ENDFOREACHA");
01062 }
01063
01064 static void
01065 dump_open(PLpgSQL_stmt_open *stmt)
01066 {
01067 dump_ind();
01068 printf("OPEN curvar=%d\n", stmt->curvar);
01069
01070 dump_indent += 2;
01071 if (stmt->argquery != NULL)
01072 {
01073 dump_ind();
01074 printf(" arguments = '");
01075 dump_expr(stmt->argquery);
01076 printf("'\n");
01077 }
01078 if (stmt->query != NULL)
01079 {
01080 dump_ind();
01081 printf(" query = '");
01082 dump_expr(stmt->query);
01083 printf("'\n");
01084 }
01085 if (stmt->dynquery != NULL)
01086 {
01087 dump_ind();
01088 printf(" execute = '");
01089 dump_expr(stmt->dynquery);
01090 printf("'\n");
01091
01092 if (stmt->params != NIL)
01093 {
01094 ListCell *lc;
01095 int i;
01096
01097 dump_indent += 2;
01098 dump_ind();
01099 printf(" USING\n");
01100 dump_indent += 2;
01101 i = 1;
01102 foreach(lc, stmt->params)
01103 {
01104 dump_ind();
01105 printf(" parameter $%d: ", i++);
01106 dump_expr((PLpgSQL_expr *) lfirst(lc));
01107 printf("\n");
01108 }
01109 dump_indent -= 4;
01110 }
01111 }
01112 dump_indent -= 2;
01113 }
01114
01115 static void
01116 dump_fetch(PLpgSQL_stmt_fetch *stmt)
01117 {
01118 dump_ind();
01119
01120 if (!stmt->is_move)
01121 {
01122 printf("FETCH curvar=%d\n", stmt->curvar);
01123 dump_cursor_direction(stmt);
01124
01125 dump_indent += 2;
01126 if (stmt->rec != NULL)
01127 {
01128 dump_ind();
01129 printf(" target = %d %s\n", stmt->rec->dno, stmt->rec->refname);
01130 }
01131 if (stmt->row != NULL)
01132 {
01133 dump_ind();
01134 printf(" target = %d %s\n", stmt->row->dno, stmt->row->refname);
01135 }
01136 dump_indent -= 2;
01137 }
01138 else
01139 {
01140 printf("MOVE curvar=%d\n", stmt->curvar);
01141 dump_cursor_direction(stmt);
01142 }
01143 }
01144
01145 static void
01146 dump_cursor_direction(PLpgSQL_stmt_fetch *stmt)
01147 {
01148 dump_indent += 2;
01149 dump_ind();
01150 switch (stmt->direction)
01151 {
01152 case FETCH_FORWARD:
01153 printf(" FORWARD ");
01154 break;
01155 case FETCH_BACKWARD:
01156 printf(" BACKWARD ");
01157 break;
01158 case FETCH_ABSOLUTE:
01159 printf(" ABSOLUTE ");
01160 break;
01161 case FETCH_RELATIVE:
01162 printf(" RELATIVE ");
01163 break;
01164 default:
01165 printf("??? unknown cursor direction %d", stmt->direction);
01166 }
01167
01168 if (stmt->expr)
01169 {
01170 dump_expr(stmt->expr);
01171 printf("\n");
01172 }
01173 else
01174 printf("%ld\n", stmt->how_many);
01175
01176 dump_indent -= 2;
01177 }
01178
01179 static void
01180 dump_close(PLpgSQL_stmt_close *stmt)
01181 {
01182 dump_ind();
01183 printf("CLOSE curvar=%d\n", stmt->curvar);
01184 }
01185
01186 static void
01187 dump_perform(PLpgSQL_stmt_perform *stmt)
01188 {
01189 dump_ind();
01190 printf("PERFORM expr = ");
01191 dump_expr(stmt->expr);
01192 printf("\n");
01193 }
01194
01195 static void
01196 dump_exit(PLpgSQL_stmt_exit *stmt)
01197 {
01198 dump_ind();
01199 printf("%s", stmt->is_exit ? "EXIT" : "CONTINUE");
01200 if (stmt->label != NULL)
01201 printf(" label='%s'", stmt->label);
01202 if (stmt->cond != NULL)
01203 {
01204 printf(" WHEN ");
01205 dump_expr(stmt->cond);
01206 }
01207 printf("\n");
01208 }
01209
01210 static void
01211 dump_return(PLpgSQL_stmt_return *stmt)
01212 {
01213 dump_ind();
01214 printf("RETURN ");
01215 if (stmt->retvarno >= 0)
01216 printf("variable %d", stmt->retvarno);
01217 else if (stmt->expr != NULL)
01218 dump_expr(stmt->expr);
01219 else
01220 printf("NULL");
01221 printf("\n");
01222 }
01223
01224 static void
01225 dump_return_next(PLpgSQL_stmt_return_next *stmt)
01226 {
01227 dump_ind();
01228 printf("RETURN NEXT ");
01229 if (stmt->retvarno >= 0)
01230 printf("variable %d", stmt->retvarno);
01231 else if (stmt->expr != NULL)
01232 dump_expr(stmt->expr);
01233 else
01234 printf("NULL");
01235 printf("\n");
01236 }
01237
01238 static void
01239 dump_return_query(PLpgSQL_stmt_return_query *stmt)
01240 {
01241 dump_ind();
01242 if (stmt->query)
01243 {
01244 printf("RETURN QUERY ");
01245 dump_expr(stmt->query);
01246 printf("\n");
01247 }
01248 else
01249 {
01250 printf("RETURN QUERY EXECUTE ");
01251 dump_expr(stmt->dynquery);
01252 printf("\n");
01253 if (stmt->params != NIL)
01254 {
01255 ListCell *lc;
01256 int i;
01257
01258 dump_indent += 2;
01259 dump_ind();
01260 printf(" USING\n");
01261 dump_indent += 2;
01262 i = 1;
01263 foreach(lc, stmt->params)
01264 {
01265 dump_ind();
01266 printf(" parameter $%d: ", i++);
01267 dump_expr((PLpgSQL_expr *) lfirst(lc));
01268 printf("\n");
01269 }
01270 dump_indent -= 4;
01271 }
01272 }
01273 }
01274
01275 static void
01276 dump_raise(PLpgSQL_stmt_raise *stmt)
01277 {
01278 ListCell *lc;
01279 int i = 0;
01280
01281 dump_ind();
01282 printf("RAISE level=%d", stmt->elog_level);
01283 if (stmt->condname)
01284 printf(" condname='%s'", stmt->condname);
01285 if (stmt->message)
01286 printf(" message='%s'", stmt->message);
01287 printf("\n");
01288 dump_indent += 2;
01289 foreach(lc, stmt->params)
01290 {
01291 dump_ind();
01292 printf(" parameter %d: ", i++);
01293 dump_expr((PLpgSQL_expr *) lfirst(lc));
01294 printf("\n");
01295 }
01296 if (stmt->options)
01297 {
01298 dump_ind();
01299 printf(" USING\n");
01300 dump_indent += 2;
01301 foreach(lc, stmt->options)
01302 {
01303 PLpgSQL_raise_option *opt = (PLpgSQL_raise_option *) lfirst(lc);
01304
01305 dump_ind();
01306 switch (opt->opt_type)
01307 {
01308 case PLPGSQL_RAISEOPTION_ERRCODE:
01309 printf(" ERRCODE = ");
01310 break;
01311 case PLPGSQL_RAISEOPTION_MESSAGE:
01312 printf(" MESSAGE = ");
01313 break;
01314 case PLPGSQL_RAISEOPTION_DETAIL:
01315 printf(" DETAIL = ");
01316 break;
01317 case PLPGSQL_RAISEOPTION_HINT:
01318 printf(" HINT = ");
01319 break;
01320 }
01321 dump_expr(opt->expr);
01322 printf("\n");
01323 }
01324 dump_indent -= 2;
01325 }
01326 dump_indent -= 2;
01327 }
01328
01329 static void
01330 dump_execsql(PLpgSQL_stmt_execsql *stmt)
01331 {
01332 dump_ind();
01333 printf("EXECSQL ");
01334 dump_expr(stmt->sqlstmt);
01335 printf("\n");
01336
01337 dump_indent += 2;
01338 if (stmt->rec != NULL)
01339 {
01340 dump_ind();
01341 printf(" INTO%s target = %d %s\n",
01342 stmt->strict ? " STRICT" : "",
01343 stmt->rec->dno, stmt->rec->refname);
01344 }
01345 if (stmt->row != NULL)
01346 {
01347 dump_ind();
01348 printf(" INTO%s target = %d %s\n",
01349 stmt->strict ? " STRICT" : "",
01350 stmt->row->dno, stmt->row->refname);
01351 }
01352 dump_indent -= 2;
01353 }
01354
01355 static void
01356 dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt)
01357 {
01358 dump_ind();
01359 printf("EXECUTE ");
01360 dump_expr(stmt->query);
01361 printf("\n");
01362
01363 dump_indent += 2;
01364 if (stmt->rec != NULL)
01365 {
01366 dump_ind();
01367 printf(" INTO%s target = %d %s\n",
01368 stmt->strict ? " STRICT" : "",
01369 stmt->rec->dno, stmt->rec->refname);
01370 }
01371 if (stmt->row != NULL)
01372 {
01373 dump_ind();
01374 printf(" INTO%s target = %d %s\n",
01375 stmt->strict ? " STRICT" : "",
01376 stmt->row->dno, stmt->row->refname);
01377 }
01378 if (stmt->params != NIL)
01379 {
01380 ListCell *lc;
01381 int i;
01382
01383 dump_ind();
01384 printf(" USING\n");
01385 dump_indent += 2;
01386 i = 1;
01387 foreach(lc, stmt->params)
01388 {
01389 dump_ind();
01390 printf(" parameter %d: ", i++);
01391 dump_expr((PLpgSQL_expr *) lfirst(lc));
01392 printf("\n");
01393 }
01394 dump_indent -= 2;
01395 }
01396 dump_indent -= 2;
01397 }
01398
01399 static void
01400 dump_dynfors(PLpgSQL_stmt_dynfors *stmt)
01401 {
01402 dump_ind();
01403 printf("FORS %s EXECUTE ",
01404 (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
01405 dump_expr(stmt->query);
01406 printf("\n");
01407 if (stmt->params != NIL)
01408 {
01409 ListCell *lc;
01410 int i;
01411
01412 dump_indent += 2;
01413 dump_ind();
01414 printf(" USING\n");
01415 dump_indent += 2;
01416 i = 1;
01417 foreach(lc, stmt->params)
01418 {
01419 dump_ind();
01420 printf(" parameter $%d: ", i++);
01421 dump_expr((PLpgSQL_expr *) lfirst(lc));
01422 printf("\n");
01423 }
01424 dump_indent -= 4;
01425 }
01426 dump_stmts(stmt->body);
01427 dump_ind();
01428 printf(" ENDFORS\n");
01429 }
01430
01431 static void
01432 dump_getdiag(PLpgSQL_stmt_getdiag *stmt)
01433 {
01434 ListCell *lc;
01435
01436 dump_ind();
01437 printf("GET %s DIAGNOSTICS ", stmt->is_stacked ? "STACKED" : "CURRENT");
01438 foreach(lc, stmt->diag_items)
01439 {
01440 PLpgSQL_diag_item *diag_item = (PLpgSQL_diag_item *) lfirst(lc);
01441
01442 if (lc != list_head(stmt->diag_items))
01443 printf(", ");
01444
01445 printf("{var %d} = %s", diag_item->target,
01446 plpgsql_getdiag_kindname(diag_item->kind));
01447 }
01448 printf("\n");
01449 }
01450
01451 static void
01452 dump_expr(PLpgSQL_expr *expr)
01453 {
01454 printf("'%s'", expr->query);
01455 }
01456
01457 void
01458 plpgsql_dumptree(PLpgSQL_function *func)
01459 {
01460 int i;
01461 PLpgSQL_datum *d;
01462
01463 printf("\nExecution tree of successfully compiled PL/pgSQL function %s:\n",
01464 func->fn_signature);
01465
01466 printf("\nFunction's data area:\n");
01467 for (i = 0; i < func->ndatums; i++)
01468 {
01469 d = func->datums[i];
01470
01471 printf(" entry %d: ", i);
01472 switch (d->dtype)
01473 {
01474 case PLPGSQL_DTYPE_VAR:
01475 {
01476 PLpgSQL_var *var = (PLpgSQL_var *) d;
01477
01478 printf("VAR %-16s type %s (typoid %u) atttypmod %d\n",
01479 var->refname, var->datatype->typname,
01480 var->datatype->typoid,
01481 var->datatype->atttypmod);
01482 if (var->isconst)
01483 printf(" CONSTANT\n");
01484 if (var->notnull)
01485 printf(" NOT NULL\n");
01486 if (var->default_val != NULL)
01487 {
01488 printf(" DEFAULT ");
01489 dump_expr(var->default_val);
01490 printf("\n");
01491 }
01492 if (var->cursor_explicit_expr != NULL)
01493 {
01494 if (var->cursor_explicit_argrow >= 0)
01495 printf(" CURSOR argument row %d\n", var->cursor_explicit_argrow);
01496
01497 printf(" CURSOR IS ");
01498 dump_expr(var->cursor_explicit_expr);
01499 printf("\n");
01500 }
01501 }
01502 break;
01503 case PLPGSQL_DTYPE_ROW:
01504 {
01505 PLpgSQL_row *row = (PLpgSQL_row *) d;
01506 int i;
01507
01508 printf("ROW %-16s fields", row->refname);
01509 for (i = 0; i < row->nfields; i++)
01510 {
01511 if (row->fieldnames[i])
01512 printf(" %s=var %d", row->fieldnames[i],
01513 row->varnos[i]);
01514 }
01515 printf("\n");
01516 }
01517 break;
01518 case PLPGSQL_DTYPE_REC:
01519 printf("REC %s\n", ((PLpgSQL_rec *) d)->refname);
01520 break;
01521 case PLPGSQL_DTYPE_RECFIELD:
01522 printf("RECFIELD %-16s of REC %d\n",
01523 ((PLpgSQL_recfield *) d)->fieldname,
01524 ((PLpgSQL_recfield *) d)->recparentno);
01525 break;
01526 case PLPGSQL_DTYPE_ARRAYELEM:
01527 printf("ARRAYELEM of VAR %d subscript ",
01528 ((PLpgSQL_arrayelem *) d)->arrayparentno);
01529 dump_expr(((PLpgSQL_arrayelem *) d)->subscript);
01530 printf("\n");
01531 break;
01532 default:
01533 printf("??? unknown data type %d\n", d->dtype);
01534 }
01535 }
01536 printf("\nFunction's statements:\n");
01537
01538 dump_indent = 0;
01539 printf("%3d:", func->action->lineno);
01540 dump_block(func->action);
01541 printf("\nEnd of execution tree of function %s\n\n", func->fn_signature);
01542 fflush(stdout);
01543 }