diff options
Diffstat (limited to 'src/backend/catalog/pg_namespace.c')
-rw-r--r-- | src/backend/catalog/pg_namespace.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c new file mode 100644 index 0000000..5ec8800 --- /dev/null +++ b/src/backend/catalog/pg_namespace.c @@ -0,0 +1,120 @@ +/*------------------------------------------------------------------------- + * + * pg_namespace.c + * routines to support manipulation of the pg_namespace relation + * + * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/catalog/pg_namespace.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/htup_details.h" +#include "access/table.h" +#include "catalog/catalog.h" +#include "catalog/dependency.h" +#include "catalog/indexing.h" +#include "catalog/objectaccess.h" +#include "catalog/pg_namespace.h" +#include "utils/builtins.h" +#include "utils/rel.h" +#include "utils/syscache.h" + + +/* ---------------- + * 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 = table_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)); + + table_close(nspdesc, RowExclusiveLock); + + /* Record dependencies */ + myself.classId = NamespaceRelationId; + myself.objectId = nspoid; + myself.objectSubId = 0; + + /* dependency on owner */ + recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId); + + /* dependencies 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; +} |