aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/indexcmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/indexcmds.c')
-rw-r--r--src/backend/commands/indexcmds.c149
1 files changed, 17 insertions, 132 deletions
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 7a6a4c33adc..94ed4370023 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -69,7 +69,6 @@ static void ComputeIndexAttrs(IndexInfo *indexInfo,
static Oid GetIndexOpClass(List *opclass, Oid attrType,
char *accessMethodName, Oid accessMethodId);
static char *ChooseIndexNameAddition(List *colnames);
-static bool relationHasPrimaryKey(Relation rel);
/*
@@ -321,92 +320,6 @@ DefineIndex(RangeVar *heapRelation,
CheckPredicate(predicate);
/*
- * Extra checks when creating a PRIMARY KEY index.
- */
- if (primary)
- {
- List *cmds;
- ListCell *keys;
-
- /*
- * If ALTER TABLE, check that there isn't already a PRIMARY KEY. In
- * CREATE TABLE, we have faith that the parser rejected multiple pkey
- * clauses; and CREATE INDEX doesn't have a way to say PRIMARY KEY, so
- * it's no problem either.
- */
- if (is_alter_table &&
- relationHasPrimaryKey(rel))
- {
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
- errmsg("multiple primary keys for table \"%s\" are not allowed",
- RelationGetRelationName(rel))));
- }
-
- /*
- * Check that all of the attributes in a primary key are marked as not
- * null, otherwise attempt to ALTER TABLE .. SET NOT NULL
- */
- cmds = NIL;
- foreach(keys, attributeList)
- {
- IndexElem *key = (IndexElem *) lfirst(keys);
- HeapTuple atttuple;
-
- if (!key->name)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("primary keys cannot be expressions")));
-
- /* System attributes are never null, so no problem */
- if (SystemAttributeByName(key->name, rel->rd_rel->relhasoids))
- continue;
-
- atttuple = SearchSysCacheAttName(relationId, key->name);
- if (HeapTupleIsValid(atttuple))
- {
- if (!((Form_pg_attribute) GETSTRUCT(atttuple))->attnotnull)
- {
- /* Add a subcommand to make this one NOT NULL */
- AlterTableCmd *cmd = makeNode(AlterTableCmd);
-
- cmd->subtype = AT_SetNotNull;
- cmd->name = key->name;
-
- cmds = lappend(cmds, cmd);
- }
- ReleaseSysCache(atttuple);
- }
- else
- {
- /*
- * This shouldn't happen during CREATE TABLE, but can happen
- * during ALTER TABLE. Keep message in sync with
- * transformIndexConstraints() in parser/parse_utilcmd.c.
- */
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_COLUMN),
- errmsg("column \"%s\" named in key does not exist",
- key->name)));
- }
- }
-
- /*
- * XXX: Shouldn't the ALTER TABLE .. SET NOT NULL cascade to child
- * tables? Currently, since the PRIMARY KEY itself doesn't cascade,
- * we don't cascade the notnull constraint(s) either; but this is
- * pretty debatable.
- *
- * XXX: possible future improvement: when being called from ALTER
- * TABLE, it would be more efficient to merge this with the outer
- * ALTER TABLE, so as to avoid two scans. But that seems to
- * complicate DefineIndex's API unduly.
- */
- if (cmds)
- AlterTableInternal(relationId, cmds, false);
- }
-
- /*
* Parse AM-specific options, convert to text array form, validate.
*/
reloptions = transformRelOptions((Datum) 0, options, NULL, NULL, false, false);
@@ -440,6 +353,12 @@ DefineIndex(RangeVar *heapRelation,
amcanorder, isconstraint);
/*
+ * Extra checks when creating a PRIMARY KEY index.
+ */
+ if (primary)
+ index_check_primary_key(rel, indexInfo, is_alter_table);
+
+ /*
* Report index creation if appropriate (delay this till after most of the
* error checks)
*/
@@ -466,17 +385,12 @@ DefineIndex(RangeVar *heapRelation,
indexRelationName, RelationGetRelationName(rel))));
}
- /* save lockrelid and locktag for below, then close rel */
- heaprelid = rel->rd_lockInfo.lockRelId;
- SET_LOCKTAG_RELATION(heaplocktag, heaprelid.dbId, heaprelid.relId);
- heap_close(rel, NoLock);
-
/*
* Make the catalog entries for the index, including constraints. Then, if
* not skip_build || concurrent, actually build the index.
*/
indexRelationId =
- index_create(relationId, indexRelationName, indexRelationId,
+ index_create(rel, indexRelationName, indexRelationId,
indexInfo, indexColNames,
accessMethodId, tablespaceId, classObjectId,
coloptions, reloptions, primary,
@@ -486,7 +400,16 @@ DefineIndex(RangeVar *heapRelation,
concurrent);
if (!concurrent)
- return; /* We're done, in the standard case */
+ {
+ /* Close the heap and we're done, in the non-concurrent case */
+ heap_close(rel, NoLock);
+ return;
+ }
+
+ /* save lockrelid and locktag for below, then close rel */
+ heaprelid = rel->rd_lockInfo.lockRelId;
+ SET_LOCKTAG_RELATION(heaplocktag, heaprelid.dbId, heaprelid.relId);
+ heap_close(rel, NoLock);
/*
* For a concurrent build, it's important to make the catalog entries
@@ -1532,44 +1455,6 @@ ChooseIndexColumnNames(List *indexElems)
}
/*
- * relationHasPrimaryKey -
- *
- * See whether an existing relation has a primary key.
- */
-static bool
-relationHasPrimaryKey(Relation rel)
-{
- bool result = false;
- List *indexoidlist;
- ListCell *indexoidscan;
-
- /*
- * Get the list of index OIDs for the table from the relcache, and look up
- * each one in the pg_index syscache until we find one marked primary key
- * (hopefully there isn't more than one such).
- */
- indexoidlist = RelationGetIndexList(rel);
-
- foreach(indexoidscan, indexoidlist)
- {
- Oid indexoid = lfirst_oid(indexoidscan);
- HeapTuple indexTuple;
-
- indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
- if (!HeapTupleIsValid(indexTuple)) /* should not happen */
- elog(ERROR, "cache lookup failed for index %u", indexoid);
- result = ((Form_pg_index) GETSTRUCT(indexTuple))->indisprimary;
- ReleaseSysCache(indexTuple);
- if (result)
- break;
- }
-
- list_free(indexoidlist);
-
- return result;
-}
-
-/*
* ReindexIndex
* Recreate a specific index.
*/