*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
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
/*
* 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
{
/*
* 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);
+ }
}
/*