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.c135
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;