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;
 
 /*

Reply via email to