Hi,

Attached is a patch to implement a feature to get the current function
name by GET DIAGNOSTICS in PL/pgSQL function.

Currentyly, we can get call stack by GET DIAGNOSTICS PG_CONTEXT, but
we cannot get the function name directly. One of our clients wanted
this feature for debugging, and this was realized by creating a 
function that extracts the function name string from call stack. 
However, the overhead of function calls was not small, and it
caused performance regression. 

I found that there are other needs for this feature[1], so I have
implemented this.

[1] 
https://stackoverflow.com/questions/12611596/getting-name-of-the-current-function-inside-of-the-function-with-plpgsql

Example:

postgres=# CREATE FUNCTION test() RETURNS void 
LANGUAGE plpgsql AS $$
DECLARE t text;
BEGIN
GET DIAGNOSTICS t = FUNCTION_NAME;
RAISE INFO 'function name: %', t;
END;
$$;
CREATE FUNCTION

postgres=# select test();
INFO:  function name: test()
 test 
------
 
(1 row)

Regards,

-- 
Yugo Nagata <nag...@sraoss.co.jp>
diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index 7d23ed4..c0daa14 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -1506,6 +1506,12 @@ GET DIAGNOSTICS integer_var = ROW_COUNT;
          <entry>line(s) of text describing the current call stack
           (see <xref linkend="plpgsql-call-stack"/>)</entry>
         </row>
+        <row>
+         <entry><literal>FUNCTION_NAME</literal></entry>
+         <entry><type>text</type></entry>
+         <entry>text describing the current function signature 
+          (see <xref linkend="plpgsql-call-stack"/>)</entry>
+        </row>
        </tbody>
       </tgroup>
      </table>
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index dd575e7..4404aac 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -1812,6 +1812,11 @@ exec_stmt_getdiag(PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt)
 				}
 				break;
 
+			case PLPGSQL_GETDIAG_FUNCTION_NAME:
+				exec_assign_c_string(estate, var,
+									 estate->func->fn_signature);
+				break;
+
 			default:
 				elog(ERROR, "unrecognized diagnostic item kind: %d",
 					 diag_item->kind);
diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c
index be779b6..9d9a493 100644
--- a/src/pl/plpgsql/src/pl_funcs.c
+++ b/src/pl/plpgsql/src/pl_funcs.c
@@ -323,6 +323,8 @@ plpgsql_getdiag_kindname(PLpgSQL_getdiag_kind kind)
 			return "TABLE_NAME";
 		case PLPGSQL_GETDIAG_SCHEMA_NAME:
 			return "SCHEMA_NAME";
+		case PLPGSQL_GETDIAG_FUNCTION_NAME:
+			return "FUNCTION_NAME";
 	}
 
 	return "unknown";
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
index e802440..adf20e7 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -287,6 +287,7 @@ static	void			check_raise_parameters(PLpgSQL_stmt_raise *stmt);
 %token <keyword>	K_FOREACH
 %token <keyword>	K_FORWARD
 %token <keyword>	K_FROM
+%token <keyword>	K_FUNCTION_NAME
 %token <keyword>	K_GET
 %token <keyword>	K_HINT
 %token <keyword>	K_IF
@@ -949,6 +950,7 @@ stmt_getdiag	: K_GET getdiag_area_opt K_DIAGNOSTICS getdiag_list ';'
 								/* these fields are disallowed in stacked case */
 								case PLPGSQL_GETDIAG_ROW_COUNT:
 								case PLPGSQL_GETDIAG_RESULT_OID:
+								case PLPGSQL_GETDIAG_FUNCTION_NAME:
 									if (new->is_stacked)
 										ereport(ERROR,
 												(errcode(ERRCODE_SYNTAX_ERROR),
@@ -1065,6 +1067,9 @@ getdiag_item :
 												K_SCHEMA_NAME, "schema_name"))
 							$$ = PLPGSQL_GETDIAG_SCHEMA_NAME;
 						else if (tok_is_keyword(tok, &yylval,
+												K_FUNCTION_NAME, "function_name"))
+							$$ = PLPGSQL_GETDIAG_FUNCTION_NAME;
+						else if (tok_is_keyword(tok, &yylval,
 												K_RETURNED_SQLSTATE, "returned_sqlstate"))
 							$$ = PLPGSQL_GETDIAG_RETURNED_SQLSTATE;
 						else
@@ -2407,6 +2412,7 @@ unreserved_keyword	:
 				| K_FETCH
 				| K_FIRST
 				| K_FORWARD
+				| K_FUNCTION_NAME
 				| K_GET
 				| K_HINT
 				| K_IMPORT
diff --git a/src/pl/plpgsql/src/pl_scanner.c b/src/pl/plpgsql/src/pl_scanner.c
index 553be8c..2b624f6 100644
--- a/src/pl/plpgsql/src/pl_scanner.c
+++ b/src/pl/plpgsql/src/pl_scanner.c
@@ -127,6 +127,7 @@ static const ScanKeyword unreserved_keywords[] = {
 	PG_KEYWORD("fetch", K_FETCH, UNRESERVED_KEYWORD)
 	PG_KEYWORD("first", K_FIRST, UNRESERVED_KEYWORD)
 	PG_KEYWORD("forward", K_FORWARD, UNRESERVED_KEYWORD)
+	PG_KEYWORD("function_name", K_FUNCTION_NAME, UNRESERVED_KEYWORD)
 	PG_KEYWORD("get", K_GET, UNRESERVED_KEYWORD)
 	PG_KEYWORD("hint", K_HINT, UNRESERVED_KEYWORD)
 	PG_KEYWORD("import", K_IMPORT, UNRESERVED_KEYWORD)
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 43d7d7d..f515f50 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -136,7 +136,8 @@ typedef enum PLpgSQL_getdiag_kind
 	PLPGSQL_GETDIAG_DATATYPE_NAME,
 	PLPGSQL_GETDIAG_MESSAGE_TEXT,
 	PLPGSQL_GETDIAG_TABLE_NAME,
-	PLPGSQL_GETDIAG_SCHEMA_NAME
+	PLPGSQL_GETDIAG_SCHEMA_NAME,
+	PLPGSQL_GETDIAG_FUNCTION_NAME
 } PLpgSQL_getdiag_kind;
 
 /*

Reply via email to