st 18. 11. 2020 v 6:58 odesílatel Pavel Stehule <pavel.steh...@gmail.com> napsal:
> > > út 17. 11. 2020 v 21:45 odesílatel Chapman Flack <c...@anastigmatix.net> > napsal: > >> On 11/17/20 15:18, Jack Christensen wrote: >> >> CREATE OR REPLACE FUNCTION very_long_name(par1 int) >> >> RETURNS int AS $$ >> >> #routine_label lnm >> >> BEGIN >> >> RAISE NOTICE '%', lnm.par1; >> >> Could that be somehow shoehorned into the existing ALIAS syntax, maybe as >> >> DECLARE >> lnm ALIAS FOR ALL very_long_name.*; >> >> or something? >> > > I thought about it - but I don't think so this syntax is correct - in your > case it should be > > lnm.* ALIAS FOR ALL very_long_name.*; > > but it looks a little bit scary in ADA based language. > > Maybe > > DECLARE lnm LABEL ALIAS FOR very_long_name; > > or > > DECLARE lnm ALIAS FOR LABEL very_long_name; > > I think so implementation should not be hard. But there are advantages, > disadvantages - 1. label aliasing increases the complexity of variable > searching (instead comparing string with name of namespace, you should > compare list of names). Probably not too much. 2. The syntax is a little > bit harder than #option. Implementation based on #option can just rename > top namespace, so there is not any overhead, and parsing #option syntax is > pretty simple (and the syntax is shorter). So from implementation reasons I > prefer #option based syntax. There is clear zero impact on performance. > > Regards > I checked code - and I have to change my opinion - the current implementation of namespaces in plpgsql doesn't allow renaming or realising labels elegantly. The design has low memory requirements but it is not flexible. I wrote a proof concept patch, and I had to hack the nsitem little bit. postgres=# create or replace function bubu(a int, b int) returns void as $$ #routine_label b begin raise notice '% %', b.a, b.b; end; $$ language plpgsql; CREATE FUNCTION postgres=# select bubu(10,20); NOTICE: 10 20 ┌──────┐ │ bubu │ ╞══════╡ │ │ └──────┘ (1 row) > Pavel > > >> >> (And would it be cool if Table C.1 [1] had some sort of javascript-y >> filtering on reservedness categories, for just such kinds of >> bikeshedding?) >> >> Regards, >> -Chap >> >> >> [1] >> https://www.postgresql.org/docs/13/sql-keywords-appendix.html#KEYWORDS-TABLE >> >
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c index 6df8e14629..9caf0fe752 100644 --- a/src/pl/plpgsql/src/pl_comp.c +++ b/src/pl/plpgsql/src/pl_comp.c @@ -376,6 +376,10 @@ do_compile(FunctionCallInfo fcinfo, */ plpgsql_ns_init(); plpgsql_ns_push(NameStr(procStruct->proname), PLPGSQL_LABEL_BLOCK); + + /* save top ns for possibility to alter top label */ + function->routine_ns = plpgsql_ns_top(); + plpgsql_DumpExecTree = false; plpgsql_start_datums(); diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c index ee60ced583..ebbb024be4 100644 --- a/src/pl/plpgsql/src/pl_funcs.c +++ b/src/pl/plpgsql/src/pl_funcs.c @@ -101,6 +101,7 @@ plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name) nse->itemtype = itemtype; nse->itemno = itemno; nse->prev = ns_top; + nse->altname = NULL; strcpy(nse->name, name); ns_top = nse; } @@ -155,7 +156,8 @@ plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, /* Check this level for qualified match to variable name */ if (name2 != NULL && - strcmp(nsitem->name, name1) == 0) + ((nsitem->altname && strcmp(nsitem->altname, name1) == 0) || + strcmp(nsitem->name, name1) == 0)) { for (nsitem = ns_cur; nsitem->itemtype != PLPGSQL_NSTYPE_LABEL; @@ -197,7 +199,8 @@ plpgsql_ns_lookup_label(PLpgSQL_nsitem *ns_cur, const char *name) while (ns_cur != NULL) { if (ns_cur->itemtype == PLPGSQL_NSTYPE_LABEL && - strcmp(ns_cur->name, name) == 0) + ((ns_cur->altname && strcmp(ns_cur->altname, name) == 0) || + strcmp(ns_cur->name, name) == 0)) return ns_cur; ns_cur = ns_cur->prev; } diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y index 8227bf0449..cf79e0d85d 100644 --- a/src/pl/plpgsql/src/pl_gram.y +++ b/src/pl/plpgsql/src/pl_gram.y @@ -335,6 +335,7 @@ static void check_raise_parameters(PLpgSQL_stmt_raise *stmt); %token <keyword> K_RETURNED_SQLSTATE %token <keyword> K_REVERSE %token <keyword> K_ROLLBACK +%token <keyword> K_ROUTINE_LABEL %token <keyword> K_ROW_COUNT %token <keyword> K_ROWTYPE %token <keyword> K_SCHEMA @@ -395,6 +396,13 @@ comp_option : '#' K_OPTION K_DUMP { plpgsql_curr_compile->resolve_option = PLPGSQL_RESOLVE_COLUMN; } + | '#' K_ROUTINE_LABEL any_identifier + { + plpgsql_curr_compile->routine_ns->altname = pstrdup($3); + + /* disable original label */ + *plpgsql_curr_compile->routine_ns->name = '\0'; + } ; option_value : T_WORD diff --git a/src/pl/plpgsql/src/pl_unreserved_kwlist.h b/src/pl/plpgsql/src/pl_unreserved_kwlist.h index 99b3cf7d8a..d6ed65b0a1 100644 --- a/src/pl/plpgsql/src/pl_unreserved_kwlist.h +++ b/src/pl/plpgsql/src/pl_unreserved_kwlist.h @@ -94,6 +94,7 @@ PG_KEYWORD("return", K_RETURN) PG_KEYWORD("returned_sqlstate", K_RETURNED_SQLSTATE) PG_KEYWORD("reverse", K_REVERSE) PG_KEYWORD("rollback", K_ROLLBACK) +PG_KEYWORD("routine_label", K_ROUTINE_LABEL) PG_KEYWORD("row_count", K_ROW_COUNT) PG_KEYWORD("rowtype", K_ROWTYPE) PG_KEYWORD("schema", K_SCHEMA) diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h index 0c3d30fb13..efef48e9cf 100644 --- a/src/pl/plpgsql/src/plpgsql.h +++ b/src/pl/plpgsql/src/plpgsql.h @@ -458,6 +458,7 @@ typedef struct PLpgSQL_nsitem */ int itemno; struct PLpgSQL_nsitem *prev; + char *altname; char name[FLEXIBLE_ARRAY_MEMBER]; /* nul-terminated string */ } PLpgSQL_nsitem; @@ -1037,6 +1038,9 @@ typedef struct PLpgSQL_function /* these fields change when the function is used */ struct PLpgSQL_execstate *cur_estate; unsigned long use_count; + + /* name of routine level namespace */ + struct PLpgSQL_nsitem *routine_ns; } PLpgSQL_function; /*