aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-12-18 15:49:00 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2011-12-18 15:50:37 -0500
commit3695a555136a6d179cac8ae48d5f90171d5b30e9 (patch)
treeefb7fb5afb3dea1292c9a50635b53215cc548e64 /src
parent19d223171801dda36f84e24dc89c9fbab1ababad (diff)
downloadpostgresql-3695a555136a6d179cac8ae48d5f90171d5b30e9.tar.gz
postgresql-3695a555136a6d179cac8ae48d5f90171d5b30e9.zip
Replace simple constant pg_am.amcanreturn with an AM support function.
The need for this was debated when we put in the index-only-scan feature, but at the time we had no near-term expectation of having AMs that could support such scans for only some indexes; so we kept it simple. However, the SP-GiST AM forces the issue, so let's fix it. This patch only installs the new API; no behavior actually changes.
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/index/indexam.c22
-rw-r--r--src/backend/access/nbtree/nbtree.c11
-rw-r--r--src/backend/access/spgist/spgscan.c7
-rw-r--r--src/backend/optimizer/path/indxpath.c4
-rw-r--r--src/backend/optimizer/util/plancat.c2
-rw-r--r--src/include/access/genam.h1
-rw-r--r--src/include/access/nbtree.h1
-rw-r--r--src/include/access/spgist.h1
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/pg_am.h52
-rw-r--r--src/include/catalog/pg_proc.h4
-rw-r--r--src/include/nodes/relation.h2
-rw-r--r--src/include/utils/rel.h1
13 files changed, 79 insertions, 31 deletions
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 6d423a7d682..e5fb5183897 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -26,6 +26,7 @@
* index_getbitmap - get all tuples from a scan
* index_bulk_delete - bulk deletion of index tuples
* index_vacuum_cleanup - post-deletion cleanup of an index
+ * index_can_return - does index support index-only scans?
* index_getprocid - get a support procedure OID
* index_getprocinfo - get a support procedure's lookup info
*
@@ -712,6 +713,27 @@ index_vacuum_cleanup(IndexVacuumInfo *info,
}
/* ----------------
+ * index_can_return - does index support index-only scans?
+ * ----------------
+ */
+bool
+index_can_return(Relation indexRelation)
+{
+ FmgrInfo *procedure;
+
+ RELATION_CHECKS;
+
+ /* amcanreturn is optional; assume FALSE if not provided by AM */
+ if (!RegProcedureIsValid(indexRelation->rd_am->amcanreturn))
+ return false;
+
+ GET_REL_PROCEDURE(amcanreturn);
+
+ return DatumGetBool(FunctionCall1(procedure,
+ PointerGetDatum(indexRelation)));
+}
+
+/* ----------------
* index_getprocid
*
* Index access methods typically require support routines that are
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index f3a1d256a05..13c05525179 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -1091,3 +1091,14 @@ restart:
goto restart;
}
}
+
+/*
+ * btcanreturn() -- Check whether btree indexes support index-only scans.
+ *
+ * btrees always do, so this is trivial.
+ */
+Datum
+btcanreturn(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_BOOL(true);
+}
diff --git a/src/backend/access/spgist/spgscan.c b/src/backend/access/spgist/spgscan.c
index ac309649682..748265ecba7 100644
--- a/src/backend/access/spgist/spgscan.c
+++ b/src/backend/access/spgist/spgscan.c
@@ -559,3 +559,10 @@ spggettuple(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(false);
}
+
+Datum
+spgcanreturn(PG_FUNCTION_ARGS)
+{
+ /* Not implemented yet */
+ PG_RETURN_BOOL(false);
+}
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 74bc7ac7c63..fa6749a2f9c 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -1075,10 +1075,10 @@ check_index_only(RelOptInfo *rel, IndexOptInfo *index)
ListCell *lc;
int i;
- /* Index-only scans must be enabled, and AM must be capable of it */
+ /* Index-only scans must be enabled, and index must be capable of them */
if (!enable_indexonlyscan)
return false;
- if (!index->amcanreturn)
+ if (!index->canreturn)
return false;
/*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index de629e93c9a..77080192efd 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -212,8 +212,8 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
info->relam = indexRelation->rd_rel->relam;
info->amcostestimate = indexRelation->rd_am->amcostestimate;
+ info->canreturn = index_can_return(indexRelation);
info->amcanorderbyop = indexRelation->rd_am->amcanorderbyop;
- info->amcanreturn = indexRelation->rd_am->amcanreturn;
info->amoptionalkey = indexRelation->rd_am->amoptionalkey;
info->amsearcharray = indexRelation->rd_am->amsearcharray;
info->amsearchnulls = indexRelation->rd_am->amsearchnulls;
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
index dd62680dd54..48ebf1986c9 100644
--- a/src/include/access/genam.h
+++ b/src/include/access/genam.h
@@ -156,6 +156,7 @@ extern IndexBulkDeleteResult *index_bulk_delete(IndexVacuumInfo *info,
void *callback_state);
extern IndexBulkDeleteResult *index_vacuum_cleanup(IndexVacuumInfo *info,
IndexBulkDeleteResult *stats);
+extern bool index_can_return(Relation indexRelation);
extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum,
uint16 procnum);
extern FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum,
diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h
index 9a751ce1004..3a3ff61e571 100644
--- a/src/include/access/nbtree.h
+++ b/src/include/access/nbtree.h
@@ -607,6 +607,7 @@ extern Datum btmarkpos(PG_FUNCTION_ARGS);
extern Datum btrestrpos(PG_FUNCTION_ARGS);
extern Datum btbulkdelete(PG_FUNCTION_ARGS);
extern Datum btvacuumcleanup(PG_FUNCTION_ARGS);
+extern Datum btcanreturn(PG_FUNCTION_ARGS);
extern Datum btoptions(PG_FUNCTION_ARGS);
/*
diff --git a/src/include/access/spgist.h b/src/include/access/spgist.h
index aa655a31402..df6fec6cf45 100644
--- a/src/include/access/spgist.h
+++ b/src/include/access/spgist.h
@@ -182,6 +182,7 @@ extern Datum spgmarkpos(PG_FUNCTION_ARGS);
extern Datum spgrestrpos(PG_FUNCTION_ARGS);
extern Datum spggetbitmap(PG_FUNCTION_ARGS);
extern Datum spggettuple(PG_FUNCTION_ARGS);
+extern Datum spgcanreturn(PG_FUNCTION_ARGS);
/* spgutils.c */
extern Datum spgoptions(PG_FUNCTION_ARGS);
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index fd424fa8d0c..8bb4c5c58cd 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201112172
+#define CATALOG_VERSION_NO 201112181
#endif
diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h
index 6fdd1d5b052..2289a8e6435 100644
--- a/src/include/catalog/pg_am.h
+++ b/src/include/catalog/pg_am.h
@@ -45,7 +45,6 @@ CATALOG(pg_am,2601)
bool amcanbackward; /* does AM support backward scan? */
bool amcanunique; /* does AM support UNIQUE indexes? */
bool amcanmulticol; /* does AM support multi-column indexes? */
- bool amcanreturn; /* can AM return IndexTuples? */
bool amoptionalkey; /* can query omit key for the first column? */
bool amsearcharray; /* can AM handle ScalarArrayOpExpr quals? */
bool amsearchnulls; /* can AM search for NULL/NOT NULL entries? */
@@ -65,6 +64,7 @@ CATALOG(pg_am,2601)
regproc ambuildempty; /* "build empty index" function */
regproc ambulkdelete; /* bulk-delete function */
regproc amvacuumcleanup; /* post-VACUUM cleanup function */
+ regproc amcanreturn; /* can indexscan return IndexTuples? */
regproc amcostestimate; /* estimate cost of an indexscan */
regproc amoptions; /* parse AM-specific parameters */
} FormData_pg_am;
@@ -89,26 +89,26 @@ typedef FormData_pg_am *Form_pg_am;
#define Anum_pg_am_amcanbackward 6
#define Anum_pg_am_amcanunique 7
#define Anum_pg_am_amcanmulticol 8
-#define Anum_pg_am_amcanreturn 9
-#define Anum_pg_am_amoptionalkey 10
-#define Anum_pg_am_amsearcharray 11
-#define Anum_pg_am_amsearchnulls 12
-#define Anum_pg_am_amstorage 13
-#define Anum_pg_am_amclusterable 14
-#define Anum_pg_am_ampredlocks 15
-#define Anum_pg_am_amkeytype 16
-#define Anum_pg_am_aminsert 17
-#define Anum_pg_am_ambeginscan 18
-#define Anum_pg_am_amgettuple 19
-#define Anum_pg_am_amgetbitmap 20
-#define Anum_pg_am_amrescan 21
-#define Anum_pg_am_amendscan 22
-#define Anum_pg_am_ammarkpos 23
-#define Anum_pg_am_amrestrpos 24
-#define Anum_pg_am_ambuild 25
-#define Anum_pg_am_ambuildempty 26
-#define Anum_pg_am_ambulkdelete 27
-#define Anum_pg_am_amvacuumcleanup 28
+#define Anum_pg_am_amoptionalkey 9
+#define Anum_pg_am_amsearcharray 10
+#define Anum_pg_am_amsearchnulls 11
+#define Anum_pg_am_amstorage 12
+#define Anum_pg_am_amclusterable 13
+#define Anum_pg_am_ampredlocks 14
+#define Anum_pg_am_amkeytype 15
+#define Anum_pg_am_aminsert 16
+#define Anum_pg_am_ambeginscan 17
+#define Anum_pg_am_amgettuple 18
+#define Anum_pg_am_amgetbitmap 19
+#define Anum_pg_am_amrescan 20
+#define Anum_pg_am_amendscan 21
+#define Anum_pg_am_ammarkpos 22
+#define Anum_pg_am_amrestrpos 23
+#define Anum_pg_am_ambuild 24
+#define Anum_pg_am_ambuildempty 25
+#define Anum_pg_am_ambulkdelete 26
+#define Anum_pg_am_amvacuumcleanup 27
+#define Anum_pg_am_amcanreturn 28
#define Anum_pg_am_amcostestimate 29
#define Anum_pg_am_amoptions 30
@@ -117,19 +117,19 @@ typedef FormData_pg_am *Form_pg_am;
* ----------------
*/
-DATA(insert OID = 403 ( btree 5 2 t f t t t t t t t f t t 0 btinsert btbeginscan btgettuple btgetbitmap btrescan btendscan btmarkpos btrestrpos btbuild btbuildempty btbulkdelete btvacuumcleanup btcostestimate btoptions ));
+DATA(insert OID = 403 ( btree 5 2 t f t t t t t t f t t 0 btinsert btbeginscan btgettuple btgetbitmap btrescan btendscan btmarkpos btrestrpos btbuild btbuildempty btbulkdelete btvacuumcleanup btcanreturn btcostestimate btoptions ));
DESCR("b-tree index access method");
#define BTREE_AM_OID 403
-DATA(insert OID = 405 ( hash 1 1 f f t f f f f f f f f f 23 hashinsert hashbeginscan hashgettuple hashgetbitmap hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbuildempty hashbulkdelete hashvacuumcleanup hashcostestimate hashoptions ));
+DATA(insert OID = 405 ( hash 1 1 f f t f f f f f f f f 23 hashinsert hashbeginscan hashgettuple hashgetbitmap hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbuildempty hashbulkdelete hashvacuumcleanup - hashcostestimate hashoptions ));
DESCR("hash index access method");
#define HASH_AM_OID 405
-DATA(insert OID = 783 ( gist 0 8 f t f f t f t f t t t f 0 gistinsert gistbeginscan gistgettuple gistgetbitmap gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbuildempty gistbulkdelete gistvacuumcleanup gistcostestimate gistoptions ));
+DATA(insert OID = 783 ( gist 0 8 f t f f t t f t t t f 0 gistinsert gistbeginscan gistgettuple gistgetbitmap gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbuildempty gistbulkdelete gistvacuumcleanup - gistcostestimate gistoptions ));
DESCR("GiST index access method");
#define GIST_AM_OID 783
-DATA(insert OID = 2742 ( gin 0 5 f f f f t f t f f t f f 0 gininsert ginbeginscan - gingetbitmap ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbuildempty ginbulkdelete ginvacuumcleanup gincostestimate ginoptions ));
+DATA(insert OID = 2742 ( gin 0 5 f f f f t t f f t f f 0 gininsert ginbeginscan - gingetbitmap ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbuildempty ginbulkdelete ginvacuumcleanup - gincostestimate ginoptions ));
DESCR("GIN index access method");
#define GIN_AM_OID 2742
-DATA(insert OID = 4000 ( spgist 0 5 f f f f f f f f f f f f 0 spginsert spgbeginscan spggettuple spggetbitmap spgrescan spgendscan spgmarkpos spgrestrpos spgbuild spgbuildempty spgbulkdelete spgvacuumcleanup spgcostestimate spgoptions ));
+DATA(insert OID = 4000 ( spgist 0 5 f f f f f f f f f f f 0 spginsert spgbeginscan spggettuple spggetbitmap spgrescan spgendscan spgmarkpos spgrestrpos spgbuild spgbuildempty spgbulkdelete spgvacuumcleanup spgcanreturn spgcostestimate spgoptions ));
DESCR("SP-GiST index access method");
#define SPGIST_AM_OID 4000
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 6da3b421ae3..60e9feb2e32 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -546,6 +546,8 @@ DATA(insert OID = 332 ( btbulkdelete PGNSP PGUID 12 1 0 0 0 f f f t f v 4 0
DESCR("btree(internal)");
DATA(insert OID = 972 ( btvacuumcleanup PGNSP PGUID 12 1 0 0 0 f f f t f v 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ btvacuumcleanup _null_ _null_ _null_ ));
DESCR("btree(internal)");
+DATA(insert OID = 276 ( btcanreturn PGNSP PGUID 12 1 0 0 0 f f f t f s 1 0 16 "2281" _null_ _null_ _null_ _null_ btcanreturn _null_ _null_ _null_ ));
+DESCR("btree(internal)");
DATA(insert OID = 1268 ( btcostestimate PGNSP PGUID 12 1 0 0 0 f f f t f v 9 0 2278 "2281 2281 2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ _null_ btcostestimate _null_ _null_ _null_ ));
DESCR("btree(internal)");
DATA(insert OID = 2785 ( btoptions PGNSP PGUID 12 1 0 0 0 f f f t f s 2 0 17 "1009 16" _null_ _null_ _null_ _null_ btoptions _null_ _null_ _null_ ));
@@ -4506,6 +4508,8 @@ DATA(insert OID = 4011 ( spgbulkdelete PGNSP PGUID 12 1 0 0 0 f f f t f v 4
DESCR("spgist(internal)");
DATA(insert OID = 4012 ( spgvacuumcleanup PGNSP PGUID 12 1 0 0 0 f f f t f v 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ spgvacuumcleanup _null_ _null_ _null_ ));
DESCR("spgist(internal)");
+DATA(insert OID = 4032 ( spgcanreturn PGNSP PGUID 12 1 0 0 0 f f f t f s 1 0 16 "2281" _null_ _null_ _null_ _null_ spgcanreturn _null_ _null_ _null_ ));
+DESCR("spgist(internal)");
DATA(insert OID = 4013 ( spgcostestimate PGNSP PGUID 12 1 0 0 0 f f f t f v 9 0 2278 "2281 2281 2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ _null_ spgcostestimate _null_ _null_ _null_ ));
DESCR("spgist(internal)");
DATA(insert OID = 4014 ( spgoptions PGNSP PGUID 12 1 0 0 0 f f f t f s 2 0 17 "1009 16" _null_ _null_ _null_ _null_ spgoptions _null_ _null_ _null_ ));
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index a400960a272..74c060b9b66 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -490,8 +490,8 @@ typedef struct IndexOptInfo
bool unique; /* true if a unique index */
bool immediate; /* is uniqueness enforced immediately? */
bool hypothetical; /* true if index doesn't really exist */
+ bool canreturn; /* can index return IndexTuples? */
bool amcanorderbyop; /* does AM support order by operator result? */
- bool amcanreturn; /* can AM return IndexTuples? */
bool amoptionalkey; /* can query omit key for the first column? */
bool amsearcharray; /* can AM handle ScalarArrayOpExpr quals? */
bool amsearchnulls; /* can AM search for NULL/NOT NULL entries? */
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 173dc16a253..70d16eb01e4 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -64,6 +64,7 @@ typedef struct RelationAmInfo
FmgrInfo ambuildempty;
FmgrInfo ambulkdelete;
FmgrInfo amvacuumcleanup;
+ FmgrInfo amcanreturn;
FmgrInfo amcostestimate;
FmgrInfo amoptions;
} RelationAmInfo;