/*
* inv_create -- create a new large object
*
* Arguments:
* lobjId - OID to use for new large object, or InvalidOid to pick one
*
* Returns:
* OID of new object
*
* If lobjId is not InvalidOid, then an error occurs if the OID is already
* in use.
*/
Oid
inv_create(Oid lobjId)
{
Oid lobjId_new;
/*
* Create a new largeobject with empty data pages
*/
lobjId_new = LargeObjectCreate(lobjId);
/*
* dependency on the owner of largeobject
*
* The reason why we use LargeObjectRelationId instead of
* LargeObjectMetadataRelationId here is to provide backward compatibility
* to the applications which utilize a knowledge about internal layout of
* system catalogs. OID of pg_largeobject_metadata and loid of
* pg_largeobject are same value, so there are no actual differences here.
*/
recordDependencyOnOwner(LargeObjectRelationId,
lobjId_new, GetUserId());
/* Post creation hook for new large object */
InvokeObjectAccessHook(OAT_POST_CREATE,
LargeObjectRelationId, lobjId_new, 0);
/*
* Advance command counter to make new tuple visible to later operations.
*/
CommandCounterIncrement();
return lobjId_new;
}
/* ----------------
* NamespaceCreate
* ---------------
*/
Oid
NamespaceCreate(const char *nspName, Oid ownerId, Oid forceOid)
{
Relation nspdesc;
HeapTuple tup;
Oid nspoid;
bool nulls[Natts_pg_namespace];
Datum values[Natts_pg_namespace];
NameData nname;
TupleDesc tupDesc;
int i;
/* sanity checks */
if (!nspName)
elog(ERROR, "no namespace name supplied");
/* make sure there is no existing namespace of same name */
if (SearchSysCacheExists(NAMESPACENAME,
PointerGetDatum(nspName),
0, 0, 0))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_SCHEMA),
errmsg("schema \"%s\" already exists", nspName)));
/* initialize nulls and values */
for (i = 0; i < Natts_pg_namespace; i++)
{
nulls[i] = false;
values[i] = (Datum) 0;
}
namestrcpy(&nname, nspName);
values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname);
values[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(ownerId);
nulls[Anum_pg_namespace_nspacl - 1] = true;
nspdesc = heap_open(NamespaceRelationId, RowExclusiveLock);
tupDesc = nspdesc->rd_att;
tup = heap_form_tuple(tupDesc, values, nulls);
if (forceOid != InvalidOid)
HeapTupleSetOid(tup, forceOid); /* override heap_insert's OID
* selection */
nspoid = simple_heap_insert(nspdesc, tup);
Assert(OidIsValid(nspoid));
CatalogUpdateIndexes(nspdesc, tup);
heap_close(nspdesc, RowExclusiveLock);
/* Record dependency on owner */
recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId);
return nspoid;
}
开发者ID:LJoNe,项目名称:gpdb,代码行数:60,代码来源:pg_namespace.c
示例3: makeOperatorDependencies
//.........这里部分代码省略.........
{
Form_pg_operator oper = (Form_pg_operator) GETSTRUCT(tuple);
ObjectAddress myself,
referenced;
myself.classId = OperatorRelationId;
myself.objectId = HeapTupleGetOid(tuple);
myself.objectSubId = 0;
/*
* If we are updating the operator, delete any existing entries, except
* for extension membership which should remain the same.
*/
if (isUpdate)
{
deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
deleteSharedDependencyRecordsFor(myself.classId, myself.objectId, 0);
}
/* Dependency on namespace */
if (OidIsValid(oper->oprnamespace))
{
referenced.classId = NamespaceRelationId;
referenced.objectId = oper->oprnamespace;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
/* Dependency on left type */
if (OidIsValid(oper->oprleft))
{
referenced.classId = TypeRelationId;
referenced.objectId = oper->oprleft;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
/* Dependency on right type */
if (OidIsValid(oper->oprright))
{
referenced.classId = TypeRelationId;
referenced.objectId = oper->oprright;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
/* Dependency on result type */
if (OidIsValid(oper->oprresult))
{
referenced.classId = TypeRelationId;
referenced.objectId = oper->oprresult;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
/*
* NOTE: we do not consider the operator to depend on the associated
* operators oprcom and oprnegate. We would not want to delete this
* operator if those go away, but only reset the link fields; which is not
* a function that the dependency code can presently handle. (Something
* could perhaps be done with objectSubId though.) For now, it's okay to
* let those links dangle if a referenced operator is removed.
*/
/* Dependency on implementation function */
if (OidIsValid(oper->oprcode))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = oper->oprcode;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
/* Dependency on restriction selectivity function */
if (OidIsValid(oper->oprrest))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = oper->oprrest;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
/* Dependency on join selectivity function */
if (OidIsValid(oper->oprjoin))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = oper->oprjoin;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
/* Dependency on owner */
recordDependencyOnOwner(OperatorRelationId, HeapTupleGetOid(tuple),
oper->oprowner);
/* Dependency on extension */
recordDependencyOnCurrentExtension(&myself, true);
return myself;
}
//.........这里部分代码省略.........
errmsg("tablespace location should not be inside the data directory")));
/*
* Disallow creation of tablespaces named "pg_xxx"; we reserve this
* namespace for system purposes.
*/
if (!allowSystemTableMods && IsReservedName(stmt->tablespacename))
ereport(ERROR,
(errcode(ERRCODE_RESERVED_NAME),
errmsg("unacceptable tablespace name \"%s\"",
stmt->tablespacename),
errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));
/*
* Check that there is no other tablespace by this name. (The unique
* index would catch this anyway, but might as well give a friendlier
* message.)
*/
if (OidIsValid(get_tablespace_oid(stmt->tablespacename, true)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("tablespace \"%s\" already exists",
stmt->tablespacename)));
/*
* Insert tuple into pg_tablespace. The purpose of doing this first is to
* lock the proposed tablename against other would-be creators. The
* insertion will roll back if we find problems below.
*/
rel = heap_open(TableSpaceRelationId, RowExclusiveLock);
MemSet(nulls, false, sizeof(nulls));
values[Anum_pg_tablespace_spcname - 1] =
DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename));
values[Anum_pg_tablespace_spcowner - 1] =
ObjectIdGetDatum(ownerId);
nulls[Anum_pg_tablespace_spcacl - 1] = true;
/* Generate new proposed spcoptions (text array) */
newOptions = transformRelOptions((Datum) 0,
stmt->options,
NULL, NULL, false, false);
(void) tablespace_reloptions(newOptions, true);
if (newOptions != (Datum) 0)
values[Anum_pg_tablespace_spcoptions - 1] = newOptions;
else
nulls[Anum_pg_tablespace_spcoptions - 1] = true;
tuple = heap_form_tuple(rel->rd_att, values, nulls);
tablespaceoid = simple_heap_insert(rel, tuple);
CatalogUpdateIndexes(rel, tuple);
heap_freetuple(tuple);
/* Record dependency on owner */
recordDependencyOnOwner(TableSpaceRelationId, tablespaceoid, ownerId);
/* Post creation hook for new tablespace */
InvokeObjectPostCreateHook(TableSpaceRelationId, tablespaceoid, 0);
create_tablespace_directories(location, tablespaceoid);
/* Record the filesystem change in XLOG */
{
xl_tblspc_create_rec xlrec;
xlrec.ts_id = tablespaceoid;
XLogBeginInsert();
XLogRegisterData((char *) &xlrec,
offsetof(xl_tblspc_create_rec, ts_path));
XLogRegisterData((char *) location, strlen(location) + 1);
(void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_CREATE);
}
/*
* Force synchronous commit, to minimize the window between creating the
* symlink on-disk and marking the transaction committed. It's not great
* that there is any window at all, but definitely we don't want to make
* it larger than necessary.
*/
ForceSyncCommit();
pfree(location);
/* We keep the lock on pg_tablespace until commit */
heap_close(rel, NoLock);
return tablespaceoid;
#else /* !HAVE_SYMLINK */
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("tablespaces are not supported on this platform")));
return InvalidOid; /* keep compiler quiet */
#endif /* HAVE_SYMLINK */
}
/*
* CollationCreate
*
* Add a new tuple to pg_collation.
*/
Oid
CollationCreate(const char *collname, Oid collnamespace,
Oid collowner,
int32 collencoding,
const char *collcollate, const char *collctype)
{
Relation rel;
TupleDesc tupDesc;
HeapTuple tup;
Datum values[Natts_pg_collation];
bool nulls[Natts_pg_collation];
NameData name_name,
name_collate,
name_ctype;
Oid oid;
ObjectAddress myself,
referenced;
AssertArg(collname);
AssertArg(collnamespace);
AssertArg(collowner);
AssertArg(collcollate);
AssertArg(collctype);
/*
* Make sure there is no existing collation of same name & encoding.
*
* This would be caught by the unique index anyway; we're just giving a
* friendlier error message. The unique index provides a backstop against
* race conditions.
*/
if (SearchSysCacheExists3(COLLNAMEENCNSP,
PointerGetDatum(collname),
Int32GetDatum(collencoding),
ObjectIdGetDatum(collnamespace)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("collation \"%s\" for encoding \"%s\" already exists",
collname, pg_encoding_to_char(collencoding))));
/*
* Also forbid matching an any-encoding entry. This test of course is not
* backed up by the unique index, but it's not a problem since we don't
* support adding any-encoding entries after initdb.
*/
if (SearchSysCacheExists3(COLLNAMEENCNSP,
PointerGetDatum(collname),
Int32GetDatum(-1),
ObjectIdGetDatum(collnamespace)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("collation \"%s\" already exists",
collname)));
/* open pg_collation */
rel = heap_open(CollationRelationId, RowExclusiveLock);
tupDesc = RelationGetDescr(rel);
/* form a tuple */
memset(nulls, 0, sizeof(nulls));
namestrcpy(&name_name, collname);
values[Anum_pg_collation_collname - 1] = NameGetDatum(&name_name);
values[Anum_pg_collation_collnamespace - 1] = ObjectIdGetDatum(collnamespace);
values[Anum_pg_collation_collowner - 1] = ObjectIdGetDatum(collowner);
values[Anum_pg_collation_collencoding - 1] = Int32GetDatum(collencoding);
namestrcpy(&name_collate, collcollate);
values[Anum_pg_collation_collcollate - 1] = NameGetDatum(&name_collate);
namestrcpy(&name_ctype, collctype);
values[Anum_pg_collation_collctype - 1] = NameGetDatum(&name_ctype);
tup = heap_form_tuple(tupDesc, values, nulls);
/* insert a new tuple */
oid = simple_heap_insert(rel, tup);
Assert(OidIsValid(oid));
/* update the index if any */
CatalogUpdateIndexes(rel, tup);
/* set up dependencies for the new collation */
myself.classId = CollationRelationId;
myself.objectId = oid;
myself.objectSubId = 0;
/* create dependency on namespace */
referenced.classId = NamespaceRelationId;
referenced.objectId = collnamespace;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
/* create dependency on owner */
recordDependencyOnOwner(CollationRelationId, HeapTupleGetOid(tup),
collowner);
//.........这里部分代码省略.........
/*
* GenerateTypeDependencies: build the dependencies needed for a type
*
* Most of what this function needs to know about the type is passed as the
* new pg_type row, typeForm. But we can't get at the varlena fields through
* that, so defaultExpr and typacl are passed separately. (typacl is really
* "Acl *", but we declare it "void *" to avoid including acl.h in pg_type.h.)
*
* relationKind and isImplicitArray aren't visible in the pg_type row either,
* so they're also passed separately.
*
* isDependentType is true if this is an implicit array or relation rowtype;
* that means it doesn't need its own dependencies on owner etc.
*
* If rebuild is true, we remove existing dependencies and rebuild them
* from scratch. This is needed for ALTER TYPE, and also when replacing
* a shell type. We don't remove an existing extension dependency, though.
* (That means an extension can't absorb a shell type created in another
* extension, nor ALTER a type created by another extension. Also, if it
* replaces a free-standing shell type or ALTERs a free-standing type,
* that type will become a member of the extension.)
*/
void
GenerateTypeDependencies(Oid typeObjectId,
Form_pg_type typeForm,
Node *defaultExpr,
void *typacl,
char relationKind, /* only for relation rowtypes */
bool isImplicitArray,
bool isDependentType,
bool rebuild)
{
ObjectAddress myself,
referenced;
/* If rebuild, first flush old dependencies, except extension deps */
if (rebuild)
{
deleteDependencyRecordsFor(TypeRelationId, typeObjectId, true);
deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId, 0);
}
myself.classId = TypeRelationId;
myself.objectId = typeObjectId;
myself.objectSubId = 0;
/*
* Make dependencies on namespace, owner, ACL, extension.
*
* Skip these for a dependent type, since it will have such dependencies
* indirectly through its depended-on type or relation.
*/
if (!isDependentType)
{
referenced.classId = NamespaceRelationId;
referenced.objectId = typeForm->typnamespace;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
recordDependencyOnOwner(TypeRelationId, typeObjectId,
typeForm->typowner);
recordDependencyOnNewAcl(TypeRelationId, typeObjectId, 0,
typeForm->typowner, typacl);
recordDependencyOnCurrentExtension(&myself, rebuild);
}
/* Normal dependencies on the I/O functions */
if (OidIsValid(typeForm->typinput))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = typeForm->typinput;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
if (OidIsValid(typeForm->typoutput))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = typeForm->typoutput;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
if (OidIsValid(typeForm->typreceive))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = typeForm->typreceive;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
if (OidIsValid(typeForm->typsend))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = typeForm->typsend;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
//.........这里部分代码省略.........
//.........这里部分代码省略.........
* Disallow creation of tablespaces named "pg_xxx"; we reserve this
* namespace for system purposes.
*/
if (!allowSystemTableMods && IsReservedName(stmt->tablespacename))
ereport(ERROR,
(errcode(ERRCODE_RESERVED_NAME),
errmsg("unacceptable tablespace name \"%s\"",
stmt->tablespacename),
errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));
/*
* Check that there is no other tablespace by this name. (The unique
* index would catch this anyway, but might as well give a friendlier
* message.)
*/
if (OidIsValid(get_tablespace_oid(stmt->tablespacename, true)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("tablespace \"%s\" already exists",
stmt->tablespacename)));
/*
* Insert tuple into pg_tablespace. The purpose of doing this first is to
* lock the proposed tablename against other would-be creators. The
* insertion will roll back if we find problems below.
*/
rel = heap_open(TableSpaceRelationId, RowExclusiveLock);
MemSet(nulls, false, sizeof(nulls));
values[Anum_pg_tablespace_spcname - 1] =
DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename));
values[Anum_pg_tablespace_spcowner - 1] =
ObjectIdGetDatum(ownerId);
nulls[Anum_pg_tablespace_spcacl - 1] = true;
nulls[Anum_pg_tablespace_spcoptions - 1] = true;
tuple = heap_form_tuple(rel->rd_att, values, nulls);
tablespaceoid = simple_heap_insert(rel, tuple);
CatalogUpdateIndexes(rel, tuple);
heap_freetuple(tuple);
/* Record dependency on owner */
recordDependencyOnOwner(TableSpaceRelationId, tablespaceoid, ownerId);
/* Post creation hook for new tablespace */
InvokeObjectAccessHook(OAT_POST_CREATE,
TableSpaceRelationId, tablespaceoid, 0, NULL);
create_tablespace_directories(location, tablespaceoid);
#ifdef PGXC
/*
* Even if we have succeeded, the transaction can be aborted because of
* failure on other nodes. So register for cleanup.
*/
set_dbcleanup_callback(createtbspc_abort_callback,
&tablespaceoid, sizeof(tablespaceoid));
#endif
/* Record the filesystem change in XLOG */
{
xl_tblspc_create_rec xlrec;
XLogRecData rdata[2];
xlrec.ts_id = tablespaceoid;
rdata[0].data = (char *) &xlrec;
rdata[0].len = offsetof(xl_tblspc_create_rec, ts_path);
rdata[0].buffer = InvalidBuffer;
rdata[0].next = &(rdata[1]);
rdata[1].data = (char *) location;
rdata[1].len = strlen(location) + 1;
rdata[1].buffer = InvalidBuffer;
rdata[1].next = NULL;
(void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_CREATE, rdata);
}
/*
* Force synchronous commit, to minimize the window between creating the
* symlink on-disk and marking the transaction committed. It's not great
* that there is any window at all, but definitely we don't want to make
* it larger than necessary.
*/
ForceSyncCommit();
pfree(location);
/* We keep the lock on pg_tablespace until commit */
heap_close(rel, NoLock);
#else /* !HAVE_SYMLINK */
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("tablespaces are not supported on this platform")));
#endif /* HAVE_SYMLINK */
}
/*
* GenerateTypeDependencies: build the dependencies needed for a type
*
* If rebuild is true, we remove existing dependencies and rebuild them
* from scratch. This is needed for ALTER TYPE, and also when replacing
* a shell type.
*/
void
GenerateTypeDependencies(Oid typeNamespace,
Oid typeObjectId,
Oid relationOid, /* only for 'c'atalog types */
char relationKind, /* ditto */
Oid owner,
Oid inputProcedure,
Oid outputProcedure,
Oid receiveProcedure,
Oid sendProcedure,
Oid analyzeProcedure,
Oid elementType,
Oid baseType,
Node *defaultExpr,
bool rebuild)
{
ObjectAddress myself,
referenced;
if (rebuild)
{
deleteDependencyRecordsFor(TypeRelationId, typeObjectId);
deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId);
}
myself.classId = TypeRelationId;
myself.objectId = typeObjectId;
myself.objectSubId = 0;
/* dependency on namespace */
/* skip for relation rowtype, since we have indirect dependency */
if (!OidIsValid(relationOid) || relationKind == RELKIND_COMPOSITE_TYPE)
{
referenced.classId = NamespaceRelationId;
referenced.objectId = typeNamespace;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
recordDependencyOnOwner(TypeRelationId, typeObjectId, owner);
}
/* Normal dependencies on the I/O functions */
if (OidIsValid(inputProcedure))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = inputProcedure;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
if (OidIsValid(outputProcedure))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = outputProcedure;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
if (OidIsValid(receiveProcedure))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = receiveProcedure;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
if (OidIsValid(sendProcedure))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = sendProcedure;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
if (OidIsValid(analyzeProcedure))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = analyzeProcedure;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
/*
* If the type is a rowtype for a relation, mark it as internally
* dependent on the relation, *unless* it is a stand-alone composite type
* relation. For the latter case, we have to reverse the dependency.
*
* In the former case, this allows the type to be auto-dropped when the
* relation is, and not otherwise. And in the latter, of course we get the
* opposite effect.
*/
if (OidIsValid(relationOid))
{
//.........这里部分代码省略.........
开发者ID:ricky-wu,项目名称:gpdb,代码行数:101,代码来源:pg_type.c
示例14: ExtProtocolCreate
//.........这里部分代码省略.........
strcasecmp(protocolName, "gpfdists") == 0)
{
ereport(ERROR,
(errcode(ERRCODE_RESERVED_NAME),
errmsg("protocol \"%s\" already exists",
protocolName),
errhint("pick a different protocol name")));
}
rel = heap_open(ExtprotocolRelationId, RowExclusiveLock);
/* make sure there is no existing protocol of same name */
ScanKeyInit(&skey,
Anum_pg_extprotocol_ptcname,
BTEqualStrategyNumber, F_NAMEEQ,
CStringGetDatum(protocolName));
scan = systable_beginscan(rel, ExtprotocolPtcnameIndexId, true,
SnapshotNow, 1, &skey);
tup = systable_getnext(scan);
if (HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("protocol \"%s\" already exists",
protocolName)));
systable_endscan(scan);
/*
* function checks: if supplied, check existence and correct signature in the catalog
*/
if (readfuncName)
readfn = ValidateProtocolFunction(readfuncName, EXTPTC_FUNC_READER);
if (writefuncName)
writefn = ValidateProtocolFunction(writefuncName, EXTPTC_FUNC_WRITER);
if (validatorfuncName)
validatorfn = ValidateProtocolFunction(validatorfuncName, EXTPTC_FUNC_VALIDATOR);
/*
* Everything looks okay. Try to create the pg_extprotocol entry for the
* protocol. (This could fail if there's already a conflicting entry.)
*/
/* initialize nulls and values */
for (i = 0; i < Natts_pg_extprotocol; i++)
{
nulls[i] = false;
values[i] = (Datum) 0;
}
namestrcpy(&prtname, protocolName);
values[Anum_pg_extprotocol_ptcname - 1] = NameGetDatum(&prtname);
values[Anum_pg_extprotocol_ptcreadfn - 1] = ObjectIdGetDatum(readfn);
values[Anum_pg_extprotocol_ptcwritefn - 1] = ObjectIdGetDatum(writefn);
values[Anum_pg_extprotocol_ptcvalidatorfn - 1] = ObjectIdGetDatum(validatorfn);
values[Anum_pg_extprotocol_ptcowner - 1] = ObjectIdGetDatum(ownerId);
values[Anum_pg_extprotocol_ptctrusted - 1] = BoolGetDatum(trusted);
nulls[Anum_pg_extprotocol_ptcacl - 1] = true;
tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
/* insert a new tuple */
protOid = simple_heap_insert(rel, tup);
CatalogUpdateIndexes(rel, tup);
heap_close(rel, RowExclusiveLock);
/*
* Create dependencies for the protocol
*/
myself.classId = ExtprotocolRelationId;
myself.objectId = protOid;
myself.objectSubId = 0;
/* Depends on read function, if any */
if (OidIsValid(readfn))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = readfn;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
/* Depends on write function, if any */
if (OidIsValid(writefn))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = writefn;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
/* dependency on owner */
recordDependencyOnOwner(ExtprotocolRelationId, protOid, GetUserId());
/* dependency on extension */
recordDependencyOnCurrentExtension(&myself, false);
return protOid;
}
/* ----------------
* NamespaceCreate
*
* Create a namespace (schema) with the given name and owner OID.
*
* If isTemp is true, this schema is a per-backend schema for holding
* temporary tables. Currently, it is used to prevent it from being
* linked as a member of any active extension. (If someone does CREATE
* TEMP TABLE in an extension script, we don't want the temp schema to
* become part of the extension). And to avoid checking for default ACL
* for temp namespace (as it is not necessary).
* ---------------
*/
Oid
NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
{
Relation nspdesc;
HeapTuple tup;
Oid nspoid;
bool nulls[Natts_pg_namespace];
Datum values[Natts_pg_namespace];
NameData nname;
TupleDesc tupDesc;
ObjectAddress myself;
int i;
Acl *nspacl;
/* sanity checks */
if (!nspName)
elog(ERROR, "no namespace name supplied");
/* make sure there is no existing namespace of same name */
if (SearchSysCacheExists1(NAMESPACENAME, PointerGetDatum(nspName)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_SCHEMA),
errmsg("schema \"%s\" already exists", nspName)));
if (!isTemp)
nspacl = get_user_default_acl(OBJECT_SCHEMA, ownerId,
InvalidOid);
else
nspacl = NULL;
nspdesc = heap_open(NamespaceRelationId, RowExclusiveLock);
tupDesc = nspdesc->rd_att;
/* initialize nulls and values */
for (i = 0; i < Natts_pg_namespace; i++)
{
nulls[i] = false;
values[i] = (Datum) NULL;
}
nspoid = GetNewOidWithIndex(nspdesc, NamespaceOidIndexId,
Anum_pg_namespace_oid);
values[Anum_pg_namespace_oid - 1] = ObjectIdGetDatum(nspoid);
namestrcpy(&nname, nspName);
values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname);
values[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(ownerId);
if (nspacl != NULL)
values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(nspacl);
else
nulls[Anum_pg_namespace_nspacl - 1] = true;
tup = heap_form_tuple(tupDesc, values, nulls);
CatalogTupleInsert(nspdesc, tup);
Assert(OidIsValid(nspoid));
heap_close(nspdesc, RowExclusiveLock);
/* Record dependencies */
myself.classId = NamespaceRelationId;
myself.objectId = nspoid;
myself.objectSubId = 0;
/* dependency on owner */
recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId);
/* dependences on roles mentioned in default ACL */
recordDependencyOnNewAcl(NamespaceRelationId, nspoid, 0, ownerId, nspacl);
/* dependency on extension ... but not for magic temp schemas */
if (!isTemp)
recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new schema */
InvokeObjectPostCreateHook(NamespaceRelationId, nspoid, 0);
return nspoid;
}
请发表评论