analyze.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,258 行 · 第 1/5 页

C
2,258
字号
	/*	 * Output results.	 */	q = makeNode(Query);	q->commandType = CMD_UTILITY;	q->utilityStmt = (Node *) stmt;	stmt->tableElts = cxt.columns;	stmt->constraints = cxt.ckconstraints;	*extras_before = nconc(*extras_before, cxt.blist);	*extras_after = nconc(cxt.alist, *extras_after);	return q;}static voidtransformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,						  ColumnDef *column){	bool		is_serial;	bool		saw_nullable;	Constraint *constraint;	List	   *clist;	cxt->columns = lappend(cxt->columns, column);	/* Check for SERIAL pseudo-types */	is_serial = false;	if (length(column->typename->names) == 1)	{		char	   *typname = strVal(lfirst(column->typename->names));		if (strcmp(typname, "serial") == 0 ||			strcmp(typname, "serial4") == 0)		{			is_serial = true;			column->typename->names = NIL;			column->typename->typeid = INT4OID;		}		else if (strcmp(typname, "bigserial") == 0 ||				 strcmp(typname, "serial8") == 0)		{			is_serial = true;			column->typename->names = NIL;			column->typename->typeid = INT8OID;		}	}	/* Do necessary work on the column type declaration */	transformColumnType(pstate, column);	/* Special actions for SERIAL pseudo-types */	if (is_serial)	{		char	   *sname;		char	   *snamespace;		char	   *qstring;		A_Const    *snamenode;		FuncCall   *funccallnode;		CreateSeqStmt *seqstmt;		/*		 * Determine name and namespace to use for the sequence.		 */		sname = makeObjectName(cxt->relation->relname, column->colname, "seq");		snamespace = get_namespace_name(RangeVarGetCreationNamespace(cxt->relation));		ereport(NOTICE,				(errmsg("%s will create implicit sequence \"%s\" for \"serial\" column \"%s.%s\"",						cxt->stmtType, sname,						cxt->relation->relname, column->colname)));		/*		 * Build a CREATE SEQUENCE command to create the sequence object,		 * and add it to the list of things to be done before this		 * CREATE/ALTER TABLE.		 */		seqstmt = makeNode(CreateSeqStmt);		seqstmt->sequence = makeRangeVar(snamespace, sname);		seqstmt->options = NIL;		cxt->blist = lappend(cxt->blist, seqstmt);		/*		 * Mark the ColumnDef so that during execution, an appropriate		 * dependency will be added from the sequence to the column.		 */		column->support = makeRangeVar(snamespace, sname);		/*		 * Create appropriate constraints for SERIAL.  We do this in full,		 * rather than shortcutting, so that we will detect any		 * conflicting constraints the user wrote (like a different		 * DEFAULT).		 *		 * Create an expression tree representing the function call		 * nextval('"sequencename"')		 */		qstring = quote_qualified_identifier(snamespace, sname);		snamenode = makeNode(A_Const);		snamenode->val.type = T_String;		snamenode->val.val.str = qstring;		funccallnode = makeNode(FuncCall);		funccallnode->funcname = SystemFuncName("nextval");		funccallnode->args = makeList1(snamenode);		funccallnode->agg_star = false;		funccallnode->agg_distinct = false;		constraint = makeNode(Constraint);		constraint->contype = CONSTR_DEFAULT;		constraint->name = sname;		constraint->raw_expr = (Node *) funccallnode;		constraint->cooked_expr = NULL;		constraint->keys = NIL;		column->constraints = lappend(column->constraints, constraint);		constraint = makeNode(Constraint);		constraint->contype = CONSTR_NOTNULL;		column->constraints = lappend(column->constraints, constraint);	}	/* Process column constraints, if any... */	transformConstraintAttrs(column->constraints);	saw_nullable = false;	foreach(clist, column->constraints)	{		constraint = lfirst(clist);		/*		 * If this column constraint is a FOREIGN KEY constraint, then we		 * fill in the current attribute's name and throw it into the list		 * of FK constraints to be processed later.		 */		if (IsA(constraint, FkConstraint))		{			FkConstraint *fkconstraint = (FkConstraint *) constraint;			fkconstraint->fk_attrs = makeList1(makeString(column->colname));			cxt->fkconstraints = lappend(cxt->fkconstraints, fkconstraint);			continue;		}		Assert(IsA(constraint, Constraint));		switch (constraint->contype)		{			case CONSTR_NULL:				if (saw_nullable && column->is_not_null)					ereport(ERROR,							(errcode(ERRCODE_SYNTAX_ERROR),							 errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",									column->colname, cxt->relation->relname)));				column->is_not_null = FALSE;				saw_nullable = true;				break;			case CONSTR_NOTNULL:				if (saw_nullable && !column->is_not_null)					ereport(ERROR,							(errcode(ERRCODE_SYNTAX_ERROR),							 errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",									column->colname, cxt->relation->relname)));				column->is_not_null = TRUE;				saw_nullable = true;				break;			case CONSTR_DEFAULT:				if (column->raw_default != NULL)					ereport(ERROR,							(errcode(ERRCODE_SYNTAX_ERROR),							 errmsg("multiple default values specified for column \"%s\" of table \"%s\"",									column->colname, cxt->relation->relname)));				column->raw_default = constraint->raw_expr;				Assert(constraint->cooked_expr == NULL);				break;			case CONSTR_PRIMARY:				if (constraint->name == NULL)					constraint->name = makeObjectName(cxt->relation->relname,													  NULL,													  "pkey");				if (constraint->keys == NIL)					constraint->keys = makeList1(makeString(column->colname));				cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);				break;			case CONSTR_UNIQUE:				if (constraint->name == NULL)					constraint->name = makeObjectName(cxt->relation->relname,													  column->colname,													  "key");				if (constraint->keys == NIL)					constraint->keys = makeList1(makeString(column->colname));				cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);				break;			case CONSTR_CHECK:				if (constraint->name == NULL)					constraint->name = makeObjectName(cxt->relation->relname,													  column->colname,													  NULL);				cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);				break;			case CONSTR_ATTR_DEFERRABLE:			case CONSTR_ATTR_NOT_DEFERRABLE:			case CONSTR_ATTR_DEFERRED:			case CONSTR_ATTR_IMMEDIATE:				/* transformConstraintAttrs took care of these */				break;			default:				elog(ERROR, "unrecognized constraint type: %d",					 constraint->contype);				break;		}	}}static voidtransformTableConstraint(ParseState *pstate, CreateStmtContext *cxt,						 Constraint *constraint){	switch (constraint->contype)	{		case CONSTR_PRIMARY:			if (constraint->name == NULL)				constraint->name = makeObjectName(cxt->relation->relname,												  NULL,												  "pkey");			cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);			break;		case CONSTR_UNIQUE:			cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);			break;		case CONSTR_CHECK:			cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);			break;		case CONSTR_NULL:		case CONSTR_NOTNULL:		case CONSTR_DEFAULT:		case CONSTR_ATTR_DEFERRABLE:		case CONSTR_ATTR_NOT_DEFERRABLE:		case CONSTR_ATTR_DEFERRED:		case CONSTR_ATTR_IMMEDIATE:			elog(ERROR, "invalid context for constraint type %d",				 constraint->contype);			break;		default:			elog(ERROR, "unrecognized constraint type: %d",				 constraint->contype);			break;	}}/* * transformInhRelation * * Change the LIKE <subtable> portion of a CREATE TABLE statement into the * column definitions which recreate the user defined column portions of <subtable>. */static voidtransformInhRelation(ParseState *pstate, CreateStmtContext *cxt,					 InhRelation *inhRelation){	AttrNumber	parent_attno;	Relation	relation;	TupleDesc	tupleDesc;	TupleConstr *constr;	AclResult	aclresult;	relation = heap_openrv(inhRelation->relation, AccessShareLock);	if (relation->rd_rel->relkind != RELKIND_RELATION)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("inherited relation \"%s\" is not a table",						inhRelation->relation->relname)));	/*	 * Check for SELECT privilages	 */	aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(),								  ACL_SELECT);	if (aclresult != ACLCHECK_OK)		aclcheck_error(aclresult, ACL_KIND_CLASS,					   RelationGetRelationName(relation));	tupleDesc = RelationGetDescr(relation);	constr = tupleDesc->constr;	/*	 * Insert the inherited attributes into the cxt for the new table	 * definition.	 */	for (parent_attno = 1; parent_attno <= tupleDesc->natts;		 parent_attno++)	{		Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];		char	   *attributeName = NameStr(attribute->attname);		ColumnDef  *def;		TypeName   *typename;		/*		 * Ignore dropped columns in the parent.		 */		if (attribute->attisdropped)			continue;		/*		 * Create a new inherited column.		 *		 * For constraints, ONLY the NOT NULL constraint is inherited by the		 * new column definition per SQL99.		 */		def = makeNode(ColumnDef);		def->colname = pstrdup(attributeName);		typename = makeNode(TypeName);		typename->typeid = attribute->atttypid;		typename->typmod = attribute->atttypmod;		def->typename = typename;		def->inhcount = 0;		def->is_local = false;		def->is_not_null = attribute->attnotnull;		def->raw_default = NULL;		def->cooked_default = NULL;		def->constraints = NIL;		def->support = NULL;		/*		 * Add to column list		 */		cxt->columns = lappend(cxt->columns, def);		/*		 * Copy default if any, and the default has been requested		 */		if (attribute->atthasdef && inhRelation->including_defaults)		{			char	   *this_default = NULL;			AttrDefault *attrdef;			int			i;			/* Find default in constraint structure */			Assert(constr != NULL);			attrdef = constr->defval;			for (i = 0; i < constr->num_defval; i++)			{				if (attrdef[i].adnum == parent_attno)				{					this_default = attrdef[i].adbin;					break;				}			}			Assert(this_default != NULL);			/*			 * If default expr could contain any vars, we'd need to fix			 * 'em, but it can't; so default is ready to apply to child.			 */			def->cooked_default = pstrdup(this_default);		}	}	/*	 * Close the parent rel, but keep our AccessShareLock on it until xact	 * commit.	That will prevent someone else from deleting or ALTERing	 * the parent before the child is committed.	 */	heap_close(relation, NoLock);}static voidtransformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt){	List	   *listptr;	List	   *keys;	IndexStmt  *index;	IndexElem  *iparam;	ColumnDef  *column;	List	   *columns;	List	   *indexlist = NIL;	/*	 * Run through the constraints that need to generate an index. For	 * PRIMARY KEY, mark each column as NOT NULL and create an index. For	 * UNIQUE, create an index as for PRIMARY KEY, but do not insist on	 * NOT NULL.	 */	foreach(listptr, cxt->ixconstraints)	{		Constraint *constraint = lfirst(listptr);		Assert(IsA(constraint, Constraint));		Assert((constraint->contype == CONSTR_PRIMARY)			   || (constraint->contype == CONSTR_UNIQUE));		index = makeNode(IndexStmt);		index->unique = true;		index->primary = (constraint->contype == CONSTR_PRIMARY);		if (index->primary)		{			/* In ALTER TABLE case, a primary index might already exist */			if (cxt->pkey != NULL ||				(OidIsValid(cxt->relOid) &&				 relationHasPrimaryKey(cxt->relOid)))				ereport(ERROR,						(errcode(ERRCODE_INVALID_TABLE_DEFINITION),						 errmsg("multiple primary keys for table \"%s\" are not allowed",								cxt->relation->relname)));			cxt->pkey = index;		}		index->isconstraint = true;		if (constraint->name != NULL)			index->idxname = pstrdup(constraint->name);		else if (constraint->contype == CONSTR_PRIMARY)			index->idxname = makeObjectName(cxt->relation->relname, NULL, "pkey");		else			index->idxname = NULL;		/* will set it later */		index->relation = cxt->relation;		index->accessMethod = DEFAULT_INDEX_TYPE;		index->indexParams = NIL;		index->whereClause = NULL;		/*		 * Make sure referenced keys exist.  If we are making a PRIMARY		 * KEY index, also make sure they are NOT NULL, if possible.		 * (Although we could leave it to DefineIndex to mark the columns		 * NOT NULL, it's more efficient to get it right the first time.)		 */		foreach(keys, constraint->keys)		{			char	   *key = strVal(lfirst(keys));			bool		found = false;			column = NULL;			foreach(columns, cxt->columns)			{				column = lfirst(columns);				Assert(IsA(column, ColumnDef));				if (strcmp(column->colname, key) == 0)

⌨️ 快捷键说明

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