• R/O
  • HTTP
  • SSH
  • HTTPS

pg_hint_plan: コミット

firtst release


コミットメタ情報

リビジョン000c325874cc07eb944447d046a122dcc8642520 (tree)
日時2019-02-26 20:09:40
作者Kyotaro Horiguchi <horiguchi.kyotaro@lab....>
コミッターKyotaro Horiguchi

ログメッセージ

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.

9.5 is not affected. Back patched back to 9.6.

変更サマリ

差分

--- a/pg_hint_plan.c
+++ b/pg_hint_plan.c
@@ -516,6 +516,7 @@ static int pg_hint_plan_debug_message_level = LOG;
516516 static bool pg_hint_plan_enable_hint_table = false;
517517
518518 static int plpgsql_recurse_level = 0; /* PLpgSQL recursion level */
519+static int recurse_level = 0; /* recursion level incl. direct SPI calls */
519520 static int hint_inhibit_level = 0; /* Inhibit hinting if this is above 0 */
520521 /* (This could not be above 1) */
521522 static int max_hint_nworkers = -1; /* Maximum nworkers of Workers hints */
@@ -2988,6 +2989,7 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
29882989 int save_nestlevel;
29892990 PlannedStmt *result;
29902991 HintState *hstate;
2992+ const char *prev_hint_str;
29912993
29922994 /*
29932995 * Use standard planner if pg_hint_plan is disabled or current nesting
@@ -3016,9 +3018,6 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
30163018 {
30173019 MemoryContext oldcontext;
30183020
3019- if (current_hint_str)
3020- pfree((void *)current_hint_str);
3021-
30223021 oldcontext = MemoryContextSwitchTo(TopMemoryContext);
30233022 current_hint_str =
30243023 get_hints_from_comment((char *)error_context_stack->arg);
@@ -3088,10 +3087,21 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
30883087 */
30893088 PG_TRY();
30903089 {
3090+ /*
3091+ * The planner call below may replace current_hint_str. Store and
3092+ * restore it so that the subsequent planning in the upper level
3093+ * doesn't get confused.
3094+ */
3095+ recurse_level++;
3096+ prev_hint_str = current_hint_str;
3097+
30913098 if (prev_planner)
30923099 result = (*prev_planner) (parse, cursorOptions, boundParams);
30933100 else
30943101 result = standard_planner(parse, cursorOptions, boundParams);
3102+
3103+ current_hint_str = prev_hint_str;
3104+ recurse_level--;
30953105 }
30963106 PG_CATCH();
30973107 {
@@ -3099,6 +3109,8 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
30993109 * Rollback changes of GUC parameters, and pop current hint context
31003110 * from hint stack to rewind the state.
31013111 */
3112+ current_hint_str = prev_hint_str;
3113+ recurse_level--;
31023114 AtEOXact_GUC(true, save_nestlevel);
31033115 pop_hint();
31043116 PG_RE_THROW();
@@ -3109,7 +3121,7 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
31093121 /*
31103122 * current_hint_str is useless after planning of the top-level query.
31113123 */
3112- if (plpgsql_recurse_level < 1 && current_hint_str)
3124+ if (recurse_level < 1 && current_hint_str)
31133125 {
31143126 pfree((void *)current_hint_str);
31153127 current_hint_str = NULL;
旧リポジトリブラウザで表示