Skip to content

Commit a018546

Browse files
committed
Rearrange the implementation of index-only scans.
This commit changes index-only scans so that data is read directly from the index tuple without first generating a faux heap tuple. The only immediate benefit is that indexes on system columns (such as OID) can be used in index-only scans, but this is necessary infrastructure if we are ever to support index-only scans on expression indexes. The executor is now ready for that, though the planner still needs substantial work to recognize the possibility. To do this, Vars in index-only plan nodes have to refer to index columns not heap columns. I introduced a new special varno, INDEX_VAR, to mark such Vars to avoid confusion. (In passing, this commit renames the two existing special varnos to OUTER_VAR and INNER_VAR.) This allows ruleutils.c to handle them with logic similar to what we use for subplan reference Vars. Since index-only scans are now fundamentally different from regular indexscans so far as their expression subtrees are concerned, I also chose to change them to have their own plan node type (and hence, their own executor source file).
1 parent fa351d5 commit a018546

34 files changed

+1313
-420
lines changed

src/backend/commands/explain.c

Lines changed: 79 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ static void show_instrumentation_count(const char *qlabel, int which,
7979
PlanState *planstate, ExplainState *es);
8080
static void show_foreignscan_info(ForeignScanState *fsstate, ExplainState *es);
8181
static const char *explain_get_index_name(Oid indexId);
82+
static void ExplainIndexScanDetails(Oid indexid, ScanDirection indexorderdir,
83+
ExplainState *es);
8284
static void ExplainScanTarget(Scan *plan, ExplainState *es);
8385
static void ExplainModifyTarget(ModifyTable *plan, ExplainState *es);
8486
static void ExplainTargetRel(Plan *plan, Index rti, ExplainState *es);
@@ -656,10 +658,10 @@ ExplainNode(PlanState *planstate, List *ancestors,
656658
pname = sname = "Seq Scan";
657659
break;
658660
case T_IndexScan:
659-
if (((IndexScan *) plan)->indexonly)
660-
pname = sname = "Index Only Scan";
661-
else
662-
pname = sname = "Index Scan";
661+
pname = sname = "Index Scan";
662+
break;
663+
case T_IndexOnlyScan:
664+
pname = sname = "Index Only Scan";
663665
break;
664666
case T_BitmapIndexScan:
665667
pname = sname = "Bitmap Index Scan";
@@ -793,42 +795,6 @@ ExplainNode(PlanState *planstate, List *ancestors,
793795

794796
switch (nodeTag(plan))
795797
{
796-
case T_IndexScan:
797-
{
798-
IndexScan *indexscan = (IndexScan *) plan;
799-
const char *indexname =
800-
explain_get_index_name(indexscan->indexid);
801-
802-
if (es->format == EXPLAIN_FORMAT_TEXT)
803-
{
804-
if (ScanDirectionIsBackward(indexscan->indexorderdir))
805-
appendStringInfoString(es->str, " Backward");
806-
appendStringInfo(es->str, " using %s", indexname);
807-
}
808-
else
809-
{
810-
const char *scandir;
811-
812-
switch (indexscan->indexorderdir)
813-
{
814-
case BackwardScanDirection:
815-
scandir = "Backward";
816-
break;
817-
case NoMovementScanDirection:
818-
scandir = "NoMovement";
819-
break;
820-
case ForwardScanDirection:
821-
scandir = "Forward";
822-
break;
823-
default:
824-
scandir = "???";
825-
break;
826-
}
827-
ExplainPropertyText("Scan Direction", scandir, es);
828-
ExplainPropertyText("Index Name", indexname, es);
829-
}
830-
}
831-
/* FALL THRU */
832798
case T_SeqScan:
833799
case T_BitmapHeapScan:
834800
case T_TidScan:
@@ -840,6 +806,26 @@ ExplainNode(PlanState *planstate, List *ancestors,
840806
case T_ForeignScan:
841807
ExplainScanTarget((Scan *) plan, es);
842808
break;
809+
case T_IndexScan:
810+
{
811+
IndexScan *indexscan = (IndexScan *) plan;
812+
813+
ExplainIndexScanDetails(indexscan->indexid,
814+
indexscan->indexorderdir,
815+
es);
816+
ExplainScanTarget((Scan *) indexscan, es);
817+
}
818+
break;
819+
case T_IndexOnlyScan:
820+
{
821+
IndexOnlyScan *indexonlyscan = (IndexOnlyScan *) plan;
822+
823+
ExplainIndexScanDetails(indexonlyscan->indexid,
824+
indexonlyscan->indexorderdir,
825+
es);
826+
ExplainScanTarget((Scan *) indexonlyscan, es);
827+
}
828+
break;
843829
case T_BitmapIndexScan:
844830
{
845831
BitmapIndexScan *bitmapindexscan = (BitmapIndexScan *) plan;
@@ -1014,6 +1000,19 @@ ExplainNode(PlanState *planstate, List *ancestors,
10141000
show_instrumentation_count("Rows Removed by Filter", 1,
10151001
planstate, es);
10161002
break;
1003+
case T_IndexOnlyScan:
1004+
show_scan_qual(((IndexOnlyScan *) plan)->indexqual,
1005+
"Index Cond", planstate, ancestors, es);
1006+
if (((IndexOnlyScan *) plan)->indexqual)
1007+
show_instrumentation_count("Rows Removed by Index Recheck", 2,
1008+
planstate, es);
1009+
show_scan_qual(((IndexOnlyScan *) plan)->indexorderby,
1010+
"Order By", planstate, ancestors, es);
1011+
show_scan_qual(plan->qual, "Filter", planstate, ancestors, es);
1012+
if (plan->qual)
1013+
show_instrumentation_count("Rows Removed by Filter", 1,
1014+
planstate, es);
1015+
break;
10171016
case T_BitmapIndexScan:
10181017
show_scan_qual(((BitmapIndexScan *) plan)->indexqualorig,
10191018
"Index Cond", planstate, ancestors, es);
@@ -1626,6 +1625,45 @@ explain_get_index_name(Oid indexId)
16261625
return result;
16271626
}
16281627

1628+
/*
1629+
* Add some additional details about an IndexScan or IndexOnlyScan
1630+
*/
1631+
static void
1632+
ExplainIndexScanDetails(Oid indexid, ScanDirection indexorderdir,
1633+
ExplainState *es)
1634+
{
1635+
const char *indexname = explain_get_index_name(indexid);
1636+
1637+
if (es->format == EXPLAIN_FORMAT_TEXT)
1638+
{
1639+
if (ScanDirectionIsBackward(indexorderdir))
1640+
appendStringInfoString(es->str, " Backward");
1641+
appendStringInfo(es->str, " using %s", indexname);
1642+
}
1643+
else
1644+
{
1645+
const char *scandir;
1646+
1647+
switch (indexorderdir)
1648+
{
1649+
case BackwardScanDirection:
1650+
scandir = "Backward";
1651+
break;
1652+
case NoMovementScanDirection:
1653+
scandir = "NoMovement";
1654+
break;
1655+
case ForwardScanDirection:
1656+
scandir = "Forward";
1657+
break;
1658+
default:
1659+
scandir = "???";
1660+
break;
1661+
}
1662+
ExplainPropertyText("Scan Direction", scandir, es);
1663+
ExplainPropertyText("Index Name", indexname, es);
1664+
}
1665+
}
1666+
16291667
/*
16301668
* Show the target of a Scan node
16311669
*/
@@ -1670,6 +1708,7 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
16701708
{
16711709
case T_SeqScan:
16721710
case T_IndexScan:
1711+
case T_IndexOnlyScan:
16731712
case T_BitmapHeapScan:
16741713
case T_TidScan:
16751714
case T_ForeignScan:

src/backend/commands/trigger.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2734,9 +2734,9 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
27342734

27352735
oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
27362736
tgqual = stringToNode(trigger->tgqual);
2737-
/* Change references to OLD and NEW to INNER and OUTER */
2738-
ChangeVarNodes(tgqual, PRS2_OLD_VARNO, INNER, 0);
2739-
ChangeVarNodes(tgqual, PRS2_NEW_VARNO, OUTER, 0);
2737+
/* Change references to OLD and NEW to INNER_VAR and OUTER_VAR */
2738+
ChangeVarNodes(tgqual, PRS2_OLD_VARNO, INNER_VAR, 0);
2739+
ChangeVarNodes(tgqual, PRS2_NEW_VARNO, OUTER_VAR, 0);
27402740
/* ExecQual wants implicit-AND form */
27412741
tgqual = (Node *) make_ands_implicit((Expr *) tgqual);
27422742
*predicate = (List *) ExecPrepareExpr((Expr *) tgqual, estate);
@@ -2783,7 +2783,7 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
27832783

27842784
/*
27852785
* Finally evaluate the expression, making the old and/or new tuples
2786-
* available as INNER/OUTER respectively.
2786+
* available as INNER_VAR/OUTER_VAR respectively.
27872787
*/
27882788
econtext->ecxt_innertuple = oldslot;
27892789
econtext->ecxt_outertuple = newslot;

src/backend/executor/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ OBJS = execAmi.o execCurrent.o execGrouping.o execJunk.o execMain.o \
1717
execUtils.o functions.o instrument.o nodeAppend.o nodeAgg.o \
1818
nodeBitmapAnd.o nodeBitmapOr.o \
1919
nodeBitmapHeapscan.o nodeBitmapIndexscan.o nodeHash.o \
20-
nodeHashjoin.o nodeIndexscan.o nodeLimit.o nodeLockRows.o \
20+
nodeHashjoin.o nodeIndexscan.o nodeIndexonlyscan.o \
21+
nodeLimit.o nodeLockRows.o \
2122
nodeMaterial.o nodeMergeAppend.o nodeMergejoin.o nodeModifyTable.o \
2223
nodeNestloop.o nodeFunctionscan.o nodeRecursiveunion.o nodeResult.o \
2324
nodeSeqscan.o nodeSetOp.o nodeSort.o nodeUnique.o \

src/backend/executor/execAmi.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "executor/nodeGroup.h"
2727
#include "executor/nodeHash.h"
2828
#include "executor/nodeHashjoin.h"
29+
#include "executor/nodeIndexonlyscan.h"
2930
#include "executor/nodeIndexscan.h"
3031
#include "executor/nodeLimit.h"
3132
#include "executor/nodeLockRows.h"
@@ -155,6 +156,10 @@ ExecReScan(PlanState *node)
155156
ExecReScanIndexScan((IndexScanState *) node);
156157
break;
157158

159+
case T_IndexOnlyScanState:
160+
ExecReScanIndexOnlyScan((IndexOnlyScanState *) node);
161+
break;
162+
158163
case T_BitmapIndexScanState:
159164
ExecReScanBitmapIndexScan((BitmapIndexScanState *) node);
160165
break;
@@ -273,6 +278,10 @@ ExecMarkPos(PlanState *node)
273278
ExecIndexMarkPos((IndexScanState *) node);
274279
break;
275280

281+
case T_IndexOnlyScanState:
282+
ExecIndexOnlyMarkPos((IndexOnlyScanState *) node);
283+
break;
284+
276285
case T_TidScanState:
277286
ExecTidMarkPos((TidScanState *) node);
278287
break;
@@ -326,6 +335,10 @@ ExecRestrPos(PlanState *node)
326335
ExecIndexRestrPos((IndexScanState *) node);
327336
break;
328337

338+
case T_IndexOnlyScanState:
339+
ExecIndexOnlyRestrPos((IndexOnlyScanState *) node);
340+
break;
341+
329342
case T_TidScanState:
330343
ExecTidRestrPos((TidScanState *) node);
331344
break;
@@ -371,6 +384,7 @@ ExecSupportsMarkRestore(NodeTag plantype)
371384
{
372385
case T_SeqScan:
373386
case T_IndexScan:
387+
case T_IndexOnlyScan:
374388
case T_TidScan:
375389
case T_ValuesScan:
376390
case T_Material:
@@ -442,6 +456,10 @@ ExecSupportsBackwardScan(Plan *node)
442456
return IndexSupportsBackwardScan(((IndexScan *) node)->indexid) &&
443457
TargetListSupportsBackwardScan(node->targetlist);
444458

459+
case T_IndexOnlyScan:
460+
return IndexSupportsBackwardScan(((IndexOnlyScan *) node)->indexid) &&
461+
TargetListSupportsBackwardScan(node->targetlist);
462+
445463
case T_SubqueryScan:
446464
return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan) &&
447465
TargetListSupportsBackwardScan(node->targetlist);
@@ -474,7 +492,8 @@ TargetListSupportsBackwardScan(List *targetlist)
474492
}
475493

476494
/*
477-
* An IndexScan node supports backward scan only if the index's AM does.
495+
* An IndexScan or IndexOnlyScan node supports backward scan only if the
496+
* index's AM does.
478497
*/
479498
static bool
480499
IndexSupportsBackwardScan(Oid indexid)

src/backend/executor/execCurrent.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ search_plan_tree(PlanState *node, Oid table_oid)
262262
*/
263263
case T_SeqScanState:
264264
case T_IndexScanState:
265+
case T_IndexOnlyScanState:
265266
case T_BitmapHeapScanState:
266267
case T_TidScanState:
267268
{

src/backend/executor/execProcnode.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
#include "executor/nodeGroup.h"
9090
#include "executor/nodeHash.h"
9191
#include "executor/nodeHashjoin.h"
92+
#include "executor/nodeIndexonlyscan.h"
9293
#include "executor/nodeIndexscan.h"
9394
#include "executor/nodeLimit.h"
9495
#include "executor/nodeLockRows.h"
@@ -192,6 +193,11 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
192193
estate, eflags);
193194
break;
194195

196+
case T_IndexOnlyScan:
197+
result = (PlanState *) ExecInitIndexOnlyScan((IndexOnlyScan *) node,
198+
estate, eflags);
199+
break;
200+
195201
case T_BitmapIndexScan:
196202
result = (PlanState *) ExecInitBitmapIndexScan((BitmapIndexScan *) node,
197203
estate, eflags);
@@ -397,6 +403,10 @@ ExecProcNode(PlanState *node)
397403
result = ExecIndexScan((IndexScanState *) node);
398404
break;
399405

406+
case T_IndexOnlyScanState:
407+
result = ExecIndexOnlyScan((IndexOnlyScanState *) node);
408+
break;
409+
400410
/* BitmapIndexScanState does not yield tuples */
401411

402412
case T_BitmapHeapScanState:
@@ -627,6 +637,10 @@ ExecEndNode(PlanState *node)
627637
ExecEndIndexScan((IndexScanState *) node);
628638
break;
629639

640+
case T_IndexOnlyScanState:
641+
ExecEndIndexOnlyScan((IndexOnlyScanState *) node);
642+
break;
643+
630644
case T_BitmapIndexScanState:
631645
ExecEndBitmapIndexScan((BitmapIndexScanState *) node);
632646
break;

src/backend/executor/execQual.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -578,14 +578,16 @@ ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
578578
/* Get the input slot and attribute number we want */
579579
switch (variable->varno)
580580
{
581-
case INNER: /* get the tuple from the inner node */
581+
case INNER_VAR: /* get the tuple from the inner node */
582582
slot = econtext->ecxt_innertuple;
583583
break;
584584

585-
case OUTER: /* get the tuple from the outer node */
585+
case OUTER_VAR: /* get the tuple from the outer node */
586586
slot = econtext->ecxt_outertuple;
587587
break;
588588

589+
/* INDEX_VAR is handled by default case */
590+
589591
default: /* get the tuple from the relation being
590592
* scanned */
591593
slot = econtext->ecxt_scantuple;
@@ -761,14 +763,16 @@ ExecEvalScalarVar(ExprState *exprstate, ExprContext *econtext,
761763
/* Get the input slot and attribute number we want */
762764
switch (variable->varno)
763765
{
764-
case INNER: /* get the tuple from the inner node */
766+
case INNER_VAR: /* get the tuple from the inner node */
765767
slot = econtext->ecxt_innertuple;
766768
break;
767769

768-
case OUTER: /* get the tuple from the outer node */
770+
case OUTER_VAR: /* get the tuple from the outer node */
769771
slot = econtext->ecxt_outertuple;
770772
break;
771773

774+
/* INDEX_VAR is handled by default case */
775+
772776
default: /* get the tuple from the relation being
773777
* scanned */
774778
slot = econtext->ecxt_scantuple;
@@ -804,14 +808,16 @@ ExecEvalWholeRowVar(ExprState *exprstate, ExprContext *econtext,
804808
/* Get the input slot we want */
805809
switch (variable->varno)
806810
{
807-
case INNER: /* get the tuple from the inner node */
811+
case INNER_VAR: /* get the tuple from the inner node */
808812
slot = econtext->ecxt_innertuple;
809813
break;
810814

811-
case OUTER: /* get the tuple from the outer node */
815+
case OUTER_VAR: /* get the tuple from the outer node */
812816
slot = econtext->ecxt_outertuple;
813817
break;
814818

819+
/* INDEX_VAR is handled by default case */
820+
815821
default: /* get the tuple from the relation being
816822
* scanned */
817823
slot = econtext->ecxt_scantuple;
@@ -873,14 +879,16 @@ ExecEvalWholeRowSlow(ExprState *exprstate, ExprContext *econtext,
873879
/* Get the input slot we want */
874880
switch (variable->varno)
875881
{
876-
case INNER: /* get the tuple from the inner node */
882+
case INNER_VAR: /* get the tuple from the inner node */
877883
slot = econtext->ecxt_innertuple;
878884
break;
879885

880-
case OUTER: /* get the tuple from the outer node */
886+
case OUTER_VAR: /* get the tuple from the outer node */
881887
slot = econtext->ecxt_outertuple;
882888
break;
883889

890+
/* INDEX_VAR is handled by default case */
891+
884892
default: /* get the tuple from the relation being
885893
* scanned */
886894
slot = econtext->ecxt_scantuple;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy