functioncmds.c

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

C
1,115
字号
	/* 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_openr(ProcedureRelationName, 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[argIndex] != OPAQUEOID)		elog(ERROR, "function %u doesn't take OPAQUE", funcOid);	/* okay to overwrite copied tuple */	procForm->proargtypes[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;	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))));	if (sourcetypeid == targettypeid)		ereport(ERROR,				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),		  errmsg("source data type and target data type are the same")));	/* 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);		if (procstruct->pronargs != 1)			ereport(ERROR,					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),					 errmsg("cast function must take one argument")));		if (procstruct->proargtypes[0] != sourcetypeid)			ereport(ERROR,					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),					 errmsg("argument of cast function must match source data type")));		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;		/*		 * 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")));	}	/* 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_openr(CastRelationName, 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 = RelationGetRelid(relation);	myself.objectId = HeapTupleGetOid(tuple);	myself.objectSubId = 0;	/* dependency on source type */	referenced.classId = RelOid_pg_type;	referenced.objectId = sourcetypeid;	referenced.objectSubId = 0;	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);	/* dependency on target type */	referenced.classId = RelOid_pg_type;	referenced.objectId = targettypeid;	referenced.objectSubId = 0;	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);	/* dependency on function */	if (OidIsValid(funcid))	{		referenced.classId = RelOid_pg_proc;		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 = get_system_catalog_relid(CastRelationName);	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_openr(CastRelationName, RowExclusiveLock);	ScanKeyEntryInitialize(&scankey, 0x0,						   ObjectIdAttributeNumber,						   F_OIDEQ,						   ObjectIdGetDatum(castOid));	scan = systable_beginscan(relation, CastOidIndex, 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);}

⌨️ 快捷键说明

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