X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=pg_hint_plan.c;h=43ac931dc1f1828805d618a98aa1948c9c68db86;hb=231a4448bb1a5a93d06b2e919d9b2fbbf40a61df;hp=d24d5e8f18916596aac67f779118229823222157;hpb=bd5dcc3c80602da637b710ee4a5547408da0f760;p=pghintplan%2Fpg_hint_plan.git diff --git a/pg_hint_plan.c b/pg_hint_plan.c index d24d5e8..43ac931 100644 --- a/pg_hint_plan.c +++ b/pg_hint_plan.c @@ -3,7 +3,7 @@ * pg_hint_plan.c * hinting on how to execute a query for PostgreSQL * - * Copyright (c) 2012-2019, NIPPON TELEGRAPH AND TELEPHONE CORPORATION + * Copyright (c) 2012-2020, NIPPON TELEGRAPH AND TELEPHONE CORPORATION * *------------------------------------------------------------------------- */ @@ -38,6 +38,7 @@ #include "partitioning/partbounds.h" #include "tcop/utility.h" #include "utils/builtins.h" +#include "utils/float.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/rel.h" @@ -363,8 +364,8 @@ struct HintState int init_min_para_tablescan_size; /* min_parallel_index_scan_size*/ int init_min_para_indexscan_size; - int init_paratup_cost; /* parallel_tuple_cost */ - int init_parasetup_cost;/* parallel_setup_cost */ + double init_paratup_cost; /* parallel_tuple_cost */ + double init_parasetup_cost;/* parallel_setup_cost */ PlannerInfo *current_root; /* PlannerInfo for the followings */ Index parent_relid; /* inherit parent of table relid */ @@ -506,6 +507,8 @@ static void setup_scan_method_enforcement(ScanMethodHint *scanhint, HintState *state); static int set_config_int32_option(const char *name, int32 value, GucContext context); +static int set_config_double_option(const char *name, double value, + GucContext context); /* GUC variables */ static bool pg_hint_plan_enable_hint = true; @@ -1180,7 +1183,8 @@ RowsHintDesc(RowsHint *hint, StringInfo buf, bool nolf) quote_value(buf, hint->relnames[i]); } } - appendStringInfo(buf, " %s", hint->rows_str); + if (hint->rows_str != NULL) + appendStringInfo(buf, " %s", hint->rows_str); appendStringInfoString(buf, ")"); if (!nolf) appendStringInfoChar(buf, '\n'); @@ -1820,7 +1824,7 @@ get_query_string(ParseState *pstate, Query *query, Query **jumblequery) * case of DESCRIBE message handling or EXECUTE command. We may still see a * candidate top-level query in pstate in the case. */ - if (!p && pstate) + if (pstate && pstate->p_sourcetext) p = pstate->p_sourcetext; /* We don't see a query string, return NULL */ @@ -1887,13 +1891,24 @@ get_query_string(ParseState *pstate, Query *query, Query **jumblequery) PreparedStatement *entry; entry = FetchPreparedStatement(stmt->name, true); - p = entry->plansource->query_string; - target_query = (Query *) linitial (entry->plansource->query_list); + + if (entry->plansource->is_valid) + { + p = entry->plansource->query_string; + target_query = (Query *) linitial (entry->plansource->query_list); + } + else + { + /* igonre the hint for EXECUTE if invalidated */ + p = NULL; + target_query = NULL; + } } /* JumbleQuery accespts only a non-utility Query */ - if (!IsA(target_query, Query) || - target_query->utilityStmt != NULL) + if (target_query && + (!IsA(target_query, Query) || + target_query->utilityStmt != NULL)) target_query = NULL; if (jumblequery) @@ -2358,6 +2373,8 @@ RowsHintParse(RowsHint *hint, HintState *hstate, Query *parse, List *name_list = NIL; char *rows_str; char *end_ptr; + ListCell *l; + int i = 0; if ((str = parse_parentheses(str, &name_list, hint_keyword)) == NULL) return NULL; @@ -2365,23 +2382,28 @@ RowsHintParse(RowsHint *hint, HintState *hstate, Query *parse, /* Last element must be rows specification */ hint->nrels = list_length(name_list) - 1; - if (hint->nrels > 0) + if (hint->nrels < 1) { - ListCell *l; - int i = 0; + hint_ereport(str, + ("%s hint needs at least one relation followed by one correction term.", + hint->base.keyword)); + hint->base.state = HINT_STATE_ERROR; - /* - * Transform relation names from list to array to sort them with qsort - * after. - */ - hint->relnames = palloc(sizeof(char *) * hint->nrels); - foreach (l, name_list) - { - if (hint->nrels <= i) - break; - hint->relnames[i] = lfirst(l); - i++; - } + return str; + } + + + /* + * Transform relation names from list to array to sort them with qsort + * after. + */ + hint->relnames = palloc(sizeof(char *) * hint->nrels); + foreach (l, name_list) + { + if (hint->nrels <= i) + break; + hint->relnames[i] = lfirst(l); + i++; } /* Retieve rows estimation */ @@ -2615,6 +2637,23 @@ set_config_int32_option(const char *name, int32 value, GucContext context) pg_hint_plan_parse_message_level); } +/* + * Sets GUC parameter of double type without throwing exceptions. Returns false + * if something wrong. + */ +static int +set_config_double_option(const char *name, double value, GucContext context) +{ + char *buf = float8out_internal(value); + int result; + + result = set_config_option_noerror(name, buf, context, + PGC_S_SESSION, GUC_ACTION_SAVE, true, + pg_hint_plan_parse_message_level); + pfree(buf); + return result; +} + /* setup scan method enforcement according to given options */ static void setup_guc_enforcement(SetHint **options, int noptions, GucContext context) @@ -2662,8 +2701,8 @@ setup_parallel_plan_enforcement(ParallelHint *hint, HintState *state) /* force means that enforce parallel as far as possible */ if (hint && hint->force_parallel && hint->nworkers > 0) { - set_config_int32_option("parallel_tuple_cost", 0, state->context); - set_config_int32_option("parallel_setup_cost", 0, state->context); + set_config_double_option("parallel_tuple_cost", 0.0, state->context); + set_config_double_option("parallel_setup_cost", 0.0, state->context); set_config_int32_option("min_parallel_table_scan_size", 0, state->context); set_config_int32_option("min_parallel_index_scan_size", 0, @@ -2671,9 +2710,9 @@ setup_parallel_plan_enforcement(ParallelHint *hint, HintState *state) } else { - set_config_int32_option("parallel_tuple_cost", + set_config_double_option("parallel_tuple_cost", state->init_paratup_cost, state->context); - set_config_int32_option("parallel_setup_cost", + set_config_double_option("parallel_setup_cost", state->init_parasetup_cost, state->context); set_config_int32_option("min_parallel_table_scan_size", state->init_min_para_tablescan_size, @@ -2857,9 +2896,7 @@ get_current_hint_string(ParseState *pstate, Query *query) */ query_len = strlen(query_str) + 1; normalized_query = - generate_normalized_query(&jstate, query_str, - query->stmt_location, - &query_len, + generate_normalized_query(&jstate, query_str, 0, &query_len, GetDatabaseEncoding()); /* @@ -2920,6 +2957,14 @@ get_current_hint_string(ParseState *pstate, Query *query) current_hint_str = get_hints_from_comment(query_str); MemoryContextSwitchTo(oldcontext); } + else + { + /* + * Failed to get query. We would be in fetching invalidated + * plancache. Try the next chance. + */ + current_hint_retrieved = false; + } if (debug_level > 1) { @@ -2989,7 +3034,7 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) int save_nestlevel; PlannedStmt *result; HintState *hstate; - const char *prev_hint_str; + const char *prev_hint_str = NULL; /* * Use standard planner if pg_hint_plan is disabled or current nesting @@ -3089,6 +3134,7 @@ pg_hint_plan_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) */ recurse_level++; prev_hint_str = current_hint_str; + current_hint_str = NULL; /* * Use PG_TRY mechanism to recover GUC parameters and current_hint_state to @@ -3155,9 +3201,15 @@ standard_planner_proc: } current_hint_state = NULL; if (prev_planner) - return (*prev_planner) (parse, cursorOptions, boundParams); + result = (*prev_planner) (parse, cursorOptions, boundParams); else - return standard_planner(parse, cursorOptions, boundParams); + result = standard_planner(parse, cursorOptions, boundParams); + + /* The upper-level planner still needs the current hint state */ + if (HintStateStack != NIL) + current_hint_state = (HintState *) lfirst(list_head(HintStateStack)); + + return result; } /*