• R/O
  • HTTP
  • SSH
  • HTTPS

pg_hint_plan: Commit

firtst release


Commit MetaInfo

Revision9599067426fd440c898ad01252e70c90b6948585 (tree)
Time2019-02-26 18:30:07
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
@@ -512,6 +512,7 @@ static int pg_hint_plan_debug_message_level = LOG;
512512 static bool pg_hint_plan_enable_hint_table = false;
513513
514514 static int plpgsql_recurse_level = 0; /* PLpgSQL recursion level */
515+static int recurse_level = 0; /* recursion level incl. direct SPI calls */
515516 static int hint_inhibit_level = 0; /* Inhibit hinting if this is above 0 */
516517 /* (This could not be above 1) */
517518 static int max_hint_nworkers = -1; /* Maximum nworkers of Workers hints */
@@ -2984,6 +2985,7 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
29842985 int save_nestlevel;
29852986 PlannedStmt *result;
29862987 HintState *hstate;
2988+ const char *prev_hint_str;
29872989
29882990 /*
29892991 * Use standard planner if pg_hint_plan is disabled or current nesting
@@ -3012,9 +3014,6 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
30123014 {
30133015 MemoryContext oldcontext;
30143016
3015- if (current_hint_str)
3016- pfree((void *)current_hint_str);
3017-
30183017 oldcontext = MemoryContextSwitchTo(TopMemoryContext);
30193018 current_hint_str =
30203019 get_hints_from_comment((char *)error_context_stack->arg);
@@ -3084,10 +3083,21 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
30843083 */
30853084 PG_TRY();
30863085 {
3086+ /*
3087+ * The planner call below may replace current_hint_str. Store and
3088+ * restore it so that the subsequent planning in the upper level
3089+ * doesn't get confused.
3090+ */
3091+ recurse_level++;
3092+ prev_hint_str = current_hint_str;
3093+
30873094 if (prev_planner)
30883095 result = (*prev_planner) (parse, cursorOptions, boundParams);
30893096 else
30903097 result = standard_planner(parse, cursorOptions, boundParams);
3098+
3099+ current_hint_str = prev_hint_str;
3100+ recurse_level--;
30913101 }
30923102 PG_CATCH();
30933103 {
@@ -3095,6 +3105,8 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
30953105 * Rollback changes of GUC parameters, and pop current hint context
30963106 * from hint stack to rewind the state.
30973107 */
3108+ current_hint_str = prev_hint_str;
3109+ recurse_level--;
30983110 AtEOXact_GUC(true, save_nestlevel);
30993111 pop_hint();
31003112 PG_RE_THROW();
@@ -3105,7 +3117,7 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
31053117 /*
31063118 * current_hint_str is useless after planning of the top-level query.
31073119 */
3108- if (plpgsql_recurse_level < 1 && current_hint_str)
3120+ if (recurse_level < 1 && current_hint_str)
31093121 {
31103122 pfree((void *)current_hint_str);
31113123 current_hint_str = NULL;
Show on old repository browser