aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/optimizer/plan/createplan.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 5658f24323f..91885084cdd 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -20,6 +20,7 @@
#include <math.h>
#include "access/sysattr.h"
+#include "catalog/pg_am.h"
#include "catalog/pg_class.h"
#include "foreign/fdwapi.h"
#include "miscadmin.h"
@@ -191,6 +192,7 @@ static IndexOnlyScan *make_indexonlyscan(List *qptlist, List *qpqual,
List *indexqual, List *indexorderby,
List *indextlist,
ScanDirection indexscandir);
+static List *make_indexonly_tlist(IndexOptInfo *indexinfo);
static BitmapIndexScan *make_bitmap_indexscan(Index scanrelid, Oid indexid,
List *indexqual,
List *indexqualorig);
@@ -621,7 +623,7 @@ create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
if (best_path->pathtype == T_IndexOnlyScan)
{
/* For index-only scan, the preferred tlist is the index's */
- tlist = copyObject(((IndexPath *) best_path)->indexinfo->indextlist);
+ tlist = copyObject(make_indexonly_tlist(((IndexPath *) best_path)->indexinfo));
/*
* Transfer sortgroupref data to the replacement tlist, if
@@ -3070,7 +3072,7 @@ create_indexscan_plan(PlannerInfo *root,
indexoid,
fixed_indexquals,
fixed_indexorderbys,
- best_path->indexinfo->indextlist,
+ make_indexonly_tlist(best_path->indexinfo),
best_path->indexscandir);
else
scan_plan = (Scan *) make_indexscan(tlist,
@@ -5462,6 +5464,53 @@ make_indexonlyscan(List *qptlist,
return node;
}
+/*
+ * make_indexonly_tlist
+ *
+ * Construct the indextlist for an IndexOnlyScan plan node.
+ * We must replace any column that can't be returned by the index AM
+ * with a null Const of the appropriate datatype. This is necessary
+ * to prevent setrefs.c from trying to use the value of such a column,
+ * and anyway it makes the indextlist a better representative of what
+ * the indexscan will really return. (We do this here, not where the
+ * IndexOptInfo is originally constructed, because earlier planner
+ * steps need to know what is in such columns.)
+ */
+static List *
+make_indexonly_tlist(IndexOptInfo *indexinfo)
+{
+ List *result;
+ int i;
+ ListCell *lc;
+
+ /* We needn't work hard for the common case of btrees. */
+ if (indexinfo->relam == BTREE_AM_OID)
+ return indexinfo->indextlist;
+
+ result = NIL;
+ i = 0;
+ foreach(lc, indexinfo->indextlist)
+ {
+ TargetEntry *indextle = (TargetEntry *) lfirst(lc);
+
+ if (indexinfo->canreturn[i])
+ result = lappend(result, indextle);
+ else
+ {
+ TargetEntry *newtle = makeNode(TargetEntry);
+ Node *texpr = (Node *) indextle->expr;
+
+ memcpy(newtle, indextle, sizeof(TargetEntry));
+ newtle->expr = (Expr *) makeNullConst(exprType(texpr),
+ exprTypmod(texpr),
+ exprCollation(texpr));
+ result = lappend(result, newtle);
+ }
+ i++;
+ }
+ return result;
+}
+
static BitmapIndexScan *
make_bitmap_indexscan(Index scanrelid,
Oid indexid,