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

📄 functioncmds.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	simple_heap_update(rel, &tup->t_self, tup);	CatalogUpdateIndexes(rel, tup);	heap_close(rel, NoLock);	heap_freetuple(tup);}/* * SetFunctionReturnType - change declared return type of a function * * This is presently only used for adjusting legacy functions that return * OPAQUE to return whatever we find their correct definition should be. * The caller should emit a suitable warning explaining what we did. */voidSetFunctionReturnType(Oid funcOid, Oid newRetType){	Relation	pg_proc_rel;	HeapTuple	tup;	Form_pg_proc procForm;	pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);	tup = SearchSysCacheCopy(PROCOID,							 ObjectIdGetDatum(funcOid),							 0, 0, 0);	if (!HeapTupleIsValid(tup)) /* should not happen */		elog(ERROR, "cache lookup failed for function %u", funcOid);	procForm = (Form_pg_proc) GETSTRUCT(tup);	if (procForm->prorettype != OPAQUEOID)		/* caller messed up */		elog(ERROR, "function %u doesn't return OPAQUE", funcOid);	/* okay to overwrite copied tuple */	procForm->prorettype = newRetType;	/* update the catalog and its indexes */	simple_heap_update(pg_proc_rel, &tup->t_self, tup);	CatalogUpdateIndexes(pg_proc_rel, tup);	heap_close(pg_proc_rel, RowExclusiveLock);}/* * SetFunctionArgType - change declared argument type of a function * * As above, but change an argument's type. */voidSetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType){	Relation	pg_proc_rel;	HeapTuple	tup;	Form_pg_proc procForm;	pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);	tup = SearchSysCacheCopy(PROCOID,							 ObjectIdGetDatum(funcOid),							 0, 0, 0);	if (!HeapTupleIsValid(tup)) /* should not happen */		elog(ERROR, "cache lookup failed for function %u", funcOid);	procForm = (Form_pg_proc) GETSTRUCT(tup);	if (argIndex < 0 || argIndex >= procForm->pronargs ||		procForm->proargtypes.values[argIndex] != OPAQUEOID)		elog(ERROR, "function %u doesn't take OPAQUE", funcOid);	/* okay to overwrite copied tuple */	procForm->proargtypes.values[argIndex] = newArgType;	/* update the catalog and its indexes */	simple_heap_update(pg_proc_rel, &tup->t_self, tup);	CatalogUpdateIndexes(pg_proc_rel, tup);	heap_close(pg_proc_rel, RowExclusiveLock);}/* * CREATE CAST */voidCreateCast(CreateCastStmt *stmt){	Oid			sourcetypeid;	Oid			targettypeid;	Oid			funcid;	int			nargs;	char		castcontext;	Relation	relation;	HeapTuple	tuple;	Datum		values[Natts_pg_cast];	char		nulls[Natts_pg_cast];	ObjectAddress myself,				referenced;	sourcetypeid = LookupTypeName(stmt->sourcetype);	if (!OidIsValid(sourcetypeid))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("source data type %s does not exist",						TypeNameToString(stmt->sourcetype))));	targettypeid = LookupTypeName(stmt->targettype);	if (!OidIsValid(targettypeid))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("target data type %s does not exist",						TypeNameToString(stmt->targettype))));	/* No shells, no pseudo-types allowed */	if (!get_typisdefined(sourcetypeid))		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("source data type %s is only a shell",						TypeNameToString(stmt->sourcetype))));	if (!get_typisdefined(targettypeid))		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("target data type %s is only a shell",						TypeNameToString(stmt->targettype))));	if (get_typtype(sourcetypeid) == 'p')		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("source data type %s is a pseudo-type",						TypeNameToString(stmt->sourcetype))));	if (get_typtype(targettypeid) == 'p')		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("target data type %s is a pseudo-type",						TypeNameToString(stmt->targettype))));	/* Permission check */	if (!pg_type_ownercheck(sourcetypeid, GetUserId())		&& !pg_type_ownercheck(targettypeid, GetUserId()))		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("must be owner of type %s or type %s",						TypeNameToString(stmt->sourcetype),						TypeNameToString(stmt->targettype))));	if (stmt->func != NULL)	{		Form_pg_proc procstruct;		funcid = LookupFuncNameTypeNames(stmt->func->funcname,										 stmt->func->funcargs,										 false);		tuple = SearchSysCache(PROCOID,							   ObjectIdGetDatum(funcid),							   0, 0, 0);		if (!HeapTupleIsValid(tuple))			elog(ERROR, "cache lookup failed for function %u", funcid);		procstruct = (Form_pg_proc) GETSTRUCT(tuple);		nargs = procstruct->pronargs;		if (nargs < 1 || nargs > 3)			ereport(ERROR,					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),				  errmsg("cast function must take one to three arguments")));		if (procstruct->proargtypes.values[0] != sourcetypeid)			ereport(ERROR,					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),			errmsg("argument of cast function must match source data type")));		if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)			ereport(ERROR,					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),			errmsg("second argument of cast function must be type integer")));		if (nargs > 2 && procstruct->proargtypes.values[2] != BOOLOID)			ereport(ERROR,					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),			errmsg("third argument of cast function must be type boolean")));		if (procstruct->prorettype != targettypeid)			ereport(ERROR,					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),					 errmsg("return data type of cast function must match target data type")));		/*		 * Restricting the volatility of a cast function may or may not be a		 * good idea in the abstract, but it definitely breaks many old		 * user-defined types.	Disable this check --- tgl 2/1/03		 */#ifdef NOT_USED		if (procstruct->provolatile == PROVOLATILE_VOLATILE)			ereport(ERROR,					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),					 errmsg("cast function must not be volatile")));#endif		if (procstruct->proisagg)			ereport(ERROR,					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),				 errmsg("cast function must not be an aggregate function")));		if (procstruct->proretset)			ereport(ERROR,					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),					 errmsg("cast function must not return a set")));		ReleaseSysCache(tuple);	}	else	{		int16		typ1len;		int16		typ2len;		bool		typ1byval;		bool		typ2byval;		char		typ1align;		char		typ2align;		/* indicates binary coercibility */		funcid = InvalidOid;		nargs = 0;		/*		 * Must be superuser to create binary-compatible casts, since		 * erroneous casts can easily crash the backend.		 */		if (!superuser())			ereport(ERROR,					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),			 errmsg("must be superuser to create a cast WITHOUT FUNCTION")));		/*		 * Also, insist that the types match as to size, alignment, and		 * pass-by-value attributes; this provides at least a crude check that		 * they have similar representations.  A pair of types that fail this		 * test should certainly not be equated.		 */		get_typlenbyvalalign(sourcetypeid, &typ1len, &typ1byval, &typ1align);		get_typlenbyvalalign(targettypeid, &typ2len, &typ2byval, &typ2align);		if (typ1len != typ2len ||			typ1byval != typ2byval ||			typ1align != typ2align)			ereport(ERROR,					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),					 errmsg("source and target data types are not physically compatible")));	}	/*	 * Allow source and target types to be same only for length coercion	 * functions.  We assume a multi-arg function does length coercion.	 */	if (sourcetypeid == targettypeid && nargs < 2)		ereport(ERROR,				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),			  errmsg("source data type and target data type are the same")));	/* convert CoercionContext enum to char value for castcontext */	switch (stmt->context)	{		case COERCION_IMPLICIT:			castcontext = COERCION_CODE_IMPLICIT;			break;		case COERCION_ASSIGNMENT:			castcontext = COERCION_CODE_ASSIGNMENT;			break;		case COERCION_EXPLICIT:			castcontext = COERCION_CODE_EXPLICIT;			break;		default:			elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);			castcontext = 0;	/* keep compiler quiet */			break;	}	relation = heap_open(CastRelationId, RowExclusiveLock);	/*	 * Check for duplicate.  This is just to give a friendly error message,	 * the unique index would catch it anyway (so no need to sweat about race	 * conditions).	 */	tuple = SearchSysCache(CASTSOURCETARGET,						   ObjectIdGetDatum(sourcetypeid),						   ObjectIdGetDatum(targettypeid),						   0, 0);	if (HeapTupleIsValid(tuple))		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_OBJECT),				 errmsg("cast from type %s to type %s already exists",						TypeNameToString(stmt->sourcetype),						TypeNameToString(stmt->targettype))));	/* ready to go */	values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);	values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);	values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);	values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);	MemSet(nulls, ' ', Natts_pg_cast);	tuple = heap_formtuple(RelationGetDescr(relation), values, nulls);	simple_heap_insert(relation, tuple);	CatalogUpdateIndexes(relation, tuple);	/* make dependency entries */	myself.classId = CastRelationId;	myself.objectId = HeapTupleGetOid(tuple);	myself.objectSubId = 0;	/* dependency on source type */	referenced.classId = TypeRelationId;	referenced.objectId = sourcetypeid;	referenced.objectSubId = 0;	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);	/* dependency on target type */	referenced.classId = TypeRelationId;	referenced.objectId = targettypeid;	referenced.objectSubId = 0;	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);	/* dependency on function */	if (OidIsValid(funcid))	{		referenced.classId = ProcedureRelationId;		referenced.objectId = funcid;		referenced.objectSubId = 0;		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);	}	heap_freetuple(tuple);	heap_close(relation, RowExclusiveLock);}/* * DROP CAST */voidDropCast(DropCastStmt *stmt){	Oid			sourcetypeid;	Oid			targettypeid;	HeapTuple	tuple;	ObjectAddress object;	sourcetypeid = LookupTypeName(stmt->sourcetype);	if (!OidIsValid(sourcetypeid))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("source data type %s does not exist",						TypeNameToString(stmt->sourcetype))));	targettypeid = LookupTypeName(stmt->targettype);	if (!OidIsValid(targettypeid))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("target data type %s does not exist",						TypeNameToString(stmt->targettype))));	tuple = SearchSysCache(CASTSOURCETARGET,						   ObjectIdGetDatum(sourcetypeid),						   ObjectIdGetDatum(targettypeid),						   0, 0);	if (!HeapTupleIsValid(tuple))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("cast from type %s to type %s does not exist",						TypeNameToString(stmt->sourcetype),						TypeNameToString(stmt->targettype))));	/* Permission check */	if (!pg_type_ownercheck(sourcetypeid, GetUserId())		&& !pg_type_ownercheck(targettypeid, GetUserId()))		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("must be owner of type %s or type %s",						TypeNameToString(stmt->sourcetype),						TypeNameToString(stmt->targettype))));	/*	 * Do the deletion	 */	object.classId = CastRelationId;	object.objectId = HeapTupleGetOid(tuple);	object.objectSubId = 0;	ReleaseSysCache(tuple);	performDeletion(&object, stmt->behavior);}voidDropCastById(Oid castOid){	Relation	relation;	ScanKeyData scankey;	SysScanDesc scan;	HeapTuple	tuple;	relation = heap_open(CastRelationId, RowExclusiveLock);	ScanKeyInit(&scankey,				ObjectIdAttributeNumber,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(castOid));	scan = systable_beginscan(relation, CastOidIndexId, true,							  SnapshotNow, 1, &scankey);	tuple = systable_getnext(scan);	if (!HeapTupleIsValid(tuple))		elog(ERROR, "could not find tuple for cast %u", castOid);	simple_heap_delete(relation, &tuple->t_self);	systable_endscan(scan);	heap_close(relation, RowExclusiveLock);}/* * Execute ALTER FUNCTION SET SCHEMA */voidAlterFunctionNamespace(List *name, List *argtypes, const char *newschema){	Oid			procOid;	Oid			oldNspOid;	Oid			nspOid;	HeapTuple	tup;	Relation	procRel;	Form_pg_proc proc;	procRel = heap_open(ProcedureRelationId, RowExclusiveLock);	/* get function OID */	procOid = LookupFuncNameTypeNames(name, argtypes, false);	/* check permissions on function */	if (!pg_proc_ownercheck(procOid, GetUserId()))		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,					   NameListToString(name));	tup = SearchSysCacheCopy(PROCOID,							 ObjectIdGetDatum(procOid),							 0, 0, 0);	if (!HeapTupleIsValid(tup))		elog(ERROR, "cache lookup failed for function %u", procOid);	proc = (Form_pg_proc) GETSTRUCT(tup);	oldNspOid = proc->pronamespace;	/* get schema OID and check its permissions */	nspOid = LookupCreationNamespace(newschema);	if (oldNspOid == nspOid)		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_FUNCTION),				 errmsg("function \"%s\" is already in schema \"%s\"",						NameListToString(name),						newschema)));	/* 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(PROCNAMEARGSNSP,							 CStringGetDatum(NameStr(proc->proname)),							 PointerGetDatum(&proc->proargtypes),							 ObjectIdGetDatum(nspOid),							 0))		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_FUNCTION),				 errmsg("function \"%s\" already exists in schema \"%s\"",						NameStr(proc->proname),						newschema)));	/* OK, modify the pg_proc row */	/* tup is a copy, so we can scribble directly on it */	proc->pronamespace = nspOid;	simple_heap_update(procRel, &tup->t_self, tup);	CatalogUpdateIndexes(procRel, tup);	/* Update dependency on schema */	if (changeDependencyFor(ProcedureRelationId, procOid,							NamespaceRelationId, oldNspOid, nspOid) != 1)		elog(ERROR, "failed to change schema dependency for function \"%s\"",			 NameListToString(name));	heap_freetuple(tup);	heap_close(procRel, RowExclusiveLock);}

⌨️ 快捷键说明

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