Add code to eval_const_expressions() to support const-simplification of
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 15 May 2008 17:37:49 +0000 (17:37 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 15 May 2008 17:37:49 +0000 (17:37 +0000)
CoerceViaIO nodes.  This improves the ability of the planner to deal with
cases where the node input is a constant.  Per bug #4170.

src/backend/optimizer/util/clauses.c

index 86654185392111db718e77d5694ea5e6a2311472..ea924222792c16a9e3d70aa78339bfb9cf4db25e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.258 2008/05/12 00:00:49 alvherre Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.259 2008/05/15 17:37:49 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -2106,6 +2106,71 @@ eval_const_expressions_mutator(Node *node,
                        return (Node *) newrelabel;
                }
        }
+       if (IsA(node, CoerceViaIO))
+       {
+               CoerceViaIO *expr = (CoerceViaIO *) node;
+               Expr       *arg;
+               Oid                     outfunc;
+               bool            outtypisvarlena;
+               Oid                     infunc;
+               Oid                     intypioparam;
+               Expr       *simple;
+               CoerceViaIO *newexpr;
+
+               /*
+                * Reduce constants in the CoerceViaIO's argument.
+                */
+               arg = (Expr *) eval_const_expressions_mutator((Node *) expr->arg,
+                                                                                                         context);
+
+               /*
+                * CoerceViaIO represents calling the source type's output function
+                * then the result type's input function.  So, try to simplify it
+                * as though it were a stack of two such function calls.  First we
+                * need to know what the functions are.
+                */
+               getTypeOutputInfo(exprType((Node *) arg), &outfunc, &outtypisvarlena);
+               getTypeInputInfo(expr->resulttype, &infunc, &intypioparam);
+
+               simple = simplify_function(outfunc,
+                                                                  CSTRINGOID, -1,
+                                                                  list_make1(arg),
+                                                                  true, context);
+               if (simple)                             /* successfully simplified output fn */
+               {
+                       /*
+                        * Input functions may want 1 to 3 arguments.  We always supply
+                        * all three, trusting that nothing downstream will complain.
+                        */
+                       List       *args;
+
+                       args = list_make3(simple,
+                                                         makeConst(OIDOID, -1, sizeof(Oid),
+                                                                               ObjectIdGetDatum(intypioparam),
+                                                                               false, true),
+                                                         makeConst(INT4OID, -1, sizeof(int32),
+                                                                               Int32GetDatum(-1),
+                                                                               false, true));
+
+                       simple = simplify_function(infunc,
+                                                                          expr->resulttype, -1,
+                                                                          args,
+                                                                          true, context);
+                       if (simple)                     /* successfully simplified input fn */
+                               return (Node *) simple;
+               }
+
+               /*
+                * The expression cannot be simplified any further, so build and
+                * return a replacement CoerceViaIO node using the possibly-simplified
+                * argument.
+                */
+               newexpr = makeNode(CoerceViaIO);
+               newexpr->arg = arg;
+               newexpr->resulttype = expr->resulttype;
+               newexpr->coerceformat = expr->coerceformat;
+               return (Node *) newexpr;
+       }
        if (IsA(node, CaseExpr))
        {
                /*----------