aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/utils/cache/lsyscache.c24
-rw-r--r--src/backend/utils/cache/partcache.c48
-rw-r--r--src/include/utils/lsyscache.h1
-rw-r--r--src/test/regress/expected/indexing.out19
-rw-r--r--src/test/regress/sql/indexing.sql2
5 files changed, 75 insertions, 19 deletions
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index bba595ad1da..82d39e94980 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -1821,6 +1821,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/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c
index e35a43405eb..5757301d054 100644
--- a/src/backend/utils/cache/partcache.c
+++ b/src/backend/utils/cache/partcache.c
@@ -797,31 +797,38 @@ RelationGetPartitionQual(Relation rel)
* get_partition_qual_relid
*
* Returns an expression tree describing the passed-in relation's partition
- * constraint. If there is no partition constraint returns NULL; this can
- * happen if the default partition is the only 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 can happen even if relispartition is true, when a default
+ * partition is the only partition.
*/
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);
+ /* 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;
}
@@ -845,7 +852,6 @@ generate_partition_qual(Relation rel)
MemoryContext oldcxt;
Datum boundDatum;
bool isnull;
- PartitionBoundSpec *bound;
List *my_qual = NIL,
*result = NIL;
Relation parent;
@@ -859,8 +865,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));
@@ -871,13 +877,17 @@ generate_partition_qual(Relation rel)
boundDatum = SysCacheGetAttr(RELOID, tuple,
Anum_pg_class_relpartbound,
&isnull);
- if (isnull)
- elog(ERROR, "null relpartbound for relation %u", RelationGetRelid(rel));
- bound = castNode(PartitionBoundSpec,
- stringToNode(TextDatumGetCString(boundDatum)));
- ReleaseSysCache(tuple);
+ if (!isnull)
+ {
+ PartitionBoundSpec *bound;
+
+ bound = castNode(PartitionBoundSpec,
+ stringToNode(TextDatumGetCString(boundDatum)));
- my_qual = get_qual_from_partbound(rel, parent, bound);
+ my_qual = get_qual_from_partbound(rel, parent, bound);
+ }
+
+ ReleaseSysCache(tuple);
/* Add the parent's quals to the list (if any) */
if (parent->rd_rel->relispartition)
@@ -903,7 +913,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/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index e55ea4035b8..e868d84cef6 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);
diff --git a/src/test/regress/expected/indexing.out b/src/test/regress/expected/indexing.out
index b9297c98d29..8ab543ae317 100644
--- a/src/test/regress/expected/indexing.out
+++ b/src/test/regress/expected/indexing.out
@@ -75,6 +75,25 @@ Indexes:
"idxpart1_a_idx" btree (a)
"idxpart1_b_c_idx" btree (b, c)
+\d+ idxpart1_a_idx
+ Index "public.idxpart1_a_idx"
+ Column | Type | Key? | Definition | Storage | Stats target
+--------+---------+------+------------+---------+--------------
+ a | integer | yes | a | plain |
+Partition of: idxparti
+No partition constraint
+btree, for table "public.idxpart1"
+
+\d+ idxpart1_b_c_idx
+ Index "public.idxpart1_b_c_idx"
+ Column | Type | Key? | Definition | Storage | Stats target
+--------+---------+------+------------+----------+--------------
+ b | integer | yes | b | plain |
+ c | text | yes | c | extended |
+Partition of: idxparti2
+No partition constraint
+btree, for table "public.idxpart1"
+
drop table idxpart;
-- If a partition already has an index, don't create a duplicative one
create table idxpart (a int, b int) partition by range (a, b);
diff --git a/src/test/regress/sql/indexing.sql b/src/test/regress/sql/indexing.sql
index 2091a87ff59..48b88532194 100644
--- a/src/test/regress/sql/indexing.sql
+++ b/src/test/regress/sql/indexing.sql
@@ -44,6 +44,8 @@ create table idxpart1 (like idxpart);
\d idxpart1
alter table idxpart attach partition idxpart1 for values from (0) to (10);
\d idxpart1
+\d+ idxpart1_a_idx
+\d+ idxpart1_b_c_idx
drop table idxpart;
-- If a partition already has an index, don't create a duplicative one