]> granicus.if.org Git - postgresql/commitdiff
Fix bogus code for extracting extended-statistics data from syscache.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 2 May 2018 16:22:48 +0000 (12:22 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 2 May 2018 16:22:48 +0000 (12:22 -0400)
statext_dependencies_load and statext_ndistinct_load were not up to snuff,
in addition to being randomly different from each other.  In detail:

* Deserialize the fetched bytea value before releasing the syscache
entry, not after.  This mistake causes visible regression test failures
when running with -DCATCACHE_FORCE_RELEASE.  Since it's not exposed by
-DCLOBBER_CACHE_ALWAYS, I think there may be no production hazard here
at present, but it's at least a latent bug.

* Use DatumGetByteaPP not DatumGetByteaP to save a detoasting cycle
for short stats values; the deserialize function has to be, and is,
prepared for short-header values since its other caller uses PP.

* Use a test-and-elog for null stats values in both functions, rather
than a test-and-elog in one case and an Assert in the other.  Perhaps
Asserts would be sufficient in both cases, but I don't see a good
argument for them being different.

* Minor cosmetic changes to make these functions more visibly alike.

Backpatch to v10 where this code came in.

Amit Langote, minor additional hacking by me

Discussion: https://postgr.es/m/1349aabb-3a1f-6675-9fc0-65e2ce7491dd@lab.ntt.co.jp

src/backend/statistics/dependencies.c
src/backend/statistics/mvdistinct.c

index ae0f304dba56d4ce11ff0fb071ff7585fa776b37..99975817de9dd1ac24b2460fd24ef8c544cce4d7 100644 (file)
@@ -631,20 +631,27 @@ dependency_implies_attribute(MVDependency *dependency, AttrNumber attnum)
 MVDependencies *
 statext_dependencies_load(Oid mvoid)
 {
+       MVDependencies *result;
        bool            isnull;
        Datum           deps;
-       HeapTuple       htup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(mvoid));
+       HeapTuple       htup;
 
+       htup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(mvoid));
        if (!HeapTupleIsValid(htup))
                elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
 
        deps = SysCacheGetAttr(STATEXTOID, htup,
                                                   Anum_pg_statistic_ext_stxdependencies, &isnull);
-       Assert(!isnull);
+       if (isnull)
+               elog(ERROR,
+                        "requested statistic kind \"%c\" is not yet built for statistics object %u",
+                        STATS_EXT_DEPENDENCIES, mvoid);
+
+       result = statext_dependencies_deserialize(DatumGetByteaPP(deps));
 
        ReleaseSysCache(htup);
 
-       return statext_dependencies_deserialize(DatumGetByteaP(deps));
+       return result;
 }
 
 /*
index 913829233eca4e2e92c6bbf8141c7f5c86bc5e49..74ab62d91a833517c847c59bcfce9e97cec29b06 100644 (file)
@@ -126,24 +126,27 @@ statext_ndistinct_build(double totalrows, int numrows, HeapTuple *rows,
 MVNDistinct *
 statext_ndistinct_load(Oid mvoid)
 {
-       bool            isnull = false;
+       MVNDistinct *result;
+       bool            isnull;
        Datum           ndist;
        HeapTuple       htup;
 
        htup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(mvoid));
-       if (!htup)
+       if (!HeapTupleIsValid(htup))
                elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
 
        ndist = SysCacheGetAttr(STATEXTOID, htup,
                                                        Anum_pg_statistic_ext_stxndistinct, &isnull);
        if (isnull)
                elog(ERROR,
-                        "requested statistic kind %c is not yet built for statistics object %u",
+                        "requested statistic kind \"%c\" is not yet built for statistics object %u",
                         STATS_EXT_NDISTINCT, mvoid);
 
+       result = statext_ndistinct_deserialize(DatumGetByteaPP(ndist));
+
        ReleaseSysCache(htup);
 
-       return statext_ndistinct_deserialize(DatumGetByteaP(ndist));
+       return result;
 }
 
 /*