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 43 1766 : 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 */ 57 1766 : if (!nspName) 58 0 : elog(ERROR, "no namespace name supplied"); 59 : 60 : /* make sure there is no existing namespace of same name */ 61 1766 : if (SearchSysCacheExists1(NAMESPACENAME, PointerGetDatum(nspName))) 62 6 : ereport(ERROR, 63 : (errcode(ERRCODE_DUPLICATE_SCHEMA), 64 : errmsg("schema \"%s\" already exists", nspName))); 65 : 66 1760 : if (!isTemp) 67 968 : nspacl = get_user_default_acl(OBJECT_SCHEMA, ownerId, 68 : InvalidOid); 69 : else 70 792 : nspacl = NULL; 71 : 72 1760 : nspdesc = table_open(NamespaceRelationId, RowExclusiveLock); 73 1760 : tupDesc = nspdesc->rd_att; 74 : 75 : /* initialize nulls and values */ 76 8800 : for (i = 0; i < Natts_pg_namespace; i++) 77 : { 78 7040 : nulls[i] = false; 79 7040 : values[i] = (Datum) NULL; 80 : } 81 : 82 1760 : nspoid = GetNewOidWithIndex(nspdesc, NamespaceOidIndexId, 83 : Anum_pg_namespace_oid); 84 1760 : values[Anum_pg_namespace_oid - 1] = ObjectIdGetDatum(nspoid); 85 1760 : namestrcpy(&nname, nspName); 86 1760 : values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname); 87 1760 : values[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(ownerId); 88 1760 : if (nspacl != NULL) 89 12 : values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(nspacl); 90 : else 91 1748 : nulls[Anum_pg_namespace_nspacl - 1] = true; 92 : 93 : 94 1760 : tup = heap_form_tuple(tupDesc, values, nulls); 95 : 96 1760 : CatalogTupleInsert(nspdesc, tup); 97 : Assert(OidIsValid(nspoid)); 98 : 99 1760 : table_close(nspdesc, RowExclusiveLock); 100 : 101 : /* Record dependencies */ 102 1760 : myself.classId = NamespaceRelationId; 103 1760 : myself.objectId = nspoid; 104 1760 : myself.objectSubId = 0; 105 : 106 : /* dependency on owner */ 107 1760 : recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId); 108 : 109 : /* dependencies on roles mentioned in default ACL */ 110 1760 : recordDependencyOnNewAcl(NamespaceRelationId, nspoid, 0, ownerId, nspacl); 111 : 112 : /* dependency on extension ... but not for magic temp schemas */ 113 1760 : if (!isTemp) 114 968 : recordDependencyOnCurrentExtension(&myself, false); 115 : 116 : /* Post creation hook for new schema */ 117 1760 : InvokeObjectPostCreateHook(NamespaceRelationId, nspoid, 0); 118 : 119 1760 : return nspoid; 120 : }