0001-Fix-record-hash-support-variant-2.patch

text/plain

Filename: 0001-Fix-record-hash-support-variant-2.patch
Type: text/plain
Part: 1
Message: Re: BUG #17158: Distinct ROW fails with Postgres 14

Patch

Format: format-patch
Series: patch 0001
Subject: Fix record hash support, variant 2
File+
src/backend/optimizer/path/joinpath.c 1 1
src/backend/optimizer/plan/initsplan.c 1 1
src/backend/parser/analyze.c 13 5
src/backend/parser/parse_clause.c 6 0
src/backend/rewrite/rewriteSearchCycle.c 3 3
src/backend/utils/cache/lsyscache.c 1 1
src/include/parser/analyze.h 1 1
From 512ba0bdc53aa140027a18449426bf1327ba3efe Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Fri, 27 Aug 2021 10:50:49 +0200
Subject: [PATCH] Fix record hash support, variant 2

---
 src/backend/optimizer/path/joinpath.c    |  2 +-
 src/backend/optimizer/plan/initsplan.c   |  2 +-
 src/backend/parser/analyze.c             | 18 +++++++++++++-----
 src/backend/parser/parse_clause.c        |  6 ++++++
 src/backend/rewrite/rewriteSearchCycle.c |  6 +++---
 src/backend/utils/cache/lsyscache.c      |  2 +-
 src/include/parser/analyze.h             |  2 +-
 7 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index 6407ede12a..385a41606e 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -437,7 +437,7 @@ paraminfo_get_equal_hashops(PlannerInfo *root, ParamPathInfo *param_info,
 									 TYPECACHE_HASH_PROC | TYPECACHE_EQ_OPR);
 
 		/* can't use a memoize node without a valid hash equals operator */
-		if (!OidIsValid(typentry->hash_proc) || !OidIsValid(typentry->eq_opr))
+		if (!OidIsValid(typentry->hash_proc) || !OidIsValid(typentry->eq_opr) || typentry->type_id == RECORDOID)
 		{
 			list_free(*operators);
 			list_free(*param_exprs);
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index e25dc9a7ca..5fc411dcce 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -2733,7 +2733,7 @@ check_memoizable(RestrictInfo *restrictinfo)
 	typentry = lookup_type_cache(exprType(leftarg), TYPECACHE_HASH_PROC |
 								 TYPECACHE_EQ_OPR);
 
-	if (!OidIsValid(typentry->hash_proc) || !OidIsValid(typentry->eq_opr))
+	if (!OidIsValid(typentry->hash_proc) || !OidIsValid(typentry->eq_opr) || typentry->type_id == RECORDOID)
 		return;
 
 	restrictinfo->hasheqoperator = typentry->eq_opr;
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 15669c8238..07623f1daa 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -1852,9 +1852,12 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
 
 /*
  * Make a SortGroupClause node for a SetOperationStmt's groupClauses
+ *
+ * If need_hash is true, the caller is indicating that they need hash support
+ * or they will fail.  So look extra hard for hash support.
  */
 SortGroupClause *
-makeSortGroupClauseForSetOp(Oid rescoltype)
+makeSortGroupClauseForSetOp(Oid rescoltype, bool need_hash)
 {
 	SortGroupClause *grpcl = makeNode(SortGroupClause);
 	Oid			sortop;
@@ -1867,6 +1870,9 @@ makeSortGroupClauseForSetOp(Oid rescoltype)
 							 &sortop, &eqop, NULL,
 							 &hashable);
 
+	if (rescoltype == RECORDOID)
+		hashable = need_hash;
+
 	/* we don't have a tlist yet, so can't assign sortgrouprefs */
 	grpcl->tleSortGroupRef = 0;
 	grpcl->eqop = eqop;
@@ -2027,6 +2033,9 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
 		ListCell   *ltl;
 		ListCell   *rtl;
 		const char *context;
+		bool recursive = (pstate->p_parent_cte &&
+						  pstate->p_parent_cte->cterecursive);
+
 
 		context = (stmt->op == SETOP_UNION ? "UNION" :
 				   (stmt->op == SETOP_INTERSECT ? "INTERSECT" :
@@ -2048,9 +2057,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
 		 * containing CTE as having those result columns.  We should do this
 		 * only at the topmost setop of the CTE, of course.
 		 */
-		if (isTopLevel &&
-			pstate->p_parent_cte &&
-			pstate->p_parent_cte->cterecursive)
+		if (isTopLevel && recursive)
 			determineRecursiveColTypes(pstate, op->larg, ltargetlist);
 
 		/*
@@ -2182,8 +2189,9 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
 				setup_parser_errposition_callback(&pcbstate, pstate,
 												  bestlocation);
 
+				/* If it's a recursive union, we need to require hashing support. */
 				op->groupClauses = lappend(op->groupClauses,
-										   makeSortGroupClauseForSetOp(rescoltype));
+										   makeSortGroupClauseForSetOp(rescoltype, recursive));
 
 				cancel_parser_errposition_callback(&pcbstate);
 			}
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index b3f151d33b..3518d359aa 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -3318,6 +3318,8 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle,
 									 true, true, false,
 									 &sortop, &eqop, NULL,
 									 &hashable);
+			if (restype == RECORDOID)
+				hashable = false;
 			reverse = false;
 			break;
 		case SORTBY_DESC:
@@ -3325,6 +3327,8 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle,
 									 false, true, true,
 									 NULL, &eqop, &sortop,
 									 &hashable);
+			if (restype == RECORDOID)
+				hashable = false;
 			reverse = true;
 			break;
 		case SORTBY_USING:
@@ -3449,6 +3453,8 @@ addTargetToGroupList(ParseState *pstate, TargetEntry *tle,
 								 false, true, false,
 								 &sortop, &eqop, NULL,
 								 &hashable);
+		if (restype == RECORDOID)
+			hashable = false;
 
 		cancel_parser_errposition_callback(&pcbstate);
 
diff --git a/src/backend/rewrite/rewriteSearchCycle.c b/src/backend/rewrite/rewriteSearchCycle.c
index c50ebdba24..ef38f4025a 100644
--- a/src/backend/rewrite/rewriteSearchCycle.c
+++ b/src/backend/rewrite/rewriteSearchCycle.c
@@ -594,7 +594,7 @@ rewriteSearchAndCycle(CommonTableExpr *cte)
 		sos->colCollations = lappend_oid(sos->colCollations, InvalidOid);
 		if (!sos->all)
 			sos->groupClauses = lappend(sos->groupClauses,
-										makeSortGroupClauseForSetOp(search_seq_type));
+										makeSortGroupClauseForSetOp(search_seq_type, true));
 	}
 	if (cte->cycle_clause)
 	{
@@ -603,14 +603,14 @@ rewriteSearchAndCycle(CommonTableExpr *cte)
 		sos->colCollations = lappend_oid(sos->colCollations, cte->cycle_clause->cycle_mark_collation);
 		if (!sos->all)
 			sos->groupClauses = lappend(sos->groupClauses,
-										makeSortGroupClauseForSetOp(cte->cycle_clause->cycle_mark_type));
+										makeSortGroupClauseForSetOp(cte->cycle_clause->cycle_mark_type, true));
 
 		sos->colTypes = lappend_oid(sos->colTypes, RECORDARRAYOID);
 		sos->colTypmods = lappend_int(sos->colTypmods, -1);
 		sos->colCollations = lappend_oid(sos->colCollations, InvalidOid);
 		if (!sos->all)
 			sos->groupClauses = lappend(sos->groupClauses,
-										makeSortGroupClauseForSetOp(RECORDARRAYOID));
+										makeSortGroupClauseForSetOp(RECORDARRAYOID, true));
 	}
 
 	/*
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 4ebaa552a2..f66b09d940 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -1421,7 +1421,7 @@ op_hashjoinable(Oid opno, Oid inputtype)
 	else if (opno == RECORD_EQ_OP)
 	{
 		typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
-		if (typentry->hash_proc == F_HASH_RECORD)
+		if (typentry->hash_proc == F_HASH_RECORD && inputtype != RECORDOID)
 			result = true;
 	}
 	else
diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h
index 6716db6c13..89d61238e9 100644
--- a/src/include/parser/analyze.h
+++ b/src/include/parser/analyze.h
@@ -48,6 +48,6 @@ extern void applyLockingClause(Query *qry, Index rtindex,
 extern List *BuildOnConflictExcludedTargetlist(Relation targetrel,
 											   Index exclRelIndex);
 
-extern SortGroupClause *makeSortGroupClauseForSetOp(Oid rescoltype);
+extern SortGroupClause *makeSortGroupClauseForSetOp(Oid rescoltype, bool need_hash);
 
 #endif							/* ANALYZE_H */
-- 
2.33.0