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.
This commit is contained in:
parent
330b4e4215
commit
e0a1ee2053
|
@ -15,7 +15,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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");
|
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 */
|
/* Public */
|
||||||
void
|
void
|
||||||
RestoreArchive(Archive *AHX, RestoreOptions *ropt)
|
RestoreArchive(Archive *AHX, RestoreOptions *ropt)
|
||||||
|
@ -453,7 +357,6 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
|
||||||
/* NULL parameter means disable ALL user triggers */
|
/* NULL parameter means disable ALL user triggers */
|
||||||
_disableTriggersIfNecessary(AH, NULL, ropt);
|
_disableTriggersIfNecessary(AH, NULL, ropt);
|
||||||
|
|
||||||
Adjust_lo_type(AH);
|
|
||||||
te = AH->toc->next;
|
te = AH->toc->next;
|
||||||
while (te != AH->toc)
|
while (te != AH->toc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Implements the basic DB functions used by the archiver.
|
* Implements the basic DB functions used by the archiver.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
*uRes;
|
||||||
int i,
|
int i,
|
||||||
n;
|
n;
|
||||||
char *attr;
|
|
||||||
|
|
||||||
if (strcmp(te->tag, BLOB_XREF_TABLE) == 0)
|
if (strcmp(te->tag, BLOB_XREF_TABLE) == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -604,7 +603,7 @@ FixupBlobRefs(ArchiveHandle *AH, TocEntry *te)
|
||||||
fmtId(te->tag));
|
fmtId(te->tag));
|
||||||
|
|
||||||
appendPQExpBuffer(tblQry,
|
appendPQExpBuffer(tblQry,
|
||||||
"SELECT a.attname FROM "
|
"SELECT a.attname, t.typname FROM "
|
||||||
"pg_catalog.pg_attribute a, pg_catalog.pg_type t "
|
"pg_catalog.pg_attribute a, pg_catalog.pg_type t "
|
||||||
"WHERE a.attnum > 0 AND a.attrelid = '%s'::pg_catalog.regclass "
|
"WHERE a.attnum > 0 AND a.attrelid = '%s'::pg_catalog.regclass "
|
||||||
"AND a.atttypid = t.oid AND t.typname in ('oid', 'lo')",
|
"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++)
|
for (i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
|
char *attr;
|
||||||
|
char *typname;
|
||||||
|
bool typeisoid;
|
||||||
|
|
||||||
attr = PQgetvalue(res, i, 0);
|
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",
|
ahlog(AH, 1, "fixing large object cross-references for %s.%s\n",
|
||||||
te->tag, attr);
|
te->tag, attr);
|
||||||
|
|
||||||
resetPQExpBuffer(tblQry);
|
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,
|
appendPQExpBuffer(tblQry,
|
||||||
"UPDATE %s SET %s = %s.newOid",
|
"UPDATE %s SET %s = ",
|
||||||
tblName->data, fmtId(attr),
|
|
||||||
BLOB_XREF_TABLE);
|
|
||||||
appendPQExpBuffer(tblQry,
|
|
||||||
" FROM %s WHERE %s.oldOid = %s.%s",
|
|
||||||
BLOB_XREF_TABLE,
|
|
||||||
BLOB_XREF_TABLE,
|
|
||||||
tblName->data, fmtId(attr));
|
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);
|
ahlog(AH, 10, "SQL: %s\n", tblQry->data);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue