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

📄 typecmds.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * Since VARNOs aren't allowed in domain constraints, relation context	 * isn't required as anything other than a shell.	 */	ccsrc = deparse_expression(expr,							   deparse_context_for(domainName,												   InvalidOid),							   false, false);	/*	 * Store the constraint in pg_constraint	 */	CreateConstraintEntry(constr->name, /* Constraint Name */						  domainNamespace,		/* namespace */						  CONSTRAINT_CHECK,		/* Constraint Type */						  false,	/* Is Deferrable */						  false,	/* Is Deferred */						  InvalidOid,	/* not a relation constraint */						  NULL,						  0,						  domainOid,	/* domain constraint */						  InvalidOid,	/* Foreign key fields */						  NULL,						  0,						  ' ',						  ' ',						  ' ',						  InvalidOid,						  expr, /* Tree form check constraint */						  ccbin,	/* Binary form check constraint */						  ccsrc);		/* Source form check constraint */	/*	 * Return the compiled constraint expression so the calling routine can	 * perform any additional required tests.	 */	return ccbin;}/* * GetDomainConstraints - get a list of the current constraints of domain * * Returns a possibly-empty list of DomainConstraintState nodes. * * This is called by the executor during plan startup for a CoerceToDomain * expression node.  The given constraints will be checked for each value * passed through the node. * * We allow this to be called for non-domain types, in which case the result * is always NIL. */List *GetDomainConstraints(Oid typeOid){	List	   *result = NIL;	bool		notNull = false;	Relation	conRel;	conRel = heap_open(ConstraintRelationId, AccessShareLock);	for (;;)	{		HeapTuple	tup;		HeapTuple	conTup;		Form_pg_type typTup;		ScanKeyData key[1];		SysScanDesc scan;		tup = SearchSysCache(TYPEOID,							 ObjectIdGetDatum(typeOid),							 0, 0, 0);		if (!HeapTupleIsValid(tup))			elog(ERROR, "cache lookup failed for type %u", typeOid);		typTup = (Form_pg_type) GETSTRUCT(tup);		if (typTup->typtype != 'd')		{			/* Not a domain, so done */			ReleaseSysCache(tup);			break;		}		/* Test for NOT NULL Constraint */		if (typTup->typnotnull)			notNull = true;		/* Look for CHECK Constraints on this domain */		ScanKeyInit(&key[0],					Anum_pg_constraint_contypid,					BTEqualStrategyNumber, F_OIDEQ,					ObjectIdGetDatum(typeOid));		scan = systable_beginscan(conRel, ConstraintTypidIndexId, true,								  SnapshotNow, 1, key);		while (HeapTupleIsValid(conTup = systable_getnext(scan)))		{			Form_pg_constraint c = (Form_pg_constraint) GETSTRUCT(conTup);			Datum		val;			bool		isNull;			Expr	   *check_expr;			DomainConstraintState *r;			/* Ignore non-CHECK constraints (presently, shouldn't be any) */			if (c->contype != CONSTRAINT_CHECK)				continue;			/*			 * Not expecting conbin to be NULL, but we'll test for it anyway			 */			val = fastgetattr(conTup, Anum_pg_constraint_conbin,							  conRel->rd_att, &isNull);			if (isNull)				elog(ERROR, "domain \"%s\" constraint \"%s\" has NULL conbin",					 NameStr(typTup->typname), NameStr(c->conname));			check_expr = (Expr *)				stringToNode(DatumGetCString(DirectFunctionCall1(textout,																 val)));			/* ExecInitExpr assumes we already fixed opfuncids */			fix_opfuncids((Node *) check_expr);			r = makeNode(DomainConstraintState);			r->constrainttype = DOM_CONSTRAINT_CHECK;			r->name = pstrdup(NameStr(c->conname));			r->check_expr = ExecInitExpr(check_expr, NULL);			/*			 * use lcons() here because constraints of lower domains should be			 * applied earlier.			 */			result = lcons(r, result);		}		systable_endscan(scan);		/* loop to next domain in stack */		typeOid = typTup->typbasetype;		ReleaseSysCache(tup);	}	heap_close(conRel, AccessShareLock);	/*	 * Only need to add one NOT NULL check regardless of how many domains in	 * the stack request it.	 */	if (notNull)	{		DomainConstraintState *r = makeNode(DomainConstraintState);		r->constrainttype = DOM_CONSTRAINT_NOTNULL;		r->name = pstrdup("NOT NULL");		r->check_expr = NULL;		/* lcons to apply the nullness check FIRST */		result = lcons(r, result);	}	return result;}/* * Change the owner of a type. */voidAlterTypeOwner(List *names, Oid newOwnerId){	TypeName   *typename;	Oid			typeOid;	Relation	rel;	HeapTuple	tup;	Form_pg_type typTup;	AclResult	aclresult;	/* Make a TypeName so we can use standard type lookup machinery */	typename = makeNode(TypeName);	typename->names = names;	typename->typmod = -1;	typename->arrayBounds = NIL;	/* Lock the type table */	rel = heap_open(TypeRelationId, RowExclusiveLock);	/* Use LookupTypeName here so that shell types can be processed (why?) */	typeOid = LookupTypeName(typename);	if (!OidIsValid(typeOid))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("type \"%s\" does not exist",						TypeNameToString(typename))));	tup = SearchSysCacheCopy(TYPEOID,							 ObjectIdGetDatum(typeOid),							 0, 0, 0);	if (!HeapTupleIsValid(tup))		elog(ERROR, "cache lookup failed for type %u", typeOid);	typTup = (Form_pg_type) GETSTRUCT(tup);	/*	 * If it's a composite type, we need to check that it really is a	 * free-standing composite type, and not a table's underlying type. We	 * want people to use ALTER TABLE not ALTER TYPE for that case.	 */	if (typTup->typtype == 'c' &&		get_rel_relkind(typTup->typrelid) != RELKIND_COMPOSITE_TYPE)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is a table's row type",						TypeNameToString(typename))));	/*	 * If the new owner is the same as the existing owner, consider the	 * command to have succeeded.  This is for dump restoration purposes.	 */	if (typTup->typowner != newOwnerId)	{		/* Superusers can always do it */		if (!superuser())		{			/* Otherwise, must be owner of the existing object */			if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId()))				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,							   TypeNameToString(typename));			/* Must be able to become new owner */			check_is_member_of_role(GetUserId(), newOwnerId);			/* New owner must have CREATE privilege on namespace */			aclresult = pg_namespace_aclcheck(typTup->typnamespace,											  newOwnerId,											  ACL_CREATE);			if (aclresult != ACLCHECK_OK)				aclcheck_error(aclresult, ACL_KIND_NAMESPACE,							   get_namespace_name(typTup->typnamespace));		}		/*		 * Modify the owner --- okay to scribble on typTup because it's a copy		 */		typTup->typowner = newOwnerId;		simple_heap_update(rel, &tup->t_self, tup);		CatalogUpdateIndexes(rel, tup);		/* Update owner dependency reference */		changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);	}	/* Clean up */	heap_close(rel, RowExclusiveLock);}/* * AlterTypeOwnerInternal - change type owner unconditionally * * This is currently only used to propagate ALTER TABLE OWNER to the * table's rowtype.  It assumes the caller has done all needed checks. */voidAlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId){	Relation	rel;	HeapTuple	tup;	Form_pg_type typTup;	rel = heap_open(TypeRelationId, RowExclusiveLock);	tup = SearchSysCacheCopy(TYPEOID,							 ObjectIdGetDatum(typeOid),							 0, 0, 0);	if (!HeapTupleIsValid(tup))		elog(ERROR, "cache lookup failed for type %u", typeOid);	typTup = (Form_pg_type) GETSTRUCT(tup);	/*	 * Modify the owner --- okay to scribble on typTup because it's a copy	 */	typTup->typowner = newOwnerId;	simple_heap_update(rel, &tup->t_self, tup);	CatalogUpdateIndexes(rel, tup);	/* Update owner dependency reference */	changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);	/* Clean up */	heap_close(rel, RowExclusiveLock);}/* * Execute ALTER TYPE SET SCHEMA */voidAlterTypeNamespace(List *names, const char *newschema){	TypeName   *typename;	Oid			typeOid;	Oid			nspOid;	/* get type OID */	typename = makeNode(TypeName);	typename->names = names;	typename->typmod = -1;	typename->arrayBounds = NIL;	typeOid = LookupTypeName(typename);	if (!OidIsValid(typeOid))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("type \"%s\" does not exist",						TypeNameToString(typename))));	/* check permissions on type */	if (!pg_type_ownercheck(typeOid, GetUserId()))		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,					   format_type_be(typeOid));	/* get schema OID and check its permissions */	nspOid = LookupCreationNamespace(newschema);	/* and do the work */	AlterTypeNamespaceInternal(typeOid, nspOid, true);}/* * Move specified type to new namespace. * * Caller must have already checked privileges. * * If errorOnTableType is TRUE, the function errors out if the type is * a table type.  ALTER TABLE has to be used to move a table to a new * namespace. */voidAlterTypeNamespaceInternal(Oid typeOid, Oid nspOid,						   bool errorOnTableType){	Relation	rel;	HeapTuple	tup;	Form_pg_type typform;	Oid			oldNspOid;	bool		isCompositeType;	rel = heap_open(TypeRelationId, RowExclusiveLock);	tup = SearchSysCacheCopy(TYPEOID,							 ObjectIdGetDatum(typeOid),							 0, 0, 0);	if (!HeapTupleIsValid(tup))		elog(ERROR, "cache lookup failed for type %u", typeOid);	typform = (Form_pg_type) GETSTRUCT(tup);	oldNspOid = typform->typnamespace;	if (oldNspOid == nspOid)		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_OBJECT),				 errmsg("type %s is already in schema \"%s\"",						format_type_be(typeOid),						get_namespace_name(nspOid))));	/* disallow renaming into or out of temp schemas */	if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),			errmsg("cannot move objects into or out of temporary schemas")));	/* same for TOAST schema */	if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("cannot move objects into or out of TOAST schema")));	/* check for duplicate name (more friendly than unique-index failure) */	if (SearchSysCacheExists(TYPENAMENSP,							 CStringGetDatum(NameStr(typform->typname)),							 ObjectIdGetDatum(nspOid),							 0, 0))		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_OBJECT),				 errmsg("type \"%s\" already exists in schema \"%s\"",						NameStr(typform->typname),						get_namespace_name(nspOid))));	/* Detect whether type is a composite type (but not a table rowtype) */	isCompositeType =		(typform->typtype == 'c' &&		 get_rel_relkind(typform->typrelid) == RELKIND_COMPOSITE_TYPE);	/* Enforce not-table-type if requested */	if (typform->typtype == 'c' && !isCompositeType && errorOnTableType)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("%s is a table's row type",						format_type_be(typeOid)),				 errhint("Use ALTER TABLE SET SCHEMA instead.")));	/* OK, modify the pg_type row */	/* tup is a copy, so we can scribble directly on it */	typform->typnamespace = nspOid;	simple_heap_update(rel, &tup->t_self, tup);	CatalogUpdateIndexes(rel, tup);	/*	 * Composite types have pg_class entries.	 *	 * We need to modify the pg_class tuple as well to reflect the change of	 * schema.	 */	if (isCompositeType)	{		Relation	classRel;		classRel = heap_open(RelationRelationId, RowExclusiveLock);		/*		 * The dependency on the schema is listed under the pg_class entry, so		 * tell AlterRelationNamespaceInternal to fix it.		 */		AlterRelationNamespaceInternal(classRel, typform->typrelid,									   oldNspOid, nspOid,									   true);		heap_close(classRel, RowExclusiveLock);		/*		 * Check for constraints associated with the composite type (we don't		 * currently support this, but probably will someday).		 */		AlterConstraintNamespaces(typform->typrelid, oldNspOid,								  nspOid, false);	}	else	{		/* If it's a domain, it might have constraints */		if (typform->typtype == 'd')			AlterConstraintNamespaces(typeOid, oldNspOid, nspOid, true);		/*		 * Update dependency on schema, if any --- a table rowtype has not got		 * one.		 */		if (typform->typtype != 'c')			if (changeDependencyFor(TypeRelationId, typeOid,								NamespaceRelationId, oldNspOid, nspOid) != 1)				elog(ERROR, "failed to change schema dependency for type %s",					 format_type_be(typeOid));	}	heap_freetuple(tup);	heap_close(rel, RowExclusiveLock);}

⌨️ 快捷键说明

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