diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 53 |
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, |