diff options
Diffstat (limited to 'src/backend/optimizer/path')
| -rw-r--r-- | src/backend/optimizer/path/clausesel.c | 12 | ||||
| -rw-r--r-- | src/backend/optimizer/path/costsize.c | 20 | ||||
| -rw-r--r-- | src/backend/optimizer/path/tidpath.c | 14 |
3 files changed, 41 insertions, 5 deletions
diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c index b8bbc29c50..4b48ae1e26 100644 --- a/src/backend/optimizer/path/clausesel.c +++ b/src/backend/optimizer/path/clausesel.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.85 2007/04/21 21:01:44 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.86 2007/06/11 01:16:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,6 +18,7 @@ #include "nodes/makefuncs.h" #include "optimizer/clauses.h" #include "optimizer/cost.h" +#include "optimizer/pathnode.h" #include "optimizer/plancat.h" #include "parser/parsetree.h" #include "utils/fmgroids.h" @@ -712,6 +713,15 @@ clause_selectivity(PlannerInfo *root, varRelid, jointype); } + else if (IsA(clause, CurrentOfExpr)) + { + /* CURRENT OF selects at most one row of its table */ + CurrentOfExpr *cexpr = (CurrentOfExpr *) clause; + RelOptInfo *crel = find_base_rel(root, cexpr->cvarno); + + if (crel->tuples > 0) + s1 = 1.0 / crel->tuples; + } else if (IsA(clause, RelabelType)) { /* Not sure this case is needed, but it can't hurt */ diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index a4d03e9f8f..f76c778998 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -54,7 +54,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.184 2007/06/05 21:31:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.185 2007/06/11 01:16:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -770,6 +770,7 @@ cost_tidscan(Path *path, PlannerInfo *root, Cost startup_cost = 0; Cost run_cost = 0; Cost cpu_per_tuple; + QualCost tid_qual_cost; int ntuples; ListCell *l; @@ -799,12 +800,20 @@ cost_tidscan(Path *path, PlannerInfo *root, } } + /* + * The TID qual expressions will be computed once, any other baserestrict + * quals once per retrived tuple. + */ + cost_qual_eval(&tid_qual_cost, tidquals, root); + /* disk costs --- assume each tuple on a different page */ run_cost += random_page_cost * ntuples; /* CPU costs */ - startup_cost += baserel->baserestrictcost.startup; - cpu_per_tuple = cpu_tuple_cost + baserel->baserestrictcost.per_tuple; + startup_cost += baserel->baserestrictcost.startup + + tid_qual_cost.per_tuple; + cpu_per_tuple = cpu_tuple_cost + baserel->baserestrictcost.per_tuple - + tid_qual_cost.per_tuple; run_cost += cpu_per_tuple * ntuples; path->startup_cost = startup_cost; @@ -1991,6 +2000,11 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context) cpu_operator_cost; } } + else if (IsA(node, CurrentOfExpr)) + { + /* This is noticeably more expensive than a typical operator */ + context->total.per_tuple += 100 * cpu_operator_cost; + } else if (IsA(node, SubLink)) { /* This routine should not be applied to un-planned expressions */ diff --git a/src/backend/optimizer/path/tidpath.c b/src/backend/optimizer/path/tidpath.c index 2470493708..84564dde73 100644 --- a/src/backend/optimizer/path/tidpath.c +++ b/src/backend/optimizer/path/tidpath.c @@ -12,6 +12,12 @@ * this allows * WHERE ctid IN (tid1, tid2, ...) * + * We also support "WHERE CURRENT OF cursor" conditions (CurrentOfExpr), + * which amount to "CTID = run-time-determined-TID". These could in + * theory be translated to a simple comparison of CTID to the result of + * a function, but in practice it works better to keep the special node + * representation all the way through to execution. + * * There is currently no special support for joins involving CTID; in * particular nothing corresponding to best_inner_indexscan(). Since it's * not very useful to store TIDs of one table in another table, there @@ -24,7 +30,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/tidpath.c,v 1.29 2007/01/05 22:19:31 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/tidpath.c,v 1.30 2007/06/11 01:16:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -174,6 +180,12 @@ TidQualFromExpr(Node *expr, int varno) if (IsTidEqualAnyClause((ScalarArrayOpExpr *) expr, varno)) rlst = list_make1(expr); } + else if (expr && IsA(expr, CurrentOfExpr)) + { + /* another base case: check for CURRENT OF on this rel */ + if (((CurrentOfExpr *) expr)->cvarno == varno) + rlst = list_make1(expr); + } else if (and_clause(expr)) { foreach(l, ((BoolExpr *) expr)->args) |
