Cause pg_dumpall to include GRANT/REVOKE for database-level permissions
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 30 May 2003 22:55:16 +0000 (22:55 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 30 May 2003 22:55:16 +0000 (22:55 +0000)
in its output.  Make it work with server versions back to 7.0, too.

src/bin/pg_dump/dumputils.c
src/bin/pg_dump/dumputils.h
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dumpall.c

index 259a8c5639508be23c91e3b0eefc8442598b311c..6b8bafdb32c79079453055fd3440ca46e58b79cd 100644 (file)
@@ -1,12 +1,13 @@
 /*-------------------------------------------------------------------------
  *
  * Utility routines for SQL dumping
+ * Basically this is stuff that is useful in both pg_dump and pg_dumpall.
+ *
  *
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v 1.3 2002/09/07 16:14:33 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v 1.4 2003/05/30 22:55:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "parser/keywords.h"
 
 
+static bool parseAclItem(const char *item, const char *type, const char *name,
+                        int remoteVersion,
+                        PQExpBuffer grantee, PQExpBuffer grantor,
+                        PQExpBuffer privs, PQExpBuffer privswgo);
+static void AddAcl(PQExpBuffer aclbuf, const char *keyword);
+
 
 /*
  * Quotes input string if it's not a legitimate SQL identifier as-is.
@@ -89,7 +96,6 @@ fmtId(const char *rawid)
 }
 
 
-
 /*
  * Convert a string value to an SQL string literal and append it to
  * the given buffer.
@@ -133,7 +139,9 @@ appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll)
 }
 
 
-
+/*
+ * Convert backend's version string into a number.
+ */
 int
 parse_version(const char *versionString)
 {
@@ -152,3 +160,295 @@ parse_version(const char *versionString)
 
    return (100 * vmaj + vmin) * 100 + vrev;
 }
+
+
+/*
+ * Build GRANT/REVOKE command(s) for an object.
+ *
+ * name: the object name, in the form to use in the commands (already quoted)
+ * type: the object type (as seen in GRANT command: must be one of
+ *     TABLE, FUNCTION, LANGUAGE, or SCHEMA, or DATABASE)
+ * acls: the ACL string fetched from the database
+ * owner: username of object owner (will be passed through fmtId), or NULL
+ * remoteVersion: version of database
+ *
+ * Returns TRUE if okay, FALSE if could not parse the acl string.
+ * The resulting commands (if any) are appended to the contents of 'sql'.
+ *
+ * Note: beware of passing fmtId() result as 'name', since this routine
+ * uses fmtId() internally.
+ */
+bool
+buildACLCommands(const char *name, const char *type,
+                const char *acls, const char *owner,
+                int remoteVersion,
+                PQExpBuffer sql)
+{
+   char       *aclbuf,
+              *tok;
+   PQExpBuffer grantee, grantor, privs, privswgo;
+   bool        found_owner_privs = false;
+
+   if (strlen(acls) == 0)
+       return true;            /* object has default permissions */
+
+   grantee = createPQExpBuffer();
+   grantor = createPQExpBuffer();
+   privs = createPQExpBuffer();
+   privswgo = createPQExpBuffer();
+
+   /*
+    * Always start with REVOKE ALL FROM PUBLIC, so that we don't have to
+    * wire-in knowledge about the default public privileges for different
+    * kinds of objects.
+    */
+   appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM PUBLIC;\n",
+                     type, name);
+
+   /* Make a working copy of acls so we can use strtok */
+   aclbuf = strdup(acls);
+
+   /* Scan comma-separated ACL items */
+   for (tok = strtok(aclbuf, ","); tok != NULL; tok = strtok(NULL, ","))
+   {
+       size_t toklen;
+
+       /*
+        * Token may start with '{' and/or '"'.  Actually only the start
+        * of the string should have '{', but we don't verify that.
+        */
+       if (*tok == '{')
+           tok++;
+       if (*tok == '"')
+           tok++;
+       toklen = strlen(tok);
+       while (toklen >=0 && (tok[toklen-1] == '"' || tok[toklen-1] == '}'))
+           tok[toklen-- - 1] = '\0';
+
+       if (!parseAclItem(tok, type, name, remoteVersion,
+                         grantee, grantor, privs, privswgo))
+           return false;
+
+       if (grantor->len == 0 && owner)
+           printfPQExpBuffer(grantor, "%s", owner);
+
+       if (privs->len > 0 || privswgo->len > 0)
+       {
+           if (owner && strcmp(grantee->data, owner) == 0)
+           {
+               /*
+                * For the owner, the default privilege level is
+                * ALL WITH GRANT OPTION.
+                */
+               found_owner_privs = true;
+               if (strcmp(privswgo->data, "ALL") != 0)
+               {
+                   appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM %s;\n",
+                                     type, name,
+                                     fmtId(grantee->data));
+                   if (privs->len > 0)
+                       appendPQExpBuffer(sql, "GRANT %s ON %s %s TO %s;\n",
+                                         privs->data, type, name,
+                                         fmtId(grantee->data));
+                   if (privswgo->len > 0)
+                       appendPQExpBuffer(sql, "GRANT %s ON %s %s TO %s WITH GRANT OPTION;\n",
+                                         privswgo->data, type, name,
+                                         fmtId(grantee->data));
+               }
+           }
+           else
+           {
+               /*
+                * Otherwise can assume we are starting from no privs.
+                */
+               if (privs->len > 0)
+               {
+                   appendPQExpBuffer(sql, "GRANT %s ON %s %s TO ",
+                                     privs->data, type, name);
+                   if (grantee->len == 0)
+                       appendPQExpBuffer(sql, "PUBLIC;\n");
+                   else if (strncmp(grantee->data, "group ",
+                                    strlen("group ")) == 0)
+                       appendPQExpBuffer(sql, "GROUP %s;\n",
+                                         fmtId(grantee->data + strlen("group ")));
+                   else
+                       appendPQExpBuffer(sql, "%s;\n", fmtId(grantee->data));
+               }
+               if (privswgo->len > 0)
+               {
+                   appendPQExpBuffer(sql, "GRANT %s ON %s %s TO ",
+                                     privswgo->data, type, name);
+                   if (grantee->len == 0)
+                       appendPQExpBuffer(sql, "PUBLIC");
+                   else if (strncmp(grantee->data, "group ",
+                                    strlen("group ")) == 0)
+                       appendPQExpBuffer(sql, "GROUP %s",
+                                         fmtId(grantee->data + strlen("group ")));
+                   else
+                       appendPQExpBuffer(sql, "%s", fmtId(grantee->data));
+                   appendPQExpBuffer(sql, " WITH GRANT OPTION;\n");
+               }
+           }
+       }
+       else
+       {
+           /* No privileges.  Issue explicit REVOKE for safety. */
+           if (grantee->len == 0)
+               ; /* Empty left-hand side means "PUBLIC"; already did it */
+           else if (strncmp(grantee->data, "group ", strlen("group ")) == 0)
+               appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM GROUP %s;\n",
+                                 type, name,
+                                 fmtId(grantee->data + strlen("group ")));
+           else
+               appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM %s;\n",
+                                 type, name, fmtId(grantee->data));
+       }
+   }
+
+   /*
+    * If we didn't find any owner privs, the owner must have revoked 'em
+    * all
+    */
+   if (!found_owner_privs && owner)
+   {
+       appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM %s;\n",
+                         type, name, fmtId(owner));
+   }
+
+   free(aclbuf);
+   destroyPQExpBuffer(grantee);
+   destroyPQExpBuffer(grantor);
+   destroyPQExpBuffer(privs);
+   destroyPQExpBuffer(privswgo);
+
+   return true;
+}
+
+
+/*
+ * This will take an aclitem string of privilege code letters and
+ * parse it into grantee, grantor, and privilege information.  The
+ * privilege information is split between privileges with grant option
+ * (privswgo) and without (privs).
+ *
+ * Note: for cross-version compatibility, it's important to use ALL when
+ * appropriate.
+ */
+static bool
+parseAclItem(const char *item, const char *type, const char *name,
+            int remoteVersion,
+            PQExpBuffer grantee, PQExpBuffer grantor,
+            PQExpBuffer privs, PQExpBuffer privswgo)
+{
+   char       *buf;
+   bool        all_with_go = true;
+   bool        all_without_go = true;
+   char       *eqpos;
+   char       *slpos;
+   char       *pos;
+
+   buf = strdup(item);
+
+   /* user name is string up to = */
+   eqpos = strchr(buf, '=');
+   if (!eqpos)
+       return false;
+   *eqpos = '\0';
+   printfPQExpBuffer(grantee, "%s", buf);
+
+   /* grantor may be listed after / */
+   slpos = strchr(eqpos + 1, '/');
+   if (slpos)
+   {
+       *slpos = '\0';
+       printfPQExpBuffer(grantor, "%s", slpos + 1);
+   }
+   else
+       resetPQExpBuffer(grantor);
+
+   /* privilege codes */
+#define CONVERT_PRIV(code, keywd) \
+   if ((pos = strchr(eqpos + 1, code))) \
+   { \
+       if (*(pos + 1) == '*') \
+       { \
+           AddAcl(privswgo, keywd); \
+           all_without_go = false; \
+       } \
+       else \
+       { \
+           AddAcl(privs, keywd); \
+           all_with_go = false; \
+       } \
+   } \
+   else \
+       all_with_go = all_without_go = false
+
+   resetPQExpBuffer(privs);
+   resetPQExpBuffer(privswgo);
+
+   if (strcmp(type, "TABLE") == 0)
+   {
+       CONVERT_PRIV('a', "INSERT");
+       CONVERT_PRIV('r', "SELECT");
+       CONVERT_PRIV('R', "RULE");
+
+       if (remoteVersion >= 70200)
+       {
+           CONVERT_PRIV('w', "UPDATE");
+           CONVERT_PRIV('d', "DELETE");
+           CONVERT_PRIV('x', "REFERENCES");
+           CONVERT_PRIV('t', "TRIGGER");
+       }
+       else
+       {
+           /* 7.0 and 7.1 have a simpler worldview */
+           CONVERT_PRIV('w', "UPDATE,DELETE");
+       }
+   }
+   else if (strcmp(type, "FUNCTION") == 0)
+       CONVERT_PRIV('X', "EXECUTE");
+   else if (strcmp(type, "LANGUAGE") == 0)
+       CONVERT_PRIV('U', "USAGE");
+   else if (strcmp(type, "SCHEMA") == 0)
+   {
+       CONVERT_PRIV('C', "CREATE");
+       CONVERT_PRIV('U', "USAGE");
+   }
+   else if (strcmp(type, "DATABASE") == 0)
+   {
+       CONVERT_PRIV('C', "CREATE");
+       CONVERT_PRIV('T', "TEMPORARY");
+   }
+   else
+       abort();
+
+#undef CONVERT_PRIV
+
+   if (all_with_go)
+   {
+       resetPQExpBuffer(privs);
+       printfPQExpBuffer(privswgo, "ALL");
+   }
+   else if (all_without_go)
+   {
+       resetPQExpBuffer(privswgo);
+       printfPQExpBuffer(privs, "ALL");
+   }
+
+   free(buf);
+
+   return true;
+}
+
+
+/*
+ * Append a privilege keyword to a keyword list, inserting comma if needed.
+ */
+static void
+AddAcl(PQExpBuffer aclbuf, const char *keyword)
+{
+   if (aclbuf->len > 0)
+       appendPQExpBufferChar(aclbuf, ',');
+   appendPQExpBuffer(aclbuf, "%s", keyword);
+}
index acaff801d880f9a09c80f8421d1fdb8382b6c2c5..41946af31af58932a7e15eca363930a03c31b2c6 100644 (file)
@@ -1,12 +1,13 @@
 /*-------------------------------------------------------------------------
  *
  * Utility routines for SQL dumping
+ * Basically this is stuff that is useful in both pg_dump and pg_dumpall.
+ *
  *
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.h,v 1.4 2002/09/07 16:14:33 petere Exp $
+ * $Id: dumputils.h,v 1.5 2003/05/30 22:55:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef DUMPUTILS_H
 #define DUMPUTILS_H
 
-#include "postgres_fe.h"
-
 #include "pqexpbuffer.h"
 
+
 extern char *simple_prompt(const char *prompt, int maxlen, bool echo);
 
 extern const char *fmtId(const char *identifier);
-extern void appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll);
+extern void appendStringLiteral(PQExpBuffer buf, const char *str,
+                               bool escapeAll);
 extern int parse_version(const char *versionString);
+extern bool buildACLCommands(const char *name, const char *type,
+                            const char *acls, const char *owner,
+                            int remoteVersion,
+                            PQExpBuffer sql);
 
 #endif   /* DUMPUTILS_H */
index 9f5f25bfd4644eb42c1a5a6a0558ed5bb7665e45..90a533c6185e4fb401161756ca10a00bc95a5373 100644 (file)
@@ -12,7 +12,7 @@
  * by PostgreSQL
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.330 2003/05/17 15:53:12 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.331 2003/05/30 22:55:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -116,12 +116,6 @@ static void selectSourceSchema(const char *schemaName);
 static char *getFormattedTypeName(const char *oid, OidOptions opts);
 static char *myFormatType(const char *typname, int32 typmod);
 static const char *fmtQualifiedId(const char *schema, const char *id);
-
-static void AddAcl(PQExpBuffer aclbuf, const char *keyword);
-static void
-parseAclItem(const char *item, const char *type, const char *name, int remoteVersion,
-            PQExpBuffer grantee, PQExpBuffer grantor, PQExpBuffer privs, PQExpBuffer privswgo);
-
 static int dumpBlobs(Archive *AH, char *, void *);
 static int dumpDatabase(Archive *AH);
 static const char *getAttrName(int attrnum, TableInfo *tblInfo);
@@ -2494,7 +2488,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                         "a.attnotnull, a.atthasdef, false as attisdropped, null as attislocal, "
                         "format_type(a.atttypid,a.atttypmod) as atttypname "
                              "from pg_attribute a, pg_type t "
-                             "where a.atttypid = t.oid"
+                             "where a.atttypid = t.oid "
                              "and a.attrelid = '%s'::oid "
                              "and a.attnum > 0::int2 "
                              "order by a.attrelid, a.attnum",
@@ -4943,128 +4937,6 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
 }
 
 
-/*
- * Append a privilege keyword to a keyword list, inserting comma if needed.
- */
-static void
-AddAcl(PQExpBuffer aclbuf, const char *keyword)
-{
-   if (aclbuf->len > 0)
-       appendPQExpBufferChar(aclbuf, ',');
-   appendPQExpBuffer(aclbuf, "%s", keyword);
-}
-
-
-/*
- * This will take an aclitem string of privilege code letters and
- * parse it into grantee, grantor, and privilege information.  The
- * privilege information is split between privileges with grant option
- * (privswgo) and without (privs).
- *
- * Note: for cross-version compatibility, it's important to use ALL when
- * appropriate.
- */
-static void
-parseAclItem(const char *item, const char *type, const char *name, int remoteVersion,
-            PQExpBuffer grantee, PQExpBuffer grantor, PQExpBuffer privs, PQExpBuffer privswgo)
-{
-   char       *buf;
-   bool        all_with_go = true;
-   bool        all_without_go = true;
-   char       *eqpos;
-   char       *slpos;
-   char       *pos;
-
-   buf = strdup(item);
-
-   /* user name is string up to = */
-   eqpos = strchr(buf, '=');
-   if (!eqpos)
-   {
-       write_msg(NULL, "could not parse ACL list (%s) for object %s (%s)\n",
-                 item, name, type);
-       exit_nicely();
-   }
-   *eqpos = '\0';
-   printfPQExpBuffer(grantee, "%s", buf);
-
-   /* grantor may be listed after / */
-   slpos = strchr(eqpos + 1, '/');
-   if (slpos)
-   {
-       *slpos = '\0';
-       printfPQExpBuffer(grantor, "%s", slpos + 1);
-   }
-   else
-       resetPQExpBuffer(grantor);
-
-   /* privilege codes */
-#define CONVERT_PRIV(code, keywd) \
-   if ((pos = strchr(eqpos + 1, code))) \
-   { \
-       if (*(pos + 1) == '*') \
-       { \
-           AddAcl(privswgo, keywd); \
-           all_without_go = false; \
-       } \
-       else \
-       { \
-           AddAcl(privs, keywd); \
-           all_with_go = false; \
-       } \
-   } \
-   else \
-       all_with_go = all_without_go = false
-
-   resetPQExpBuffer(privs);
-   resetPQExpBuffer(privswgo);
-
-   if (strcmp(type, "TABLE") == 0)
-   {
-       CONVERT_PRIV('a', "INSERT");
-       CONVERT_PRIV('r', "SELECT");
-       CONVERT_PRIV('R', "RULE");
-
-       if (remoteVersion >= 70200)
-       {
-           CONVERT_PRIV('w', "UPDATE");
-           CONVERT_PRIV('d', "DELETE");
-           CONVERT_PRIV('x', "REFERENCES");
-           CONVERT_PRIV('t', "TRIGGER");
-       }
-       else
-       {
-           /* 7.0 and 7.1 have a simpler worldview */
-           CONVERT_PRIV('w', "UPDATE,DELETE");
-       }
-   }
-   else if (strcmp(type, "FUNCTION") == 0)
-       CONVERT_PRIV('X', "EXECUTE");
-   else if (strcmp(type, "LANGUAGE") == 0)
-       CONVERT_PRIV('U', "USAGE");
-   else if (strcmp(type, "SCHEMA") == 0)
-   {
-       CONVERT_PRIV('C', "CREATE");
-       CONVERT_PRIV('U', "USAGE");
-   }
-   else
-       abort();
-
-#undef CONVERT_PRIV
-
-   if (all_with_go)
-   {
-       resetPQExpBuffer(privs);
-       printfPQExpBuffer(privswgo, "ALL");
-   }
-   else if (all_without_go)
-   {
-       resetPQExpBuffer(privswgo);
-       printfPQExpBuffer(privs, "ALL");
-   }
-}
-
-
 /*----------
  * Write out grant/revoke information
  *
@@ -5083,10 +4955,7 @@ dumpACL(Archive *fout, const char *type, const char *name,
        const char *tag, const char *nspname, const char *owner,
        const char *acls, const char *objoid)
 {
-   char       *aclbuf,
-              *tok;
-   PQExpBuffer sql, grantee, grantor, privs, privswgo;
-   bool        found_owner_privs = false;
+   PQExpBuffer sql;
 
        /* acl_lang is a flag only true if we are dumping language's ACL,
         * so we can set 'type' to a value that is suitable to build
@@ -5098,142 +4967,22 @@ dumpACL(Archive *fout, const char *type, const char *name,
        acl_lang = true;
    }
 
-   if (strlen(acls) == 0)
-       return;                 /* object has default permissions */
-
-#define MKENTRY(grantor, command) \
-   ArchiveEntry(fout, objoid, tag, nspname, grantor ? grantor : "", acl_lang ? "ACL LANGUAGE" : "ACL" , NULL, command, "", NULL, NULL, NULL)
-
    sql = createPQExpBuffer();
-   grantee = createPQExpBuffer();
-   grantor = createPQExpBuffer();
-   privs = createPQExpBuffer();
-   privswgo = createPQExpBuffer();
 
-   /*
-    * Always start with REVOKE ALL FROM PUBLIC, so that we don't have to
-    * wire-in knowledge about the default public privileges for different
-    * kinds of objects.
-    */
-   printfPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM PUBLIC;\n",
-                     type, name);
-   MKENTRY(owner, sql->data);
-
-   /* Make a working copy of acls so we can use strtok */
-   aclbuf = strdup(acls);
-
-   /* Scan comma-separated ACL items */
-   for (tok = strtok(aclbuf, ","); tok != NULL; tok = strtok(NULL, ","))
+   if (!buildACLCommands(name, type, acls, owner, fout->remoteVersion, sql))
    {
-       size_t toklen;
-
-       resetPQExpBuffer(sql);
-
-       /*
-        * Token may start with '{' and/or '"'.  Actually only the start
-        * of the string should have '{', but we don't verify that.
-        */
-       if (*tok == '{')
-           tok++;
-       if (*tok == '"')
-           tok++;
-       toklen = strlen(tok);
-       while (toklen >=0 && (tok[toklen-1] == '"' || tok[toklen-1] == '}'))
-           tok[toklen-- - 1] = '\0';
-
-       parseAclItem(tok, type, name, fout->remoteVersion,
-                    grantee, grantor, privs, privswgo);
-       if (grantor->len == 0 && owner)
-           printfPQExpBuffer(grantor, "%s", owner);
-
-       if (privs->len > 0 || privswgo->len > 0)
-       {
-           if (owner && strcmp(grantee->data, owner) == 0)
-           {
-               /*
-                * For the owner, the default privilege level is ALL WITH GRANT OPTION.
-                */
-               found_owner_privs = true;
-               if (strcmp(privswgo->data, "ALL") != 0)
-               {
-                   appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM %s;\n",
-                                     type, name, fmtId(grantee->data));
-                   if (privs->len > 0)
-                       appendPQExpBuffer(sql, "GRANT %s ON %s %s TO %s;\n",
-                                         privs->data, type, name, fmtId(grantee->data));
-                   if (privswgo->len > 0)
-                       appendPQExpBuffer(sql, "GRANT %s ON %s %s TO %s WITH GRANT OPTION;\n",
-                                         privswgo->data, type, name, fmtId(grantee->data));
-               }
-           }
-           else
-           {
-               /*
-                * Otherwise can assume we are starting from no privs.
-                */
-               if (privs->len > 0)
-               {
-                   appendPQExpBuffer(sql, "GRANT %s ON %s %s TO ",
-                                     privs->data, type, name);
-                   if (grantee->len == 0)
-                       appendPQExpBuffer(sql, "PUBLIC;\n");
-                   else if (strncmp(grantee->data, "group ", strlen("group ")) == 0)
-                       appendPQExpBuffer(sql, "GROUP %s;\n",
-                                         fmtId(grantee->data + strlen("group ")));
-                   else
-                       appendPQExpBuffer(sql, "%s;\n", fmtId(grantee->data));
-               }
-               if (privswgo->len > 0)
-               {
-                   appendPQExpBuffer(sql, "GRANT %s ON %s %s TO ",
-                                     privswgo->data, type, name);
-                   if (grantee->len == 0)
-                       appendPQExpBuffer(sql, "PUBLIC");
-                   else if (strncmp(grantee->data, "group ", strlen("group ")) == 0)
-                       appendPQExpBuffer(sql, "GROUP %s",
-                                         fmtId(grantee->data + strlen("group ")));
-                   else
-                       appendPQExpBuffer(sql, "%s", fmtId(grantee->data));
-                   appendPQExpBuffer(sql, " WITH GRANT OPTION;\n");
-               }
-           }
-       }
-       else
-       {
-           /* No privileges.  Issue explicit REVOKE for safety. */
-           if (grantee->len == 0)
-               ; /* Empty left-hand side means "PUBLIC"; already did it */
-           else if (strncmp(grantee->data, "group ", strlen("group ")) == 0)
-               appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM GROUP %s;\n",
-                                 type, name,
-                                 fmtId(grantee->data + strlen("group ")));
-           else
-               appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM %s;\n",
-                                 type, name, fmtId(grantee->data));
-       }
-
-       if (sql->len > 0)
-           MKENTRY(grantor->data, sql->data);
+       write_msg(NULL, "could not parse ACL list (%s) for object %s (%s)\n",
+                 acls, name, type);
+       exit_nicely();
    }
 
-   /*
-    * If we didn't find any owner privs, the owner must have revoked 'em
-    * all
-    */
-   if (!found_owner_privs && owner)
-   {
-       printfPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM %s;\n",
-                         type, name, fmtId(owner));
-       MKENTRY(owner, sql->data);
-   }
+   if (sql->len > 0)
+       ArchiveEntry(fout, objoid, tag, nspname,
+                    owner ? owner : "",
+                    acl_lang ? "ACL LANGUAGE" : "ACL",
+                    NULL, sql->data, "", NULL, NULL, NULL);
 
-   free(aclbuf);
    destroyPQExpBuffer(sql);
-   destroyPQExpBuffer(grantee);
-   destroyPQExpBuffer(grantor);
-   destroyPQExpBuffer(privs);
-   destroyPQExpBuffer(privswgo);
-#undef MKENTRY
 }
 
 
index f9db6dfdec1377adf4c63035858718cba9965aeb..7737c8fa129e386dd9594d56f3db0fd9e235beca 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.18 2003/05/14 03:26:02 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.19 2003/05/30 22:55:16 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -248,10 +248,18 @@ dumpUsers(PGconn *conn)
    printf("--\n-- Users\n--\n\n");
    printf("DELETE FROM pg_shadow WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');\n\n");
 
-   res = executeQuery(conn,
-                      "SELECT usename, usesysid, passwd, usecreatedb, usesuper, CAST(valuntil AS timestamp) "
-                      "FROM pg_shadow "
-                      "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');");
+   if (server_version >= 70100)
+       res = executeQuery(conn,
+                          "SELECT usename, usesysid, passwd, usecreatedb, "
+                          "usesuper, CAST(valuntil AS timestamp) "
+                          "FROM pg_shadow "
+                          "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0')");
+   else
+       res = executeQuery(conn,
+                          "SELECT usename, usesysid, passwd, usecreatedb, "
+                          "usesuper, CAST(valuntil AS timestamp) "
+                          "FROM pg_shadow "
+                          "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template1')");
 
    for (i = 0; i < PQntuples(res); i++)
    {
@@ -280,7 +288,8 @@ dumpUsers(PGconn *conn)
            appendPQExpBuffer(buf, " NOCREATEUSER");
 
        if (!PQgetisnull(res, i, 5))
-           appendPQExpBuffer(buf, " VALID UNTIL '%s'", PQgetvalue(res, i, 5));
+           appendPQExpBuffer(buf, " VALID UNTIL '%s'",
+                             PQgetvalue(res, i, 5));
 
        appendPQExpBuffer(buf, ";\n");
 
@@ -309,7 +318,7 @@ dumpGroups(PGconn *conn)
    printf("--\n-- Groups\n--\n\n");
    printf("DELETE FROM pg_group;\n\n");
 
-   res = executeQuery(conn, "SELECT groname, grosysid, grolist FROM pg_group;");
+   res = executeQuery(conn, "SELECT groname, grosysid, grolist FROM pg_group");
 
    for (i = 0; i < PQntuples(res); i++)
    {
@@ -374,11 +383,38 @@ dumpCreateDB(PGconn *conn)
 
    printf("--\n-- Database creation\n--\n\n");
 
-   /*
-    * Basically this query returns: dbname, dbowner, encoding,
-    * istemplate, dbpath
-    */
-   res = executeQuery(conn, "SELECT datname, coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), pg_encoding_to_char(d.encoding), datistemplate, datpath FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) WHERE datallowconn ORDER BY 1;");
+   if (server_version >= 70300)
+       res = executeQuery(conn,
+                          "SELECT datname, "
+                          "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
+                          "pg_encoding_to_char(d.encoding), "
+                          "datistemplate, datpath, datacl "
+                          "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
+                          "WHERE datallowconn ORDER BY 1");
+   else if (server_version >= 70100)
+       res = executeQuery(conn,
+                          "SELECT datname, "
+                          "coalesce("
+                          "(select usename from pg_shadow where usesysid=datdba), "
+                          "(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
+                          "pg_encoding_to_char(d.encoding), "
+                          "datistemplate, datpath, '' as datacl "
+                          "FROM pg_database d "
+                          "WHERE datallowconn ORDER BY 1");
+   else
+   {
+       /*
+        * Note: 7.0 fails to cope with sub-select in COALESCE, so just
+        * deal with getting a NULL by not printing any OWNER clause.
+        */
+       res = executeQuery(conn,
+                          "SELECT datname, "
+                          "(select usename from pg_shadow where usesysid=datdba), "
+                          "pg_encoding_to_char(d.encoding), "
+                          "'f' as datistemplate, datpath, '' as datacl "
+                          "FROM pg_database d "
+                          "ORDER BY 1");
+   }
 
    for (i = 0; i < PQntuples(res); i++)
    {
@@ -388,19 +424,27 @@ dumpCreateDB(PGconn *conn)
        char       *dbencoding = PQgetvalue(res, i, 2);
        char       *dbistemplate = PQgetvalue(res, i, 3);
        char       *dbpath = PQgetvalue(res, i, 4);
+       char       *dbacl = PQgetvalue(res, i, 5);
+       char       *fdbname;
 
        if (strcmp(dbname, "template1") == 0)
            continue;
 
        buf = createPQExpBuffer();
 
+       /* needed for buildACLCommands() */
+       fdbname = strdup(fmtId(dbname));
+
        if (output_clean)
-           appendPQExpBuffer(buf, "DROP DATABASE %s;\n", fmtId(dbname));
+           appendPQExpBuffer(buf, "DROP DATABASE %s;\n", fdbname);
 
-       appendPQExpBuffer(buf, "CREATE DATABASE %s", fmtId(dbname));
-       appendPQExpBuffer(buf, " WITH OWNER = %s TEMPLATE = template0", fmtId(dbowner));
+       appendPQExpBuffer(buf, "CREATE DATABASE %s", fdbname);
+       if (strlen(dbowner) != 0)
+           appendPQExpBuffer(buf, " WITH OWNER = %s",
+                             fmtId(dbowner));
+       appendPQExpBuffer(buf, " TEMPLATE = template0");
 
-       if (strcmp(dbpath, "") != 0)
+       if (strlen(dbpath) != 0)
        {
            appendPQExpBuffer(buf, " LOCATION = ");
            appendStringLiteral(buf, dbpath, true);
@@ -417,8 +461,19 @@ dumpCreateDB(PGconn *conn)
            appendStringLiteral(buf, dbname, true);
            appendPQExpBuffer(buf, ";\n");
        }
+
+       if (!buildACLCommands(fdbname, "DATABASE", dbacl, dbowner,
+                             server_version, buf))
+       {
+           fprintf(stderr, _("%s: could not parse ACL list (%s) for database %s\n"),
+                   progname, dbacl, fdbname);
+           PQfinish(conn);
+           exit(1);
+       }
+
        printf("%s", buf->data);
        destroyPQExpBuffer(buf);
+       free(fdbname);
 
        if (server_version >= 70300)
            dumpDatabaseConfig(conn, dbname);
@@ -539,7 +594,11 @@ dumpDatabases(PGconn *conn)
    PGresult   *res;
    int         i;
 
-   res = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;");
+   if (server_version >= 70100)
+       res = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1");
+   else
+       res = executeQuery(conn, "SELECT datname FROM pg_database ORDER BY 1");
+
    for (i = 0; i < PQntuples(res); i++)
    {
        int         ret;
@@ -688,6 +747,9 @@ executeQuery(PGconn *conn, const char *query)
 {
    PGresult   *res;
 
+   if (verbose)
+       fprintf(stderr, _("%s: executing %s\n"), progname, query);
+
    res = PQexec(conn, query);
    if (!res ||
        PQresultStatus(res) != PGRES_TUPLES_OK)