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