PG-197: Fix conflict with pg_stat_statements.

If pg_stat_monitor is loaded after pg_stat_statement, then it will end
up calling standard_planner function twice in the pgss_planner_hook()
function, this will trigger an assertion failure from PostgreSQL as this
function expects an untouched Query* object, and the first call to
standard_planner() done by pg_stat_statements modifies the object.

To address the problem, we avoid calling standard_planner function twice
in pg_stat_monitor, if a previous handler is installed for the hook
planner_hook, then we assume that this previous hook has already called
standard_planner function and don't do it again.
pull/84/head
Diego Fronza 2021-07-20 17:38:01 -04:00
parent 2200ba8659
commit a3a4c99011
1 changed files with 20 additions and 4 deletions

View File

@ -699,9 +699,17 @@ pgss_planner_hook(Query *parse, const char *query_string, int cursorOptions, Par
plan_nested_level++;
PG_TRY();
{
if (planner_hook_next)
result = planner_hook_next(parse, query_string, cursorOptions, boundParams);
result = standard_planner(parse, query_string, cursorOptions, boundParams);
/*
* If there is a previous installed hook, then assume it's going to call
* standard_planner() function, otherwise we call the function here.
* This is to avoid calling standard_planner() function twice, since it
* modifies the first argument (Query *), the second call would trigger an
* assertion failure.
*/
if (planner_hook_next)
result = planner_hook_next(parse, query_string, cursorOptions, boundParams);
else
result = standard_planner(parse, query_string, cursorOptions, boundParams);
}
PG_FINALLY();
{
@ -734,9 +742,17 @@ pgss_planner_hook(Query *parse, const char *query_string, int cursorOptions, Par
}
else
{
/*
* If there is a previous installed hook, then assume it's going to call
* standard_planner() function, otherwise we call the function here.
* This is to avoid calling standard_planner() function twice, since it
* modifies the first argument (Query *), the second call would trigger an
* assertion failure.
*/
if (planner_hook_next)
result = planner_hook_next(parse, query_string, cursorOptions, boundParams);
result = standard_planner(parse, query_string, cursorOptions, boundParams);
else
result = standard_planner(parse, query_string, cursorOptions, boundParams);
}
return result;
}