1 /**********************************************************************
2 * pl_funcs.c - Misc functins for the PL/pgSQL
6 * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.15 2001/07/12 17:42:08 momjian Exp $
8 * This software is copyrighted by Jan Wieck - Hamburg.
10 * The author hereby grants permission to use, copy, modify,
11 * distribute, and license this software and its documentation
12 * for any purpose, provided that existing copyright notices are
13 * retained in all copies and that this notice is included
14 * verbatim in any distributions. No written agreement, license,
15 * or royalty fee is required for any of the authorized uses.
16 * Modifications to this software may be copyrighted by their
17 * author and need not follow the licensing terms described
18 * here, provided that the new terms are clearly indicated on
19 * the first page of each file where they apply.
21 * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
22 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
23 * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
24 * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
25 * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
28 * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
31 * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
32 * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
33 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
34 * ENHANCEMENTS, OR MODIFICATIONS.
36 **********************************************************************/
51 * Local variables for the namestack handling
54 static PLpgSQL_ns *ns_current = NULL;
55 static bool ns_localmode = false;
59 * plpgsql_dstring_init Dynamic string initialization
63 plpgsql_dstring_init(PLpgSQL_dstring * ds)
65 ds->value = palloc(ds->alloc = 512);
71 * plpgsql_dstring_free Dynamic string destruction
75 plpgsql_dstring_free(PLpgSQL_dstring * ds)
82 * plpgsql_dstring_append Dynamic string extending
86 plpgsql_dstring_append(PLpgSQL_dstring * ds, char *str)
88 int len = strlen(str);
90 if (ds->used + len + 1 > ds->alloc)
93 ds->value = repalloc(ds->value, ds->alloc);
96 strcpy(&(ds->value[ds->used]), str);
102 * plpgsql_dstring_get Dynamic string get value
106 plpgsql_dstring_get(PLpgSQL_dstring * ds)
113 * plpgsql_ns_init Initialize the namestack
117 plpgsql_ns_init(void)
120 ns_localmode = false;
125 * plpgsql_ns_setlocal Tell plpgsql_ns_lookup to or to
126 * not look into the current level
131 plpgsql_ns_setlocal(bool flag)
135 oldstate = ns_localmode;
142 * plpgsql_ns_push Enter a new namestack level
146 plpgsql_ns_push(char *label)
150 new = palloc(sizeof(PLpgSQL_ns));
151 memset(new, 0, sizeof(PLpgSQL_ns));
152 new->upper = ns_current;
155 plpgsql_ns_additem(PLPGSQL_NSTYPE_LABEL, 0, label);
160 * plpgsql_ns_pop Return to the previous level
170 ns_current = old->upper;
172 for (i = 0; i < old->items_used; i++)
173 pfree(old->items[i]);
180 * plpgsql_ns_additem Add an item to the current
185 plpgsql_ns_additem(int itemtype, int itemno, char *name)
187 PLpgSQL_ns *ns = ns_current;
192 name = plpgsql_tolower(name);
194 if (ns->items_used == ns->items_alloc)
196 if (ns->items_alloc == 0)
198 ns->items_alloc = 32;
199 ns->items = palloc(sizeof(PLpgSQL_nsitem *) * ns->items_alloc);
203 ns->items_alloc *= 2;
204 ns->items = repalloc(ns->items,
205 sizeof(PLpgSQL_nsitem *) * ns->items_alloc);
209 nse = palloc(sizeof(PLpgSQL_nsitem) + strlen(name));
210 nse->itemtype = itemtype;
211 nse->itemno = itemno;
212 strcpy(nse->name, name);
213 ns->items[ns->items_used++] = nse;
218 * plpgsql_ns_lookup Lookup for a word in the namestack
222 plpgsql_ns_lookup(char *name, char *label)
228 * If a label is specified, lookup only in that
232 for (ns = ns_current; ns != NULL; ns = ns->upper)
234 if (!strcmp(ns->items[0]->name, label))
236 for (i = 1; i < ns->items_used; i++)
238 if (!strcmp(ns->items[i]->name, name))
241 return NULL; /* name not found in specified label */
244 return NULL; /* label not found */
248 * No label given, lookup for visible labels ignoring localmode
250 for (ns = ns_current; ns != NULL; ns = ns->upper)
252 if (!strcmp(ns->items[0]->name, name))
257 * Finally lookup name in the namestack
259 for (ns = ns_current; ns != NULL; ns = ns->upper)
261 for (i = 1; i < ns->items_used; i++)
263 if (!strcmp(ns->items[i]->name, name))
268 return NULL; /* name not found in current namespace */
277 * plpgsql_ns_rename Rename a namespace entry
281 plpgsql_ns_rename(char *oldname, char *newname)
284 PLpgSQL_nsitem *newitem;
288 * Lookup in the current namespace only
292 * Lookup name in the namestack
294 for (ns = ns_current; ns != NULL; ns = ns->upper)
296 for (i = 1; i < ns->items_used; i++)
298 if (!strcmp(ns->items[i]->name, oldname))
300 newitem = palloc(sizeof(PLpgSQL_nsitem) + strlen(newname));
301 newitem->itemtype = ns->items[i]->itemtype;
302 newitem->itemno = ns->items[i]->itemno;
303 strcpy(newitem->name, newname);
309 ns->items[i] = newitem;
315 elog(ERROR, "there is no variable '%s' in the current block", oldname);
320 * plpgsql_tolower Translate a string to lower case
321 * but honor "" escaping.
325 plpgsql_tolower(char *s)
330 ret = palloc(strlen(s) + 1);
346 plpgsql_comperrinfo();
347 elog(ERROR, "unterminated \"");
353 if (isupper((unsigned char) *s))
354 *cp++ = tolower((unsigned char) *s++);
368 /**********************************************************************
369 * Debug functions for analyzing the compiled code
370 **********************************************************************/
371 static int dump_indent;
373 static void dump_ind();
374 static void dump_stmt(PLpgSQL_stmt * stmt);
375 static void dump_block(PLpgSQL_stmt_block * block);
376 static void dump_assign(PLpgSQL_stmt_assign * stmt);
377 static void dump_if(PLpgSQL_stmt_if * stmt);
378 static void dump_loop(PLpgSQL_stmt_loop * stmt);
379 static void dump_while(PLpgSQL_stmt_while * stmt);
380 static void dump_fori(PLpgSQL_stmt_fori * stmt);
381 static void dump_fors(PLpgSQL_stmt_fors * stmt);
382 static void dump_select(PLpgSQL_stmt_select * stmt);
383 static void dump_exit(PLpgSQL_stmt_exit * stmt);
384 static void dump_return(PLpgSQL_stmt_return * stmt);
385 static void dump_raise(PLpgSQL_stmt_raise * stmt);
386 static void dump_execsql(PLpgSQL_stmt_execsql * stmt);
387 static void dump_dynexecute(PLpgSQL_stmt_dynexecute * stmt);
388 static void dump_dynfors(PLpgSQL_stmt_dynfors * stmt);
389 static void dump_getdiag(PLpgSQL_stmt_getdiag * stmt);
390 static void dump_open(PLpgSQL_stmt_open * stmt);
391 static void dump_fetch(PLpgSQL_stmt_fetch * stmt);
392 static void dump_close(PLpgSQL_stmt_close * stmt);
393 static void dump_expr(PLpgSQL_expr * expr);
401 for (i = 0; i < dump_indent; i++)
406 dump_stmt(PLpgSQL_stmt * stmt)
408 printf("%3d:", stmt->lineno);
409 switch (stmt->cmd_type)
411 case PLPGSQL_STMT_BLOCK:
412 dump_block((PLpgSQL_stmt_block *) stmt);
414 case PLPGSQL_STMT_ASSIGN:
415 dump_assign((PLpgSQL_stmt_assign *) stmt);
417 case PLPGSQL_STMT_IF:
418 dump_if((PLpgSQL_stmt_if *) stmt);
420 case PLPGSQL_STMT_LOOP:
421 dump_loop((PLpgSQL_stmt_loop *) stmt);
423 case PLPGSQL_STMT_WHILE:
424 dump_while((PLpgSQL_stmt_while *) stmt);
426 case PLPGSQL_STMT_FORI:
427 dump_fori((PLpgSQL_stmt_fori *) stmt);
429 case PLPGSQL_STMT_FORS:
430 dump_fors((PLpgSQL_stmt_fors *) stmt);
432 case PLPGSQL_STMT_SELECT:
433 dump_select((PLpgSQL_stmt_select *) stmt);
435 case PLPGSQL_STMT_EXIT:
436 dump_exit((PLpgSQL_stmt_exit *) stmt);
438 case PLPGSQL_STMT_RETURN:
439 dump_return((PLpgSQL_stmt_return *) stmt);
441 case PLPGSQL_STMT_RAISE:
442 dump_raise((PLpgSQL_stmt_raise *) stmt);
444 case PLPGSQL_STMT_EXECSQL:
445 dump_execsql((PLpgSQL_stmt_execsql *) stmt);
447 case PLPGSQL_STMT_DYNEXECUTE:
448 dump_dynexecute((PLpgSQL_stmt_dynexecute *) stmt);
450 case PLPGSQL_STMT_DYNFORS:
451 dump_dynfors((PLpgSQL_stmt_dynfors *) stmt);
453 case PLPGSQL_STMT_GETDIAG:
454 dump_getdiag((PLpgSQL_stmt_getdiag *) stmt);
456 case PLPGSQL_STMT_OPEN:
457 dump_open((PLpgSQL_stmt_open *) stmt);
459 case PLPGSQL_STMT_FETCH:
460 dump_fetch((PLpgSQL_stmt_fetch *) stmt);
462 case PLPGSQL_STMT_CLOSE:
463 dump_close((PLpgSQL_stmt_close *) stmt);
466 elog(ERROR, "plpgsql_dump: unknown cmd_type %d\n", stmt->cmd_type);
472 dump_block(PLpgSQL_stmt_block * block)
477 if (block->label == NULL)
483 printf("BLOCK <<%s>>\n", name);
486 for (i = 0; i < block->body->stmts_used; i++)
487 dump_stmt((PLpgSQL_stmt *) (block->body->stmts[i]));
491 printf(" END -- %s\n", name);
495 dump_assign(PLpgSQL_stmt_assign * stmt)
498 printf("ASSIGN var %d := ", stmt->varno);
499 dump_expr(stmt->expr);
504 dump_if(PLpgSQL_stmt_if * stmt)
510 dump_expr(stmt->cond);
514 for (i = 0; i < stmt->true_body->stmts_used; i++)
515 dump_stmt((PLpgSQL_stmt *) (stmt->true_body->stmts[i]));
522 for (i = 0; i < stmt->false_body->stmts_used; i++)
523 dump_stmt((PLpgSQL_stmt *) (stmt->false_body->stmts[i]));
531 dump_loop(PLpgSQL_stmt_loop * stmt)
539 for (i = 0; i < stmt->body->stmts_used; i++)
540 dump_stmt((PLpgSQL_stmt *) (stmt->body->stmts[i]));
544 printf(" ENDLOOP\n");
548 dump_while(PLpgSQL_stmt_while * stmt)
554 dump_expr(stmt->cond);
558 for (i = 0; i < stmt->body->stmts_used; i++)
559 dump_stmt((PLpgSQL_stmt *) (stmt->body->stmts[i]));
563 printf(" ENDWHILE\n");
567 dump_fori(PLpgSQL_stmt_fori * stmt)
572 printf("FORI %s %s\n", stmt->var->refname, (stmt->reverse) ? "REVERSE" : "NORMAL");
577 dump_expr(stmt->lower);
581 dump_expr(stmt->upper);
584 for (i = 0; i < stmt->body->stmts_used; i++)
585 dump_stmt((PLpgSQL_stmt *) (stmt->body->stmts[i]));
589 printf(" ENDFORI\n");
593 dump_fors(PLpgSQL_stmt_fors * stmt)
598 printf("FORS %s ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
599 dump_expr(stmt->query);
603 for (i = 0; i < stmt->body->stmts_used; i++)
604 dump_stmt((PLpgSQL_stmt *) (stmt->body->stmts[i]));
608 printf(" ENDFORS\n");
612 dump_select(PLpgSQL_stmt_select * stmt)
616 dump_expr(stmt->query);
620 if (stmt->rec != NULL)
623 printf(" target = %d %s\n", stmt->rec->recno, stmt->rec->refname);
625 if (stmt->row != NULL)
628 printf(" target = %d %s\n", stmt->row->rowno, stmt->row->refname);
635 dump_open(PLpgSQL_stmt_open * stmt)
638 printf("OPEN curvar=%d\n", stmt->curvar);
641 if (stmt->argquery != NULL)
644 printf(" arguments = '");
645 dump_expr(stmt->argquery);
648 if (stmt->query != NULL)
651 printf(" query = '");
652 dump_expr(stmt->query);
655 if (stmt->dynquery != NULL)
658 printf(" execute = '");
659 dump_expr(stmt->dynquery);
667 dump_fetch(PLpgSQL_stmt_fetch * stmt)
670 printf("FETCH curvar=%d\n", stmt->curvar);
673 if (stmt->rec != NULL)
676 printf(" target = %d %s\n", stmt->rec->recno, stmt->rec->refname);
678 if (stmt->row != NULL)
681 printf(" target = %d %s\n", stmt->row->rowno, stmt->row->refname);
688 dump_close(PLpgSQL_stmt_close * stmt)
691 printf("CLOSE curvar=%d\n", stmt->curvar);
695 dump_exit(PLpgSQL_stmt_exit * stmt)
698 printf("EXIT lbl='%s'", stmt->label);
699 if (stmt->cond != NULL)
702 dump_expr(stmt->cond);
708 dump_return(PLpgSQL_stmt_return * stmt)
712 if (stmt->retrecno > 0)
713 printf("record %d", stmt->retrecno);
716 if (stmt->expr == NULL)
719 dump_expr(stmt->expr);
725 dump_raise(PLpgSQL_stmt_raise * stmt)
730 printf("RAISE '%s'", stmt->message);
731 for (i = 0; i < stmt->nparams; i++)
732 printf(" %d", stmt->params[i]);
737 dump_execsql(PLpgSQL_stmt_execsql * stmt)
741 dump_expr(stmt->sqlstmt);
746 dump_dynexecute(PLpgSQL_stmt_dynexecute * stmt)
750 dump_expr(stmt->query);
755 dump_dynfors(PLpgSQL_stmt_dynfors * stmt)
760 printf("FORS %s EXECUTE ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
761 dump_expr(stmt->query);
765 for (i = 0; i < stmt->body->stmts_used; i++)
766 dump_stmt((PLpgSQL_stmt *) (stmt->body->stmts[i]));
770 printf(" ENDFORS\n");
774 dump_getdiag(PLpgSQL_stmt_getdiag * stmt)
779 printf("GET DIAGNOSTICS ");
780 for (i = 0; i < stmt->ndtitems; i++)
782 PLpgSQL_diag_item *dtitem = &stmt->dtitems[i];
787 printf("{var %d} = ", dtitem->target);
789 switch (dtitem->item)
791 case PLPGSQL_GETDIAG_ROW_COUNT:
795 case PLPGSQL_GETDIAG_RESULT_OID:
796 printf("RESULT_OID");
808 dump_expr(PLpgSQL_expr * expr)
812 printf("'%s", expr->query);
813 if (expr->nparams > 0)
816 for (i = 0; i < expr->nparams; i++)
820 printf("$%d=%d", i + 1, expr->params[i]);
828 plpgsql_dumptree(PLpgSQL_function * func)
833 printf("\nExecution tree of successfully compiled PL/pgSQL function %s:\n",
836 printf("\nFunctions data area:\n");
837 for (i = 0; i < func->ndatums; i++)
841 printf(" entry %d: ", i);
844 case PLPGSQL_DTYPE_VAR:
846 PLpgSQL_var *var = (PLpgSQL_var *) d;
848 printf("VAR %-16s type %s (typoid %u) atttypmod %d\n",
849 var->refname, var->datatype->typname,
850 var->datatype->typoid,
851 var->datatype->atttypmod);
853 printf(" CONSTANT\n");
855 printf(" NOT NULL\n");
856 if (var->default_val != NULL)
859 dump_expr(var->default_val);
862 if (var->cursor_explicit_expr != NULL)
864 if (var->cursor_explicit_argrow >= 0)
865 printf(" CURSOR argument row %d\n", var->cursor_explicit_argrow);
867 printf(" CURSOR IS ");
868 dump_expr(var->cursor_explicit_expr);
873 case PLPGSQL_DTYPE_ROW:
875 PLpgSQL_row *row = (PLpgSQL_row *) d;
878 printf("ROW %-16s fields", row->refname);
879 for (i = 0; i < row->nfields; i++)
881 printf(" %s=var %d", row->fieldnames[i],
887 case PLPGSQL_DTYPE_REC:
888 printf("REC %s\n", ((PLpgSQL_rec *) d)->refname);
890 case PLPGSQL_DTYPE_RECFIELD:
891 printf("RECFIELD %-16s of REC %d\n", ((PLpgSQL_recfield *) d)->fieldname, ((PLpgSQL_recfield *) d)->recno);
893 case PLPGSQL_DTYPE_TRIGARG:
895 dump_expr(((PLpgSQL_trigarg *) d)->argnum);
899 printf("??? unknown data type %d\n", d->dtype);
902 printf("\nFunctions statements:\n");
905 printf("%3d:", func->action->lineno);
906 dump_block(func->action);
907 printf("\nEnd of execution tree of function %s\n\n", func->fn_name);