bool found_deferrable = false;
List *indexoidlist;
ListCell *indexoidscan;
+ int i,
+ j;
+
+ /*
+ * Reject duplicate appearances of columns in the referenced-columns list.
+ * Such a case is forbidden by the SQL standard, and even if we thought it
+ * useful to allow it, there would be ambiguity about how to match the
+ * list to unique indexes (in particular, it'd be unclear which index
+ * opclass goes with which FK column).
+ */
+ for (i = 0; i < numattrs; i++)
+ {
+ for (j = i + 1; j < numattrs; j++)
+ {
+ if (attnums[i] == attnums[j])
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FOREIGN_KEY),
+ errmsg("foreign key referenced-columns list must not contain duplicates")));
+ }
+ }
/*
* Get the list of index OIDs for the table from the relcache, and look up
{
HeapTuple indexTuple;
Form_pg_index indexStruct;
- int i,
- j;
indexoid = lfirst_oid(indexoidscan);
indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
heap_attisnull(indexTuple, Anum_pg_index_indpred) &&
heap_attisnull(indexTuple, Anum_pg_index_indexprs))
{
- /* Must get indclass the hard way */
Datum indclassDatum;
bool isnull;
oidvector *indclass;
+ /* Must get indclass the hard way */
indclassDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
Anum_pg_index_indclass, &isnull);
Assert(!isnull);
/*
* The given attnum list may match the index columns in any order.
- * Check that each list is a subset of the other.
+ * Check for a match, and extract the appropriate opclasses while
+ * we're at it.
+ *
+ * We know that attnums[] is duplicate-free per the test at the
+ * start of this function, and we checked above that the number of
+ * index columns agrees, so if we find a match for each attnums[]
+ * entry then we must have a one-to-one match in some order.
*/
for (i = 0; i < numattrs; i++)
{
{
if (attnums[i] == indexStruct->indkey.values[j])
{
+ opclasses[i] = indclass->values[j];
found = true;
break;
}
if (!found)
break;
}
- if (found)
- {
- for (i = 0; i < numattrs; i++)
- {
- found = false;
- for (j = 0; j < numattrs; j++)
- {
- if (attnums[j] == indexStruct->indkey.values[i])
- {
- opclasses[j] = indclass->values[i];
- found = true;
- break;
- }
- }
- if (!found)
- break;
- }
- }
/*
* Refuse to use a deferrable unique/primary key. This is per SQL