v22-0008-WIP-Support-row-compare-index-scans-with-non-btr.patch

text/plain

Filename: v22-0008-WIP-Support-row-compare-index-scans-with-non-btr.patch
Type: text/plain
Part: 7
Message: Re: Index AM API cleanup

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v22-0008
Subject: WIP: Support row compare index scans with non-btree indexes
File+
src/backend/executor/nodeIndexscan.c 7 2
src/backend/optimizer/path/indxpath.c 20 21
src/backend/parser/parse_expr.c 1 1
src/test/regress/expected/rowtypes.out 1 1
From dc31e865fed00cc79daa964762b5dfa8d9ef89bb Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Wed, 19 Mar 2025 19:51:54 +0100
Subject: [PATCH v22 08/10] WIP: Support row compare index scans with non-btree
 indexes

---
 src/backend/executor/nodeIndexscan.c   |  9 ++++--
 src/backend/optimizer/path/indxpath.c  | 41 +++++++++++++-------------
 src/backend/parser/parse_expr.c        |  2 +-
 src/test/regress/expected/rowtypes.out |  2 +-
 4 files changed, 29 insertions(+), 25 deletions(-)

diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index c04fe461083..39f55052759 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -1334,6 +1334,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 				int			flags = SK_ROW_MEMBER;
 				Datum		scanvalue;
 				Oid			inputcollation;
+				CompareType op_cmptype;
 
 				leftop = (Expr *) lfirst(largs_cell);
 				rightop = (Expr *) lfirst(rargs_cell);
@@ -1365,10 +1366,11 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 
 				get_op_opfamily_properties(opno, opfamily, isorderby,
 										   &op_strategy,
+										   &op_cmptype,
 										   &op_lefttype,
 										   &op_righttype);
 
-				if (op_strategy != rc->cmptype)
+				if (op_cmptype != rc->cmptype)
 					elog(ERROR, "RowCompare index qualification contains wrong operator");
 
 				opfuncid = get_opfamily_proc(opfamily,
@@ -1445,7 +1447,10 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 			MemSet(this_scan_key, 0, sizeof(ScanKeyData));
 			this_scan_key->sk_flags = SK_ROW_HEADER;
 			this_scan_key->sk_attno = first_sub_key->sk_attno;
-			this_scan_key->sk_strategy = rc->cmptype;
+			this_scan_key->sk_strategy = IndexAmTranslateCompareType(rc->cmptype,
+																	 index->rd_rel->relam,
+																	 0,  // FIXME
+																	 false);
 			/* sk_subtype, sk_collation, sk_func not used in a header */
 			this_scan_key->sk_argument = PointerGetDatum(first_sub_key);
 		}
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index e81cd8e1f45..14447e56e2b 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -3158,8 +3158,9 @@ match_rowcompare_to_indexcol(PlannerInfo *root,
 	bool		var_on_left;
 	Oid			expr_op;
 	Oid			expr_coll;
+	StrategyNumber opstrategy;
 
-	/* Forget it if we're not dealing with a btree index */
+	/* Forget it if we're not dealing with a btree index FIXME */
 	if (index->relam != BTREE_AM_OID)
 		return NULL;
 
@@ -3210,18 +3211,21 @@ match_rowcompare_to_indexcol(PlannerInfo *root,
 		return NULL;
 
 	/* We're good if the operator is the right type of opfamily member */
-	switch (get_op_opfamily_strategy(expr_op, opfamily))
+	opstrategy = get_op_opfamily_strategy(expr_op, opfamily);
+	switch (IndexAmTranslateStrategy(opstrategy, index->relam, opfamily, true))
 	{
-		case BTLessStrategyNumber:
-		case BTLessEqualStrategyNumber:
-		case BTGreaterEqualStrategyNumber:
-		case BTGreaterStrategyNumber:
+		case COMPARE_LT:
+		case COMPARE_LE:
+		case COMPARE_GE:
+		case COMPARE_GT:
 			return expand_indexqual_rowcompare(root,
 											   rinfo,
 											   indexcol,
 											   index,
 											   expr_op,
 											   var_on_left);
+		default:
+			break;
 	}
 
 	return NULL;
@@ -3650,8 +3654,7 @@ expand_indexqual_rowcompare(PlannerInfo *root,
 			/* very easy, just use the commuted operators */
 			new_ops = expr_ops;
 		}
-		else if (op_strategy == BTLessEqualStrategyNumber ||
-				 op_strategy == BTGreaterEqualStrategyNumber)
+		else if (op_cmptype == COMPARE_LE || op_cmptype == COMPARE_GE)
 		{
 			/* easy, just use the same (possibly commuted) operators */
 			new_ops = list_truncate(expr_ops, matching_cols);
@@ -3662,12 +3665,12 @@ expand_indexqual_rowcompare(PlannerInfo *root,
 			ListCell   *lefttypes_cell;
 			ListCell   *righttypes_cell;
 
-			if (op_strategy == BTLessStrategyNumber)
-				op_strategy = BTLessEqualStrategyNumber;
-			else if (op_strategy == BTGreaterStrategyNumber)
-				op_strategy = BTGreaterEqualStrategyNumber;
+			if (op_cmptype == COMPARE_LT)
+				op_cmptype = COMPARE_LE;
+			else if (op_cmptype == COMPARE_GT)
+				op_cmptype = COMPARE_GE;
 			else
-				elog(ERROR, "unexpected strategy number %d", op_strategy);
+				elog(ERROR, "unexpected compare type %d", op_cmptype);
 			new_ops = NIL;
 			forthree(opfamilies_cell, opfamilies,
 					 lefttypes_cell, lefttypes,
@@ -3677,11 +3680,11 @@ expand_indexqual_rowcompare(PlannerInfo *root,
 				Oid			lefttype = lfirst_oid(lefttypes_cell);
 				Oid			righttype = lfirst_oid(righttypes_cell);
 
-				expr_op = get_opfamily_member(opfam, lefttype, righttype,
-											  op_strategy);
+				expr_op = get_opfamily_member_for_cmptype(opfam, lefttype, righttype,
+														  op_cmptype);
 				if (!OidIsValid(expr_op))	/* should not happen */
 					elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
-						 op_strategy, lefttype, righttype, opfam);
+						 op_cmptype, lefttype, righttype, opfam);
 				new_ops = lappend_oid(new_ops, expr_op);
 			}
 		}
@@ -3691,11 +3694,7 @@ expand_indexqual_rowcompare(PlannerInfo *root,
 		{
 			RowCompareExpr *rc = makeNode(RowCompareExpr);
 
-			/*
-			 * XXX This assumes that CompareType values match btree strategy
-			 * numbers; see cmptype.h.
-			 */
-			rc->cmptype = (CompareType) op_strategy;
+			rc->cmptype = op_cmptype;
 			rc->opnos = new_ops;
 			rc->opfamilies = list_copy_head(clause->opfamilies,
 											matching_cols);
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 806ccb97537..b83dfc759d8 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -2943,7 +2943,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("could not determine interpretation of row comparison operator %s",
 						strVal(llast(opname))),
-				 errhint("Row comparison operators must be associated with btree operator families."),
+				 errhint("Row comparison operators must be associated with btree-compatible operator families."),
 				 parser_errposition(pstate, location)));
 	}
 	cmptype = (CompareType) i;
diff --git a/src/test/regress/expected/rowtypes.out b/src/test/regress/expected/rowtypes.out
index 9168979a620..025afa2c628 100644
--- a/src/test/regress/expected/rowtypes.out
+++ b/src/test/regress/expected/rowtypes.out
@@ -266,7 +266,7 @@ select ROW('ABC','DEF') ~~ ROW('DEF','ABC') as fail;
 ERROR:  could not determine interpretation of row comparison operator ~~
 LINE 1: select ROW('ABC','DEF') ~~ ROW('DEF','ABC') as fail;
                                 ^
-HINT:  Row comparison operators must be associated with btree operator families.
+HINT:  Row comparison operators must be associated with btree-compatible operator families.
 -- Comparisons of ROW() expressions can cope with some type mismatches
 select ROW(1,2) = ROW(1,2::int8);
  ?column? 
-- 
2.49.0