@ -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 ( heapR elation,
( concurrent ? ShareUpdateExclusiveLock : ShareLock ) ) ;
rel = heap_openrv ( stmt - > r elation,
( 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 ( tableSpaceNam e )
if ( stmt - > tableSpace )
{
tablespaceId = get_tablespace_oid ( tableSpaceNam e , 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 ,
exclusion OpNames,
primary ,
isconstraint ) ;
stmt - > exclude OpNames,
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 ( predicat e)
CheckPredicate ( predicat e) ;
if ( stmt - > whereClaus e)
CheckPredicate ( ( Expr * ) stmt - > whereClaus e) ;
/*
* 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 ( predicat e) ;
indexInfo - > ii_Predicate = make_ands_implicit ( ( Expr * ) stmt - > whereClaus e) ;
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 ,
exclusion OpNames, relationId ,
coloptions , stmt - > indexParams ,
stmt - > exclude OpNames, 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 ( exclusion OpNames ! = NIL )
else if ( stmt - > exclude OpNames ! = NIL )
constraint_type = " EXCLUDE " ;
else
{
@ -601,27 +577,32 @@ DefineIndex(RangeVar *heapRelation,
}
/*
* A valid relFile Node implies that we already have a built form of the
* A valid stmt - > old Node implies that we already have a built form of the
* index . The caller should also decline any index build .
*/
Assert ( ! OidIsValid ( relFile Node) | | ( skip_build & & ! concurrent ) ) ;
Assert ( ! OidIsValid ( stmt - > old Node) | | ( 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 , relFile Node,
index_create ( rel , indexRelationName , indexRelationId , stmt - > old Node,
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 ( heapR elation, ShareUpdateExclusiveLock ) ;
rel = heap_openrv ( stmt - > r elation, 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 ;