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

📄 typecmds.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
						 0, 0, 0);	if (!HeapTupleIsValid(tup))		elog(ERROR, "cache lookup failed for type %u", typeOid);	simple_heap_delete(relation, &tup->t_self);	ReleaseSysCache(tup);	heap_close(relation, RowExclusiveLock);}/* * DefineDomain *		Registers a new domain. */voidDefineDomain(CreateDomainStmt *stmt){	char	   *domainName;	Oid			domainNamespace;	AclResult	aclresult;	int16		internalLength;	Oid			inputProcedure;	Oid			outputProcedure;	Oid			receiveProcedure;	Oid			sendProcedure;	Oid			analyzeProcedure;	bool		byValue;	char		delimiter;	char		alignment;	char		storage;	char		typtype;	Datum		datum;	bool		isnull;	Node	   *defaultExpr = NULL;	char	   *defaultValue = NULL;	char	   *defaultValueBin = NULL;	bool		typNotNull = false;	bool		nullDefined = false;	Oid			basetypelem;	int32		typNDims = list_length(stmt->typename->arrayBounds);	HeapTuple	typeTup;	List	   *schema = stmt->constraints;	ListCell   *listptr;	Oid			basetypeoid;	Oid			domainoid;	Form_pg_type baseType;	/* Convert list of names to a name and namespace */	domainNamespace = QualifiedNameGetCreationNamespace(stmt->domainname,														&domainName);	/* Check we have creation rights in target namespace */	aclresult = pg_namespace_aclcheck(domainNamespace, GetUserId(),									  ACL_CREATE);	if (aclresult != ACLCHECK_OK)		aclcheck_error(aclresult, ACL_KIND_NAMESPACE,					   get_namespace_name(domainNamespace));	/*	 * Domainnames, unlike typenames don't need to account for the '_' prefix.	 * So they can be one character longer.  (This test is presently useless	 * since the parser will have truncated the name to fit.  But leave it	 * here since we may someday support arrays of domains, in which case	 * we'll be back to needing to enforce NAMEDATALEN-2.)	 */	if (strlen(domainName) > (NAMEDATALEN - 1))		ereport(ERROR,				(errcode(ERRCODE_INVALID_NAME),				 errmsg("domain names must be %d characters or less",						NAMEDATALEN - 1)));	/*	 * Look up the base type.	 */	typeTup = typenameType(stmt->typename);	baseType = (Form_pg_type) GETSTRUCT(typeTup);	basetypeoid = HeapTupleGetOid(typeTup);	/*	 * Base type must be a plain base type.  Domains over pseudo types would	 * create a security hole.	Domains of domains might be made to work in	 * the future, but not today.  Ditto for domains over complex types.	 */	typtype = baseType->typtype;	if (typtype != 'b')		ereport(ERROR,				(errcode(ERRCODE_DATATYPE_MISMATCH),				 errmsg("\"%s\" is not a valid base type for a domain",						TypeNameToString(stmt->typename))));	/* passed by value */	byValue = baseType->typbyval;	/* Required Alignment */	alignment = baseType->typalign;	/* TOAST Strategy */	storage = baseType->typstorage;	/* Storage Length */	internalLength = baseType->typlen;	/* Array element Delimiter */	delimiter = baseType->typdelim;	/* I/O Functions */	inputProcedure = baseType->typinput;	outputProcedure = baseType->typoutput;	receiveProcedure = baseType->typreceive;	sendProcedure = baseType->typsend;	/* Analysis function */	analyzeProcedure = baseType->typanalyze;	/* Inherited default value */	datum = SysCacheGetAttr(TYPEOID, typeTup,							Anum_pg_type_typdefault, &isnull);	if (!isnull)		defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum));	/* Inherited default binary value */	datum = SysCacheGetAttr(TYPEOID, typeTup,							Anum_pg_type_typdefaultbin, &isnull);	if (!isnull)		defaultValueBin = DatumGetCString(DirectFunctionCall1(textout, datum));	/*	 * Pull out the typelem name of the parent OID.	 *	 * This is what enables us to make a domain of an array	 */	basetypelem = baseType->typelem;	/*	 * Run through constraints manually to avoid the additional processing	 * conducted by DefineRelation() and friends.	 */	foreach(listptr, schema)	{		Node	   *newConstraint = lfirst(listptr);		Constraint *constr;		ParseState *pstate;		/* Check for unsupported constraint types */		if (IsA(newConstraint, FkConstraint))			ereport(ERROR,					(errcode(ERRCODE_SYNTAX_ERROR),				errmsg("foreign key constraints not possible for domains")));		/* otherwise it should be a plain Constraint */		if (!IsA(newConstraint, Constraint))			elog(ERROR, "unrecognized node type: %d",				 (int) nodeTag(newConstraint));		constr = (Constraint *) newConstraint;		switch (constr->contype)		{			case CONSTR_DEFAULT:				/*				 * The inherited default value may be overridden by the user				 * with the DEFAULT <expr> statement.				 */				if (defaultExpr)					ereport(ERROR,							(errcode(ERRCODE_SYNTAX_ERROR),							 errmsg("multiple default expressions")));				/* Create a dummy ParseState for transformExpr */				pstate = make_parsestate(NULL);				/*				 * Cook the constr->raw_expr into an expression. Note: Name is				 * strictly for error message				 */				defaultExpr = cookDefault(pstate, constr->raw_expr,										  basetypeoid,										  stmt->typename->typmod,										  domainName);				/*				 * Expression must be stored as a nodeToString result, but we				 * also require a valid textual representation (mainly to make				 * life easier for pg_dump).				 */				defaultValue = deparse_expression(defaultExpr,											  deparse_context_for(domainName,																  InvalidOid),												  false, false);				defaultValueBin = nodeToString(defaultExpr);				break;			case CONSTR_NOTNULL:				if (nullDefined && !typNotNull)					ereport(ERROR,							(errcode(ERRCODE_SYNTAX_ERROR),						   errmsg("conflicting NULL/NOT NULL constraints")));				typNotNull = true;				nullDefined = true;				break;			case CONSTR_NULL:				if (nullDefined && typNotNull)					ereport(ERROR,							(errcode(ERRCODE_SYNTAX_ERROR),						   errmsg("conflicting NULL/NOT NULL constraints")));				typNotNull = false;				nullDefined = true;				break;			case CONSTR_CHECK:				/*				 * Check constraints are handled after domain creation, as				 * they require the Oid of the domain				 */				break;				/*				 * All else are error cases				 */			case CONSTR_UNIQUE:				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),					 errmsg("unique constraints not possible for domains")));				break;			case CONSTR_PRIMARY:				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),				errmsg("primary key constraints not possible for domains")));				break;			case CONSTR_ATTR_DEFERRABLE:			case CONSTR_ATTR_NOT_DEFERRABLE:			case CONSTR_ATTR_DEFERRED:			case CONSTR_ATTR_IMMEDIATE:				ereport(ERROR,						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),						 errmsg("specifying constraint deferrability not supported for domains")));				break;			default:				elog(ERROR, "unrecognized constraint subtype: %d",					 (int) constr->contype);				break;		}	}	/*	 * Have TypeCreate do all the real work.	 */	domainoid =		TypeCreate(domainName,	/* type name */				   domainNamespace,		/* namespace */				   InvalidOid,	/* relation oid (n/a here) */				   0,			/* relation kind (ditto) */				   internalLength,		/* internal size */				   'd',			/* type-type (domain type) */				   delimiter,	/* array element delimiter */				   inputProcedure,		/* input procedure */				   outputProcedure,		/* output procedure */				   receiveProcedure,	/* receive procedure */				   sendProcedure,		/* send procedure */				   analyzeProcedure,	/* analyze procedure */				   basetypelem, /* element type ID */				   basetypeoid, /* base type ID */				   defaultValue,	/* default type value (text) */				   defaultValueBin,		/* default type value (binary) */				   byValue,		/* passed by value */				   alignment,	/* required alignment */				   storage,		/* TOAST strategy */				   stmt->typename->typmod,		/* typeMod value */				   typNDims,	/* Array dimensions for base type */				   typNotNull); /* Type NOT NULL */	/*	 * Process constraints which refer to the domain ID returned by TypeCreate	 */	foreach(listptr, schema)	{		Constraint *constr = lfirst(listptr);		/* it must be a Constraint, per check above */		switch (constr->contype)		{			case CONSTR_CHECK:				domainAddConstraint(domainoid, domainNamespace,									basetypeoid, stmt->typename->typmod,									constr, domainName);				break;				/* Other constraint types were fully processed above */			default:				break;		}		/* CCI so we can detect duplicate constraint names */		CommandCounterIncrement();	}	/*	 * Now we can clean up.	 */	ReleaseSysCache(typeTup);}/* *	RemoveDomain *		Removes a domain. * * This is identical to RemoveType except we insist it be a domain. */voidRemoveDomain(List *names, DropBehavior behavior){	TypeName   *typename;	Oid			typeoid;	HeapTuple	tup;	char		typtype;	ObjectAddress object;	/* Make a TypeName so we can use standard type lookup machinery */	typename = makeNode(TypeName);	typename->names = names;	typename->typmod = -1;	typename->arrayBounds = NIL;	/* Use LookupTypeName here so that shell types can be removed. */	typeoid = LookupTypeName(typename);	if (!OidIsValid(typeoid))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("type \"%s\" does not exist",						TypeNameToString(typename))));	tup = SearchSysCache(TYPEOID,						 ObjectIdGetDatum(typeoid),						 0, 0, 0);	if (!HeapTupleIsValid(tup))		elog(ERROR, "cache lookup failed for type %u", typeoid);	/* Permission check: must own type or its namespace */	if (!pg_type_ownercheck(typeoid, GetUserId()) &&	  !pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace,							   GetUserId()))		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,					   TypeNameToString(typename));	/* Check that this is actually a domain */	typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype;	if (typtype != 'd')		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is not a domain",						TypeNameToString(typename))));	ReleaseSysCache(tup);	/*	 * Do the deletion	 */	object.classId = TypeRelationId;	object.objectId = typeoid;	object.objectSubId = 0;	performDeletion(&object, behavior);}/* * Find suitable I/O functions for a type. * * typeOid is the type's OID (which will already exist, if only as a shell * type). */static OidfindTypeInputFunction(List *procname, Oid typeOid){	Oid			argList[3];	Oid			procOid;	/*	 * Input functions can take a single argument of type CSTRING, or three	 * arguments (string, typioparam OID, typmod).	 *	 * For backwards compatibility we allow OPAQUE in place of CSTRING; if we	 * see this, we issue a warning and fix up the pg_proc entry.	 */	argList[0] = CSTRINGOID;	procOid = LookupFuncName(procname, 1, argList, true);	if (OidIsValid(procOid))		return procOid;	argList[1] = OIDOID;	argList[2] = INT4OID;	procOid = LookupFuncName(procname, 3, argList, true);	if (OidIsValid(procOid))		return procOid;	/* No luck, try it with OPAQUE */	argList[0] = OPAQUEOID;	procOid = LookupFuncName(procname, 1, argList, true);	if (!OidIsValid(procOid))	{		argList[1] = OIDOID;		argList[2] = INT4OID;		procOid = LookupFuncName(procname, 3, argList, true);	}	if (OidIsValid(procOid))	{		/* Found, but must complain and fix the pg_proc entry */		ereport(WARNING,				(errmsg("changing argument type of function %s from \"opaque\" to \"cstring\"",						NameListToString(procname))));		SetFunctionArgType(procOid, 0, CSTRINGOID);		/*		 * Need CommandCounterIncrement since DefineType will likely try to		 * alter the pg_proc tuple again.		 */		CommandCounterIncrement();		return procOid;	}	/* Use CSTRING (preferred) in the error message */	argList[0] = CSTRINGOID;	ereport(ERROR,			(errcode(ERRCODE_UNDEFINED_FUNCTION),			 errmsg("function %s does not exist",					func_signature_string(procname, 1, argList))));	return InvalidOid;			/* keep compiler quiet */}static OidfindTypeOutputFunction(List *procname, Oid typeOid){	Oid			argList[1];	Oid			procOid;	/*	 * Output functions can take a single argument of the type.

⌨️ 快捷键说明

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