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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy