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
parent
2200ba8659
commit
a3a4c99011
|
@ -699,9 +699,17 @@ pgss_planner_hook(Query *parse, const char *query_string, int cursorOptions, Par
|
||||||
plan_nested_level++;
|
plan_nested_level++;
|
||||||
PG_TRY();
|
PG_TRY();
|
||||||
{
|
{
|
||||||
if (planner_hook_next)
|
/*
|
||||||
result = planner_hook_next(parse, query_string, cursorOptions, boundParams);
|
* If there is a previous installed hook, then assume it's going to call
|
||||||
result = standard_planner(parse, query_string, cursorOptions, boundParams);
|
* 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();
|
PG_FINALLY();
|
||||||
{
|
{
|
||||||
|
@ -734,9 +742,17 @@ pgss_planner_hook(Query *parse, const char *query_string, int cursorOptions, Par
|
||||||
}
|
}
|
||||||
else
|
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)
|
if (planner_hook_next)
|
||||||
result = planner_hook_next(parse, query_string, cursorOptions, boundParams);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue