From 05300ab86f4c4bf65ce9f59de52c1093d470b694 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Tue, 11 Jul 2023 10:29:07 +0900 Subject: [PATCH] Fix handling of unavailable indexes in Scan hints As showed by the regression tests, this fixes a lot of correctness issues behind the hints considered as "used" by the module but not actually used because the index restrictions were applied before enforcing a scan method. For example, an index IndexScan with a list of indexes not used caused two problems: - The hint would be marked as used, but it resulted in being not used, falling down to a sequential scan. - Discarding all the indexes in the hint could cause invisible regressions, as the hint would fail to consider any existing hints. There was also an extra case with IndexScanRegexp where having a list of indexes available turns out to cause a sequential scan and still mark the hint as used. This commit now prevents restrict_indexes from removing any indexes from the relation index list if none of the hinted indexes are available, and switches the scan enforcement method to be after the index restrictions are applied. This safeguard prevents an IndexScan hint supplied without any available indexes to result in a sequential scan, for example. Per discussion on #136. Author: Sami Imseih Backpatch-through: 13 --- expected/pg_hint_plan.out | 126 +++++++++++++++++++------------------- expected/ut-S.out | 62 +++++++++---------- pg_hint_plan.c | 77 +++++++++++++++++++---- 3 files changed, 158 insertions(+), 107 deletions(-) diff --git a/expected/pg_hint_plan.out b/expected/pg_hint_plan.out index 58c6dada..b282bb97 100644 --- a/expected/pg_hint_plan.out +++ b/expected/pg_hint_plan.out @@ -5479,15 +5479,15 @@ EXPLAIN (COSTS false) SELECT * FROM t5 WHERE t5.id = 1; LOG: available indexes for IndexScan(t5): LOG: pg_hint_plan: used hint: -IndexScan(t5 no_exist) not used hint: +IndexScan(t5 no_exist) duplication hint: error hint: - QUERY PLAN --------------------- - Seq Scan on t5 - Filter: (id = 1) + QUERY PLAN +---------------------------------------------------------------------------------------- + Index Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 + Index Cond: (id = 1) (2 rows) /*+IndexScan(t5 t5_id1 t5_id2)*/ @@ -5527,15 +5527,15 @@ EXPLAIN (COSTS false) SELECT * FROM t5 WHERE t5.id = 1; LOG: available indexes for IndexScan(t5): LOG: pg_hint_plan: used hint: -IndexScan(t5 no_exist5 no_exist2) not used hint: +IndexScan(t5 no_exist5 no_exist2) duplication hint: error hint: - QUERY PLAN --------------------- - Seq Scan on t5 - Filter: (id = 1) + QUERY PLAN +---------------------------------------------------------------------------------------- + Index Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 + Index Cond: (id = 1) (2 rows) -- outer inner @@ -6654,8 +6654,8 @@ LOG: available indexes for IndexScan(p2_c3_c1): LOG: available indexes for IndexScan(p2_c3_c2): LOG: pg_hint_plan: used hint: -IndexScan(p2 p2_val) not used hint: +IndexScan(p2 p2_val) duplication hint: error hint: @@ -6832,8 +6832,8 @@ LOG: available indexes for IndexScan(p2_c1_c1): LOG: available indexes for IndexScan(p2_c1_c2): LOG: pg_hint_plan: used hint: -IndexScan(p2 no_exist) not used hint: +IndexScan(p2 no_exist) duplication hint: error hint: @@ -7195,15 +7195,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for IndexScanRegexp(t5): LOG: pg_hint_plan: used hint: -IndexScanRegexp(t5 t5[^_].*) not used hint: +IndexScanRegexp(t5 t5[^_].*) duplication hint: error hint: - QUERY PLAN --------------------- - Seq Scan on t5 - Filter: (id = 1) + QUERY PLAN +--------------------------------------------------------------------------------------------- + Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 + Index Cond: (id = 1) (2 rows) /*+ IndexScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab)*/ @@ -7211,15 +7211,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for IndexScanRegexp(t5): LOG: pg_hint_plan: used hint: -IndexScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab) not used hint: +IndexScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab) duplication hint: error hint: - QUERY PLAN --------------------- - Seq Scan on t5 - Filter: (id = 1) + QUERY PLAN +--------------------------------------------------------------------------------------------- + Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 + Index Cond: (id = 1) (2 rows) /*+ IndexScan(t5 t5_id[0-9].*)*/ @@ -7227,15 +7227,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for IndexScan(t5): LOG: pg_hint_plan: used hint: -IndexScan(t5 t5_id[0-9].*) not used hint: +IndexScan(t5 t5_id[0-9].*) duplication hint: error hint: - QUERY PLAN --------------------- - Seq Scan on t5 - Filter: (id = 1) + QUERY PLAN +--------------------------------------------------------------------------------------------- + Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 + Index Cond: (id = 1) (2 rows) /*+ IndexOnlyScanRegexp(t5 t5_[^i].*)*/ @@ -7275,15 +7275,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for IndexOnlyScanRegexp(t5): LOG: pg_hint_plan: used hint: -IndexOnlyScanRegexp(t5 t5[^_].*) not used hint: +IndexOnlyScanRegexp(t5 t5[^_].*) duplication hint: error hint: - QUERY PLAN --------------------- - Seq Scan on t5 - Filter: (id = 1) + QUERY PLAN +--------------------------------------------------------------------------------------------- + Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 + Index Cond: (id = 1) (2 rows) /*+ IndexOnlyScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab)*/ @@ -7291,15 +7291,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for IndexOnlyScanRegexp(t5): LOG: pg_hint_plan: used hint: -IndexOnlyScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab) not used hint: +IndexOnlyScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab) duplication hint: error hint: - QUERY PLAN --------------------- - Seq Scan on t5 - Filter: (id = 1) + QUERY PLAN +--------------------------------------------------------------------------------------------- + Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 + Index Cond: (id = 1) (2 rows) /*+ IndexOnlyScan(t5 t5_id[0-9].*)*/ @@ -7307,15 +7307,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for IndexOnlyScan(t5): LOG: pg_hint_plan: used hint: -IndexOnlyScan(t5 t5_id[0-9].*) not used hint: +IndexOnlyScan(t5 t5_id[0-9].*) duplication hint: error hint: - QUERY PLAN --------------------- - Seq Scan on t5 - Filter: (id = 1) + QUERY PLAN +--------------------------------------------------------------------------------------------- + Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 + Index Cond: (id = 1) (2 rows) /*+ BitmapScanRegexp(t5 t5_[^i].*)*/ @@ -7359,15 +7359,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for BitmapScanRegexp(t5): LOG: pg_hint_plan: used hint: -BitmapScanRegexp(t5 t5[^_].*) not used hint: +BitmapScanRegexp(t5 t5[^_].*) duplication hint: error hint: - QUERY PLAN --------------------- - Seq Scan on t5 - Filter: (id = 1) + QUERY PLAN +--------------------------------------------------------------------------------------------- + Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 + Index Cond: (id = 1) (2 rows) /*+ BitmapScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab)*/ @@ -7375,15 +7375,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for BitmapScanRegexp(t5): LOG: pg_hint_plan: used hint: -BitmapScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab) not used hint: +BitmapScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab) duplication hint: error hint: - QUERY PLAN --------------------- - Seq Scan on t5 - Filter: (id = 1) + QUERY PLAN +--------------------------------------------------------------------------------------------- + Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 + Index Cond: (id = 1) (2 rows) /*+ BitmapScan(t5 t5_id[0-9].*)*/ @@ -7391,15 +7391,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for BitmapScan(t5): LOG: pg_hint_plan: used hint: -BitmapScan(t5 t5_id[0-9].*) not used hint: +BitmapScan(t5 t5_id[0-9].*) duplication hint: error hint: - QUERY PLAN --------------------- - Seq Scan on t5 - Filter: (id = 1) + QUERY PLAN +--------------------------------------------------------------------------------------------- + Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 + Index Cond: (id = 1) (2 rows) -- Inheritance @@ -7522,8 +7522,8 @@ LOG: available indexes for IndexScanRegexp(p1_c3_c1): LOG: available indexes for IndexScanRegexp(p1_c3_c2): LOG: pg_hint_plan: used hint: -IndexScanRegexp(p1 p1[^_].*) not used hint: +IndexScanRegexp(p1 p1[^_].*) duplication hint: error hint: @@ -7563,8 +7563,8 @@ LOG: available indexes for IndexScan(p1_c3_c1): LOG: available indexes for IndexScan(p1_c3_c2): LOG: pg_hint_plan: used hint: -IndexScan(p1 p1_.*val2.*) not used hint: +IndexScan(p1 p1_.*val2.*) duplication hint: error hint: @@ -7686,8 +7686,8 @@ LOG: available indexes for IndexOnlyScanRegexp(p1_c3_c1): LOG: available indexes for IndexOnlyScanRegexp(p1_c3_c2): LOG: pg_hint_plan: used hint: -IndexOnlyScanRegexp(p1 p1[^_].*) not used hint: +IndexOnlyScanRegexp(p1 p1[^_].*) duplication hint: error hint: @@ -7727,8 +7727,8 @@ LOG: available indexes for IndexOnlyScan(p1_c3_c1): LOG: available indexes for IndexOnlyScan(p1_c3_c2): LOG: pg_hint_plan: used hint: -IndexOnlyScan(p1 p1_.*val2.*) not used hint: +IndexOnlyScan(p1 p1_.*val2.*) duplication hint: error hint: @@ -7868,8 +7868,8 @@ LOG: available indexes for BitmapScanRegexp(p1_c3_c1): LOG: available indexes for BitmapScanRegexp(p1_c3_c2): LOG: pg_hint_plan: used hint: -BitmapScanRegexp(p1 p1[^_].*) not used hint: +BitmapScanRegexp(p1 p1[^_].*) duplication hint: error hint: @@ -7909,8 +7909,8 @@ LOG: available indexes for BitmapScan(p1_c3_c1): LOG: available indexes for BitmapScan(p1_c3_c2): LOG: pg_hint_plan: used hint: -BitmapScan(p1 p1_.*val2.*) not used hint: +BitmapScan(p1 p1_.*val2.*) duplication hint: error hint: diff --git a/expected/ut-S.out b/expected/ut-S.out index 0f36d22a..8c5fd359 100644 --- a/expected/ut-S.out +++ b/expected/ut-S.out @@ -4534,8 +4534,8 @@ error hint: LOG: available indexes for IndexScan(ti1): LOG: pg_hint_plan: used hint: -IndexScan(ti1 not_exist) not used hint: +IndexScan(ti1 not_exist) duplication hint: error hint: @@ -4543,8 +4543,8 @@ error hint: \! sql/maskout.sh results/ut-S.tmpout QUERY PLAN ---------------- - Seq Scan on ti1 (cost={inf}..{inf} rows=1 width=xxx) - Filter: (c1 = 100) + Index Scan using ti1_hash on ti1 (cost=xxx..xxx rows=1 width=xxx) + Index Cond: (c1 = 100) -- No. S-3-5-5 \o results/ut-S.tmpout @@ -4552,8 +4552,8 @@ error hint: LOG: available indexes for BitmapScan(ti1): LOG: pg_hint_plan: used hint: -BitmapScan(ti1 not_exist) not used hint: +BitmapScan(ti1 not_exist) duplication hint: error hint: @@ -4561,8 +4561,8 @@ error hint: \! sql/maskout.sh results/ut-S.tmpout QUERY PLAN ---------------- - Seq Scan on ti1 (cost={inf}..{inf} rows=1 width=xxx) - Filter: (c1 = 100) + Index Scan using ti1_hash on ti1 (cost=xxx..xxx rows=1 width=xxx) + Index Cond: (c1 = 100) -- No. S-3-5-6 \o results/ut-S.tmpout @@ -4570,8 +4570,8 @@ error hint: LOG: available indexes for IndexOnlyScan(ti1): LOG: pg_hint_plan: used hint: -IndexOnlyScan(ti1 not_exist) not used hint: +IndexOnlyScan(ti1 not_exist) duplication hint: error hint: @@ -4579,8 +4579,8 @@ error hint: \! sql/maskout.sh results/ut-S.tmpout QUERY PLAN ---------------- - Seq Scan on ti1 (cost={inf}..{inf} rows=1 width=xxx) - Filter: (c1 = 100) + Index Scan using ti1_hash on ti1 (cost=xxx..xxx rows=1 width=xxx) + Index Cond: (c1 = 100) -- No. S-3-5-7 EXPLAIN (COSTS false) SELECT * FROM s1.t1 WHERE t1.c1 = 1; @@ -5282,11 +5282,11 @@ error hint: Append (cost=xxx..xxx rows=4 width=xxx) -> Index Scan using p1_i2 on p1 p1_1 (cost=xxx..xxx rows=1 width=xxx) Index Cond: (c2 = 1) - -> Seq Scan on p1c1 p1_2 (cost={inf}..{inf} rows=1 width=xxx) + -> Seq Scan on p1c1 p1_2 (cost=xxx..xxx rows=1 width=xxx) Filter: (c2 = 1) - -> Seq Scan on p1c2 p1_3 (cost={inf}..{inf} rows=1 width=xxx) + -> Seq Scan on p1c2 p1_3 (cost=xxx..xxx rows=1 width=xxx) Filter: (c2 = 1) - -> Seq Scan on p1c3 p1_4 (cost={inf}..{inf} rows=1 width=xxx) + -> Seq Scan on p1c3 p1_4 (cost=xxx..xxx rows=1 width=xxx) Filter: (c2 = 1) -- No. S-3-10-5 @@ -5306,12 +5306,12 @@ error hint: \! sql/maskout.sh results/ut-S.tmpout QUERY PLAN ---------------- - Append (cost={inf}..{inf} rows=3 width=xxx) - -> Seq Scan on p2 p2_1 (cost={inf}..{inf} rows=1 width=xxx) + Append (cost=xxx..xxx rows=3 width=xxx) + -> Seq Scan on p2 p2_1 (cost=xxx..xxx rows=1 width=xxx) Filter: (c1 = 1) -> Index Scan using p2c1_pkey on p2c1 p2_2 (cost=xxx..xxx rows=1 width=xxx) Index Cond: (c1 = 1) - -> Seq Scan on p2c1c1 p2_3 (cost={inf}..{inf} rows=1 width=xxx) + -> Seq Scan on p2c1c1 p2_3 (cost=xxx..xxx rows=1 width=xxx) Filter: (c1 = 1) ---- @@ -6009,15 +6009,15 @@ EXPLAIN (COSTS false) SELECT * FROM s1.ti1 WHERE c2 = 1; LOG: available indexes for IndexScanRegexp(ti1): LOG: pg_hint_plan: used hint: -IndexScanRegexp(ti1 no.*_exist) not used hint: +IndexScanRegexp(ti1 no.*_exist) duplication hint: error hint: - QUERY PLAN --------------------- - Seq Scan on ti1 - Filter: (c2 = 1) + QUERY PLAN +-------------------------------- + Index Scan using ti1_i4 on ti1 + Index Cond: (c2 = 1) (2 rows) -- No. S-3-14-4 @@ -6069,8 +6069,8 @@ LOG: available indexes for IndexScanRegexp(p1): LOG: available indexes for IndexScanRegexp(p1c1): LOG: pg_hint_plan: used hint: -IndexScanRegexp(p1 no.*_exist) not used hint: +IndexScanRegexp(p1 no.*_exist) duplication hint: error hint: @@ -6109,15 +6109,15 @@ EXPLAIN (COSTS false) SELECT * FROM s1.ti1 WHERE c2 = 1; LOG: available indexes for IndexScan(ti1): LOG: pg_hint_plan: used hint: -IndexScan(ti1 not_exist) not used hint: +IndexScan(ti1 not_exist) duplication hint: error hint: - QUERY PLAN --------------------- - Seq Scan on ti1 - Filter: (c2 = 1) + QUERY PLAN +-------------------------------- + Index Scan using ti1_i4 on ti1 + Index Cond: (c2 = 1) (2 rows) -- No. S-3-15-3 @@ -6160,15 +6160,15 @@ EXPLAIN (COSTS false) SELECT * FROM s1.ti1 WHERE c2 = 1; LOG: available indexes for IndexScan(ti1): LOG: pg_hint_plan: used hint: -IndexScan(ti1 not_exist1 not_exist2) not used hint: +IndexScan(ti1 not_exist1 not_exist2) duplication hint: error hint: - QUERY PLAN --------------------- - Seq Scan on ti1 - Filter: (c2 = 1) + QUERY PLAN +-------------------------------- + Index Scan using ti1_i4 on ti1 + Index Cond: (c2 = 1) (2 rows) DELETE FROM pg_db_role_setting WHERE setrole = (SELECT oid FROM pg_roles WHERE rolname = current_user); diff --git a/pg_hint_plan.c b/pg_hint_plan.c index a31bb480..d9ae882c 100644 --- a/pg_hint_plan.c +++ b/pg_hint_plan.c @@ -3433,15 +3433,25 @@ regexpeq(const char *s1, const char *s2) } -/* Remove indexes instructed not to use by hint. */ -static void +/* + * Filter out indexes instructed in the hint as not to be used. + * + * This routine is used in relationship with the scan method enforcement, and + * it returns true to allow the follow-up scan method to be enforced, and false + * to prevent the scan enforcement. Currently, this code will not enforce + * the scan enforcement if *all* the indexes available to a relation have been + * discarded. + */ +static bool restrict_indexes(PlannerInfo *root, ScanMethodHint *hint, RelOptInfo *rel, - bool using_parent_hint) + bool using_parent_hint) { ListCell *cell; StringInfoData buf; RangeTblEntry *rte = root->simple_rte_array[rel->relid]; Oid relationObjectId = rte->relid; + List *unused_indexes = NIL; + bool restrict_result; /* * We delete all the IndexOptInfo list and prevent you from being usable by @@ -3454,18 +3464,20 @@ restrict_indexes(PlannerInfo *root, ScanMethodHint *hint, RelOptInfo *rel, rel->indexlist = NIL; hint->base.state = HINT_STATE_USED; - return; + return true; } /* * When a list of indexes is not specified, we just use all indexes. */ if (hint->indexnames == NIL) - return; + return true; /* * Leaving only an specified index, we delete it from a IndexOptInfo list - * other than it. + * other than it. However, if none of the specified indexes are available, + * then we keep all the indexes and skip enforcing the scan method. i.e., + * we skip the scan hint altogether for the relation. */ if (debug_level > 0) initStringInfo(&buf); @@ -3646,11 +3658,42 @@ restrict_indexes(PlannerInfo *root, ScanMethodHint *hint, RelOptInfo *rel, } if (!use_index) - rel->indexlist = foreach_delete_current(rel->indexlist, cell); + unused_indexes = lappend_oid(unused_indexes, info->indexoid); pfree(indexname); } + /* + * Update the list of indexes available to the IndexOptInfo based on what + * has been discarded previously. + * + * If the hint has no matching indexes, skip applying the hinted scan + * method. For example if an IndexScan hint does not have any matching + * indexes, we should not enforce an enable_indexscan. + */ + if (list_length(unused_indexes) < list_length(rel->indexlist)) + { + foreach (cell, unused_indexes) + { + Oid final_oid = lfirst_oid(cell); + ListCell *l; + + foreach (l, rel->indexlist) + { + IndexOptInfo *info = (IndexOptInfo *) lfirst(l); + + if (info->indexoid == final_oid) + rel->indexlist = foreach_delete_current(rel->indexlist, l); + } + } + + restrict_result = true; + } + else + restrict_result = false; + + list_free(unused_indexes); + if (debug_level > 0) { StringInfoData rel_buf; @@ -3677,6 +3720,8 @@ restrict_indexes(PlannerInfo *root, ScanMethodHint *hint, RelOptInfo *rel, pfree(buf.data); pfree(rel_buf.data); } + + return restrict_result; } /* @@ -3897,8 +3942,6 @@ setup_hint_enforcement(PlannerInfo *root, RelOptInfo *rel, { ScanMethodHint * pshint = current_hint_state->parent_scan_hint; - pshint->base.state = HINT_STATE_USED; - /* Apply index mask in the same manner to the parent. */ if (pshint->indexnames) { @@ -3944,14 +3987,22 @@ setup_hint_enforcement(PlannerInfo *root, RelOptInfo *rel, { bool using_parent_hint = (shint == current_hint_state->parent_scan_hint); + bool restrict_result; ret |= HINT_BM_SCAN_METHOD; - /* Setup scan enforcement environment */ - setup_scan_method_enforcement(shint, current_hint_state); + /* restrict unwanted indexes */ + restrict_result = restrict_indexes(root, shint, rel, using_parent_hint); - /* restrict unwanted inexes */ - restrict_indexes(root, shint, rel, using_parent_hint); + /* + * Setup scan enforcement environment + * + * This has to be called after restrict_indexes(), that may decide to + * skip the scan method enforcement depending on the index restrictions + * applied. + */ + if (restrict_result) + setup_scan_method_enforcement(shint, current_hint_state); if (debug_level > 1) {