Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * pg_namespace.c
4 : : * routines to support manipulation of the pg_namespace relation
5 : : *
6 : : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7 : : * Portions Copyright (c) 1994, Regents of the University of California
8 : : *
9 : : *
10 : : * IDENTIFICATION
11 : : * src/backend/catalog/pg_namespace.c
12 : : *
13 : : *-------------------------------------------------------------------------
14 : : */
15 : : #include "postgres.h"
16 : :
17 : : #include "access/htup_details.h"
18 : : #include "access/table.h"
19 : : #include "catalog/catalog.h"
20 : : #include "catalog/dependency.h"
21 : : #include "catalog/indexing.h"
22 : : #include "catalog/objectaccess.h"
23 : : #include "catalog/pg_namespace.h"
24 : : #include "utils/builtins.h"
25 : : #include "utils/rel.h"
26 : : #include "utils/syscache.h"
27 : :
28 : :
29 : : /* ----------------
30 : : * NamespaceCreate
31 : : *
32 : : * Create a namespace (schema) with the given name and owner OID.
33 : : *
34 : : * If isTemp is true, this schema is a per-backend schema for holding
35 : : * temporary tables. Currently, it is used to prevent it from being
36 : : * linked as a member of any active extension. (If someone does CREATE
37 : : * TEMP TABLE in an extension script, we don't want the temp schema to
38 : : * become part of the extension). And to avoid checking for default ACL
39 : : * for temp namespace (as it is not necessary).
40 : : * ---------------
41 : : */
42 : : Oid
4420 tgl@sss.pgh.pa.us 43 :CBC 859 : NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
44 : : {
45 : : Relation nspdesc;
46 : : HeapTuple tup;
47 : : Oid nspoid;
48 : : bool nulls[Natts_pg_namespace];
49 : : Datum values[Natts_pg_namespace];
50 : : NameData nname;
51 : : TupleDesc tupDesc;
52 : : ObjectAddress myself;
53 : : int i;
54 : : Acl *nspacl;
55 : :
56 : : /* sanity checks */
8059 57 [ - + ]: 859 : if (!nspName)
8059 tgl@sss.pgh.pa.us 58 [ # # ]:UBC 0 : elog(ERROR, "no namespace name supplied");
59 : :
60 : : /* make sure there is no existing namespace of same name */
5173 rhaas@postgresql.org 61 [ + + ]:CBC 859 : if (SearchSysCacheExists1(NAMESPACENAME, PointerGetDatum(nspName)))
7573 tgl@sss.pgh.pa.us 62 [ + - ]: 3 : ereport(ERROR,
63 : : (errcode(ERRCODE_DUPLICATE_SCHEMA),
64 : : errmsg("schema \"%s\" already exists", nspName)));
65 : :
2574 teodor@sigaev.ru 66 [ + + ]: 856 : if (!isTemp)
2377 peter_e@gmx.net 67 : 468 : nspacl = get_user_default_acl(OBJECT_SCHEMA, ownerId,
68 : : InvalidOid);
69 : : else
2574 teodor@sigaev.ru 70 : 388 : nspacl = NULL;
71 : :
1910 andres@anarazel.de 72 : 856 : nspdesc = table_open(NamespaceRelationId, RowExclusiveLock);
1972 73 : 856 : tupDesc = nspdesc->rd_att;
74 : :
75 : : /* initialize nulls and values */
8059 tgl@sss.pgh.pa.us 76 [ + + ]: 4280 : for (i = 0; i < Natts_pg_namespace; i++)
77 : : {
5642 78 : 3424 : nulls[i] = false;
8059 79 : 3424 : values[i] = (Datum) NULL;
80 : : }
81 : :
1972 andres@anarazel.de 82 : 856 : nspoid = GetNewOidWithIndex(nspdesc, NamespaceOidIndexId,
83 : : Anum_pg_namespace_oid);
84 : 856 : values[Anum_pg_namespace_oid - 1] = ObjectIdGetDatum(nspoid);
8059 tgl@sss.pgh.pa.us 85 : 856 : namestrcpy(&nname, nspName);
86 : 856 : values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname);
6865 87 : 856 : values[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(ownerId);
2574 teodor@sigaev.ru 88 [ + + ]: 856 : if (nspacl != NULL)
89 : 6 : values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(nspacl);
90 : : else
91 : 850 : nulls[Anum_pg_namespace_nspacl - 1] = true;
92 : :
93 : :
5642 tgl@sss.pgh.pa.us 94 : 856 : tup = heap_form_tuple(tupDesc, values, nulls);
95 : :
1972 andres@anarazel.de 96 : 856 : CatalogTupleInsert(nspdesc, tup);
7999 tgl@sss.pgh.pa.us 97 [ - + ]: 856 : Assert(OidIsValid(nspoid));
98 : :
1910 andres@anarazel.de 99 : 856 : table_close(nspdesc, RowExclusiveLock);
100 : :
101 : : /* Record dependencies */
4814 tgl@sss.pgh.pa.us 102 : 856 : myself.classId = NamespaceRelationId;
103 : 856 : myself.objectId = nspoid;
104 : 856 : myself.objectSubId = 0;
105 : :
106 : : /* dependency on owner */
6856 107 : 856 : recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId);
108 : :
109 : : /* dependencies on roles mentioned in default ACL */
1983 110 : 856 : recordDependencyOnNewAcl(NamespaceRelationId, nspoid, 0, ownerId, nspacl);
111 : :
112 : : /* dependency on extension ... but not for magic temp schemas */
4420 113 [ + + ]: 856 : if (!isTemp)
114 : 468 : recordDependencyOnCurrentExtension(&myself, false);
115 : :
116 : : /* Post creation hook for new schema */
4057 rhaas@postgresql.org 117 [ + + ]: 856 : InvokeObjectPostCreateHook(NamespaceRelationId, nspoid, 0);
118 : :
8059 tgl@sss.pgh.pa.us 119 : 856 : return nspoid;
120 : : }
|