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 <[email protected]>
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;
/*