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 + -
显示快捷键?