From b40ac42efb0dbba0f84cd7ed353726596b4ea2b7 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 2 Oct 1999 23:29:19 +0000 Subject: [PATCH] Teach parse_coerce about non-cachable functions (actually, make it call eval_const_expressions() so that it doesn't have to know). --- src/backend/parser/parse_coerce.c | 49 ++++++++++------------------- src/test/regress/expected/rules.out | 2 +- 2 files changed, 18 insertions(+), 33 deletions(-) diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 297337da4d..127e493db1 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -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; diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 6e09822c60..5c15ab919a 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -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) -- 2.40.0