1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-13 16:22:44 +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/optimizer/path/clausesel.c,v 1.53 2002/11/25 21:29:39 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.54 2002/12/12 15:49:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -141,7 +141,7 @@ clauselist_selectivity(Query *root,
if (is_opclause(clause) &&
(varRelid != 0 || NumRelids(clause) == 1))
{
Expr *expr = (Expr *) clause;
OpExpr *expr = (OpExpr *) clause;
if (length(expr->args) == 2)
{
@@ -151,7 +151,7 @@ clauselist_selectivity(Query *root,
(varonleft = false,
is_pseudo_constant_clause(lfirst(expr->args))))
{
Oid opno = ((Oper *) expr->oper)->opno;
Oid opno = expr->opno;
RegProcedure oprrest = get_oprrest(opno);
s2 = restriction_selectivity(root, opno,
@@ -430,7 +430,7 @@ clause_selectivity(Query *root,
{
/* share code with clauselist_selectivity() */
s1 = clauselist_selectivity(root,
((Expr *) clause)->args,
((BoolExpr *) clause)->args,
varRelid);
}
else if (or_clause(clause))
@@ -443,7 +443,7 @@ clause_selectivity(Query *root,
List *arg;
s1 = 0.0;
foreach(arg, ((Expr *) clause)->args)
foreach(arg, ((BoolExpr *) clause)->args)
{
Selectivity s2 = clause_selectivity(root,
(Node *) lfirst(arg),
@@ -454,7 +454,7 @@ clause_selectivity(Query *root,
}
else if (is_opclause(clause))
{
Oid opno = ((Oper *) ((Expr *) clause)->oper)->opno;
Oid opno = ((OpExpr *) clause)->opno;
bool is_join_clause;
if (varRelid != 0)
@@ -479,13 +479,14 @@ clause_selectivity(Query *root,
{
/* Estimate selectivity for a join clause. */
s1 = join_selectivity(root, opno,
((Expr *) clause)->args);
((OpExpr *) clause)->args);
}
else
{
/* Estimate selectivity for a restriction clause. */
s1 = restriction_selectivity(root, opno,
((Expr *) clause)->args, varRelid);
((OpExpr *) clause)->args,
varRelid);
}
}
else if (is_funcclause(clause))
@@ -509,7 +510,7 @@ clause_selectivity(Query *root,
/* Use node specific selectivity calculation function */
s1 = nulltestsel(root,
((NullTest *) clause)->nulltesttype,
((NullTest *) clause)->arg,
(Node *) ((NullTest *) clause)->arg,
varRelid);
}
else if (IsA(clause, BooleanTest))
@@ -517,14 +518,14 @@ clause_selectivity(Query *root,
/* Use node specific selectivity calculation function */
s1 = booltestsel(root,
((BooleanTest *) clause)->booltesttype,
((BooleanTest *) clause)->arg,
(Node *) ((BooleanTest *) clause)->arg,
varRelid);
}
else if (IsA(clause, RelabelType))
{
/* Not sure this case is needed, but it can't hurt */
s1 = clause_selectivity(root,
((RelabelType *) clause)->arg,
(Node *) ((RelabelType *) clause)->arg,
varRelid);
}

View File

@@ -42,7 +42,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.93 2002/11/30 05:21:02 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.94 2002/12/12 15:49:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1220,63 +1220,48 @@ cost_qual_eval_walker(Node *node, Cost *total)
* Should we try to account for the possibility of short-circuit
* evaluation of AND/OR?
*/
if (IsA(node, Expr))
if (IsA(node, FuncExpr) ||
IsA(node, OpExpr) ||
IsA(node, DistinctExpr))
*total += cpu_operator_cost;
else if (IsA(node, SubPlanExpr))
{
Expr *expr = (Expr *) node;
/*
* A subplan node in an expression indicates that the
* subplan will be executed on each evaluation, so charge
* accordingly. (We assume that sub-selects that can be
* executed as InitPlans have already been removed from
* the expression.)
*
* NOTE: this logic should agree with the estimates used by
* make_subplan() in plan/subselect.c.
*/
SubPlanExpr *subplan = (SubPlanExpr *) node;
Plan *plan = subplan->plan;
Cost subcost;
switch (expr->opType)
if (subplan->sublink->subLinkType == EXISTS_SUBLINK)
{
case OP_EXPR:
case DISTINCT_EXPR:
case FUNC_EXPR:
*total += cpu_operator_cost;
break;
case OR_EXPR:
case AND_EXPR:
case NOT_EXPR:
break;
case SUBPLAN_EXPR:
/*
* A subplan node in an expression indicates that the
* subplan will be executed on each evaluation, so charge
* accordingly. (We assume that sub-selects that can be
* executed as InitPlans have already been removed from
* the expression.)
*
* NOTE: this logic should agree with the estimates used by
* make_subplan() in plan/subselect.c.
*/
{
SubPlan *subplan = (SubPlan *) expr->oper;
Plan *plan = subplan->plan;
Cost subcost;
if (subplan->sublink->subLinkType == EXISTS_SUBLINK)
{
/* we only need to fetch 1 tuple */
subcost = plan->startup_cost +
(plan->total_cost - plan->startup_cost) / plan->plan_rows;
}
else if (subplan->sublink->subLinkType == ALL_SUBLINK ||
subplan->sublink->subLinkType == ANY_SUBLINK)
{
/* assume we need 50% of the tuples */
subcost = plan->startup_cost +
0.50 * (plan->total_cost - plan->startup_cost);
/* XXX what if subplan has been materialized? */
}
else
{
/* assume we need all tuples */
subcost = plan->total_cost;
}
*total += subcost;
}
break;
/* we only need to fetch 1 tuple */
subcost = plan->startup_cost +
(plan->total_cost - plan->startup_cost) / plan->plan_rows;
}
/* fall through to examine args of Expr node */
else if (subplan->sublink->subLinkType == ALL_SUBLINK ||
subplan->sublink->subLinkType == ANY_SUBLINK)
{
/* assume we need 50% of the tuples */
subcost = plan->startup_cost +
0.50 * (plan->total_cost - plan->startup_cost);
/* XXX what if subplan has been materialized? */
}
else
{
/* assume we need all tuples */
subcost = plan->total_cost;
}
*total += subcost;
}
return expression_tree_walker(node, cost_qual_eval_walker,
(void *) total);
}

View File

@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.126 2002/11/25 21:29:39 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.127 2002/12/12 15:49:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -73,6 +73,8 @@ static bool match_clause_to_indexkey(RelOptInfo *rel, IndexOptInfo *index,
int indexkey, Oid opclass, Expr *clause);
static bool match_join_clause_to_indexkey(RelOptInfo *rel, IndexOptInfo *index,
int indexkey, Oid opclass, Expr *clause);
static Oid indexable_operator(Expr *clause, Oid opclass,
bool indexkey_on_left);
static bool pred_test(List *predicate_list, List *restrictinfo_list,
List *joininfo_list, int relvarno);
static bool pred_test_restrict_list(Expr *predicate, List *restrictinfo_list);
@@ -280,7 +282,7 @@ match_index_orclauses(RelOptInfo *rel,
*/
restrictinfo->subclauseindices =
match_index_orclause(rel, index,
restrictinfo->clause->args,
((BoolExpr *) restrictinfo->clause)->args,
restrictinfo->subclauseindices);
}
}
@@ -377,7 +379,7 @@ match_or_subclause_to_indexkey(RelOptInfo *rel,
{
List *item;
foreach(item, clause->args)
foreach(item, ((BoolExpr *) clause)->args)
{
if (match_clause_to_indexkey(rel, index, indexkey, opclass,
lfirst(item)))
@@ -443,7 +445,7 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
if (and_clause((Node *) orsubclause))
{
foreach(item, orsubclause->args)
foreach(item, ((BoolExpr *) orsubclause)->args)
{
Expr *subsubclause = (Expr *) lfirst(item);
@@ -715,7 +717,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
*rightop;
/* Clause must be a binary opclause. */
if (!is_opclause((Node *) clause))
if (!is_opclause(clause))
return false;
leftop = get_leftop(clause);
rightop = get_rightop(clause);
@@ -803,7 +805,7 @@ match_join_clause_to_indexkey(RelOptInfo *rel,
*rightop;
/* Clause must be a binary opclause. */
if (!is_opclause((Node *) clause))
if (!is_opclause(clause))
return false;
leftop = get_leftop(clause);
rightop = get_rightop(clause);
@@ -857,10 +859,10 @@ match_join_clause_to_indexkey(RelOptInfo *rel,
* (Formerly, this routine might return a binary-compatible operator
* rather than the original one, but that kluge is history.)
*/
Oid
static Oid
indexable_operator(Expr *clause, Oid opclass, bool indexkey_on_left)
{
Oid expr_op = ((Oper *) clause->oper)->opno;
Oid expr_op = ((OpExpr *) clause)->opno;
Oid commuted_op;
/* Get the commuted operator if necessary */
@@ -985,7 +987,7 @@ pred_test_recurse_clause(Expr *predicate, Node *clause)
Assert(clause != NULL);
if (or_clause(clause))
{
items = ((Expr *) clause)->args;
items = ((BoolExpr *) clause)->args;
foreach(item, items)
{
/* if any OR item doesn't imply the predicate, clause doesn't */
@@ -996,7 +998,7 @@ pred_test_recurse_clause(Expr *predicate, Node *clause)
}
else if (and_clause(clause))
{
items = ((Expr *) clause)->args;
items = ((BoolExpr *) clause)->args;
foreach(item, items)
{
/*
@@ -1029,7 +1031,7 @@ pred_test_recurse_pred(Expr *predicate, Node *clause)
Assert(predicate != NULL);
if (or_clause((Node *) predicate))
{
items = predicate->args;
items = ((BoolExpr *) predicate)->args;
foreach(item, items)
{
/* if any item is implied, the whole predicate is implied */
@@ -1040,7 +1042,7 @@ pred_test_recurse_pred(Expr *predicate, Node *clause)
}
else if (and_clause((Node *) predicate))
{
items = predicate->args;
items = ((BoolExpr *) predicate)->args;
foreach(item, items)
{
/*
@@ -1121,7 +1123,6 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
StrategyNumber pred_strategy = 0,
clause_strategy,
test_strategy;
Oper *test_oper;
Expr *test_expr;
Datum test_result;
bool isNull;
@@ -1140,7 +1141,7 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
* Can't do anything more unless they are both binary opclauses with a
* Var on the left and a Const on the right.
*/
if (!is_opclause((Node *) predicate))
if (!is_opclause(predicate))
return false;
pred_var = (Var *) get_leftop(predicate);
pred_const = (Const *) get_rightop(predicate);
@@ -1167,8 +1168,8 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
return false;
/* Get the operators for the two clauses we're comparing */
pred_op = ((Oper *) ((Expr *) predicate)->oper)->opno;
clause_op = ((Oper *) ((Expr *) clause)->oper)->opno;
pred_op = ((OpExpr *) predicate)->opno;
clause_op = ((OpExpr *) clause)->opno;
/*
* 1. Find a "btree" strategy number for the pred_op
@@ -1267,14 +1268,12 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
/*
* 5. Evaluate the test
*/
test_oper = makeOper(test_op, /* opno */
InvalidOid, /* opid */
BOOLOID, /* opresulttype */
false); /* opretset */
replace_opid(test_oper);
test_expr = make_opclause(test_oper,
(Var *) clause_const,
(Var *) pred_const);
test_expr = make_opclause(test_op,
BOOLOID,
false,
(Expr *) clause_const,
(Expr *) pred_const);
set_opfuncid((OpExpr *) test_expr);
econtext = MakeExprContext(NULL, TransactionCommandContext);
test_result = ExecEvalExprSwitchContext((Node *) test_expr, econtext,
@@ -1627,7 +1626,7 @@ static bool
function_index_operand(Expr *funcOpnd, RelOptInfo *rel, IndexOptInfo *index)
{
int relvarno = lfirsti(rel->relids);
Func *function;
FuncExpr *function;
List *funcargs;
int *indexKeys = index->indexkeys;
List *arg;
@@ -1636,13 +1635,12 @@ function_index_operand(Expr *funcOpnd, RelOptInfo *rel, IndexOptInfo *index)
/*
* sanity check, make sure we know what we're dealing with here.
*/
if (funcOpnd == NULL || !IsA(funcOpnd, Expr) ||
funcOpnd->opType != FUNC_EXPR ||
funcOpnd->oper == NULL || indexKeys == NULL)
if (funcOpnd == NULL || !IsA(funcOpnd, FuncExpr) ||
indexKeys == NULL)
return false;
function = (Func *) funcOpnd->oper;
funcargs = funcOpnd->args;
function = (FuncExpr *) funcOpnd;
funcargs = function->args;
if (function->funcid != index->indproc)
return false;
@@ -1752,7 +1750,7 @@ match_special_index_operator(Expr *clause, Oid opclass,
/* we know these will succeed */
leftop = get_leftop(clause);
rightop = get_rightop(clause);
expr_op = ((Oper *) clause->oper)->opno;
expr_op = ((OpExpr *) clause)->opno;
/* again, required for all current special ops: */
if (!IsA(rightop, Const) ||
@@ -1916,7 +1914,7 @@ expand_indexqual_conditions(List *indexquals)
/* we know these will succeed */
Var *leftop = get_leftop(clause);
Var *rightop = get_rightop(clause);
Oid expr_op = ((Oper *) clause->oper)->opno;
Oid expr_op = ((OpExpr *) clause)->opno;
Const *patt = (Const *) rightop;
Const *prefix = NULL;
Const *rest = NULL;
@@ -2011,7 +2009,6 @@ prefix_quals(Var *leftop, Oid expr_op,
Oid oproid;
char *prefix;
Const *con;
Oper *op;
Expr *expr;
Const *greaterstr = NULL;
@@ -2070,8 +2067,8 @@ prefix_quals(Var *leftop, Oid expr_op,
if (oproid == InvalidOid)
elog(ERROR, "prefix_quals: no = operator for type %u", datatype);
con = string_to_const(prefix, datatype);
op = makeOper(oproid, InvalidOid, BOOLOID, false);
expr = make_opclause(op, leftop, (Var *) con);
expr = make_opclause(oproid, BOOLOID, false,
(Expr *) leftop, (Expr *) con);
result = makeList1(expr);
return result;
}
@@ -2085,8 +2082,8 @@ prefix_quals(Var *leftop, Oid expr_op,
if (oproid == InvalidOid)
elog(ERROR, "prefix_quals: no >= operator for type %u", datatype);
con = string_to_const(prefix, datatype);
op = makeOper(oproid, InvalidOid, BOOLOID, false);
expr = make_opclause(op, leftop, (Var *) con);
expr = make_opclause(oproid, BOOLOID, false,
(Expr *) leftop, (Expr *) con);
result = makeList1(expr);
/*-------
@@ -2100,8 +2097,8 @@ prefix_quals(Var *leftop, Oid expr_op,
oproid = find_operator("<", datatype);
if (oproid == InvalidOid)
elog(ERROR, "prefix_quals: no < operator for type %u", datatype);
op = makeOper(oproid, InvalidOid, BOOLOID, false);
expr = make_opclause(op, leftop, (Var *) greaterstr);
expr = make_opclause(oproid, BOOLOID, false,
(Expr *) leftop, (Expr *) greaterstr);
result = lappend(result, expr);
}
@@ -2124,7 +2121,6 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop)
Oid opr2oid;
List *result;
Oid datatype;
Oper *op;
Expr *expr;
switch (expr_op)
@@ -2164,10 +2160,10 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop)
opr1right = network_scan_first(rightop);
op = makeOper(opr1oid, InvalidOid, BOOLOID, false);
expr = make_opclause(op, leftop,
(Var *) makeConst(datatype, -1, opr1right,
false, false));
expr = make_opclause(opr1oid, BOOLOID, false,
(Expr *) leftop,
(Expr *) makeConst(datatype, -1, opr1right,
false, false));
result = makeList1(expr);
/* create clause "key <= network_scan_last( rightop )" */
@@ -2179,10 +2175,10 @@ network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop)
opr2right = network_scan_last(rightop);
op = makeOper(opr2oid, InvalidOid, BOOLOID, false);
expr = make_opclause(op, leftop,
(Var *) makeConst(datatype, -1, opr2right,
false, false));
expr = make_opclause(opr2oid, BOOLOID, false,
(Expr *) leftop,
(Expr *) makeConst(datatype, -1, opr2right,
false, false));
result = lappend(result, expr);
return result;

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.48 2002/11/24 21:52:14 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.49 2002/12/12 15:49:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -96,7 +96,7 @@ create_or_index_paths(Query *root, RelOptInfo *rel)
best_or_subclause_indices(root,
rel,
restrictinfo->clause->args,
((BoolExpr *) restrictinfo->clause)->args,
restrictinfo->subclauseindices,
pathnode);

View File

@@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.41 2002/09/18 21:35:21 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.42 2002/12/12 15:49:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -514,22 +514,9 @@ build_index_pathkeys(Query *root,
if (index->indproc)
{
/* Functional index: build a representation of the function call */
Func *funcnode = makeNode(Func);
Expr *funcnode;
List *funcargs = NIL;
funcnode->funcid = index->indproc;
funcnode->funcresulttype = get_func_rettype(index->indproc);
funcnode->funcretset = false; /* can never be a set */
funcnode->funcformat = COERCE_DONTCARE; /* to match any user expr */
funcnode->func_fcache = NULL;
while (*indexkeys != 0)
{
funcargs = lappend(funcargs,
find_indexkey_var(root, rel, *indexkeys));
indexkeys++;
}
sortop = *ordering;
if (ScanDirectionIsBackward(scandir))
{
@@ -538,9 +525,21 @@ build_index_pathkeys(Query *root,
return NIL; /* oops, no reverse sort operator? */
}
while (*indexkeys != 0)
{
funcargs = lappend(funcargs,
find_indexkey_var(root, rel, *indexkeys));
indexkeys++;
}
funcnode = make_funcclause(index->indproc,
get_func_rettype(index->indproc),
false, /* cannot be a set */
COERCE_DONTCARE, /* to match any user expr */
funcargs);
/* Make a one-sublist pathkeys list for the function expression */
item = makePathKeyItem((Node *) make_funcclause(funcnode, funcargs),
sortop);
item = makePathKeyItem((Node *) funcnode, sortop);
retval = makeList1(make_canonical_pathkey(root, item));
}
else

View File

@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/tidpath.c,v 1.12 2002/11/24 21:52:14 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/tidpath.c,v 1.13 2002/12/12 15:49:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,15 +27,14 @@
static List *TidqualFromRestrictinfo(List *relids, List *restrictinfo);
static bool isEvaluable(int varno, Node *node);
static Node *TidequalClause(int varno, Expr *node);
static Node *TidequalClause(int varno, OpExpr *node);
static List *TidqualFromExpr(int varno, Expr *expr);
static
bool
static bool
isEvaluable(int varno, Node *node)
{
List *lst;
Expr *expr;
FuncExpr *expr;
if (IsA(node, Const))
return true;
@@ -51,7 +50,7 @@ isEvaluable(int varno, Node *node)
}
if (!is_funcclause(node))
return false;
expr = (Expr *) node;
expr = (FuncExpr *) node;
foreach(lst, expr->args)
{
if (!isEvaluable(varno, lfirst(lst)))
@@ -66,33 +65,26 @@ isEvaluable(int varno, Node *node)
* Extract the right node if the opclause is CTID= ....
* or the left node if the opclause is ....=CTID
*/
static
Node *
TidequalClause(int varno, Expr *node)
static Node *
TidequalClause(int varno, OpExpr *node)
{
Node *rnode = 0,
Node *rnode = NULL,
*arg1,
*arg2,
*arg;
Oper *oper;
Var *var;
Const *aconst;
Param *param;
Expr *expr;
FuncExpr *expr;
if (!node->oper)
return rnode;
if (!node->args)
if (node->opno != TIDEqualOperator)
return rnode;
if (length(node->args) != 2)
return rnode;
oper = (Oper *) node->oper;
if (oper->opno != TIDEqualOperator)
return rnode;
arg1 = lfirst(node->args);
arg2 = lsecond(node->args);
arg = (Node *) 0;
arg = NULL;
if (IsA(arg1, Var))
{
var = (Var *) arg1;
@@ -138,11 +130,9 @@ TidequalClause(int varno, Expr *node)
return rnode;
rnode = arg;
break;
case T_Expr:
expr = (Expr *) arg;
if (expr->typeOid != TIDOID)
return rnode;
if (expr->opType != FUNC_EXPR)
case T_FuncExpr:
expr = (FuncExpr *) arg;
if (expr->funcresulttype != TIDOID)
return rnode;
if (isEvaluable(varno, (Node *) expr))
rnode = arg;
@@ -162,8 +152,7 @@ TidequalClause(int varno, Expr *node)
* CTID values if we could extract the CTID values from a member
* node.
*/
static
List *
static List *
TidqualFromExpr(int varno, Expr *expr)
{
List *rlst = NIL,
@@ -174,17 +163,15 @@ TidqualFromExpr(int varno, Expr *expr)
if (is_opclause(node))
{
rnode = TidequalClause(varno, expr);
rnode = TidequalClause(varno, (OpExpr *) expr);
if (rnode)
rlst = lcons(rnode, rlst);
}
else if (and_clause(node))
{
foreach(lst, expr->args)
foreach(lst, ((BoolExpr *) expr)->args)
{
node = lfirst(lst);
if (!IsA(node, Expr))
continue;
rlst = TidqualFromExpr(varno, (Expr *) node);
if (rlst)
break;
@@ -192,11 +179,11 @@ TidqualFromExpr(int varno, Expr *expr)
}
else if (or_clause(node))
{
foreach(lst, expr->args)
foreach(lst, ((BoolExpr *) expr)->args)
{
node = lfirst(lst);
if (IsA(node, Expr) &&
(frtn = TidqualFromExpr(varno, (Expr *) node)))
frtn = TidqualFromExpr(varno, (Expr *) node);
if (frtn)
rlst = nconc(rlst, frtn);
else
{