diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/catalog/partition.c | 32 | ||||
-rw-r--r-- | src/backend/utils/cache/lsyscache.c | 24 | ||||
-rw-r--r-- | src/include/utils/lsyscache.h | 1 |
3 files changed, 46 insertions, 11 deletions
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index 627b09f01e9..8219d05d830 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -959,26 +959,36 @@ RelationGetPartitionQual(Relation rel) * * Returns an expression tree describing the passed-in relation's partition * constraint. + * + * If the relation is not found, or is not a partition, or there is no + * partition constraint, return NULL. We must guard against the first two + * cases because this supports a SQL function that could be passed any OID. + * The last case shouldn't happen in v10, but cope anyway. */ Expr * get_partition_qual_relid(Oid relid) { - Relation rel = heap_open(relid, AccessShareLock); Expr *result = NULL; - List *and_args; - /* Do the work only if this relation is a partition. */ - if (rel->rd_rel->relispartition) + /* Do the work only if this relation exists and is a partition. */ + if (get_rel_relispartition(relid)) { + Relation rel = relation_open(relid, AccessShareLock); + List *and_args; + and_args = generate_partition_qual(rel); - if (list_length(and_args) > 1) + + /* Convert implicit-AND list format to boolean expression */ + if (and_args == NIL) + result = NULL; + else if (list_length(and_args) > 1) result = makeBoolExpr(AND_EXPR, and_args, -1); else result = linitial(and_args); - } - /* Keep the lock. */ - heap_close(rel, NoLock); + /* Keep the lock, to allow safe deparsing against the rel by caller. */ + relation_close(rel, NoLock); + } return result; } @@ -1833,8 +1843,8 @@ generate_partition_qual(Relation rel) return copyObject(rel->rd_partcheck); /* Grab at least an AccessShareLock on the parent table */ - parent = heap_open(get_partition_parent(RelationGetRelid(rel)), - AccessShareLock); + parent = relation_open(get_partition_parent(RelationGetRelid(rel)), + AccessShareLock); /* Get pg_class.relpartbound */ tuple = SearchSysCache1(RELOID, RelationGetRelid(rel)); @@ -1878,7 +1888,7 @@ generate_partition_qual(Relation rel) MemoryContextSwitchTo(oldcxt); /* Keep the parent locked until commit */ - heap_close(parent, NoLock); + relation_close(parent, NoLock); return result; } diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 82763f8013d..7694c6894b9 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -1817,6 +1817,30 @@ get_rel_relkind(Oid relid) } /* + * get_rel_relispartition + * + * Returns the relispartition flag associated with a given relation. + */ +bool +get_rel_relispartition(Oid relid) +{ + HeapTuple tp; + + tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + if (HeapTupleIsValid(tp)) + { + Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp); + bool result; + + result = reltup->relispartition; + ReleaseSysCache(tp); + return result; + } + else + return false; +} + +/* * get_rel_tablespace * * Returns the pg_tablespace OID associated with a given relation. diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 07208b56cef..16ec85b300f 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -126,6 +126,7 @@ extern char *get_rel_name(Oid relid); extern Oid get_rel_namespace(Oid relid); extern Oid get_rel_type_id(Oid relid); extern char get_rel_relkind(Oid relid); +extern bool get_rel_relispartition(Oid relid); extern Oid get_rel_tablespace(Oid relid); extern char get_rel_persistence(Oid relid); extern Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes); |