tablecmds.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,338 行 · 第 1/5 页
C
2,338 行
* Automatically create the secondary relation for TOAST if it * formerly had no such but now has toastable attributes. */ AlterTableCreateToastTable(myrelid, true);}/* * ALTER TABLE ALTER COLUMN DROP NOT NULL */voidAlterTableAlterColumnDropNotNull(Oid myrelid, bool recurse, const char *colName){ Relation rel; HeapTuple tuple; AttrNumber attnum; Relation attr_rel; List *indexoidlist; List *indexoidscan; rel = heap_open(myrelid, AccessExclusiveLock); if (rel->rd_rel->relkind != RELKIND_RELATION) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a table", RelationGetRelationName(rel)))); /* Permissions checks */ if (!pg_class_ownercheck(myrelid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, RelationGetRelationName(rel)); if (!allowSystemTableMods && IsSystemRelation(rel)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied: \"%s\" is a system catalog", RelationGetRelationName(rel)))); /* * Propagate to children if desired */ if (recurse) { List *child, *children; /* this routine is actually in the planner */ children = find_all_inheritors(myrelid); /* * find_all_inheritors does the recursive search of the * inheritance hierarchy, so all we have to do is process all of * the relids in the list that it returns. */ foreach(child, children) { Oid childrelid = lfirsto(child); if (childrelid == myrelid) continue; AlterTableAlterColumnDropNotNull(childrelid, false, colName); } } /* now do the thing on this relation */ /* * get the number of the attribute */ attnum = get_attnum(myrelid, colName); if (attnum == InvalidAttrNumber) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column \"%s\" of relation \"%s\" does not exist", colName, RelationGetRelationName(rel)))); /* Prevent them from altering a system attribute */ if (attnum < 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot alter system column \"%s\"", colName))); /* * Check that the attribute is not in a primary key */ /* Loop over all indexes on the relation */ indexoidlist = RelationGetIndexList(rel); foreach(indexoidscan, indexoidlist) { Oid indexoid = lfirsto(indexoidscan); HeapTuple indexTuple; Form_pg_index indexStruct; int i; indexTuple = SearchSysCache(INDEXRELID, ObjectIdGetDatum(indexoid), 0, 0, 0); if (!HeapTupleIsValid(indexTuple)) elog(ERROR, "cache lookup failed for index %u", indexoid); indexStruct = (Form_pg_index) GETSTRUCT(indexTuple); /* If the index is not a primary key, skip the check */ if (indexStruct->indisprimary) { /* * Loop over each attribute in the primary key and see if it * matches the to-be-altered attribute */ for (i = 0; i < indexStruct->indnatts; i++) { if (indexStruct->indkey[i] == attnum) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("column \"%s\" is in a primary key", colName))); } } ReleaseSysCache(indexTuple); } freeList(indexoidlist); /* * Okay, actually perform the catalog change */ attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock); tuple = SearchSysCacheCopyAttName(myrelid, colName); if (!HeapTupleIsValid(tuple)) /* shouldn't happen */ elog(ERROR, "cache lookup failed for attribute \"%s\" of relation %u", colName, myrelid); ((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull = FALSE; simple_heap_update(attr_rel, &tuple->t_self, tuple); /* keep the system catalog indexes current */ CatalogUpdateIndexes(attr_rel, tuple); heap_close(attr_rel, RowExclusiveLock); heap_close(rel, NoLock);}/* * ALTER TABLE ALTER COLUMN SET NOT NULL */voidAlterTableAlterColumnSetNotNull(Oid myrelid, bool recurse, const char *colName){ Relation rel; HeapTuple tuple; AttrNumber attnum; Relation attr_rel; HeapScanDesc scan; TupleDesc tupdesc; rel = heap_open(myrelid, AccessExclusiveLock); if (rel->rd_rel->relkind != RELKIND_RELATION) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a table", RelationGetRelationName(rel)))); /* Permissions checks */ if (!pg_class_ownercheck(myrelid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, RelationGetRelationName(rel)); if (!allowSystemTableMods && IsSystemRelation(rel)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied: \"%s\" is a system catalog", RelationGetRelationName(rel)))); /* * Propagate to children if desired */ if (recurse) { List *child, *children; /* this routine is actually in the planner */ children = find_all_inheritors(myrelid); /* * find_all_inheritors does the recursive search of the * inheritance hierarchy, so all we have to do is process all of * the relids in the list that it returns. */ foreach(child, children) { Oid childrelid = lfirsto(child); if (childrelid == myrelid) continue; AlterTableAlterColumnSetNotNull(childrelid, false, colName); } } /* now do the thing on this relation */ /* * get the number of the attribute */ attnum = get_attnum(myrelid, colName); if (attnum == InvalidAttrNumber) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column \"%s\" of relation \"%s\" does not exist", colName, RelationGetRelationName(rel)))); /* Prevent them from altering a system attribute */ if (attnum < 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot alter system column \"%s\"", colName))); /* * Perform a scan to ensure that there are no NULL values already in * the relation */ tupdesc = RelationGetDescr(rel); scan = heap_beginscan(rel, SnapshotNow, 0, NULL); while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { Datum d; bool isnull; d = heap_getattr(tuple, attnum, tupdesc, &isnull); if (isnull) ereport(ERROR, (errcode(ERRCODE_NOT_NULL_VIOLATION), errmsg("column \"%s\" contains null values", colName))); } heap_endscan(scan); /* * Okay, actually perform the catalog change */ attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock); tuple = SearchSysCacheCopyAttName(myrelid, colName); if (!HeapTupleIsValid(tuple)) /* shouldn't happen */ elog(ERROR, "cache lookup failed for attribute \"%s\" of relation %u", colName, myrelid); ((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull = TRUE; simple_heap_update(attr_rel, &tuple->t_self, tuple); /* keep the system catalog indexes current */ CatalogUpdateIndexes(attr_rel, tuple); heap_close(attr_rel, RowExclusiveLock); heap_close(rel, NoLock);}/* * ALTER TABLE ALTER COLUMN SET/DROP DEFAULT */voidAlterTableAlterColumnDefault(Oid myrelid, bool recurse, const char *colName, Node *newDefault){ Relation rel; AttrNumber attnum; rel = heap_open(myrelid, AccessExclusiveLock); /* * We allow defaults on views so that INSERT into a view can have * default-ish behavior. This works because the rewriter substitutes * default values into INSERTs before it expands rules. */ if (rel->rd_rel->relkind != RELKIND_RELATION && rel->rd_rel->relkind != RELKIND_VIEW) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a table or view", RelationGetRelationName(rel)))); /* Permissions checks */ if (!pg_class_ownercheck(myrelid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, RelationGetRelationName(rel)); if (!allowSystemTableMods && IsSystemRelation(rel)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied: \"%s\" is a system catalog", RelationGetRelationName(rel)))); /* * Propagate to children if desired */ if (recurse) { List *child, *children; /* this routine is actually in the planner */ children = find_all_inheritors(myrelid); /* * find_all_inheritors does the recursive search of the * inheritance hierarchy, so all we have to do is process all of * the relids in the list that it returns. */ foreach(child, children) { Oid childrelid = lfirsto(child); if (childrelid == myrelid) continue; AlterTableAlterColumnDefault(childrelid, false, colName, newDefault); } } /* now do the thing on this relation */ /* * get the number of the attribute */ attnum = get_attnum(myrelid, colName); if (attnum == InvalidAttrNumber) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column \"%s\" of relation \"%s\" does not exist", colName, RelationGetRelationName(rel)))); /* Prevent them from altering a system attribute */ if (attnum < 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot alter system column \"%s\"", colName))); /* * Remove any old default for the column. We use RESTRICT here for * safety, but at present we do not expect anything to depend on the * default. */ RemoveAttrDefault(myrelid, attnum, DROP_RESTRICT, false); if (newDefault) { /* SET DEFAULT */ RawColumnDefault *rawEnt; rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault)); rawEnt->attnum = attnum; rawEnt->raw_default = newDefault; /* * This function is intended for CREATE TABLE, so it processes a * _list_ of defaults, but we just do one. */ AddRelationRawConstraints(rel, makeList1(rawEnt), NIL); } heap_close(rel, NoLock);}/* * ALTER TABLE ALTER COLUMN SET STATISTICS / STORAGE */voidAlterTableAlterColumnFlags(Oid myrelid, bool recurse, const char *colName, Node *flagValue, const char *flagType){ Relation rel; int newtarget = 1; char newstorage = 'p'; Relation attrelation; HeapTuple tuple; Form_pg_attribute attrtuple; rel = heap_open(myrelid, AccessExclusiveLock); if (rel->rd_rel->relkind != RELKIND_RELATION) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a table", RelationGetRelationName(rel)))); /* Permissions checks */ if (!pg_class_ownercheck(myrelid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, RelationGetRelationName(rel)); /* * we allow statistics case for system tables */ if (*flagType != 'S' && !allowSystemTableMods && IsSystemRelation(rel)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied: \"%s\" is a system catalog", RelationGetRelationName(rel)))); /* * Check the supplied parameters before anything else */ if (*flagType == 'S') { /* STATISTICS */ Assert(IsA(flagValue, Integer)); newtarget = intVal(flagValue); /* * Limit target to a sane range */ if (newtarget < -1) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("statistics target %d is too low", newtarget))); } else if (newtarget > 1000) { newtarget = 1000; ereport(WARNING, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("lowering statistics target to %d", newtarget))); } } else if (*flagType == 'M') { /* STORAGE */ char *storagemode; Assert(IsA(flagValue, String)); storagemode = strVal(flagValue); if (strcasecmp(storagemode, "plain") == 0) newstorage = 'p'; else if (strcasecmp(storagemode, "external") == 0) newstorage = 'e'; else if (strcasecmp(storagemode, "extended") == 0) newstorage = 'x'; else if (strcasecmp(storagemode, "main") == 0) newstorage = 'm'; else er
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?