summaryrefslogtreecommitdiffstats
path: root/src/backend/commands/statscmds.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/backend/commands/statscmds.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c
index f442d85..fa7a0c0 100644
--- a/src/backend/commands/statscmds.c
+++ b/src/backend/commands/statscmds.c
@@ -735,19 +735,12 @@ void
RemoveStatisticsById(Oid statsOid)
{
Relation relation;
+ Relation rel;
HeapTuple tup;
Form_pg_statistic_ext statext;
Oid relid;
/*
- * First delete the pg_statistic_ext_data tuples holding the actual
- * statistical data. There might be data with/without inheritance, so
- * attempt deleting both.
- */
- RemoveStatisticsDataById(statsOid, true);
- RemoveStatisticsDataById(statsOid, false);
-
- /*
* Delete the pg_statistic_ext tuple. Also send out a cache inval on the
* associated table, so that dependent plans will be rebuilt.
*/
@@ -761,12 +754,26 @@ RemoveStatisticsById(Oid statsOid)
statext = (Form_pg_statistic_ext) GETSTRUCT(tup);
relid = statext->stxrelid;
+ /*
+ * Delete the pg_statistic_ext_data tuples holding the actual statistical
+ * data. There might be data with/without inheritance, so attempt deleting
+ * both. We lock the user table first, to prevent other processes (e.g.
+ * DROP STATISTICS) from removing the row concurrently.
+ */
+ rel = table_open(relid, ShareUpdateExclusiveLock);
+
+ RemoveStatisticsDataById(statsOid, true);
+ RemoveStatisticsDataById(statsOid, false);
+
CacheInvalidateRelcacheByRelid(relid);
CatalogTupleDelete(relation, &tup->t_self);
ReleaseSysCache(tup);
+ /* Keep lock until the end of the transaction. */
+ table_close(rel, NoLock);
+
table_close(relation, RowExclusiveLock);
}