⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tablecmds.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
		}		values[Anum_pg_trigger_tgargs - 1] = PointerGetDatum(newtgargs);		replaces[Anum_pg_trigger_tgargs - 1] = 'r';		tuple = heap_modifytuple(tuple, RelationGetDescr(tgrel), values, nulls, replaces);		/*		 * Update pg_trigger and its indexes		 */		simple_heap_update(tgrel, &tuple->t_self, tuple);		CatalogUpdateIndexes(tgrel, tuple);		/*		 * Invalidate trigger's relation's relcache entry so that other		 * backends (and this one too!) are sent SI message to make them		 * rebuild relcache entries.  (Ideally this should happen		 * automatically...)		 *		 * We can skip this for triggers on relid itself, since that relcache		 * flush will happen anyway due to the table or column rename.	We		 * just need to catch the far ends of RI relationships.		 */		pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);		if (pg_trigger->tgrelid != relid)			CacheInvalidateRelcacheByRelid(pg_trigger->tgrelid);		/* free up our scratch memory */		pfree(newtgargs);		heap_freetuple(tuple);	}	systable_endscan(trigscan);	heap_close(tgrel, RowExclusiveLock);	/*	 * Increment cmd counter to make updates visible; this is needed in case	 * the same tuple has to be updated again by next pass (can happen in case	 * of a self-referential FK relationship).	 */	CommandCounterIncrement();}/* * AlterTable *		Execute ALTER TABLE, which can be a list of subcommands * * ALTER TABLE is performed in three phases: *		1. Examine subcommands and perform pre-transformation checking. *		2. Update system catalogs. *		3. Scan table(s) to check new constraints, and optionally recopy *		   the data into new table(s). * Phase 3 is not performed unless one or more of the subcommands requires * it.	The intention of this design is to allow multiple independent * updates of the table schema to be performed with only one pass over the * data. * * ATPrepCmd performs phase 1.	A "work queue" entry is created for * each table to be affected (there may be multiple affected tables if the * commands traverse a table inheritance hierarchy).  Also we do preliminary * validation of the subcommands, including parse transformation of those * expressions that need to be evaluated with respect to the old table * schema. * * ATRewriteCatalogs performs phase 2 for each affected table (note that * phases 2 and 3 do no explicit recursion, since phase 1 already did it). * Certain subcommands need to be performed before others to avoid * unnecessary conflicts; for example, DROP COLUMN should come before * ADD COLUMN.	Therefore phase 1 divides the subcommands into multiple * lists, one for each logical "pass" of phase 2. * * ATRewriteTables performs phase 3 for those tables that need it. * * Thanks to the magic of MVCC, an error anywhere along the way rolls back * the whole operation; we don't have to do anything special to clean up. */voidAlterTable(AlterTableStmt *stmt){	ATController(relation_openrv(stmt->relation, AccessExclusiveLock),				 stmt->cmds,				 interpretInhOption(stmt->relation->inhOpt));}/* * AlterTableInternal * * ALTER TABLE with target specified by OID */voidAlterTableInternal(Oid relid, List *cmds, bool recurse){	ATController(relation_open(relid, AccessExclusiveLock),				 cmds,				 recurse);}static voidATController(Relation rel, List *cmds, bool recurse){	List	   *wqueue = NIL;	ListCell   *lcmd;	/* Phase 1: preliminary examination of commands, create work queue */	foreach(lcmd, cmds)	{		AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);		ATPrepCmd(&wqueue, rel, cmd, recurse, false);	}	/* Close the relation, but keep lock until commit */	relation_close(rel, NoLock);	/* Phase 2: update system catalogs */	ATRewriteCatalogs(&wqueue);	/* Phase 3: scan/rewrite tables as needed */	ATRewriteTables(&wqueue);}/* * ATPrepCmd * * Traffic cop for ALTER TABLE Phase 1 operations, including simple * recursion and permission checks. * * Caller must have acquired AccessExclusiveLock on relation already. * This lock should be held until commit. */static voidATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,		  bool recurse, bool recursing){	AlteredTableInfo *tab;	int			pass;	/* Find or create work queue entry for this table */	tab = ATGetQueueEntry(wqueue, rel);	/*	 * Copy the original subcommand for each table.  This avoids conflicts	 * when different child tables need to make different parse	 * transformations (for example, the same column may have different column	 * numbers in different children).	 */	cmd = copyObject(cmd);	/*	 * Do permissions checking, recursion to child tables if needed, and any	 * additional phase-1 processing needed.	 */	switch (cmd->subtype)	{		case AT_AddColumn:		/* ADD COLUMN */			ATSimplePermissions(rel, false);			/* Performs own recursion */			ATPrepAddColumn(wqueue, rel, recurse, cmd);			pass = AT_PASS_ADD_COL;			break;		case AT_ColumnDefault:	/* ALTER COLUMN DEFAULT */			/*			 * 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.			 */			ATSimplePermissions(rel, true);			ATSimpleRecursion(wqueue, rel, cmd, recurse);			/* No command-specific prep needed */			pass = AT_PASS_ADD_CONSTR;			break;		case AT_DropNotNull:	/* ALTER COLUMN DROP NOT NULL */			ATSimplePermissions(rel, false);			ATSimpleRecursion(wqueue, rel, cmd, recurse);			/* No command-specific prep needed */			pass = AT_PASS_DROP;			break;		case AT_SetNotNull:		/* ALTER COLUMN SET NOT NULL */			ATSimplePermissions(rel, false);			ATSimpleRecursion(wqueue, rel, cmd, recurse);			/* No command-specific prep needed */			pass = AT_PASS_ADD_CONSTR;			break;		case AT_SetStatistics:	/* ALTER COLUMN STATISTICS */			ATSimpleRecursion(wqueue, rel, cmd, recurse);			/* Performs own permission checks */			ATPrepSetStatistics(rel, cmd->name, cmd->def);			pass = AT_PASS_COL_ATTRS;			break;		case AT_SetStorage:		/* ALTER COLUMN STORAGE */			ATSimplePermissions(rel, false);			ATSimpleRecursion(wqueue, rel, cmd, recurse);			/* No command-specific prep needed */			pass = AT_PASS_COL_ATTRS;			break;		case AT_DropColumn:		/* DROP COLUMN */			ATSimplePermissions(rel, false);			/* Recursion occurs during execution phase */			/* No command-specific prep needed except saving recurse flag */			if (recurse)				cmd->subtype = AT_DropColumnRecurse;			pass = AT_PASS_DROP;			break;		case AT_AddIndex:		/* ADD INDEX */			ATSimplePermissions(rel, false);			/* This command never recurses */			/* No command-specific prep needed */			pass = AT_PASS_ADD_INDEX;			break;		case AT_AddConstraint:	/* ADD CONSTRAINT */			ATSimplePermissions(rel, false);			/*			 * Currently we recurse only for CHECK constraints, never for			 * foreign-key constraints.  UNIQUE/PKEY constraints won't be seen			 * here.			 */			if (IsA(cmd->def, Constraint))				ATSimpleRecursion(wqueue, rel, cmd, recurse);			/* No command-specific prep needed */			pass = AT_PASS_ADD_CONSTR;			break;		case AT_DropConstraint:	/* DROP CONSTRAINT */			ATSimplePermissions(rel, false);			/* Performs own recursion */			ATPrepDropConstraint(wqueue, rel, recurse, cmd);			pass = AT_PASS_DROP;			break;		case AT_DropConstraintQuietly:	/* DROP CONSTRAINT for child */			ATSimplePermissions(rel, false);			ATSimpleRecursion(wqueue, rel, cmd, recurse);			/* No command-specific prep needed */			pass = AT_PASS_DROP;			break;		case AT_AlterColumnType:		/* ALTER COLUMN TYPE */			ATSimplePermissions(rel, false);			/* Performs own recursion */			ATPrepAlterColumnType(wqueue, tab, rel, recurse, recursing, cmd);			pass = AT_PASS_ALTER_TYPE;			break;		case AT_ToastTable:		/* CREATE TOAST TABLE */			ATSimplePermissions(rel, false);			/* This command never recurses */			/* No command-specific prep needed */			pass = AT_PASS_MISC;			break;		case AT_ChangeOwner:	/* ALTER OWNER */			/* This command never recurses */			/* No command-specific prep needed */			pass = AT_PASS_MISC;			break;		case AT_ClusterOn:		/* CLUSTER ON */		case AT_DropCluster:	/* SET WITHOUT CLUSTER */			ATSimplePermissions(rel, false);			/* These commands never recurse */			/* No command-specific prep needed */			pass = AT_PASS_MISC;			break;		case AT_DropOids:		/* SET WITHOUT OIDS */			ATSimplePermissions(rel, false);			/* Performs own recursion */			if (rel->rd_rel->relhasoids)			{				AlterTableCmd *dropCmd = makeNode(AlterTableCmd);				dropCmd->subtype = AT_DropColumn;				dropCmd->name = pstrdup("oid");				dropCmd->behavior = cmd->behavior;				ATPrepCmd(wqueue, rel, dropCmd, recurse, false);			}			pass = AT_PASS_DROP;			break;		case AT_SetTableSpace:	/* SET TABLESPACE */			/* This command never recurses */			ATPrepSetTableSpace(tab, rel, cmd->name);			pass = AT_PASS_MISC;	/* doesn't actually matter */			break;		case AT_EnableTrig:		/* ENABLE TRIGGER variants */		case AT_EnableTrigAll:		case AT_EnableTrigUser:		case AT_DisableTrig:	/* DISABLE TRIGGER variants */		case AT_DisableTrigAll:		case AT_DisableTrigUser:			ATSimplePermissions(rel, false);			/* These commands never recurse */			/* No command-specific prep needed */			pass = AT_PASS_MISC;			break;		default:				/* oops */			elog(ERROR, "unrecognized alter table type: %d",				 (int) cmd->subtype);			pass = 0;			/* keep compiler quiet */			break;	}	/* Add the subcommand to the appropriate list for phase 2 */	tab->subcmds[pass] = lappend(tab->subcmds[pass], cmd);}/* * ATRewriteCatalogs * * Traffic cop for ALTER TABLE Phase 2 operations.	Subcommands are * dispatched in a "safe" execution order (designed to avoid unnecessary * conflicts). */static voidATRewriteCatalogs(List **wqueue){	int			pass;	ListCell   *ltab;	/*	 * We process all the tables "in parallel", one pass at a time.  This is	 * needed because we may have to propagate work from one table to another	 * (specifically, ALTER TYPE on a foreign key's PK has to dispatch the	 * re-adding of the foreign key constraint to the other table).  Work can	 * only be propagated into later passes, however.	 */	for (pass = 0; pass < AT_NUM_PASSES; pass++)	{		/* Go through each table that needs to be processed */		foreach(ltab, *wqueue)		{			AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);			List	   *subcmds = tab->subcmds[pass];			Relation	rel;			ListCell   *lcmd;			if (subcmds == NIL)				continue;			/*			 * Exclusive lock was obtained by phase 1, needn't get it again			 */			rel = relation_open(tab->relid, NoLock);			foreach(lcmd, subcmds)				ATExecCmd(tab, rel, (AlterTableCmd *) lfirst(lcmd));			/*			 * After the ALTER TYPE pass, do cleanup work (this is not done in			 * ATExecAlterColumnType since it should be done only once if			 * multiple columns of a table are altered).			 */			if (pass == AT_PASS_ALTER_TYPE)				ATPostAlterTypeCleanup(wqueue, tab);			relation_close(rel, NoLock);		}	}	/*	 * Do an implicit CREATE TOAST TABLE if we executed any subcommands that	 * might have added a column or changed column storage.	 */	foreach(ltab, *wqueue)	{		AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);		if (tab->relkind == RELKIND_RELATION &&			(tab->subcmds[AT_PASS_ADD_COL] ||			 tab->subcmds[AT_PASS_ALTER_TYPE] ||			 tab->subcmds[AT_PASS_COL_ATTRS]))			AlterTableCreateToastTable(tab->relid, true);	}}/* * ATExecCmd: dispatch a subcommand to appropriate execution routine */static voidATExecCmd(AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd){	switch (cmd->subtype)	{		case AT_AddColumn:		/* ADD COLUMN */			ATExecAddColumn(tab, rel, (ColumnDef *) cmd->def);			break;		case AT_ColumnDefault:	/* ALTER COLUMN DEFAULT */			ATExecColumnDefault(rel, cmd->name, cmd->def);			break;		case AT_DropNotNull:	/* ALTER COLUMN DROP NOT NULL */			ATExecDropNotNull(rel, cmd->name);			break;		case AT_SetNotNull:		/* ALTER COLUMN SET NOT NULL */			ATExecSetNotNull(tab, rel, cmd->name);			break;		case AT_SetStatistics:	/* ALTER COLUMN STATISTICS */			ATExecSetStatistics(rel, cmd->name, cmd->def);			break;		case AT_SetStorage:		/* ALTER COLUMN STORAGE */			ATExecSetStorage(rel, cmd->name, cmd->def);			break;		case AT_DropColumn:		/* DROP COLUMN */			ATExecDropColumn(rel, cmd->name, cmd->behavior, false, false);			break;		case AT_DropColumnRecurse:		/* DROP COLUMN with recursion */			ATExecDropColumn(rel, cmd->name, cmd->behavior, true, false);			break;		case AT_AddIndex:		/* ADD INDEX */			ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, false);			break;		case AT_ReAddIndex:		/* ADD INDEX */			ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, true);			break;		case AT_AddConstraint:	/* ADD CONSTRAINT */			ATExecAddConstraint(tab, rel, cmd->def);			break;		case AT_DropConstraint:	/* DROP CONSTRAINT */			ATExecDropConstraint(rel, cmd->name, cmd->behavior, false);			break;		case AT_DropConstraintQuietly:	/* DROP CONSTRAINT for child */			ATExecDropConstraint(rel, cmd->name, cmd->behavior, true);			break;		case AT_AlterColumnType:		/* ALTER COLUMN TYPE */			ATExecAlterColumnType(tab, rel, cmd->name, (TypeName *) cmd->def);			break;		case AT_ToastTable:		/* CREATE TOAST TABLE */			AlterTableCreateToastTable(RelationGetRelid(rel), false);			break;		case AT_ChangeOwner:	/* ALTER OWNER */			ATExecChangeOwner(RelationGetRelid(rel),							  g

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -