|
20 | 20 | #include <math.h>
|
21 | 21 |
|
22 | 22 | #include "access/sysattr.h"
|
| 23 | +#include "catalog/pg_am.h" |
23 | 24 | #include "catalog/pg_class.h"
|
24 | 25 | #include "foreign/fdwapi.h"
|
25 | 26 | #include "miscadmin.h"
|
@@ -191,6 +192,7 @@ static IndexOnlyScan *make_indexonlyscan(List *qptlist, List *qpqual,
|
191 | 192 | List *indexqual, List *indexorderby,
|
192 | 193 | List *indextlist,
|
193 | 194 | ScanDirection indexscandir);
|
| 195 | +static List *make_indexonly_tlist(IndexOptInfo *indexinfo); |
194 | 196 | static BitmapIndexScan *make_bitmap_indexscan(Index scanrelid, Oid indexid,
|
195 | 197 | List *indexqual,
|
196 | 198 | List *indexqualorig);
|
@@ -621,7 +623,7 @@ create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
|
621 | 623 | if (best_path->pathtype == T_IndexOnlyScan)
|
622 | 624 | {
|
623 | 625 | /* For index-only scan, the preferred tlist is the index's */
|
624 |
| - tlist = copyObject(((IndexPath *) best_path)->indexinfo->indextlist); |
| 626 | + tlist = copyObject(make_indexonly_tlist(((IndexPath *) best_path)->indexinfo)); |
625 | 627 |
|
626 | 628 | /*
|
627 | 629 | * Transfer sortgroupref data to the replacement tlist, if
|
@@ -3070,7 +3072,7 @@ create_indexscan_plan(PlannerInfo *root,
|
3070 | 3072 | indexoid,
|
3071 | 3073 | fixed_indexquals,
|
3072 | 3074 | fixed_indexorderbys,
|
3073 |
| - best_path->indexinfo->indextlist, |
| 3075 | + make_indexonly_tlist(best_path->indexinfo), |
3074 | 3076 | best_path->indexscandir);
|
3075 | 3077 | else
|
3076 | 3078 | scan_plan = (Scan *) make_indexscan(tlist,
|
@@ -5462,6 +5464,53 @@ make_indexonlyscan(List *qptlist,
|
5462 | 5464 | return node;
|
5463 | 5465 | }
|
5464 | 5466 |
|
| 5467 | +/* |
| 5468 | + * make_indexonly_tlist |
| 5469 | + * |
| 5470 | + * Construct the indextlist for an IndexOnlyScan plan node. |
| 5471 | + * We must replace any column that can't be returned by the index AM |
| 5472 | + * with a null Const of the appropriate datatype. This is necessary |
| 5473 | + * to prevent setrefs.c from trying to use the value of such a column, |
| 5474 | + * and anyway it makes the indextlist a better representative of what |
| 5475 | + * the indexscan will really return. (We do this here, not where the |
| 5476 | + * IndexOptInfo is originally constructed, because earlier planner |
| 5477 | + * steps need to know what is in such columns.) |
| 5478 | + */ |
| 5479 | +static List * |
| 5480 | +make_indexonly_tlist(IndexOptInfo *indexinfo) |
| 5481 | +{ |
| 5482 | + List *result; |
| 5483 | + int i; |
| 5484 | + ListCell *lc; |
| 5485 | + |
| 5486 | + /* We needn't work hard for the common case of btrees. */ |
| 5487 | + if (indexinfo->relam == BTREE_AM_OID) |
| 5488 | + return indexinfo->indextlist; |
| 5489 | + |
| 5490 | + result = NIL; |
| 5491 | + i = 0; |
| 5492 | + foreach(lc, indexinfo->indextlist) |
| 5493 | + { |
| 5494 | + TargetEntry *indextle = (TargetEntry *) lfirst(lc); |
| 5495 | + |
| 5496 | + if (indexinfo->canreturn[i]) |
| 5497 | + result = lappend(result, indextle); |
| 5498 | + else |
| 5499 | + { |
| 5500 | + TargetEntry *newtle = makeNode(TargetEntry); |
| 5501 | + Node *texpr = (Node *) indextle->expr; |
| 5502 | + |
| 5503 | + memcpy(newtle, indextle, sizeof(TargetEntry)); |
| 5504 | + newtle->expr = (Expr *) makeNullConst(exprType(texpr), |
| 5505 | + exprTypmod(texpr), |
| 5506 | + exprCollation(texpr)); |
| 5507 | + result = lappend(result, newtle); |
| 5508 | + } |
| 5509 | + i++; |
| 5510 | + } |
| 5511 | + return result; |
| 5512 | +} |
| 5513 | + |
5465 | 5514 | static BitmapIndexScan *
|
5466 | 5515 | make_bitmap_indexscan(Index scanrelid,
|
5467 | 5516 | Oid indexid,
|
|
0 commit comments