aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-09-19 23:32:27 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2017-09-19 23:32:59 -0400
commitd3a4f89d8a3e500bd7c0b7a8a8a5ce1b47859128 (patch)
tree70fb69ae101513a3b225629ef3c6b75f838c2896 /src
parent896537f078ba4d709ce754ecaff8350fd55bdfd8 (diff)
downloadpostgresql-d3a4f89d8a3e500bd7c0b7a8a8a5ce1b47859128.tar.gz
postgresql-d3a4f89d8a3e500bd7c0b7a8a8a5ce1b47859128.zip
Allow no-op GiST support functions to be omitted.
There are common use-cases in which the compress and/or decompress functions can be omitted, with the result being that we make no data transformation when storing or retrieving index values. Previously, you had to provide a no-op function anyway, but this patch allows such opclass support functions to be omitted. Furthermore, if the compress function is omitted, then the core code knows that the stored representation is the same as the original data. This means we can allow index-only scans without requiring a fetch function to be provided either. Previously you had to provide a no-op fetch function if you wanted IOS to work. This reportedly provides a small performance benefit in such cases, but IMO the real reason for doing it is just to reduce the amount of useless boilerplate code that has to be written for GiST opclasses. Andrey Borodin, reviewed by Dmitriy Sarafannikov Discussion: https://postgr.es/m/CAJEAwVELVx9gYscpE=Be6iJxvdW5unZ_LkcAaVNSeOwvdwtD=A@mail.gmail.com
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/gist/gist.c24
-rw-r--r--src/backend/access/gist/gistget.c4
-rw-r--r--src/backend/access/gist/gistutil.c42
-rw-r--r--src/backend/access/gist/gistvalidate.c3
4 files changed, 61 insertions, 12 deletions
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 565525bbdfc..aec174cd006 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -1453,12 +1453,23 @@ initGISTstate(Relation index)
fmgr_info_copy(&(giststate->unionFn[i]),
index_getprocinfo(index, i + 1, GIST_UNION_PROC),
scanCxt);
- fmgr_info_copy(&(giststate->compressFn[i]),
- index_getprocinfo(index, i + 1, GIST_COMPRESS_PROC),
- scanCxt);
- fmgr_info_copy(&(giststate->decompressFn[i]),
- index_getprocinfo(index, i + 1, GIST_DECOMPRESS_PROC),
- scanCxt);
+
+ /* opclasses are not required to provide a Compress method */
+ if (OidIsValid(index_getprocid(index, i + 1, GIST_COMPRESS_PROC)))
+ fmgr_info_copy(&(giststate->compressFn[i]),
+ index_getprocinfo(index, i + 1, GIST_COMPRESS_PROC),
+ scanCxt);
+ else
+ giststate->compressFn[i].fn_oid = InvalidOid;
+
+ /* opclasses are not required to provide a Decompress method */
+ if (OidIsValid(index_getprocid(index, i + 1, GIST_DECOMPRESS_PROC)))
+ fmgr_info_copy(&(giststate->decompressFn[i]),
+ index_getprocinfo(index, i + 1, GIST_DECOMPRESS_PROC),
+ scanCxt);
+ else
+ giststate->decompressFn[i].fn_oid = InvalidOid;
+
fmgr_info_copy(&(giststate->penaltyFn[i]),
index_getprocinfo(index, i + 1, GIST_PENALTY_PROC),
scanCxt);
@@ -1468,6 +1479,7 @@ initGISTstate(Relation index)
fmgr_info_copy(&(giststate->equalFn[i]),
index_getprocinfo(index, i + 1, GIST_EQUAL_PROC),
scanCxt);
+
/* opclasses are not required to provide a Distance method */
if (OidIsValid(index_getprocid(index, i + 1, GIST_DISTANCE_PROC)))
fmgr_info_copy(&(giststate->distanceFn[i]),
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index 760ea0c997e..06dac0bb53d 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -801,11 +801,13 @@ gistgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
* Can we do index-only scans on the given index column?
*
* Opclasses that implement a fetch function support index-only scans.
+ * Opclasses without compression functions also support index-only scans.
*/
bool
gistcanreturn(Relation index, int attno)
{
- if (OidIsValid(index_getprocid(index, attno, GIST_FETCH_PROC)))
+ if (OidIsValid(index_getprocid(index, attno, GIST_FETCH_PROC)) ||
+ !OidIsValid(index_getprocid(index, attno, GIST_COMPRESS_PROC)))
return true;
else
return false;
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index b6ccc1a66a1..26d89f79ae6 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -550,6 +550,11 @@ gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e,
GISTENTRY *dep;
gistentryinit(*e, k, r, pg, o, l);
+
+ /* there may not be a decompress function in opclass */
+ if (!OidIsValid(giststate->decompressFn[nkey].fn_oid))
+ return;
+
dep = (GISTENTRY *)
DatumGetPointer(FunctionCall1Coll(&giststate->decompressFn[nkey],
giststate->supportCollation[nkey],
@@ -585,10 +590,14 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
gistentryinit(centry, attdata[i], r, NULL, (OffsetNumber) 0,
isleaf);
- cep = (GISTENTRY *)
- DatumGetPointer(FunctionCall1Coll(&giststate->compressFn[i],
- giststate->supportCollation[i],
- PointerGetDatum(&centry)));
+ /* there may not be a compress function in opclass */
+ if (OidIsValid(giststate->compressFn[i].fn_oid))
+ cep = (GISTENTRY *)
+ DatumGetPointer(FunctionCall1Coll(&giststate->compressFn[i],
+ giststate->supportCollation[i],
+ PointerGetDatum(&centry)));
+ else
+ cep = &centry;
compatt[i] = cep->key;
}
}
@@ -648,6 +657,17 @@ gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
else
fetchatt[i] = (Datum) 0;
}
+ else if (giststate->compressFn[i].fn_oid == InvalidOid)
+ {
+ /*
+ * If opclass does not provide compress method that could change
+ * original value, att is necessarily stored in original form.
+ */
+ if (!isnull[i])
+ fetchatt[i] = datum;
+ else
+ fetchatt[i] = (Datum) 0;
+ }
else
{
/*
@@ -934,6 +954,20 @@ gistproperty(Oid index_oid, int attno,
ObjectIdGetDatum(opcintype),
ObjectIdGetDatum(opcintype),
Int16GetDatum(procno));
+
+ /*
+ * Special case: even without a fetch function, AMPROP_RETURNABLE is true
+ * if the opclass has no compress function.
+ */
+ if (prop == AMPROP_RETURNABLE && !*res)
+ {
+ *res = !SearchSysCacheExists4(AMPROCNUM,
+ ObjectIdGetDatum(opfamily),
+ ObjectIdGetDatum(opcintype),
+ ObjectIdGetDatum(opcintype),
+ Int16GetDatum(GIST_COMPRESS_PROC));
+ }
+
return true;
}
diff --git a/src/backend/access/gist/gistvalidate.c b/src/backend/access/gist/gistvalidate.c
index 42254c5f153..42f91ac0c96 100644
--- a/src/backend/access/gist/gistvalidate.c
+++ b/src/backend/access/gist/gistvalidate.c
@@ -258,7 +258,8 @@ gistvalidate(Oid opclassoid)
if (opclassgroup &&
(opclassgroup->functionset & (((uint64) 1) << i)) != 0)
continue; /* got it */
- if (i == GIST_DISTANCE_PROC || i == GIST_FETCH_PROC)
+ if (i == GIST_DISTANCE_PROC || i == GIST_FETCH_PROC ||
+ i == GIST_COMPRESS_PROC || i == GIST_DECOMPRESS_PROC)
continue; /* optional methods */
ereport(INFO,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),