]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Centralize code for interpreting schema references, which had gotten
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 29 Jul 2002 23:46:35 +0000 (23:46 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 29 Jul 2002 23:46:35 +0000 (23:46 +0000)
copied more places than I first thought it would.  This fixes a bug:
a couple of these places were neglecting to enforce USAGE access on
explicitly-referenced schemas.

src/backend/catalog/namespace.c
src/backend/commands/comment.c
src/backend/commands/indexcmds.c
src/backend/commands/opclasscmds.c
src/backend/parser/parse_type.c
src/include/catalog/namespace.h

index f02789fa807295840902fa48e0a5f0b3242b07d6..0425e44c1cd8653bb0cbd037d90047b99eae7f55 100644 (file)
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.26 2002/07/20 05:16:56 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.27 2002/07/29 23:46:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -164,18 +164,7 @@ RangeVarGetRelid(const RangeVar *relation, bool failOK)
        if (relation->schemaname)
        {
                /* use exact schema given */
-               AclResult       aclresult;
-
-               namespaceId = GetSysCacheOid(NAMESPACENAME,
-                                                                        CStringGetDatum(relation->schemaname),
-                                                                        0, 0, 0);
-               if (!OidIsValid(namespaceId))
-                       elog(ERROR, "Namespace \"%s\" does not exist",
-                                relation->schemaname);
-               aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
-               if (aclresult != ACLCHECK_OK)
-                       aclcheck_error(aclresult, relation->schemaname);
-
+               namespaceId = LookupExplicitNamespace(relation->schemaname);
                relId = get_relname_relid(relation->relname, namespaceId);
        }
        else
@@ -239,6 +228,7 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation)
                if (!OidIsValid(namespaceId))
                        elog(ERROR, "Namespace \"%s\" does not exist",
                                 newRelation->schemaname);
+               /* we do not check for USAGE rights here! */
        }
        else
        {
@@ -431,53 +421,19 @@ FuncCandidateList
 FuncnameGetCandidates(List *names, int nargs)
 {
        FuncCandidateList resultList = NULL;
-       char       *catalogname;
-       char       *schemaname = NULL;
-       char       *funcname = NULL;
+       char       *schemaname;
+       char       *funcname;
        Oid                     namespaceId;
        CatCList   *catlist;
        int                     i;
 
        /* deconstruct the name list */
-       switch (length(names))
-       {
-               case 1:
-                       funcname = strVal(lfirst(names));
-                       break;
-               case 2:
-                       schemaname = strVal(lfirst(names));
-                       funcname = strVal(lsecond(names));
-                       break;
-               case 3:
-                       catalogname = strVal(lfirst(names));
-                       schemaname = strVal(lsecond(names));
-                       funcname = strVal(lfirst(lnext(lnext(names))));
-                       /*
-                        * We check the catalog name and then ignore it.
-                        */
-                       if (strcmp(catalogname, DatabaseName) != 0)
-                               elog(ERROR, "Cross-database references are not implemented");
-                       break;
-               default:
-                       elog(ERROR, "Improper qualified name (too many dotted names): %s",
-                                NameListToString(names));
-                       break;
-       }
+       DeconstructQualifiedName(names, &schemaname, &funcname);
 
        if (schemaname)
        {
                /* use exact schema given */
-               AclResult       aclresult;
-
-               namespaceId = GetSysCacheOid(NAMESPACENAME,
-                                                                        CStringGetDatum(schemaname),
-                                                                        0, 0, 0);
-               if (!OidIsValid(namespaceId))
-                       elog(ERROR, "Namespace \"%s\" does not exist",
-                                schemaname);
-               aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
-               if (aclresult != ACLCHECK_OK)
-                       aclcheck_error(aclresult, schemaname);
+               namespaceId = LookupExplicitNamespace(schemaname);
        }
        else
        {
@@ -684,53 +640,19 @@ FuncCandidateList
 OpernameGetCandidates(List *names, char oprkind)
 {
        FuncCandidateList resultList = NULL;
-       char       *catalogname;
-       char       *schemaname = NULL;
-       char       *opername = NULL;
+       char       *schemaname;
+       char       *opername;
        Oid                     namespaceId;
        CatCList   *catlist;
        int                     i;
 
        /* deconstruct the name list */
-       switch (length(names))
-       {
-               case 1:
-                       opername = strVal(lfirst(names));
-                       break;
-               case 2:
-                       schemaname = strVal(lfirst(names));
-                       opername = strVal(lsecond(names));
-                       break;
-               case 3:
-                       catalogname = strVal(lfirst(names));
-                       schemaname = strVal(lsecond(names));
-                       opername = strVal(lfirst(lnext(lnext(names))));
-                       /*
-                        * We check the catalog name and then ignore it.
-                        */
-                       if (strcmp(catalogname, DatabaseName) != 0)
-                               elog(ERROR, "Cross-database references are not implemented");
-                       break;
-               default:
-                       elog(ERROR, "Improper qualified name (too many dotted names): %s",
-                                NameListToString(names));
-                       break;
-       }
+       DeconstructQualifiedName(names, &schemaname, &opername);
 
        if (schemaname)
        {
                /* use exact schema given */
-               AclResult       aclresult;
-
-               namespaceId = GetSysCacheOid(NAMESPACENAME,
-                                                                        CStringGetDatum(schemaname),
-                                                                        0, 0, 0);
-               if (!OidIsValid(namespaceId))
-                       elog(ERROR, "Namespace \"%s\" does not exist",
-                                schemaname);
-               aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
-               if (aclresult != ACLCHECK_OK)
-                       aclcheck_error(aclresult, schemaname);
+               namespaceId = LookupExplicitNamespace(schemaname);
        }
        else
        {
@@ -1105,25 +1027,22 @@ OpclassIsVisible(Oid opcid)
        return visible;
 }
 
-
 /*
- * QualifiedNameGetCreationNamespace
- *             Given a possibly-qualified name for an object (in List-of-Values
- *             format), determine what namespace the object should be created in.
- *             Also extract and return the object name (last component of list).
+ * DeconstructQualifiedName
+ *             Given a possibly-qualified name expressed as a list of String nodes,
+ *             extract the schema name and object name.
  *
- * This is *not* used for tables.  Hence, the TEMP table namespace is
- * never selected as the creation target.
+ * *nspname_p is set to NULL if there is no explicit schema name.
  */
-Oid
-QualifiedNameGetCreationNamespace(List *names, char **objname_p)
+void
+DeconstructQualifiedName(List *names,
+                                                char **nspname_p,
+                                                char **objname_p)
 {
        char       *catalogname;
        char       *schemaname = NULL;
        char       *objname = NULL;
-       Oid                     namespaceId;
 
-       /* deconstruct the name list */
        switch (length(names))
        {
                case 1:
@@ -1149,6 +1068,55 @@ QualifiedNameGetCreationNamespace(List *names, char **objname_p)
                        break;
        }
 
+       *nspname_p = schemaname;
+       *objname_p = objname;
+}
+
+/*
+ * LookupExplicitNamespace
+ *             Process an explicitly-specified schema name: look up the schema
+ *             and verify we have USAGE (lookup) rights in it.
+ *
+ * Returns the namespace OID.  Raises elog if any problem.
+ */
+Oid
+LookupExplicitNamespace(char *nspname)
+{
+       Oid                     namespaceId;
+       AclResult       aclresult;
+
+       namespaceId = GetSysCacheOid(NAMESPACENAME,
+                                                                CStringGetDatum(nspname),
+                                                                0, 0, 0);
+       if (!OidIsValid(namespaceId))
+               elog(ERROR, "Namespace \"%s\" does not exist", nspname);
+
+       aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
+       if (aclresult != ACLCHECK_OK)
+               aclcheck_error(aclresult, nspname);
+
+       return namespaceId;
+}
+
+/*
+ * QualifiedNameGetCreationNamespace
+ *             Given a possibly-qualified name for an object (in List-of-Values
+ *             format), determine what namespace the object should be created in.
+ *             Also extract and return the object name (last component of list).
+ *
+ * This is *not* used for tables.  Hence, the TEMP table namespace is
+ * never selected as the creation target.
+ */
+Oid
+QualifiedNameGetCreationNamespace(List *names, char **objname_p)
+{
+       char       *schemaname;
+       char       *objname;
+       Oid                     namespaceId;
+
+       /* deconstruct the name list */
+       DeconstructQualifiedName(names, &schemaname, &objname);
+
        if (schemaname)
        {
                /* use exact schema given */
@@ -1158,6 +1126,7 @@ QualifiedNameGetCreationNamespace(List *names, char **objname_p)
                if (!OidIsValid(namespaceId))
                        elog(ERROR, "Namespace \"%s\" does not exist",
                                 schemaname);
+               /* we do not check for USAGE rights here! */
        }
        else
        {
index 83b8af7e6bfd1d0fd1aa464f52df445d6f0ffd7e..c5dee8f8af9a65651b5bcd075a7993894e37cf65 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 1996-2001, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.52 2002/07/20 05:16:57 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.53 2002/07/29 23:46:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,7 +22,6 @@
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_database.h"
 #include "catalog/pg_description.h"
-#include "catalog/pg_namespace.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_trigger.h"
@@ -468,36 +467,28 @@ CommentNamespace(List *qualname, char *comment)
 {
        Oid                     oid;
        Oid                     classoid;
-       HeapTuple       tp;
        char       *namespace;
 
        if (length(qualname) != 1)
                elog(ERROR, "CommentSchema: schema name may not be qualified");
        namespace = strVal(lfirst(qualname));
 
-       tp = SearchSysCache(NAMESPACENAME,
-                                               CStringGetDatum(namespace),
-                                               0, 0, 0);
-       if (!HeapTupleIsValid(tp))
+       oid = GetSysCacheOid(NAMESPACENAME,
+                                                CStringGetDatum(namespace),
+                                                0, 0, 0);
+       if (!OidIsValid(oid))
                elog(ERROR, "CommentSchema: Schema \"%s\" could not be found",
                         namespace);
 
-       /* no TupleDesc here to Assert(...->tdhasoid); */
-       oid = HeapTupleGetOid(tp);
-
        /* Check object security */
        if (!pg_namespace_ownercheck(oid, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, namespace);
 
        /* pg_namespace doesn't have a hard-coded OID, so must look it up */
-       classoid = get_relname_relid(NamespaceRelationName, PG_CATALOG_NAMESPACE);
-       Assert(OidIsValid(classoid));
+       classoid = get_system_catalog_relid(NamespaceRelationName);
 
        /* Call CreateComments() to create/drop the comments */
        CreateComments(oid, classoid, 0, comment);
-
-       /* Cleanup */
-       ReleaseSysCache(tp);
 }
 
 /*
@@ -607,8 +598,7 @@ CommentRule(List *qualname, char *comment)
                aclcheck_error(aclcheck, rulename);
 
        /* pg_rewrite doesn't have a hard-coded OID, so must look it up */
-       classoid = get_relname_relid(RewriteRelationName, PG_CATALOG_NAMESPACE);
-       Assert(OidIsValid(classoid));
+       classoid = get_system_catalog_relid(RewriteRelationName);
 
        /* Call CreateComments() to create/drop the comments */
 
@@ -740,8 +730,7 @@ CommentOperator(List *opername, List *arguments, char *comment)
                aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(opername));
 
        /* pg_operator doesn't have a hard-coded OID, so must look it up */
-       classoid = get_relname_relid(OperatorRelationName, PG_CATALOG_NAMESPACE);
-       Assert(OidIsValid(classoid));
+       classoid = get_system_catalog_relid(OperatorRelationName);
 
        /* Call CreateComments() to create/drop the comments */
        CreateComments(oid, classoid, 0, comment);
index f36bad8ada17fdd7fa6f347dda6fa8a27be76ba4..4049e7435c56a54af4ed4f1e571779b8178d7c66 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.78 2002/07/20 05:16:57 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.79 2002/07/29 23:46:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -410,9 +410,8 @@ static Oid
 GetAttrOpClass(IndexElem *attribute, Oid attrType,
                           char *accessMethodName, Oid accessMethodId)
 {
-       char       *catalogname;
-       char       *schemaname = NULL;
-       char       *opcname = NULL;
+       char       *schemaname;
+       char       *opcname;
        HeapTuple       tuple;
        Oid                     opClassId,
                                opInputType;
@@ -434,42 +433,14 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
         */
 
        /* deconstruct the name list */
-       switch (length(attribute->opclass))
-       {
-               case 1:
-                       opcname = strVal(lfirst(attribute->opclass));
-                       break;
-               case 2:
-                       schemaname = strVal(lfirst(attribute->opclass));
-                       opcname = strVal(lsecond(attribute->opclass));
-                       break;
-               case 3:
-                       catalogname = strVal(lfirst(attribute->opclass));
-                       schemaname = strVal(lsecond(attribute->opclass));
-                       opcname = strVal(lfirst(lnext(lnext(attribute->opclass))));
-                       /*
-                        * We check the catalog name and then ignore it.
-                        */
-                       if (strcmp(catalogname, DatabaseName) != 0)
-                               elog(ERROR, "Cross-database references are not implemented");
-                       break;
-               default:
-                       elog(ERROR, "Improper opclass name (too many dotted names): %s",
-                                NameListToString(attribute->opclass));
-                       break;
-       }
+       DeconstructQualifiedName(attribute->opclass, &schemaname, &opcname);
 
        if (schemaname)
        {
                /* Look in specific schema only */
                Oid             namespaceId;
 
-               namespaceId = GetSysCacheOid(NAMESPACENAME,
-                                                                        CStringGetDatum(schemaname),
-                                                                        0, 0, 0);
-               if (!OidIsValid(namespaceId))
-                       elog(ERROR, "Namespace \"%s\" does not exist",
-                                schemaname);
+               namespaceId = LookupExplicitNamespace(schemaname);
                tuple = SearchSysCache(CLAAMNAMENSP,
                                                           ObjectIdGetDatum(accessMethodId),
                                                           PointerGetDatum(opcname),
index fb86c980b986f4229e760fbf39334e6446f8f686..c56b0e1fa84b0b5f7fcb7605dc2d5a0ed3637f03 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.1 2002/07/29 22:14:10 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.2 2002/07/29 23:46:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -467,10 +467,9 @@ storeProcedures(Oid opclassoid, int numProcs, Oid *procedures)
 void
 RemoveOpClass(RemoveOpClassStmt *stmt)
 {
-       Oid                             amID, opcID;
-       char       *catalogname;
-       char       *schemaname = NULL;
-       char       *opcname = NULL;
+       Oid                     amID, opcID;
+       char       *schemaname;
+       char       *opcname;
        HeapTuple       tuple;
        ObjectAddress object;
 
@@ -489,42 +488,14 @@ RemoveOpClass(RemoveOpClassStmt *stmt)
         */
 
        /* deconstruct the name list */
-       switch (length(stmt->opclassname))
-       {
-               case 1:
-                       opcname = strVal(lfirst(stmt->opclassname));
-                       break;
-               case 2:
-                       schemaname = strVal(lfirst(stmt->opclassname));
-                       opcname = strVal(lsecond(stmt->opclassname));
-                       break;
-               case 3:
-                       catalogname = strVal(lfirst(stmt->opclassname));
-                       schemaname = strVal(lsecond(stmt->opclassname));
-                       opcname = strVal(lfirst(lnext(lnext(stmt->opclassname))));
-                       /*
-                        * We check the catalog name and then ignore it.
-                        */
-                       if (strcmp(catalogname, DatabaseName) != 0)
-                               elog(ERROR, "Cross-database references are not implemented");
-                       break;
-               default:
-                       elog(ERROR, "Improper opclass name (too many dotted names): %s",
-                                NameListToString(stmt->opclassname));
-                       break;
-       }
+       DeconstructQualifiedName(stmt->opclassname, &schemaname, &opcname);
 
        if (schemaname)
        {
                /* Look in specific schema only */
                Oid             namespaceId;
 
-               namespaceId = GetSysCacheOid(NAMESPACENAME,
-                                                                        CStringGetDatum(schemaname),
-                                                                        0, 0, 0);
-               if (!OidIsValid(namespaceId))
-                       elog(ERROR, "Namespace \"%s\" does not exist",
-                                schemaname);
+               namespaceId = LookupExplicitNamespace(schemaname);
                tuple = SearchSysCache(CLAAMNAMENSP,
                                                           ObjectIdGetDatum(amID),
                                                           PointerGetDatum(opcname),
index 7eafe3e7c84bdef8a2b04263b45b7d9b63938474..159428894e47bf886a4a277e07d481f0aeb0366b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.45 2002/07/20 05:16:58 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.46 2002/07/29 23:46:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -99,35 +99,11 @@ LookupTypeName(const TypeName *typename)
        else
        {
                /* Normal reference to a type name */
-               char       *catalogname;
-               char       *schemaname = NULL;
-               char       *typname = NULL;
+               char       *schemaname;
+               char       *typname;
 
                /* deconstruct the name list */
-               switch (length(typename->names))
-               {
-                       case 1:
-                               typname = strVal(lfirst(typename->names));
-                               break;
-                       case 2:
-                               schemaname = strVal(lfirst(typename->names));
-                               typname = strVal(lsecond(typename->names));
-                               break;
-                       case 3:
-                               catalogname = strVal(lfirst(typename->names));
-                               schemaname = strVal(lsecond(typename->names));
-                               typname = strVal(lfirst(lnext(lnext(typename->names))));
-                               /*
-                                * We check the catalog name and then ignore it.
-                                */
-                               if (strcmp(catalogname, DatabaseName) != 0)
-                                       elog(ERROR, "Cross-database references are not implemented");
-                               break;
-                       default:
-                               elog(ERROR, "Improper type name (too many dotted names): %s",
-                                        NameListToString(typename->names));
-                               break;
-               }
+               DeconstructQualifiedName(typename->names, &schemaname, &typname);
 
                /* If an array reference, look up the array type instead */
                if (typename->arrayBounds != NIL)
@@ -138,12 +114,7 @@ LookupTypeName(const TypeName *typename)
                        /* Look in specific schema only */
                        Oid             namespaceId;
 
-                       namespaceId = GetSysCacheOid(NAMESPACENAME,
-                                                                                CStringGetDatum(schemaname),
-                                                                                0, 0, 0);
-                       if (!OidIsValid(namespaceId))
-                               elog(ERROR, "Namespace \"%s\" does not exist",
-                                        schemaname);
+                       namespaceId = LookupExplicitNamespace(schemaname);
                        restype = GetSysCacheOid(TYPENAMENSP,
                                                                         PointerGetDatum(typname),
                                                                         ObjectIdGetDatum(namespaceId),
index 5341027c0716d4653831b2bd3f69bfb2e8688157..bd0f176f28a88fb5ce59d3bca19d829a8fbd6b5b 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: namespace.h,v 1.16 2002/07/16 06:58:13 ishii Exp $
+ * $Id: namespace.h,v 1.17 2002/07/29 23:46:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -66,6 +66,11 @@ extern OpclassCandidateList OpclassGetCandidates(Oid amid);
 extern Oid     OpclassnameGetOpcid(Oid amid, const char *opcname);
 extern bool OpclassIsVisible(Oid opcid);
 
+extern void DeconstructQualifiedName(List *names,
+                                                                        char **nspname_p,
+                                                                        char **objname_p);
+extern Oid     LookupExplicitNamespace(char *nspname);
+
 extern Oid     QualifiedNameGetCreationNamespace(List *names, char **objname_p);
 extern RangeVar *makeRangeVarFromNameList(List *names);
 extern char *NameListToString(List *names);