]> granicus.if.org Git - postgresql/commitdiff
Teach parse_coerce about non-cachable functions (actually,
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 2 Oct 1999 23:29:19 +0000 (23:29 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 2 Oct 1999 23:29:19 +0000 (23:29 +0000)
make it call eval_const_expressions() so that it doesn't have to know).

src/backend/parser/parse_coerce.c
src/test/regress/expected/rules.out

index 297337da4dcc766f09decc4fa31ea93778ea8909..127e493db141cb7e51790c83cf69a83bf77aef07 100644 (file)
@@ -7,13 +7,14 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.23 1999/08/24 00:09:56 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.24 1999/10/02 23:29:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
 
+#include "optimizer/clauses.h"
 #include "parser/parse_coerce.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_func.h"
@@ -49,7 +50,8 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, Oid targetTypeId,
        }
        else if (inputTypeId == UNKNOWNOID && IsA(node, Const))
        {
-               /* Input is a string constant with previously undetermined type.
+               /*
+                * Input is a string constant with previously undetermined type.
                 * Apply the target type's typinput function to it to produce
                 * a constant of the target type.
                 *
@@ -58,6 +60,11 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, Oid targetTypeId,
                 * necessarily behave the same as a type conversion function.
                 * For example, int4's typinput function will reject "1.2",
                 * whereas float-to-int type conversion will round to integer.
+                *
+                * XXX if the typinput function is not cachable, we really ought
+                * to postpone evaluation of the function call until runtime.
+                * But there is no way to represent a typinput function call as
+                * an expression tree, because C-string values are not Datums.
                 */
                Const      *con = (Const *) node;
                Const      *newcon = makeNode(Const);
@@ -97,38 +104,16 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, Oid targetTypeId,
 
                /*
                 * If the input is a constant, apply the type conversion function
-                * now instead of delaying to runtime.  (This could someday be
-                * done in a downstream constant-expression-simplifier, but we
-                * can save cycles in the rewriter if we do it here.)
+                * now instead of delaying to runtime.  (We could, of course,
+                * just leave this to be done during planning/optimization;
+                * but it's a very frequent special case, and we save cycles
+                * in the rewriter if we fold the expression now.)
                 *
-                * XXX there are cases where we probably shouldn't do this,
-                * such as coercing text 'now' to datetime?  Need a way to
-                * know whether type conversion function is cacheable...
+                * Note that no folding will occur if the conversion function is
+                * not marked 'iscachable'.
                 */
-               if (IsA(node, Const) && ! ((Const *) node)->constisnull)
-               {
-                       Const      *con = (Const *) node;
-                       Oid                     convertFuncid;
-                       Datum           val;
-
-                       Assert(IsA(result, Expr) &&
-                                  ((Expr *) result)->opType == FUNC_EXPR);
-
-                       /* Convert the given constant */
-                       convertFuncid = ((Func *) (((Expr *) result)->oper))->funcid;
-                       val = (Datum) fmgr(convertFuncid, con->constvalue);
-
-                       /* now make a new const node */
-                       con = makeNode(Const);
-                       con->consttype = targetTypeId;
-                       con->constlen = typeLen(targetType);
-                       con->constbyval = typeByVal(targetType);
-                       con->constvalue = val;
-                       con->constisnull = false;
-                       con->constisset = false;
-
-                       result = (Node *) con;
-               }
+               if (IsA(node, Const))
+                       result = eval_const_expressions(result);
        }
 
        return result;
index 6e09822c60b861a340e1354fa76fb2a7ac6d28d5..5c15ab919a5a8975940645e775af42f2ce1a4797 100644 (file)
@@ -1118,7 +1118,7 @@ rtest_v1     |rtest_v1_upd   |CREATE RULE "rtest_v1_upd" AS ON UPDATE TO "rtest_
 shoelace     |shoelace_del   |CREATE RULE "shoelace_del" AS ON DELETE TO "shoelace" DO INSTEAD DELETE FROM "shoelace_data" WHERE ("shoelace_data"."sl_name" = old."sl_name");                                                                                                                                       
 shoelace     |shoelace_ins   |CREATE RULE "shoelace_ins" AS ON INSERT TO "shoelace" DO INSTEAD INSERT INTO "shoelace_data" ("sl_name", "sl_avail", "sl_color", "sl_len", "sl_unit") VALUES (new."sl_name", new."sl_avail", new."sl_color", new."sl_len", new."sl_unit");                                            
 shoelace     |shoelace_upd   |CREATE RULE "shoelace_upd" AS ON UPDATE TO "shoelace" DO INSTEAD UPDATE "shoelace_data" SET "sl_name" = new."sl_name", "sl_avail" = new."sl_avail", "sl_color" = new."sl_color", "sl_len" = new."sl_len", "sl_unit" = new."sl_unit" WHERE ("shoelace_data"."sl_name" = old."sl_name");
-shoelace_data|log_shoelace   |CREATE RULE "log_shoelace" AS ON UPDATE TO "shoelace_data" WHERE (new."sl_avail" <> old."sl_avail") DO INSERT INTO "shoelace_log" ("sl_name", "sl_avail", "log_who", "log_when") VALUES (new."sl_name", new."sl_avail", 'Al Bundy'::"name", 'epoch'::"datetime");                     
+shoelace_data|log_shoelace   |CREATE RULE "log_shoelace" AS ON UPDATE TO "shoelace_data" WHERE (new."sl_avail" <> old."sl_avail") DO INSERT INTO "shoelace_log" ("sl_name", "sl_avail", "log_who", "log_when") VALUES (new."sl_name", new."sl_avail", 'Al Bundy'::"name", "datetime"('epoch'::"text"));             
 shoelace_ok  |shoelace_ok_ins|CREATE RULE "shoelace_ok_ins" AS ON INSERT TO "shoelace_ok" DO INSTEAD UPDATE "shoelace" SET "sl_avail" = ("shoelace"."sl_avail" + new."ok_quant") WHERE ("shoelace"."sl_name" = new."ok_name");                                                                                      
 (27 rows)