Skip to content

Commit a61f5ab

Browse files
committed
Simplify index_[constraint_]create API
Instead of passing large swaths of boolean arguments, define some flags that can be used in a bitmask. This makes it easier not only to figure out what each call site is doing, but also to add some new flags. The flags are split in two -- one set for index_create directly and another for constraints. index_create() itself receives both, and then passes down the latter to index_constraint_create(), which can also be called standalone. Discussion: https://postgr.es/m/20171023151251.j75uoe27gajdjmlm@alvherre.pgsql Reviewed-by: Simon Riggs
1 parent 591c504 commit a61f5ab

File tree

5 files changed

+104
-79
lines changed

5 files changed

+104
-79
lines changed

src/backend/catalog/index.c

Lines changed: 54 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -680,19 +680,25 @@ UpdateIndexRelation(Oid indexoid,
680680
* classObjectId: array of index opclass OIDs, one per index column
681681
* coloptions: array of per-index-column indoption settings
682682
* reloptions: AM-specific options
683-
* isprimary: index is a PRIMARY KEY
684-
* isconstraint: index is owned by PRIMARY KEY, UNIQUE, or EXCLUSION constraint
685-
* deferrable: constraint is DEFERRABLE
686-
* initdeferred: constraint is INITIALLY DEFERRED
683+
* flags: bitmask that can include any combination of these bits:
684+
* INDEX_CREATE_IS_PRIMARY
685+
* the index is a primary key
686+
* INDEX_CREATE_ADD_CONSTRAINT:
687+
* invoke index_constraint_create also
688+
* INDEX_CREATE_SKIP_BUILD:
689+
* skip the index_build() step for the moment; caller must do it
690+
* later (typically via reindex_index())
691+
* INDEX_CREATE_CONCURRENT:
692+
* do not lock the table against writers. The index will be
693+
* marked "invalid" and the caller must take additional steps
694+
* to fix it up.
695+
* INDEX_CREATE_IF_NOT_EXISTS:
696+
* do not throw an error if a relation with the same name
697+
* already exists.
698+
* constr_flags: flags passed to index_constraint_create
699+
* (only if INDEX_CREATE_ADD_CONSTRAINT is set)
687700
* allow_system_table_mods: allow table to be a system catalog
688-
* skip_build: true to skip the index_build() step for the moment; caller
689-
* must do it later (typically via reindex_index())
690-
* concurrent: if true, do not lock the table against writers. The index
691-
* will be marked "invalid" and the caller must take additional steps
692-
* to fix it up.
693701
* is_internal: if true, post creation hook for new index
694-
* if_not_exists: if true, do not throw an error if a relation with
695-
* the same name already exists.
696702
*
697703
* Returns the OID of the created index.
698704
*/
@@ -709,15 +715,10 @@ index_create(Relation heapRelation,
709715
Oid *classObjectId,
710716
int16 *coloptions,
711717
Datum reloptions,
712-
bool isprimary,
713-
bool isconstraint,
714-
bool deferrable,
715-
bool initdeferred,
718+
bits16 flags,
719+
bits16 constr_flags,
716720
bool allow_system_table_mods,
717-
bool skip_build,
718-
bool concurrent,
719-
bool is_internal,
720-
bool if_not_exists)
721+
bool is_internal)
721722
{
722723
Oid heapRelationId = RelationGetRelid(heapRelation);
723724
Relation pg_class;
@@ -729,6 +730,12 @@ index_create(Relation heapRelation,
729730
Oid namespaceId;
730731
int i;
731732
char relpersistence;
733+
bool isprimary = (flags & INDEX_CREATE_IS_PRIMARY) != 0;
734+
bool concurrent = (flags & INDEX_CREATE_CONCURRENT) != 0;
735+
736+
/* constraint flags can only be set when a constraint is requested */
737+
Assert((constr_flags == 0) ||
738+
((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0));
732739

733740
is_exclusion = (indexInfo->ii_ExclusionOps != NULL);
734741

@@ -794,7 +801,7 @@ index_create(Relation heapRelation,
794801

795802
if (get_relname_relid(indexRelationName, namespaceId))
796803
{
797-
if (if_not_exists)
804+
if ((flags & INDEX_CREATE_IF_NOT_EXISTS) != 0)
798805
{
799806
ereport(NOTICE,
800807
(errcode(ERRCODE_DUPLICATE_TABLE),
@@ -917,7 +924,7 @@ index_create(Relation heapRelation,
917924
UpdateIndexRelation(indexRelationId, heapRelationId, indexInfo,
918925
collationObjectId, classObjectId, coloptions,
919926
isprimary, is_exclusion,
920-
!deferrable,
927+
(constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) == 0,
921928
!concurrent);
922929

923930
/*
@@ -943,7 +950,7 @@ index_create(Relation heapRelation,
943950
myself.objectId = indexRelationId;
944951
myself.objectSubId = 0;
945952

946-
if (isconstraint)
953+
if ((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0)
947954
{
948955
char constraintType;
949956

@@ -964,11 +971,7 @@ index_create(Relation heapRelation,
964971
indexInfo,
965972
indexRelationName,
966973
constraintType,
967-
deferrable,
968-
initdeferred,
969-
false, /* already marked primary */
970-
false, /* pg_index entry is OK */
971-
false, /* no old dependencies */
974+
constr_flags,
972975
allow_system_table_mods,
973976
is_internal);
974977
}
@@ -1005,10 +1008,6 @@ index_create(Relation heapRelation,
10051008

10061009
recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
10071010
}
1008-
1009-
/* Non-constraint indexes can't be deferrable */
1010-
Assert(!deferrable);
1011-
Assert(!initdeferred);
10121011
}
10131012

10141013
/* Store dependency on collations */
@@ -1059,9 +1058,7 @@ index_create(Relation heapRelation,
10591058
else
10601059
{
10611060
/* Bootstrap mode - assert we weren't asked for constraint support */
1062-
Assert(!isconstraint);
1063-
Assert(!deferrable);
1064-
Assert(!initdeferred);
1061+
Assert((flags & INDEX_CREATE_ADD_CONSTRAINT) == 0);
10651062
}
10661063

10671064
/* Post creation hook for new index */
@@ -1089,15 +1086,16 @@ index_create(Relation heapRelation,
10891086
* If this is bootstrap (initdb) time, then we don't actually fill in the
10901087
* index yet. We'll be creating more indexes and classes later, so we
10911088
* delay filling them in until just before we're done with bootstrapping.
1092-
* Similarly, if the caller specified skip_build then filling the index is
1093-
* delayed till later (ALTER TABLE can save work in some cases with this).
1094-
* Otherwise, we call the AM routine that constructs the index.
1089+
* Similarly, if the caller specified to skip the build then filling the
1090+
* index is delayed till later (ALTER TABLE can save work in some cases
1091+
* with this). Otherwise, we call the AM routine that constructs the
1092+
* index.
10951093
*/
10961094
if (IsBootstrapProcessingMode())
10971095
{
10981096
index_register(heapRelationId, indexRelationId, indexInfo);
10991097
}
1100-
else if (skip_build)
1098+
else if ((flags & INDEX_CREATE_SKIP_BUILD) != 0)
11011099
{
11021100
/*
11031101
* Caller is responsible for filling the index later on. However,
@@ -1137,12 +1135,13 @@ index_create(Relation heapRelation,
11371135
* constraintName: what it say (generally, should match name of index)
11381136
* constraintType: one of CONSTRAINT_PRIMARY, CONSTRAINT_UNIQUE, or
11391137
* CONSTRAINT_EXCLUSION
1140-
* deferrable: constraint is DEFERRABLE
1141-
* initdeferred: constraint is INITIALLY DEFERRED
1142-
* mark_as_primary: if true, set flags to mark index as primary key
1143-
* update_pgindex: if true, update pg_index row (else caller's done that)
1144-
* remove_old_dependencies: if true, remove existing dependencies of index
1145-
* on table's columns
1138+
* flags: bitmask that can include any combination of these bits:
1139+
* INDEX_CONSTR_CREATE_MARK_AS_PRIMARY: index is a PRIMARY KEY
1140+
* INDEX_CONSTR_CREATE_DEFERRABLE: constraint is DEFERRABLE
1141+
* INDEX_CONSTR_CREATE_INIT_DEFERRED: constraint is INITIALLY DEFERRED
1142+
* INDEX_CONSTR_CREATE_UPDATE_INDEX: update the pg_index row
1143+
* INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS: remove existing dependencies
1144+
* of index on table's columns
11461145
* allow_system_table_mods: allow table to be a system catalog
11471146
* is_internal: index is constructed due to internal process
11481147
*/
@@ -1152,18 +1151,21 @@ index_constraint_create(Relation heapRelation,
11521151
IndexInfo *indexInfo,
11531152
const char *constraintName,
11541153
char constraintType,
1155-
bool deferrable,
1156-
bool initdeferred,
1157-
bool mark_as_primary,
1158-
bool update_pgindex,
1159-
bool remove_old_dependencies,
1154+
bits16 constr_flags,
11601155
bool allow_system_table_mods,
11611156
bool is_internal)
11621157
{
11631158
Oid namespaceId = RelationGetNamespace(heapRelation);
11641159
ObjectAddress myself,
11651160
referenced;
11661161
Oid conOid;
1162+
bool deferrable;
1163+
bool initdeferred;
1164+
bool mark_as_primary;
1165+
1166+
deferrable = (constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) != 0;
1167+
initdeferred = (constr_flags & INDEX_CONSTR_CREATE_INIT_DEFERRED) != 0;
1168+
mark_as_primary = (constr_flags & INDEX_CONSTR_CREATE_MARK_AS_PRIMARY) != 0;
11671169

11681170
/* constraint creation support doesn't work while bootstrapping */
11691171
Assert(!IsBootstrapProcessingMode());
@@ -1190,7 +1192,7 @@ index_constraint_create(Relation heapRelation,
11901192
* has any expressions or predicate, but we'd never be turning such an
11911193
* index into a UNIQUE or PRIMARY KEY constraint.
11921194
*/
1193-
if (remove_old_dependencies)
1195+
if (constr_flags & INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS)
11941196
deleteDependencyRecordsForClass(RelationRelationId, indexRelationId,
11951197
RelationRelationId, DEPENDENCY_AUTO);
11961198

@@ -1295,7 +1297,8 @@ index_constraint_create(Relation heapRelation,
12951297
* is a risk that concurrent readers of the table will miss seeing this
12961298
* index at all.
12971299
*/
1298-
if (update_pgindex && (mark_as_primary || deferrable))
1300+
if ((constr_flags & INDEX_CONSTR_CREATE_UPDATE_INDEX) &&
1301+
(mark_as_primary || deferrable))
12991302
{
13001303
Relation pg_index;
13011304
HeapTuple indexTuple;

src/backend/catalog/toasting.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
333333
BTREE_AM_OID,
334334
rel->rd_rel->reltablespace,
335335
collationObjectId, classObjectId, coloptions, (Datum) 0,
336-
true, false, false, false,
337-
true, false, false, true, false);
336+
INDEX_CREATE_IS_PRIMARY, 0, true, true);
338337

339338
heap_close(toast_rel, NoLock);
340339

src/backend/commands/indexcmds.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,8 @@ DefineIndex(Oid relationId,
333333
Datum reloptions;
334334
int16 *coloptions;
335335
IndexInfo *indexInfo;
336+
bits16 flags;
337+
bits16 constr_flags;
336338
int numberOfAttributes;
337339
TransactionId limitXmin;
338340
VirtualTransactionId *old_snapshots;
@@ -661,20 +663,35 @@ DefineIndex(Oid relationId,
661663
Assert(!OidIsValid(stmt->oldNode) || (skip_build && !stmt->concurrent));
662664

663665
/*
664-
* Make the catalog entries for the index, including constraints. Then, if
665-
* not skip_build || concurrent, actually build the index.
666+
* Make the catalog entries for the index, including constraints. This
667+
* step also actually builds the index, except if caller requested not to
668+
* or in concurrent mode, in which case it'll be done later.
666669
*/
670+
flags = constr_flags = 0;
671+
if (stmt->isconstraint)
672+
flags |= INDEX_CREATE_ADD_CONSTRAINT;
673+
if (skip_build || stmt->concurrent)
674+
flags |= INDEX_CREATE_SKIP_BUILD;
675+
if (stmt->if_not_exists)
676+
flags |= INDEX_CREATE_IF_NOT_EXISTS;
677+
if (stmt->concurrent)
678+
flags |= INDEX_CREATE_CONCURRENT;
679+
if (stmt->primary)
680+
flags |= INDEX_CREATE_IS_PRIMARY;
681+
682+
if (stmt->deferrable)
683+
constr_flags |= INDEX_CONSTR_CREATE_DEFERRABLE;
684+
if (stmt->initdeferred)
685+
constr_flags |= INDEX_CONSTR_CREATE_INIT_DEFERRED;
686+
667687
indexRelationId =
668688
index_create(rel, indexRelationName, indexRelationId, stmt->oldNode,
669689
indexInfo, indexColNames,
670690
accessMethodId, tablespaceId,
671691
collationObjectId, classObjectId,
672-
coloptions, reloptions, stmt->primary,
673-
stmt->isconstraint, stmt->deferrable, stmt->initdeferred,
674-
allowSystemTableMods,
675-
skip_build || stmt->concurrent,
676-
stmt->concurrent, !check_rights,
677-
stmt->if_not_exists);
692+
coloptions, reloptions,
693+
flags, constr_flags,
694+
allowSystemTableMods, !check_rights);
678695

679696
ObjectAddressSet(address, RelationRelationId, indexRelationId);
680697

src/backend/commands/tablecmds.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6836,6 +6836,7 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
68366836
char *constraintName;
68376837
char constraintType;
68386838
ObjectAddress address;
6839+
bits16 flags;
68396840

68406841
Assert(IsA(stmt, IndexStmt));
68416842
Assert(OidIsValid(index_oid));
@@ -6880,16 +6881,18 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
68806881
constraintType = CONSTRAINT_UNIQUE;
68816882

68826883
/* Create the catalog entries for the constraint */
6884+
flags = INDEX_CONSTR_CREATE_UPDATE_INDEX |
6885+
INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS |
6886+
(stmt->initdeferred ? INDEX_CONSTR_CREATE_INIT_DEFERRED : 0) |
6887+
(stmt->deferrable ? INDEX_CONSTR_CREATE_DEFERRABLE : 0) |
6888+
(stmt->primary ? INDEX_CONSTR_CREATE_MARK_AS_PRIMARY : 0);
6889+
68836890
address = index_constraint_create(rel,
68846891
index_oid,
68856892
indexInfo,
68866893
constraintName,
68876894
constraintType,
6888-
stmt->deferrable,
6889-
stmt->initdeferred,
6890-
stmt->primary,
6891-
true, /* update pg_index */
6892-
true, /* remove old dependencies */
6895+
flags,
68936896
allowSystemTableMods,
68946897
false); /* is_internal */
68956898

src/include/catalog/index.h

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ extern void index_check_primary_key(Relation heapRel,
4242
IndexInfo *indexInfo,
4343
bool is_alter_table);
4444

45+
#define INDEX_CREATE_IS_PRIMARY (1 << 0)
46+
#define INDEX_CREATE_ADD_CONSTRAINT (1 << 1)
47+
#define INDEX_CREATE_SKIP_BUILD (1 << 2)
48+
#define INDEX_CREATE_CONCURRENT (1 << 3)
49+
#define INDEX_CREATE_IF_NOT_EXISTS (1 << 4)
50+
4551
extern Oid index_create(Relation heapRelation,
4652
const char *indexRelationName,
4753
Oid indexRelationId,
@@ -54,26 +60,23 @@ extern Oid index_create(Relation heapRelation,
5460
Oid *classObjectId,
5561
int16 *coloptions,
5662
Datum reloptions,
57-
bool isprimary,
58-
bool isconstraint,
59-
bool deferrable,
60-
bool initdeferred,
63+
bits16 flags,
64+
bits16 constr_flags,
6165
bool allow_system_table_mods,
62-
bool skip_build,
63-
bool concurrent,
64-
bool is_internal,
65-
bool if_not_exists);
66+
bool is_internal);
67+
68+
#define INDEX_CONSTR_CREATE_MARK_AS_PRIMARY (1 << 0)
69+
#define INDEX_CONSTR_CREATE_DEFERRABLE (1 << 1)
70+
#define INDEX_CONSTR_CREATE_INIT_DEFERRED (1 << 2)
71+
#define INDEX_CONSTR_CREATE_UPDATE_INDEX (1 << 3)
72+
#define INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS (1 << 4)
6673

6774
extern ObjectAddress index_constraint_create(Relation heapRelation,
6875
Oid indexRelationId,
6976
IndexInfo *indexInfo,
7077
const char *constraintName,
7178
char constraintType,
72-
bool deferrable,
73-
bool initdeferred,
74-
bool mark_as_primary,
75-
bool update_pgindex,
76-
bool remove_old_dependencies,
79+
bits16 constr_flags,
7780
bool allow_system_table_mods,
7881
bool is_internal);
7982

0 commit comments

Comments
 (0)