]> granicus.if.org Git - postgresql/commitdiff
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)