| Line | Hits | Source | Commit |
| 1903 |
- |
index_constraint_create(Relation heapRelation, |
- |
| 1904 |
- |
Oid indexRelationId, |
- |
| 1905 |
- |
Oid parentConstraintId, |
- |
| 1906 |
- |
const IndexInfo *indexInfo, |
- |
| 1907 |
- |
const char *constraintName, |
- |
| 1908 |
- |
char constraintType, |
- |
| 1909 |
- |
uint16 constr_flags, |
- |
| 1910 |
- |
bool allow_system_table_mods, |
- |
| 1911 |
- |
bool is_internal) |
- |
| 1912 |
- |
{ |
- |
| 1913 |
- |
Oid namespaceId = RelationGetNamespace(heapRelation); |
- |
| 1914 |
- |
ObjectAddress myself, |
- |
| 1915 |
- |
idxaddr; |
- |
| 1916 |
- |
Oid conOid; |
- |
| 1917 |
- |
bool deferrable; |
- |
| 1918 |
- |
bool initdeferred; |
- |
| 1919 |
- |
bool mark_as_primary; |
- |
| 1920 |
- |
bool islocal; |
- |
| 1921 |
- |
bool noinherit; |
- |
| 1922 |
- |
bool is_without_overlaps; |
- |
| 1923 |
- |
int16 inhcount; |
- |
| 1924 |
- |
|
- |
| 1925 |
- |
deferrable = (constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) != 0; |
- |
| 1926 |
- |
initdeferred = (constr_flags & INDEX_CONSTR_CREATE_INIT_DEFERRED) != 0; |
- |
| 1927 |
- |
mark_as_primary = (constr_flags & INDEX_CONSTR_CREATE_MARK_AS_PRIMARY) != 0; |
- |
| 1928 |
- |
is_without_overlaps = (constr_flags & INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS) != 0; |
- |
| 1929 |
- |
|
- |
| 1930 |
- |
/* constraint creation support doesn't work while bootstrapping */ |
- |
| 1931 |
- |
Assert(!IsBootstrapProcessingMode()); |
- |
| 1932 |
- |
|
- |
| 1933 |
- |
/* enforce system-table restriction */ |
- |
| 1934 |
- |
if (!allow_system_table_mods && |
- |
| 1935 |
- |
IsSystemRelation(heapRelation) && |
- |
| 1936 |
- |
IsNormalProcessingMode()) |
- |
| 1937 |
- |
ereport(ERROR, |
- |
| 1938 |
- |
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
- |
| 1939 |
- |
errmsg("user-defined indexes on system catalog tables are not supported"))); |
- |
| 1940 |
- |
|
- |
| 1941 |
- |
/* primary/unique constraints shouldn't have any expressions */ |
- |
| 1942 |
- |
if (indexInfo->ii_Expressions && |
- |
| 1943 |
- |
constraintType != CONSTRAINT_EXCLUSION) |
- |
| 1944 |
- |
elog(ERROR, "constraints cannot have index expressions"); |
- |
| 1945 |
- |
|
- |
| 1946 |
- |
/* |
- |
| 1947 |
- |
* If we're manufacturing a constraint for a pre-existing index, we need |
- |
| 1948 |
- |
* to get rid of the existing auto dependencies for the index (the ones |
- |
| 1949 |
- |
* that index_create() would have made instead of calling this function). |
- |
| 1950 |
- |
* |
- |
| 1951 |
- |
* Note: this code would not necessarily do the right thing if the index |
- |
| 1952 |
- |
* has any expressions or predicate, but we'd never be turning such an |
- |
| 1953 |
- |
* index into a UNIQUE or PRIMARY KEY constraint. |
- |
| 1954 |
- |
*/ |
- |
| 1955 |
- |
if (constr_flags & INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS) |
- |
| 1956 |
- |
deleteDependencyRecordsForClass(RelationRelationId, indexRelationId, |
- |
| 1957 |
- |
RelationRelationId, DEPENDENCY_AUTO); |
- |
| 1958 |
- |
|
- |
| 1959 |
- |
if (OidIsValid(parentConstraintId)) |
- |
| 1960 |
- |
{ |
- |
| 1961 |
- |
islocal = false; |
- |
| 1962 |
- |
inhcount = 1; |
- |
| 1963 |
- |
noinherit = false; |
- |
| 1964 |
- |
} |
- |
| 1965 |
- |
else |
- |
| 1966 |
- |
{ |
- |
| 1967 |
- |
islocal = true; |
- |
| 1968 |
- |
inhcount = 0; |
- |
| 1969 |
- |
noinherit = true; |
- |
| 1970 |
- |
} |
- |
| 1971 |
- |
|
- |
| 1972 |
- |
/* |
- |
| 1973 |
- |
* Construct a pg_constraint entry. |
- |
| 1974 |
- |
*/ |
- |
| 1975 |
- |
conOid = CreateConstraintEntry(constraintName, |
- |
| 1976 |
- |
namespaceId, |
- |
| 1977 |
- |
constraintType, |
- |
| 1978 |
- |
deferrable, |
- |
| 1979 |
- |
initdeferred, |
- |
| 1980 |
- |
true, /* Is Enforced */ |
- |
| 1981 |
- |
true, |
- |
| 1982 |
- |
parentConstraintId, |
- |
| 1983 |
- |
RelationGetRelid(heapRelation), |
- |
| 1984 |
- |
indexInfo->ii_IndexAttrNumbers, |
- |
| 1985 |
- |
indexInfo->ii_NumIndexKeyAttrs, |
- |
| 1986 |
- |
indexInfo->ii_NumIndexAttrs, |
- |
| 1987 |
- |
InvalidOid, /* no domain */ |
- |
| 1988 |
- |
indexRelationId, /* index OID */ |
- |
| 1989 |
- |
InvalidOid, /* no foreign key */ |
- |
| 1990 |
- |
NULL, |
- |
| 1991 |
- |
NULL, |
- |
| 1992 |
- |
NULL, |
- |
| 1993 |
- |
NULL, |
- |
| 1994 |
- |
0, |
- |
| 1995 |
- |
' ', |
- |
| 1996 |
- |
' ', |
- |
| 1997 |
- |
NULL, |
- |
| 1998 |
- |
0, |
- |
| 1999 |
- |
' ', |
- |
| 2000 |
- |
indexInfo->ii_ExclusionOps, |
- |
| 2001 |
- |
NULL, /* no check constraint */ |
- |
| 2002 |
- |
NULL, |
- |
| 2003 |
- |
islocal, |
- |
| 2004 |
- |
inhcount, |
- |
| 2005 |
- |
noinherit, |
- |
| 2006 |
- |
is_without_overlaps, |
- |
| 2007 |
- |
is_internal); |
- |
| 2008 |
- |
|
- |
| 2009 |
- |
/* |
- |
| 2010 |
- |
* Register the index as internally dependent on the constraint. |
- |
| 2011 |
- |
* |
- |
| 2012 |
- |
* Note that the constraint has a dependency on the table, so we don't |
- |
| 2013 |
- |
* need (or want) any direct dependency from the index to the table. |
- |
| 2014 |
- |
*/ |
- |
| 2015 |
- |
ObjectAddressSet(myself, ConstraintRelationId, conOid); |
- |
| 2016 |
- |
ObjectAddressSet(idxaddr, RelationRelationId, indexRelationId); |
- |
| 2017 |
- |
recordDependencyOn(&idxaddr, &myself, DEPENDENCY_INTERNAL); |
- |
| 2018 |
- |
|
- |
| 2019 |
- |
/* |
- |
| 2020 |
- |
* Also, if this is a constraint on a partition, give it partition-type |
- |
| 2021 |
- |
* dependencies on the parent constraint as well as the table. |
- |
| 2022 |
- |
*/ |
- |
| 2023 |
- |
if (OidIsValid(parentConstraintId)) |
- |
| 2024 |
- |
{ |
- |
| 2025 |
- |
ObjectAddress referenced; |
- |
| 2026 |
- |
|
- |
| 2027 |
- |
ObjectAddressSet(referenced, ConstraintRelationId, parentConstraintId); |
- |
| 2028 |
- |
recordDependencyOn(&myself, &referenced, DEPENDENCY_PARTITION_PRI); |
- |
| 2029 |
- |
ObjectAddressSet(referenced, RelationRelationId, |
- |
| 2030 |
- |
RelationGetRelid(heapRelation)); |
- |
| 2031 |
- |
recordDependencyOn(&myself, &referenced, DEPENDENCY_PARTITION_SEC); |
- |
| 2032 |
- |
} |
- |
| 2033 |
- |
|
- |
| 2034 |
- |
/* |
- |
| 2035 |
- |
* If the constraint is deferrable, create the deferred uniqueness |
- |
| 2036 |
- |
* checking trigger. (The trigger will be given an internal dependency on |
- |
| 2037 |
- |
* the constraint by CreateTrigger.) |
- |
| 2038 |
- |
*/ |
- |
| 2039 |
- |
if (deferrable) |
- |
| 2040 |
- |
{ |
- |
| 2041 |
- |
CreateTrigStmt *trigger = makeNode(CreateTrigStmt); |
- |
| 2042 |
- |
|
- |
| 2043 |
- |
trigger->replace = false; |
- |
| 2044 |
111 |
trigger->tgenabled = TRIGGER_FIRES_ON_ORIGIN; |
39ae762CREATE TABLE LIKE INCLUDING TRIGGERS copies tgenabled |
| 2045 |
- |
trigger->isconstraint = true; |
- |
| 2046 |
- |
trigger->trigname = (constraintType == CONSTRAINT_PRIMARY) ? |
- |
| 2047 |
- |
"PK_ConstraintTrigger" : |
- |
| 2048 |
- |
"Unique_ConstraintTrigger"; |
- |
| 2049 |
- |
trigger->relation = NULL; |
- |
| 2050 |
- |
trigger->funcname = SystemFuncName("unique_key_recheck"); |
- |
| 2051 |
- |
trigger->args = NIL; |
- |
| 2052 |
- |
trigger->row = true; |
- |
| 2053 |
- |
trigger->timing = TRIGGER_TYPE_AFTER; |
- |
| 2054 |
- |
trigger->events = TRIGGER_TYPE_INSERT | TRIGGER_TYPE_UPDATE; |
- |
| 2055 |
- |
trigger->columns = NIL; |
- |
| 2056 |
- |
trigger->whenClause = NULL; |
- |
| 2057 |
- |
trigger->transitionRels = NIL; |
- |
| 2058 |
- |
trigger->deferrable = true; |
- |
| 2059 |
- |
trigger->initdeferred = initdeferred; |
- |
| 2060 |
- |
trigger->constrrel = NULL; |
- |
| 2061 |
111 |
trigger->trigcomment = NULL; |
e73f551CREATE TABLE LIKE INCLUDING TRIGGERS |
| 2062 |
111 |
trigger->transformed = true; |
e73f551CREATE TABLE LIKE INCLUDING TRIGGERS |
| 2063 |
- |
|
- |
| 2064 |
- |
(void) CreateTrigger(trigger, NULL, RelationGetRelid(heapRelation), |
- |
| 2065 |
- |
InvalidOid, conOid, indexRelationId, InvalidOid, |
- |
| 2066 |
- |
InvalidOid, NULL, true, false); |
- |
| 2067 |
- |
} |
- |
| 2068 |
- |
|
- |
| 2069 |
- |
/* |
- |
| 2070 |
- |
* If needed, mark the index as primary and/or deferred in pg_index. |
- |
| 2071 |
- |
* |
- |
| 2072 |
- |
* Note: When making an existing index into a constraint, caller must have |
- |
| 2073 |
- |
* a table lock that prevents concurrent table updates; otherwise, there |
- |
| 2074 |
- |
* is a risk that concurrent readers of the table will miss seeing this |
- |
| 2075 |
- |
* index at all. |
- |
| 2076 |
- |
*/ |
- |
| 2077 |
- |
if ((constr_flags & INDEX_CONSTR_CREATE_UPDATE_INDEX) && |
- |
| 2078 |
- |
(mark_as_primary || deferrable)) |
- |
| 2079 |
- |
{ |
- |
| 2080 |
- |
Relation pg_index; |
- |
| 2081 |
- |
HeapTuple indexTuple; |
- |
| 2082 |
- |
Form_pg_index indexForm; |
- |
| 2083 |
- |
bool dirty = false; |
- |
| 2084 |
- |
bool marked_as_primary = false; |
- |
| 2085 |
- |
|
- |
| 2086 |
- |
pg_index = table_open(IndexRelationId, RowExclusiveLock); |
- |
| 2087 |
- |
|
- |
| 2088 |
- |
indexTuple = SearchSysCacheCopy1(INDEXRELID, |
- |
| 2089 |
- |
ObjectIdGetDatum(indexRelationId)); |
- |
| 2090 |
- |
if (!HeapTupleIsValid(indexTuple)) |
- |
| 2091 |
- |
elog(ERROR, "cache lookup failed for index %u", indexRelationId); |
- |
| 2092 |
- |
indexForm = (Form_pg_index) GETSTRUCT(indexTuple); |
- |
| 2093 |
- |
|
- |
| 2094 |
- |
if (mark_as_primary && !indexForm->indisprimary) |
- |
| 2095 |
- |
{ |
- |
| 2096 |
- |
indexForm->indisprimary = true; |
- |
| 2097 |
- |
dirty = true; |
- |
| 2098 |
- |
marked_as_primary = true; |
- |
| 2099 |
- |
} |
- |
| 2100 |
- |
|
- |
| 2101 |
- |
if (deferrable && indexForm->indimmediate) |
- |
| 2102 |
- |
{ |
- |
| 2103 |
- |
indexForm->indimmediate = false; |
- |
| 2104 |
- |
dirty = true; |
- |
| 2105 |
- |
} |
- |
| 2106 |
- |
|
- |
| 2107 |
- |
if (dirty) |
- |
| 2108 |
- |
{ |
- |
| 2109 |
- |
CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple); |
- |
| 2110 |
- |
|
- |
| 2111 |
- |
/* |
- |
| 2112 |
- |
* When we mark an existing index as primary, force a relcache |
- |
| 2113 |
- |
* flush on its parent table, so that all sessions will become |
- |
| 2114 |
- |
* aware that the table now has a primary key. This is important |
- |
| 2115 |
- |
* because it affects some replication behaviors. |
- |
| 2116 |
- |
*/ |
- |
| 2117 |
- |
if (marked_as_primary) |
- |
| 2118 |
- |
CacheInvalidateRelcache(heapRelation); |
- |
| 2119 |
- |
|
- |
| 2120 |
- |
InvokeObjectPostAlterHookArg(IndexRelationId, indexRelationId, 0, |
- |
| 2121 |
- |
InvalidOid, is_internal); |
- |
| 2122 |
- |
} |
- |
| 2123 |
- |
|
- |
| 2124 |
- |
heap_freetuple(indexTuple); |
- |
| 2125 |
- |
table_close(pg_index, RowExclusiveLock); |
- |
| 2126 |
- |
} |
- |
| 2127 |
- |
|
- |
| 2128 |
- |
return myself; |
- |
| 2129 |
- |
} |
- |