diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2004-03-17 20:48:43 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2004-03-17 20:48:43 +0000 |
commit | 55f7c3300d164d370d28b127210223d078da524d (patch) | |
tree | e5c91b7d50eef3b40dd395e3ecce877bb6663636 /src/backend/parser/parse_expr.c | |
parent | 8c702ea7ace30026dfff4f2e514027cd4d6d7579 (diff) | |
download | postgresql-55f7c3300d164d370d28b127210223d078da524d.tar.gz postgresql-55f7c3300d164d370d28b127210223d078da524d.zip |
Reimplement CASE val WHEN compval1 THEN ... WHEN compval2 THEN ... END
so that the 'val' is computed only once, per recent discussion. The
speedup is not much when 'val' is just a simple variable, but could be
significant for larger expressions. More importantly this avoids issues
with multiple evaluations of a volatile 'val', and it allows the CASE
expression to be reverse-listed in its original form by ruleutils.c.
Diffstat (limited to 'src/backend/parser/parse_expr.c')
-rw-r--r-- | src/backend/parser/parse_expr.c | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index c23e39a25d0..3881cc39538 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.165 2004/02/13 01:08:20 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.166 2004/03/17 20:48:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -637,14 +637,39 @@ transformExpr(ParseState *pstate, Node *expr) case T_CaseExpr: { CaseExpr *c = (CaseExpr *) expr; - CaseExpr *newc = makeNode(CaseExpr); - List *newargs = NIL; - List *typeids = NIL; + CaseExpr *newc; + Node *arg; + CaseTestExpr *placeholder; + List *newargs; + List *typeids; List *args; Node *defresult; Oid ptype; + /* If we already transformed this node, do nothing */ + if (OidIsValid(c->casetype)) + { + result = expr; + break; + } + newc = makeNode(CaseExpr); + + /* transform the test expression, if any */ + arg = transformExpr(pstate, (Node *) c->arg); + newc->arg = (Expr *) arg; + /* generate placeholder for test expression */ + if (arg) + { + placeholder = makeNode(CaseTestExpr); + placeholder->typeId = exprType(arg); + placeholder->typeMod = exprTypmod(arg); + } + else + placeholder = NULL; + /* transform the list of arguments */ + newargs = NIL; + typeids = NIL; foreach(args, c->args) { CaseWhen *w = (CaseWhen *) lfirst(args); @@ -654,11 +679,11 @@ transformExpr(ParseState *pstate, Node *expr) Assert(IsA(w, CaseWhen)); warg = (Node *) w->expr; - if (c->arg != NULL) + if (placeholder) { /* shorthand form was specified, so expand... */ warg = (Node *) makeSimpleA_Expr(AEXPR_OP, "=", - (Node *) c->arg, + (Node *) placeholder, warg); } neww->expr = (Expr *) transformExpr(pstate, warg); @@ -667,18 +692,7 @@ transformExpr(ParseState *pstate, Node *expr) (Node *) neww->expr, "CASE/WHEN"); - /* - * result is NULL for NULLIF() construct - thomas - * 1998-11-11 - */ warg = (Node *) w->result; - if (warg == NULL) - { - A_Const *n = makeNode(A_Const); - - n->val.type = T_Null; - warg = (Node *) n; - } neww->result = (Expr *) transformExpr(pstate, warg); newargs = lappend(newargs, neww); @@ -687,13 +701,6 @@ transformExpr(ParseState *pstate, Node *expr) newc->args = newargs; - /* - * It's not shorthand anymore, so drop the implicit - * argument. This is necessary to keep any re-application - * of transformExpr from doing the wrong thing. - */ - newc->arg = NULL; - /* transform the default clause */ defresult = (Node *) c->defresult; if (defresult == NULL) @@ -714,6 +721,7 @@ transformExpr(ParseState *pstate, Node *expr) typeids = lconso(exprType((Node *) newc->defresult), typeids); ptype = select_common_type(typeids, "CASE"); + Assert(OidIsValid(ptype)); newc->casetype = ptype; /* Convert default result clause, if necessary */ @@ -915,6 +923,7 @@ transformExpr(ParseState *pstate, Node *expr) case T_BoolExpr: case T_FieldSelect: case T_RelabelType: + case T_CaseTestExpr: case T_CoerceToDomain: case T_CoerceToDomainValue: case T_SetToDefault: @@ -1288,6 +1297,9 @@ exprType(Node *expr) case T_CaseWhen: type = exprType((Node *) ((CaseWhen *) expr)->result); break; + case T_CaseTestExpr: + type = ((CaseTestExpr *) expr)->typeId; + break; case T_ArrayExpr: type = ((ArrayExpr *) expr)->array_typeid; break; @@ -1408,6 +1420,8 @@ exprTypmod(Node *expr) return typmod; } break; + case T_CaseTestExpr: + return ((CaseTestExpr *) expr)->typeMod; case T_CoalesceExpr: { /* |