diff options
Diffstat (limited to 'src/backend/commands/indexcmds.c')
-rw-r--r-- | src/backend/commands/indexcmds.c | 135 |
1 files changed, 58 insertions, 77 deletions
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index e5d1d8b699a..a0840d1bf06 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -24,6 +24,7 @@ #include "catalog/pg_opfamily.h" #include "catalog/pg_tablespace.h" #include "catalog/pg_type.h" +#include "commands/comment.h" #include "commands/dbcommands.h" #include "commands/defrem.h" #include "commands/tablecmds.h" @@ -65,7 +66,11 @@ static void ComputeIndexAttrs(IndexInfo *indexInfo, bool isconstraint); static Oid GetIndexOpClass(List *opclass, Oid attrType, char *accessMethodName, Oid accessMethodId); +static char *ChooseIndexName(const char *tabname, Oid namespaceId, + List *colnames, List *exclusionOpNames, + bool primary, bool isconstraint); static char *ChooseIndexNameAddition(List *colnames); +static List *ChooseIndexColumnNames(List *indexElems); static void RangeVarCallbackForReindexIndex(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg); @@ -268,60 +273,28 @@ CheckIndexCompatible(Oid oldId, * DefineIndex * Creates a new index. * - * 'heapRelation': the relation the index will apply to. - * 'indexRelationName': the name for the new index, or NULL to indicate - * that a nonconflicting default name should be picked. + * 'stmt': IndexStmt describing the properties of the new index. * 'indexRelationId': normally InvalidOid, but during bootstrap can be * nonzero to specify a preselected OID for the index. - * 'relFileNode': normally InvalidOid, but can be nonzero to specify existing - * storage constituting a valid build of this index. - * 'accessMethodName': name of the AM to use. - * 'tableSpaceName': name of the tablespace to create the index in. - * NULL specifies using the appropriate default. - * 'attributeList': a list of IndexElem specifying columns and expressions - * to index on. - * 'predicate': the partial-index condition, or NULL if none. - * 'options': reloptions from WITH (in list-of-DefElem form). - * 'exclusionOpNames': list of names of exclusion-constraint operators, - * or NIL if not an exclusion constraint. - * 'unique': make the index enforce uniqueness. - * 'primary': mark the index as a primary key in the catalogs. - * 'isconstraint': index is for a PRIMARY KEY or UNIQUE constraint, - * so build a pg_constraint entry for it. - * 'deferrable': constraint is DEFERRABLE. - * 'initdeferred': constraint is INITIALLY DEFERRED. * 'is_alter_table': this is due to an ALTER rather than a CREATE operation. * 'check_rights': check for CREATE rights in the namespace. (This should * be true except when ALTER is deleting/recreating an index.) * 'skip_build': make the catalog entries but leave the index file empty; * it will be filled later. * 'quiet': suppress the NOTICE chatter ordinarily provided for constraints. - * 'concurrent': avoid blocking writers to the table while building. * * Returns the OID of the created index. */ Oid -DefineIndex(RangeVar *heapRelation, - char *indexRelationName, +DefineIndex(IndexStmt *stmt, Oid indexRelationId, - Oid relFileNode, - char *accessMethodName, - char *tableSpaceName, - List *attributeList, - Expr *predicate, - List *options, - List *exclusionOpNames, - bool unique, - bool primary, - bool isconstraint, - bool deferrable, - bool initdeferred, bool is_alter_table, bool check_rights, bool skip_build, - bool quiet, - bool concurrent) + bool quiet) { + char *indexRelationName; + char *accessMethodName; Oid *typeObjectId; Oid *collationObjectId; Oid *classObjectId; @@ -354,7 +327,7 @@ DefineIndex(RangeVar *heapRelation, /* * count attributes in index */ - numberOfAttributes = list_length(attributeList); + numberOfAttributes = list_length(stmt->indexParams); if (numberOfAttributes <= 0) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), @@ -372,8 +345,8 @@ DefineIndex(RangeVar *heapRelation, * index build; but for concurrent builds we allow INSERT/UPDATE/DELETE * (but not VACUUM). */ - rel = heap_openrv(heapRelation, - (concurrent ? ShareUpdateExclusiveLock : ShareLock)); + rel = heap_openrv(stmt->relation, + (stmt->concurrent ? ShareUpdateExclusiveLock : ShareLock)); relationId = RelationGetRelid(rel); namespaceId = RelationGetNamespace(rel); @@ -389,12 +362,12 @@ DefineIndex(RangeVar *heapRelation, ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot create index on foreign table \"%s\"", - heapRelation->relname))); + RelationGetRelationName(rel)))); else ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a table", - heapRelation->relname))); + RelationGetRelationName(rel)))); } /* @@ -426,9 +399,9 @@ DefineIndex(RangeVar *heapRelation, * Select tablespace to use. If not specified, use default tablespace * (which may in turn default to database's default). */ - if (tableSpaceName) + if (stmt->tableSpace) { - tablespaceId = get_tablespace_oid(tableSpaceName, false); + tablespaceId = get_tablespace_oid(stmt->tableSpace, false); } else { @@ -463,22 +436,24 @@ DefineIndex(RangeVar *heapRelation, /* * Choose the index column names. */ - indexColNames = ChooseIndexColumnNames(attributeList); + indexColNames = ChooseIndexColumnNames(stmt->indexParams); /* * Select name for index if caller didn't specify */ + indexRelationName = stmt->idxname; if (indexRelationName == NULL) indexRelationName = ChooseIndexName(RelationGetRelationName(rel), namespaceId, indexColNames, - exclusionOpNames, - primary, - isconstraint); + stmt->excludeOpNames, + stmt->primary, + stmt->isconstraint); /* * look up the access method, verify it can handle the requested features */ + accessMethodName = stmt->accessMethod; tuple = SearchSysCache1(AMNAME, PointerGetDatum(accessMethodName)); if (!HeapTupleIsValid(tuple)) { @@ -503,7 +478,7 @@ DefineIndex(RangeVar *heapRelation, accessMethodId = HeapTupleGetOid(tuple); accessMethodForm = (Form_pg_am) GETSTRUCT(tuple); - if (unique && !accessMethodForm->amcanunique) + if (stmt->unique && !accessMethodForm->amcanunique) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("access method \"%s\" does not support unique indexes", @@ -513,7 +488,7 @@ DefineIndex(RangeVar *heapRelation, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("access method \"%s\" does not support multicolumn indexes", accessMethodName))); - if (exclusionOpNames != NIL && !OidIsValid(accessMethodForm->amgettuple)) + if (stmt->excludeOpNames && !OidIsValid(accessMethodForm->amgettuple)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("access method \"%s\" does not support exclusion constraints", @@ -527,13 +502,14 @@ DefineIndex(RangeVar *heapRelation, /* * Validate predicate, if given */ - if (predicate) - CheckPredicate(predicate); + if (stmt->whereClause) + CheckPredicate((Expr *) stmt->whereClause); /* * Parse AM-specific options, convert to text array form, validate. */ - reloptions = transformRelOptions((Datum) 0, options, NULL, NULL, false, false); + reloptions = transformRelOptions((Datum) 0, stmt->options, + NULL, NULL, false, false); (void) index_reloptions(amoptions, reloptions, true); @@ -545,15 +521,15 @@ DefineIndex(RangeVar *heapRelation, indexInfo->ii_NumIndexAttrs = numberOfAttributes; indexInfo->ii_Expressions = NIL; /* for now */ indexInfo->ii_ExpressionsState = NIL; - indexInfo->ii_Predicate = make_ands_implicit(predicate); + indexInfo->ii_Predicate = make_ands_implicit((Expr *) stmt->whereClause); indexInfo->ii_PredicateState = NIL; indexInfo->ii_ExclusionOps = NULL; indexInfo->ii_ExclusionProcs = NULL; indexInfo->ii_ExclusionStrats = NULL; - indexInfo->ii_Unique = unique; + indexInfo->ii_Unique = stmt->unique; /* In a concurrent build, mark it not-ready-for-inserts */ - indexInfo->ii_ReadyForInserts = !concurrent; - indexInfo->ii_Concurrent = concurrent; + indexInfo->ii_ReadyForInserts = !stmt->concurrent; + indexInfo->ii_Concurrent = stmt->concurrent; indexInfo->ii_BrokenHotChain = false; typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid)); @@ -562,30 +538,30 @@ DefineIndex(RangeVar *heapRelation, coloptions = (int16 *) palloc(numberOfAttributes * sizeof(int16)); ComputeIndexAttrs(indexInfo, typeObjectId, collationObjectId, classObjectId, - coloptions, attributeList, - exclusionOpNames, relationId, + coloptions, stmt->indexParams, + stmt->excludeOpNames, relationId, accessMethodName, accessMethodId, - amcanorder, isconstraint); + amcanorder, stmt->isconstraint); /* * Extra checks when creating a PRIMARY KEY index. */ - if (primary) + if (stmt->primary) index_check_primary_key(rel, indexInfo, is_alter_table); /* * Report index creation if appropriate (delay this till after most of the * error checks) */ - if (isconstraint && !quiet) + if (stmt->isconstraint && !quiet) { const char *constraint_type; - if (primary) + if (stmt->primary) constraint_type = "PRIMARY KEY"; - else if (unique) + else if (stmt->unique) constraint_type = "UNIQUE"; - else if (exclusionOpNames != NIL) + else if (stmt->excludeOpNames != NIL) constraint_type = "EXCLUDE"; else { @@ -601,27 +577,32 @@ DefineIndex(RangeVar *heapRelation, } /* - * A valid relFileNode implies that we already have a built form of the + * A valid stmt->oldNode implies that we already have a built form of the * index. The caller should also decline any index build. */ - Assert(!OidIsValid(relFileNode) || (skip_build && !concurrent)); + Assert(!OidIsValid(stmt->oldNode) || (skip_build && !stmt->concurrent)); /* * Make the catalog entries for the index, including constraints. Then, if * not skip_build || concurrent, actually build the index. */ indexRelationId = - index_create(rel, indexRelationName, indexRelationId, relFileNode, + index_create(rel, indexRelationName, indexRelationId, stmt->oldNode, indexInfo, indexColNames, accessMethodId, tablespaceId, collationObjectId, classObjectId, - coloptions, reloptions, primary, - isconstraint, deferrable, initdeferred, + coloptions, reloptions, stmt->primary, + stmt->isconstraint, stmt->deferrable, stmt->initdeferred, allowSystemTableMods, - skip_build || concurrent, - concurrent); + skip_build || stmt->concurrent, + stmt->concurrent); - if (!concurrent) + /* Add any requested comment */ + if (stmt->idxcomment != NULL) + CreateComments(indexRelationId, RelationRelationId, 0, + stmt->idxcomment); + + if (!stmt->concurrent) { /* Close the heap and we're done, in the non-concurrent case */ heap_close(rel, NoLock); @@ -709,7 +690,7 @@ DefineIndex(RangeVar *heapRelation, */ /* Open and lock the parent heap relation */ - rel = heap_openrv(heapRelation, ShareUpdateExclusiveLock); + rel = heap_openrv(stmt->relation, ShareUpdateExclusiveLock); /* And the target index relation */ indexRelation = index_open(indexRelationId, RowExclusiveLock); @@ -724,7 +705,7 @@ DefineIndex(RangeVar *heapRelation, indexInfo->ii_BrokenHotChain = false; /* Now build the index */ - index_build(rel, indexRelation, indexInfo, primary, false); + index_build(rel, indexRelation, indexInfo, stmt->primary, false); /* Close both the relations, but keep the locks */ heap_close(rel, NoLock); @@ -1594,7 +1575,7 @@ ChooseRelationName(const char *name1, const char *name2, * * The argument list is pretty ad-hoc :-( */ -char * +static char * ChooseIndexName(const char *tabname, Oid namespaceId, List *colnames, List *exclusionOpNames, bool primary, bool isconstraint) @@ -1676,7 +1657,7 @@ ChooseIndexNameAddition(List *colnames) * * Returns a List of plain strings (char *, not String nodes). */ -List * +static List * ChooseIndexColumnNames(List *indexElems) { List *result = NIL; |