aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>1999-11-23 20:07:06 +0000
committerBruce Momjian <bruce@momjian.us>1999-11-23 20:07:06 +0000
commit6f9ff92cc0ff6a07d2fe38abe044286ee98d44a0 (patch)
tree797395e647f1e8a741214d5eaafb9ee66a64c462 /src/backend/optimizer/path
parent54ffd4677aaf56e928af9e3f689297d6c06d1fe9 (diff)
downloadpostgresql-6f9ff92cc0ff6a07d2fe38abe044286ee98d44a0.tar.gz
postgresql-6f9ff92cc0ff6a07d2fe38abe044286ee98d44a0.zip
Tid access method feature from Hiroshi Inoue, Inoue@tpf.co.jp
Diffstat (limited to 'src/backend/optimizer/path')
-rw-r--r--src/backend/optimizer/path/Makefile5
-rw-r--r--src/backend/optimizer/path/allpaths.c9
-rw-r--r--src/backend/optimizer/path/costsize.c26
-rw-r--r--src/backend/optimizer/path/tidpath.c296
4 files changed, 331 insertions, 5 deletions
diff --git a/src/backend/optimizer/path/Makefile b/src/backend/optimizer/path/Makefile
index cdc401b8310..5e903ce666d 100644
--- a/src/backend/optimizer/path/Makefile
+++ b/src/backend/optimizer/path/Makefile
@@ -4,7 +4,7 @@
# Makefile for optimizer/path
#
# IDENTIFICATION
-# $Header: /cvsroot/pgsql/src/backend/optimizer/path/Makefile,v 1.9 1999/08/16 02:17:50 tgl Exp $
+# $Header: /cvsroot/pgsql/src/backend/optimizer/path/Makefile,v 1.10 1999/11/23 20:06:54 momjian Exp $
#
#-------------------------------------------------------------------------
@@ -14,7 +14,8 @@ include ../../../Makefile.global
CFLAGS += -I../..
OBJS = allpaths.o clausesel.o costsize.o indxpath.o \
- joinpath.o joinrels.o orindxpath.o pathkeys.o prune.o
+ joinpath.o joinrels.o orindxpath.o pathkeys.o prune.o \
+ tidpath.o
all: SUBSYS.o
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 23c759bd6e6..3cc8466f77b 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.53 1999/08/16 02:17:50 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.54 1999/11/23 20:06:54 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -108,9 +108,14 @@ set_base_rel_pathlist(Query *root, List *rels)
List *sequential_scan_list;
List *rel_index_scan_list;
List *or_index_scan_list;
+ List *tidscan_pathlist;
sequential_scan_list = lcons(create_seqscan_path(rel), NIL);
-
+ /* Tid Scan Pathlist add */
+ tidscan_pathlist = create_tidscan_paths(root, rel);
+ if (tidscan_pathlist)
+ sequential_scan_list = nconc(sequential_scan_list,
+ tidscan_pathlist);
rel_index_scan_list = create_index_paths(root,
rel,
indices,
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index fcf462b83eb..99ee42cf8c7 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -18,7 +18,7 @@
* Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.45 1999/08/22 20:14:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.46 1999/11/23 20:06:54 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -59,6 +59,7 @@ bool _enable_sort_ = true;
bool _enable_nestloop_ = true;
bool _enable_mergejoin_ = true;
bool _enable_hashjoin_ = true;
+bool _enable_tidscan_ = true;
Cost _cpu_page_weight_ = _CPU_PAGE_WEIGHT_;
Cost _cpu_index_page_weight_ = _CPU_INDEX_PAGE_WEIGHT_;
@@ -175,6 +176,29 @@ cost_index(Oid indexid,
}
/*
+ * cost_tidscan
+ * Determines and returns the cost of scanning a relation using tid-s.
+ *
+ * disk = number of tids
+ * cpu = *CPU-PAGE-WEIGHT* * number_of_tids
+ *
+ * Returns a flonum.
+ *
+ */
+Cost
+cost_tidscan(List *tideval)
+{
+ Cost temp = 0;
+
+ if (!_enable_tidscan_)
+ temp += _disable_cost_;
+
+ temp += (1.0 + _cpu_page_weight_) * length(tideval);
+
+ return temp;
+}
+
+/*
* cost_sort
* Determines and returns the cost of sorting a relation by considering
* the cost of doing an external sort: XXX this is probably too low
diff --git a/src/backend/optimizer/path/tidpath.c b/src/backend/optimizer/path/tidpath.c
new file mode 100644
index 00000000000..9e618f7a872
--- /dev/null
+++ b/src/backend/optimizer/path/tidpath.c
@@ -0,0 +1,296 @@
+/*-------------------------------------------------------------------------
+ *
+ * tidpath.c
+ * Routines to determine which tids are usable for scanning a
+ * given relation, and create TidPaths accordingly.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/tidpath.c,v 1.1 1999/11/23 20:06:55 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <math.h>
+
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "catalog/catname.h"
+#include "catalog/pg_amop.h"
+#include "catalog/pg_operator.h"
+#include "executor/executor.h"
+#include "nodes/makefuncs.h"
+#include "nodes/nodeFuncs.h"
+#include "optimizer/clauses.h"
+#include "optimizer/cost.h"
+#include "optimizer/pathnode.h"
+#include "optimizer/paths.h"
+#include "optimizer/plancat.h"
+#include "optimizer/restrictinfo.h"
+#include "parser/parse_coerce.h"
+#include "parser/parse_expr.h"
+#include "parser/parse_oper.h"
+#include "parser/parsetree.h"
+#include "utils/lsyscache.h"
+
+static List *create_tidscan_joinpaths(RelOptInfo *);
+static List *TidqualFromRestrictinfo(List *relids, List * restrictinfo);
+static bool isEvaluable(int varno, Node *node);
+static Node *TidequalClause(int varno, Expr *node);
+static List *TidqualFromExpr(int varno, Expr *expr);
+
+static
+bool isEvaluable(int varno, Node *node)
+{
+ List *lst;
+ Expr *expr;
+
+ if (IsA(node, Const)) return true;
+ if (IsA(node, Param)) return true;
+ if (IsA(node, Var))
+ {
+ Var *var = (Var *)node;
+
+ if (var->varno == varno)
+ return false;
+ return true;
+ }
+ if (!is_funcclause(node)) return false;
+ expr = (Expr *)node;
+ foreach (lst, expr->args)
+ {
+ if (!isEvaluable(varno, lfirst(lst)))
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * The 2nd parameter should be an opclause
+ * 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)
+{
+ Node *rnode = 0, *arg1, *arg2, *arg;
+ Oper *oper;
+ Var *var;
+ Const *aconst;
+ Param *param;
+ Expr *expr;
+
+ if (!node->oper) return rnode;
+ if (!node->args) 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;
+ if (IsA(arg1, Var))
+ {
+ var = (Var *) arg1;
+ if (var->varno == varno &&
+ var->varattno == SelfItemPointerAttributeNumber &&
+ var->vartype == TIDOID)
+ arg = arg2;
+ else if (var->varnoold == varno &&
+ var->varoattno == SelfItemPointerAttributeNumber &&
+ var->vartype == TIDOID)
+ arg = arg2;
+ }
+ if ((!arg) && IsA(arg2, Var))
+ {
+ var = (Var *) arg2;
+ if (var->varno == varno &&
+ var->varattno == SelfItemPointerAttributeNumber &&
+ var->vartype == TIDOID)
+ arg = arg1;
+ }
+ if (!arg)
+ return rnode;
+ switch (nodeTag(arg))
+ {
+ case T_Const:
+ aconst = (Const *) arg;
+ if (aconst->consttype != TIDOID)
+ return rnode;
+ if (aconst->constbyval)
+ return rnode;
+ rnode = arg;
+ break;
+ case T_Param:
+ param = (Param *) arg;
+ if (param->paramtype != TIDOID)
+ return rnode;
+ rnode = arg;
+ break;
+ case T_Var:
+ var = (Var *) arg;
+ if (var->varno == varno ||
+ var->vartype != TIDOID)
+ return rnode;
+ rnode = arg;
+ break;
+ case T_Expr:
+ expr = (Expr *) arg;
+ if (expr->typeOid != TIDOID) return rnode;
+ if (expr->opType != FUNC_EXPR) return rnode;
+ if (isEvaluable(varno, (Node *)expr))
+ rnode = arg;
+ break;
+ default:
+ break;
+ }
+ return rnode;
+}
+
+/*
+ * Extract the list of CTID values from a specified expr node.
+ * When the expr node is an or_clause,we try to extract CTID
+ * values from all member nodes. However we would discard them
+ * all if we couldn't extract CTID values from a member node.
+ * When the expr node is an and_clause,we return the list of
+ * CTID values if we could extract the CTID values from a member
+ * node.
+ */
+static
+List *TidqualFromExpr(int varno, Expr *expr)
+{
+ List *rlst = NIL, *lst, *frtn;
+ Node *node = (Node *) expr, *rnode;
+
+ if (is_opclause(node))
+ {
+ rnode = TidequalClause(varno, expr);
+ if (rnode)
+ {
+ rlst = lcons(rnode, rlst);
+ }
+ }
+ else if (and_clause(node))
+ {
+ foreach (lst, expr->args)
+ {
+ node = lfirst(lst);
+ if (!IsA(node, Expr))
+ continue;
+ rlst = TidqualFromExpr(varno, (Expr *)node);
+ if (rlst)
+ break;
+ }
+ }
+ else if (or_clause(node))
+ {
+ foreach (lst, expr->args)
+ {
+ node = lfirst(lst);
+ if (IsA(node, Expr) &&
+ (frtn = TidqualFromExpr(varno, (Expr *)node)) )
+ {
+ rlst = nconc(rlst, frtn);
+ }
+ else
+ {
+ if (rlst)
+ freeList(rlst);
+ rlst = NIL;
+ break;
+ }
+ }
+ }
+ return rlst;
+}
+
+static
+List *TidqualFromRestrictinfo(List *relids, List * restrictinfo)
+{
+ List *lst, *rlst = NIL;
+ int varno;
+ Node *node;
+ Expr *expr;
+
+ if (length(relids)>1) return NIL;
+ varno = (int)lfirst(relids);
+ foreach (lst, restrictinfo)
+ {
+ node = lfirst(lst);
+ if (!IsA(node, RestrictInfo)) continue;
+ expr = ((RestrictInfo *)node)->clause;
+ rlst = TidqualFromExpr(varno, expr);
+ if (rlst)
+ {
+ break;
+ }
+ }
+ return rlst;
+}
+
+/*
+ * create_tidscan_joinpaths
+ * Creates a path corresponding to a tid_direct scan, returning the
+ * pathnode.
+ *
+ */
+List *
+create_tidscan_joinpaths(RelOptInfo *rel)
+{
+ List *rlst = NIL, *lst;
+ TidPath *pathnode = (TidPath *)0;
+ List *restinfo, *tideval;
+
+ foreach (lst, rel->joininfo)
+ {
+ JoinInfo *joininfo = (JoinInfo *)lfirst(lst);
+ restinfo = joininfo->jinfo_restrictinfo;
+ tideval = TidqualFromRestrictinfo(rel->relids, restinfo);
+ if (tideval && length(tideval) == 1)
+ {
+ pathnode = makeNode(TidPath);
+
+ pathnode->path.pathtype = T_TidScan;
+ pathnode->path.parent = rel;
+ pathnode->path.path_cost = 0.0;
+ pathnode->path.pathkeys = NIL;
+
+ pathnode->path.path_cost = cost_tidscan(tideval);
+ pathnode->tideval = tideval;
+ /*
+ pathnode->tideval = copyObject(tideval);
+ freeList(tideval);
+ */
+ pathnode->unjoined_relids = joininfo->unjoined_relids;
+ rlst = lappend(rlst, pathnode);
+ }
+ }
+ rel->innerjoin = nconc(rel->innerjoin, rlst);
+ return rlst;
+}
+
+/*
+ * create_tidscan_paths
+ * Creates a path corresponding to a tid direct scan, returning the
+ * pathnode List.
+ *
+ */
+List *
+create_tidscan_paths(Query *root, RelOptInfo *rel)
+{
+ List *rlst = NIL;
+ TidPath *pathnode = (TidPath *)0;
+ List *tideval = TidqualFromRestrictinfo(rel->relids, rel->restrictinfo);
+
+ if (tideval)
+ pathnode = create_tidscan_path(rel, tideval);
+ if (pathnode)
+ rlst = lcons(pathnode, rlst);
+ create_tidscan_joinpaths(rel);
+
+ return rlst;
+}