1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-17 17:02:08 +03:00

Phase 2 of read-only-plans project: restructure expression-tree nodes

so that all executable expression nodes inherit from a common supertype
Expr.  This is somewhat of an exercise in code purity rather than any
real functional advance, but getting rid of the extra Oper or Func node
formerly used in each operator or function call should provide at least
a little space and speed improvement.
initdb forced by changes in stored-rules representation.
This commit is contained in:
Tom Lane
2002-12-12 15:49:42 +00:00
parent debb072886
commit a0bf885f9e
69 changed files with 3390 additions and 3433 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.135 2002/12/06 05:00:26 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.136 2002/12/12 15:49:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -199,9 +199,9 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
n->nulltesttype = IS_NULL;
if (exprIsNullConstant(a->lexpr))
n->arg = a->rexpr;
n->arg = (Expr *) a->rexpr;
else
n->arg = a->lexpr;
n->arg = (Expr *) a->lexpr;
result = transformExpr(pstate,
(Node *) n, domVal);
@ -225,15 +225,13 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
a->lexpr, domVal);
Node *rexpr = transformExpr(pstate,
a->rexpr, domVal);
Expr *expr = makeNode(Expr);
lexpr = coerce_to_boolean(lexpr, "AND");
rexpr = coerce_to_boolean(rexpr, "AND");
expr->typeOid = BOOLOID;
expr->opType = AND_EXPR;
expr->args = makeList2(lexpr, rexpr);
result = (Node *) expr;
result = (Node *) makeBoolExpr(AND_EXPR,
makeList2(lexpr,
rexpr));
}
break;
case OR:
@ -242,29 +240,24 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
a->lexpr, domVal);
Node *rexpr = transformExpr(pstate,
a->rexpr, domVal);
Expr *expr = makeNode(Expr);
lexpr = coerce_to_boolean(lexpr, "OR");
rexpr = coerce_to_boolean(rexpr, "OR");
expr->typeOid = BOOLOID;
expr->opType = OR_EXPR;
expr->args = makeList2(lexpr, rexpr);
result = (Node *) expr;
result = (Node *) makeBoolExpr(OR_EXPR,
makeList2(lexpr,
rexpr));
}
break;
case NOT:
{
Node *rexpr = transformExpr(pstate,
a->rexpr, domVal);
Expr *expr = makeNode(Expr);
rexpr = coerce_to_boolean(rexpr, "NOT");
expr->typeOid = BOOLOID;
expr->opType = NOT_EXPR;
expr->args = makeList1(rexpr);
result = (Node *) expr;
result = (Node *) makeBoolExpr(NOT_EXPR,
makeList1(rexpr));
}
break;
case DISTINCT:
@ -277,9 +270,12 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
result = (Node *) make_op(a->name,
lexpr,
rexpr);
if (((Expr *) result)->typeOid != BOOLOID)
if (((OpExpr *) result)->opresulttype != BOOLOID)
elog(ERROR, "IS DISTINCT FROM requires = operator to yield boolean");
((Expr *) result)->opType = DISTINCT_EXPR;
/*
* We rely on DistinctExpr and OpExpr being same struct
*/
NodeSetTag(result, T_DistinctExpr);
}
break;
case OF:
@ -433,7 +429,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
Node *lexpr;
Operator optup;
Form_pg_operator opform;
Oper *newop;
OpExpr *newop;
right_list = lnext(right_list);
if (tent->resdom->resjunk)
@ -451,7 +447,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
*/
optup = oper(op,
exprType(lexpr),
exprType(tent->expr),
exprType((Node *) tent->expr),
false);
opform = (Form_pg_operator) GETSTRUCT(optup);
@ -466,11 +462,15 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
" to be used with quantified predicate subquery",
opname);
newop = makeOper(oprid(optup), /* opno */
InvalidOid, /* opid */
opform->oprresult,
false);
newop = makeNode(OpExpr);
newop->opno = oprid(optup);
newop->opfuncid = InvalidOid;
newop->opresulttype = opform->oprresult;
newop->opretset = false;
newop->args = NIL; /* for now */
sublink->oper = lappend(sublink->oper, newop);
ReleaseSysCache(optup);
}
if (left_list != NIL)
@ -499,22 +499,24 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
Assert(IsA(w, CaseWhen));
warg = w->expr;
warg = (Node *) w->expr;
if (c->arg != NULL)
{
/* shorthand form was specified, so expand... */
warg = (Node *) makeSimpleA_Expr(OP, "=",
c->arg, warg);
(Node *) c->arg,
warg);
}
neww->expr = transformExpr(pstate, warg, domVal);
neww->expr = (Expr *) transformExpr(pstate, warg, domVal);
neww->expr = coerce_to_boolean(neww->expr, "CASE/WHEN");
neww->expr = (Expr *) coerce_to_boolean((Node *) neww->expr,
"CASE/WHEN");
/*
* result is NULL for NULLIF() construct - thomas
* 1998-11-11
*/
warg = w->result;
warg = (Node *) w->result;
if (warg == NULL)
{
A_Const *n = makeNode(A_Const);
@ -522,10 +524,10 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
n->val.type = T_Null;
warg = (Node *) n;
}
neww->result = transformExpr(pstate, warg, domVal);
neww->result = (Expr *) transformExpr(pstate, warg, domVal);
newargs = lappend(newargs, neww);
typeids = lappendi(typeids, exprType(neww->result));
typeids = lappendi(typeids, exprType((Node *) neww->result));
}
newc->args = newargs;
@ -538,7 +540,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
newc->arg = NULL;
/* transform the default clause */
defresult = c->defresult;
defresult = (Node *) c->defresult;
if (defresult == NULL)
{
A_Const *n = makeNode(A_Const);
@ -546,7 +548,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
n->val.type = T_Null;
defresult = (Node *) n;
}
newc->defresult = transformExpr(pstate, defresult, domVal);
newc->defresult = (Expr *) transformExpr(pstate, defresult, domVal);
/*
* Note: default result is considered the most significant
@ -554,24 +556,26 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
* code worked before, but it seems a little bogus to me
* --- tgl
*/
typeids = lconsi(exprType(newc->defresult), typeids);
typeids = lconsi(exprType((Node *) newc->defresult), typeids);
ptype = select_common_type(typeids, "CASE");
newc->casetype = ptype;
/* Convert default result clause, if necessary */
newc->defresult = coerce_to_common_type(newc->defresult,
ptype,
"CASE/ELSE");
newc->defresult = (Expr *)
coerce_to_common_type((Node *) newc->defresult,
ptype,
"CASE/ELSE");
/* Convert when-clause results, if necessary */
foreach(args, newc->args)
{
CaseWhen *w = (CaseWhen *) lfirst(args);
w->result = coerce_to_common_type(w->result,
ptype,
"CASE/WHEN");
w->result = (Expr *)
coerce_to_common_type((Node *) w->result,
ptype,
"CASE/WHEN");
}
result = (Node *) newc;
@ -582,7 +586,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
{
NullTest *n = (NullTest *) expr;
n->arg = transformExpr(pstate, n->arg, domVal);
n->arg = (Expr *) transformExpr(pstate, (Node *) n->arg, domVal);
/* the argument can be any type, so don't coerce it */
result = expr;
break;
@ -619,9 +623,9 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
clausename = NULL; /* keep compiler quiet */
}
b->arg = transformExpr(pstate, b->arg, domVal);
b->arg = (Expr *) transformExpr(pstate, (Node *) b->arg, domVal);
b->arg = coerce_to_boolean(b->arg, clausename);
b->arg = (Expr *) coerce_to_boolean((Node *) b->arg, clausename);
result = expr;
break;
@ -885,36 +889,39 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
Oid
exprType(Node *expr)
{
Oid type = (Oid) InvalidOid;
Oid type;
if (!expr)
return type;
return InvalidOid;
switch (nodeTag(expr))
{
case T_Var:
type = ((Var *) expr)->vartype;
break;
case T_Expr:
type = ((Expr *) expr)->typeOid;
break;
case T_Const:
type = ((Const *) expr)->consttype;
break;
case T_ArrayRef:
type = ((ArrayRef *) expr)->refrestype;
break;
case T_Aggref:
type = ((Aggref *) expr)->aggtype;
break;
case T_Param:
type = ((Param *) expr)->paramtype;
break;
case T_FieldSelect:
type = ((FieldSelect *) expr)->resulttype;
case T_Aggref:
type = ((Aggref *) expr)->aggtype;
break;
case T_RelabelType:
type = ((RelabelType *) expr)->resulttype;
case T_ArrayRef:
type = ((ArrayRef *) expr)->refrestype;
break;
case T_FuncExpr:
type = ((FuncExpr *) expr)->funcresulttype;
break;
case T_OpExpr:
type = ((OpExpr *) expr)->opresulttype;
break;
case T_DistinctExpr:
type = ((DistinctExpr *) expr)->opresulttype;
break;
case T_BoolExpr:
type = BOOLOID;
break;
case T_SubLink:
{
@ -938,11 +945,17 @@ exprType(Node *expr)
}
}
break;
case T_FieldSelect:
type = ((FieldSelect *) expr)->resulttype;
break;
case T_RelabelType:
type = ((RelabelType *) expr)->resulttype;
break;
case T_CaseExpr:
type = ((CaseExpr *) expr)->casetype;
break;
case T_CaseWhen:
type = exprType(((CaseWhen *) expr)->result);
type = exprType((Node *) ((CaseWhen *) expr)->result);
break;
case T_NullTest:
type = BOOLOID;
@ -951,7 +964,7 @@ exprType(Node *expr)
type = BOOLOID;
break;
case T_ConstraintTest:
type = exprType(((ConstraintTest *) expr)->arg);
type = exprType((Node *) ((ConstraintTest *) expr)->arg);
break;
case T_ConstraintTestValue:
type = ((ConstraintTestValue *) expr)->typeId;
@ -959,6 +972,7 @@ exprType(Node *expr)
default:
elog(ERROR, "exprType: Do not know how to get type for %d node",
nodeTag(expr));
type = InvalidOid; /* keep compiler quiet */
break;
}
return type;
@ -995,7 +1009,7 @@ exprTypmod(Node *expr)
}
}
break;
case T_Expr:
case T_FuncExpr:
{
int32 coercedTypmod;
@ -1021,9 +1035,9 @@ exprTypmod(Node *expr)
if (!cexpr->defresult)
return -1;
if (exprType(cexpr->defresult) != casetype)
if (exprType((Node *) cexpr->defresult) != casetype)
return -1;
typmod = exprTypmod(cexpr->defresult);
typmod = exprTypmod((Node *) cexpr->defresult);
if (typmod < 0)
return -1; /* no point in trying harder */
foreach(arg, cexpr->args)
@ -1031,16 +1045,16 @@ exprTypmod(Node *expr)
CaseWhen *w = (CaseWhen *) lfirst(arg);
Assert(IsA(w, CaseWhen));
if (exprType(w->result) != casetype)
if (exprType((Node *) w->result) != casetype)
return -1;
if (exprTypmod(w->result) != typmod)
if (exprTypmod((Node *) w->result) != typmod)
return -1;
}
return typmod;
}
break;
case T_ConstraintTest:
return exprTypmod(((ConstraintTest *) expr)->arg);
return exprTypmod((Node *) ((ConstraintTest *) expr)->arg);
default:
break;
@ -1059,7 +1073,7 @@ exprTypmod(Node *expr)
bool
exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
{
Func *func;
FuncExpr *func;
int nargs;
Const *second_arg;
@ -1067,12 +1081,9 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
*coercedTypmod = -1; /* default result on failure */
/* Is it a function-call at all? */
if (expr == NULL ||
!IsA(expr, Expr) ||
((Expr *) expr)->opType != FUNC_EXPR)
if (expr == NULL || !IsA(expr, FuncExpr))
return false;
func = (Func *) (((Expr *) expr)->oper);
Assert(IsA(func, Func));
func = (FuncExpr *) expr;
/*
* If it didn't come from a coercion context, reject.
@ -1086,11 +1097,11 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
* argument being an int4 constant, it can't have been created from a
* length coercion (it must be a type coercion, instead).
*/
nargs = length(((Expr *) expr)->args);
nargs = length(func->args);
if (nargs < 2 || nargs > 3)
return false;
second_arg = (Const *) lsecond(((Expr *) expr)->args);
second_arg = (Const *) lsecond(func->args);
if (!IsA(second_arg, Const) ||
second_arg->consttype != INT4OID ||
second_arg->constisnull)