aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_expr.c')
-rw-r--r--src/backend/parser/parse_expr.c62
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:
{
/*