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

📄 tablecmds.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/*------------------------------------------------------------------------- * * tablecmds.c *	  Commands for creating and altering table structures and settings * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.174.2.2 2006/01/30 16:19:04 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/genam.h"#include "access/tuptoaster.h"#include "catalog/catalog.h"#include "catalog/dependency.h"#include "catalog/heap.h"#include "catalog/index.h"#include "catalog/indexing.h"#include "catalog/namespace.h"#include "catalog/pg_constraint.h"#include "catalog/pg_depend.h"#include "catalog/pg_inherits.h"#include "catalog/pg_namespace.h"#include "catalog/pg_opclass.h"#include "catalog/pg_trigger.h"#include "catalog/pg_type.h"#include "commands/cluster.h"#include "commands/defrem.h"#include "commands/tablecmds.h"#include "commands/tablespace.h"#include "commands/trigger.h"#include "commands/typecmds.h"#include "executor/executor.h"#include "lib/stringinfo.h"#include "miscadmin.h"#include "nodes/makefuncs.h"#include "optimizer/clauses.h"#include "optimizer/plancat.h"#include "optimizer/prep.h"#include "parser/analyze.h"#include "parser/gramparse.h"#include "parser/parser.h"#include "parser/parse_clause.h"#include "parser/parse_coerce.h"#include "parser/parse_expr.h"#include "parser/parse_oper.h"#include "parser/parse_relation.h"#include "parser/parse_type.h"#include "rewrite/rewriteHandler.h"#include "storage/smgr.h"#include "utils/acl.h"#include "utils/builtins.h"#include "utils/fmgroids.h"#include "utils/inval.h"#include "utils/lsyscache.h"#include "utils/memutils.h"#include "utils/relcache.h"#include "utils/syscache.h"/* * ON COMMIT action list */typedef struct OnCommitItem{	Oid			relid;			/* relid of relation */	OnCommitAction oncommit;	/* what to do at end of xact */	/*	 * If this entry was created during the current transaction,	 * creating_subid is the ID of the creating subxact; if created in a prior	 * transaction, creating_subid is zero.  If deleted during the current	 * transaction, deleting_subid is the ID of the deleting subxact; if no	 * deletion request is pending, deleting_subid is zero.	 */	SubTransactionId creating_subid;	SubTransactionId deleting_subid;} OnCommitItem;static List *on_commits = NIL;/* * State information for ALTER TABLE * * The pending-work queue for an ALTER TABLE is a List of AlteredTableInfo * structs, one for each table modified by the operation (the named table * plus any child tables that are affected).  We save lists of subcommands * to apply to this table (possibly modified by parse transformation steps); * these lists will be executed in Phase 2.  If a Phase 3 step is needed, * necessary information is stored in the constraints and newvals lists. * * Phase 2 is divided into multiple passes; subcommands are executed in * a pass determined by subcommand type. */#define AT_PASS_DROP			0		/* DROP (all flavors) */#define AT_PASS_ALTER_TYPE		1		/* ALTER COLUMN TYPE */#define AT_PASS_OLD_INDEX		2		/* re-add existing indexes */#define AT_PASS_OLD_CONSTR		3		/* re-add existing constraints */#define AT_PASS_COL_ATTRS		4		/* set other column attributes *//* We could support a RENAME COLUMN pass here, but not currently used */#define AT_PASS_ADD_COL			5		/* ADD COLUMN */#define AT_PASS_ADD_INDEX		6		/* ADD indexes */#define AT_PASS_ADD_CONSTR		7		/* ADD constraints, defaults */#define AT_PASS_MISC			8		/* other stuff */#define AT_NUM_PASSES			9typedef struct AlteredTableInfo{	/* Information saved before any work commences: */	Oid			relid;			/* Relation to work on */	char		relkind;		/* Its relkind */	TupleDesc	oldDesc;		/* Pre-modification tuple descriptor */	/* Information saved by Phase 1 for Phase 2: */	List	   *subcmds[AT_NUM_PASSES]; /* Lists of AlterTableCmd */	/* Information saved by Phases 1/2 for Phase 3: */	List	   *constraints;	/* List of NewConstraint */	List	   *newvals;		/* List of NewColumnValue */	Oid			newTableSpace;	/* new tablespace; 0 means no change */	/* Objects to rebuild after completing ALTER TYPE operations */	List	   *changedConstraintOids;	/* OIDs of constraints to rebuild */	List	   *changedConstraintDefs;	/* string definitions of same */	List	   *changedIndexOids;		/* OIDs of indexes to rebuild */	List	   *changedIndexDefs;		/* string definitions of same */} AlteredTableInfo;/* Struct describing one new constraint to check in Phase 3 scan */typedef struct NewConstraint{	char	   *name;			/* Constraint name, or NULL if none */	ConstrType	contype;		/* CHECK, NOT_NULL, or FOREIGN */	AttrNumber	attnum;			/* only relevant for NOT_NULL */	Oid			refrelid;		/* PK rel, if FOREIGN */	Node	   *qual;			/* Check expr or FkConstraint struct */	List	   *qualstate;		/* Execution state for CHECK */} NewConstraint;/* * Struct describing one new column value that needs to be computed during * Phase 3 copy (this could be either a new column with a non-null default, or * a column that we're changing the type of).  Columns without such an entry * are just copied from the old table during ATRewriteTable.  Note that the * expr is an expression over *old* table values. */typedef struct NewColumnValue{	AttrNumber	attnum;			/* which column */	Expr	   *expr;			/* expression to compute */	ExprState  *exprstate;		/* execution state */} NewColumnValue;static List *MergeAttributes(List *schema, List *supers, bool istemp,				List **supOids, List **supconstr, int *supOidCount);static bool change_varattnos_of_a_node(Node *node, const AttrNumber *newattno);static void StoreCatalogInheritance(Oid relationId, List *supers);static int	findAttrByName(const char *attributeName, List *schema);static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);static bool needs_toast_table(Relation rel);static void AlterIndexNamespaces(Relation classRel, Relation rel,					 Oid oldNspOid, Oid newNspOid);static void AlterSeqNamespaces(Relation classRel, Relation rel,				   Oid oldNspOid, Oid newNspOid,				   const char *newNspName);static int transformColumnNameList(Oid relId, List *colList,						int16 *attnums, Oid *atttypids);static int transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,						   List **attnamelist,						   int16 *attnums, Oid *atttypids,						   Oid *opclasses);static Oid transformFkeyCheckAttrs(Relation pkrel,						int numattrs, int16 *attnums,						Oid *opclasses);static void validateForeignKeyConstraint(FkConstraint *fkconstraint,							 Relation rel, Relation pkrel);static void createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,						 Oid constrOid);static char *fkMatchTypeToString(char match_type);static void ATController(Relation rel, List *cmds, bool recurse);static void ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,		  bool recurse, bool recursing);static void ATRewriteCatalogs(List **wqueue);static void ATExecCmd(AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd);static void ATRewriteTables(List **wqueue);static void ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap);static AlteredTableInfo *ATGetQueueEntry(List **wqueue, Relation rel);static void ATSimplePermissions(Relation rel, bool allowView);static void ATSimpleRecursion(List **wqueue, Relation rel,				  AlterTableCmd *cmd, bool recurse);static void ATOneLevelRecursion(List **wqueue, Relation rel,					AlterTableCmd *cmd);static void find_composite_type_dependencies(Oid typeOid,								 const char *origTblName);static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse,				AlterTableCmd *cmd);static void ATExecAddColumn(AlteredTableInfo *tab, Relation rel,				ColumnDef *colDef);static void add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid);static void add_column_support_dependency(Oid relid, int32 attnum,							  RangeVar *support);static void ATExecDropNotNull(Relation rel, const char *colName);static void ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,				 const char *colName);static void ATExecColumnDefault(Relation rel, const char *colName,					Node *newDefault);static void ATPrepSetStatistics(Relation rel, const char *colName,					Node *flagValue);static void ATExecSetStatistics(Relation rel, const char *colName,					Node *newValue);static void ATExecSetStorage(Relation rel, const char *colName,				 Node *newValue);static void ATExecDropColumn(Relation rel, const char *colName,				 DropBehavior behavior,				 bool recurse, bool recursing);static void ATExecAddIndex(AlteredTableInfo *tab, Relation rel,			   IndexStmt *stmt, bool is_rebuild);static void ATExecAddConstraint(AlteredTableInfo *tab, Relation rel,					Node *newConstraint);static void ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,						  FkConstraint *fkconstraint);static void ATPrepDropConstraint(List **wqueue, Relation rel,					 bool recurse, AlterTableCmd *cmd);static void ATExecDropConstraint(Relation rel, const char *constrName,					 DropBehavior behavior, bool quiet);static void ATPrepAlterColumnType(List **wqueue,					  AlteredTableInfo *tab, Relation rel,					  bool recurse, bool recursing,					  AlterTableCmd *cmd);static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,					  const char *colName, TypeName *typename);static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab);static void ATPostAlterTypeParse(char *cmd, List **wqueue);static void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing);static void change_owner_recurse_to_sequences(Oid relationOid,								  Oid newOwnerId);static void ATExecClusterOn(Relation rel, const char *indexName);static void ATExecDropCluster(Relation rel);static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel,					char *tablespacename);static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace);static void ATExecEnableDisableTrigger(Relation rel, char *trigname,						   bool enable, bool skip_system);static void copy_relation_data(Relation rel, SMgrRelation dst);static void update_ri_trigger_args(Oid relid,					   const char *oldname,					   const char *newname,					   bool fk_scan,					   bool update_relname);/* ---------------------------------------------------------------- *		DefineRelation *				Creates a new relation. * * If successful, returns the OID of the new relation. * ---------------------------------------------------------------- */OidDefineRelation(CreateStmt *stmt, char relkind){	char		relname[NAMEDATALEN];	Oid			namespaceId;	List	   *schema = stmt->tableElts;	Oid			relationId;	Oid			tablespaceId;	Relation	rel;	TupleDesc	descriptor;	List	   *inheritOids;	List	   *old_constraints;	bool		localHasOids;	int			parentOidCount;	List	   *rawDefaults;	ListCell   *listptr;	int			i;	AttrNumber	attnum;	/*	 * Truncate relname to appropriate length (probably a waste of time, as	 * parser should have done this already).	 */	StrNCpy(relname, stmt->relation->relname, NAMEDATALEN);	/*	 * Check consistency of arguments	 */	if (stmt->oncommit != ONCOMMIT_NOOP && !stmt->relation->istemp)		ereport(ERROR,				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),				 errmsg("ON COMMIT can only be used on temporary tables")));	/*	 * Look up the namespace in which we are supposed to create the relation.	 * Check we have permission to create there. Skip check if bootstrapping,	 * since permissions machinery may not be working yet.	 */	namespaceId = RangeVarGetCreationNamespace(stmt->relation);	if (!IsBootstrapProcessingMode())	{		AclResult	aclresult;		aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),										  ACL_CREATE);		if (aclresult != ACLCHECK_OK)			aclcheck_error(aclresult, ACL_KIND_NAMESPACE,						   get_namespace_name(namespaceId));	}	/*	 * Select tablespace to use.  If not specified, use default_tablespace	 * (which may in turn default to database's default).	 */	if (stmt->tablespacename)	{		tablespaceId = get_tablespace_oid(stmt->tablespacename);		if (!OidIsValid(tablespaceId))			ereport(ERROR,					(errcode(ERRCODE_UNDEFINED_OBJECT),					 errmsg("tablespace \"%s\" does not exist",							stmt->tablespacename)));	}	else	{		tablespaceId = GetDefaultTablespace();		/* note InvalidOid is OK in this case */	}	/* Check permissions except when using database's default */	if (OidIsValid(tablespaceId))	{		AclResult	aclresult;		aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(),										   ACL_CREATE);		if (aclresult != ACLCHECK_OK)			aclcheck_error(aclresult, ACL_KIND_TABLESPACE,						   get_tablespace_name(tablespaceId));	}	/*	 * Look up inheritance ancestors and generate relation schema, including	 * inherited attributes.	 */	schema = MergeAttributes(schema, stmt->inhRelations,							 stmt->relation->istemp,							 &inheritOids, &old_constraints, &parentOidCount);	/*	 * Create a relation descriptor from the relation schema and create the	 * relation.  Note that in this stage only inherited (pre-cooked) defaults	 * and constraints will be included into the new relation.	 * (BuildDescForRelation takes care of the inherited defaults, but we have	 * to copy inherited constraints here.)	 */	descriptor = BuildDescForRelation(schema);	localHasOids = interpretOidsOption(stmt->hasoids);	descriptor->tdhasoid = (localHasOids || parentOidCount > 0);	if (old_constraints != NIL)	{		ConstrCheck *check = (ConstrCheck *)		palloc0(list_length(old_constraints) * sizeof(ConstrCheck));		int			ncheck = 0;		foreach(listptr, old_constraints)		{			Constraint *cdef = (Constraint *) lfirst(listptr);			bool		dup = false;			if (cdef->contype != CONSTR_CHECK)				continue;			Assert(cdef->name != NULL);			Assert(cdef->raw_expr == NULL && cdef->cooked_expr != NULL);			/*			 * In multiple-inheritance situations, it's possible to inherit			 * the same grandparent constraint through multiple parents.			 * Hence, discard inherited constraints that match as to both name			 * and expression.	Otherwise, gripe if the names conflict.			 */			for (i = 0; i < ncheck; i++)			{				if (strcmp(check[i].ccname, cdef->name) != 0)					continue;				if (strcmp(check[i].ccbin, cdef->cooked_expr) == 0)				{					dup = true;					break;				}				ereport(ERROR,						(errcode(ERRCODE_DUPLICATE_OBJECT),						 errmsg("duplicate check constraint name \"%s\"",								cdef->name)));			}			if (!dup)			{				check[ncheck].ccname = cdef->name;				check[ncheck].ccbin = pstrdup(cdef->cooked_expr);				ncheck++;			}		}		if (ncheck > 0)		{			if (descriptor->constr == NULL)			{				descriptor->constr = (TupleConstr *) palloc(sizeof(TupleConstr));				descriptor->constr->defval = NULL;				descriptor->constr->num_defval = 0;				descriptor->constr->has_not_null = false;			}			descriptor->constr->num_check = ncheck;			descriptor->constr->check = check;		}	}	relationId = heap_create_with_catalog(relname,										  namespaceId,										  tablespaceId,										  InvalidOid,										  GetUserId(),										  descriptor,										  relkind,										  false,

⌨️ 快捷键说明

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