st 18. 11. 2020 v 6:58 odesílatel Pavel Stehule <[email protected]>
napsal:
>
>
> út 17. 11. 2020 v 21:45 odesílatel Chapman Flack <[email protected]>
> 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;
/*