* 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;
}
MemoryContext oldcxt;
Datum boundDatum;
bool isnull;
- PartitionBoundSpec *bound;
List *my_qual = NIL,
*result = NIL;
Relation parent;
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));
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)
MemoryContextSwitchTo(oldcxt);
/* Keep the parent locked until commit */
- heap_close(parent, NoLock);
+ relation_close(parent, NoLock);
return result;
}
"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);