diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index fb799db71b..51f68f2bab 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -252,6 +252,9 @@ void RestoreArchive(Archive* AHX, RestoreOptions *ropt) */ if (_canRestoreBlobs(AH) && AH->createdBlobXref) { + /* NULL parameter means disable ALL user triggers */ + _disableTriggers(AH, NULL, ropt); + te = AH->toc->next; while (te != AH->toc) { @@ -275,6 +278,9 @@ void RestoreArchive(Archive* AHX, RestoreOptions *ropt) te = te->next; } + + /* NULL parameter means enable ALL user triggers */ + _enableTriggers(AH, NULL, ropt); } /* @@ -335,13 +341,16 @@ static void _disableTriggers(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ro */ if (ropt->superuser) { - /* If we're not allowing changes for ownership, then remember the user - * so we can change it back here. Otherwise, let _reconnectAsOwner - * do what it has to do. - */ - if (ropt->noOwner) - oldUser = strdup(ConnectedUser(AH)); - _reconnectAsUser(AH, "-", ropt->superuser); + if (!_restoringToDB(AH) || !ConnectedUserIsSuperuser(AH)) + { + /* If we're not allowing changes for ownership, then remember the user + * so we can change it back here. Otherwise, let _reconnectAsOwner + * do what it has to do. + */ + if (ropt->noOwner) + oldUser = strdup(ConnectedUser(AH)); + _reconnectAsUser(AH, "-", ropt->superuser); + } } ahlog(AH, 1, "Disabling triggers\n"); @@ -351,7 +360,16 @@ static void _disableTriggers(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ro * command when one is available. */ ahprintf(AH, "-- Disable triggers\n"); - ahprintf(AH, "UPDATE \"pg_class\" SET \"reltriggers\" = 0 WHERE \"relname\" !~ '^pg_';\n\n"); + + /* + * Just update the AFFECTED table, if known. + */ + + if (te && te->name && strlen(te->name) > 0) + ahprintf(AH, "UPDATE \"pg_class\" SET \"reltriggers\" = 0 WHERE \"relname\" ~* '%s';\n", + te->name); + else + ahprintf(AH, "UPDATE \"pg_class\" SET \"reltriggers\" = 0 WHERE \"relname\" !~ '^pg_';\n\n"); /* * Restore the user connection from the start of this procedure @@ -378,14 +396,17 @@ static void _enableTriggers(ArchiveHandle *AH, TocEntry *te, RestoreOptions *rop */ if (ropt->superuser) { - /* If we're not allowing changes for ownership, then remember the user - * so we can change it back here. Otherwise, let _reconnectAsOwner - * do what it has to do - */ - if (ropt->noOwner) - oldUser = strdup(ConnectedUser(AH)); + if (!_restoringToDB(AH) || !ConnectedUserIsSuperuser(AH)) + { + /* If we're not allowing changes for ownership, then remember the user + * so we can change it back here. Otherwise, let _reconnectAsOwner + * do what it has to do + */ + if (ropt->noOwner) + oldUser = strdup(ConnectedUser(AH)); - _reconnectAsUser(AH, "-", ropt->superuser); + _reconnectAsUser(AH, "-", ropt->superuser); + } } ahlog(AH, 1, "Enabling triggers\n"); @@ -397,9 +418,19 @@ static void _enableTriggers(ArchiveHandle *AH, TocEntry *te, RestoreOptions *rop ahprintf(AH, "-- Enable triggers\n"); ahprintf(AH, "BEGIN TRANSACTION;\n"); ahprintf(AH, "CREATE TEMP TABLE \"tr\" (\"tmp_relname\" name, \"tmp_reltriggers\" smallint);\n"); - ahprintf(AH, "INSERT INTO \"tr\" SELECT C.\"relname\", count(T.\"oid\") FROM \"pg_class\" C," - " \"pg_trigger\" T WHERE C.\"oid\" = T.\"tgrelid\" AND C.\"relname\" !~ '^pg_' " - " GROUP BY 1;\n"); + + /* + * Just update the affected table, if known. + */ + if (te && te->name && strlen(te->name) > 0) + ahprintf(AH, "INSERT INTO \"tr\" SELECT C.\"relname\", count(T.\"oid\") FROM \"pg_class\" C," + " \"pg_trigger\" T WHERE C.\"oid\" = T.\"tgrelid\" AND C.\"relname\" ~* '%s' " + " GROUP BY 1;\n", te->name); + else + ahprintf(AH, "INSERT INTO \"tr\" SELECT C.\"relname\", count(T.\"oid\") FROM \"pg_class\" C," + " \"pg_trigger\" T WHERE C.\"oid\" = T.\"tgrelid\" AND C.\"relname\" !~ '^pg_' " + " GROUP BY 1;\n"); + ahprintf(AH, "UPDATE \"pg_class\" SET \"reltriggers\" = TMP.\"tmp_reltriggers\" " "FROM \"tr\" TMP WHERE " "\"pg_class\".\"relname\" = TMP.\"tmp_relname\";\n"); @@ -580,7 +611,7 @@ void StartRestoreBlob(ArchiveHandle* AH, int oid) if (loOid == 0) die_horribly(AH, "%s: unable to create BLOB\n", progname); - ahlog(AH, 1, "Restoring BLOB oid %d as %d\n", oid, loOid); + ahlog(AH, 2, "Restoring BLOB oid %d as %d\n", oid, loOid); InsertBlobXref(AH, oid, loOid); diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h index f200526879..6eb1860432 100644 --- a/src/bin/pg_dump/pg_backup_archiver.h +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -59,7 +59,7 @@ typedef z_stream *z_streamp; #define K_VERS_MAJOR 1 #define K_VERS_MINOR 4 -#define K_VERS_REV 8 +#define K_VERS_REV 10 /* Data block types */ #define BLK_DATA 1 diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c index adf692797c..e2c6039a5f 100644 --- a/src/bin/pg_dump/pg_backup_db.c +++ b/src/bin/pg_dump/pg_backup_db.c @@ -593,21 +593,30 @@ void FixupBlobRefs(ArchiveHandle *AH, char *tablename) ahlog(AH, 1, " - %s.%s\n", tablename, attr); resetPQExpBuffer(tblQry); - appendPQExpBuffer(tblQry, "Update \"%s\" Set \"%s\" = x.newOid From %s x " - "Where x.oldOid = \"%s\".\"%s\";", - tablename, attr, BLOB_XREF_TABLE, tablename, attr); + /* + * We should use coalesce here (rather than 'exists'), but it seems to + * be broken in 7.0.2 (weird optimizer strategy) + */ + appendPQExpBuffer(tblQry, "UPDATE \"%s\" SET \"%s\" = ",tablename, attr); + appendPQExpBuffer(tblQry, " (SELECT x.newOid FROM \"%s\" x WHERE x.oldOid = \"%s\".\"%s\")", + BLOB_XREF_TABLE, tablename, attr); + appendPQExpBuffer(tblQry, " where exists" + "(select * from %s x where x.oldOid = \"%s\".\"%s\");", + BLOB_XREF_TABLE, tablename, attr); - ahlog(AH, 10, " - sql = %s\n", tblQry->data); + ahlog(AH, 10, " - sql:\n%s\n", tblQry->data); uRes = PQexec(AH->blobConnection, tblQry->data); if (!uRes) die_horribly(AH, "%s: could not update attr %s of table %s. Explanation from backend '%s'\n", - progname, attr, tablename, PQerrorMessage(AH->connection)); + progname, attr, tablename, PQerrorMessage(AH->blobConnection)); if ( PQresultStatus(uRes) != PGRES_COMMAND_OK ) - die_horribly(AH, "%s: error while updating attr %s of table %s. Explanation from backend '%s'\n", - progname, attr, tablename, PQerrorMessage(AH->connection)); + die_horribly(AH, "%s: error while updating attr %s of table %s (result = %d)." + " Explanation from backend '%s'\n", + progname, attr, tablename, PQresultStatus(uRes), + PQerrorMessage(AH->blobConnection)); PQclear(uRes); } @@ -631,7 +640,10 @@ void CreateBlobXrefTable(ArchiveHandle* AH) ahlog(AH, 1, "Creating table for BLOBS xrefs\n"); +/* appendPQExpBuffer(qry, "Create Temporary Table %s(oldOid oid, newOid oid);", BLOB_XREF_TABLE); +*/ + appendPQExpBuffer(qry, "Create Table %s(oldOid oid, newOid oid);", BLOB_XREF_TABLE); _executeSqlCommand(AH, AH->blobConnection, qry, "can not create BLOB xref table '" BLOB_XREF_TABLE "'");