From e0a1ee205333ea83604dd3a042f5c53cfc759b9d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 1 Feb 2003 22:06:59 +0000 Subject: [PATCH] Cleaner solution to the problem of loading pre-7.3 dumps containing columns of type lo (see contrib/lo). Rather than hacking the function definitions on-the-fly, just modify the queries issued by FixupBlobRefs so that they work even if CREATE CAST hasn't been issued. --- src/bin/pg_dump/pg_backup_archiver.c | 99 +--------------------------- src/bin/pg_dump/pg_backup_db.c | 51 ++++++++++---- 2 files changed, 41 insertions(+), 109 deletions(-) diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 52202c7df5..9c8eaaf14e 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.66 2003/01/27 00:23:38 tgl Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.67 2003/02/01 22:06:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -122,102 +122,6 @@ CloseArchive(Archive *AHX) die_horribly(AH, modulename, "could not close the output file in CloseArchive\n"); } -/* - * This function repairs a slip when upgrading PG cast - * mechanism from 7.2 or earlier to 7.3 or later. - * The casts between lo and oid are needed when retrieving - * lo type data in FixupBlobRefs and so adjust lo type in - * contrib before processing FixupBlobRefs. - */ -static void -Adjust_lo_type(ArchiveHandle *AH) -{ - PGresult *res; - int nTuples; - - /* - * First check the existence of the cast oid as lo. - */ - res = PQexec(AH->blobConnection, "select 1 from pg_cast where" - " castsource in (select oid from pg_type where typname = 'oid')" - " and casttarget in (select oid from pg_type where typname = 'lo')"); - - if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) - die_horribly(AH, modulename, "error while checking the cast oid as lo\n"); - nTuples = PQntuples(res); - PQclear(res); - if (nTuples == 0) - { - /* - * Check the existence of the cast function lo(oid) - * and change it to be IMMUTABLE. - */ - res = PQexec(AH->blobConnection, "update pg_proc set provolatile = 'i'" - " where proname = 'lo'" - " and pronargs = 1" - " and prorettype in (select oid from pg_type where typname = 'lo')" - " and proargtypes[0] in (select oid from pg_type where typname = 'oid')"); - - if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) - die_horribly(AH, modulename, "could not adjust lo(oid) function\n"); - nTuples = atoi(PQcmdTuples(res)); - PQclear(res); - if (nTuples == 1) - { - /* - * The cast function lo(oid) exists and - * then create the correspoding cast. - */ - res = PQexec(AH->blobConnection, "create cast" - " (oid as lo) with function lo(oid) as implicit"); - if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) - die_horribly(AH, modulename, "couldn't create cast (oid as lo)\n"); - PQclear(res); - } - } - - /* - * Also check the existence of the cast lo as oid. - */ - res = PQexec(AH->blobConnection, "select 1 from pg_cast where" - " castsource in (select oid from pg_type where typname = 'lo')" - " and casttarget in (select oid from pg_type where typname = 'oid')"); - - if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) - die_horribly(AH, modulename, "error while checking the cast lo as oid\n"); - nTuples = PQntuples(res); - PQclear(res); - if (nTuples == 0) - { - /* - * Check the existence of the cast function oid(lo) - * and change it to be IMMUTABLE. - */ - res = PQexec(AH->blobConnection, "update pg_proc set provolatile = 'i'" - " where proname = 'oid'" - " and pronargs = 1" - " and prorettype in (select oid from pg_type where typname = 'oid')" - " and proargtypes[0] in (select oid from pg_type where typname = 'lo')"); - - if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) - die_horribly(AH, modulename, "could not adjust oid(lo) function\n"); - nTuples = atoi(PQcmdTuples(res)); - PQclear(res); - if (nTuples == 1) - { - /* - * The cast function oid(lo) exists and - * then create the correspoding cast. - */ - res = PQexec(AH->blobConnection, "create cast" - " (lo as oid) with function oid(lo) as implicit"); - if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) - die_horribly(AH, modulename, "couldn't create cast (lo as oid)\n"); - PQclear(res); - } - } -} - /* Public */ void RestoreArchive(Archive *AHX, RestoreOptions *ropt) @@ -453,7 +357,6 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt) /* NULL parameter means disable ALL user triggers */ _disableTriggersIfNecessary(AH, NULL, ropt); - Adjust_lo_type(AH); te = AH->toc->next; while (te != AH->toc) { diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c index 93a8137431..d5ed76d910 100644 --- a/src/bin/pg_dump/pg_backup_db.c +++ b/src/bin/pg_dump/pg_backup_db.c @@ -5,7 +5,7 @@ * Implements the basic DB functions used by the archiver. * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.43 2002/10/22 19:15:23 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.44 2003/02/01 22:06:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -589,7 +589,6 @@ FixupBlobRefs(ArchiveHandle *AH, TocEntry *te) *uRes; int i, n; - char *attr; if (strcmp(te->tag, BLOB_XREF_TABLE) == 0) return; @@ -604,7 +603,7 @@ FixupBlobRefs(ArchiveHandle *AH, TocEntry *te) fmtId(te->tag)); appendPQExpBuffer(tblQry, - "SELECT a.attname FROM " + "SELECT a.attname, t.typname FROM " "pg_catalog.pg_attribute a, pg_catalog.pg_type t " "WHERE a.attnum > 0 AND a.attrelid = '%s'::pg_catalog.regclass " "AND a.atttypid = t.oid AND t.typname in ('oid', 'lo')", @@ -623,23 +622,53 @@ FixupBlobRefs(ArchiveHandle *AH, TocEntry *te) for (i = 0; i < n; i++) { + char *attr; + char *typname; + bool typeisoid; + attr = PQgetvalue(res, i, 0); + typname = PQgetvalue(res, i, 1); + + typeisoid = (strcmp(typname, "oid") == 0); ahlog(AH, 1, "fixing large object cross-references for %s.%s\n", te->tag, attr); resetPQExpBuffer(tblQry); - /* Can't use fmtId twice in one call... */ + /* + * Note: we use explicit typename() cast style here because if we + * are dealing with a dump from a pre-7.3 database containing LO + * columns, the dump probably will not have CREATE CAST commands + * for lo<->oid conversions. What it will have is functions, + * which we will invoke as functions. + */ + + /* Can't use fmtId more than once per call... */ appendPQExpBuffer(tblQry, - "UPDATE %s SET %s = %s.newOid", - tblName->data, fmtId(attr), - BLOB_XREF_TABLE); - appendPQExpBuffer(tblQry, - " FROM %s WHERE %s.oldOid = %s.%s", - BLOB_XREF_TABLE, - BLOB_XREF_TABLE, + "UPDATE %s SET %s = ", tblName->data, fmtId(attr)); + if (typeisoid) + appendPQExpBuffer(tblQry, + "%s.newOid", + BLOB_XREF_TABLE); + else + appendPQExpBuffer(tblQry, + "%s(%s.newOid)", + fmtId(typname), + BLOB_XREF_TABLE); + appendPQExpBuffer(tblQry, + " FROM %s WHERE %s.oldOid = ", + BLOB_XREF_TABLE, + BLOB_XREF_TABLE); + if (typeisoid) + appendPQExpBuffer(tblQry, + "%s.%s", + tblName->data, fmtId(attr)); + else + appendPQExpBuffer(tblQry, + "oid(%s.%s)", + tblName->data, fmtId(attr)); ahlog(AH, 10, "SQL: %s\n", tblQry->data);