diff options
author | Peter Eisentraut <peter@eisentraut.org> | 2024-03-17 05:58:04 +0100 |
---|---|---|
committer | Peter Eisentraut <peter@eisentraut.org> | 2024-03-17 05:58:04 +0100 |
commit | 20e58105badff383bd43f0b97e532771768f94df (patch) | |
tree | 4bff7fadb1d4fbf269477787dae80b81c27c4596 /src/backend/access/common/tupdesc.c | |
parent | b7831865159d5fb6f0d263e6023f0986589fe254 (diff) | |
download | postgresql-20e58105badff383bd43f0b97e532771768f94df.tar.gz postgresql-20e58105badff383bd43f0b97e532771768f94df.zip |
Separate equalRowTypes() from equalTupleDescs()
This introduces a new function equalRowTypes() that is effectively a
subset of equalTupleDescs() but only compares the number of attributes
and attribute name, type, typmod, and collation. This is enough for
most existing uses of equalTupleDescs(), which are changed to use the
new function. The only remaining callers of equalTupleDescs() are
those that really want to check the full tuple descriptor as such,
without concern about record or row or record type semantics.
The existing function hashTupleDesc() is renamed to hashRowType(),
because it now corresponds more to equalRowTypes().
The purpose of this change is to be clearer about the semantics of the
equality asked for by each caller. (At least one caller had a comment
that questioned whether equalTupleDescs() was too restrictive.) For
example, 4f622503d6d removed attstattarget from the tuple descriptor
structure. It was not fully clear at the time how this should affect
equalTupleDescs(). Now the answer is clear: By their own definitions,
equalRowTypes() does not care, and equalTupleDescs() just compares
whatever is in the tuple descriptor but does not care why it is in
there.
Reviewed-by: Tomas Vondra <tomas.vondra@enterprisedb.com>
Discussion: https://www.postgresql.org/message-id/flat/f656d6d9-6660-4518-a006-2f65cafbebd1%40eisentraut.org
Diffstat (limited to 'src/backend/access/common/tupdesc.c')
-rw-r--r-- | src/backend/access/common/tupdesc.c | 72 |
1 files changed, 60 insertions, 12 deletions
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index bc80caee117..47379fef220 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -414,11 +414,6 @@ DecrTupleDescRefCount(TupleDesc tupdesc) /* * Compare two TupleDesc structures for logical equality - * - * Note: we deliberately do not check the attrelid and tdtypmod fields. - * This allows typcache.c to use this routine to see if a cached record type - * matches a requested type, and is harmless for relcache.c's uses. - * We don't compare tdrefcount, either. */ bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) @@ -431,6 +426,8 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) if (tupdesc1->tdtypeid != tupdesc2->tdtypeid) return false; + /* tdtypmod and tdrefcount are not checked */ + for (i = 0; i < tupdesc1->natts; i++) { Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i); @@ -561,17 +558,68 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) } /* - * hashTupleDesc - * Compute a hash value for a tuple descriptor. + * equalRowTypes * - * If two tuple descriptors would be considered equal by equalTupleDescs() - * then their hash value will be equal according to this function. + * This determines whether two tuple descriptors have equal row types. This + * only checks those fields in pg_attribute that are applicable for row types, + * while ignoring those fields that define the physical row storage or those + * that define table column metadata. + * + * Specifically, this checks: + * + * - same number of attributes + * - same composite type ID (but could both be zero) + * - corresponding attributes (in order) have same the name, type, typmod, + * collation + * + * This is used to check whether two record types are compatible, whether + * function return row types are the same, and other similar situations. + * + * (XXX There was some discussion whether attndims should be checked here, but + * for now it has been decided not to.) + * + * Note: We deliberately do not check the tdtypmod field. This allows + * typcache.c to use this routine to see if a cached record type matches a + * requested type. + */ +bool +equalRowTypes(TupleDesc tupdesc1, TupleDesc tupdesc2) +{ + if (tupdesc1->natts != tupdesc2->natts) + return false; + if (tupdesc1->tdtypeid != tupdesc2->tdtypeid) + return false; + + for (int i = 0; i < tupdesc1->natts; i++) + { + Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i); + Form_pg_attribute attr2 = TupleDescAttr(tupdesc2, i); + + if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0) + return false; + if (attr1->atttypid != attr2->atttypid) + return false; + if (attr1->atttypmod != attr2->atttypmod) + return false; + if (attr1->attcollation != attr2->attcollation) + return false; + + /* Record types derived from tables could have dropped fields. */ + if (attr1->attisdropped != attr2->attisdropped) + return false; + } + + return true; +} + +/* + * hashRowType * - * Note that currently contents of constraint are not hashed - it'd be a bit - * painful to do so, and conflicts just due to constraints are unlikely. + * If two tuple descriptors would be considered equal by equalRowTypes() + * then their hash value will be equal according to this function. */ uint32 -hashTupleDesc(TupleDesc desc) +hashRowType(TupleDesc desc) { uint32 s; int i; |