Commit 4a8c5d03 authored by Tom Lane's avatar Tom Lane

Create executor and planner-backend support for decoupled heap and index

scans, using in-memory tuple ID bitmaps as the intermediary.  The planner
frontend (path creation and cost estimation) is not there yet, so none
of this code can be executed.  I have tested it using some hacked planner
code that is far too ugly to see the light of day, however.  Committing
now so that the bulk of the infrastructure changes go in before the tree
drifts under me.
parent 04ce41ca
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.132 2005/04/16 20:07:35 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.133 2005/04/19 22:35:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -423,6 +423,12 @@ explain_outNode(StringInfo str,
case T_Append:
pname = "Append";
break;
case T_BitmapAnd:
pname = "BitmapAnd";
break;
case T_BitmapOr:
pname = "BitmapOr";
break;
case T_NestLoop:
switch (((NestLoop *) plan)->join.jointype)
{
......@@ -498,6 +504,12 @@ explain_outNode(StringInfo str,
case T_IndexScan:
pname = "Index Scan";
break;
case T_BitmapIndexScan:
pname = "Bitmap Index Scan";
break;
case T_BitmapHeapScan:
pname = "Bitmap Heap Scan";
break;
case T_TidScan:
pname = "Tid Scan";
break;
......@@ -586,6 +598,7 @@ explain_outNode(StringInfo str,
}
/* FALL THRU */
case T_SeqScan:
case T_BitmapHeapScan:
case T_TidScan:
if (((Scan *) plan)->scanrelid > 0)
{
......@@ -606,6 +619,10 @@ explain_outNode(StringInfo str,
quote_identifier(rte->eref->aliasname));
}
break;
case T_BitmapIndexScan:
appendStringInfo(str, " on %s",
quote_identifier(get_rel_name(((BitmapIndexScan *) plan)->indxid)));
break;
case T_SubqueryScan:
if (((Scan *) plan)->scanrelid > 0)
{
......@@ -696,6 +713,21 @@ explain_outNode(StringInfo str,
outer_plan,
str, indent, es);
break;
case T_BitmapIndexScan:
show_scan_qual(((BitmapIndexScan *) plan)->indxqualorig, false,
"Index Cond",
((Scan *) plan)->scanrelid,
outer_plan,
str, indent, es);
break;
case T_BitmapHeapScan:
/* XXX do we want to show this in production? */
show_scan_qual(((BitmapHeapScan *) plan)->bitmapqualorig, false,
"Recheck Cond",
((Scan *) plan)->scanrelid,
outer_plan,
str, indent, es);
/* FALL THRU */
case T_SeqScan:
case T_TidScan:
case T_SubqueryScan:
......@@ -857,6 +889,54 @@ explain_outNode(StringInfo str,
}
}
if (IsA(plan, BitmapAnd))
{
BitmapAnd *bitmapandplan = (BitmapAnd *) plan;
BitmapAndState *bitmapandstate = (BitmapAndState *) planstate;
ListCell *lst;
int j;
j = 0;
foreach(lst, bitmapandplan->bitmapplans)
{
Plan *subnode = (Plan *) lfirst(lst);
for (i = 0; i < indent; i++)
appendStringInfo(str, " ");
appendStringInfo(str, " -> ");
explain_outNode(str, subnode,
bitmapandstate->bitmapplans[j],
NULL,
indent + 3, es);
j++;
}
}
if (IsA(plan, BitmapOr))
{
BitmapOr *bitmaporplan = (BitmapOr *) plan;
BitmapOrState *bitmaporstate = (BitmapOrState *) planstate;
ListCell *lst;
int j;
j = 0;
foreach(lst, bitmaporplan->bitmapplans)
{
Plan *subnode = (Plan *) lfirst(lst);
for (i = 0; i < indent; i++)
appendStringInfo(str, " ");
appendStringInfo(str, " -> ");
explain_outNode(str, subnode,
bitmaporstate->bitmapplans[j],
NULL,
indent + 3, es);
j++;
}
}
if (IsA(plan, SubqueryScan))
{
SubqueryScan *subqueryscan = (SubqueryScan *) plan;
......
......@@ -4,7 +4,7 @@
# Makefile for executor
#
# IDENTIFICATION
# $PostgreSQL: pgsql/src/backend/executor/Makefile,v 1.22 2003/11/29 19:51:48 pgsql Exp $
# $PostgreSQL: pgsql/src/backend/executor/Makefile,v 1.23 2005/04/19 22:35:11 tgl Exp $
#
#-------------------------------------------------------------------------
......@@ -14,7 +14,9 @@ include $(top_builddir)/src/Makefile.global
OBJS = execAmi.o execGrouping.o execJunk.o execMain.o \
execProcnode.o execQual.o execScan.o execTuples.o \
execUtils.o functions.o instrument.o nodeAppend.o nodeAgg.o nodeHash.o \
execUtils.o functions.o instrument.o nodeAppend.o nodeAgg.o \
nodeBitmapAnd.o nodeBitmapOr.o \
nodeBitmapHeapscan.o nodeBitmapIndexscan.o nodeHash.o \
nodeHashjoin.o nodeIndexscan.o nodeMaterial.o nodeMergejoin.o \
nodeNestloop.o nodeFunctionscan.o nodeResult.o nodeSeqscan.o \
nodeSetOp.o nodeSort.o nodeUnique.o nodeLimit.o nodeGroup.o \
......
......@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.82 2004/12/31 21:59:45 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.83 2005/04/19 22:35:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -19,6 +19,10 @@
#include "executor/instrument.h"
#include "executor/nodeAgg.h"
#include "executor/nodeAppend.h"
#include "executor/nodeBitmapAnd.h"
#include "executor/nodeBitmapHeapscan.h"
#include "executor/nodeBitmapIndexscan.h"
#include "executor/nodeBitmapOr.h"
#include "executor/nodeFunctionscan.h"
#include "executor/nodeGroup.h"
#include "executor/nodeGroup.h"
......@@ -107,6 +111,14 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
ExecReScanAppend((AppendState *) node, exprCtxt);
break;
case T_BitmapAndState:
ExecReScanBitmapAnd((BitmapAndState *) node, exprCtxt);
break;
case T_BitmapOrState:
ExecReScanBitmapOr((BitmapOrState *) node, exprCtxt);
break;
case T_SeqScanState:
ExecSeqReScan((SeqScanState *) node, exprCtxt);
break;
......@@ -115,6 +127,14 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
ExecIndexReScan((IndexScanState *) node, exprCtxt);
break;
case T_BitmapIndexScanState:
ExecBitmapIndexReScan((BitmapIndexScanState *) node, exprCtxt);
break;
case T_BitmapHeapScanState:
ExecBitmapHeapReScan((BitmapHeapScanState *) node, exprCtxt);
break;
case T_TidScanState:
ExecTidReScan((TidScanState *) node, exprCtxt);
break;
......@@ -380,6 +400,7 @@ ExecMayReturnRawTuples(PlanState *node)
/* Table scan nodes */
case T_SeqScanState:
case T_IndexScanState:
case T_BitmapHeapScanState:
case T_TidScanState:
case T_SubqueryScanState:
case T_FunctionScanState:
......
......@@ -12,7 +12,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execProcnode.c,v 1.49 2005/04/16 20:07:35 tgl Exp $
* $PostgreSQL: pgsql/src/backend/executor/execProcnode.c,v 1.50 2005/04/19 22:35:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -81,6 +81,10 @@
#include "executor/instrument.h"
#include "executor/nodeAgg.h"
#include "executor/nodeAppend.h"
#include "executor/nodeBitmapAnd.h"
#include "executor/nodeBitmapHeapscan.h"
#include "executor/nodeBitmapIndexscan.h"
#include "executor/nodeBitmapOr.h"
#include "executor/nodeFunctionscan.h"
#include "executor/nodeGroup.h"
#include "executor/nodeHash.h"
......@@ -140,6 +144,14 @@ ExecInitNode(Plan *node, EState *estate)
result = (PlanState *) ExecInitAppend((Append *) node, estate);
break;
case T_BitmapAnd:
result = (PlanState *) ExecInitBitmapAnd((BitmapAnd *) node, estate);
break;
case T_BitmapOr:
result = (PlanState *) ExecInitBitmapOr((BitmapOr *) node, estate);
break;
/*
* scan nodes
*/
......@@ -151,6 +163,14 @@ ExecInitNode(Plan *node, EState *estate)
result = (PlanState *) ExecInitIndexScan((IndexScan *) node, estate);
break;
case T_BitmapIndexScan:
result = (PlanState *) ExecInitBitmapIndexScan((BitmapIndexScan *) node, estate);
break;
case T_BitmapHeapScan:
result = (PlanState *) ExecInitBitmapHeapScan((BitmapHeapScan *) node, estate);
break;
case T_TidScan:
result = (PlanState *) ExecInitTidScan((TidScan *) node, estate);
break;
......@@ -290,6 +310,10 @@ ExecProcNode(PlanState *node)
result = ExecAppend((AppendState *) node);
break;
/* BitmapAndState does not yield tuples */
/* BitmapOrState does not yield tuples */
/*
* scan nodes
*/
......@@ -301,6 +325,12 @@ ExecProcNode(PlanState *node)
result = ExecIndexScan((IndexScanState *) node);
break;
/* BitmapIndexScanState does not yield tuples */
case T_BitmapHeapScanState:
result = ExecBitmapHeapScan((BitmapHeapScanState *) node);
break;
case T_TidScanState:
result = ExecTidScan((TidScanState *) node);
break;
......@@ -409,6 +439,18 @@ MultiExecProcNode(PlanState *node)
result = MultiExecHash((HashState *) node);
break;
case T_BitmapIndexScanState:
result = MultiExecBitmapIndexScan((BitmapIndexScanState *) node);
break;
case T_BitmapAndState:
result = MultiExecBitmapAnd((BitmapAndState *) node);
break;
case T_BitmapOrState:
result = MultiExecBitmapOr((BitmapOrState *) node);
break;
default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
result = NULL;
......@@ -442,6 +484,12 @@ ExecCountSlotsNode(Plan *node)
case T_Append:
return ExecCountSlotsAppend((Append *) node);
case T_BitmapAnd:
return ExecCountSlotsBitmapAnd((BitmapAnd *) node);
case T_BitmapOr:
return ExecCountSlotsBitmapOr((BitmapOr *) node);
/*
* scan nodes
*/
......@@ -451,6 +499,12 @@ ExecCountSlotsNode(Plan *node)
case T_IndexScan:
return ExecCountSlotsIndexScan((IndexScan *) node);
case T_BitmapIndexScan:
return ExecCountSlotsBitmapIndexScan((BitmapIndexScan *) node);
case T_BitmapHeapScan:
return ExecCountSlotsBitmapHeapScan((BitmapHeapScan *) node);
case T_TidScan:
return ExecCountSlotsTidScan((TidScan *) node);
......@@ -554,6 +608,14 @@ ExecEndNode(PlanState *node)
ExecEndAppend((AppendState *) node);
break;
case T_BitmapAndState:
ExecEndBitmapAnd((BitmapAndState *) node);
break;
case T_BitmapOrState:
ExecEndBitmapOr((BitmapOrState *) node);
break;
/*
* scan nodes
*/
......@@ -565,6 +627,14 @@ ExecEndNode(PlanState *node)
ExecEndIndexScan((IndexScanState *) node);
break;
case T_BitmapIndexScanState:
ExecEndBitmapIndexScan((BitmapIndexScanState *) node);
break;
case T_BitmapHeapScanState:
ExecEndBitmapHeapScan((BitmapHeapScanState *) node);
break;
case T_TidScanState:
ExecEndTidScan((TidScanState *) node);
break;
......
/*-------------------------------------------------------------------------
*
* nodeBitmapAnd.c
* routines to handle BitmapAnd nodes.
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapAnd.c,v 1.1 2005/04/19 22:35:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* INTERFACE ROUTINES
* ExecInitBitmapAnd - initialize the BitmapAnd node
* MultiExecBitmapAnd - retrieve the result bitmap from the node
* ExecEndBitmapAnd - shut down the BitmapAnd node
* ExecReScanBitmapAnd - rescan the BitmapAnd node
*
* NOTES
* BitmapAnd nodes don't make use of their left and right
* subtrees, rather they maintain a list of subplans,
* much like Append nodes. The logic is much simpler than
* Append, however, since we needn't cope with forward/backward
* execution.
*/
#include "postgres.h"
#include "executor/execdebug.h"
#include "executor/instrument.h"
#include "executor/nodeBitmapAnd.h"
/* ----------------------------------------------------------------
* ExecInitBitmapAnd
*
* Begin all of the subscans of the BitmapAnd node.
* ----------------------------------------------------------------
*/
BitmapAndState *
ExecInitBitmapAnd(BitmapAnd *node, EState *estate)
{
BitmapAndState *bitmapandstate = makeNode(BitmapAndState);
PlanState **bitmapplanstates;
int nplans;
int i;
Plan *initNode;
CXT1_printf("ExecInitBitmapAnd: context is %d\n", CurrentMemoryContext);
/*
* Set up empty vector of subplan states
*/
nplans = list_length(node->bitmapplans);
bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
/*
* create new BitmapAndState for our BitmapAnd node
*/
bitmapandstate->ps.plan = (Plan *) node;
bitmapandstate->ps.state = estate;
bitmapandstate->bitmapplans = bitmapplanstates;
bitmapandstate->nplans = nplans;
/*
* Miscellaneous initialization
*
* BitmapAnd plans don't have expression contexts because they never call
* ExecQual or ExecProject. They don't need any tuple slots either.
*/
#define BITMAPAND_NSLOTS 0
/*
* call ExecInitNode on each of the plans to be executed and save the
* results into the array "bitmapplanstates".
*/
for (i = 0; i < nplans; i++)
{
initNode = (Plan *) list_nth(node->bitmapplans, i);
bitmapplanstates[i] = ExecInitNode(initNode, estate);
}
return bitmapandstate;
}
int
ExecCountSlotsBitmapAnd(BitmapAnd *node)
{
ListCell *plan;
int nSlots = 0;
foreach(plan, node->bitmapplans)
nSlots += ExecCountSlotsNode((Plan *) lfirst(plan));
return nSlots + BITMAPAND_NSLOTS;
}
/* ----------------------------------------------------------------
* MultiExecBitmapAnd
* ----------------------------------------------------------------
*/
Node *
MultiExecBitmapAnd(BitmapAndState *node)
{
PlanState **bitmapplans;
int nplans;
int i;
TIDBitmap *result = NULL;
/* must provide our own instrumentation support */
if (node->ps.instrument)
InstrStartNode(node->ps.instrument);
/*
* get information from the node
*/
bitmapplans = node->bitmapplans;
nplans = node->nplans;
/*
* Scan all the subplans and AND their result bitmaps
*/
for (i = 0; i < nplans; i++)
{
PlanState *subnode = bitmapplans[i];
TIDBitmap *subresult;
subresult = (TIDBitmap *) MultiExecProcNode(subnode);
if (!subresult || !IsA(subresult, TIDBitmap))
elog(ERROR, "unrecognized result from subplan");
if (result == NULL)
result = subresult; /* first subplan */
else
{
tbm_intersect(result, subresult);
tbm_free(subresult);
}
}
if (result == NULL)
elog(ERROR, "BitmapAnd doesn't support zero inputs");
/* must provide our own instrumentation support */
if (node->ps.instrument)
InstrStopNodeMulti(node->ps.instrument, 0 /* XXX */);
return (Node *) result;
}
/* ----------------------------------------------------------------
* ExecEndBitmapAnd
*
* Shuts down the subscans of the BitmapAnd node.
*
* Returns nothing of interest.
* ----------------------------------------------------------------
*/
void
ExecEndBitmapAnd(BitmapAndState *node)
{
PlanState **bitmapplans;
int nplans;
int i;
/*
* get information from the node
*/
bitmapplans = node->bitmapplans;
nplans = node->nplans;
/*
* shut down each of the subscans (that we've initialized)
*/
for (i = 0; i < nplans; i++)
{
if (bitmapplans[i])
ExecEndNode(bitmapplans[i]);
}
}
void
ExecReScanBitmapAnd(BitmapAndState *node, ExprContext *exprCtxt)
{
int i;
for (i = 0; i < node->nplans; i++)
{
PlanState *subnode = node->bitmapplans[i];
/*
* ExecReScan doesn't know about my subplans, so I have to do
* changed-parameter signaling myself.
*/
if (node->ps.chgParam != NULL)
UpdateChangedParamSet(subnode, node->ps.chgParam);
/*
* Always rescan the inputs immediately, to ensure we can pass down
* any outer tuple that might be used in index quals.
*/
ExecReScan(subnode, exprCtxt);
}
}
This diff is collapsed.
This diff is collapsed.
/*-------------------------------------------------------------------------
*
* nodeBitmapOr.c
* routines to handle BitmapOr nodes.
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapOr.c,v 1.1 2005/04/19 22:35:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* INTERFACE ROUTINES
* ExecInitBitmapOr - initialize the BitmapOr node
* MultiExecBitmapOr - retrieve the result bitmap from the node
* ExecEndBitmapOr - shut down the BitmapOr node
* ExecReScanBitmapOr - rescan the BitmapOr node
*
* NOTES
* BitmapOr nodes don't make use of their left and right
* subtrees, rather they maintain a list of subplans,
* much like Append nodes. The logic is much simpler than
* Append, however, since we needn't cope with forward/backward
* execution.
*/
#include "postgres.h"
#include "executor/execdebug.h"
#include "executor/instrument.h"
#include "executor/nodeBitmapOr.h"
/* ----------------------------------------------------------------
* ExecInitBitmapOr
*
* Begin all of the subscans of the BitmapOr node.
* ----------------------------------------------------------------
*/
BitmapOrState *
ExecInitBitmapOr(BitmapOr *node, EState *estate)
{
BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
PlanState **bitmapplanstates;
int nplans;
int i;
Plan *initNode;
CXT1_printf("ExecInitBitmapOr: context is %d\n", CurrentMemoryContext);
/*
* Set up empty vector of subplan states
*/
nplans = list_length(node->bitmapplans);
bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
/*
* create new BitmapOrState for our BitmapOr node
*/
bitmaporstate->ps.plan = (Plan *) node;
bitmaporstate->ps.state = estate;
bitmaporstate->bitmapplans = bitmapplanstates;
bitmaporstate->nplans = nplans;
/*
* Miscellaneous initialization
*
* BitmapOr plans don't have expression contexts because they never call
* ExecQual or ExecProject. They don't need any tuple slots either.
*/
#define BITMAPOR_NSLOTS 0
/*
* call ExecInitNode on each of the plans to be executed and save the
* results into the array "bitmapplanstates".
*/
for (i = 0; i < nplans; i++)
{
initNode = (Plan *) list_nth(node->bitmapplans, i);
bitmapplanstates[i] = ExecInitNode(initNode, estate);
}
return bitmaporstate;
}
int
ExecCountSlotsBitmapOr(BitmapOr *node)
{
ListCell *plan;
int nSlots = 0;
foreach(plan, node->bitmapplans)
nSlots += ExecCountSlotsNode((Plan *) lfirst(plan));
return nSlots + BITMAPOR_NSLOTS;
}
/* ----------------------------------------------------------------
* MultiExecBitmapOr
* ----------------------------------------------------------------
*/
Node *
MultiExecBitmapOr(BitmapOrState *node)
{
PlanState **bitmapplans;
int nplans;
int i;
TIDBitmap *result = NULL;
/* must provide our own instrumentation support */
if (node->ps.instrument)
InstrStartNode(node->ps.instrument);
/*
* get information from the node
*/
bitmapplans = node->bitmapplans;
nplans = node->nplans;
/*
* Scan all the subplans and OR their result bitmaps
*/
for (i = 0; i < nplans; i++)
{
PlanState *subnode = bitmapplans[i];
TIDBitmap *subresult;
subresult = (TIDBitmap *) MultiExecProcNode(subnode);
if (!subresult || !IsA(subresult, TIDBitmap))
elog(ERROR, "unrecognized result from subplan");
if (result == NULL)
result = subresult; /* first subplan */
else
{
tbm_union(result, subresult);
tbm_free(subresult);
}
}
/* We could return an empty result set here? */
if (result == NULL)
elog(ERROR, "BitmapOr doesn't support zero inputs");
/* must provide our own instrumentation support */
if (node->ps.instrument)
InstrStopNodeMulti(node->ps.instrument, 0 /* XXX */);
return (Node *) result;
}
/* ----------------------------------------------------------------
* ExecEndBitmapOr
*
* Shuts down the subscans of the BitmapOr node.
*
* Returns nothing of interest.
* ----------------------------------------------------------------
*/
void
ExecEndBitmapOr(BitmapOrState *node)
{
PlanState **bitmapplans;
int nplans;
int i;
/*
* get information from the node
*/
bitmapplans = node->bitmapplans;
nplans = node->nplans;
/*
* shut down each of the subscans (that we've initialized)
*/
for (i = 0; i < nplans; i++)
{
if (bitmapplans[i])
ExecEndNode(bitmapplans[i]);
}
}
void
ExecReScanBitmapOr(BitmapOrState *node, ExprContext *exprCtxt)
{
int i;
for (i = 0; i < node->nplans; i++)
{
PlanState *subnode = node->bitmapplans[i];
/*
* ExecReScan doesn't know about my subplans, so I have to do
* changed-parameter signaling myself.
*/
if (node->ps.chgParam != NULL)
UpdateChangedParamSet(subnode, node->ps.chgParam);
/*
* Always rescan the inputs immediately, to ensure we can pass down
* any outer tuple that might be used in index quals.
*/
ExecReScan(subnode, exprCtxt);
}
}
......@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.301 2005/04/07 01:51:38 neilc Exp $
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.302 2005/04/19 22:35:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -148,6 +148,48 @@ _copyAppend(Append *from)
return newnode;
}
/*
* _copyBitmapAnd
*/
static BitmapAnd *
_copyBitmapAnd(BitmapAnd *from)
{
BitmapAnd *newnode = makeNode(BitmapAnd);
/*
* copy node superclass fields
*/
CopyPlanFields((Plan *) from, (Plan *) newnode);
/*
* copy remainder of node
*/
COPY_NODE_FIELD(bitmapplans);
return newnode;
}
/*
* _copyBitmapOr
*/
static BitmapOr *
_copyBitmapOr(BitmapOr *from)
{
BitmapOr *newnode = makeNode(BitmapOr);
/*
* copy node superclass fields
*/
CopyPlanFields((Plan *) from, (Plan *) newnode);
/*
* copy remainder of node
*/
COPY_NODE_FIELD(bitmapplans);
return newnode;
}
/*
* CopyScanFields
......@@ -222,6 +264,52 @@ _copyIndexScan(IndexScan *from)
return newnode;
}
/*
* _copyBitmapIndexScan
*/
static BitmapIndexScan *
_copyBitmapIndexScan(BitmapIndexScan *from)
{
BitmapIndexScan *newnode = makeNode(BitmapIndexScan);
/*
* copy node superclass fields
*/
CopyScanFields((Scan *) from, (Scan *) newnode);
/*
* copy remainder of node
*/
COPY_SCALAR_FIELD(indxid);
COPY_NODE_FIELD(indxqual);
COPY_NODE_FIELD(indxqualorig);
COPY_NODE_FIELD(indxstrategy);
COPY_NODE_FIELD(indxsubtype);
return newnode;
}
/*
* _copyBitmapHeapScan
*/
static BitmapHeapScan *
_copyBitmapHeapScan(BitmapHeapScan *from)
{
BitmapHeapScan *newnode = makeNode(BitmapHeapScan);
/*
* copy node superclass fields
*/
CopyScanFields((Scan *) from, (Scan *) newnode);
/*
* copy remainder of node
*/
COPY_NODE_FIELD(bitmapqualorig);
return newnode;
}
/*
* _copyTidScan
*/
......@@ -2598,6 +2686,12 @@ copyObject(void *from)
case T_Append:
retval = _copyAppend(from);
break;
case T_BitmapAnd:
retval = _copyBitmapAnd(from);
break;
case T_BitmapOr:
retval = _copyBitmapOr(from);
break;
case T_Scan:
retval = _copyScan(from);
break;
......@@ -2607,6 +2701,12 @@ copyObject(void *from)
case T_IndexScan:
retval = _copyIndexScan(from);
break;
case T_BitmapIndexScan:
retval = _copyBitmapIndexScan(from);
break;
case T_BitmapHeapScan:
retval = _copyBitmapHeapScan(from);
break;
case T_TidScan:
retval = _copyTidScan(from);
break;
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.246 2005/04/06 16:34:05 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.247 2005/04/19 22:35:14 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
......@@ -308,6 +308,26 @@ _outAppend(StringInfo str, Append *node)
WRITE_BOOL_FIELD(isTarget);
}
static void
_outBitmapAnd(StringInfo str, BitmapAnd *node)
{
WRITE_NODE_TYPE("BITMAPAND");
_outPlanInfo(str, (Plan *) node);
WRITE_NODE_FIELD(bitmapplans);
}
static void
_outBitmapOr(StringInfo str, BitmapOr *node)
{
WRITE_NODE_TYPE("BITMAPOR");
_outPlanInfo(str, (Plan *) node);
WRITE_NODE_FIELD(bitmapplans);
}
static void
_outScan(StringInfo str, Scan *node)
{
......@@ -340,6 +360,30 @@ _outIndexScan(StringInfo str, IndexScan *node)
WRITE_ENUM_FIELD(indxorderdir, ScanDirection);
}
static void
_outBitmapIndexScan(StringInfo str, BitmapIndexScan *node)
{
WRITE_NODE_TYPE("BITMAPINDEXSCAN");
_outScanInfo(str, (Scan *) node);
WRITE_OID_FIELD(indxid);
WRITE_NODE_FIELD(indxqual);
WRITE_NODE_FIELD(indxqualorig);
WRITE_NODE_FIELD(indxstrategy);
WRITE_NODE_FIELD(indxsubtype);
}
static void
_outBitmapHeapScan(StringInfo str, BitmapHeapScan *node)
{
WRITE_NODE_TYPE("BITMAPHEAPSCAN");
_outScanInfo(str, (Scan *) node);
WRITE_NODE_FIELD(bitmapqualorig);
}
static void
_outTidScan(StringInfo str, TidScan *node)
{
......@@ -968,9 +1012,6 @@ _outPath(StringInfo str, Path *node)
_outPathInfo(str, (Path *) node);
}
/*
* IndexPath is a subclass of Path.
*/
static void
_outIndexPath(StringInfo str, IndexPath *node)
{
......@@ -986,6 +1027,18 @@ _outIndexPath(StringInfo str, IndexPath *node)
WRITE_FLOAT_FIELD(rows, "%.0f");
}
static void
_outBitmapHeapPath(StringInfo str, BitmapHeapPath *node)
{
WRITE_NODE_TYPE("BITMAPHEAPPATH");
_outPathInfo(str, (Path *) node);
WRITE_NODE_FIELD(bitmapqual);
WRITE_BOOL_FIELD(isjoininner);
WRITE_FLOAT_FIELD(rows, "%.0f");
}
static void
_outTidPath(StringInfo str, TidPath *node)
{
......@@ -1620,6 +1673,12 @@ _outNode(StringInfo str, void *obj)
case T_Append:
_outAppend(str, obj);
break;
case T_BitmapAnd:
_outBitmapAnd(str, obj);
break;
case T_BitmapOr:
_outBitmapOr(str, obj);
break;
case T_Scan:
_outScan(str, obj);
break;
......@@ -1629,6 +1688,12 @@ _outNode(StringInfo str, void *obj)
case T_IndexScan:
_outIndexScan(str, obj);
break;
case T_BitmapIndexScan:
_outBitmapIndexScan(str, obj);
break;
case T_BitmapHeapScan:
_outBitmapHeapScan(str, obj);
break;
case T_TidScan:
_outTidScan(str, obj);
break;
......@@ -1783,6 +1848,9 @@ _outNode(StringInfo str, void *obj)
case T_IndexPath:
_outIndexPath(str, obj);
break;
case T_BitmapHeapPath:
_outBitmapHeapPath(str, obj);
break;
case T_TidPath:
_outTidPath(str, obj);
break;
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/print.c,v 1.74 2005/04/06 16:34:05 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/print.c,v 1.75 2005/04/19 22:35:15 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
......@@ -493,12 +493,20 @@ plannode_type(Plan *p)
return "RESULT";
case T_Append:
return "APPEND";
case T_BitmapAnd:
return "BITMAPAND";
case T_BitmapOr:
return "BITMAPOR";
case T_Scan:
return "SCAN";
case T_SeqScan:
return "SEQSCAN";
case T_IndexScan:
return "INDEXSCAN";
case T_BitmapIndexScan:
return "BITMAPINDEXSCAN";
case T_BitmapHeapScan:
return "BITMAPHEAPSCAN";
case T_TidScan:
return "TIDSCAN";
case T_SubqueryScan:
......@@ -551,7 +559,8 @@ print_plan_recursive(Plan *p, Query *parsetree, int indentLevel, char *label)
p->startup_cost, p->total_cost,
p->plan_rows, p->plan_width);
if (IsA(p, Scan) ||
IsA(p, SeqScan))
IsA(p, SeqScan) ||
IsA(p, BitmapHeapScan))
{
RangeTblEntry *rte;
......@@ -584,27 +593,48 @@ print_plan_recursive(Plan *p, Query *parsetree, int indentLevel, char *label)
if (IsA(p, Append))
{
ListCell *l;
int whichplan = 0;
Append *appendplan = (Append *) p;
foreach(l, appendplan->appendplans)
{
Plan *subnode = (Plan *) lfirst(l);
/*
* I don't think we need to fiddle with the range table here,
* bjm
*/
print_plan_recursive(subnode, parsetree, indentLevel + 3, "a: ");
}
}
if (IsA(p, BitmapAnd))
{
ListCell *l;
BitmapAnd *bitmapandplan = (BitmapAnd *) p;
foreach(l, bitmapandplan->bitmapplans)
{
Plan *subnode = (Plan *) lfirst(l);
whichplan++;
print_plan_recursive(subnode, parsetree, indentLevel + 3, "a: ");
}
}
}
/* print_plan
prints just the plan node types */
if (IsA(p, BitmapOr))
{
ListCell *l;
BitmapOr *bitmaporplan = (BitmapOr *) p;
foreach(l, bitmaporplan->bitmapplans)
{
Plan *subnode = (Plan *) lfirst(l);
print_plan_recursive(subnode, parsetree, indentLevel + 3, "a: ");
}
}
}
/*
* print_plan
*
* prints just the plan node types
*/
void
print_plan(Plan *p, Query *parsetree)
{
......
......@@ -23,7 +23,7 @@
* Copyright (c) 2003-2005, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/tidbitmap.c,v 1.1 2005/04/17 22:24:02 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/tidbitmap.c,v 1.2 2005/04/19 22:35:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -160,7 +160,7 @@ tbm_create(long maxbytes)
hash_ctl.hash = tag_hash;
hash_ctl.hcxt = CurrentMemoryContext;
tbm->pagetable = hash_create("TIDBitmap",
nbuckets,
128, /* start small and extend */
&hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.125 2005/04/06 16:34:05 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.126 2005/04/19 22:35:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -898,6 +898,9 @@ print_path(Query *root, Path *path, int indent)
case T_IndexPath:
ptype = "IdxScan";
break;
case T_BitmapHeapPath:
ptype = "BitmapHeapScan";
break;
case T_TidPath:
ptype = "TidScan";
break;
......
......@@ -49,7 +49,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.141 2005/04/04 01:43:12 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.142 2005/04/19 22:35:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -400,6 +400,36 @@ cost_index(Path *path, Query *root,
path->total_cost = startup_cost + run_cost;
}
/*
* cost_bitmap_scan
* Determines and returns the cost of scanning a relation using a bitmap
* index-then-heap plan.
*
* 'root' is the query root
* 'baserel' is the relation to be scanned
* 'bitmapqual' is an AND/OR tree of IndexPaths for the component scans
* 'is_injoin' is T if we are considering using the scan as the inside
* of a nestloop join (hence, some of the quals are join clauses)
*/
void
cost_bitmap_scan(Path *path, Query *root, RelOptInfo *baserel,
Node *bitmapqual, bool is_injoin)
{
Cost startup_cost = 0;
Cost run_cost = 0;
/* Should only be applied to base relations */
Assert(IsA(baserel, RelOptInfo));
Assert(baserel->relid > 0);
Assert(baserel->rtekind == RTE_RELATION);
/* XXX lots to do here */
run_cost += 10;
path->startup_cost = startup_cost;
path->total_cost = startup_cost + run_cost;
}
/*
* cost_tidscan
* Determines and returns the cost of scanning a relation using TIDs.
......@@ -760,6 +790,8 @@ cost_nestloop(NestPath *path, Query *root)
*/
if (IsA(inner_path, IndexPath))
inner_path_rows = ((IndexPath *) inner_path)->rows;
else if (IsA(inner_path, BitmapHeapPath))
inner_path_rows = ((BitmapHeapPath *) inner_path)->rows;
if (!enable_nestloop)
startup_cost += disable_cost;
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.92 2005/01/23 02:21:26 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.93 2005/04/19 22:35:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -391,6 +391,7 @@ match_unsorted_outer(Query *root,
* waste of time.)
*/
if (!(IsA(inner_cheapest_total, IndexPath) ||
IsA(inner_cheapest_total, BitmapHeapPath) ||
IsA(inner_cheapest_total, TidPath)))
matpath = (Path *)
create_material_path(innerrel, inner_cheapest_total);
......
This diff is collapsed.
......@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.106 2005/04/06 16:34:05 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.107 2005/04/19 22:35:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -107,6 +107,21 @@ set_plan_references(Plan *plan, List *rtable)
fix_expr_references(plan,
(Node *) ((IndexScan *) plan)->indxqualorig);
break;
case T_BitmapIndexScan:
/* no need to fix targetlist and qual */
Assert(plan->targetlist == NIL);
Assert(plan->qual == NIL);
fix_expr_references(plan,
(Node *) ((BitmapIndexScan *) plan)->indxqual);
fix_expr_references(plan,
(Node *) ((BitmapIndexScan *) plan)->indxqualorig);
break;
case T_BitmapHeapScan:
fix_expr_references(plan, (Node *) plan->targetlist);
fix_expr_references(plan, (Node *) plan->qual);
fix_expr_references(plan,
(Node *) ((BitmapHeapScan *) plan)->bitmapqualorig);
break;
case T_TidScan:
fix_expr_references(plan, (Node *) plan->targetlist);
fix_expr_references(plan, (Node *) plan->qual);
......@@ -225,6 +240,16 @@ set_plan_references(Plan *plan, List *rtable)
foreach(l, ((Append *) plan)->appendplans)
set_plan_references((Plan *) lfirst(l), rtable);
break;
case T_BitmapAnd:
/* BitmapAnd works like Append */
foreach(l, ((BitmapAnd *) plan)->bitmapplans)
set_plan_references((Plan *) lfirst(l), rtable);
break;
case T_BitmapOr:
/* BitmapOr works like Append */
foreach(l, ((BitmapOr *) plan)->bitmapplans)
set_plan_references((Plan *) lfirst(l), rtable);
break;
default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(plan));
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.96 2005/04/11 23:06:55 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.97 2005/04/19 22:35:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1037,6 +1037,20 @@ finalize_plan(Plan *plan, List *rtable,
*/
break;
case T_BitmapIndexScan:
finalize_primnode((Node *) ((BitmapIndexScan *) plan)->indxqual,
&context);
/*
* we need not look at indxqualorig, since it will have the
* same param references as indxqual.
*/
break;
case T_BitmapHeapScan:
finalize_primnode((Node *) ((BitmapHeapScan *) plan)->bitmapqualorig,
&context);
break;
case T_TidScan:
finalize_primnode((Node *) ((TidScan *) plan)->tideval,
&context);
......@@ -1082,6 +1096,38 @@ finalize_plan(Plan *plan, List *rtable,
}
break;
case T_BitmapAnd:
{
ListCell *l;
foreach(l, ((BitmapAnd *) plan)->bitmapplans)
{
context.paramids =
bms_add_members(context.paramids,
finalize_plan((Plan *) lfirst(l),
rtable,
outer_params,
valid_params));
}
}
break;
case T_BitmapOr:
{
ListCell *l;
foreach(l, ((BitmapOr *) plan)->bitmapplans)
{
context.paramids =
bms_add_members(context.paramids,
finalize_plan((Plan *) lfirst(l),
rtable,
outer_params,
valid_params));
}
}
break;
case T_NestLoop:
finalize_primnode((Node *) ((Join *) plan)->joinqual,
&context);
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.115 2005/04/06 16:34:06 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.116 2005/04/19 22:35:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -471,6 +471,39 @@ create_index_path(Query *root,
return pathnode;
}
/*
* create_bitmap_heap_path
* Creates a path node for a bitmap scan.
*
* 'bitmapqual' is an AND/OR tree of IndexPath nodes.
*/
BitmapHeapPath *
create_bitmap_heap_path(Query *root,
RelOptInfo *rel,
Node *bitmapqual)
{
BitmapHeapPath *pathnode = makeNode(BitmapHeapPath);
pathnode->path.pathtype = T_BitmapHeapScan;
pathnode->path.parent = rel;
pathnode->path.pathkeys = NIL; /* always unordered */
pathnode->bitmapqual = bitmapqual;
/* It's not an innerjoin path. */
pathnode->isjoininner = false;
/*
* The number of rows is the same as the parent rel's estimate, since
* this isn't a join inner indexscan.
*/
pathnode->rows = rel->rows;
cost_bitmap_scan(&pathnode->path, root, rel, bitmapqual, false);
return pathnode;
}
/*
* create_tidscan_path
* Creates a path corresponding to a tid_direct scan, returning the
......
/*-------------------------------------------------------------------------
*
* nodeBitmapAnd.h
*
*
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeBitmapAnd.h,v 1.1 2005/04/19 22:35:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef NODEBITMAPAND_H
#define NODEBITMAPAND_H
#include "nodes/execnodes.h"
extern int ExecCountSlotsBitmapAnd(BitmapAnd *node);
extern BitmapAndState *ExecInitBitmapAnd(BitmapAnd *node, EState *estate);
extern Node *MultiExecBitmapAnd(BitmapAndState *node);
extern void ExecEndBitmapAnd(BitmapAndState *node);
extern void ExecReScanBitmapAnd(BitmapAndState *node, ExprContext *exprCtxt);
#endif /* NODEBITMAPAND_H */
/*-------------------------------------------------------------------------
*
* nodeBitmapHeapscan.h
*
*
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeBitmapHeapscan.h,v 1.1 2005/04/19 22:35:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef NODEBITMAPHEAPSCAN_H
#define NODEBITMAPHEAPSCAN_H
#include "nodes/execnodes.h"
extern int ExecCountSlotsBitmapHeapScan(BitmapHeapScan *node);
extern BitmapHeapScanState *ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate);
extern TupleTableSlot *ExecBitmapHeapScan(BitmapHeapScanState *node);
extern void ExecEndBitmapHeapScan(BitmapHeapScanState *node);
extern void ExecBitmapHeapReScan(BitmapHeapScanState *node, ExprContext *exprCtxt);
#endif /* NODEBITMAPHEAPSCAN_H */
/*-------------------------------------------------------------------------
*
* nodeBitmapIndexscan.h
*
*
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeBitmapIndexscan.h,v 1.1 2005/04/19 22:35:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef NODEBITMAPINDEXSCAN_H
#define NODEBITMAPINDEXSCAN_H
#include "nodes/execnodes.h"
extern int ExecCountSlotsBitmapIndexScan(BitmapIndexScan *node);
extern BitmapIndexScanState *ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate);
extern Node *MultiExecBitmapIndexScan(BitmapIndexScanState *node);
extern void ExecEndBitmapIndexScan(BitmapIndexScanState *node);
extern void ExecBitmapIndexReScan(BitmapIndexScanState *node, ExprContext *exprCtxt);
#endif /* NODEBITMAPINDEXSCAN_H */
/*-------------------------------------------------------------------------
*
* nodeBitmapOr.h
*
*
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeBitmapOr.h,v 1.1 2005/04/19 22:35:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef NODEBITMAPOR_H
#define NODEBITMAPOR_H
#include "nodes/execnodes.h"
extern int ExecCountSlotsBitmapOr(BitmapOr *node);
extern BitmapOrState *ExecInitBitmapOr(BitmapOr *node, EState *estate);
extern Node *MultiExecBitmapOr(BitmapOrState *node);
extern void ExecEndBitmapOr(BitmapOrState *node);
extern void ExecReScanBitmapOr(BitmapOrState *node, ExprContext *exprCtxt);
#endif /* NODEBITMAPOR_H */
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeIndexscan.h,v 1.21 2004/12/31 22:03:29 pgsql Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeIndexscan.h,v 1.22 2005/04/19 22:35:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -24,6 +24,4 @@ extern void ExecIndexMarkPos(IndexScanState *node);
extern void ExecIndexRestrPos(IndexScanState *node);
extern void ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt);
extern void ExecUpdateIndexScanKeys(IndexScanState *node, ExprContext *econtext);
#endif /* NODEINDEXSCAN_H */
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.125 2005/03/25 21:58:00 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.126 2005/04/19 22:35:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -20,6 +20,7 @@
#include "nodes/bitmapset.h"
#include "nodes/params.h"
#include "nodes/plannodes.h"
#include "nodes/tidbitmap.h"
#include "utils/hsearch.h"
#include "utils/tuplestore.h"
......@@ -803,6 +804,28 @@ typedef struct AppendState
int as_lastplan;
} AppendState;
/* ----------------
* BitmapAndState information
* ----------------
*/
typedef struct BitmapAndState
{
PlanState ps; /* its first field is NodeTag */
PlanState **bitmapplans; /* array of PlanStates for my inputs */
int nplans; /* number of input plans */
} BitmapAndState;
/* ----------------
* BitmapOrState information
* ----------------
*/
typedef struct BitmapOrState
{
PlanState ps; /* its first field is NodeTag */
PlanState **bitmapplans; /* array of PlanStates for my inputs */
int nplans; /* number of input plans */
} BitmapOrState;
/* ----------------------------------------------------------------
* Scan State Information
* ----------------------------------------------------------------
......@@ -875,6 +898,53 @@ typedef struct IndexScanState
long iss_MaxHash;
} IndexScanState;
/* ----------------
* BitmapIndexScanState information
*
* ScanKeys Skey structures to scan index rel
* NumScanKeys number of Skey structs
* RuntimeKeyInfo array of exprstates for Skeys
* that will be evaluated at runtime
* RuntimeContext expr context for evaling runtime Skeys
* RuntimeKeysReady true if runtime Skeys have been computed
* RelationDesc relation descriptor
* ScanDesc scan descriptor
* ----------------
*/
typedef struct BitmapIndexScanState
{
ScanState ss; /* its first field is NodeTag */
ScanKey biss_ScanKeys;
int biss_NumScanKeys;
ExprState **biss_RuntimeKeyInfo;
ExprContext *biss_RuntimeContext;
bool biss_RuntimeKeysReady;
Relation biss_RelationDesc;
IndexScanDesc biss_ScanDesc;
} BitmapIndexScanState;
/* ----------------
* BitmapHeapScanState information
*
* bitmapqualorig execution state for bitmapqualorig expressions
* tbm bitmap obtained from child index scan(s)
* tbmres current-page data
* curslot current tbmres index or tuple offset on page
* minslot lowest tbmres index or tuple offset to try
* maxslot highest tbmres index or tuple offset to try
* ----------------
*/
typedef struct BitmapHeapScanState
{
ScanState ss; /* its first field is NodeTag */
List *bitmapqualorig;
TIDBitmap *tbm;
TBMIterateResult *tbmres;
int curslot;
int minslot;
int maxslot;
} BitmapHeapScanState;
/* ----------------
* TidScanState information
*
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.166 2005/04/17 22:24:02 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.167 2005/04/19 22:35:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -44,9 +44,13 @@ typedef enum NodeTag
T_Plan = 100,
T_Result,
T_Append,
T_BitmapAnd,
T_BitmapOr,
T_Scan,
T_SeqScan,
T_IndexScan,
T_BitmapIndexScan,
T_BitmapHeapScan,
T_TidScan,
T_SubqueryScan,
T_FunctionScan,
......@@ -71,9 +75,13 @@ typedef enum NodeTag
T_PlanState = 200,
T_ResultState,
T_AppendState,
T_BitmapAndState,
T_BitmapOrState,
T_ScanState,
T_SeqScanState,
T_IndexScanState,
T_BitmapIndexScanState,
T_BitmapHeapScanState,
T_TidScanState,
T_SubqueryScanState,
T_FunctionScanState,
......@@ -161,6 +169,7 @@ typedef enum NodeTag
T_IndexOptInfo,
T_Path,
T_IndexPath,
T_BitmapHeapPath,
T_NestPath,
T_MergePath,
T_HashPath,
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.77 2004/12/31 22:03:34 pgsql Exp $
* $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.78 2005/04/19 22:35:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -134,6 +134,34 @@ typedef struct Append
bool isTarget;
} Append;
/* ----------------
* BitmapAnd node -
* Generate the intersection of the results of sub-plans.
*
* The subplans must be of types that yield tuple bitmaps. The targetlist
* and qual fields of the plan are unused and are always NIL.
* ----------------
*/
typedef struct BitmapAnd
{
Plan plan;
List *bitmapplans;
} BitmapAnd;
/* ----------------
* BitmapOr node -
* Generate the union of the results of sub-plans.
*
* The subplans must be of types that yield tuple bitmaps. The targetlist
* and qual fields of the plan are unused and are always NIL.
* ----------------
*/
typedef struct BitmapOr
{
Plan plan;
List *bitmapplans;
} BitmapOr;
/*
* ==========
* Scan nodes
......@@ -156,6 +184,8 @@ typedef Scan SeqScan;
*
* Note: this can actually represent N indexscans, all on the same table
* but potentially using different indexes, put together with OR semantics.
* (XXX that extension should probably go away, because bitmapindexscan will
* largely eliminate the need for it.)
* ----------------
*/
typedef struct IndexScan
......@@ -171,7 +201,46 @@ typedef struct IndexScan
} IndexScan;
/* ----------------
* tid scan node
* bitmap index scan node
*
* BitmapIndexScan delivers a bitmap of potential tuple locations;
* it does not access the heap itself. The bitmap is used by an
* ancestor BitmapHeapScan node, possibly after passing through
* intermediate BitmapAnd and/or BitmapOr nodes to combine it with
* the results of other BitmapIndexScans.
*
* In a BitmapIndexScan plan node, the targetlist and qual fields are
* not used and are always NIL. The indxqualorig field is useless at
* run time too, but is saved for the benefit of EXPLAIN.
* ----------------
*/
typedef struct BitmapIndexScan
{
Scan scan;
Oid indxid; /* OID of index to scan */
List *indxqual; /* list of index quals */
List *indxqualorig; /* list of original forms of index quals */
List *indxstrategy; /* list of strategy numbers */
List *indxsubtype; /* list of strategy subtypes */
} BitmapIndexScan;
/* ----------------
* bitmap sequential scan node
*
* This needs a copy of the qual conditions being used by the input index
* scans because there are various cases where we need to recheck the quals;
* for example, when the bitmap is lossy about the specific rows on a page
* that meet the index condition.
* ----------------
*/
typedef struct BitmapHeapScan
{
Scan scan;
List *bitmapqualorig; /* index quals, in standard expr form */
} BitmapHeapScan;
/* ----------------
* tid scan node
* ----------------
*/
typedef struct TidScan
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.104 2005/03/27 06:29:45 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.105 2005/04/19 22:35:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -342,6 +342,9 @@ typedef struct Path
* tuples matched during any scan. (The executor is smart enough not to return
* the same tuple more than once, even if it is matched in multiple scans.)
*
* XXX bitmap index scans will probably obviate the need for plain OR
* indexscans, allowing a lot of this to be simplified.
*
* 'indexinfo' is a list of IndexOptInfo nodes, one per scan to be performed.
*
* 'indexclauses' is a list of index qualifications, also one per scan.
......@@ -389,6 +392,30 @@ typedef struct IndexPath
double rows; /* estimated number of result tuples */
} IndexPath;
/*
* BitmapHeapPath represents one or more indexscans that generate TID bitmaps
* instead of directly accessing the heap, followed by AND/OR combinations
* to produce a single bitmap, followed by a heap scan that uses the bitmap.
* Note that the output is always considered unordered, since it will come
* out in physical heap order no matter what the underlying indexes did.
*
* The individual indexscans are represented by IndexPath nodes, and any
* logic on top of them is represented by regular AND and OR expressions.
* Notice that we can use the same IndexPath node both to represent an
* ordered index scan, and as the child of a BitmapHeapPath that represents
* scanning the same index in an unordered way.
*
* BitmapHeapPaths can be nestloop inner indexscans. The isjoininner and
* rows fields serve the same purpose as for plain IndexPaths.
*/
typedef struct BitmapHeapPath
{
Path path;
Node *bitmapqual; /* the IndexPath/AND/OR tree */
bool isjoininner; /* T if it's a nestloop inner scan */
double rows; /* estimated number of result tuples */
} BitmapHeapPath;
/*
* TidPath represents a scan by TID
*
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.63 2005/03/27 06:29:49 tgl Exp $
* $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.64 2005/04/19 22:35:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -53,6 +53,8 @@ extern double clamp_row_est(double nrows);
extern void cost_seqscan(Path *path, Query *root, RelOptInfo *baserel);
extern void cost_index(Path *path, Query *root, IndexOptInfo *index,
List *indexQuals, bool is_injoin);
extern void cost_bitmap_scan(Path *path, Query *root, RelOptInfo *baserel,
Node *bitmapqual, bool is_injoin);
extern void cost_tidscan(Path *path, Query *root,
RelOptInfo *baserel, List *tideval);
extern void cost_subqueryscan(Path *path, RelOptInfo *baserel);
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/optimizer/pathnode.h,v 1.57 2005/03/27 06:29:49 tgl Exp $
* $PostgreSQL: pgsql/src/include/optimizer/pathnode.h,v 1.58 2005/04/19 22:35:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -33,6 +33,9 @@ extern IndexPath *create_index_path(Query *root,
List *restriction_clauses,
List *pathkeys,
ScanDirection indexscandir);
extern BitmapHeapPath *create_bitmap_heap_path(Query *root,
RelOptInfo *rel,
Node *bitmapqual);
extern TidPath *create_tidscan_path(Query *root, RelOptInfo *rel,
List *tideval);
extern AppendPath *create_append_path(RelOptInfo *rel, List *subpaths);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment