git.postgresql.org Git - postgresql.git/commitdiff (original) (raw)

#include <math.h>

#include "access/sysattr.h"

+#include "catalog/pg_am.h"

#include "catalog/pg_class.h"

#include "foreign/fdwapi.h"

#include "miscadmin.h"

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);

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

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,

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,

* indextlist, which represents the contents of the index as a targetlist

* with one TLE per index column. Vars appearing in this list reference

* the base table, and this is the only field in the plan node that may

- * contain such Vars.

+ * contain such Vars. Note however that index columns that the AM can't

+ * reconstruct are replaced by null Consts in indextlist.

* ----------------

*/

typedef struct IndexOnlyScan

(11 rows)

drop index gist_tbl_multi_index;

+-- Test that we don't try to return the value of a non-returnable

+-- column in an index-only scan. (This isn't GIST-specific, but

+-- it only applies to index AMs that can return some columns and not

+-- others, so GIST with appropriate opclasses is a convenient test case.)

+create index gist_tbl_multi_index on gist_tbl using gist (circle(p,1), p);

+explain (verbose, costs off)

+select circle(p,1) from gist_tbl

+where p <@ box(point(5, 5), point(5.3, 5.3));

+ QUERY PLAN

+---------------------------------------------------------------

+ Index Only Scan using gist_tbl_multi_index on public.gist_tbl

+ Output: circle(p, '1'::double precision)

+ Index Cond: (gist_tbl.p <@ '(5.3,5.3),(5,5)'::box)

+(3 rows)

+select circle(p,1) from gist_tbl

+where p <@ box(point(5, 5), point(5.3, 5.3));

+ circle

+-----------------

+ <(5,5),1>

+ <(5.05,5.05),1>

+ <(5.1,5.1),1>

+ <(5.15,5.15),1>

+ <(5.2,5.2),1>

+ <(5.25,5.25),1>

+ <(5.3,5.3),1>

+(7 rows)

-- Clean up

reset enable_seqscan;

reset enable_bitmapscan;

drop index gist_tbl_multi_index;

+-- Test that we don't try to return the value of a non-returnable

+-- column in an index-only scan. (This isn't GIST-specific, but

+-- it only applies to index AMs that can return some columns and not

+-- others, so GIST with appropriate opclasses is a convenient test case.)

+create index gist_tbl_multi_index on gist_tbl using gist (circle(p,1), p);

+explain (verbose, costs off)

+select circle(p,1) from gist_tbl

+where p <@ box(point(5, 5), point(5.3, 5.3));

+select circle(p,1) from gist_tbl

+where p <@ box(point(5, 5), point(5.3, 5.3));

-- Clean up

reset enable_seqscan;

reset enable_bitmapscan;