mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
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.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.155 2004/03/17 01:02:23 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.156 2004/03/17 20:48:42 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -81,6 +81,9 @@ static Datum ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
|
||||
bool *isNull, ExprDoneCond *isDone);
|
||||
static Datum ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
|
||||
bool *isNull, ExprDoneCond *isDone);
|
||||
static Datum ExecEvalCaseTestExpr(ExprState *exprstate,
|
||||
ExprContext *econtext,
|
||||
bool *isNull, ExprDoneCond *isDone);
|
||||
static Datum ExecEvalArray(ArrayExprState *astate,
|
||||
ExprContext *econtext,
|
||||
bool *isNull, ExprDoneCond *isDone);
|
||||
@@ -1809,10 +1812,29 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
|
||||
{
|
||||
List *clauses = caseExpr->args;
|
||||
List *clause;
|
||||
Datum save_datum;
|
||||
bool save_isNull;
|
||||
|
||||
if (isDone)
|
||||
*isDone = ExprSingleResult;
|
||||
|
||||
/*
|
||||
* If there's a test expression, we have to evaluate it and save
|
||||
* the value where the CaseTestExpr placeholders can find it.
|
||||
* We must save and restore prior setting of econtext's caseValue fields,
|
||||
* in case this node is itself within a larger CASE.
|
||||
*/
|
||||
save_datum = econtext->caseValue_datum;
|
||||
save_isNull = econtext->caseValue_isNull;
|
||||
|
||||
if (caseExpr->arg)
|
||||
{
|
||||
econtext->caseValue_datum = ExecEvalExpr(caseExpr->arg,
|
||||
econtext,
|
||||
&econtext->caseValue_isNull,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* we evaluate each of the WHEN clauses in turn, as soon as one is
|
||||
* true we return the corresponding result. If none are true then we
|
||||
@@ -1835,6 +1857,8 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
|
||||
*/
|
||||
if (DatumGetBool(clause_value) && !*isNull)
|
||||
{
|
||||
econtext->caseValue_datum = save_datum;
|
||||
econtext->caseValue_isNull = save_isNull;
|
||||
return ExecEvalExpr(wclause->result,
|
||||
econtext,
|
||||
isNull,
|
||||
@@ -1842,6 +1866,9 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
|
||||
}
|
||||
}
|
||||
|
||||
econtext->caseValue_datum = save_datum;
|
||||
econtext->caseValue_isNull = save_isNull;
|
||||
|
||||
if (caseExpr->defresult)
|
||||
{
|
||||
return ExecEvalExpr(caseExpr->defresult,
|
||||
@@ -1854,6 +1881,22 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
|
||||
return (Datum) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ExecEvalCaseTestExpr
|
||||
*
|
||||
* Return the value stored by CASE.
|
||||
*/
|
||||
static Datum
|
||||
ExecEvalCaseTestExpr(ExprState *exprstate,
|
||||
ExprContext *econtext,
|
||||
bool *isNull, ExprDoneCond *isDone)
|
||||
{
|
||||
if (isDone)
|
||||
*isDone = ExprSingleResult;
|
||||
*isNull = econtext->caseValue_isNull;
|
||||
return econtext->caseValue_datum;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecEvalArray - ARRAY[] expressions
|
||||
*
|
||||
@@ -2478,6 +2521,10 @@ ExecInitExpr(Expr *node, PlanState *parent)
|
||||
state = (ExprState *) makeNode(ExprState);
|
||||
state->evalfunc = ExecEvalCoerceToDomainValue;
|
||||
break;
|
||||
case T_CaseTestExpr:
|
||||
state = (ExprState *) makeNode(ExprState);
|
||||
state->evalfunc = ExecEvalCaseTestExpr;
|
||||
break;
|
||||
case T_Aggref:
|
||||
{
|
||||
Aggref *aggref = (Aggref *) node;
|
||||
@@ -2666,6 +2713,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
|
||||
List *inlist;
|
||||
|
||||
cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCase;
|
||||
cstate->arg = ExecInitExpr(caseexpr->arg, parent);
|
||||
FastListInit(&outlist);
|
||||
foreach(inlist, caseexpr->args)
|
||||
{
|
||||
@@ -2680,8 +2728,6 @@ ExecInitExpr(Expr *node, PlanState *parent)
|
||||
FastAppend(&outlist, wstate);
|
||||
}
|
||||
cstate->args = FastListValue(&outlist);
|
||||
/* caseexpr->arg should be null by now */
|
||||
Assert(caseexpr->arg == NULL);
|
||||
cstate->defresult = ExecInitExpr(caseexpr->defresult, parent);
|
||||
state = (ExprState *) cstate;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.109 2004/01/22 02:23:21 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.110 2004/03/17 20:48:42 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -306,6 +306,9 @@ CreateExprContext(EState *estate)
|
||||
econtext->ecxt_aggvalues = NULL;
|
||||
econtext->ecxt_aggnulls = NULL;
|
||||
|
||||
econtext->caseValue_datum = (Datum) 0;
|
||||
econtext->caseValue_isNull = true;
|
||||
|
||||
econtext->domainValue_datum = (Datum) 0;
|
||||
econtext->domainValue_isNull = true;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.278 2004/03/11 01:47:35 ishii Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.279 2004/03/17 20:48:42 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -968,6 +968,20 @@ _copyCaseWhen(CaseWhen *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/*
|
||||
* _copyCaseTestExpr
|
||||
*/
|
||||
static CaseTestExpr *
|
||||
_copyCaseTestExpr(CaseTestExpr *from)
|
||||
{
|
||||
CaseTestExpr *newnode = makeNode(CaseTestExpr);
|
||||
|
||||
COPY_SCALAR_FIELD(typeId);
|
||||
COPY_SCALAR_FIELD(typeMod);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/*
|
||||
* _copyArrayExpr
|
||||
*/
|
||||
@@ -2643,6 +2657,9 @@ copyObject(void *from)
|
||||
case T_CaseWhen:
|
||||
retval = _copyCaseWhen(from);
|
||||
break;
|
||||
case T_CaseTestExpr:
|
||||
retval = _copyCaseTestExpr(from);
|
||||
break;
|
||||
case T_ArrayExpr:
|
||||
retval = _copyArrayExpr(from);
|
||||
break;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.217 2004/03/14 23:41:26 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.218 2004/03/17 20:48:42 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -403,6 +403,15 @@ _equalCaseWhen(CaseWhen *a, CaseWhen *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalCaseTestExpr(CaseTestExpr *a, CaseTestExpr *b)
|
||||
{
|
||||
COMPARE_SCALAR_FIELD(typeId);
|
||||
COMPARE_SCALAR_FIELD(typeMod);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalArrayExpr(ArrayExpr *a, ArrayExpr *b)
|
||||
{
|
||||
@@ -1724,6 +1733,9 @@ equal(void *a, void *b)
|
||||
case T_CaseWhen:
|
||||
retval = _equalCaseWhen(a, b);
|
||||
break;
|
||||
case T_CaseTestExpr:
|
||||
retval = _equalCaseTestExpr(a, b);
|
||||
break;
|
||||
case T_ArrayExpr:
|
||||
retval = _equalArrayExpr(a, b);
|
||||
break;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.232 2004/01/31 05:09:40 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.233 2004/03/17 20:48:42 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Every node type that can appear in stored rules' parsetrees *must*
|
||||
@@ -805,6 +805,15 @@ _outCaseWhen(StringInfo str, CaseWhen *node)
|
||||
WRITE_NODE_FIELD(result);
|
||||
}
|
||||
|
||||
static void
|
||||
_outCaseTestExpr(StringInfo str, CaseTestExpr *node)
|
||||
{
|
||||
WRITE_NODE_TYPE("CASETESTEXPR");
|
||||
|
||||
WRITE_OID_FIELD(typeId);
|
||||
WRITE_INT_FIELD(typeMod);
|
||||
}
|
||||
|
||||
static void
|
||||
_outArrayExpr(StringInfo str, ArrayExpr *node)
|
||||
{
|
||||
@@ -1701,6 +1710,9 @@ _outNode(StringInfo str, void *obj)
|
||||
case T_CaseWhen:
|
||||
_outCaseWhen(str, obj);
|
||||
break;
|
||||
case T_CaseTestExpr:
|
||||
_outCaseTestExpr(str, obj);
|
||||
break;
|
||||
case T_ArrayExpr:
|
||||
_outArrayExpr(str, obj);
|
||||
break;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.165 2004/01/14 23:01:55 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.166 2004/03/17 20:48:42 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Path and Plan nodes do not have any readfuncs support, because we
|
||||
@@ -648,6 +648,20 @@ _readCaseWhen(void)
|
||||
READ_DONE();
|
||||
}
|
||||
|
||||
/*
|
||||
* _readCaseTestExpr
|
||||
*/
|
||||
static CaseTestExpr *
|
||||
_readCaseTestExpr(void)
|
||||
{
|
||||
READ_LOCALS(CaseTestExpr);
|
||||
|
||||
READ_OID_FIELD(typeId);
|
||||
READ_INT_FIELD(typeMod);
|
||||
|
||||
READ_DONE();
|
||||
}
|
||||
|
||||
/*
|
||||
* _readArrayExpr
|
||||
*/
|
||||
@@ -1010,6 +1024,8 @@ parseNodeString(void)
|
||||
return_value = _readCaseExpr();
|
||||
else if (MATCH("WHEN", 4))
|
||||
return_value = _readCaseWhen();
|
||||
else if (MATCH("CASETESTEXPR", 12))
|
||||
return_value = _readCaseTestExpr();
|
||||
else if (MATCH("ARRAY", 5))
|
||||
return_value = _readArrayExpr();
|
||||
else if (MATCH("COALESCE", 8))
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.164 2004/03/14 23:41:27 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.165 2004/03/17 20:48:42 tgl Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@@ -1397,15 +1397,29 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
|
||||
* simplify the entire CASE to that alternative's expression.
|
||||
* If there are no non-FALSE alternatives, we simplify the entire
|
||||
* CASE to the default result (ELSE result).
|
||||
*
|
||||
* If we have a simple-form CASE with constant test expression and
|
||||
* one or more constant comparison expressions, we could run the
|
||||
* implied comparisons and potentially reduce those arms to constants.
|
||||
* This is not yet implemented, however. At present, the
|
||||
* CaseTestExpr placeholder will always act as a non-constant node
|
||||
* and prevent the comparison boolean expressions from being reduced
|
||||
* to Const nodes.
|
||||
*----------
|
||||
*/
|
||||
CaseExpr *caseexpr = (CaseExpr *) node;
|
||||
CaseExpr *newcase;
|
||||
Node *newarg;
|
||||
FastList newargs;
|
||||
Node *defresult;
|
||||
Const *const_input;
|
||||
List *arg;
|
||||
|
||||
/* Simplify the test expression, if any */
|
||||
newarg = eval_const_expressions_mutator((Node *) caseexpr->arg,
|
||||
active_fns);
|
||||
|
||||
/* Simplify the WHEN clauses */
|
||||
FastListInit(&newargs);
|
||||
foreach(arg, caseexpr->args)
|
||||
{
|
||||
@@ -1454,7 +1468,7 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
|
||||
/* Otherwise we need a new CASE node */
|
||||
newcase = makeNode(CaseExpr);
|
||||
newcase->casetype = caseexpr->casetype;
|
||||
newcase->arg = NULL;
|
||||
newcase->arg = (Expr *) newarg;
|
||||
newcase->args = FastListValue(&newargs);
|
||||
newcase->defresult = (Expr *) defresult;
|
||||
return (Node *) newcase;
|
||||
@@ -2319,6 +2333,7 @@ expression_tree_walker(Node *node,
|
||||
case T_Const:
|
||||
case T_Param:
|
||||
case T_CoerceToDomainValue:
|
||||
case T_CaseTestExpr:
|
||||
case T_SetToDefault:
|
||||
case T_RangeTblRef:
|
||||
/* primitive node types with no subnodes */
|
||||
@@ -2425,6 +2440,8 @@ expression_tree_walker(Node *node,
|
||||
{
|
||||
CaseExpr *caseexpr = (CaseExpr *) node;
|
||||
|
||||
if (walker(caseexpr->arg, context))
|
||||
return true;
|
||||
/* we assume walker doesn't care about CaseWhens, either */
|
||||
foreach(temp, caseexpr->args)
|
||||
{
|
||||
@@ -2436,9 +2453,6 @@ expression_tree_walker(Node *node,
|
||||
if (walker(when->result, context))
|
||||
return true;
|
||||
}
|
||||
/* caseexpr->arg should be null, but we'll check it anyway */
|
||||
if (walker(caseexpr->arg, context))
|
||||
return true;
|
||||
if (walker(caseexpr->defresult, context))
|
||||
return true;
|
||||
}
|
||||
@@ -2692,6 +2706,7 @@ expression_tree_mutator(Node *node,
|
||||
case T_Const:
|
||||
case T_Param:
|
||||
case T_CoerceToDomainValue:
|
||||
case T_CaseTestExpr:
|
||||
case T_SetToDefault:
|
||||
case T_RangeTblRef:
|
||||
/* primitive node types with no subnodes */
|
||||
@@ -2829,9 +2844,8 @@ expression_tree_mutator(Node *node,
|
||||
CaseExpr *newnode;
|
||||
|
||||
FLATCOPY(newnode, caseexpr, CaseExpr);
|
||||
MUTATE(newnode->args, caseexpr->args, List *);
|
||||
/* caseexpr->arg should be null, but we'll check it anyway */
|
||||
MUTATE(newnode->arg, caseexpr->arg, Expr *);
|
||||
MUTATE(newnode->args, caseexpr->args, List *);
|
||||
MUTATE(newnode->defresult, caseexpr->defresult, Expr *);
|
||||
return (Node *) newnode;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.448 2004/03/11 01:47:37 ishii Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.449 2004/03/17 20:48:42 tgl Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@@ -6965,6 +6965,7 @@ in_expr: select_with_parens
|
||||
case_expr: CASE case_arg when_clause_list case_default END_P
|
||||
{
|
||||
CaseExpr *c = makeNode(CaseExpr);
|
||||
c->casetype = InvalidOid; /* not analyzed yet */
|
||||
c->arg = (Expr *) $2;
|
||||
c->args = $3;
|
||||
c->defresult = (Expr *) $4;
|
||||
|
||||
@@ -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:
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* back to source text
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.162 2004/01/31 05:09:40 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.163 2004/03/17 20:48:42 tgl Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@@ -2564,7 +2564,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
|
||||
case T_ArrayExpr: /* other separators */
|
||||
case T_CoalesceExpr: /* own parentheses */
|
||||
case T_NullIfExpr: /* other separators */
|
||||
case T_Aggref: /* own parentheses */
|
||||
case T_Aggref: /* own parentheses */
|
||||
case T_CaseExpr: /* other separators */
|
||||
return true;
|
||||
default:
|
||||
@@ -2610,7 +2610,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
|
||||
case T_ArrayExpr: /* other separators */
|
||||
case T_CoalesceExpr: /* own parentheses */
|
||||
case T_NullIfExpr: /* other separators */
|
||||
case T_Aggref: /* own parentheses */
|
||||
case T_Aggref: /* own parentheses */
|
||||
case T_CaseExpr: /* other separators */
|
||||
return true;
|
||||
default:
|
||||
@@ -3026,6 +3026,11 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
|
||||
appendContextKeyword(context, "CASE",
|
||||
0, PRETTYINDENT_VAR, 0);
|
||||
if (caseexpr->arg)
|
||||
{
|
||||
appendStringInfoChar(buf, ' ');
|
||||
get_rule_expr((Node *) caseexpr->arg, context, true);
|
||||
}
|
||||
foreach(temp, caseexpr->args)
|
||||
{
|
||||
CaseWhen *when = (CaseWhen *) lfirst(temp);
|
||||
@@ -3034,7 +3039,17 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
appendStringInfoChar(buf, ' ');
|
||||
appendContextKeyword(context, "WHEN ",
|
||||
0, 0, 0);
|
||||
get_rule_expr((Node *) when->expr, context, false);
|
||||
if (caseexpr->arg)
|
||||
{
|
||||
/* Show only the RHS of "CaseTestExpr = RHS" */
|
||||
Node *rhs;
|
||||
|
||||
Assert(IsA(when->expr, OpExpr));
|
||||
rhs = (Node *) lsecond(((OpExpr *) when->expr)->args);
|
||||
get_rule_expr(rhs, context, false);
|
||||
}
|
||||
else
|
||||
get_rule_expr((Node *) when->expr, context, false);
|
||||
appendStringInfo(buf, " THEN ");
|
||||
get_rule_expr((Node *) when->result, context, true);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user