88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.67 2000/10/05 19:48:20 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.68 2000/11/08 22:09:53 tgl Exp $
1212 *
1313 * NOTES
1414 * some of the executor utility code such as "ExecTypeFromTL" should be
@@ -228,7 +228,9 @@ FreeTupleDesc(TupleDesc tupdesc)
228228bool
229229equalTupleDescs (TupleDesc tupdesc1 ,TupleDesc tupdesc2 )
230230{
231- int i ;
231+ int i ,
232+ j ,
233+ n ;
232234
233235if (tupdesc1 -> natts != tupdesc2 -> natts )
234236return false;
@@ -240,7 +242,9 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
240242/*
241243 * We do not need to check every single field here, and in fact
242244 * some fields such as attdispersion probably shouldn't be
243- * compared.
245+ * compared. We can also disregard attnum (it was used to
246+ * place the row in the attrs array) and everything derived
247+ * from the column datatype.
244248 */
245249if (strcmp (NameStr (attr1 -> attname ),NameStr (attr2 -> attname ))!= 0 )
246250return false;
@@ -260,32 +264,53 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
260264
261265if (constr2 == NULL )
262266return false;
263- if (constr1 -> num_defval != constr2 -> num_defval )
267+ if (constr1 -> has_not_null != constr2 -> has_not_null )
268+ return false;
269+ n = constr1 -> num_defval ;
270+ if (n != (int )constr2 -> num_defval )
264271return false;
265- for (i = 0 ;i < ( int ) constr1 -> num_defval ;i ++ )
272+ for (i = 0 ;i < n ;i ++ )
266273{
267274AttrDefault * defval1 = constr1 -> defval + i ;
268- AttrDefault * defval2 = constr2 -> defval + i ;
275+ AttrDefault * defval2 = constr2 -> defval ;
269276
270- if (defval1 -> adnum != defval2 -> adnum )
277+ /*
278+ * We can't assume that the items are always read from the
279+ * system catalogs in the same order; so use the adnum field to
280+ * identify the matching item to compare.
281+ */
282+ for (j = 0 ;j < n ;defval2 ++ ,j ++ )
283+ {
284+ if (defval1 -> adnum == defval2 -> adnum )
285+ break ;
286+ }
287+ if (j >=n )
271288return false;
272289if (strcmp (defval1 -> adbin ,defval2 -> adbin )!= 0 )
273290return false;
274291}
275- if (constr1 -> num_check != constr2 -> num_check )
292+ n = constr1 -> num_check ;
293+ if (n != (int )constr2 -> num_check )
276294return false;
277- for (i = 0 ;i < ( int ) constr1 -> num_check ;i ++ )
295+ for (i = 0 ;i < n ;i ++ )
278296{
279297ConstrCheck * check1 = constr1 -> check + i ;
280- ConstrCheck * check2 = constr2 -> check + i ;
298+ ConstrCheck * check2 = constr2 -> check ;
281299
282- if (strcmp (check1 -> ccname ,check2 -> ccname )!= 0 )
283- return false;
284- if (strcmp (check1 -> ccbin ,check2 -> ccbin )!= 0 )
300+ /*
301+ * Similarly, don't assume that the checks are always read
302+ * in the same order; match them up by name and contents.
303+ * (The name *should* be unique, but...)
304+ */
305+ for (j = 0 ;j < n ;check2 ++ ,j ++ )
306+ {
307+ if (strcmp (check1 -> ccname ,check2 -> ccname )== 0 &&
308+ strcmp (check1 -> ccbin ,check2 -> ccbin )== 0 )
309+ break ;
310+ }
311+ if (j >=n )
285312return false;
286313}
287- if (constr1 -> has_not_null != constr2 -> has_not_null )
288- return false;
289314}
290315else if (tupdesc2 -> constr != NULL )
291316return false;