From dc31e865fed00cc79daa964762b5dfa8d9ef89bb Mon Sep 17 00:00:00 2001 From: Peter Eisentraut 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