summaryrefslogtreecommitdiffstats
path: root/src/backend/catalog/pg_namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/catalog/pg_namespace.c')
-rw-r--r--src/backend/catalog/pg_namespace.c120
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;
+}