*** pgsql.q2/src/backend/commands/command.c	Thu Nov 16 14:30:19 2000
--- pgsql/src/backend/commands/command.c	Sat Dec  2 14:17:31 2000
***************
*** 1287,1312 ****
  				{
  					List	   *attrl;
  
! 					/* go through the fkconstraint->pk_attrs list */
! 					foreach(attrl, fkconstraint->pk_attrs)
! 					{
! 						Ident *attr=lfirst(attrl);
! 						found = false;
! 						for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
  						{
! 							int pkattno = indexStruct->indkey[i];
! 							if (pkattno>0)
  							{
! 								char *name = NameStr(rel_attrs[pkattno-1]->attname);
! 								if (strcmp(name, attr->name)==0)
  								{
! 									found = true;
! 									break;
  								}
  							}
  						}
- 						if (!found)
- 							break;
  					}
  				}
  				ReleaseSysCache(indexTuple);
--- 1287,1319 ----
  				{
  					List	   *attrl;
  
! 					/* Make sure this index has the same number of keys -- It obviously
! 					 * won't match otherwise. */
! 					for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++);
! 					if (i!=length(fkconstraint->pk_attrs))
! 						found=false;
! 					else {
! 						/* go through the fkconstraint->pk_attrs list */
! 						foreach(attrl, fkconstraint->pk_attrs)
  						{
! 							Ident *attr=lfirst(attrl);
! 							found = false;
! 							for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
  							{
! 								int pkattno = indexStruct->indkey[i];
! 								if (pkattno>0)
  								{
! 									char *name = NameStr(rel_attrs[pkattno-1]->attname);
! 									if (strcmp(name, attr->name)==0)
! 									{
! 										found = true;
! 										break;
! 									}
  								}
  							}
+ 							if (!found)
+ 								break;
  						}
  					}
  				}
  				ReleaseSysCache(indexTuple);
*** pgsql.q2/src/backend/parser/analyze.c	Fri Nov 24 12:16:39 2000
--- pgsql/src/backend/parser/analyze.c	Sat Dec  2 15:05:57 2000
***************
*** 1202,1219 ****
  						List *pkattrs;
  						Ident *pkattr;
  						if (ind->unique) {
! 							foreach(pkattrs, fkconstraint->pk_attrs) {
  								found=0;
! 								pkattr=lfirst(pkattrs);
! 								foreach(indparms, ind->indexParams) {
! 									indparm=lfirst(indparms);
! 									if (strcmp(indparm->name, pkattr->name)==0) {
! 										found=1;
! 										break;
  									}
  								}
- 								if (!found)
- 									break;
  							}
  						}
  						if (found)
--- 1202,1227 ----
  						List *pkattrs;
  						Ident *pkattr;
  						if (ind->unique) {
! 							int count=0;
! 							foreach(indparms, ind->indexParams) {
! 								count++;
! 							}
! 							if (count!=length(fkconstraint->pk_attrs))
  								found=0;
! 							else {
! 								foreach(pkattrs, fkconstraint->pk_attrs) {
! 									found=0;
! 									pkattr=lfirst(pkattrs);
! 									foreach(indparms, ind->indexParams) {
! 										indparm=lfirst(indparms);
! 										if (strcmp(indparm->name, pkattr->name)==0) {
! 											found=1;
! 											break;
! 										}
  									}
+ 									if (!found)
+ 										break;
  								}
  							}
  						}
  						if (found)
***************
*** 2606,2631 ****
  		{
  			List *attrl;
  
! 			/* go through the fkconstraint->pk_attrs list */
! 			foreach(attrl, fkconstraint->pk_attrs)
! 			{
! 				Ident *attr=lfirst(attrl);
! 				found = false;
! 				for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
  				{
! 					int		pkattno = indexStruct->indkey[i];
! 					if (pkattno>0)
  					{
! 						char *name = NameStr(pkrel_attrs[pkattno - 1]->attname);
! 						if (strcmp(name, attr->name)==0)
  						{
! 							found = true;
! 							break;
  						}
  					}
  				}
- 				if (!found)
- 					break;
  			}
  		}
  		ReleaseSysCache(indexTuple);
--- 2614,2644 ----
  		{
  			List *attrl;
  
! 			for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++);
! 			if (i!=length(fkconstraint->pk_attrs))
! 				found=false;
! 			else {
! 				/* go through the fkconstraint->pk_attrs list */
! 				foreach(attrl, fkconstraint->pk_attrs)
  				{
! 					Ident *attr=lfirst(attrl);
! 					found = false;
! 					for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
  					{
! 						int		pkattno = indexStruct->indkey[i];
! 						if (pkattno>0)
  						{
! 							char *name = NameStr(pkrel_attrs[pkattno - 1]->attname);
! 							if (strcmp(name, attr->name)==0)
! 							{
! 								found = true;
! 								break;
! 							}
  						}
  					}
+ 					if (!found)
+ 						break;
  				}
  			}
  		}
  		ReleaseSysCache(indexTuple);
*** pgsql.q2/src/test/regress/sql/foreign_key.sql	Mon Aug 28 21:20:47 2000
--- pgsql/src/test/regress/sql/foreign_key.sql	Sat Dec  2 15:20:07 2000
***************
*** 418,420 ****
--- 418,427 ----
  DROP TABLE FKTABLE_FAIL1;
  DROP TABLE FKTABLE_FAIL2;
  DROP TABLE PKTABLE;
+ 
+ -- Test for referencing column number smaller than referenced constraint
+ CREATE TABLE PKTABLE (ptest1 int, ptest2 int, UNIQUE(ptest1, ptest2));
+ CREATE TABLE FKTABLE_FAIL1 (ftest1 int REFERENCES pktable(ptest1));
+ 
+ DROP TABLE FKTABLE_FAIL1;
+ DROP TABLE PKTABLE;
*** pgsql.q2/src/test/regress/expected/foreign_key.out	Sun Oct 22 16:32:45 2000
--- pgsql/src/test/regress/expected/foreign_key.out	Sat Dec  2 15:37:09 2000
***************
*** 703,705 ****
--- 703,714 ----
  DROP TABLE FKTABLE_FAIL2;
  ERROR:  table "fktable_fail2" does not exist
  DROP TABLE PKTABLE;
+ -- Test for referencing column number smaller than referenced constraint
+ CREATE TABLE PKTABLE (ptest1 int, ptest2 int, UNIQUE(ptest1, ptest2));
+ NOTICE:  CREATE TABLE/UNIQUE will create implicit index 'pktable_ptest1_key' for table 'pktable'
+ CREATE TABLE FKTABLE_FAIL1 (ftest1 int REFERENCES pktable(ptest1));
+ NOTICE:  CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
+ ERROR:  UNIQUE constraint matching given keys for referenced table "pktable" not found
+ DROP TABLE FKTABLE_FAIL1;
+ ERROR:  table "fktable_fail1" does not exist
+ DROP TABLE PKTABLE;
*** pgsql.q2/src/test/regress/sql/alter_table.sql	Mon Aug 28 21:20:47 2000
--- pgsql/src/test/regress/sql/alter_table.sql	Sat Dec  2 15:22:09 2000
***************
*** 169,174 ****
--- 169,178 ----
  
  CREATE TABLE tmp3 (a int, b int);
  
+ CREATE TABLE tmp4 (a int, b int, unique(a,b));
+ 
+ CREATE TABLE tmp5 (a int, b int);
+ 
  -- Insert rows into tmp2 (pktable)
  INSERT INTO tmp2 values (1);
  INSERT INTO tmp2 values (2);
***************
*** 194,199 ****
--- 198,212 ----
  
  -- Try (and succeed)
  ALTER TABLE tmp3 add constraint tmpconstr foreign key (a) references tmp2 match full;
+ 
+ -- Try (and fail) to create constraint from tmp5(a) to tmp4(a) - unique constraint on
+ -- tmp4 is a,b
+ 
+ ALTER TABLE tmp5 add constraint tmpconstr foreign key(a) references tmp4(a) match full;
+ 
+ DROP TABLE tmp5;
+ 
+ DROP TABLE tmp4;
  
  DROP TABLE tmp3;
  
*** pgsql.q2/src/test/regress/expected/alter_table.out	Mon Aug 28 21:20:45 2000
--- pgsql/src/test/regress/expected/alter_table.out	Sat Dec  2 15:37:14 2000
***************
*** 273,278 ****
--- 273,281 ----
  CREATE TABLE tmp2 (a int primary key);
  NOTICE:  CREATE TABLE/PRIMARY KEY will create implicit index 'tmp2_pkey' for table 'tmp2'
  CREATE TABLE tmp3 (a int, b int);
+ CREATE TABLE tmp4 (a int, b int, unique(a,b));
+ NOTICE:  CREATE TABLE/UNIQUE will create implicit index 'tmp4_a_key' for table 'tmp4'
+ CREATE TABLE tmp5 (a int, b int);
  -- Insert rows into tmp2 (pktable)
  INSERT INTO tmp2 values (1);
  INSERT INTO tmp2 values (2);
***************
*** 299,304 ****
--- 302,314 ----
  -- Try (and succeed)
  ALTER TABLE tmp3 add constraint tmpconstr foreign key (a) references tmp2 match full;
  NOTICE:  ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s)
+ -- Try (and fail) to create constraint from tmp5(a) to tmp4(a) - unique constraint on
+ -- tmp4 is a,b
+ ALTER TABLE tmp5 add constraint tmpconstr foreign key(a) references tmp4(a) match full;
+ NOTICE:  ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s)
+ ERROR:  UNIQUE constraint matching given keys for referenced table "tmp4" not found
+ DROP TABLE tmp5;
+ DROP TABLE tmp4;
  DROP TABLE tmp3;
  NOTICE:  DROP TABLE implicitly drops referential integrity trigger from table "tmp2"
  NOTICE:  DROP TABLE implicitly drops referential integrity trigger from table "tmp2"
