modules_poc_1.patch
application/octet-stream
Filename: modules_poc_1.patch
Type: application/octet-stream
Part: 0
Message:
Support for CREATE MODULE?
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/catalog/aclchk.c | 8 | 2 |
| src/backend/catalog/namespace.c | 197 | 52 |
| src/backend/catalog/objectaddress.c | 29 | 3 |
| src/backend/catalog/pg_namespace.c | 5 | 2 |
| src/backend/commands/extension.c | 3 | 3 |
| src/backend/commands/schemacmds.c | 6 | 5 |
| src/backend/utils/adt/acl.c | 1 | 1 |
| src/backend/utils/adt/pg_upgrade_support.c | 1 | 1 |
| src/backend/utils/adt/regproc.c | 2 | 2 |
| src/backend/utils/cache/syscache.c | 2 | 2 |
| src/include/catalog/namespace.h | 7 | 4 |
| src/include/catalog/pg_namespace.dat | 6 | 3 |
| src/include/catalog/pg_namespace.h | 11 | 2 |
unchanged:
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -706,7 +706,7 @@ objectNamesToOids(ObjectType objtype, List *objnames)
char *nspname = strVal(lfirst(cell));
Oid oid;
- oid = get_namespace_oid(nspname, false);
+ oid = get_namespace_oid(nspname, InvalidOid, false);
objects = lappend_oid(objects, oid);
}
break;
@@ -1113,7 +1113,7 @@ SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames)
{
char *nspname = strVal(lfirst(nspcell));
- iacls->nspid = get_namespace_oid(nspname, false);
+ iacls->nspid = get_namespace_oid(nspname, InvalidOid, false);
/*
* We used to insist that the target role have CREATE privileges
@@ -3372,6 +3372,9 @@ aclcheck_error(AclResult aclerr, ObjectType objtype,
case OBJECT_MATVIEW:
msg = gettext_noop("permission denied for materialized view %s");
break;
+ case OBJECT_MODULE:
+ msg = gettext_noop("permission denied for module %s");
+ break;
case OBJECT_OPCLASS:
msg = gettext_noop("permission denied for operator class %s");
break;
@@ -3500,6 +3503,9 @@ aclcheck_error(AclResult aclerr, ObjectType objtype,
case OBJECT_MATVIEW:
msg = gettext_noop("must be owner of materialized view %s");
break;
+ case OBJECT_MODULE:
+ msg = gettext_noop("must be owner of module %s");
+ break;
case OBJECT_OPCLASS:
msg = gettext_noop("must be owner of operator class %s");
break;
unchanged:
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -473,7 +473,7 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation)
return myTempNamespace;
}
/* use exact schema given */
- namespaceId = get_namespace_oid(newRelation->schemaname, false);
+ namespaceId = get_namespace_oid(newRelation->schemaname, InvalidOid, false);
/* we do not check for USAGE rights here! */
}
else if (newRelation->relpersistence == RELPERSISTENCE_TEMP)
@@ -945,9 +945,11 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
{
FuncCandidateList resultList = NULL;
bool any_special = false;
- char *schemaname;
+ char *nspname;
+ char *modulename;
char *funcname;
Oid namespaceId;
+ Oid moduleId;
CatCList *catlist;
int i;
@@ -955,19 +957,31 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
Assert(nargs >= 0 || !(expand_variadic | expand_defaults));
/* deconstruct the name list */
- DeconstructQualifiedName(names, &schemaname, &funcname);
+ DeconstructQualifiedName(names, &nspname, &modulename, &funcname, true);
- if (schemaname)
+ if (nspname && modulename)
{
/* use exact schema given */
- namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
+ namespaceId = LookupExplicitNamespace(nspname, missing_ok);
if (!OidIsValid(namespaceId))
return NULL;
+
+ moduleId = get_namespace_oid(modulename, namespaceId, true);
+ if (!OidIsValid(moduleId))
+ return NULL;
+ }
+ else if (nspname)
+ {
+ moduleId = InvalidOid;
+ namespaceId = LookupExplicitNamespace(nspname, true);
+ if (!OidIsValid(namespaceId))
+ recomputeNamespacePath();
}
else
{
/* flag to indicate we need namespace search */
namespaceId = InvalidOid;
+ moduleId = InvalidOid;
recomputeNamespacePath();
}
@@ -987,9 +1001,15 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
int *argnumbers = NULL;
FuncCandidateList newResult;
- if (OidIsValid(namespaceId))
+ if (OidIsValid(moduleId))
{
- /* Consider only procs in specified namespace */
+ /* Consider only procs in specified module */
+ if (procform->pronamespace != moduleId)
+ continue;
+ }
+ else if (OidIsValid(namespaceId))
+ {
+ /* Consider only procs in specified schema */
if (procform->pronamespace != namespaceId)
continue;
}
@@ -1003,7 +1023,16 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
foreach(nsp, activeSearchPath)
{
- if (procform->pronamespace == lfirst_oid(nsp) &&
+ /* check if there is a module in the schema */
+ if (nspname)
+ {
+ moduleId = get_namespace_oid(nspname, lfirst_oid(nsp), true);
+ if (OidIsValid(moduleId))
+ if (procform->pronamespace == moduleId &&
+ procform->pronamespace != myTempNamespace)
+ break;
+ }
+ else if (procform->pronamespace == lfirst_oid(nsp) &&
procform->pronamespace != myTempNamespace)
break;
pathpos++;
@@ -1449,7 +1478,6 @@ FunctionIsVisible(Oid funcid)
clist = FuncnameGetCandidates(list_make1(makeString(proname)),
nargs, NIL, false, false, false);
-
for (; clist; clist = clist->next)
{
if (memcmp(clist->args, procform->proargtypes.values,
@@ -1488,7 +1516,7 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
ListCell *l;
/* deconstruct the name list */
- DeconstructQualifiedName(names, &schemaname, &opername);
+ DeconstructQualifiedName(names, &schemaname, NULL, &opername, false);
if (schemaname)
{
@@ -1595,7 +1623,7 @@ OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
int i;
/* deconstruct the name list */
- DeconstructQualifiedName(names, &schemaname, &opername);
+ DeconstructQualifiedName(names, &schemaname, NULL, &opername, false);
if (schemaname)
{
@@ -2183,7 +2211,7 @@ get_statistics_object_oid(List *names, bool missing_ok)
ListCell *l;
/* deconstruct the name list */
- DeconstructQualifiedName(names, &schemaname, &stats_name);
+ DeconstructQualifiedName(names, &schemaname, NULL, &stats_name, false);
if (schemaname)
{
@@ -2224,6 +2252,60 @@ get_statistics_object_oid(List *names, bool missing_ok)
return stats_oid;
}
+/*
+ * get_module_oid - find a module by possibly qualified name
+ *
+ * If not found, returns InvalidOid if missing_ok, else throws error
+ */
+Oid
+get_module_oid(List *names, bool missing_ok)
+{
+ char *schemaname;
+ char *modulename;
+ Oid namespaceId;
+ Oid moduleId = InvalidOid;
+ ListCell *l;
+
+ /* deconstruct the name list */
+ DeconstructQualifiedName(names, &schemaname, NULL, &modulename, false);
+
+ if (schemaname)
+ {
+ /* use exact schema given */
+ namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
+ if (missing_ok && !OidIsValid(namespaceId))
+ moduleId = InvalidOid;
+ else
+ moduleId = GetSysCacheOid2(NAMESPACENAME, Anum_pg_namespace_oid,
+ CStringGetDatum(modulename), ObjectIdGetDatum(namespaceId));
+ }
+ else
+ {
+ /* search for it in search path */
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+ moduleId = GetSysCacheOid2(NAMESPACENAME, Anum_pg_namespace_oid,
+ CStringGetDatum(modulename), ObjectIdGetDatum(namespaceId));
+ if (OidIsValid(moduleId))
+ break;
+ }
+ }
+
+ if (!OidIsValid(moduleId) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("module \"%s\" does not exist",
+ NameListToString(names))));
+
+ return moduleId;
+}
+
/*
* StatisticsObjIsVisible
* Determine whether a statistics object (identified by OID) is visible in
@@ -2305,7 +2387,7 @@ get_ts_parser_oid(List *names, bool missing_ok)
ListCell *l;
/* deconstruct the name list */
- DeconstructQualifiedName(names, &schemaname, &parser_name);
+ DeconstructQualifiedName(names, &schemaname, NULL, &parser_name, false);
if (schemaname)
{
@@ -2431,7 +2513,7 @@ get_ts_dict_oid(List *names, bool missing_ok)
ListCell *l;
/* deconstruct the name list */
- DeconstructQualifiedName(names, &schemaname, &dict_name);
+ DeconstructQualifiedName(names, &schemaname, NULL, &dict_name, false);
if (schemaname)
{
@@ -2558,7 +2640,7 @@ get_ts_template_oid(List *names, bool missing_ok)
ListCell *l;
/* deconstruct the name list */
- DeconstructQualifiedName(names, &schemaname, &template_name);
+ DeconstructQualifiedName(names, &schemaname, NULL, &template_name, false);
if (schemaname)
{
@@ -2684,7 +2766,7 @@ get_ts_config_oid(List *names, bool missing_ok)
ListCell *l;
/* deconstruct the name list */
- DeconstructQualifiedName(names, &schemaname, &config_name);
+ DeconstructQualifiedName(names, &schemaname, NULL, &config_name, false);
if (schemaname)
{
@@ -2800,17 +2882,21 @@ TSConfigIsVisible(Oid cfgid)
/*
* DeconstructQualifiedName
* Given a possibly-qualified name expressed as a list of String nodes,
- * extract the schema name and object name.
+ * extract the schema name, module name and object name.
*
* *nspname_p is set to NULL if there is no explicit schema name.
+ * *modname_p is set to NULL if there is no explicit module name.
*/
void
DeconstructQualifiedName(List *names,
char **nspname_p,
- char **objname_p)
+ char **modname_p,
+ char **objname_p,
+ bool check_module)
{
char *catalogname;
- char *schemaname = NULL;
+ char *nspname = NULL;
+ char *modulename = NULL;
char *objname = NULL;
switch (list_length(names))
@@ -2819,22 +2905,70 @@ DeconstructQualifiedName(List *names,
objname = strVal(linitial(names));
break;
case 2:
- schemaname = strVal(linitial(names));
+ nspname = strVal(linitial(names));
objname = strVal(lsecond(names));
break;
case 3:
- catalogname = strVal(linitial(names));
- schemaname = strVal(lsecond(names));
- objname = strVal(lthird(names));
+ if (check_module)
+ {
+ /*
+ * Since we don't allow cross-database references, check if the
+ * first element is the current catalog and if is different assume
+ * the first element is a schema
+ */
+ if (strcmp(strVal(linitial(names)), get_database_name(MyDatabaseId)) != 0)
+ {
+ nspname = strVal(linitial(names));
+ modulename = strVal(lsecond(names));
+ }
+ else
+ {
+ catalogname = strVal(linitial(names));
+ nspname = strVal(lsecond(names));
+ }
- /*
- * We check the catalog name and then ignore it.
- */
- if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
+ objname = strVal(lthird(names));
+ }
+ else
+ {
+ catalogname = strVal(linitial(names));
+ nspname = strVal(lsecond(names));
+ objname = strVal(lthird(names));
+
+ /*
+ * We check the catalog name and then ignore it.
+ */
+ if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cross-database references are not implemented: %s",
+ NameListToString(names))));
+ }
+ break;
+ case 4:
+ if (check_module)
+ {
+ catalogname = strVal(linitial(names));
+ nspname = strVal(lsecond(names));
+ modulename = strVal(lthird(names));
+ objname = strVal(lfourth(names));
+
+ /*
+ * We check the catalog name and then ignore it.
+ */
+ if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cross-database references are not implemented: %s",
+ NameListToString(names))));
+ }
+ else
+ {
ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("cross-database references are not implemented: %s",
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("improper qualified name (too many dotted names): %s",
NameListToString(names))));
+ }
break;
default:
ereport(ERROR,
@@ -2844,7 +2978,9 @@ DeconstructQualifiedName(List *names,
break;
}
- *nspname_p = schemaname;
+ *nspname_p = nspname;
+ if (modname_p)
+ *modname_p = modulename;
*objname_p = objname;
}
@@ -2878,7 +3014,7 @@ LookupNamespaceNoError(const char *nspname)
return InvalidOid;
}
- return get_namespace_oid(nspname, true);
+ return get_namespace_oid(nspname, InvalidOid, true);
}
/*
@@ -2907,7 +3043,7 @@ LookupExplicitNamespace(const char *nspname, bool missing_ok)
*/
}
- namespaceId = get_namespace_oid(nspname, missing_ok);
+ namespaceId = get_namespace_oid(nspname, InvalidOid, missing_ok);
if (missing_ok && !OidIsValid(namespaceId))
return InvalidOid;
@@ -2945,7 +3081,7 @@ LookupCreationNamespace(const char *nspname)
return myTempNamespace;
}
- namespaceId = get_namespace_oid(nspname, false);
+ namespaceId = get_namespace_oid(nspname, InvalidOid, false);
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
if (aclresult != ACLCHECK_OK)
@@ -2991,25 +3127,34 @@ CheckSetNamespace(Oid oldNspOid, Oid nspOid)
* if we have to create or clean out the temp namespace.
*/
Oid
-QualifiedNameGetCreationNamespace(List *names, char **objname_p)
+QualifiedNameGetCreationNamespace(List *names, char **objname_p, bool check_module)
{
- char *schemaname;
+ char *nspname = NULL;
+ char *modulename = NULL;
+ Oid nspparent;
Oid namespaceId;
/* deconstruct the name list */
- DeconstructQualifiedName(names, &schemaname, objname_p);
+ DeconstructQualifiedName(names, &nspname, &modulename, objname_p, check_module);
- if (schemaname)
+ if (nspname && modulename)
+ {
+ /* use exact schema given */
+ nspparent = LookupExplicitNamespace(nspname, false);
+
+ namespaceId = get_namespace_oid(modulename, nspparent, false);
+ }
+ else if (nspname)
{
/* check for pg_temp alias */
- if (strcmp(schemaname, "pg_temp") == 0)
+ if (strcmp(nspname, "pg_temp") == 0)
{
/* Initialize temp namespace */
AccessTempTableNamespace(false);
return myTempNamespace;
}
/* use exact schema given */
- namespaceId = get_namespace_oid(schemaname, false);
+ namespaceId = get_namespace_oid(nspname, InvalidOid, false);
/* we do not check for USAGE rights here! */
}
else
@@ -3039,12 +3184,12 @@ QualifiedNameGetCreationNamespace(List *names, char **objname_p)
* true, just return InvalidOid.
*/
Oid
-get_namespace_oid(const char *nspname, bool missing_ok)
+get_namespace_oid(const char *nspname, Oid nspnamespace, bool missing_ok)
{
Oid oid;
- oid = GetSysCacheOid1(NAMESPACENAME, Anum_pg_namespace_oid,
- CStringGetDatum(nspname));
+ oid = GetSysCacheOid2(NAMESPACENAME, Anum_pg_namespace_oid,
+ CStringGetDatum(nspname), ObjectIdGetDatum(nspnamespace));
if (!OidIsValid(oid) && !missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_SCHEMA),
@@ -3607,7 +3752,7 @@ get_collation_oid(List *name, bool missing_ok)
ListCell *l;
/* deconstruct the name list */
- DeconstructQualifiedName(name, &schemaname, &collation_name);
+ DeconstructQualifiedName(name, &schemaname, NULL, &collation_name, false);
if (schemaname)
{
@@ -3660,7 +3805,7 @@ get_conversion_oid(List *name, bool missing_ok)
ListCell *l;
/* deconstruct the name list */
- DeconstructQualifiedName(name, &schemaname, &conversion_name);
+ DeconstructQualifiedName(name, &schemaname, NULL, &conversion_name, false);
if (schemaname)
{
@@ -3789,7 +3934,7 @@ recomputeNamespacePath(void)
char *rname;
rname = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);
- namespaceId = get_namespace_oid(rname, true);
+ namespaceId = get_namespace_oid(rname, InvalidOid, true);
ReleaseSysCache(tuple);
if (OidIsValid(namespaceId) &&
!list_member_oid(oidlist, namespaceId) &&
@@ -3818,7 +3963,7 @@ recomputeNamespacePath(void)
else
{
/* normal namespace reference */
- namespaceId = get_namespace_oid(curname, true);
+ namespaceId = get_namespace_oid(curname, InvalidOid, true);
if (OidIsValid(namespaceId) &&
!list_member_oid(oidlist, namespaceId) &&
pg_namespace_aclcheck(namespaceId, roleid,
@@ -3987,7 +4132,7 @@ InitTempTableNamespace(void)
snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
- namespaceId = get_namespace_oid(namespaceName, true);
+ namespaceId = get_namespace_oid(namespaceName, InvalidOid, true);
if (!OidIsValid(namespaceId))
{
/*
@@ -3998,8 +4143,8 @@ InitTempTableNamespace(void)
* temp tables. This works because the places that access the temp
* namespace for my own backend skip permissions checks on it.
*/
- namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
- true);
+ namespaceId = NamespaceCreate(namespaceName, InvalidOid, NSPKIND_SCHEMA,
+ BOOTSTRAP_SUPERUSERID, true);
/* Advance command counter to make namespace visible */
CommandCounterIncrement();
}
@@ -4020,11 +4165,11 @@ InitTempTableNamespace(void)
snprintf(namespaceName, sizeof(namespaceName), "pg_toast_temp_%d",
MyBackendId);
- toastspaceId = get_namespace_oid(namespaceName, true);
+ toastspaceId = get_namespace_oid(namespaceName, InvalidOid, true);
if (!OidIsValid(toastspaceId))
{
- toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
- true);
+ toastspaceId = NamespaceCreate(namespaceName, InvalidOid, NSPKIND_SCHEMA,
+ BOOTSTRAP_SUPERUSERID, true);
/* Advance command counter to make namespace visible */
CommandCounterIncrement();
}
unchanged:
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -406,12 +406,26 @@ static const ObjectPropertyType ObjectProperty[] =
NAMESPACENAME,
Anum_pg_namespace_oid,
Anum_pg_namespace_nspname,
- InvalidAttrNumber,
+ Anum_pg_namespace_nspnamespace,
Anum_pg_namespace_nspowner,
Anum_pg_namespace_nspacl,
OBJECT_SCHEMA,
true
},
+ {
+ "module",
+ NamespaceRelationId,
+ NamespaceOidIndexId,
+ NAMESPACEOID,
+ NAMESPACENAME,
+ Anum_pg_namespace_oid,
+ Anum_pg_namespace_nspname,
+ Anum_pg_namespace_nspnamespace,
+ Anum_pg_namespace_nspowner,
+ Anum_pg_namespace_nspacl,
+ OBJECT_MODULE,
+ true
+ },
{
"relation",
RelationRelationId,
@@ -765,6 +779,10 @@ static const struct object_type_map
{
"schema", OBJECT_SCHEMA
},
+ /* OCLASS_MODULE */
+ {
+ "module", OBJECT_MODULE
+ },
/* OCLASS_TSPARSER */
{
"text search parser", OBJECT_TSPARSER
@@ -1128,6 +1146,12 @@ get_object_address(ObjectType objtype, Node *object,
missing_ok);
address.objectSubId = 0;
break;
+ case OBJECT_MODULE:
+ address.classId = NamespaceRelationId;
+ address.objectId = get_module_oid(castNode(List, object),
+ missing_ok);
+ address.objectSubId = 0;
+ break;
default:
elog(ERROR, "unrecognized objtype: %d", (int) objtype);
/* placate compiler, in case it thinks elog might return */
@@ -1281,7 +1305,7 @@ get_object_address_unqualified(ObjectType objtype,
break;
case OBJECT_SCHEMA:
address.classId = NamespaceRelationId;
- address.objectId = get_namespace_oid(name, missing_ok);
+ address.objectId = get_namespace_oid(name, InvalidOid, missing_ok);
address.objectSubId = 0;
break;
case OBJECT_LANGUAGE:
@@ -2013,7 +2037,7 @@ get_object_address_defacl(List *object, bool missing_ok)
*/
if (schema)
{
- schemaid = get_namespace_oid(schema, true);
+ schemaid = get_namespace_oid(schema, InvalidOid, true);
if (schemaid == InvalidOid)
goto not_found;
}
@@ -2267,6 +2291,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
case OBJECT_TABCONSTRAINT:
case OBJECT_OPCLASS:
case OBJECT_OPFAMILY:
+ case OBJECT_MODULE:
objnode = (Node *) name;
break;
case OBJECT_ACCESS_METHOD:
@@ -2431,6 +2456,7 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
NameListToString((castNode(ObjectWithArgs, object))->objname));
break;
case OBJECT_SCHEMA:
+ case OBJECT_MODULE:
if (!pg_namespace_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
strVal((Value *) object));
unchanged:
--- a/src/backend/catalog/pg_namespace.c
+++ b/src/backend/catalog/pg_namespace.c
@@ -40,7 +40,8 @@
* ---------------
*/
Oid
-NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
+NamespaceCreate(const char *nspName, Oid nspnamespace, char nspkind,
+ Oid ownerId, bool isTemp)
{
Relation nspdesc;
HeapTuple tup;
@@ -58,7 +59,7 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
elog(ERROR, "no namespace name supplied");
/* make sure there is no existing namespace of same name */
- if (SearchSysCacheExists1(NAMESPACENAME, PointerGetDatum(nspName)))
+ if (SearchSysCacheExists2(NAMESPACENAME, PointerGetDatum(nspName), nspnamespace))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_SCHEMA),
errmsg("schema \"%s\" already exists", nspName)));
@@ -85,6 +86,8 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
namestrcpy(&nname, nspName);
values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname);
values[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(ownerId);
+ values[Anum_pg_namespace_nspnamespace - 1] = ObjectIdGetDatum(nspnamespace);
+ values[Anum_pg_namespace_nspkind - 1] = CharGetDatum(nspkind);
if (nspacl != NULL)
values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(nspacl);
else
unchanged:
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1460,7 +1460,7 @@ CreateExtensionInternal(char *extensionName,
if (schemaName)
{
/* If the user is giving us the schema name, it must exist already. */
- schemaOid = get_namespace_oid(schemaName, false);
+ schemaOid = get_namespace_oid(schemaName, InvalidOid, false);
}
if (control->schema != NULL)
@@ -1484,7 +1484,7 @@ CreateExtensionInternal(char *extensionName,
schemaName = control->schema;
/* Find or create the schema in case it does not exist. */
- schemaOid = get_namespace_oid(schemaName, true);
+ schemaOid = get_namespace_oid(schemaName, InvalidOid, true);
if (!OidIsValid(schemaOid))
{
@@ -1501,7 +1501,7 @@ CreateExtensionInternal(char *extensionName,
* CreateSchemaCommand includes CommandCounterIncrement, so new
* schema is now visible.
*/
- schemaOid = get_namespace_oid(schemaName, false);
+ schemaOid = get_namespace_oid(schemaName, InvalidOid, false);
}
}
else if (!OidIsValid(schemaOid))
unchanged:
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -113,7 +113,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
* creation-permission check first, we do likewise.
*/
if (stmt->if_not_exists &&
- SearchSysCacheExists1(NAMESPACENAME, PointerGetDatum(schemaName)))
+ SearchSysCacheExists2(NAMESPACENAME, PointerGetDatum(schemaName), InvalidOid))
{
ereport(NOTICE,
(errcode(ERRCODE_DUPLICATE_SCHEMA),
@@ -135,7 +135,8 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
/* Create the schema's namespace */
- namespaceId = NamespaceCreate(schemaName, owner_uid, false);
+ namespaceId = NamespaceCreate(schemaName, InvalidOid, NSPKIND_SCHEMA,
+ owner_uid, false);
/* Advance cmd counter to make the namespace visible */
CommandCounterIncrement();
@@ -226,7 +227,7 @@ RenameSchema(const char *oldname, const char *newname)
rel = table_open(NamespaceRelationId, RowExclusiveLock);
- tup = SearchSysCacheCopy1(NAMESPACENAME, CStringGetDatum(oldname));
+ tup = SearchSysCacheCopy2(NAMESPACENAME, CStringGetDatum(oldname), InvalidOid);
if (!HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_SCHEMA),
@@ -236,7 +237,7 @@ RenameSchema(const char *oldname, const char *newname)
nspOid = nspform->oid;
/* make sure the new name doesn't exist */
- if (OidIsValid(get_namespace_oid(newname, true)))
+ if (OidIsValid(get_namespace_oid(newname, InvalidOid, true)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_SCHEMA),
errmsg("schema \"%s\" already exists", newname)));
@@ -306,7 +307,7 @@ AlterSchemaOwner(const char *name, Oid newOwnerId)
rel = table_open(NamespaceRelationId, RowExclusiveLock);
- tup = SearchSysCache1(NAMESPACENAME, CStringGetDatum(name));
+ tup = SearchSysCache2(NAMESPACENAME, CStringGetDatum(name), InvalidOid);
if (!HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_SCHEMA),
unchanged:
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -3827,7 +3827,7 @@ convert_schema_name(text *schemaname)
{
char *nspname = text_to_cstring(schemaname);
- return get_namespace_oid(nspname, false);
+ return get_namespace_oid(nspname, InvalidOid, false);
}
/*
unchanged:
--- a/src/backend/utils/adt/pg_upgrade_support.c
+++ b/src/backend/utils/adt/pg_upgrade_support.c
@@ -184,7 +184,7 @@ binary_upgrade_create_empty_extension(PG_FUNCTION_ARGS)
InsertExtensionTuple(text_to_cstring(extName),
GetUserId(),
- get_namespace_oid(text_to_cstring(schemaName), false),
+ get_namespace_oid(text_to_cstring(schemaName), InvalidOid, false),
relocatable,
text_to_cstring(extVersion),
extConfig,
unchanged:
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -1762,7 +1762,7 @@ regnamespacein(PG_FUNCTION_ARGS)
(errcode(ERRCODE_INVALID_NAME),
errmsg("invalid name syntax")));
- result = get_namespace_oid(strVal(linitial(names)), false);
+ result = get_namespace_oid(strVal(linitial(names)), InvalidOid, false);
PG_RETURN_OID(result);
}
@@ -1786,7 +1786,7 @@ to_regnamespace(PG_FUNCTION_ARGS)
(errcode(ERRCODE_INVALID_NAME),
errmsg("invalid name syntax")));
- result = get_namespace_oid(strVal(linitial(names)), true);
+ result = get_namespace_oid(strVal(linitial(names)), InvalidOid, true);
if (OidIsValid(result))
PG_RETURN_OID(result);
unchanged:
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -509,10 +509,10 @@ static const struct cachedesc cacheinfo[] = {
},
{NamespaceRelationId, /* NAMESPACENAME */
NamespaceNameIndexId,
- 1,
+ 2,
{
Anum_pg_namespace_nspname,
- 0,
+ Anum_pg_namespace_nspnamespace,
0,
0
},
only in patch2:
unchanged:
--- a/src/include/catalog/namespace.h
+++ b/src/include/catalog/namespace.h
@@ -135,15 +135,18 @@ extern Oid get_ts_config_oid(List *names, bool missing_ok);
extern bool TSConfigIsVisible(Oid cfgid);
extern void DeconstructQualifiedName(List *names,
- char **nspname_p,
- char **objname_p);
+ char **nspname_p,
+ char **modname_p,
+ char **objname_p,
+ bool check_module);
extern Oid LookupNamespaceNoError(const char *nspname);
extern Oid LookupExplicitNamespace(const char *nspname, bool missing_ok);
-extern Oid get_namespace_oid(const char *nspname, bool missing_ok);
+extern Oid get_namespace_oid(const char *nspname, Oid nspnamespace, bool missing_ok);
+extern Oid get_module_oid(List *names, bool missing_ok);
extern Oid LookupCreationNamespace(const char *nspname);
extern void CheckSetNamespace(Oid oldNspOid, Oid nspOid);
-extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p);
+extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p, bool check_module);
extern RangeVar *makeRangeVarFromNameList(List *names);
extern char *NameListToString(List *names);
extern char *NameListToQuotedString(List *names);
only in patch2:
unchanged:
--- a/src/include/catalog/pg_namespace.dat
+++ b/src/include/catalog/pg_namespace.dat
@@ -14,12 +14,15 @@
{ oid => '11', oid_symbol => 'PG_CATALOG_NAMESPACE',
descr => 'system catalog schema',
- nspname => 'pg_catalog', nspacl => '_null_' },
+ nspname => 'pg_catalog', nspnamespace => '0',
+ nspkind => 's', nspacl => '_null_' },
{ oid => '99', oid_symbol => 'PG_TOAST_NAMESPACE',
descr => 'reserved schema for TOAST tables',
- nspname => 'pg_toast', nspacl => '_null_' },
+ nspname => 'pg_toast', nspnamespace => '0',
+ nspkind => 's', nspacl => '_null_' },
{ oid => '2200', oid_symbol => 'PG_PUBLIC_NAMESPACE',
descr => 'standard public schema',
- nspname => 'public', nspacl => '_null_' },
+ nspname => 'public', nspnamespace => '0',
+ nspkind => 's', nspacl => '_null_' },
]
only in patch2:
unchanged:
--- a/src/include/catalog/pg_namespace.h
+++ b/src/include/catalog/pg_namespace.h
@@ -29,6 +29,8 @@
*
* nspname name of the namespace
* nspowner owner (creator) of the namespace
+ * nspnamespace parent of the namespace
+ * nspkind the type namespace
* nspacl access privilege list
* ----------------------------------------------------------------
*/
@@ -38,6 +40,9 @@ CATALOG(pg_namespace,2615,NamespaceRelationId)
NameData nspname;
Oid nspowner BKI_DEFAULT(POSTGRES) BKI_LOOKUP(pg_authid);
+ Oid nspnamespace BKI_DEFAULT(0);
+ char nspkind BKI_DEFAULT(s);
+
#ifdef CATALOG_VARLEN /* variable-length fields start here */
aclitem nspacl[1];
@@ -53,14 +58,18 @@ typedef FormData_pg_namespace *Form_pg_namespace;
DECLARE_TOAST(pg_namespace, 4163, 4164);
-DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, on pg_namespace using btree(nspname name_ops));
+DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, on pg_namespace using btree(nspname name_ops, nspnamespace oid_ops));
#define NamespaceNameIndexId 2684
DECLARE_UNIQUE_INDEX_PKEY(pg_namespace_oid_index, 2685, on pg_namespace using btree(oid oid_ops));
#define NamespaceOidIndexId 2685
+#define NSPKIND_SCHEMA 's' /* schema */
+#define NSPKIND_MODULE 'm' /* module */
+
/*
* prototypes for functions in pg_namespace.c
*/
-extern Oid NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp);
+extern Oid NamespaceCreate(const char *nspName, Oid nspnamespace, char nspkind,
+ Oid ownerId, bool isTemp);
#endif /* PG_NAMESPACE_H */