Teach eval_const_expressions() to simplify an ArrayCoerceExpr to a constant
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 26 Aug 2008 02:16:39 +0000 (02:16 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 26 Aug 2008 02:16:39 +0000 (02:16 +0000)
when its input is constant and the element coercion function is immutable
(or nonexistent, ie, binary-coercible case).  This is an oversight in the
8.3 implementation of ArrayCoerceExpr, and its result is that certain cases
involving IN or NOT IN with constants don't get optimized as they should be.
Per experimentation with an example from Ow Mun Heng.

src/backend/optimizer/util/clauses.c

index 46b8852e7937308b576d99490b6d9a487facaa70..093446970618b357d9df802c93c7ad5e7a1e0fb7 100644 (file)
@@ -2359,6 +2359,41 @@ eval_const_expressions_mutator(Node *node,
                newexpr->coerceformat = expr->coerceformat;
                return (Node *) newexpr;
        }
+       if (IsA(node, ArrayCoerceExpr))
+       {
+               ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
+               Expr       *arg;
+               ArrayCoerceExpr *newexpr;
+
+               /*
+                * Reduce constants in the ArrayCoerceExpr's argument, then build
+                * a new ArrayCoerceExpr.
+                */
+               arg = (Expr *) eval_const_expressions_mutator((Node *) expr->arg,
+                                                                                                         context);
+
+               newexpr = makeNode(ArrayCoerceExpr);
+               newexpr->arg = arg;
+               newexpr->elemfuncid = expr->elemfuncid;
+               newexpr->resulttype = expr->resulttype;
+               newexpr->resulttypmod = expr->resulttypmod;
+               newexpr->isExplicit = expr->isExplicit;
+               newexpr->coerceformat = expr->coerceformat;
+
+               /*
+                * If constant argument and it's a binary-coercible or immutable
+                * conversion, we can simplify it to a constant.
+                */
+               if (arg && IsA(arg, Const) &&
+                       (!OidIsValid(newexpr->elemfuncid) ||
+                        func_volatile(newexpr->elemfuncid) == PROVOLATILE_IMMUTABLE))
+                       return (Node *) evaluate_expr((Expr *) newexpr,
+                                                                                 newexpr->resulttype,
+                                                                                 newexpr->resulttypmod);
+
+               /* Else we must return the partially-simplified node */
+               return (Node *) newexpr;
+       }
        if (IsA(node, CaseExpr))
        {
                /*----------