Hi

so 13. 3. 2021 v 12:48 odesílatel Julien Rouhaud <rjuju...@gmail.com>
napsal:

> On Sat, Mar 13, 2021 at 12:10:29PM +0100, Pavel Stehule wrote:
> >
> > so 13. 3. 2021 v 9:53 odesílatel Julien Rouhaud <rjuju...@gmail.com>
> napsal:
> > >
> > > I don't think that it makes sense to have multiple occurences of this
> > > command,
> > > and we should simply error out if
> plpgsql_curr_compile->root_ns->itemno is
> > > PLPGSQL_LABEL_REPLACED.  If any case this should also be covered in the
> > > regression tests.
> > >
> >
> > I did it. Thank you for check
>
> Thanks, LGTM.
>
> > I wrote few sentences to documentation
>
> Great!
>
> I just had a few cosmetic comments:
>
> +      block can be changed by inserting special command at the start of
> the function
> [...]
> +     arguments) is possible with option <literal>routine_label</literal>:
> [...]
> +                                errhint("The option \"routine_label\" can
> be used only once in rutine."),
> [...]
> +-- Check root namespace renaming (routine_label option)
>
> You're sometimes using "command" and "sometimes" option.  Should we always
> use
> the same term, maybe "command" as it's already used for #variable_conflict
> documentation?
>
> Also
>
> +      variables can be qualified with the function's name. The name of
> this outer
> +      block can be changed by inserting special command at the start of
> the function
> +      <literal>#routine_label new_name</literal>.
>
> It's missing a preposition before "special command".  Maybe
>
> +      variables can be qualified with the function's name. The name of
> this outer
> +      block can be changed by inserting a special command
> +      <literal>#routine_label new_name</literal> at the start of the
> function.
>
>
> +     The function's argument can be qualified by function name:
>
> Should be "qualified with the function name"
>
> +     Sometimes the function name is too long and can be more practical to
> use
> +     some shorter label. An change of label of top namespace (with
> functions's
> +     arguments) is possible with option <literal>routine_label</literal>:
>
> Few similar issues.  How about:
>
> Sometimes the function name is too long and *it* can be more practical to
> use
> some shorter label. *The top namespace label can be changed* (*along* with
> *the* functions' arguments) *using the option*
> <literal>routine_label</literal>:
>
> I'm not a native English speaker so the proposes changed may be wrong or
> not
> enough.
>

My English is good enough for taking beer everywhere in the world :) . Ti
is not good, but a lot of people who don't understand to English understand
my simplified fork of English language.

Thank you for check

updated patch attached

Pavel
diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index 9242c54329..1af56eef86 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -292,7 +292,10 @@ $$ LANGUAGE plpgsql;
       special variables such as <literal>FOUND</literal> (see
       <xref linkend="plpgsql-statements-diagnostics"/>).  The outer block is
       labeled with the function's name, meaning that parameters and special
-      variables can be qualified with the function's name.
+      variables can be qualified with the function's name. The name of this outer
+      block can be changed by inserting special command 
+      <literal>#routine_label new_name</literal> at the start of the function.
+      .
      </para>
     </note>
 
@@ -435,6 +438,31 @@ $$ LANGUAGE plpgsql;
      </para>
     </note>
 
+    <para>
+     The function's argument can be qualified with the function name:
+<programlisting>
+CREATE FUNCTION sales_tax(subtotal real) RETURNS real AS $$
+BEGIN
+    RETURN sales_tax.subtotal * 0.06;
+END;
+$$ LANGUAGE plpgsql;
+</programlisting>
+    </para>
+
+    <para>
+     Sometimes the function name is too long and it can be more practical to use
+     some shorter label. The top namespace label can be changed (along with
+     the functions' arguments) using the option <literal>routine_label</literal>:
+<programlisting>
+CREATE FUNCTION sales_tax(subtotal real) RETURNS real AS $$
+#routine_label s
+BEGIN
+    RETURN s.subtotal * 0.06;
+END;
+$$ LANGUAGE plpgsql;
+</programlisting>
+    </para>
+
      <para>
       Some more examples:
 <programlisting>
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index ce8d97447d..d32e050c32 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -378,6 +378,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->root_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 919b968826..9dc07f9e58 100644
--- a/src/pl/plpgsql/src/pl_funcs.c
+++ b/src/pl/plpgsql/src/pl_funcs.c
@@ -105,6 +105,40 @@ plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
 	ns_top = nse;
 }
 
+/*
+ * Replace ns item of label type by creating new entry and redirect
+ * old entry to new one.
+ */
+void
+plpgsql_ns_replace_root_label(PLpgSQL_nsitem *nse,
+							  const char *name,
+							  int location)
+{
+	PLpgSQL_nsitem *new_nse;
+
+	Assert(name != NULL);
+
+	/* Don't allow repeated redefination of routine label */
+	if (nse->itemno == PLPGSQL_LABEL_REPLACED)
+		ereport(ERROR,
+				(errcode(ERRCODE_SYNTAX_ERROR),
+				 errmsg("redundant option"),
+				 errhint("The command \"routine_label\" can be used only once in rutine."),
+				 plpgsql_scanner_errposition(location)));
+
+	Assert(nse->itemtype == PLPGSQL_NSTYPE_LABEL &&
+		   nse->itemno == (int) PLPGSQL_LABEL_BLOCK &&
+		   nse->prev == NULL);
+
+	new_nse = palloc(offsetof(PLpgSQL_nsitem, name) + strlen(name) + 1);
+	new_nse->itemtype = nse->itemtype;
+	new_nse->itemno = nse->itemno;
+	new_nse->prev = NULL;
+	strcpy(new_nse->name, name);
+
+	nse->prev = new_nse;
+	nse->itemno = (int) PLPGSQL_LABEL_REPLACED;
+}
 
 /* ----------
  * plpgsql_ns_lookup		Lookup an identifier in the given namespace chain
@@ -153,6 +187,14 @@ plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode,
 			}
 		}
 
+		if (nsitem->itemtype == PLPGSQL_NSTYPE_LABEL &&
+			 nsitem->itemno == (int) PLPGSQL_LABEL_REPLACED)
+		{
+			Assert(nsitem->prev &&
+				   nsitem->prev->itemtype == PLPGSQL_NSTYPE_LABEL);
+			nsitem = nsitem->prev;
+		}
+
 		/* Check this level for qualified match to variable name */
 		if (name2 != NULL &&
 			strcmp(nsitem->name, name1) == 0)
@@ -197,6 +239,7 @@ plpgsql_ns_lookup_label(PLpgSQL_nsitem *ns_cur, const char *name)
 	while (ns_cur != NULL)
 	{
 		if (ns_cur->itemtype == PLPGSQL_NSTYPE_LABEL &&
+			ns_cur->itemno != PLPGSQL_LABEL_REPLACED &&
 			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 34e0520719..528a80c1c4 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -333,6 +333,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
@@ -393,6 +394,12 @@ comp_option		: '#' K_OPTION K_DUMP
 					{
 						plpgsql_curr_compile->resolve_option = PLPGSQL_RESOLVE_COLUMN;
 					}
+				| '#' K_ROUTINE_LABEL any_identifier
+					{
+						plpgsql_ns_replace_root_label(plpgsql_curr_compile->root_ns,
+													  pstrdup($3),
+													  @1);
+					}
 				;
 
 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 44c8b68bfb..d09d4729b7 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 d5010862a5..def1192b75 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -52,7 +52,8 @@ typedef enum PLpgSQL_label_type
 {
 	PLPGSQL_LABEL_BLOCK,		/* DECLARE/BEGIN block */
 	PLPGSQL_LABEL_LOOP,			/* looping construct */
-	PLPGSQL_LABEL_OTHER			/* anything else */
+	PLPGSQL_LABEL_OTHER,		/* anything else */
+	PLPGSQL_LABEL_REPLACED,		/* replaced label */
 } PLpgSQL_label_type;
 
 /*
@@ -1024,6 +1025,9 @@ typedef struct PLpgSQL_function
 	/* these fields change when the function is used */
 	struct PLpgSQL_execstate *cur_estate;
 	unsigned long use_count;
+
+	/* routine level namespace entry */
+	struct PLpgSQL_nsitem *root_ns;
 } PLpgSQL_function;
 
 /*
@@ -1294,6 +1298,8 @@ extern void plpgsql_ns_push(const char *label,
 extern void plpgsql_ns_pop(void);
 extern PLpgSQL_nsitem *plpgsql_ns_top(void);
 extern void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name);
+extern void plpgsql_ns_replace_root_label(PLpgSQL_nsitem *nse, const char *name,
+										  int location);
 extern PLpgSQL_nsitem *plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode,
 										 const char *name1, const char *name2,
 										 const char *name3, int *names_used);
diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out
index 6ea169d9ad..04176fa40a 100644
--- a/src/test/regress/expected/plpgsql.out
+++ b/src/test/regress/expected/plpgsql.out
@@ -5701,3 +5701,48 @@ END; $$ LANGUAGE plpgsql;
 ERROR:  "x" is not a scalar variable
 LINE 3:   GET DIAGNOSTICS x = ROW_COUNT;
                           ^
+--
+-- Check root namespace renaming (routine_label option)
+--
+CREATE OR REPLACE FUNCTION test_root_namespace_rename(arg1 int)
+RETURNS void AS $$
+#ROUTINE_LABEL argsns
+BEGIN
+  RAISE NOTICE '% %', arg1, argsns.arg1;
+END;
+$$ LANGUAGE plpgsql;
+SELECT test_root_namespace_rename(10);
+NOTICE:  10 10
+ test_root_namespace_rename 
+----------------------------
+ 
+(1 row)
+
+CREATE OR REPLACE FUNCTION test_root_namespace_rename(arg1 int)
+RETURNS void AS $$
+#ROUTINE_LABEL argsns
+BEGIN
+  -- should to fail, original name is overwritten
+  RAISE NOTICE '% %', arg1, test_root_namespace_rename.arg1;
+END;
+$$ LANGUAGE plpgsql;
+SELECT test_root_namespace_rename(10);
+ERROR:  missing FROM-clause entry for table "test_root_namespace_rename"
+LINE 1: test_root_namespace_rename.arg1
+        ^
+QUERY:  test_root_namespace_rename.arg1
+CONTEXT:  PL/pgSQL function test_root_namespace_rename(integer) line 5 at RAISE
+-- should fail, syntax error - redundant option
+CREATE OR REPLACE FUNCTION test_root_namespace_rename(arg1 int)
+RETURNS void AS $$
+#ROUTINE_LABEL argsns
+#ROUTINE_LABEL argsns
+BEGIN
+  -- should to fail, original name is overwritten
+  RAISE NOTICE '% %', arg1, test_root_namespace_rename.arg1;
+END;
+$$ LANGUAGE plpgsql;
+ERROR:  redundant option
+LINE 4: #ROUTINE_LABEL argsns
+        ^
+HINT:  The command "routine_label" can be used only once in rutine.
diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql
index 781666a83a..da58e46182 100644
--- a/src/test/regress/sql/plpgsql.sql
+++ b/src/test/regress/sql/plpgsql.sql
@@ -4645,3 +4645,38 @@ BEGIN
   GET DIAGNOSTICS x = ROW_COUNT;
   RETURN;
 END; $$ LANGUAGE plpgsql;
+
+--
+-- Check root namespace renaming (routine_label option)
+--
+CREATE OR REPLACE FUNCTION test_root_namespace_rename(arg1 int)
+RETURNS void AS $$
+#ROUTINE_LABEL argsns
+BEGIN
+  RAISE NOTICE '% %', arg1, argsns.arg1;
+END;
+$$ LANGUAGE plpgsql;
+
+SELECT test_root_namespace_rename(10);
+
+CREATE OR REPLACE FUNCTION test_root_namespace_rename(arg1 int)
+RETURNS void AS $$
+#ROUTINE_LABEL argsns
+BEGIN
+  -- should to fail, original name is overwritten
+  RAISE NOTICE '% %', arg1, test_root_namespace_rename.arg1;
+END;
+$$ LANGUAGE plpgsql;
+
+SELECT test_root_namespace_rename(10);
+
+-- should fail, syntax error - redundant option
+CREATE OR REPLACE FUNCTION test_root_namespace_rename(arg1 int)
+RETURNS void AS $$
+#ROUTINE_LABEL argsns
+#ROUTINE_LABEL argsns
+BEGIN
+  -- should to fail, original name is overwritten
+  RAISE NOTICE '% %', arg1, test_root_namespace_rename.arg1;
+END;
+$$ LANGUAGE plpgsql;

Reply via email to