From 8dc42a3aa2d2c1cfb02d70531088c3bbf4e4aac7 Mon Sep 17 00:00:00 2001 From: Philip Warner Date: Wed, 25 Apr 2001 07:03:20 +0000 Subject: [PATCH] - Fixed CONSTRAINT TRIGGER dump to record tgconstrelid properly - pgsql v7.0 compatbility --- src/bin/pg_dump/pg_backup.h | 11 +- src/bin/pg_dump/pg_backup_archiver.c | 22 +- src/bin/pg_dump/pg_backup_archiver.h | 4 +- src/bin/pg_dump/pg_backup_custom.c | 8 +- src/bin/pg_dump/pg_backup_db.c | 38 ++- src/bin/pg_dump/pg_backup_tar.c | 3 +- src/bin/pg_dump/pg_dump.c | 354 ++++++++++++++++++++++----- src/bin/pg_dump/pg_dump.h | 3 +- 8 files changed, 370 insertions(+), 73 deletions(-) diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index 0bde27b3e5..bf453c73ab 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.10 2001/04/01 05:42:50 pjw Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.11 2001/04/25 07:03:19 pjw Exp $ * * Modifications - 28-Jun-2000 - pjw@rhyme.com.au * @@ -50,6 +50,9 @@ #define atooid(x) ((Oid) strtoul((x), NULL, 10)) #define oidcmp(x,y) ( ((x) < (y) ? -1 : ((x) > (y)) ? 1 : 0) ) #define oideq(x,y) ( (x) == (y) ) +#define oidle(x,y) ( (x) <= (y) ) +#define oidge(x,y) ( (x) >= (y) ) +#define oidzero(x) ( (x) == 0 ) typedef enum _archiveFormat { @@ -66,7 +69,10 @@ typedef enum _archiveFormat */ typedef struct _Archive { - int verbose; + int verbose; + int remoteVersion; + int minRemoteVersion; + int maxRemoteVersion; /* The rest is private */ } Archive; @@ -115,6 +121,7 @@ typedef struct _restoreOptions int limitToList; int compression; + int suppressDumpWarnings; /* Suppress output of WARNING entries to stderr */ } RestoreOptions; /* diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index af98a05dc3..a1faab4b60 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.24 2001/04/14 13:11:03 pjw Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.25 2001/04/25 07:03:19 pjw Exp $ * * Modifications - 28-Jun-2000 - pjw@rhyme.com.au * @@ -169,6 +169,10 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt) if (AH->version < K_VERS_1_3) die_horribly(AH, "Direct database connections are not supported in pre-1.3 archives"); + /* XXX Should get this from the archive */ + AHX->minRemoteVersion = 070100; + AHX->maxRemoteVersion = 999999; + ConnectDatabase(AHX, ropt->dbname, ropt->pghost, ropt->pgport, ropt->requirePassword, ropt->ignoreVersion); @@ -260,6 +264,18 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt) /* Work out what, if anything, we want from this entry */ reqs = _tocEntryRequired(te, ropt); + /* Dump any relevant dump warnings to stderr */ + if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0) + { + if (!ropt->dataOnly && te->defn != NULL && strlen(te->defn) != 0) + { + fprintf(stderr, "%s: Warning from original dump file:\n%s\n", progname, te->defn); + } else if (te->copyStmt != NULL && strlen(te->copyStmt) != 0) + { + fprintf(stderr, "%s: Warning from original dump file:\n%s\n", progname, te->copyStmt); + } + } + if ((reqs & 1) != 0) /* We want the schema */ { /* Reconnect if necessary */ @@ -405,6 +421,7 @@ NewRestoreOptions(void) opts = (RestoreOptions *) calloc(1, sizeof(RestoreOptions)); opts->format = archUnknown; + opts->suppressDumpWarnings = false; return opts; } @@ -1419,7 +1436,8 @@ _discoverArchiveFormat(ArchiveHandle *AH) cnt = fread(sig, 1, 5, fh); if (cnt != 5) - die_horribly(AH, "%s: input file is too short, or is unreadable\n", progname); + die_horribly(AH, "%s: input file is too short, or is unreadable (read %d, expected 5)\n", + progname, cnt); /* Save it, just in case we need it later */ strncpy(&AH->lookahead[0], sig, 5); diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h index c9206af3b1..bb5b03ae1f 100644 --- a/src/bin/pg_dump/pg_backup_archiver.h +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -17,7 +17,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.31 2001/04/14 13:11:03 pjw Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.32 2001/04/25 07:03:19 pjw Exp $ * * Modifications - 28-Jun-2000 - pjw@rhyme.com.au * - Initial version. @@ -68,7 +68,7 @@ typedef z_stream *z_streamp; #define K_VERS_MAJOR 1 #define K_VERS_MINOR 5 -#define K_VERS_REV 3 +#define K_VERS_REV 5 /* Data block types */ #define BLK_DATA 1 diff --git a/src/bin/pg_dump/pg_backup_custom.c b/src/bin/pg_dump/pg_backup_custom.c index b4311e8f87..3e839ca38b 100644 --- a/src/bin/pg_dump/pg_backup_custom.c +++ b/src/bin/pg_dump/pg_backup_custom.c @@ -19,7 +19,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_custom.c,v 1.10 2001/04/01 05:42:51 pjw Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_custom.c,v 1.11 2001/04/25 07:03:19 pjw Exp $ * * Modifications - 28-Jun-2000 - pjw@rhyme.com.au * @@ -786,6 +786,7 @@ _ReadBuf(ArchiveHandle *AH, void *buf, int len) res = fread(buf, 1, len, AH->FH); ctx->filePos += res; + return res; } @@ -854,7 +855,10 @@ _getFilePos(ArchiveHandle *AH, lclContext *ctx) { pos = ftell(AH->FH); if (pos != ctx->filePos) - fprintf(stderr, "Warning: ftell mismatch with filePos\n"); + { + fprintf(stderr, "Warning: ftell mismatch with filePos - filePos used\n"); + pos = ctx->filePos; + } } else pos = ctx->filePos; diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c index 9f46863819..a0d9a2dc5f 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.17 2001/03/23 04:49:55 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.18 2001/04/25 07:03:19 pjw Exp $ * * NOTES * @@ -114,17 +114,36 @@ _prompt_for_password(char *username, char *password) fprintf(stderr, "\n\n"); } +static int +_parse_version(ArchiveHandle *AH, const char* versionString) +{ + int cnt; + int vmaj, vmin, vrev; + + cnt = sscanf(versionString, "%d.%d.%d", &vmaj, &vmin, &vrev); + + if (cnt < 2) + { + die_horribly(AH, "Unable to parse version string: %s\n", versionString); + } + + if (cnt == 2) + vrev = 0; + + return (100 * vmaj + vmin) * 100 + vrev; +} static void _check_database_version(ArchiveHandle *AH, bool ignoreVersion) { PGresult *res; - double myversion; + int myversion; const char *remoteversion_str; - double remoteversion; + int remoteversion; PGconn *conn = AH->connection; - myversion = strtod(PG_VERSION, NULL); + myversion = _parse_version(AH, PG_VERSION); + res = PQexec(conn, "SELECT version()"); if (!res || PQresultStatus(res) != PGRES_TUPLES_OK || @@ -134,8 +153,14 @@ _check_database_version(ArchiveHandle *AH, bool ignoreVersion) "Explanation from backend: '%s'.\n", PQerrorMessage(conn)); remoteversion_str = PQgetvalue(res, 0, 0); - remoteversion = strtod(remoteversion_str + 11, NULL); - if (myversion != remoteversion) + remoteversion = _parse_version(AH, remoteversion_str + 11); + + PQclear(res); + + AH->public.remoteVersion = remoteversion; + + if (myversion != remoteversion + && (remoteversion < AH->public.minRemoteVersion || remoteversion > AH->public.maxRemoteVersion) ) { fprintf(stderr, "Database version: %s\n%s version: %s\n", remoteversion_str, progname, PG_VERSION); @@ -145,7 +170,6 @@ _check_database_version(ArchiveHandle *AH, bool ignoreVersion) die_horribly(AH, "Aborting because of version mismatch.\n" "Use --ignore-version if you think it's safe to proceed anyway.\n"); } - PQclear(res); } /* diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c index 93afbefb54..8c67141cd3 100644 --- a/src/bin/pg_dump/pg_backup_tar.c +++ b/src/bin/pg_dump/pg_backup_tar.c @@ -16,7 +16,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_tar.c,v 1.14 2001/04/14 13:11:03 pjw Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_tar.c,v 1.15 2001/04/25 07:03:19 pjw Exp $ * * Modifications - 28-Jun-2000 - pjw@rhyme.com.au * @@ -834,6 +834,7 @@ _CloseArchive(ArchiveHandle *AH) ropt->dropSchema = 1; ropt->compression = 0; ropt->superuser = PQuser(AH->connection); + ropt->suppressDumpWarnings = true; savVerbose = AH->public.verbose; AH->public.verbose = 0; diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 3d8eb7b1ff..b06ee7f58b 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -22,7 +22,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.204 2001/04/23 23:36:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.205 2001/04/25 07:03:19 pjw Exp $ * * Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb * @@ -185,7 +185,8 @@ static void formatStringLiteral(PQExpBuffer buf, const char *str, const formatLi static void clearTableInfo(TableInfo *, int); static void dumpOneFunc(Archive *fout, FuncInfo *finfo, int i, TypeInfo *tinfo, int numTypes); -static Oid findLastBuiltinOid(const char *); +static Oid findLastBuiltinOid_V71(const char *); +static Oid findLastBuiltinOid_V70(void); static void setMaxOid(Archive *fout); static void AddAcl(char *aclbuf, const char *keyword); @@ -495,8 +496,13 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv) int tuple; int field; - appendPQExpBuffer(q, "SELECT * FROM ONLY %s", - fmtId(classname, force_quotes)); + if (fout->remoteVersion >= 70100) + { + appendPQExpBuffer(q, "SELECT * FROM ONLY %s", fmtId(classname, force_quotes)); + } else { + appendPQExpBuffer(q, "SELECT * FROM %s", fmtId(classname, force_quotes)); + } + res = PQexec(g_conn, q->data); if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) @@ -1037,8 +1043,10 @@ main(int argc, char **argv) /* * Open the database using the Archiver, so it knows about it. Errors - * mean death + * mean death. Accept 7.0 & 7.1 database versions. */ + g_fout->minRemoteVersion = 70000; + g_fout->maxRemoteVersion = 70199; g_conn = ConnectDatabase(g_fout, dbname, pghost, pgport, use_password, ignore_version); /* @@ -1061,7 +1069,10 @@ main(int argc, char **argv) PQclear(res); } - g_last_builtin_oid = findLastBuiltinOid(dbname); + if (g_fout->remoteVersion >= 70100) + g_last_builtin_oid = findLastBuiltinOid_V71(dbname); + else + g_last_builtin_oid = findLastBuiltinOid_V70(); /* Dump the database definition */ if (!dataOnly) @@ -1120,6 +1131,8 @@ main(int argc, char **argv) else ropt->compression = compressLevel; + ropt->suppressDumpWarnings = true; /* We've already shown them */ + RestoreArchive(g_fout, ropt); } @@ -1210,7 +1223,12 @@ dumpBlobs(Archive *AH, char *junkOid, void *junkVal) fprintf(stderr, "%s saving BLOBs\n", g_comment_start); /* Cursor to get all BLOB tables */ - appendPQExpBuffer(oidQry, "Declare blobOid Cursor for SELECT DISTINCT loid FROM pg_largeobject"); + if (AH->remoteVersion >= 70100) + { + appendPQExpBuffer(oidQry, "Declare blobOid Cursor for SELECT DISTINCT loid FROM pg_largeobject"); + } else { + appendPQExpBuffer(oidQry, "Declare blobOid Cursor for SELECT oid from pg_class where relkind = 'l'"); + } res = PQexec(g_conn, oidQry->data); if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) @@ -1320,12 +1338,22 @@ getTypes(int *numTypes) * we filter out the built-in types when we dump out the types */ - appendPQExpBuffer(query, "SELECT pg_type.oid, typowner, typname, typlen, typprtlen, " - "typinput, typoutput, typreceive, typsend, typelem, typdelim, " - "typdefault, typrelid, typbyval, " - "(select usename from pg_user where typowner = usesysid) as usename, " - "format_type(pg_type.oid, NULL) as typedefn " - "from pg_type"); + if (g_fout->remoteVersion < 70100) + { + appendPQExpBuffer(query, "SELECT pg_type.oid, typowner, typname, typlen, typprtlen, " + "typinput, typoutput, typreceive, typsend, typelem, typdelim, " + "typdefault, typrelid, typbyval, " + "(select usename from pg_user where typowner = usesysid) as usename, " + "typname as typedefn " + "from pg_type"); + } else { + appendPQExpBuffer(query, "SELECT pg_type.oid, typowner, typname, typlen, typprtlen, " + "typinput, typoutput, typreceive, typsend, typelem, typdelim, " + "typdefault, typrelid, typbyval, " + "(select usename from pg_user where typowner = usesysid) as usename, " + "format_type(pg_type.oid, NULL) as typedefn " + "from pg_type"); + } res = PQexec(g_conn, query->data); if (!res || @@ -1787,15 +1815,26 @@ getAggregates(int *numAggs) int i_aggbasetype; int i_agginitval; int i_usename; + int i_convertok; /* find all user-defined aggregates */ - appendPQExpBuffer(query, - "SELECT pg_aggregate.oid, aggname, aggtransfn, " - "aggfinalfn, aggtranstype, aggbasetype, " - "agginitval, " - "(select usename from pg_user where aggowner = usesysid) as usename " - "from pg_aggregate"); + if (g_fout->remoteVersion < 70100) + { + appendPQExpBuffer(query, "SELECT pg_aggregate.oid, aggname, aggtransfn1 as aggtransfn, " + "aggfinalfn, aggtranstype1 as aggtranstype, aggbasetype, " + "agginitval1 as agginitval, " + "(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) as convertok, " + "(select usename from pg_user where aggowner = usesysid) as usename " + "from pg_aggregate"); + } else { + appendPQExpBuffer(query, "SELECT pg_aggregate.oid, aggname, aggtransfn, " + "aggfinalfn, aggtranstype, aggbasetype, " + "agginitval, " + "'t'::boolean as convertok, " + "(select usename from pg_user where aggowner = usesysid) as usename " + "from pg_aggregate"); + } res = PQexec(g_conn, query->data); if (!res || @@ -1819,6 +1858,7 @@ getAggregates(int *numAggs) i_aggbasetype = PQfnumber(res, "aggbasetype"); i_agginitval = PQfnumber(res, "agginitval"); i_usename = PQfnumber(res, "usename"); + i_convertok = PQfnumber(res, "convertok"); for (i = 0; i < ntups; i++) { @@ -1834,6 +1874,8 @@ getAggregates(int *numAggs) fprintf(stderr, "WARNING: owner of aggregate '%s' appears to be invalid\n", agginfo[i].aggname); + agginfo[i].convertok = (PQgetvalue(res, i, i_convertok)[0] == 't'); + } PQclear(res); @@ -1874,14 +1916,26 @@ getFuncs(int *numFuncs) /* find all user-defined funcs */ - appendPQExpBuffer(query, + if (g_fout->remoteVersion < 70100) + { + appendPQExpBuffer(query, "SELECT pg_proc.oid, proname, prolang, pronargs, prorettype, " "proretset, proargtypes, prosrc, probin, " - "(select usename from pg_user where proowner = usesysid) as usename, " - "proiscachable, proisstrict " - "from pg_proc " - "where pg_proc.oid > '%u'::oid", + "(select usename from pg_user where proowner = usesysid) as usename, " + "proiscachable, 't'::boolean as proisstrict " + "from pg_proc " + "where pg_proc.oid > '%u'::oid", g_last_builtin_oid); + } else { + appendPQExpBuffer(query, + "SELECT pg_proc.oid, proname, prolang, pronargs, prorettype, " + "proretset, proargtypes, prosrc, probin, " + "(select usename from pg_user where proowner = usesysid) as usename, " + "proiscachable, proisstrict " + "from pg_proc " + "where pg_proc.oid > '%u'::oid", + g_last_builtin_oid); + } res = PQexec(g_conn, query->data); if (!res || @@ -1935,7 +1989,7 @@ getFuncs(int *numFuncs) if (finfo[i].nargs < 0 || finfo[i].nargs > FUNC_MAX_ARGS) { - fprintf(stderr, "failed sanity check: %s has %d args\n", + fprintf(stderr, "getFuncs(): failed sanity check: %s has %d args\n", finfo[i].proname, finfo[i].nargs); exit(1); } @@ -2217,12 +2271,32 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs) int n; resetPQExpBuffer(query); - appendPQExpBuffer(query, + if (g_fout->remoteVersion < 70100) + { + /* Fake the LOJ from below */ + appendPQExpBuffer(query, + " SELECT c.relname " + " FROM pg_index i, pg_class c " + " WHERE i.indrelid = %s" + " AND i.indisprimary " + " AND c.oid = i.indexrelid" + " UNION ALL " + " SELECT NULL " + " FROM pg_index i " + " WHERE i.indrelid = %s" + " AND i.indisprimary " + " And NOT Exists(Select * From pg_class c Where c.oid = i.indexrelid)", + tblinfo[i].oid, tblinfo[i].oid); + + } else { + appendPQExpBuffer(query, "SELECT c.relname " "FROM pg_index i LEFT OUTER JOIN pg_class c ON c.oid = i.indexrelid " "WHERE i.indrelid = %s" "AND i.indisprimary ", tblinfo[i].oid); + } + res2 = PQexec(g_conn, query->data); if (!res2 || PQresultStatus(res2) != PGRES_TUPLES_OK) { @@ -2275,6 +2349,8 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs) i_tgisconstraint, i_tgconstrname, i_tgdeferrable, + i_tgconstrrelid, + i_tgconstrrelname, i_tginitdeferred; int ntups2; int i2; @@ -2286,7 +2362,12 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs) g_comment_end); resetPQExpBuffer(query); - appendPQExpBuffer(query, "SELECT tgname, tgfoid, tgtype, tgnargs, tgargs, tgisconstraint, tgconstrname, tgdeferrable, tginitdeferred, oid " + appendPQExpBuffer(query, + "SELECT tgname, tgfoid, tgtype, tgnargs, tgargs, " + "tgisconstraint, tgconstrname, tgdeferrable, " + "tgconstrrelid, tginitdeferred, oid, " + "(select relname from pg_class where oid = tgconstrrelid) " + " as tgconstrrelname " "from pg_trigger " "where tgrelid = '%s'::oid ", tblinfo[i].oid); @@ -2314,6 +2395,8 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs) i_tgisconstraint = PQfnumber(res2, "tgisconstraint"); i_tgconstrname = PQfnumber(res2, "tgconstrname"); i_tgdeferrable = PQfnumber(res2, "tgdeferrable"); + i_tgconstrrelid = PQfnumber(res2, "tgconstrrelid"); + i_tgconstrrelname = PQfnumber(res2, "tgconstrrelname"); i_tginitdeferred = PQfnumber(res2, "tginitdeferred"); tblinfo[i].triggers = (TrigInfo *) malloc(ntups2 * sizeof(TrigInfo)); @@ -2328,9 +2411,13 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs) int tgisconstraint; int tgdeferrable; int tginitdeferred; + char *tgconstrrelid; + char *tgname; const char *p; int findx; + tgname = PQgetvalue(res2, i2, i_tgname); + if (strcmp(PQgetvalue(res2, i2, i_tgisconstraint), "f") == 0) tgisconstraint = 0; else @@ -2376,7 +2463,7 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs) if (!r || PQresultStatus(r) != PGRES_TUPLES_OK) { fprintf(stderr, "getTables(): SELECT (funcname) failed for trigger %s. Explanation from backend: '%s'.\n", - PQgetvalue(res2, i2, i_tgname), PQerrorMessage(g_conn)); + tgname, PQerrorMessage(g_conn)); exit_nicely(g_conn); } @@ -2385,7 +2472,7 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs) if (numFuncs != 1) { fprintf(stderr, "getTables(): SELECT (funcname) for trigger %s returned %d tuples. Expected 1.\n", - PQgetvalue(res2, i2, i_tgname), numFuncs); + tgname, numFuncs); exit_nicely(g_conn); } @@ -2395,9 +2482,7 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs) else tgfunc = strdup(finfo[findx].proname); - appendPQExpBuffer(delqry, "DROP TRIGGER %s ", - fmtId(PQgetvalue(res2, i2, i_tgname), - force_quotes)); + appendPQExpBuffer(delqry, "DROP TRIGGER %s ", fmtId(tgname, force_quotes)); appendPQExpBuffer(delqry, "ON %s;\n", fmtId(tblinfo[i].relname, force_quotes)); @@ -2410,7 +2495,7 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs) else { appendPQExpBuffer(query, "CREATE TRIGGER "); - appendPQExpBuffer(query, fmtId(PQgetvalue(res2, i2, i_tgname), force_quotes)); + appendPQExpBuffer(query, fmtId(tgname, force_quotes)); } appendPQExpBufferChar(query, ' '); /* Trigger type */ @@ -2443,6 +2528,21 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs) if (tgisconstraint) { + tgconstrrelid = PQgetvalue(res2, i2, i_tgconstrrelid); + + if (strcmp(tgconstrrelid, "0") != 0) { + + if (PQgetisnull(res2, i2, i_tgconstrrelname)) + { + fprintf(stderr, "getTables(): SELECT produced NULL referenced table name " + "for trigger '%s' on relation '%s' (oid was %s).\n", + tgname, tblinfo[i].relname, tgconstrrelid); + exit_nicely(g_conn); + } + + appendPQExpBuffer(query, " FROM %s", + fmtId(PQgetvalue(res2, i2, i_tgconstrrelname), force_quotes)); + } if (!tgdeferrable) appendPQExpBuffer(query, " NOT"); appendPQExpBuffer(query, " DEFERRABLE INITIALLY "); @@ -2469,7 +2569,7 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs) "string (%s) for trigger '%s'\n", tblinfo[i].relname, PQgetvalue(res2, i2, i_tgargs), - PQgetvalue(res2, i2, i_tgname)); + tgname); exit_nicely(g_conn); } p++; @@ -2501,12 +2601,12 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs) resetPQExpBuffer(query); appendPQExpBuffer(query, "TRIGGER %s ", - fmtId(PQgetvalue(res2, i2, i_tgname), force_quotes)); + fmtId(tgname, force_quotes)); appendPQExpBuffer(query, "ON %s", fmtId(tblinfo[i].relname, force_quotes)); tblinfo[i].triggers[i2].tgcomment = strdup(query->data); tblinfo[i].triggers[i2].oid = strdup(PQgetvalue(res2, i2, i_tgoid)); - tblinfo[i].triggers[i2].tgname = strdup(fmtId(PQgetvalue(res2, i2, i_tgname), false)); + tblinfo[i].triggers[i2].tgname = strdup(fmtId(tgname, false)); tblinfo[i].triggers[i2].tgdel = strdup(delqry->data); if (tgfunc) @@ -2624,12 +2724,35 @@ getTableAttrs(TableInfo *tblinfo, int numTables) g_comment_end); resetPQExpBuffer(q); - appendPQExpBuffer(q, "SELECT a.oid as attoid, a.attnum, a.attname, t.typname, a.atttypmod, " - "a.attnotnull, a.atthasdef, format_type(a.atttypid, a.atttypmod) as atttypedefn " - "from pg_attribute a LEFT OUTER JOIN pg_type t ON a.atttypid = t.oid " - "where a.attrelid = '%s'::oid " - "and a.attnum > 0 order by attnum", - tblinfo[i].oid); + + if (g_fout->remoteVersion < 70100) + { + /* Fake the LOJ below */ + appendPQExpBuffer(q, + " SELECT a.oid as attoid, a.attnum, a.attname, t.typname, a.atttypmod, " + " a.attnotnull, a.atthasdef, NULL as atttypedefn " + " from pg_attribute a, pg_type t " + " where a.attrelid = '%s'::oid " + " and a.attnum > 0 " + " and a.atttypid = t.oid " + " UNION ALL SELECT a.oid as attoid, a.attnum, a.attname, NULL as typname, a.atttypmod, " + " a.attnotnull, a.atthasdef, NULL as atttypedefn " + " from pg_attribute a " + " where a.attrelid = '%s'::oid " + " and a.attnum > 0 " + " and Not Exists(Select * From pg_type t where a.atttypid = t.oid)" + " order by attnum", + tblinfo[i].oid, tblinfo[i].oid); + + } else { + appendPQExpBuffer(q, "SELECT a.oid as attoid, a.attnum, a.attname, t.typname, a.atttypmod, " + "a.attnotnull, a.atthasdef, format_type(a.atttypid, a.atttypmod) as atttypedefn " + "from pg_attribute a LEFT OUTER JOIN pg_type t ON a.atttypid = t.oid " + "where a.attrelid = '%s'::oid " + "and a.attnum > 0 order by attnum", + tblinfo[i].oid); + } + res = PQexec(g_conn, q->data); if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) @@ -2778,6 +2901,9 @@ getIndices(int *numIndices) "and t2.relname !~ '^pg_' ", g_last_builtin_oid); + if (g_fout->remoteVersion < 70100) + appendPQExpBuffer(query, " and t2.relkind != 'l'"); + res = PQexec(g_conn, query->data); if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) @@ -3499,9 +3625,13 @@ dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs, TypeInfo *tinfo, int numTypes) { #define AGG_NOTICE(arg) {\ - fprintf(stderr, "Notice: aggregate \"%s\"(oid %s) is not dumped.\n",agginfo[i].aggname, agginfo[i].oid);\ - fprintf(stderr, "Reason: " CppAsString(arg) );\ - fprintf (stderr, " (oid %s) not found.\n",agginfo[i].arg);\ + resetPQExpBuffer(q);\ + appendPQExpBuffer(q, "-- Notice: aggregate \"%s\"(oid %s) is not dumped.\n",agginfo[i].aggname, agginfo[i].oid);\ + appendPQExpBuffer(q, "-- Reason: " CppAsString(arg) );\ + appendPQExpBuffer(q, " (oid %s) not found.\n",agginfo[i].arg);\ + fprintf(stderr, q->data);\ + ArchiveEntry(fout, agginfo[i].oid, aggSig->data, "WARNING", NULL,\ + q->data, "" /* Del */, "", agginfo[i].usename, NULL, NULL);\ } int i; @@ -3517,9 +3647,25 @@ dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs, resetPQExpBuffer(details); /* skip all the builtin oids */ - if (atooid(agginfo[i].oid) <= g_last_builtin_oid) + if ( oidle( atooid(agginfo[i].oid), g_last_builtin_oid) ) continue; + resetPQExpBuffer(aggSig); + appendPQExpBuffer(aggSig, "%s(%s)", agginfo[i].aggname, + findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype, zeroAsOpaque + useBaseTypeName)); + + if (!agginfo[i].convertok) + { + resetPQExpBuffer(q); + appendPQExpBuffer(q, "-- WARNING: Aggregate %s could not be dumped correctly for this database version - ignored\n", + aggSig->data); + fprintf(stderr, q->data); + + ArchiveEntry(fout, agginfo[i].oid, aggSig->data, "WARNING", NULL, + q->data, "" /* Del */, "", agginfo[i].usename, NULL, NULL); + continue; + } + name = findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype, zeroAsAny + useBaseTypeName); if (name == NULL) { @@ -3548,10 +3694,6 @@ dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs, appendPQExpBuffer(details, ", FINALFUNC = %s", agginfo[i].aggfinalfn); - resetPQExpBuffer(aggSig); - appendPQExpBuffer(aggSig, "%s %s", agginfo[i].aggname, - findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype, zeroAsOpaque + useBaseTypeName)); - resetPQExpBuffer(delq); appendPQExpBuffer(delq, "DROP AGGREGATE %s;\n", aggSig->data); @@ -3737,6 +3879,61 @@ dumpACL(Archive *fout, TableInfo tbinfo) } +static void +_dumpTableAttr70(Archive *fout, TableInfo *tblinfo, int i, int j, PQExpBuffer q) +{ + int32 tmp_typmod; + int precision; + int scale; + + /* Show lengths on bpchar and varchar */ + if (!strcmp(tblinfo[i].typnames[j], "bpchar")) + { + int len = (tblinfo[i].atttypmod[j] - VARHDRSZ); + + appendPQExpBuffer(q, "character"); + if (len > 1) + appendPQExpBuffer(q, "(%d)", + tblinfo[i].atttypmod[j] - VARHDRSZ); + } + else if (!strcmp(tblinfo[i].typnames[j], "varchar")) + { + appendPQExpBuffer(q, "character varying"); + if (tblinfo[i].atttypmod[j] != -1) + { + appendPQExpBuffer(q, "(%d)", + tblinfo[i].atttypmod[j] - VARHDRSZ); + } + } + else if (!strcmp(tblinfo[i].typnames[j], "numeric")) + { + appendPQExpBuffer(q, "numeric"); + if (tblinfo[i].atttypmod[j] != -1) + { + tmp_typmod = tblinfo[i].atttypmod[j] - VARHDRSZ; + precision = (tmp_typmod >> 16) & 0xffff; + scale = tmp_typmod & 0xffff; + appendPQExpBuffer(q, "(%d,%d)", + precision, scale); + } + } + + /* + * char is an internal single-byte data type; Let's + * make sure we force it through with quotes. - thomas + * 1998-12-13 + */ + else if (!strcmp(tblinfo[i].typnames[j], "char")) + { + appendPQExpBuffer(q, "%s", + fmtId(tblinfo[i].typnames[j], true)); + } + else + { + appendPQExpBuffer(q, "%s", + fmtId(tblinfo[i].typnames[j], false)); + } +} /* * dumpTables: @@ -3830,9 +4027,14 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables, appendPQExpBuffer(q, ",\n\t"); /* Attr name & type */ - appendPQExpBuffer(q, "%s %s", - fmtId(tblinfo[i].attnames[j], force_quotes), - tblinfo[i].atttypedefns[j]); + appendPQExpBuffer(q, "%s ", fmtId(tblinfo[i].attnames[j], force_quotes)); + + if (g_fout->remoteVersion >= 70100) + { + appendPQExpBuffer(q, "%s", tblinfo[i].atttypedefns[j]); + } else { + _dumpTableAttr70(fout, tblinfo, i, j, q); + } /* Default value */ if (tblinfo[i].adef_expr[j] != NULL && tblinfo[i].inhAttrDef[j] == 0) @@ -4033,7 +4235,7 @@ dumpIndices(Archive *fout, IndInfo *indinfo, int numIndices, indinfo[i].indrelname); if (tableInd < 0) { - fprintf(stderr, "failed sanity check, table %s was not found\n", + fprintf(stderr, "dumpIndices(): failed sanity check, table %s was not found\n", indinfo[i].indrelname); exit(1); } @@ -4357,7 +4559,7 @@ setMaxOid(Archive *fout) */ static Oid -findLastBuiltinOid(const char *dbname) +findLastBuiltinOid_V71(const char *dbname) { PGresult *res; int ntups; @@ -4389,11 +4591,51 @@ findLastBuiltinOid(const char *dbname) fprintf(stderr, "There is more than one entry for this database in the 'pg_database' table\n"); exit_nicely(g_conn); } - last_oid = atoi(PQgetvalue(res, 0, PQfnumber(res, "datlastsysoid"))); + last_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "datlastsysoid"))); PQclear(res); return last_oid; } +/* + * findLastBuiltInOid - + * find the last built in oid + * we do this by looking up the oid of 'template1' in pg_database, + * this is probably not foolproof but comes close +*/ + +static Oid +findLastBuiltinOid_V70(void) +{ + PGresult *res; + int ntups; + int last_oid; + + res = PQexec(g_conn, + "SELECT oid from pg_database where datname = 'template1'"); + if (res == NULL || + PQresultStatus(res) != PGRES_TUPLES_OK) + { + fprintf(stderr, "pg_dump error in finding the template1 database."); + fprintf(stderr, "Explanation from backend: '%s'.\n", PQerrorMessage(g_conn)); + exit_nicely(g_conn); + } + ntups = PQntuples(res); + if (ntups < 1) + { + fprintf(stderr, "pg_dump: couldn't find the template1 database.\n"); + fprintf(stderr, "There is no 'template1' entry in the 'pg_database' table.\n"); + exit_nicely(g_conn); + } + if (ntups > 1) + { + fprintf(stderr, "pg_dump: found more than one template1 database.\n"); + fprintf(stderr, "There is more than one 'template1' entry in the 'pg_database' table\n"); + exit_nicely(g_conn); + } + last_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "oid"))); + PQclear(res); + return last_oid; +} static void dumpSequence(Archive *fout, TableInfo tbinfo, const bool schemaOnly, const bool dataOnly) diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index b10d40876d..8e5db6015c 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_dump.h,v 1.62 2001/04/14 13:11:03 pjw Exp $ + * $Id: pg_dump.h,v 1.63 2001/04/25 07:03:20 pjw Exp $ * * Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2 * @@ -159,6 +159,7 @@ typedef struct _aggInfo char *aggbasetype; char *agginitval; char *usename; + int convertok; /* Flag to indicate of version convertsion is OK */ } AggInfo; typedef struct _oprInfo