1 /**********************************************************************
2 * pl_funcs.c - Misc functins for the PL/pgSQL
6 * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.37 2004/09/14 23:46:46 neilc 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 **********************************************************************/
43 #include "parser/scansup.h"
47 * Local variables for the namestack handling
50 static PLpgSQL_ns *ns_current = NULL;
51 static bool ns_localmode = false;
55 * plpgsql_dstring_init Dynamic string initialization
59 plpgsql_dstring_init(PLpgSQL_dstring *ds)
61 ds->value = palloc(ds->alloc = 512);
68 * plpgsql_dstring_free Dynamic string destruction
72 plpgsql_dstring_free(PLpgSQL_dstring *ds)
79 * plpgsql_dstring_append Dynamic string extending
83 plpgsql_dstring_append(PLpgSQL_dstring *ds, const char *str)
85 int len = strlen(str);
86 int needed = ds->used + len + 1;
88 if (needed > ds->alloc)
90 /* might have to double more than once, if len is large */
94 } while (needed > ds->alloc);
95 ds->value = repalloc(ds->value, ds->alloc);
98 strcpy(&(ds->value[ds->used]), str);
104 * plpgsql_dstring_get Dynamic string get value
108 plpgsql_dstring_get(PLpgSQL_dstring *ds)
115 * plpgsql_ns_init Initialize the namestack
119 plpgsql_ns_init(void)
122 ns_localmode = false;
127 * plpgsql_ns_setlocal Tell plpgsql_ns_lookup to or to
128 * not look into the current level
133 plpgsql_ns_setlocal(bool flag)
137 oldstate = ns_localmode;
144 * plpgsql_ns_push Enter a new namestack level
148 plpgsql_ns_push(char *label)
155 new = palloc(sizeof(PLpgSQL_ns));
156 memset(new, 0, sizeof(PLpgSQL_ns));
157 new->upper = ns_current;
160 plpgsql_ns_additem(PLPGSQL_NSTYPE_LABEL, 0, label);
165 * plpgsql_ns_pop Return to the previous level
175 ns_current = old->upper;
177 for (i = 0; i < old->items_used; i++)
178 pfree(old->items[i]);
185 * plpgsql_ns_additem Add an item to the current
190 plpgsql_ns_additem(int itemtype, int itemno, char *name)
192 PLpgSQL_ns *ns = ns_current;
195 Assert(name != NULL);
197 if (ns->items_used == ns->items_alloc)
199 if (ns->items_alloc == 0)
201 ns->items_alloc = 32;
202 ns->items = palloc(sizeof(PLpgSQL_nsitem *) * ns->items_alloc);
206 ns->items_alloc *= 2;
207 ns->items = repalloc(ns->items,
208 sizeof(PLpgSQL_nsitem *) * ns->items_alloc);
212 nse = palloc(sizeof(PLpgSQL_nsitem) + strlen(name));
213 nse->itemtype = itemtype;
214 nse->itemno = itemno;
215 strcpy(nse->name, name);
216 ns->items[ns->items_used++] = nse;
221 * plpgsql_ns_lookup Lookup for a word in the namestack
225 plpgsql_ns_lookup(char *name, char *label)
231 * If a label is specified, lookup only in that
235 for (ns = ns_current; ns != NULL; ns = ns->upper)
237 if (!strcmp(ns->items[0]->name, label))
239 for (i = 1; i < ns->items_used; i++)
241 if (!strcmp(ns->items[i]->name, name))
244 return NULL; /* name not found in specified label */
247 return NULL; /* label not found */
251 * No label given, lookup for visible labels ignoring localmode
253 for (ns = ns_current; ns != NULL; ns = ns->upper)
255 if (!strcmp(ns->items[0]->name, name))
260 * Finally lookup name in the namestack
262 for (ns = ns_current; ns != NULL; ns = ns->upper)
264 for (i = 1; i < ns->items_used; i++)
266 if (!strcmp(ns->items[i]->name, name))
270 return NULL; /* name not found in current namespace */
278 * plpgsql_ns_rename Rename a namespace entry
282 plpgsql_ns_rename(char *oldname, char *newname)
285 PLpgSQL_nsitem *newitem;
289 * Lookup in the current namespace only
293 * Lookup name in the namestack
295 for (ns = ns_current; ns != NULL; ns = ns->upper)
297 for (i = 1; i < ns->items_used; i++)
299 if (!strcmp(ns->items[i]->name, oldname))
301 newitem = palloc(sizeof(PLpgSQL_nsitem) + strlen(newname));
302 newitem->itemtype = ns->items[i]->itemtype;
303 newitem->itemno = ns->items[i]->itemno;
304 strcpy(newitem->name, newname);
310 ns->items[i] = newitem;
317 (errcode(ERRCODE_UNDEFINED_OBJECT),
318 errmsg("there is no variable \"%s\" in the current block",
324 * plpgsql_convert_ident
326 * Convert a possibly-qualified identifier to internal form: handle
327 * double quotes, translate to lower case where not inside quotes,
328 * truncate to NAMEDATALEN.
330 * There may be several identifiers separated by dots and optional
331 * whitespace. Each one is converted to a separate palloc'd string.
332 * The caller passes the expected number of identifiers, as well as
333 * a char* array to hold them. It is an error if we find the wrong
334 * number of identifiers (cf grammar processing of fori_varname).
336 * NOTE: the input string has already been accepted by the flex lexer,
337 * so we don't need a heckuva lot of error checking here.
341 plpgsql_convert_ident(const char *s, char **output, int numidents)
343 const char *sstart = s;
346 /* Outer loop over identifiers */
352 /* Process current identifier */
356 /* Quoted identifier: copy, collapsing out doubled quotes */
358 curident = palloc(strlen(s) + 1); /* surely enough room */
371 if (*s != '"') /* should not happen if lexer checked */
373 (errcode(ERRCODE_SYNTAX_ERROR),
374 errmsg("unterminated \" in name: %s", sstart)));
377 /* Truncate to NAMEDATALEN */
378 truncate_identifier(curident, cp - curident, false);
382 /* Normal identifier: extends till dot or whitespace */
383 const char *thisstart = s;
385 while (*s && *s != '.' && !isspace((unsigned char) *s))
387 /* Downcase and truncate to NAMEDATALEN */
388 curident = downcase_truncate_identifier(thisstart, s - thisstart,
392 /* Pass ident to caller */
393 if (identctr < numidents)
394 output[identctr++] = curident;
397 (errcode(ERRCODE_SYNTAX_ERROR),
398 errmsg("qualified identifier cannot be used here: %s",
401 /* If not done, skip whitespace, dot, whitespace */
404 while (*s && isspace((unsigned char) *s))
407 elog(ERROR, "expected dot between identifiers: %s", sstart);
408 while (*s && isspace((unsigned char) *s))
411 elog(ERROR, "expected another identifier: %s", sstart);
415 if (identctr != numidents)
416 elog(ERROR, "improperly qualified identifier: %s",
422 * Statement type as a string, for use in error messages etc.
425 plpgsql_stmt_typename(PLpgSQL_stmt *stmt)
427 switch (stmt->cmd_type)
429 case PLPGSQL_STMT_BLOCK:
430 return "block variables initialization";
431 case PLPGSQL_STMT_ASSIGN:
433 case PLPGSQL_STMT_IF:
435 case PLPGSQL_STMT_LOOP:
437 case PLPGSQL_STMT_WHILE:
439 case PLPGSQL_STMT_FORI:
440 return "for with integer loopvar";
441 case PLPGSQL_STMT_FORS:
442 return "for over select rows";
443 case PLPGSQL_STMT_SELECT:
444 return "select into variables";
445 case PLPGSQL_STMT_EXIT:
447 case PLPGSQL_STMT_RETURN:
449 case PLPGSQL_STMT_RETURN_NEXT:
450 return "return next";
451 case PLPGSQL_STMT_RAISE:
453 case PLPGSQL_STMT_EXECSQL:
454 return "SQL statement";
455 case PLPGSQL_STMT_DYNEXECUTE:
456 return "execute statement";
457 case PLPGSQL_STMT_DYNFORS:
458 return "for over execute statement";
459 case PLPGSQL_STMT_GETDIAG:
460 return "get diagnostics";
461 case PLPGSQL_STMT_OPEN:
463 case PLPGSQL_STMT_FETCH:
465 case PLPGSQL_STMT_CLOSE:
467 case PLPGSQL_STMT_PERFORM:
475 /**********************************************************************
476 * Debug functions for analyzing the compiled code
477 **********************************************************************/
478 static int dump_indent;
480 static void dump_ind();
481 static void dump_stmt(PLpgSQL_stmt *stmt);
482 static void dump_block(PLpgSQL_stmt_block *block);
483 static void dump_assign(PLpgSQL_stmt_assign *stmt);
484 static void dump_if(PLpgSQL_stmt_if *stmt);
485 static void dump_loop(PLpgSQL_stmt_loop *stmt);
486 static void dump_while(PLpgSQL_stmt_while *stmt);
487 static void dump_fori(PLpgSQL_stmt_fori *stmt);
488 static void dump_fors(PLpgSQL_stmt_fors *stmt);
489 static void dump_select(PLpgSQL_stmt_select *stmt);
490 static void dump_exit(PLpgSQL_stmt_exit *stmt);
491 static void dump_return(PLpgSQL_stmt_return *stmt);
492 static void dump_return_next(PLpgSQL_stmt_return_next *stmt);
493 static void dump_raise(PLpgSQL_stmt_raise *stmt);
494 static void dump_execsql(PLpgSQL_stmt_execsql *stmt);
495 static void dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt);
496 static void dump_dynfors(PLpgSQL_stmt_dynfors *stmt);
497 static void dump_getdiag(PLpgSQL_stmt_getdiag *stmt);
498 static void dump_open(PLpgSQL_stmt_open *stmt);
499 static void dump_fetch(PLpgSQL_stmt_fetch *stmt);
500 static void dump_close(PLpgSQL_stmt_close *stmt);
501 static void dump_perform(PLpgSQL_stmt_perform *stmt);
502 static void dump_expr(PLpgSQL_expr *expr);
510 for (i = 0; i < dump_indent; i++)
515 dump_stmt(PLpgSQL_stmt *stmt)
517 printf("%3d:", stmt->lineno);
518 switch (stmt->cmd_type)
520 case PLPGSQL_STMT_BLOCK:
521 dump_block((PLpgSQL_stmt_block *) stmt);
523 case PLPGSQL_STMT_ASSIGN:
524 dump_assign((PLpgSQL_stmt_assign *) stmt);
526 case PLPGSQL_STMT_IF:
527 dump_if((PLpgSQL_stmt_if *) stmt);
529 case PLPGSQL_STMT_LOOP:
530 dump_loop((PLpgSQL_stmt_loop *) stmt);
532 case PLPGSQL_STMT_WHILE:
533 dump_while((PLpgSQL_stmt_while *) stmt);
535 case PLPGSQL_STMT_FORI:
536 dump_fori((PLpgSQL_stmt_fori *) stmt);
538 case PLPGSQL_STMT_FORS:
539 dump_fors((PLpgSQL_stmt_fors *) stmt);
541 case PLPGSQL_STMT_SELECT:
542 dump_select((PLpgSQL_stmt_select *) stmt);
544 case PLPGSQL_STMT_EXIT:
545 dump_exit((PLpgSQL_stmt_exit *) stmt);
547 case PLPGSQL_STMT_RETURN:
548 dump_return((PLpgSQL_stmt_return *) stmt);
550 case PLPGSQL_STMT_RETURN_NEXT:
551 dump_return_next((PLpgSQL_stmt_return_next *) stmt);
553 case PLPGSQL_STMT_RAISE:
554 dump_raise((PLpgSQL_stmt_raise *) stmt);
556 case PLPGSQL_STMT_EXECSQL:
557 dump_execsql((PLpgSQL_stmt_execsql *) stmt);
559 case PLPGSQL_STMT_DYNEXECUTE:
560 dump_dynexecute((PLpgSQL_stmt_dynexecute *) stmt);
562 case PLPGSQL_STMT_DYNFORS:
563 dump_dynfors((PLpgSQL_stmt_dynfors *) stmt);
565 case PLPGSQL_STMT_GETDIAG:
566 dump_getdiag((PLpgSQL_stmt_getdiag *) stmt);
568 case PLPGSQL_STMT_OPEN:
569 dump_open((PLpgSQL_stmt_open *) stmt);
571 case PLPGSQL_STMT_FETCH:
572 dump_fetch((PLpgSQL_stmt_fetch *) stmt);
574 case PLPGSQL_STMT_CLOSE:
575 dump_close((PLpgSQL_stmt_close *) stmt);
577 case PLPGSQL_STMT_PERFORM:
578 dump_perform((PLpgSQL_stmt_perform *) stmt);
581 elog(ERROR, "unrecognized cmd_type: %d", stmt->cmd_type);
587 dump_stmts(PLpgSQL_stmts *stmts)
592 for (i = 0; i < stmts->stmts_used; i++)
593 dump_stmt(stmts->stmts[i]);
598 dump_block(PLpgSQL_stmt_block *block)
603 if (block->label == NULL)
609 printf("BLOCK <<%s>>\n", name);
611 dump_stmts(block->body);
613 if (block->exceptions)
615 for (i = 0; i < block->exceptions->exceptions_used; i++)
617 PLpgSQL_exception *exc = block->exceptions->exceptions[i];
618 PLpgSQL_condition *cond;
621 printf(" EXCEPTION WHEN ");
622 for (cond = exc->conditions; cond; cond = cond->next)
624 if (cond != exc->conditions)
626 printf("%s", cond->condname);
629 dump_stmts(exc->action);
634 printf(" END -- %s\n", name);
638 dump_assign(PLpgSQL_stmt_assign *stmt)
641 printf("ASSIGN var %d := ", stmt->varno);
642 dump_expr(stmt->expr);
647 dump_if(PLpgSQL_stmt_if *stmt)
651 dump_expr(stmt->cond);
654 dump_stmts(stmt->true_body);
659 dump_stmts(stmt->false_body);
666 dump_loop(PLpgSQL_stmt_loop *stmt)
671 dump_stmts(stmt->body);
674 printf(" ENDLOOP\n");
678 dump_while(PLpgSQL_stmt_while *stmt)
682 dump_expr(stmt->cond);
685 dump_stmts(stmt->body);
688 printf(" ENDWHILE\n");
692 dump_fori(PLpgSQL_stmt_fori *stmt)
695 printf("FORI %s %s\n", stmt->var->refname, (stmt->reverse) ? "REVERSE" : "NORMAL");
700 dump_expr(stmt->lower);
704 dump_expr(stmt->upper);
708 dump_stmts(stmt->body);
711 printf(" ENDFORI\n");
715 dump_fors(PLpgSQL_stmt_fors *stmt)
718 printf("FORS %s ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
719 dump_expr(stmt->query);
722 dump_stmts(stmt->body);
725 printf(" ENDFORS\n");
729 dump_select(PLpgSQL_stmt_select *stmt)
733 dump_expr(stmt->query);
737 if (stmt->rec != NULL)
740 printf(" target = %d %s\n", stmt->rec->recno, stmt->rec->refname);
742 if (stmt->row != NULL)
745 printf(" target = %d %s\n", stmt->row->rowno, stmt->row->refname);
752 dump_open(PLpgSQL_stmt_open *stmt)
755 printf("OPEN curvar=%d\n", stmt->curvar);
758 if (stmt->argquery != NULL)
761 printf(" arguments = '");
762 dump_expr(stmt->argquery);
765 if (stmt->query != NULL)
768 printf(" query = '");
769 dump_expr(stmt->query);
772 if (stmt->dynquery != NULL)
775 printf(" execute = '");
776 dump_expr(stmt->dynquery);
784 dump_fetch(PLpgSQL_stmt_fetch *stmt)
787 printf("FETCH curvar=%d\n", stmt->curvar);
790 if (stmt->rec != NULL)
793 printf(" target = %d %s\n", stmt->rec->recno, stmt->rec->refname);
795 if (stmt->row != NULL)
798 printf(" target = %d %s\n", stmt->row->rowno, stmt->row->refname);
805 dump_close(PLpgSQL_stmt_close *stmt)
808 printf("CLOSE curvar=%d\n", stmt->curvar);
812 dump_perform(PLpgSQL_stmt_perform *stmt)
815 printf("PERFORM expr = ");
816 dump_expr(stmt->expr);
821 dump_exit(PLpgSQL_stmt_exit *stmt)
824 printf("EXIT lbl='%s'", stmt->label);
825 if (stmt->cond != NULL)
828 dump_expr(stmt->cond);
834 dump_return(PLpgSQL_stmt_return *stmt)
838 if (stmt->retrecno >= 0)
839 printf("record %d", stmt->retrecno);
840 else if (stmt->retrowno >= 0)
841 printf("row %d", stmt->retrowno);
842 else if (stmt->expr == NULL)
845 dump_expr(stmt->expr);
850 dump_return_next(PLpgSQL_stmt_return_next *stmt)
853 printf("RETURN NEXT ");
854 if (stmt->rec != NULL)
855 printf("target = %d %s\n", stmt->rec->recno, stmt->rec->refname);
856 else if (stmt->row != NULL)
857 printf("target = %d %s\n", stmt->row->rowno, stmt->row->refname);
858 else if (stmt->expr != NULL)
859 dump_expr(stmt->expr);
864 dump_raise(PLpgSQL_stmt_raise *stmt)
869 printf("RAISE '%s'", stmt->message);
870 for (i = 0; i < stmt->nparams; i++)
871 printf(" %d", stmt->params[i]);
876 dump_execsql(PLpgSQL_stmt_execsql *stmt)
880 dump_expr(stmt->sqlstmt);
885 dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt)
889 dump_expr(stmt->query);
894 dump_dynfors(PLpgSQL_stmt_dynfors *stmt)
897 printf("FORS %s EXECUTE ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
898 dump_expr(stmt->query);
901 dump_stmts(stmt->body);
904 printf(" ENDFORS\n");
908 dump_getdiag(PLpgSQL_stmt_getdiag *stmt)
913 printf("GET DIAGNOSTICS ");
914 for (i = 0; i < stmt->ndtitems; i++)
916 PLpgSQL_diag_item *dtitem = &stmt->dtitems[i];
921 printf("{var %d} = ", dtitem->target);
923 switch (dtitem->item)
925 case PLPGSQL_GETDIAG_ROW_COUNT:
929 case PLPGSQL_GETDIAG_RESULT_OID:
930 printf("RESULT_OID");
942 dump_expr(PLpgSQL_expr *expr)
946 printf("'%s", expr->query);
947 if (expr->nparams > 0)
950 for (i = 0; i < expr->nparams; i++)
954 printf("$%d=%d", i + 1, expr->params[i]);
962 plpgsql_dumptree(PLpgSQL_function *func)
967 printf("\nExecution tree of successfully compiled PL/pgSQL function %s:\n",
970 printf("\nFunctions data area:\n");
971 for (i = 0; i < func->ndatums; i++)
975 printf(" entry %d: ", i);
978 case PLPGSQL_DTYPE_VAR:
980 PLpgSQL_var *var = (PLpgSQL_var *) d;
982 printf("VAR %-16s type %s (typoid %u) atttypmod %d\n",
983 var->refname, var->datatype->typname,
984 var->datatype->typoid,
985 var->datatype->atttypmod);
987 printf(" CONSTANT\n");
989 printf(" NOT NULL\n");
990 if (var->default_val != NULL)
993 dump_expr(var->default_val);
996 if (var->cursor_explicit_expr != NULL)
998 if (var->cursor_explicit_argrow >= 0)
999 printf(" CURSOR argument row %d\n", var->cursor_explicit_argrow);
1001 printf(" CURSOR IS ");
1002 dump_expr(var->cursor_explicit_expr);
1007 case PLPGSQL_DTYPE_ROW:
1009 PLpgSQL_row *row = (PLpgSQL_row *) d;
1012 printf("ROW %-16s fields", row->refname);
1013 for (i = 0; i < row->nfields; i++)
1015 if (row->fieldnames[i])
1016 printf(" %s=var %d", row->fieldnames[i],
1022 case PLPGSQL_DTYPE_REC:
1023 printf("REC %s\n", ((PLpgSQL_rec *) d)->refname);
1025 case PLPGSQL_DTYPE_RECFIELD:
1026 printf("RECFIELD %-16s of REC %d\n",
1027 ((PLpgSQL_recfield *) d)->fieldname,
1028 ((PLpgSQL_recfield *) d)->recparentno);
1030 case PLPGSQL_DTYPE_ARRAYELEM:
1031 printf("ARRAYELEM of VAR %d subscript ",
1032 ((PLpgSQL_arrayelem *) d)->arrayparentno);
1033 dump_expr(((PLpgSQL_arrayelem *) d)->subscript);
1036 case PLPGSQL_DTYPE_TRIGARG:
1038 dump_expr(((PLpgSQL_trigarg *) d)->argnum);
1042 printf("??? unknown data type %d\n", d->dtype);
1045 printf("\nFunctions statements:\n");
1048 printf("%3d:", func->action->lineno);
1049 dump_block(func->action);
1050 printf("\nEnd of execution tree of function %s\n\n", func->fn_name);