1 /**********************************************************************
2 * pl_funcs.c - Misc functins for the PL/pgSQL
6 * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.27 2003/07/25 23:37:29 tgl 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 "mb/pg_wchar.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, 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 */
353 /* Process current identifier */
354 curident = palloc(strlen(s) + 1); /* surely enough room */
359 /* Quoted identifier: copy, collapsing out doubled quotes */
371 if (*s != '"') /* should not happen if lexer checked */
373 (errcode(ERRCODE_SYNTAX_ERROR),
374 errmsg("unterminated \" in name: %s", sstart)));
380 * Normal identifier: downcase, stop at dot or whitespace.
382 * Note that downcasing is locale-sensitive, following SQL99
383 * rules for identifiers. We have already decided that the
384 * item is not a PLPGSQL keyword.
386 while (*s && *s != '.' && !isspace((unsigned char) *s))
388 if (isupper((unsigned char) *s))
389 *cp++ = tolower((unsigned char) *s++);
395 /* Truncate to NAMEDATALEN */
399 if (i >= NAMEDATALEN)
403 len = pg_mbcliplen(curident, i, NAMEDATALEN - 1);
404 curident[len] = '\0';
407 /* Pass ident to caller */
408 if (identctr < numidents)
409 output[identctr++] = curident;
412 (errcode(ERRCODE_SYNTAX_ERROR),
413 errmsg("qualified identifier cannot be used here: %s",
416 /* If not done, skip whitespace, dot, whitespace */
419 while (*s && isspace((unsigned char) *s))
422 elog(ERROR, "expected dot between identifiers: %s", sstart);
423 while (*s && isspace((unsigned char) *s))
426 elog(ERROR, "expected another identifier: %s", sstart);
430 if (identctr != numidents)
431 elog(ERROR, "improperly qualified identifier: %s",
437 * Statement type as a string, for use in error messages etc.
440 plpgsql_stmt_typename(PLpgSQL_stmt * stmt)
442 switch (stmt->cmd_type)
444 case PLPGSQL_STMT_BLOCK:
445 return "block variables initialization";
446 case PLPGSQL_STMT_ASSIGN:
448 case PLPGSQL_STMT_IF:
450 case PLPGSQL_STMT_LOOP:
452 case PLPGSQL_STMT_WHILE:
454 case PLPGSQL_STMT_FORI:
455 return "for with integer loopvar";
456 case PLPGSQL_STMT_FORS:
457 return "for over select rows";
458 case PLPGSQL_STMT_SELECT:
459 return "select into variables";
460 case PLPGSQL_STMT_EXIT:
462 case PLPGSQL_STMT_RETURN:
464 case PLPGSQL_STMT_RETURN_NEXT:
465 return "return next";
466 case PLPGSQL_STMT_RAISE:
468 case PLPGSQL_STMT_EXECSQL:
469 return "SQL statement";
470 case PLPGSQL_STMT_DYNEXECUTE:
471 return "execute statement";
472 case PLPGSQL_STMT_DYNFORS:
473 return "for over execute statement";
474 case PLPGSQL_STMT_GETDIAG:
475 return "get diagnostics";
476 case PLPGSQL_STMT_OPEN:
478 case PLPGSQL_STMT_FETCH:
480 case PLPGSQL_STMT_CLOSE:
482 case PLPGSQL_STMT_PERFORM:
490 /**********************************************************************
491 * Debug functions for analyzing the compiled code
492 **********************************************************************/
493 static int dump_indent;
495 static void dump_ind();
496 static void dump_stmt(PLpgSQL_stmt * stmt);
497 static void dump_block(PLpgSQL_stmt_block * block);
498 static void dump_assign(PLpgSQL_stmt_assign * stmt);
499 static void dump_if(PLpgSQL_stmt_if * stmt);
500 static void dump_loop(PLpgSQL_stmt_loop * stmt);
501 static void dump_while(PLpgSQL_stmt_while * stmt);
502 static void dump_fori(PLpgSQL_stmt_fori * stmt);
503 static void dump_fors(PLpgSQL_stmt_fors * stmt);
504 static void dump_select(PLpgSQL_stmt_select * stmt);
505 static void dump_exit(PLpgSQL_stmt_exit * stmt);
506 static void dump_return(PLpgSQL_stmt_return * stmt);
507 static void dump_return_next(PLpgSQL_stmt_return_next * stmt);
508 static void dump_raise(PLpgSQL_stmt_raise * stmt);
509 static void dump_execsql(PLpgSQL_stmt_execsql * stmt);
510 static void dump_dynexecute(PLpgSQL_stmt_dynexecute * stmt);
511 static void dump_dynfors(PLpgSQL_stmt_dynfors * stmt);
512 static void dump_getdiag(PLpgSQL_stmt_getdiag * stmt);
513 static void dump_open(PLpgSQL_stmt_open * stmt);
514 static void dump_fetch(PLpgSQL_stmt_fetch * stmt);
515 static void dump_close(PLpgSQL_stmt_close * stmt);
516 static void dump_perform(PLpgSQL_stmt_perform * stmt);
517 static void dump_expr(PLpgSQL_expr * expr);
525 for (i = 0; i < dump_indent; i++)
530 dump_stmt(PLpgSQL_stmt * stmt)
532 printf("%3d:", stmt->lineno);
533 switch (stmt->cmd_type)
535 case PLPGSQL_STMT_BLOCK:
536 dump_block((PLpgSQL_stmt_block *) stmt);
538 case PLPGSQL_STMT_ASSIGN:
539 dump_assign((PLpgSQL_stmt_assign *) stmt);
541 case PLPGSQL_STMT_IF:
542 dump_if((PLpgSQL_stmt_if *) stmt);
544 case PLPGSQL_STMT_LOOP:
545 dump_loop((PLpgSQL_stmt_loop *) stmt);
547 case PLPGSQL_STMT_WHILE:
548 dump_while((PLpgSQL_stmt_while *) stmt);
550 case PLPGSQL_STMT_FORI:
551 dump_fori((PLpgSQL_stmt_fori *) stmt);
553 case PLPGSQL_STMT_FORS:
554 dump_fors((PLpgSQL_stmt_fors *) stmt);
556 case PLPGSQL_STMT_SELECT:
557 dump_select((PLpgSQL_stmt_select *) stmt);
559 case PLPGSQL_STMT_EXIT:
560 dump_exit((PLpgSQL_stmt_exit *) stmt);
562 case PLPGSQL_STMT_RETURN:
563 dump_return((PLpgSQL_stmt_return *) stmt);
565 case PLPGSQL_STMT_RETURN_NEXT:
566 dump_return_next((PLpgSQL_stmt_return_next *) stmt);
568 case PLPGSQL_STMT_RAISE:
569 dump_raise((PLpgSQL_stmt_raise *) stmt);
571 case PLPGSQL_STMT_EXECSQL:
572 dump_execsql((PLpgSQL_stmt_execsql *) stmt);
574 case PLPGSQL_STMT_DYNEXECUTE:
575 dump_dynexecute((PLpgSQL_stmt_dynexecute *) stmt);
577 case PLPGSQL_STMT_DYNFORS:
578 dump_dynfors((PLpgSQL_stmt_dynfors *) stmt);
580 case PLPGSQL_STMT_GETDIAG:
581 dump_getdiag((PLpgSQL_stmt_getdiag *) stmt);
583 case PLPGSQL_STMT_OPEN:
584 dump_open((PLpgSQL_stmt_open *) stmt);
586 case PLPGSQL_STMT_FETCH:
587 dump_fetch((PLpgSQL_stmt_fetch *) stmt);
589 case PLPGSQL_STMT_CLOSE:
590 dump_close((PLpgSQL_stmt_close *) stmt);
592 case PLPGSQL_STMT_PERFORM:
593 dump_perform((PLpgSQL_stmt_perform *) stmt);
596 elog(ERROR, "unknown cmd_type: %d", stmt->cmd_type);
602 dump_block(PLpgSQL_stmt_block * block)
607 if (block->label == NULL)
613 printf("BLOCK <<%s>>\n", name);
616 for (i = 0; i < block->body->stmts_used; i++)
617 dump_stmt((PLpgSQL_stmt *) (block->body->stmts[i]));
621 printf(" END -- %s\n", name);
625 dump_assign(PLpgSQL_stmt_assign * stmt)
628 printf("ASSIGN var %d := ", stmt->varno);
629 dump_expr(stmt->expr);
634 dump_if(PLpgSQL_stmt_if * stmt)
640 dump_expr(stmt->cond);
644 for (i = 0; i < stmt->true_body->stmts_used; i++)
645 dump_stmt((PLpgSQL_stmt *) (stmt->true_body->stmts[i]));
652 for (i = 0; i < stmt->false_body->stmts_used; i++)
653 dump_stmt((PLpgSQL_stmt *) (stmt->false_body->stmts[i]));
661 dump_loop(PLpgSQL_stmt_loop * stmt)
669 for (i = 0; i < stmt->body->stmts_used; i++)
670 dump_stmt((PLpgSQL_stmt *) (stmt->body->stmts[i]));
674 printf(" ENDLOOP\n");
678 dump_while(PLpgSQL_stmt_while * stmt)
684 dump_expr(stmt->cond);
688 for (i = 0; i < stmt->body->stmts_used; i++)
689 dump_stmt((PLpgSQL_stmt *) (stmt->body->stmts[i]));
693 printf(" ENDWHILE\n");
697 dump_fori(PLpgSQL_stmt_fori * stmt)
702 printf("FORI %s %s\n", stmt->var->refname, (stmt->reverse) ? "REVERSE" : "NORMAL");
707 dump_expr(stmt->lower);
711 dump_expr(stmt->upper);
714 for (i = 0; i < stmt->body->stmts_used; i++)
715 dump_stmt((PLpgSQL_stmt *) (stmt->body->stmts[i]));
719 printf(" ENDFORI\n");
723 dump_fors(PLpgSQL_stmt_fors * stmt)
728 printf("FORS %s ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
729 dump_expr(stmt->query);
733 for (i = 0; i < stmt->body->stmts_used; i++)
734 dump_stmt((PLpgSQL_stmt *) (stmt->body->stmts[i]));
738 printf(" ENDFORS\n");
742 dump_select(PLpgSQL_stmt_select * stmt)
746 dump_expr(stmt->query);
750 if (stmt->rec != NULL)
753 printf(" target = %d %s\n", stmt->rec->recno, stmt->rec->refname);
755 if (stmt->row != NULL)
758 printf(" target = %d %s\n", stmt->row->rowno, stmt->row->refname);
765 dump_open(PLpgSQL_stmt_open * stmt)
768 printf("OPEN curvar=%d\n", stmt->curvar);
771 if (stmt->argquery != NULL)
774 printf(" arguments = '");
775 dump_expr(stmt->argquery);
778 if (stmt->query != NULL)
781 printf(" query = '");
782 dump_expr(stmt->query);
785 if (stmt->dynquery != NULL)
788 printf(" execute = '");
789 dump_expr(stmt->dynquery);
797 dump_fetch(PLpgSQL_stmt_fetch * stmt)
800 printf("FETCH curvar=%d\n", stmt->curvar);
803 if (stmt->rec != NULL)
806 printf(" target = %d %s\n", stmt->rec->recno, stmt->rec->refname);
808 if (stmt->row != NULL)
811 printf(" target = %d %s\n", stmt->row->rowno, stmt->row->refname);
818 dump_close(PLpgSQL_stmt_close * stmt)
821 printf("CLOSE curvar=%d\n", stmt->curvar);
825 dump_perform(PLpgSQL_stmt_perform * stmt)
828 printf("PERFORM expr = ");
829 dump_expr(stmt->expr);
834 dump_exit(PLpgSQL_stmt_exit * stmt)
837 printf("EXIT lbl='%s'", stmt->label);
838 if (stmt->cond != NULL)
841 dump_expr(stmt->cond);
847 dump_return(PLpgSQL_stmt_return * stmt)
851 if (stmt->retrecno > 0)
852 printf("record %d", stmt->retrecno);
855 if (stmt->expr == NULL)
858 dump_expr(stmt->expr);
864 dump_return_next(PLpgSQL_stmt_return_next * stmt)
867 printf("RETURN NEXT ");
868 if (stmt->rec != NULL)
869 printf("target = %d %s\n", stmt->rec->recno, stmt->rec->refname);
870 else if (stmt->row != NULL)
871 printf("target = %d %s\n", stmt->row->rowno, stmt->row->refname);
872 else if (stmt->expr != NULL)
873 dump_expr(stmt->expr);
878 dump_raise(PLpgSQL_stmt_raise * stmt)
883 printf("RAISE '%s'", stmt->message);
884 for (i = 0; i < stmt->nparams; i++)
885 printf(" %d", stmt->params[i]);
890 dump_execsql(PLpgSQL_stmt_execsql * stmt)
894 dump_expr(stmt->sqlstmt);
899 dump_dynexecute(PLpgSQL_stmt_dynexecute * stmt)
903 dump_expr(stmt->query);
908 dump_dynfors(PLpgSQL_stmt_dynfors * stmt)
913 printf("FORS %s EXECUTE ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
914 dump_expr(stmt->query);
918 for (i = 0; i < stmt->body->stmts_used; i++)
919 dump_stmt((PLpgSQL_stmt *) (stmt->body->stmts[i]));
923 printf(" ENDFORS\n");
927 dump_getdiag(PLpgSQL_stmt_getdiag * stmt)
932 printf("GET DIAGNOSTICS ");
933 for (i = 0; i < stmt->ndtitems; i++)
935 PLpgSQL_diag_item *dtitem = &stmt->dtitems[i];
940 printf("{var %d} = ", dtitem->target);
942 switch (dtitem->item)
944 case PLPGSQL_GETDIAG_ROW_COUNT:
948 case PLPGSQL_GETDIAG_RESULT_OID:
949 printf("RESULT_OID");
961 dump_expr(PLpgSQL_expr * expr)
965 printf("'%s", expr->query);
966 if (expr->nparams > 0)
969 for (i = 0; i < expr->nparams; i++)
973 printf("$%d=%d", i + 1, expr->params[i]);
981 plpgsql_dumptree(PLpgSQL_function * func)
986 printf("\nExecution tree of successfully compiled PL/pgSQL function %s:\n",
989 printf("\nFunctions data area:\n");
990 for (i = 0; i < func->ndatums; i++)
994 printf(" entry %d: ", i);
997 case PLPGSQL_DTYPE_VAR:
999 PLpgSQL_var *var = (PLpgSQL_var *) d;
1001 printf("VAR %-16s type %s (typoid %u) atttypmod %d\n",
1002 var->refname, var->datatype->typname,
1003 var->datatype->typoid,
1004 var->datatype->atttypmod);
1006 printf(" CONSTANT\n");
1008 printf(" NOT NULL\n");
1009 if (var->default_val != NULL)
1011 printf(" DEFAULT ");
1012 dump_expr(var->default_val);
1015 if (var->cursor_explicit_expr != NULL)
1017 if (var->cursor_explicit_argrow >= 0)
1018 printf(" CURSOR argument row %d\n", var->cursor_explicit_argrow);
1020 printf(" CURSOR IS ");
1021 dump_expr(var->cursor_explicit_expr);
1026 case PLPGSQL_DTYPE_ROW:
1028 PLpgSQL_row *row = (PLpgSQL_row *) d;
1031 printf("ROW %-16s fields", row->refname);
1032 for (i = 0; i < row->nfields; i++)
1034 printf(" %s=var %d", row->fieldnames[i],
1040 case PLPGSQL_DTYPE_REC:
1041 printf("REC %s\n", ((PLpgSQL_rec *) d)->refname);
1043 case PLPGSQL_DTYPE_RECFIELD:
1044 printf("RECFIELD %-16s of REC %d\n",
1045 ((PLpgSQL_recfield *) d)->fieldname,
1046 ((PLpgSQL_recfield *) d)->recparentno);
1048 case PLPGSQL_DTYPE_ARRAYELEM:
1049 printf("ARRAYELEM of VAR %d subscript ",
1050 ((PLpgSQL_arrayelem *) d)->arrayparentno);
1051 dump_expr(((PLpgSQL_arrayelem *) d)->subscript);
1054 case PLPGSQL_DTYPE_TRIGARG:
1056 dump_expr(((PLpgSQL_trigarg *) d)->argnum);
1060 printf("??? unknown data type %d\n", d->dtype);
1063 printf("\nFunctions statements:\n");
1066 printf("%3d:", func->action->lineno);
1067 dump_block(func->action);
1068 printf("\nEnd of execution tree of function %s\n\n", func->fn_name);