From: Tom Lane Date: Tue, 4 Apr 2023 17:33:18 +0000 (-0400) Subject: Add a way to get the current function's OID in pl/pgsql. X-Git-Tag: REL_16_BETA1~336 X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=d3d53f955cf6ad755ba3682577e0f6fa10106438;p=postgresql.git Add a way to get the current function's OID in pl/pgsql. Invent "GET DIAGNOSTICS oid_variable = PG_ROUTINE_OID". This is useful for avoiding the maintenance nuisances that come with embedding a function's name in its body, as one might do for logging purposes for example. Typically users would cast the result to regproc or regprocedure to get something human-readable, but we won't pre-judge whether that's appropriate. Pavel Stehule, reviewed by Kirk Wolak and myself Discussion: https://postgr.es/m/CAFj8pRA4zMd5pY-B89Gm64bDLRt-L+akOd34aD1j4PEstHHSVQ@mail.gmail.com --- diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index 7c8a49fe435..f55e901c7e5 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -1639,6 +1639,11 @@ GET DIAGNOSTICS integer_var = ROW_COUNT; line(s) of text describing the current call stack (see ) + + PG_ROUTINE_OID + oid + OID of the current function + diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b0a2cac2276..e271ae51519 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -2411,6 +2411,12 @@ exec_stmt_getdiag(PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt) false, INT8OID, -1); break; + case PLPGSQL_GETDIAG_ROUTINE_OID: + exec_assign_value(estate, var, + ObjectIdGetDatum(estate->func->fn_oid), + false, OIDOID, -1); + break; + case PLPGSQL_GETDIAG_ERROR_CONTEXT: exec_assign_c_string(estate, var, estate->cur_error->context); diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c index 5a6eadccd5a..f010515fdf6 100644 --- a/src/pl/plpgsql/src/pl_funcs.c +++ b/src/pl/plpgsql/src/pl_funcs.c @@ -303,6 +303,8 @@ plpgsql_getdiag_kindname(PLpgSQL_getdiag_kind kind) { case PLPGSQL_GETDIAG_ROW_COUNT: return "ROW_COUNT"; + case PLPGSQL_GETDIAG_ROUTINE_OID: + return "PG_ROUTINE_OID"; case PLPGSQL_GETDIAG_CONTEXT: return "PG_CONTEXT"; case PLPGSQL_GETDIAG_ERROR_CONTEXT: diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y index edeb72c3808..6a09bfdd675 100644 --- a/src/pl/plpgsql/src/pl_gram.y +++ b/src/pl/plpgsql/src/pl_gram.y @@ -322,6 +322,7 @@ static void check_raise_parameters(PLpgSQL_stmt_raise *stmt); %token K_PG_EXCEPTION_CONTEXT %token K_PG_EXCEPTION_DETAIL %token K_PG_EXCEPTION_HINT +%token K_PG_ROUTINE_OID %token K_PRINT_STRICT_PARAMS %token K_PRIOR %token K_QUERY @@ -1008,6 +1009,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_ROUTINE_OID: if (new->is_stacked) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), @@ -1090,6 +1092,9 @@ getdiag_item : if (tok_is_keyword(tok, &yylval, K_ROW_COUNT, "row_count")) $$ = PLPGSQL_GETDIAG_ROW_COUNT; + else if (tok_is_keyword(tok, &yylval, + K_PG_ROUTINE_OID, "pg_routine_oid")) + $$ = PLPGSQL_GETDIAG_ROUTINE_OID; else if (tok_is_keyword(tok, &yylval, K_PG_CONTEXT, "pg_context")) $$ = PLPGSQL_GETDIAG_CONTEXT; @@ -2528,6 +2533,7 @@ unreserved_keyword : | K_PG_EXCEPTION_CONTEXT | K_PG_EXCEPTION_DETAIL | K_PG_EXCEPTION_HINT + | K_PG_ROUTINE_OID | K_PRINT_STRICT_PARAMS | K_PRIOR | K_QUERY diff --git a/src/pl/plpgsql/src/pl_unreserved_kwlist.h b/src/pl/plpgsql/src/pl_unreserved_kwlist.h index 466bdc7a205..3e258a6bb95 100644 --- a/src/pl/plpgsql/src/pl_unreserved_kwlist.h +++ b/src/pl/plpgsql/src/pl_unreserved_kwlist.h @@ -85,6 +85,7 @@ PG_KEYWORD("pg_datatype_name", K_PG_DATATYPE_NAME) PG_KEYWORD("pg_exception_context", K_PG_EXCEPTION_CONTEXT) PG_KEYWORD("pg_exception_detail", K_PG_EXCEPTION_DETAIL) PG_KEYWORD("pg_exception_hint", K_PG_EXCEPTION_HINT) +PG_KEYWORD("pg_routine_oid", K_PG_ROUTINE_OID) PG_KEYWORD("print_strict_params", K_PRINT_STRICT_PARAMS) PG_KEYWORD("prior", K_PRIOR) PG_KEYWORD("query", K_QUERY) diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h index 355c9f678d8..c40471bb898 100644 --- a/src/pl/plpgsql/src/plpgsql.h +++ b/src/pl/plpgsql/src/plpgsql.h @@ -147,6 +147,7 @@ enum typedef enum PLpgSQL_getdiag_kind { PLPGSQL_GETDIAG_ROW_COUNT, + PLPGSQL_GETDIAG_ROUTINE_OID, PLPGSQL_GETDIAG_CONTEXT, PLPGSQL_GETDIAG_ERROR_CONTEXT, PLPGSQL_GETDIAG_ERROR_DETAIL, diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out index 2d26be1a810..272f5d2111b 100644 --- a/src/test/regress/expected/plpgsql.out +++ b/src/test/regress/expected/plpgsql.out @@ -5229,7 +5229,7 @@ NOTICE: outer_func() done 20 (1 row) --- repeated call should to work +-- repeated call should work select outer_outer_func(20); NOTICE: calling down into outer_func() NOTICE: calling down into inner_func() @@ -5311,7 +5311,7 @@ NOTICE: outer_func() done 20 (1 row) --- repeated call should to work +-- repeated call should work select outer_outer_func(20); NOTICE: calling down into outer_func() NOTICE: calling down into inner_func() @@ -5332,6 +5332,33 @@ NOTICE: outer_func() done drop function outer_outer_func(int); drop function outer_func(int); drop function inner_func(int); +-- Test pg_routine_oid +create function current_function(text) +returns regprocedure as $$ +declare + fn_oid regprocedure; +begin + get diagnostics fn_oid = pg_routine_oid; + return fn_oid; +end; +$$ language plpgsql; +select current_function('foo'); + current_function +------------------------ + current_function(text) +(1 row) + +drop function current_function(text); +-- shouldn't fail in DO, even though there's no useful data +do $$ +declare + fn_oid oid; +begin + get diagnostics fn_oid = pg_routine_oid; + raise notice 'pg_routine_oid = %', fn_oid; +end; +$$; +NOTICE: pg_routine_oid = 0 -- -- Test ASSERT -- diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql index 98365e087f8..924d5240946 100644 --- a/src/test/regress/sql/plpgsql.sql +++ b/src/test/regress/sql/plpgsql.sql @@ -4206,7 +4206,7 @@ end; $$ language plpgsql; select outer_outer_func(10); --- repeated call should to work +-- repeated call should work select outer_outer_func(20); drop function outer_outer_func(int); @@ -4261,13 +4261,38 @@ end; $$ language plpgsql; select outer_outer_func(10); --- repeated call should to work +-- repeated call should work select outer_outer_func(20); drop function outer_outer_func(int); drop function outer_func(int); drop function inner_func(int); +-- Test pg_routine_oid +create function current_function(text) +returns regprocedure as $$ +declare + fn_oid regprocedure; +begin + get diagnostics fn_oid = pg_routine_oid; + return fn_oid; +end; +$$ language plpgsql; + +select current_function('foo'); + +drop function current_function(text); + +-- shouldn't fail in DO, even though there's no useful data +do $$ +declare + fn_oid oid; +begin + get diagnostics fn_oid = pg_routine_oid; + raise notice 'pg_routine_oid = %', fn_oid; +end; +$$; + -- -- Test ASSERT --