aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/common/tupdesc.c72
-rw-r--r--src/backend/catalog/pg_proc.c2
-rw-r--r--src/backend/commands/analyze.c4
-rw-r--r--src/backend/commands/view.c14
-rw-r--r--src/backend/utils/cache/plancache.c5
-rw-r--r--src/backend/utils/cache/typcache.c10
-rw-r--r--src/include/access/tupdesc.h4
7 files changed, 79 insertions, 32 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;
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index e6c6001f399..528c17cd7f6 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -437,7 +437,7 @@ ProcedureCreate(const char *procedureName,
if (olddesc == NULL && newdesc == NULL)
/* ok, both are runtime-defined RECORDs */ ;
else if (olddesc == NULL || newdesc == NULL ||
- !equalTupleDescs(olddesc, newdesc))
+ !equalRowTypes(olddesc, newdesc))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("cannot change return type of existing function"),
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 28880bd2991..8a82af4a4ca 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -1581,8 +1581,8 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
/* We may need to convert from child's rowtype to parent's */
if (childrows > 0 &&
- !equalTupleDescs(RelationGetDescr(childrel),
- RelationGetDescr(onerel)))
+ !equalRowTypes(RelationGetDescr(childrel),
+ RelationGetDescr(onerel)))
{
TupleConversionMap *map;
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index becc1fb4583..fdad8338324 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -30,7 +30,7 @@
#include "utils/lsyscache.h"
#include "utils/rel.h"
-static void checkViewTupleDesc(TupleDesc newdesc, TupleDesc olddesc);
+static void checkViewColumns(TupleDesc newdesc, TupleDesc olddesc);
/*---------------------------------------------------------------------
* DefineVirtualRelation
@@ -130,7 +130,7 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace,
* column list.
*/
descriptor = BuildDescForRelation(attrList);
- checkViewTupleDesc(descriptor, rel->rd_att);
+ checkViewColumns(descriptor, rel->rd_att);
/*
* If new attributes have been added, we must add pg_attribute entries
@@ -258,13 +258,13 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace,
}
/*
- * Verify that tupledesc associated with proposed new view definition
- * matches tupledesc of old view. This is basically a cut-down version
- * of equalTupleDescs(), with code added to generate specific complaints.
- * Also, we allow the new tupledesc to have more columns than the old.
+ * Verify that the columns associated with proposed new view definition match
+ * the columns of the old view. This is similar to equalRowTypes(), with code
+ * added to generate specific complaints. Also, we allow the new view to have
+ * more columns than the old.
*/
static void
-checkViewTupleDesc(TupleDesc newdesc, TupleDesc olddesc)
+checkViewColumns(TupleDesc newdesc, TupleDesc olddesc)
{
int i;
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index e16f4c36ec5..5af1a168ec2 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -727,8 +727,7 @@ RevalidateCachedQuery(CachedPlanSource *plansource,
PopActiveSnapshot();
/*
- * Check or update the result tupdesc. XXX should we use a weaker
- * condition than equalTupleDescs() here?
+ * Check or update the result tupdesc.
*
* We assume the parameter types didn't change from the first time, so no
* need to update that.
@@ -739,7 +738,7 @@ RevalidateCachedQuery(CachedPlanSource *plansource,
/* OK, doesn't return tuples */
}
else if (resultDesc == NULL || plansource->resultDesc == NULL ||
- !equalTupleDescs(resultDesc, plansource->resultDesc))
+ !equalRowTypes(resultDesc, plansource->resultDesc))
{
/* can we give a better error message? */
if (plansource->fixed_result)
diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c
index 0d4d0b0a154..d86c3b06fa0 100644
--- a/src/backend/utils/cache/typcache.c
+++ b/src/backend/utils/cache/typcache.c
@@ -147,7 +147,7 @@ typedef struct TypeCacheEnumData
* We use a separate table for storing the definitions of non-anonymous
* record types. Once defined, a record type will be remembered for the
* life of the backend. Subsequent uses of the "same" record type (where
- * sameness means equalTupleDescs) will refer to the existing table entry.
+ * sameness means equalRowTypes) will refer to the existing table entry.
*
* Stored record types are remembered in a linear array of TupleDescs,
* 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,
else
t2 = k2->u.local_tupdesc;
- return equalTupleDescs(t1, t2) ? 0 : 1;
+ return equalRowTypes(t1, t2) ? 0 : 1;
}
/*
@@ -249,7 +249,7 @@ shared_record_table_hash(const void *a, size_t size, void *arg)
else
t = k->u.local_tupdesc;
- return hashTupleDesc(t);
+ return hashRowType(t);
}
/* Parameters for SharedRecordTypmodRegistry's TupleDesc table. */
@@ -1927,7 +1927,7 @@ record_type_typmod_hash(const void *data, size_t size)
{
RecordCacheEntry *entry = (RecordCacheEntry *) data;
- return hashTupleDesc(entry->tupdesc);
+ return hashRowType(entry->tupdesc);
}
/*
@@ -1939,7 +1939,7 @@ record_type_typmod_compare(const void *a, const void *b, size_t size)
RecordCacheEntry *left = (RecordCacheEntry *) a;
RecordCacheEntry *right = (RecordCacheEntry *) b;
- return equalTupleDescs(left->tupdesc, right->tupdesc) ? 0 : 1;
+ return equalRowTypes(left->tupdesc, right->tupdesc) ? 0 : 1;
}
/*
diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h
index 3d767dde65d..8930a28d660 100644
--- a/src/include/access/tupdesc.h
+++ b/src/include/access/tupdesc.h
@@ -126,8 +126,8 @@ extern void DecrTupleDescRefCount(TupleDesc tupdesc);
} while (0)
extern bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2);
-
-extern uint32 hashTupleDesc(TupleDesc desc);
+extern bool equalRowTypes(TupleDesc tupdesc1, TupleDesc tupdesc2);
+extern uint32 hashRowType(TupleDesc desc);
extern void TupleDescInitEntry(TupleDesc desc,
AttrNumber attributeNumber,