Skip to content

Commit 71f2993

Browse files
committed
Fix transformExpr() to not scribble on its input datastructure while
transforming CASE expressions. This was definitely confusing FigureColname, and might lead to bad things elsewhere as well.
1 parent 1c7bef3 commit 71f2993

File tree

1 file changed

+57
-49
lines changed

1 file changed

+57
-49
lines changed

src/backend/parser/parse_expr.c

Lines changed: 57 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.102 2001/09/28 08:09:09 thomas Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.103 2001/10/08 21:46:59 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -426,15 +426,23 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
426426
case T_CaseExpr:
427427
{
428428
CaseExpr *c = (CaseExpr *) expr;
429-
CaseWhen *w;
429+
CaseExpr *newc = makeNode(CaseExpr);
430+
List *newargs = NIL;
430431
List *typeids = NIL;
431432
List *args;
433+
Node *defresult;
432434
Oid ptype;
433435

434436
/* transform the list of arguments */
435437
foreach(args, c->args)
436438
{
437-
w = lfirst(args);
439+
CaseWhen *w = (CaseWhen *) lfirst(args);
440+
CaseWhen *neww = makeNode(CaseWhen);
441+
Node *warg;
442+
443+
Assert(IsA(w, CaseWhen));
444+
445+
warg = w->expr;
438446
if (c->arg != NULL)
439447
{
440448
/* shorthand form was specified, so expand... */
@@ -443,81 +451,81 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
443451
a->oper = OP;
444452
a->opname = "=";
445453
a->lexpr = c->arg;
446-
a->rexpr = w->expr;
447-
w->expr = (Node *) a;
454+
a->rexpr = warg;
455+
warg = (Node *) a;
448456
}
449-
lfirst(args) = transformExpr(pstate, (Node *) w, precedence);
450-
typeids = lappendi(typeids, exprType(w->result));
457+
neww->expr = transformExpr(pstate, warg, precedence);
458+
459+
if (! coerce_to_boolean(pstate, &neww->expr))
460+
elog(ERROR, "WHEN clause must have a boolean result");
461+
462+
/*
463+
* result is NULL for NULLIF() construct - thomas
464+
* 1998-11-11
465+
*/
466+
warg = w->result;
467+
if (warg == NULL)
468+
{
469+
A_Const *n = makeNode(A_Const);
470+
471+
n->val.type = T_Null;
472+
warg = (Node *) n;
473+
}
474+
neww->result = transformExpr(pstate, warg, precedence);
475+
476+
newargs = lappend(newargs, neww);
477+
typeids = lappendi(typeids, exprType(neww->result));
451478
}
452479

480+
newc->args = newargs;
481+
453482
/*
454483
* It's not shorthand anymore, so drop the implicit
455-
* argument. This is necessary to keep the executor from
456-
* seeing an untransformed expression... not to mention
457-
* keeping a re-application of transformExpr from doing
458-
* the wrong thing.
484+
* argument. This is necessary to keep any re-application
485+
* of transformExpr from doing the wrong thing.
459486
*/
460-
c->arg = NULL;
487+
newc->arg = NULL;
461488

462489
/* transform the default clause */
463-
if (c->defresult == NULL)
490+
defresult = c->defresult;
491+
if (defresult == NULL)
464492
{
465493
A_Const *n = makeNode(A_Const);
466494

467495
n->val.type = T_Null;
468-
c->defresult = (Node *) n;
496+
defresult = (Node *) n;
469497
}
470-
c->defresult = transformExpr(pstate, c->defresult, precedence);
498+
newc->defresult = transformExpr(pstate, defresult, precedence);
471499

472500
/*
473501
* Note: default result is considered the most significant
474502
* type in determining preferred type. This is how the
475503
* code worked before, but it seems a little bogus to me
476504
* --- tgl
477505
*/
478-
typeids = lconsi(exprType(c->defresult), typeids);
506+
typeids = lconsi(exprType(newc->defresult), typeids);
479507

480508
ptype = select_common_type(typeids, "CASE");
481-
c->casetype = ptype;
509+
newc->casetype = ptype;
482510

483511
/* Convert default result clause, if necessary */
484-
c->defresult = coerce_to_common_type(pstate, c->defresult,
485-
ptype, "CASE/ELSE");
512+
newc->defresult = coerce_to_common_type(pstate,
513+
newc->defresult,
514+
ptype,
515+
"CASE/ELSE");
486516

487517
/* Convert when-clause results, if necessary */
488-
foreach(args, c->args)
489-
{
490-
w = lfirst(args);
491-
w->result = coerce_to_common_type(pstate, w->result,
492-
ptype, "CASE/WHEN");
493-
}
494-
495-
result = expr;
496-
break;
497-
}
498-
499-
case T_CaseWhen:
500-
{
501-
CaseWhen *w = (CaseWhen *) expr;
502-
503-
w->expr = transformExpr(pstate, w->expr, precedence);
504-
505-
if (! coerce_to_boolean(pstate, &w->expr))
506-
elog(ERROR, "WHEN clause must have a boolean result");
507-
508-
/*
509-
* result is NULL for NULLIF() construct - thomas
510-
* 1998-11-11
511-
*/
512-
if (w->result == NULL)
518+
foreach(args, newc->args)
513519
{
514-
A_Const *n = makeNode(A_Const);
520+
CaseWhen *w = (CaseWhen *) lfirst(args);
515521

516-
n->val.type = T_Null;
517-
w->result = (Node *) n;
522+
w->result = coerce_to_common_type(pstate,
523+
w->result,
524+
ptype,
525+
"CASE/WHEN");
518526
}
519-
w->result = transformExpr(pstate, w->result, precedence);
520-
result = expr;
527+
528+
result = (Node *) newc;
521529
break;
522530
}
523531

0 commit comments

Comments
 (0)