From 240dde791039ef5bac163e453da4daa1c382dd94 Mon Sep 17 00:00:00 2001 From: "Anton A. Melnikov" Date: Sun, 31 Dec 2023 14:10:23 +0300 Subject: [PATCH 1/5] Introduce IndexAmRoutine.ammorderbyopfirstcol Currently IndexAmRoutine.amcanorderbyop property means that index access method supports "column op const" ordering for every indexed column. Upcoming knn-btree supports it only for the first column. In future we will probably need to a callback to check whether particular ordering is supported. But now there are no potential use-cases around. So, don't overengineer it and leave with just boolean property. Discussion: https://postgr.es/m/ce35e97b-cf34-3f5d-6b99-2c25bae49999%40postgrespro.ru Author: Nikita Glukhov Reviewed-by: Robert Haas, Tom Lane, Anastasia Lubennikova, Alexander Korotkov --- contrib/bloom/blutils.c | 1 + doc/src/sgml/indexam.sgml | 9 ++++++++- src/backend/access/brin/brin.c | 1 + src/backend/access/gin/ginutil.c | 1 + src/backend/access/gist/gist.c | 1 + src/backend/access/hash/hash.c | 1 + src/backend/access/nbtree/nbtree.c | 1 + src/backend/access/spgist/spgutils.c | 1 + src/backend/optimizer/path/indxpath.c | 22 +++++++++++++++------- src/include/access/amapi.h | 6 ++++++ src/include/nodes/pathnodes.h | 2 ++ 11 files changed, 38 insertions(+), 8 deletions(-) diff --git a/contrib/bloom/blutils.c b/contrib/bloom/blutils.c index 6836129c90d..916734f675c 100644 --- a/contrib/bloom/blutils.c +++ b/contrib/bloom/blutils.c @@ -112,6 +112,7 @@ blhandler(PG_FUNCTION_ARGS) amroutine->amoptsprocnum = BLOOM_OPTIONS_PROC; amroutine->amcanorder = false; amroutine->amcanorderbyop = false; + amroutine->amorderbyopfirstcol = false; amroutine->amcanbackward = false; amroutine->amcanunique = false; amroutine->amcanmulticol = true; diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index e3c1539a1e3..a69135cb780 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -103,6 +103,11 @@ typedef struct IndexAmRoutine bool amcanorder; /* does AM support ORDER BY result of an operator on indexed column? */ bool amcanorderbyop; + /* + * Does AM support only the one ORDER BY operator on first indexed column? + * amcanorderbyop is implied. + */ + bool amorderbyopfirstcol; /* does AM support backward scanning? */ bool amcanbackward; /* does AM support UNIQUE indexes? */ @@ -932,7 +937,9 @@ amparallelrescan (IndexScanDesc scan); an order satisfying ORDER BY index_key operator constant. Scan modifiers of that form can be passed to amrescan as described - previously. + previously. If the access method supports the only one ORDER BY operator + on the first indexed column, then it should set + amorderbyopfirstcol to true. diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c index 6467bed604a..c371f726979 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -253,6 +253,7 @@ brinhandler(PG_FUNCTION_ARGS) amroutine->amoptsprocnum = BRIN_PROCNUM_OPTIONS; amroutine->amcanorder = false; amroutine->amcanorderbyop = false; + amroutine->amorderbyopfirstcol = false; amroutine->amcanbackward = false; amroutine->amcanunique = false; amroutine->amcanmulticol = true; diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c index 5747ae6a4ca..e9536fd9238 100644 --- a/src/backend/access/gin/ginutil.c +++ b/src/backend/access/gin/ginutil.c @@ -43,6 +43,7 @@ ginhandler(PG_FUNCTION_ARGS) amroutine->amoptsprocnum = GIN_OPTIONS_PROC; amroutine->amcanorder = false; amroutine->amcanorderbyop = false; + amroutine->amorderbyopfirstcol = false; amroutine->amcanbackward = false; amroutine->amcanunique = false; amroutine->amcanmulticol = true; diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index ed4ffa63a77..f6ed5023ef0 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -65,6 +65,7 @@ gisthandler(PG_FUNCTION_ARGS) amroutine->amoptsprocnum = GIST_OPTIONS_PROC; amroutine->amcanorder = false; amroutine->amcanorderbyop = true; + amroutine->amorderbyopfirstcol = false; amroutine->amcanbackward = false; amroutine->amcanunique = false; amroutine->amcanmulticol = true; diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index 01d06b7c328..5a090907bb3 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -63,6 +63,7 @@ hashhandler(PG_FUNCTION_ARGS) amroutine->amoptsprocnum = HASHOPTIONS_PROC; amroutine->amcanorder = false; amroutine->amcanorderbyop = false; + amroutine->amorderbyopfirstcol = false; amroutine->amcanbackward = true; amroutine->amcanunique = false; amroutine->amcanmulticol = false; diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 686a3206f72..2d65adb22f7 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -107,6 +107,7 @@ bthandler(PG_FUNCTION_ARGS) amroutine->amoptsprocnum = BTOPTIONS_PROC; amroutine->amcanorder = true; amroutine->amcanorderbyop = false; + amroutine->amorderbyopfirstcol = false; amroutine->amcanbackward = true; amroutine->amcanunique = true; amroutine->amcanmulticol = true; diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c index 76b80146ff0..2ba8cbc966b 100644 --- a/src/backend/access/spgist/spgutils.c +++ b/src/backend/access/spgist/spgutils.c @@ -50,6 +50,7 @@ spghandler(PG_FUNCTION_ARGS) amroutine->amoptsprocnum = SPGIST_OPTIONS_PROC; amroutine->amcanorder = false; amroutine->amcanorderbyop = true; + amroutine->amorderbyopfirstcol = false; amroutine->amcanbackward = false; amroutine->amcanunique = false; amroutine->amcanmulticol = false; diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index c0fcc7d78df..c9685a86196 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -3030,6 +3030,10 @@ match_pathkeys_to_index(IndexOptInfo *index, List *pathkeys, if (!index->amcanorderbyop) return; + /* Only the one pathkey is supported when amorderbyopfirstcol is true */ + if (index->amorderbyopfirstcol && list_length(pathkeys) != 1) + return; + foreach(lc1, pathkeys) { PathKey *pathkey = (PathKey *) lfirst(lc1); @@ -3058,20 +3062,24 @@ match_pathkeys_to_index(IndexOptInfo *index, List *pathkeys, { EquivalenceMember *member = (EquivalenceMember *) lfirst(lc2); int indexcol; + int ncolumns; /* No possibility of match if it references other relations */ if (!bms_equal(member->em_relids, index->rel->relids)) continue; /* - * We allow any column of the index to match each pathkey; they - * don't have to match left-to-right as you might expect. This is - * correct for GiST, and it doesn't matter for SP-GiST because - * that doesn't handle multiple columns anyway, and no other - * existing AMs support amcanorderbyop. We might need different - * logic in future for other implementations. + * We allow any column or only the first of the index to match + * each pathkey; they don't have to match left-to-right as you + * might expect. This is correct for GiST, and it doesn't matter + * for SP-GiST and B-Tree because they do not handle multiple + * columns anyway, and no other existing AMs support + * amcanorderbyop. We might need different logic in future for + * other implementations. */ - for (indexcol = 0; indexcol < index->nkeycolumns; indexcol++) + ncolumns = index->amorderbyopfirstcol ? 1 : index->nkeycolumns; + + for (indexcol = 0; indexcol < ncolumns; indexcol++) { Expr *expr; diff --git a/src/include/access/amapi.h b/src/include/access/amapi.h index f25c9d58a7d..21b5d3149f8 100644 --- a/src/include/access/amapi.h +++ b/src/include/access/amapi.h @@ -224,6 +224,12 @@ typedef struct IndexAmRoutine bool amcanorder; /* does AM support ORDER BY result of an operator on indexed column? */ bool amcanorderbyop; + + /* + * Does AM support only the one ORDER BY operator on first indexed column? + * amcanorderbyop is implied. + */ + bool amorderbyopfirstcol; /* does AM support backward scanning? */ bool amcanbackward; /* does AM support UNIQUE indexes? */ diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 14ccfc1ac1c..b7267f3ecfd 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -1188,6 +1188,8 @@ struct IndexOptInfo * (IndexAmRoutine). These fields are not set for partitioned indexes. */ bool amcanorderbyop; + bool amorderbyopfirstcol; /* order by op is supported only on + * first column? */ bool amoptionalkey; bool amsearcharray; bool amsearchnulls; -- 2.45.2