Teach parse_coerce about non-cachable functions (actually,
make it call eval_const_expressions() so that it doesn't have to know).
This commit is contained in:
parent
6eb8d255d2
commit
b40ac42efb
@ -7,13 +7,14 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 "postgres.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "optimizer/clauses.h"
|
||||||
#include "parser/parse_coerce.h"
|
#include "parser/parse_coerce.h"
|
||||||
#include "parser/parse_expr.h"
|
#include "parser/parse_expr.h"
|
||||||
#include "parser/parse_func.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))
|
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
|
* Apply the target type's typinput function to it to produce
|
||||||
* a constant of the target type.
|
* 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.
|
* necessarily behave the same as a type conversion function.
|
||||||
* For example, int4's typinput function will reject "1.2",
|
* For example, int4's typinput function will reject "1.2",
|
||||||
* whereas float-to-int type conversion will round to integer.
|
* 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 *con = (Const *) node;
|
||||||
Const *newcon = makeNode(Const);
|
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
|
* If the input is a constant, apply the type conversion function
|
||||||
* now instead of delaying to runtime. (This could someday be
|
* now instead of delaying to runtime. (We could, of course,
|
||||||
* done in a downstream constant-expression-simplifier, but we
|
* just leave this to be done during planning/optimization;
|
||||||
* can save cycles in the rewriter if we do it here.)
|
* 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,
|
* Note that no folding will occur if the conversion function is
|
||||||
* such as coercing text 'now' to datetime? Need a way to
|
* not marked 'iscachable'.
|
||||||
* know whether type conversion function is cacheable...
|
|
||||||
*/
|
*/
|
||||||
if (IsA(node, Const) && ! ((Const *) node)->constisnull)
|
if (IsA(node, Const))
|
||||||
{
|
result = eval_const_expressions(result);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -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_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_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 |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");
|
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)
|
(27 rows)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user