Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 20e5810

Browse files
committed
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, 4f62250 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
1 parent b783186 commit 20e5810

File tree

7 files changed

+79
-32
lines changed

7 files changed

+79
-32
lines changed

src/backend/access/common/tupdesc.c

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -414,11 +414,6 @@ DecrTupleDescRefCount(TupleDesc tupdesc)
414414

415415
/*
416416
* Compare two TupleDesc structures for logical equality
417-
*
418-
* Note: we deliberately do not check the attrelid and tdtypmod fields.
419-
* This allows typcache.c to use this routine to see if a cached record type
420-
* matches a requested type, and is harmless for relcache.c's uses.
421-
* We don't compare tdrefcount, either.
422417
*/
423418
bool
424419
equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
@@ -431,6 +426,8 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
431426
if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
432427
return false;
433428

429+
/* tdtypmod and tdrefcount are not checked */
430+
434431
for (i = 0; i < tupdesc1->natts; i++)
435432
{
436433
Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i);
@@ -561,17 +558,68 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
561558
}
562559

563560
/*
564-
* hashTupleDesc
565-
* Compute a hash value for a tuple descriptor.
561+
* equalRowTypes
566562
*
567-
* If two tuple descriptors would be considered equal by equalTupleDescs()
568-
* then their hash value will be equal according to this function.
563+
* This determines whether two tuple descriptors have equal row types. This
564+
* only checks those fields in pg_attribute that are applicable for row types,
565+
* while ignoring those fields that define the physical row storage or those
566+
* that define table column metadata.
567+
*
568+
* Specifically, this checks:
569+
*
570+
* - same number of attributes
571+
* - same composite type ID (but could both be zero)
572+
* - corresponding attributes (in order) have same the name, type, typmod,
573+
* collation
574+
*
575+
* This is used to check whether two record types are compatible, whether
576+
* function return row types are the same, and other similar situations.
577+
*
578+
* (XXX There was some discussion whether attndims should be checked here, but
579+
* for now it has been decided not to.)
580+
*
581+
* Note: We deliberately do not check the tdtypmod field. This allows
582+
* typcache.c to use this routine to see if a cached record type matches a
583+
* requested type.
584+
*/
585+
bool
586+
equalRowTypes(TupleDesc tupdesc1, TupleDesc tupdesc2)
587+
{
588+
if (tupdesc1->natts != tupdesc2->natts)
589+
return false;
590+
if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
591+
return false;
592+
593+
for (int i = 0; i < tupdesc1->natts; i++)
594+
{
595+
Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i);
596+
Form_pg_attribute attr2 = TupleDescAttr(tupdesc2, i);
597+
598+
if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0)
599+
return false;
600+
if (attr1->atttypid != attr2->atttypid)
601+
return false;
602+
if (attr1->atttypmod != attr2->atttypmod)
603+
return false;
604+
if (attr1->attcollation != attr2->attcollation)
605+
return false;
606+
607+
/* Record types derived from tables could have dropped fields. */
608+
if (attr1->attisdropped != attr2->attisdropped)
609+
return false;
610+
}
611+
612+
return true;
613+
}
614+
615+
/*
616+
* hashRowType
569617
*
570-
* Note that currently contents of constraint are not hashed - it'd be a bit
571-
* painful to do so, and conflicts just due to constraints are unlikely.
618+
* If two tuple descriptors would be considered equal by equalRowTypes()
619+
* then their hash value will be equal according to this function.
572620
*/
573621
uint32
574-
hashTupleDesc(TupleDesc desc)
622+
hashRowType(TupleDesc desc)
575623
{
576624
uint32 s;
577625
int i;

src/backend/catalog/pg_proc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ ProcedureCreate(const char *procedureName,
437437
if (olddesc == NULL && newdesc == NULL)
438438
/* ok, both are runtime-defined RECORDs */ ;
439439
else if (olddesc == NULL || newdesc == NULL ||
440-
!equalTupleDescs(olddesc, newdesc))
440+
!equalRowTypes(olddesc, newdesc))
441441
ereport(ERROR,
442442
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
443443
errmsg("cannot change return type of existing function"),

src/backend/commands/analyze.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,8 +1581,8 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
15811581

15821582
/* We may need to convert from child's rowtype to parent's */
15831583
if (childrows > 0 &&
1584-
!equalTupleDescs(RelationGetDescr(childrel),
1585-
RelationGetDescr(onerel)))
1584+
!equalRowTypes(RelationGetDescr(childrel),
1585+
RelationGetDescr(onerel)))
15861586
{
15871587
TupleConversionMap *map;
15881588

src/backend/commands/view.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#include "utils/lsyscache.h"
3131
#include "utils/rel.h"
3232

33-
static void checkViewTupleDesc(TupleDesc newdesc, TupleDesc olddesc);
33+
static void checkViewColumns(TupleDesc newdesc, TupleDesc olddesc);
3434

3535
/*---------------------------------------------------------------------
3636
* DefineVirtualRelation
@@ -130,7 +130,7 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace,
130130
* column list.
131131
*/
132132
descriptor = BuildDescForRelation(attrList);
133-
checkViewTupleDesc(descriptor, rel->rd_att);
133+
checkViewColumns(descriptor, rel->rd_att);
134134

135135
/*
136136
* If new attributes have been added, we must add pg_attribute entries
@@ -258,13 +258,13 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace,
258258
}
259259

260260
/*
261-
* Verify that tupledesc associated with proposed new view definition
262-
* matches tupledesc of old view. This is basically a cut-down version
263-
* of equalTupleDescs(), with code added to generate specific complaints.
264-
* Also, we allow the new tupledesc to have more columns than the old.
261+
* Verify that the columns associated with proposed new view definition match
262+
* the columns of the old view. This is similar to equalRowTypes(), with code
263+
* added to generate specific complaints. Also, we allow the new view to have
264+
* more columns than the old.
265265
*/
266266
static void
267-
checkViewTupleDesc(TupleDesc newdesc, TupleDesc olddesc)
267+
checkViewColumns(TupleDesc newdesc, TupleDesc olddesc)
268268
{
269269
int i;
270270

src/backend/utils/cache/plancache.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -727,8 +727,7 @@ RevalidateCachedQuery(CachedPlanSource *plansource,
727727
PopActiveSnapshot();
728728

729729
/*
730-
* Check or update the result tupdesc. XXX should we use a weaker
731-
* condition than equalTupleDescs() here?
730+
* Check or update the result tupdesc.
732731
*
733732
* We assume the parameter types didn't change from the first time, so no
734733
* need to update that.
@@ -739,7 +738,7 @@ RevalidateCachedQuery(CachedPlanSource *plansource,
739738
/* OK, doesn't return tuples */
740739
}
741740
else if (resultDesc == NULL || plansource->resultDesc == NULL ||
742-
!equalTupleDescs(resultDesc, plansource->resultDesc))
741+
!equalRowTypes(resultDesc, plansource->resultDesc))
743742
{
744743
/* can we give a better error message? */
745744
if (plansource->fixed_result)

src/backend/utils/cache/typcache.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ typedef struct TypeCacheEnumData
147147
* We use a separate table for storing the definitions of non-anonymous
148148
* record types. Once defined, a record type will be remembered for the
149149
* life of the backend. Subsequent uses of the "same" record type (where
150-
* sameness means equalTupleDescs) will refer to the existing table entry.
150+
* sameness means equalRowTypes) will refer to the existing table entry.
151151
*
152152
* Stored record types are remembered in a linear array of TupleDescs,
153153
* which can be indexed quickly with the assigned typmod. There is also
@@ -231,7 +231,7 @@ shared_record_table_compare(const void *a, const void *b, size_t size,
231231
else
232232
t2 = k2->u.local_tupdesc;
233233

234-
return equalTupleDescs(t1, t2) ? 0 : 1;
234+
return equalRowTypes(t1, t2) ? 0 : 1;
235235
}
236236

237237
/*
@@ -249,7 +249,7 @@ shared_record_table_hash(const void *a, size_t size, void *arg)
249249
else
250250
t = k->u.local_tupdesc;
251251

252-
return hashTupleDesc(t);
252+
return hashRowType(t);
253253
}
254254

255255
/* Parameters for SharedRecordTypmodRegistry's TupleDesc table. */
@@ -1927,7 +1927,7 @@ record_type_typmod_hash(const void *data, size_t size)
19271927
{
19281928
RecordCacheEntry *entry = (RecordCacheEntry *) data;
19291929

1930-
return hashTupleDesc(entry->tupdesc);
1930+
return hashRowType(entry->tupdesc);
19311931
}
19321932

19331933
/*
@@ -1939,7 +1939,7 @@ record_type_typmod_compare(const void *a, const void *b, size_t size)
19391939
RecordCacheEntry *left = (RecordCacheEntry *) a;
19401940
RecordCacheEntry *right = (RecordCacheEntry *) b;
19411941

1942-
return equalTupleDescs(left->tupdesc, right->tupdesc) ? 0 : 1;
1942+
return equalRowTypes(left->tupdesc, right->tupdesc) ? 0 : 1;
19431943
}
19441944

19451945
/*

src/include/access/tupdesc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ extern void DecrTupleDescRefCount(TupleDesc tupdesc);
126126
} while (0)
127127

128128
extern bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2);
129-
130-
extern uint32 hashTupleDesc(TupleDesc desc);
129+
extern bool equalRowTypes(TupleDesc tupdesc1, TupleDesc tupdesc2);
130+
extern uint32 hashRowType(TupleDesc desc);
131131

132132
extern void TupleDescInitEntry(TupleDesc desc,
133133
AttrNumber attributeNumber,

0 commit comments

Comments
 (0)