• R/O
  • HTTP
  • SSH
  • HTTPS

pg_hint_plan: Commit

firtst release


Commit MetaInfo

Revision009aa8bbf3c97cc9b46d524d94148ca15e6cfa9f (tree)
Time2019-02-26 16:10:29
AuthorKyotaro Horiguchi <horiguchi.kyotaro@lab....>
CommiterKyotaro Horiguchi

Log Message

Correctly handle planner nesting

pg_hint_plan assumed that plpgsql is the only source of nested planner
calls. Actually nested call can be made in any shapes. Most of the
cases doesn't harm but in a special case where pg_dbms_stats makes a
SPI call during query planning, that affects subsequent planner
work. Hints lose effect when pg_dbms_stats searches "locked
statistics" tables while planning the target query.

Change Summary

Incremental Difference

--- a/pg_hint_plan.c
+++ b/pg_hint_plan.c
@@ -513,6 +513,7 @@ static int pg_hint_plan_debug_message_level = LOG;
513513 static bool pg_hint_plan_enable_hint_table = false;
514514
515515 static int plpgsql_recurse_level = 0; /* PLpgSQL recursion level */
516+static int recurse_level = 0; /* recursion level incl. direct SPI calls */
516517 static int hint_inhibit_level = 0; /* Inhibit hinting if this is above 0 */
517518 /* (This could not be above 1) */
518519 static int max_hint_nworkers = -1; /* Maximum nworkers of Workers hints */
@@ -2986,6 +2987,7 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
29862987 int save_nestlevel;
29872988 PlannedStmt *result;
29882989 HintState *hstate;
2990+ const char *prev_hint_str;
29892991
29902992 /*
29912993 * Use standard planner if pg_hint_plan is disabled or current nesting
@@ -3014,9 +3016,6 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
30143016 {
30153017 MemoryContext oldcontext;
30163018
3017- if (current_hint_str)
3018- pfree((void *)current_hint_str);
3019-
30203019 oldcontext = MemoryContextSwitchTo(TopMemoryContext);
30213020 current_hint_str =
30223021 get_hints_from_comment((char *)error_context_stack->arg);
@@ -3083,10 +3082,21 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
30833082 */
30843083 PG_TRY();
30853084 {
3085+ /*
3086+ * The planner call below may replace current_hint_str. Store and
3087+ * restore it so that the subsequent planning in the upper level
3088+ * doesn't get confused.
3089+ */
3090+ recurse_level++;
3091+ prev_hint_str = current_hint_str;
3092+
30863093 if (prev_planner)
30873094 result = (*prev_planner) (parse, cursorOptions, boundParams);
30883095 else
30893096 result = standard_planner(parse, cursorOptions, boundParams);
3097+
3098+ current_hint_str = prev_hint_str;
3099+ recurse_level--;
30903100 }
30913101 PG_CATCH();
30923102 {
@@ -3094,6 +3104,8 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
30943104 * Rollback changes of GUC parameters, and pop current hint context
30953105 * from hint stack to rewind the state.
30963106 */
3107+ current_hint_str = prev_hint_str;
3108+ recurse_level--;
30973109 AtEOXact_GUC(true, save_nestlevel);
30983110 pop_hint();
30993111 PG_RE_THROW();
@@ -3104,7 +3116,7 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
31043116 /*
31053117 * current_hint_str is useless after planning of the top-level query.
31063118 */
3107- if (plpgsql_recurse_level < 1 && current_hint_str)
3119+ if (recurse_level < 1 && current_hint_str)
31083120 {
31093121 pfree((void *)current_hint_str);
31103122 current_hint_str = NULL;
Show on old repository browser