]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix incorrect hash equality operator bug in Memoize
authorDavid Rowley <drowley@postgresql.org>
Mon, 8 Nov 2021 01:41:13 +0000 (14:41 +1300)
committerDavid Rowley <drowley@postgresql.org>
Mon, 8 Nov 2021 01:41:13 +0000 (14:41 +1300)
In v14, because we don't have a field in RestrictInfo to cache both the
left and right type's hash equality operator, we just restrict the scope
of Memoize to only when the left and right types of a RestrictInfo are the
same.

In master we add another field to RestrictInfo and cache both hash
equality operators.

Reported-by: Jaime Casanova
Author: David Rowley
Discussion: https://postgr.es/m/20210929185544.GB24346%40ahch-to
Backpatch-through: 14

src/backend/optimizer/plan/initsplan.c

index e25dc9a7ca7c25acfedbaf70d2ccb09ff48f6f68..276e62b74b6d921f87109cbc1637f86e017db771 100644 (file)
@@ -2719,7 +2719,8 @@ check_memoizable(RestrictInfo *restrictinfo)
 {
        TypeCacheEntry *typentry;
        Expr       *clause = restrictinfo->clause;
-       Node       *leftarg;
+       Oid                     lefttype;
+       Oid                     righttype;
 
        if (restrictinfo->pseudoconstant)
                return;
@@ -2728,10 +2729,20 @@ check_memoizable(RestrictInfo *restrictinfo)
        if (list_length(((OpExpr *) clause)->args) != 2)
                return;
 
-       leftarg = linitial(((OpExpr *) clause)->args);
+       lefttype = exprType(linitial(((OpExpr *) clause)->args));
+       righttype = exprType(lsecond(((OpExpr *) clause)->args));
+
+       /*
+        * Really there should be a field for both the left and right hash
+        * equality operator, however, in v14, there's only a single field in
+        * RestrictInfo to record the operator in, so we must insist that the left
+        * and right types match.
+        */
+       if (lefttype != righttype)
+               return;
 
-       typentry = lookup_type_cache(exprType(leftarg), TYPECACHE_HASH_PROC |
-                                                                TYPECACHE_EQ_OPR);
+       typentry = lookup_type_cache(lefttype, TYPECACHE_HASH_PROC |
+                                                                                  TYPECACHE_EQ_OPR);
 
        if (!OidIsValid(typentry->hash_proc) || !OidIsValid(typentry->eq_opr))
                return;