OSDN Git Service

Clean up pg_dump's handling of ownership for indexes (including
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 11 Jan 2005 05:14:13 +0000 (05:14 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 11 Jan 2005 05:14:13 +0000 (05:14 +0000)
pkey/unique constraint indexes) and schemas.  Per report from
Michael Fuhr.

src/bin/pg_dump/pg_backup_archiver.c
src/bin/pg_dump/pg_dump.c

index 002e329..2764107 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *             $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.100 2004/11/06 19:36:01 tgl Exp $
+ *             $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.101 2005/01/11 05:14:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,7 +47,7 @@ static char *modulename = gettext_noop("archiver");
 
 static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
                 const int compression, ArchiveMode mode);
-static char *_getObjectFromDropStmt(const char *dropStmt, const char *type);
+static void _getObjectDescription(PQExpBuffer buf, TocEntry *te);
 static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData, bool acl_pass);
 
 
@@ -2363,64 +2363,78 @@ _selectTablespace(ArchiveHandle *AH, const char *tablespace)
        destroyPQExpBuffer(qry);
 }
 
-/**
- * Parses the dropStmt part of a TOC entry and returns
- * a newly allocated string that is the object identifier
- * The caller must free the result.
+/*
+ * Extract an object description for a TOC entry, and append it to buf.
+ *
+ * This is not quite as general as it may seem, since it really only
+ * handles constructing the right thing to put into ALTER ... OWNER TO.
+ *
+ * The whole thing is pretty grotty, but we are kind of stuck since the
+ * information used is all that's available in older dump files.
  */
-static char *
-_getObjectFromDropStmt(const char *dropStmt, const char *type)
+static void
+_getObjectDescription(PQExpBuffer buf, TocEntry *te)
 {
-       /* Chop "DROP" off the front and make a copy */
-       char       *first = strdup(dropStmt + 5);
-       char       *last = first + strlen(first) - 1;           /* Points to the last
-                                                                                                                * real char in extract */
-       char       *buf = NULL;
+       const char *type = te->desc;
 
-       /*
-        * Loop from the end of the string until last char is no longer '\n'
-        * or ';'
-        */
-       while (last >= first && (*last == '\n' || *last == ';'))
-               last--;
+       /* Use ALTER TABLE for views and sequences */
+       if (strcmp(type, "VIEW") == 0 ||
+               strcmp(type, "SEQUENCE") == 0)
+               type = "TABLE";
 
-       /* Insert end of string one place after last */
-       *(last + 1) = '\0';
+       /* We assume CONSTRAINTs are always pkey/unique indexes */
+       if (strcmp(type, "CONSTRAINT") == 0)
+               type = "INDEX";
 
-       /*
-        * Take off CASCADE if necessary.  Only TYPEs seem to have this, but
-        * may as well check for all
-        */
-       if ((last - first) >= 8)
+       /* objects named by a schema and name */
+       if (strcmp(type, "CONVERSION") == 0 ||
+               strcmp(type, "DOMAIN") == 0 ||
+               strcmp(type, "INDEX") == 0 ||
+               strcmp(type, "TABLE") == 0 ||
+               strcmp(type, "TYPE") == 0)
        {
-               if (strcmp(last - 7, " CASCADE") == 0)
-                       last -= 8;
+               appendPQExpBuffer(buf, "%s %s", type, fmtId(te->namespace));
+               appendPQExpBuffer(buf, ".%s", fmtId(te->tag));
+               return;
        }
 
-       /* Insert end of string one place after last */
-       *(last + 1) = '\0';
-
-       /* Special case VIEWs and SEQUENCEs.  They must use ALTER TABLE. */
-       if (strcmp(type, "VIEW") == 0 && (last - first) >= 5)
+       /* objects named by just a name */
+       if (strcmp(type, "DATABASE") == 0 ||
+               strcmp(type, "SCHEMA") == 0)
        {
-               int                     len = 6 + strlen(first + 5) + 1;
-
-               buf = malloc(len);
-               snprintf(buf, len, "TABLE %s", first + 5);
-               free(first);
+               appendPQExpBuffer(buf, "%s %s", type, fmtId(te->tag));
+               return;
        }
-       else if (strcmp(type, "SEQUENCE") == 0 && (last - first) >= 9)
+
+       /*
+        * These object types require additional decoration.  Fortunately,
+        * the information needed is exactly what's in the DROP command.
+        */
+       if (strcmp(type, "AGGREGATE") == 0 ||
+               strcmp(type, "FUNCTION") == 0 ||
+               strcmp(type, "OPERATOR") == 0 ||
+               strcmp(type, "OPERATOR CLASS") == 0)
        {
-               int                     len = 6 + strlen(first + 9) + 1;
+               /* Chop "DROP " off the front and make a modifiable copy */
+               char       *first = strdup(te->dropStmt + 5);
+               char       *last;
+
+               /* point to last character in string */
+               last = first + strlen(first) - 1;
+
+               /* Strip off any ';' or '\n' at the end */
+               while (last >= first && (*last == '\n' || *last == ';'))
+                       last--;
+               *(last + 1) = '\0';
+
+               appendPQExpBufferStr(buf, first);
 
-               buf = malloc(len);
-               snprintf(buf, len, "TABLE %s", first + 9);
                free(first);
+               return;
        }
-       else
-               buf = first;
 
-       return buf;
+       write_msg(modulename, "WARNING: don't know how to set owner for object type %s\n",
+                         type);
 }
 
 static void
@@ -2497,13 +2511,14 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
        /*
         * Actually print the definition.
         *
-        * Really crude hack for suppressing AUTHORIZATION clause of CREATE
-        * SCHEMA when --no-owner mode is selected.  This is ugly, but I see
+        * Really crude hack for suppressing AUTHORIZATION clause that old
+        * pg_dump versions put into CREATE SCHEMA.  We have to do this when
+        * --no-owner mode is selected.  This is ugly, but I see
         * no other good way ...
         */
-       if (AH->ropt && AH->ropt->noOwner && strcmp(te->desc, "SCHEMA") == 0)
+       if (ropt->noOwner && strcmp(te->desc, "SCHEMA") == 0)
        {
-               ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", te->tag);
+               ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
        }
        else
        {
@@ -2513,29 +2528,51 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
 
        /*
         * If we aren't using SET SESSION AUTH to determine ownership, we must
-        * instead issue an ALTER OWNER command.  Ugly, since we have to cons
-        * one up based on the dropStmt.  We don't need this for schemas
-        * (since we use CREATE SCHEMA AUTHORIZATION instead), nor for some
-        * other object types.
+        * instead issue an ALTER OWNER command.  We assume that anything without
+        * a DROP command is not a separately ownable object.  All the categories
+        * with DROP commands must appear in one list or the other.
         */
        if (!ropt->noOwner && !ropt->use_setsessauth &&
-               strlen(te->owner) > 0 && strlen(te->dropStmt) > 0 &&
-               (strcmp(te->desc, "AGGREGATE") == 0 ||
-                strcmp(te->desc, "CONVERSION") == 0 ||
-                strcmp(te->desc, "DATABASE") == 0 ||
-                strcmp(te->desc, "DOMAIN") == 0 ||
-                strcmp(te->desc, "FUNCTION") == 0 ||
-                strcmp(te->desc, "OPERATOR") == 0 ||
-                strcmp(te->desc, "OPERATOR CLASS") == 0 ||
-                strcmp(te->desc, "TABLE") == 0 ||
-                strcmp(te->desc, "TYPE") == 0 ||
-                strcmp(te->desc, "VIEW") == 0 ||
-                strcmp(te->desc, "SEQUENCE") == 0))
-       {
-               char       *temp = _getObjectFromDropStmt(te->dropStmt, te->desc);
-
-               ahprintf(AH, "ALTER %s OWNER TO %s;\n\n", temp, fmtId(te->owner));
-               free(temp);
+               strlen(te->owner) > 0 && strlen(te->dropStmt) > 0)
+       {
+               if (strcmp(te->desc, "AGGREGATE") == 0 ||
+                       strcmp(te->desc, "CONSTRAINT") == 0 ||
+                       strcmp(te->desc, "CONVERSION") == 0 ||
+                       strcmp(te->desc, "DATABASE") == 0 ||
+                       strcmp(te->desc, "DOMAIN") == 0 ||
+                       strcmp(te->desc, "FUNCTION") == 0 ||
+                       strcmp(te->desc, "INDEX") == 0 ||
+                       strcmp(te->desc, "OPERATOR") == 0 ||
+                       strcmp(te->desc, "OPERATOR CLASS") == 0 ||
+                       strcmp(te->desc, "SCHEMA") == 0 ||
+                       strcmp(te->desc, "TABLE") == 0 ||
+                       strcmp(te->desc, "TYPE") == 0 ||
+                       strcmp(te->desc, "VIEW") == 0 ||
+                       strcmp(te->desc, "SEQUENCE") == 0)
+               {
+                       PQExpBuffer temp = createPQExpBuffer();
+
+                       appendPQExpBuffer(temp, "ALTER ");
+                       _getObjectDescription(temp, te);
+                       appendPQExpBuffer(temp, " OWNER TO %s;", fmtId(te->owner));
+                       ahprintf(AH, "%s\n\n", temp->data);
+                       destroyPQExpBuffer(temp);
+               }
+               else if (strcmp(te->desc, "CAST") == 0 ||
+                                strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
+                                strcmp(te->desc, "DEFAULT") == 0 ||
+                                strcmp(te->desc, "FK CONSTRAINT") == 0 ||
+                                strcmp(te->desc, "PROCEDURAL LANGUAGE") == 0 ||
+                                strcmp(te->desc, "RULE") == 0 ||
+                                strcmp(te->desc, "TRIGGER") == 0)
+               {
+                       /* these object types don't have separate owners */
+               }
+               else
+               {
+                       write_msg(modulename, "WARNING: don't know how to set owner for object type %s\n",
+                                         te->desc);
+               }
        }
 
        /*
index 73bc213..a6d6fe5 100644 (file)
@@ -12,7 +12,7 @@
  *     by PostgreSQL
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.398 2005/01/04 22:27:46 tgl Exp $
+ *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.399 2005/01/11 05:14:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -4428,23 +4428,14 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 
        qnspname = strdup(fmtId(nspinfo->dobj.name));
 
-       /*
-        * Note that ownership is shown in the AUTHORIZATION clause, while the
-        * archive entry is listed with empty owner (causing it to be emitted
-        * with SET SESSION AUTHORIZATION DEFAULT). This seems the best way of
-        * dealing with schemas owned by users without CREATE SCHEMA
-        * privilege.  Further hacking has to be applied for --no-owner mode,
-        * though!
-        */
        appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname);
 
-       appendPQExpBuffer(q, "CREATE SCHEMA %s AUTHORIZATION %s;\n",
-                                         qnspname, fmtId(nspinfo->usename));
+       appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname);
 
        ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId,
                                 nspinfo->dobj.name,
                                 NULL, NULL, 
-                                strcmp(nspinfo->dobj.name, "public") == 0 ? nspinfo->usename : "",
+                                nspinfo->usename,
                                 false, "SCHEMA", q->data, delq->data, NULL,
                                 nspinfo->dobj.dependencies, nspinfo->dobj.nDeps,
                                 NULL, NULL);