• R/O
  • HTTP
  • SSH
  • HTTPS

pg_hint_plan: Commit

firtst release


Commit MetaInfo

Revision647bad47746afec7b58d3a498bce6f36bd9ae984 (tree)
Time2019-02-26 17:49:50
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
@@ -521,6 +521,7 @@ static int pg_hint_plan_debug_message_level = LOG;
521521 static bool pg_hint_plan_enable_hint_table = false;
522522
523523 static int plpgsql_recurse_level = 0; /* PLpgSQL recursion level */
524+static int recurse_level = 0; /* recursion level incl. direct SPI calls */
524525 static int hint_inhibit_level = 0; /* Inhibit hinting if this is above 0 */
525526 /* (This could not be above 1) */
526527 static int max_hint_nworkers = -1; /* Maximum nworkers of Workers hints */
@@ -2993,6 +2994,7 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
29932994 int save_nestlevel;
29942995 PlannedStmt *result;
29952996 HintState *hstate;
2997+ const char *prev_hint_str;
29962998
29972999 /*
29983000 * Use standard planner if pg_hint_plan is disabled or current nesting
@@ -3021,9 +3023,6 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
30213023 {
30223024 MemoryContext oldcontext;
30233025
3024- if (current_hint_str)
3025- pfree((void *)current_hint_str);
3026-
30273026 oldcontext = MemoryContextSwitchTo(TopMemoryContext);
30283027 current_hint_str =
30293028 get_hints_from_comment((char *)error_context_stack->arg);
@@ -3093,10 +3092,21 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
30933092 */
30943093 PG_TRY();
30953094 {
3095+ /*
3096+ * The planner call below may replace current_hint_str. Store and
3097+ * restore it so that the subsequent planning in the upper level
3098+ * doesn't get confused.
3099+ */
3100+ recurse_level++;
3101+ prev_hint_str = current_hint_str;
3102+
30963103 if (prev_planner)
30973104 result = (*prev_planner) (parse, cursorOptions, boundParams);
30983105 else
30993106 result = standard_planner(parse, cursorOptions, boundParams);
3107+
3108+ current_hint_str = prev_hint_str;
3109+ recurse_level--;
31003110 }
31013111 PG_CATCH();
31023112 {
@@ -3104,6 +3114,8 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
31043114 * Rollback changes of GUC parameters, and pop current hint context
31053115 * from hint stack to rewind the state.
31063116 */
3117+ current_hint_str = prev_hint_str;
3118+ recurse_level--;
31073119 AtEOXact_GUC(true, save_nestlevel);
31083120 pop_hint();
31093121 PG_RE_THROW();
@@ -3114,7 +3126,7 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
31143126 /*
31153127 * current_hint_str is useless after planning of the top-level query.
31163128 */
3117- if (plpgsql_recurse_level < 1 && current_hint_str)
3129+ if (recurse_level < 1 && current_hint_str)
31183130 {
31193131 pfree((void *)current_hint_str);
31203132 current_hint_str = NULL;
Show on old repository browser