• R/O
  • HTTP
  • SSH
  • HTTPS

pg_hint_plan: コミット

firtst release


コミットメタ情報

リビジョン2990c5918903889cf281b87cd4f874548c0120b7 (tree)
日時2014-09-18 11:43:47
作者Kyotaro Horiguchi <horiguchi.kyotaro@lab....>
コミッターKyotaro Horiguchi

ログメッセージ

Fix a bug that index restriction by name doesn't work for UPDATEs on
inheritance parent.

Inheritance planner doesn't claim for the inheritance parent relation,
so pg_hint_plan_get_relation_info cannot have the chance to prepare
the index spec information for chlid relations. This change make the
function to try to find parent relation even if it is called for the
children with inhparent == false from the first.

変更サマリ

差分

--- a/expected/ut-S.out
+++ b/expected/ut-S.out
@@ -4966,7 +4966,7 @@ error hint:
49664966 (30 rows)
49674967
49684968 ----
4969----- No. S-3-8 inheritance table select type
4969+---- No. S-3-8 inheritance table select/update type
49704970 ----
49714971 -- No. S-3-8-1
49724972 EXPLAIN (COSTS false) SELECT * FROM ONLY s1.p1 WHERE c1 = 1;
@@ -5020,6 +5020,99 @@ error hint:
50205020 Index Cond: (c1 = 1)
50215021 (5 rows)
50225022
5023+-- No. S-3-8-3
5024+EXPLAIN (COSTS false) UPDATE ONLY s1.p1 SET c4 = c4 WHERE c1 = 1;
5025+ QUERY PLAN
5026+--------------------------
5027+ Update on p1
5028+ -> Seq Scan on p1
5029+ Filter: (c1 = 1)
5030+(3 rows)
5031+
5032+/*+IndexScan(p1)*/
5033+EXPLAIN (COSTS false) UPDATE ONLY s1.p1 SET c4 = c4 WHERE c1 = 1;
5034+LOG: pg_hint_plan:
5035+used hint:
5036+IndexScan(p1)
5037+not used hint:
5038+duplication hint:
5039+error hint:
5040+
5041+ QUERY PLAN
5042+-----------------------------------
5043+ Update on p1
5044+ -> Index Scan using p1_i on p1
5045+ Index Cond: (c1 = 1)
5046+(3 rows)
5047+
5048+/*+IndexScan(p1 p1_pkey)*/
5049+EXPLAIN (COSTS false) UPDATE ONLY s1.p1 SET c4 = c4 WHERE c1 = 1;
5050+LOG: available indexes for IndexScan(p1): p1_pkey
5051+LOG: pg_hint_plan:
5052+used hint:
5053+IndexScan(p1 p1_pkey)
5054+not used hint:
5055+duplication hint:
5056+error hint:
5057+
5058+ QUERY PLAN
5059+--------------------------------------
5060+ Update on p1
5061+ -> Index Scan using p1_pkey on p1
5062+ Index Cond: (c1 = 1)
5063+(3 rows)
5064+
5065+-- No. S-3-8-4
5066+EXPLAIN (COSTS false) UPDATE s1.p1 SET c4 = c4 WHERE c1 = 1;
5067+ QUERY PLAN
5068+--------------------------
5069+ Update on p1
5070+ -> Seq Scan on p1
5071+ Filter: (c1 = 1)
5072+ -> Seq Scan on p1c1
5073+ Filter: (c1 = 1)
5074+(5 rows)
5075+
5076+/*+IndexScan(p1)*/
5077+EXPLAIN (COSTS false) UPDATE s1.p1 SET c4 = c4 WHERE c1 = 1;
5078+LOG: pg_hint_plan:
5079+used hint:
5080+IndexScan(p1)
5081+not used hint:
5082+duplication hint:
5083+error hint:
5084+
5085+ QUERY PLAN
5086+---------------------------------------
5087+ Update on p1
5088+ -> Index Scan using p1_i on p1
5089+ Index Cond: (c1 = 1)
5090+ -> Index Scan using p1c1_i on p1c1
5091+ Index Cond: (c1 = 1)
5092+(5 rows)
5093+
5094+/*+IndexScan(p1 p1_pkey)*/
5095+EXPLAIN (COSTS false) UPDATE s1.p1 SET c4 = c4 WHERE c1 = 1;
5096+LOG: available indexes for IndexScan(p1): p1_pkey
5097+LOG: available indexes for IndexScan(p1c1): p1c1_pkey
5098+LOG: available indexes for IndexScan(p1c2): p1c2_pkey
5099+LOG: available indexes for IndexScan(p1c3): p1c3_pkey
5100+LOG: pg_hint_plan:
5101+used hint:
5102+IndexScan(p1 p1_pkey)
5103+not used hint:
5104+duplication hint:
5105+error hint:
5106+
5107+ QUERY PLAN
5108+------------------------------------------
5109+ Update on p1
5110+ -> Index Scan using p1_pkey on p1
5111+ Index Cond: (c1 = 1)
5112+ -> Index Scan using p1c1_pkey on p1c1
5113+ Index Cond: (c1 = 1)
5114+(5 rows)
5115+
50235116 ----
50245117 ---- No. S-3-9 inheritance table number
50255118 ----
--- a/pg_hint_plan.c
+++ b/pg_hint_plan.c
@@ -2529,7 +2529,7 @@ standard_planner_proc:
25292529 * Return scan method hint which matches given aliasname.
25302530 */
25312531 static ScanMethodHint *
2532-find_scan_hint(PlannerInfo *root, RelOptInfo *rel)
2532+find_scan_hint(PlannerInfo *root, Index relid, RelOptInfo *rel)
25332533 {
25342534 RangeTblEntry *rte;
25352535 int i;
@@ -2539,10 +2539,10 @@ find_scan_hint(PlannerInfo *root, RelOptInfo *rel)
25392539 * - not a base relation
25402540 * - not an ordinary relation (such as join and subquery)
25412541 */
2542- if (rel->reloptkind != RELOPT_BASEREL || rel->rtekind != RTE_RELATION)
2542+ if (rel && (rel->reloptkind != RELOPT_BASEREL || rel->rtekind != RTE_RELATION))
25432543 return NULL;
25442544
2545- rte = root->simple_rte_array[rel->relid];
2545+ rte = root->simple_rte_array[relid];
25462546
25472547 /* We can't force scan method of foreign tables */
25482548 if (rte->relkind == RELKIND_FOREIGN_TABLE)
@@ -2932,105 +2932,134 @@ static void
29322932 pg_hint_plan_get_relation_info(PlannerInfo *root, Oid relationObjectId,
29332933 bool inhparent, RelOptInfo *rel)
29342934 {
2935- ScanMethodHint *hint;
2935+ ScanMethodHint *hint = NULL;
2936+ ListCell *l;
2937+ Index new_parent_relid = 0;
29362938
29372939 if (prev_get_relation_info)
29382940 (*prev_get_relation_info) (root, relationObjectId, inhparent, rel);
29392941
29402942 /*
2941- * Do nothing if we don't have valid hint in this context or current
2942- * nesting depth is nesting depth of SPI calls.
2943+ * Do nothing if we don't have a valid hint in this context or current
2944+ * nesting depth is at SPI calls.
29432945 */
29442946 if (!current_hint || nested_level > 0)
29452947 return;
29462948
2949+ /*
2950+ * We could register the parent relation of the following children here
2951+ * when inhparent == true but inheritnce planner doesn't request
2952+ * information for inheritance parents. We also cannot distinguish the
2953+ * caller so we should always find the parents without this function being
2954+ * called for them.
2955+ */
29472956 if (inhparent)
2957+ return;
2958+
2959+ /* Find the parent for this relation */
2960+ foreach (l, root->append_rel_list)
2961+ {
2962+ AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
2963+
2964+ if (appinfo->child_relid == rel->relid)
2965+ {
2966+ if (current_hint->parent_relid != appinfo->parent_relid)
2967+ new_parent_relid = appinfo->parent_relid;
2968+ break;
2969+ }
2970+ }
2971+
2972+ if (!l)
29482973 {
2949- /* store relid of the parent table. */
2950- current_hint->parent_relid = rel->relid;
2974+ /* This relation doesn't have a parent. Cancel current_hint. */
2975+ current_hint->parent_relid = 0;
2976+ current_hint->parent_hint = NULL;
29512977 }
2952- else if (current_hint->parent_relid != 0)
2978+
2979+ if (new_parent_relid > 0)
29532980 {
29542981 /*
2955- * We use the same GUC parameter if this table is the child table of a
2956- * table called pg_hint_plan_get_relation_info just before that.
2982+ * Here we found a parent relation different from the remembered one.
2983+ * Remember it, apply the scan mask of it and then resolve the index
2984+ * restriction in order to be used by its children.
29572985 */
2958- ListCell *l;
2986+ int scanmask = current_hint->init_scan_mask;
2987+ ScanMethodHint *parent_hint;
29592988
2960- /* append_rel_list contains all append rels; ignore others */
2961- foreach(l, root->append_rel_list)
2989+ current_hint->parent_relid = new_parent_relid;
2990+
2991+ /*
2992+ * Get and apply the hint for the new parent relation. It should be an
2993+ * ordinary relation so calling find_scan_hint with rel == NULL is
2994+ * safe.
2995+ */
2996+ current_hint->parent_hint = parent_hint =
2997+ find_scan_hint(root, current_hint->parent_relid, NULL);
2998+
2999+ if (parent_hint)
29623000 {
2963- AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
3001+ scanmask = current_hint->parent_hint->enforce_mask;
3002+ parent_hint->base.state = HINT_STATE_USED;
29643003
2965- /* This rel is child table. */
2966- if (appinfo->parent_relid == current_hint->parent_relid &&
2967- appinfo->child_relid == rel->relid)
3004+ /* Resolve index name mask (if any) using the parent. */
3005+ if (parent_hint->indexnames)
29683006 {
2969- if (current_hint->parent_hint)
2970- delete_indexes(current_hint->parent_hint, rel,
2971- relationObjectId);
3007+ Oid parentrel_oid;
3008+ Relation parent_rel;
29723009
2973- return;
3010+ parentrel_oid =
3011+ root->simple_rte_array[current_hint->parent_relid]->relid;
3012+ parent_rel = heap_open(parentrel_oid, NoLock);
3013+
3014+ /* Search the parent relation for indexes match the hint spec */
3015+ foreach(l, RelationGetIndexList(parent_rel))
3016+ {
3017+ Oid indexoid = lfirst_oid(l);
3018+ char *indexname = get_rel_name(indexoid);
3019+ ListCell *lc;
3020+ ParentIndexInfo *parent_index_info;
3021+
3022+ foreach(lc, parent_hint->indexnames)
3023+ {
3024+ if (RelnameCmp(&indexname, &lfirst(lc)) == 0)
3025+ break;
3026+ }
3027+ if (!lc)
3028+ continue;
3029+
3030+ parent_index_info =
3031+ get_parent_index_info(indexoid, parentrel_oid);
3032+ current_hint->parent_index_infos =
3033+ lappend(current_hint->parent_index_infos, parent_index_info);
3034+ }
3035+ heap_close(parent_rel, NoLock);
29743036 }
29753037 }
2976-
2977- /* This rel is not inherit table. */
2978- current_hint->parent_relid = 0;
2979- current_hint->parent_hint = NULL;
3038+
3039+ set_scan_config_options(scanmask, current_hint->context);
29803040 }
29813041
2982- /*
2983- * If scan method hint was given, reset GUC parameters which control
2984- * planner behavior about choosing scan methods.
2985- */
2986- if ((hint = find_scan_hint(root, rel)) == NULL)
3042+ if (current_hint->parent_hint != 0)
29873043 {
2988- set_scan_config_options(current_hint->init_scan_mask,
2989- current_hint->context);
3044+ delete_indexes(current_hint->parent_hint, rel,
3045+ relationObjectId);
3046+
3047+ /* Scan fixation status is the same to the parent. */
29903048 return;
29913049 }
2992- set_scan_config_options(hint->enforce_mask, current_hint->context);
2993- hint->base.state = HINT_STATE_USED;
29943050
2995- if (inhparent)
3051+ /* This table doesn't have a parent hint. Apply its own hint if any. */
3052+ if ((hint = find_scan_hint(root, rel->relid, rel)) != NULL)
29963053 {
2997- Relation relation;
2998- List *indexoidlist;
2999- ListCell *l;
3000-
3001- current_hint->parent_hint = hint;
3002-
3003- relation = heap_open(relationObjectId, NoLock);
3004- indexoidlist = RelationGetIndexList(relation);
3005-
3006- foreach(l, indexoidlist)
3007- {
3008- Oid indexoid = lfirst_oid(l);
3009- char *indexname = get_rel_name(indexoid);
3010- bool use_index = false;
3011- ListCell *lc;
3012- ParentIndexInfo *parent_index_info;
3013-
3014- foreach(lc, hint->indexnames)
3015- {
3016- if (RelnameCmp(&indexname, &lfirst(lc)) == 0)
3017- {
3018- use_index = true;
3019- break;
3020- }
3021- }
3022- if (!use_index)
3023- continue;
3054+ set_scan_config_options(hint->enforce_mask, current_hint->context);
3055+ hint->base.state = HINT_STATE_USED;
30243056
3025- parent_index_info = get_parent_index_info(indexoid,
3026- relationObjectId);
3027- current_hint->parent_index_infos =
3028- lappend(current_hint->parent_index_infos, parent_index_info);
3029- }
3030- heap_close(relation, NoLock);
3057+ delete_indexes(hint, rel, InvalidOid);
30313058 }
30323059 else
3033- delete_indexes(hint, rel, InvalidOid);
3060+ set_scan_config_options(current_hint->init_scan_mask,
3061+ current_hint->context);
3062+ return;
30343063 }
30353064
30363065 /*
@@ -3525,7 +3554,7 @@ rebuild_scan_path(HintState *hstate, PlannerInfo *root, int level,
35253554 * planner if scan method hint is not specified, otherwise use
35263555 * specified hints and mark the hint as used.
35273556 */
3528- if ((hint = find_scan_hint(root, rel)) == NULL)
3557+ if ((hint = find_scan_hint(root, rel->relid, rel)) == NULL)
35293558 set_scan_config_options(hstate->init_scan_mask,
35303559 hstate->context);
35313560 else
@@ -3611,7 +3640,7 @@ add_paths_to_joinrel_wrapper(PlannerInfo *root,
36113640 JoinMethodHint *join_hint;
36123641 int save_nestlevel;
36133642
3614- if ((scan_hint = find_scan_hint(root, innerrel)) != NULL)
3643+ if ((scan_hint = find_scan_hint(root, innerrel->relid, innerrel)) != NULL)
36153644 {
36163645 set_scan_config_options(scan_hint->enforce_mask, current_hint->context);
36173646 scan_hint->base.state = HINT_STATE_USED;
--- a/sql/ut-S.sql
+++ b/sql/ut-S.sql
@@ -907,7 +907,7 @@ SELECT max(b2t1.c1) FROM s1.t1 b2t1 WHERE b2t1.c1 = 1
907907 SELECT max(b4t1.c1) FROM s1.t1 b4t1 WHERE b4t1.c1 = 1);
908908
909909 ----
910----- No. S-3-8 inheritance table select type
910+---- No. S-3-8 inheritance table select/update type
911911 ----
912912
913913 -- No. S-3-8-1
@@ -920,6 +920,20 @@ EXPLAIN (COSTS false) SELECT * FROM s1.p1 WHERE c1 = 1;
920920 /*+IndexScan(p1)*/
921921 EXPLAIN (COSTS false) SELECT * FROM s1.p1 WHERE c1 = 1;
922922
923+-- No. S-3-8-3
924+EXPLAIN (COSTS false) UPDATE ONLY s1.p1 SET c4 = c4 WHERE c1 = 1;
925+/*+IndexScan(p1)*/
926+EXPLAIN (COSTS false) UPDATE ONLY s1.p1 SET c4 = c4 WHERE c1 = 1;
927+/*+IndexScan(p1 p1_pkey)*/
928+EXPLAIN (COSTS false) UPDATE ONLY s1.p1 SET c4 = c4 WHERE c1 = 1;
929+
930+-- No. S-3-8-4
931+EXPLAIN (COSTS false) UPDATE s1.p1 SET c4 = c4 WHERE c1 = 1;
932+/*+IndexScan(p1)*/
933+EXPLAIN (COSTS false) UPDATE s1.p1 SET c4 = c4 WHERE c1 = 1;
934+/*+IndexScan(p1 p1_pkey)*/
935+EXPLAIN (COSTS false) UPDATE s1.p1 SET c4 = c4 WHERE c1 = 1;
936+
923937 ----
924938 ---- No. S-3-9 inheritance table number
925939 ----
旧リポジトリブラウザで表示