diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2020-11-16 16:39:59 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2020-11-16 16:39:59 -0500 |
commit | fea5960fafb0002ea2a80bed1dc03e3a4f85fa1d (patch) | |
tree | 9481ec27b4dc732b4428441b276fafc3bfa4387f /src/backend/partitioning/partbounds.c | |
parent | 53c7b4f6221be2800ba49840ce29cb1b5c0b1ab7 (diff) |
Do not return NULL for error cases in satisfies_hash_partition().
Since this function is used as a CHECK constraint condition,
returning NULL is tantamount to returning TRUE, which would have the
effect of letting in a row that doesn't satisfy the hash condition.
Admittedly, the cases for which this is done should be unreachable
in practice, but that doesn't make it any less a bad idea. It also
seems like a dartboard was used to decide which error cases should
throw errors as opposed to returning NULL.
For the checks for NULL input values, I just switched it to returning
false. There's some argument that an error would be better; but the
case really should be can't-happen in a generated hash constraint,
so it's likely not worth more code for.
For the parent-relation-open-failure case, it seems like we might
as well let relation_open throw an error, instead of having an
impossible-to-diagnose constraint failure.
Back-patch to v11 where this code came in.
Discussion: https://postgr.es/m/24067.1605134819@sss.pgh.pa.us
Diffstat (limited to 'src/backend/partitioning/partbounds.c')
-rw-r--r-- | src/backend/partitioning/partbounds.c | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c index 3d2d3f4c3da..19d055493ed 100644 --- a/src/backend/partitioning/partbounds.c +++ b/src/backend/partitioning/partbounds.c @@ -4653,6 +4653,8 @@ compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc, Oid *partcoll * * Returns true if remainder produced when this computed single hash value is * divided by the given modulus is equal to given remainder, otherwise false. + * NB: it's important that this never return null, as the constraint machinery + * would consider that to be a "pass". * * See get_qual_for_hash() for usage. */ @@ -4677,9 +4679,9 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) ColumnsHashData *my_extra; uint64 rowHash = 0; - /* Return null if the parent OID, modulus, or remainder is NULL. */ + /* Return false if the parent OID, modulus, or remainder is NULL. */ if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2)) - PG_RETURN_NULL(); + PG_RETURN_BOOL(false); parentId = PG_GETARG_OID(0); modulus = PG_GETARG_INT32(1); remainder = PG_GETARG_INT32(2); @@ -4709,14 +4711,11 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) int j; /* Open parent relation and fetch partition key info */ - parent = try_relation_open(parentId, AccessShareLock); - if (parent == NULL) - PG_RETURN_NULL(); + parent = relation_open(parentId, AccessShareLock); key = RelationGetPartitionKey(parent); /* Reject parent table that is not hash-partitioned. */ - if (parent->rd_rel->relkind != RELKIND_PARTITIONED_TABLE || - key->strategy != PARTITION_STRATEGY_HASH) + if (key == NULL || key->strategy != PARTITION_STRATEGY_HASH) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("\"%s\" is not a hash partitioned table", |