1 /*-------------------------------------------------------------------------
4 * Routines to determine which tids are usable for scanning a
5 * given relation, and create TidPaths accordingly.
7 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * $PostgreSQL: pgsql/src/backend/optimizer/path/tidpath.c,v 1.19 2004/05/26 04:41:22 neilc Exp $
14 *-------------------------------------------------------------------------
20 #include "catalog/pg_operator.h"
21 #include "optimizer/clauses.h"
22 #include "optimizer/cost.h"
23 #include "optimizer/pathnode.h"
24 #include "optimizer/paths.h"
25 #include "parser/parse_coerce.h"
26 #include "utils/lsyscache.h"
28 static List *TidqualFromRestrictinfo(Relids relids, List *restrictinfo);
29 static bool isEvaluable(int varno, Node *node);
30 static Node *TidequalClause(int varno, OpExpr *node);
31 static List *TidqualFromExpr(int varno, Expr *expr);
34 isEvaluable(int varno, Node *node)
45 Var *var = (Var *) node;
47 if (var->varno == varno)
51 if (!is_funcclause(node))
53 expr = (FuncExpr *) node;
54 foreach(l, expr->args)
56 if (!isEvaluable(varno, lfirst(l)))
64 * The 2nd parameter should be an opclause
65 * Extract the right node if the opclause is CTID= ....
66 * or the left node if the opclause is ....=CTID
69 TidequalClause(int varno, OpExpr *node)
80 if (node->opno != TIDEqualOperator)
82 if (length(node->args) != 2)
84 arg1 = linitial(node->args);
85 arg2 = lsecond(node->args);
91 if (var->varno == varno &&
92 var->varattno == SelfItemPointerAttributeNumber &&
93 var->vartype == TIDOID)
95 else if (var->varnoold == varno &&
96 var->varoattno == SelfItemPointerAttributeNumber &&
97 var->vartype == TIDOID)
100 if ((!arg) && IsA(arg2, Var))
103 if (var->varno == varno &&
104 var->varattno == SelfItemPointerAttributeNumber &&
105 var->vartype == TIDOID)
110 switch (nodeTag(arg))
113 aconst = (Const *) arg;
114 if (aconst->consttype != TIDOID)
116 if (aconst->constbyval)
121 param = (Param *) arg;
122 if (param->paramtype != TIDOID)
128 if (var->varno == varno ||
129 var->vartype != TIDOID)
134 expr = (FuncExpr *) arg;
135 if (expr->funcresulttype != TIDOID)
137 if (isEvaluable(varno, (Node *) expr))
147 * Extract the list of CTID values from a specified expr node.
148 * When the expr node is an or_clause,we try to extract CTID
149 * values from all member nodes. However we would discard them
150 * all if we couldn't extract CTID values from a member node.
151 * When the expr node is an and_clause,we return the list of
152 * CTID values if we could extract the CTID values from a member
156 TidqualFromExpr(int varno, Expr *expr)
161 Node *node = (Node *) expr,
164 if (is_opclause(node))
166 rnode = TidequalClause(varno, (OpExpr *) expr);
168 rlst = lcons(rnode, rlst);
170 else if (and_clause(node))
172 foreach(l, ((BoolExpr *) expr)->args)
174 node = (Node *) lfirst(l);
175 rlst = TidqualFromExpr(varno, (Expr *) node);
180 else if (or_clause(node))
182 foreach(l, ((BoolExpr *) expr)->args)
184 node = (Node *) lfirst(l);
185 frtn = TidqualFromExpr(varno, (Expr *) node);
187 rlst = nconc(rlst, frtn);
201 TidqualFromRestrictinfo(Relids relids, List *restrictinfo)
209 if (bms_membership(relids) != BMS_SINGLETON)
211 varno = bms_singleton_member(relids);
212 foreach(l, restrictinfo)
214 node = (Node *) lfirst(l);
215 if (!IsA(node, RestrictInfo))
217 expr = ((RestrictInfo *) node)->clause;
218 rlst = TidqualFromExpr(varno, expr);
226 * create_tidscan_paths
227 * Creates paths corresponding to tid direct scans of the given rel.
228 * Candidate paths are added to the rel's pathlist (using add_path).
231 create_tidscan_paths(Query *root, RelOptInfo *rel)
233 List *tideval = TidqualFromRestrictinfo(rel->relids,
234 rel->baserestrictinfo);
237 add_path(rel, (Path *) create_tidscan_path(root, rel, tideval));