Fix a failure in DROP EXTENSION (#96)
When pg_ivm is dropped, the error "could not open relation with OID ..." occurred at the hook function that enables DROP TABLE on an IMMV to remove the entry in pg_ivm_immv. It was because that the primary key was already dropped at the time pg_ivm_immv's toast is been dropped. Also, DROP TABLE command issued concurrently with DROP EXTENSION pg_Ivm also could cause the same error because pg_ivm_immv could be already dropped. This race condition is fixed by using always RangeVarGetRelidExtended to get OID of pg_ivm_immv instead of using a cache of get_relname_relid results. This makes sure that pg_ivm_immv exists when this is scanned.
This commit is contained in:
parent
36d4a4770e
commit
edde972624
1 changed files with 16 additions and 19 deletions
33
pg_ivm.c
33
pg_ivm.c
|
|
@ -25,6 +25,8 @@
|
||||||
#include "parser/parser.h"
|
#include "parser/parser.h"
|
||||||
#include "parser/scansup.h"
|
#include "parser/scansup.h"
|
||||||
#include "tcop/tcopprot.h"
|
#include "tcop/tcopprot.h"
|
||||||
|
#include "nodes/makefuncs.h"
|
||||||
|
#include "utils/syscache.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/fmgroids.h"
|
#include "utils/fmgroids.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
|
|
@ -36,8 +38,6 @@
|
||||||
|
|
||||||
PG_MODULE_MAGIC;
|
PG_MODULE_MAGIC;
|
||||||
|
|
||||||
static Oid pg_ivm_immv_id = InvalidOid;
|
|
||||||
static Oid pg_ivm_immv_pkey_id = InvalidOid;
|
|
||||||
|
|
||||||
static object_access_hook_type PrevObjectAccessHook = NULL;
|
static object_access_hook_type PrevObjectAccessHook = NULL;
|
||||||
|
|
||||||
|
|
@ -326,10 +326,9 @@ CreateChangePreventTrigger(Oid matviewOid)
|
||||||
Oid
|
Oid
|
||||||
PgIvmImmvRelationId(void)
|
PgIvmImmvRelationId(void)
|
||||||
{
|
{
|
||||||
if (!OidIsValid(pg_ivm_immv_id))
|
return RangeVarGetRelidExtended(
|
||||||
pg_ivm_immv_id = get_relname_relid("pg_ivm_immv", PG_CATALOG_NAMESPACE);
|
makeRangeVar("pg_catalog", "pg_ivm_immv", -1),
|
||||||
|
AccessShareLock, RVR_MISSING_OK, NULL, NULL);
|
||||||
return pg_ivm_immv_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -338,10 +337,9 @@ PgIvmImmvRelationId(void)
|
||||||
Oid
|
Oid
|
||||||
PgIvmImmvPrimaryKeyIndexId(void)
|
PgIvmImmvPrimaryKeyIndexId(void)
|
||||||
{
|
{
|
||||||
if (!OidIsValid(pg_ivm_immv_pkey_id))
|
return RangeVarGetRelidExtended(
|
||||||
pg_ivm_immv_pkey_id = get_relname_relid("pg_ivm_immv_pkey", PG_CATALOG_NAMESPACE);
|
makeRangeVar("pg_catalog", "pg_ivm_immv_pkey", -1),
|
||||||
|
AccessShareLock, RVR_MISSING_OK, NULL, NULL);
|
||||||
return pg_ivm_immv_pkey_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -391,16 +389,15 @@ PgIvmObjectAccessHook(ObjectAccessType access, Oid classId,
|
||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
Oid pgIvmImmvOid = PgIvmImmvRelationId();
|
Oid pgIvmImmvOid = PgIvmImmvRelationId();
|
||||||
|
|
||||||
/* pg_ivm_immv is not created yet, so there are no IMMVs, either. */
|
Oid pgIvmImmvPkOid = PgIvmImmvPrimaryKeyIndexId();
|
||||||
if (pgIvmImmvOid == InvalidOid)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When the dropped table is pg_ivm_immv, we don't need to continue
|
* Index or table not yet created (so no IMMVs yet), already dropped
|
||||||
* any more. Also, in this case, the index on it is already dropped,
|
* (expect IMMVs also gone soon), or renamed. It's not great that a
|
||||||
* so the index scan below will fail and raise an error.
|
* rename of either object will silently break IMMVs, but that's
|
||||||
|
* better than ERROR below.
|
||||||
*/
|
*/
|
||||||
if (objectId == pgIvmImmvOid)
|
if (pgIvmImmvPkOid == InvalidOid || pgIvmImmvOid == InvalidOid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pgIvmImmv = table_open(pgIvmImmvOid, AccessShareLock);
|
pgIvmImmv = table_open(pgIvmImmvOid, AccessShareLock);
|
||||||
|
|
@ -408,7 +405,7 @@ PgIvmObjectAccessHook(ObjectAccessType access, Oid classId,
|
||||||
Anum_pg_ivm_immv_immvrelid,
|
Anum_pg_ivm_immv_immvrelid,
|
||||||
BTEqualStrategyNumber, F_OIDEQ,
|
BTEqualStrategyNumber, F_OIDEQ,
|
||||||
ObjectIdGetDatum(objectId));
|
ObjectIdGetDatum(objectId));
|
||||||
scan = systable_beginscan(pgIvmImmv, PgIvmImmvPrimaryKeyIndexId(),
|
scan = systable_beginscan(pgIvmImmv, pgIvmImmvPkOid,
|
||||||
true, NULL, 1, &key);
|
true, NULL, 1, &key);
|
||||||
|
|
||||||
tup = systable_getnext(scan);
|
tup = systable_getnext(scan);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue