diff --git a/expected/pg_hint_plan.out b/expected/pg_hint_plan.out index b282bb97..6d9eae85 100644 --- a/expected/pg_hint_plan.out +++ b/expected/pg_hint_plan.out @@ -4418,6 +4418,32 @@ error hint: Index Cond: (id < 10) (7 rows) +-- IndexScan is safe for unordered indexes +CREATE TABLE ischk (a text, b tsvector) PARTITION BY LIST(a); +CREATE TABLE ischk_d1 PARTITION OF ischk FOR VALUES IN (0); +CREATE TABLE ischk_d2 PARTITION OF ischk FOR VALUES IN (1); +CREATE INDEX ischk_idx ON ischk USING gin (b); +/*+ IndexScan(ischk ischk_idx) */ +EXPLAIN (COSTS false) SELECT * FROM ischk WHERE b = 'x'; +LOG: available indexes for IndexScan(ischk_d1): ischk_d1_b_idx +LOG: available indexes for IndexScan(ischk_d2): ischk_d2_b_idx +LOG: pg_hint_plan: +used hint: +IndexScan(ischk ischk_idx) +not used hint: +duplication hint: +error hint: + + QUERY PLAN +----------------------------------------- + Append + -> Seq Scan on ischk_d1 ischk_1 + Filter: (b = '''x'''::tsvector) + -> Seq Scan on ischk_d2 ischk_2 + Filter: (b = '''x'''::tsvector) +(5 rows) + +DROP TABLE ischk; -- quote test /*+SeqScan("""t1 ) ")IndexScan("t 2 """)HashJoin("""t1 ) "T3"t 2 """)Leading("""t1 ) "T3"t 2 """)Set(application_name"a a a"" a A")*/ EXPLAIN (COSTS false) SELECT * FROM t1 """t1 ) ", t2 "t 2 """, t3 "T3" WHERE """t1 ) ".id = "t 2 """.id AND """t1 ) ".id = "T3".id; diff --git a/pg_hint_plan.c b/pg_hint_plan.c index 4ec55fd4..9e71cbdb 100644 --- a/pg_hint_plan.c +++ b/pg_hint_plan.c @@ -3583,11 +3583,24 @@ restrict_indexes(PlannerInfo *root, ScanMethodHint *hint, RelOptInfo *rel, /* deny if any of column attributes don't match */ if (strcmp(p_attname, c_attname) != 0 || p_info->indcollation[i] != info->indexcollations[i] || - p_info->opclass[i] != info->opcintype[i]|| - ((p_info->indoption[i] & INDOPTION_DESC) != 0) - != info->reverse_sort[i] || - ((p_info->indoption[i] & INDOPTION_NULLS_FIRST) != 0) - != info->nulls_first[i]) + p_info->opclass[i] != info->opcintype[i]) + break; + + /* + * Compare index ordering if this index is ordered. + * + * We already confirmed that this and the parent indexes + * share the same column set (actually only the length of + * the column set is compard, though.) and index access + * method. So if this index is unordered, the parent can be + * assumed to be be unodered. Thus no need to bother + * checking the parent's orderedness. + */ + if (info->sortopfamily != NULL && + (((p_info->indoption[i] & INDOPTION_DESC) != 0) + != info->reverse_sort[i] || + ((p_info->indoption[i] & INDOPTION_NULLS_FIRST) != 0) + != info->nulls_first[i])) break; } diff --git a/sql/pg_hint_plan.sql b/sql/pg_hint_plan.sql index 532dd933..619b23d2 100644 --- a/sql/pg_hint_plan.sql +++ b/sql/pg_hint_plan.sql @@ -460,6 +460,15 @@ EXPLAIN (COSTS false) SELECT * FROM ONLY p1, t1 WHERE p1.id >= 50 AND p1.id <= 5 /*+TidScan(p1)*/ EXPLAIN (COSTS false) SELECT * FROM ONLY p1, t1 WHERE p1.id >= 50 AND p1.id <= 51 AND p1.ctid = '(1,1)' AND p1.id = t1.id AND t1.id < 10; +-- IndexScan is safe for unordered indexes +CREATE TABLE ischk (a text, b tsvector) PARTITION BY LIST(a); +CREATE TABLE ischk_d1 PARTITION OF ischk FOR VALUES IN (0); +CREATE TABLE ischk_d2 PARTITION OF ischk FOR VALUES IN (1); +CREATE INDEX ischk_idx ON ischk USING gin (b); +/*+ IndexScan(ischk ischk_idx) */ +EXPLAIN (COSTS false) SELECT * FROM ischk WHERE b = 'x'; +DROP TABLE ischk; + -- quote test /*+SeqScan("""t1 ) ")IndexScan("t 2 """)HashJoin("""t1 ) "T3"t 2 """)Leading("""t1 ) "T3"t 2 """)Set(application_name"a a a"" a A")*/ EXPLAIN (COSTS false) SELECT * FROM t1 """t1 ) ", t2 "t 2 """, t3 "T3" WHERE """t1 ) ".id = "t 2 """.id AND """t1 ) ".id = "T3".id;