From d63e41e9b20cea5d2d57fd30e21e50321b2ceca5 Mon Sep 17 00:00:00 2001 From: Philip Warner Date: Fri, 12 Jan 2001 15:41:29 +0000 Subject: [PATCH] Fixed handling of renamed columns in PK constraints --- src/bin/pg_dump/common.c | 49 +++----- src/bin/pg_dump/pg_backup_archiver.h | 2 +- src/bin/pg_dump/pg_dump.c | 165 ++++++++++++++++++++------- src/bin/pg_dump/pg_dump.h | 7 +- 4 files changed, 146 insertions(+), 77 deletions(-) diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c index 4711a76976..a466dafc5d 100644 --- a/src/bin/pg_dump/common.c +++ b/src/bin/pg_dump/common.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.48 2000/12/03 20:45:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.49 2001/01/12 15:41:29 pjw Exp $ * * Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2 * @@ -270,12 +270,14 @@ dumpSchema(Archive *fout, int numInherits; int numAggregates; int numOperators; + int numIndices; TypeInfo *tinfo = NULL; FuncInfo *finfo = NULL; AggInfo *agginfo = NULL; TableInfo *tblinfo = NULL; InhInfo *inhinfo = NULL; OprInfo *oprinfo = NULL; + IndInfo *indinfo = NULL; if (g_verbose) fprintf(stderr, "%s reading user-defined types %s\n", @@ -302,6 +304,11 @@ dumpSchema(Archive *fout, g_comment_start, g_comment_end); tblinfo = getTables(&numTables, finfo, numFuncs); + if (g_verbose) + fprintf(stderr, "%s reading indices information %s\n", + g_comment_start, g_comment_end); + indinfo = getIndices(&numIndices); + if (g_verbose) fprintf(stderr, "%s reading table inheritance information %s\n", g_comment_start, g_comment_end); @@ -336,9 +343,18 @@ dumpSchema(Archive *fout, if (g_verbose) fprintf(stderr, "%s dumping out tables %s\n", g_comment_start, g_comment_end); - dumpTables(fout, tblinfo, numTables, inhinfo, numInherits, + + dumpTables(fout, tblinfo, numTables, indinfo, numIndices, inhinfo, numInherits, tinfo, numTypes, tablename, aclsSkip, oids, schemaOnly, dataOnly); + if (fout && !dataOnly) + { + if (g_verbose) + fprintf(stderr, "%s dumping out indices %s\n", + g_comment_start, g_comment_end); + dumpIndices(fout, indinfo, numIndices, tblinfo, numTables, tablename); + } + if (!tablename && !dataOnly) { if (g_verbose) @@ -377,35 +393,8 @@ dumpSchema(Archive *fout, clearTypeInfo(tinfo, numTypes); clearFuncInfo(finfo, numFuncs); clearInhInfo(inhinfo, numInherits); - return tblinfo; -} - -/* - * dumpSchemaIdx: - * dump indexes at the end for performance - * - */ - -extern void -dumpSchemaIdx(Archive *fout, const char *tablename, - TableInfo *tblinfo, int numTables) -{ - int numIndices; - IndInfo *indinfo; - - if (g_verbose) - fprintf(stderr, "%s reading indices information %s\n", - g_comment_start, g_comment_end); - indinfo = getIndices(&numIndices); - - if (fout) - { - if (g_verbose) - fprintf(stderr, "%s dumping out indices %s\n", - g_comment_start, g_comment_end); - dumpIndices(fout, indinfo, numIndices, tblinfo, numTables, tablename); - } clearIndInfo(indinfo, numIndices); + return tblinfo; } /* flagInhAttrs - diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h index 9a9c2e78a8..0808af32c8 100644 --- a/src/bin/pg_dump/pg_backup_archiver.h +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -62,7 +62,7 @@ typedef z_stream *z_streamp; #define K_VERS_MAJOR 1 #define K_VERS_MINOR 4 -#define K_VERS_REV 23 +#define K_VERS_REV 24 /* Data block types */ #define BLK_DATA 1 diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index ba10354b6d..a383ec7dd6 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.186 2001/01/12 04:32:07 pjw Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.187 2001/01/12 15:41:29 pjw Exp $ * * Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb * @@ -155,6 +155,7 @@ static char *GetPrivileges(const char *s); static int dumpBlobs(Archive *AH, char*, void*); static int dumpDatabase(Archive *AH); +static PQExpBuffer getPKconstraint(TableInfo *tblInfo, IndInfo *indInfo); extern char *optarg; extern int optind, @@ -1027,7 +1028,6 @@ main(int argc, char **argv) if (!dataOnly) /* dump indexes and triggers at the end * for performance */ { - dumpSchemaIdx(g_fout, tablename, tblinfo, numTables); dumpTriggers(g_fout, tablename, tblinfo, numTables); dumpRules(g_fout, tablename, tblinfo, numTables); } @@ -1038,6 +1038,7 @@ main(int argc, char **argv) MoveToEnd(g_fout, "TABLE DATA"); MoveToEnd(g_fout, "BLOBS"); MoveToEnd(g_fout, "INDEX"); + MoveToEnd(g_fout, "CONSTRAINT"); MoveToEnd(g_fout, "TRIGGER"); MoveToEnd(g_fout, "RULE"); MoveToEnd(g_fout, "SEQUENCE SET"); @@ -1568,8 +1569,6 @@ clearTableInfo(TableInfo *tblinfo, int numTables) free(tblinfo[i].typnames); if (tblinfo[i].notnull) free(tblinfo[i].notnull); - if (tblinfo[i].primary_key) - free(tblinfo[i].primary_key); if (tblinfo[i].primary_key_name) free(tblinfo[i].primary_key_name); } @@ -1656,6 +1655,8 @@ clearIndInfo(IndInfo *ind, int numIndices) free(ind[i].indproc); if (ind[i].indisunique) free(ind[i].indisunique); + if (ind[i].indisprimary) + free(ind[i].indisprimary); for (a = 0; a < INDEX_MAX_KEYS; ++a) { if (ind[i].indkey[a]) @@ -2132,50 +2133,36 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs) if (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0) { PGresult *res2; - char str[INDEX_MAX_KEYS * (NAMEDATALEN * 2 + 4) + 1]; - int j; resetPQExpBuffer(query); appendPQExpBuffer(query, - "SELECT a.attname " - "FROM pg_index i, pg_class c, pg_attribute a " - "WHERE i.indisprimary AND i.indrelid = %s " - " AND i.indexrelid = c.oid AND a.attnum > 0 AND a.attrelid = c.oid " - "ORDER BY a.attnum ", + "SELECT Oid FROM pg_index i WHERE i.indisprimary AND i.indrelid = %s ", tblinfo[i].oid); res2 = PQexec(g_conn, query->data); if (!res2 || PQresultStatus(res2) != PGRES_TUPLES_OK) { - fprintf(stderr, "getTables(): SELECT (for PRIMARY KEY) failed. Explanation from backend: %s", + fprintf(stderr, "getTables(): SELECT (for PRIMARY KEY) failed. Explanation from backend: %s\n", PQerrorMessage(g_conn)); exit_nicely(g_conn); } - str[0] = '\0'; - for (j = 0; j < PQntuples(res2); j++) - { - if (strlen(str) > 0) - strcat(str, ", "); - strcat(str, fmtId(PQgetvalue(res2, j, 0), force_quotes)); + if (PQntuples(res2) > 1) { + fprintf(stderr, "getTables(): SELECT (for PRIMARY KEY) produced more than one row.\n"); + exit_nicely(g_conn); } - if (strlen(str) > 0) - { - tblinfo[i].primary_key = strdup(str); - if (tblinfo[i].primary_key == NULL) - { - perror("strdup"); - exit(1); - } + if (PQntuples(res2) == 1) { + tblinfo[i].pkIndexOid = strdup(PQgetvalue(res2, 0, 0)); + } else { + tblinfo[i].pkIndexOid = NULL; } - else - tblinfo[i].primary_key = NULL; + } else - tblinfo[i].primary_key = NULL; + tblinfo[i].pkIndexOid = NULL; /* Get primary key name (if primary key exist) */ - if (tblinfo[i].primary_key) + if (tblinfo[i].pkIndexOid != NULL) { PGresult *res2; int n; @@ -2695,6 +2682,8 @@ getIndices(int *numIndices) int i_indclass; int i_indisunique; int i_indoid; + int i_oid; + int i_indisprimary; /* * find all the user-defined indices. We do not handle partial @@ -2706,13 +2695,13 @@ getIndices(int *numIndices) */ appendPQExpBuffer(query, - "SELECT t1.oid as indoid, t1.relname as indexrelname, t2.relname as indrelname, " + "SELECT i.oid, t1.oid as indoid, t1.relname as indexrelname, t2.relname as indrelname, " "i.indproc, i.indkey, i.indclass, " - "a.amname as indamname, i.indisunique " + "a.amname as indamname, i.indisunique, i.indisprimary " "from pg_index i, pg_class t1, pg_class t2, pg_am a " "WHERE t1.oid = i.indexrelid and t2.oid = i.indrelid " "and t1.relam = a.oid and i.indexrelid > '%u'::oid " - "and t2.relname !~ '^pg_' and not i.indisprimary", + "and t2.relname !~ '^pg_' ", g_last_builtin_oid); res = PQexec(g_conn, query->data); @@ -2732,6 +2721,7 @@ getIndices(int *numIndices) memset((char *) indinfo, 0, ntups * sizeof(IndInfo)); + i_oid = PQfnumber(res, "oid"); i_indoid = PQfnumber(res, "indoid"); i_indexrelname = PQfnumber(res, "indexrelname"); i_indrelname = PQfnumber(res, "indrelname"); @@ -2740,9 +2730,11 @@ getIndices(int *numIndices) i_indkey = PQfnumber(res, "indkey"); i_indclass = PQfnumber(res, "indclass"); i_indisunique = PQfnumber(res, "indisunique"); + i_indisprimary = PQfnumber(res, "indisprimary"); for (i = 0; i < ntups; i++) { + indinfo[i].oid = strdup(PQgetvalue(res, i, i_oid)); indinfo[i].indoid = strdup(PQgetvalue(res, i, i_indoid)); indinfo[i].indexrelname = strdup(PQgetvalue(res, i, i_indexrelname)); indinfo[i].indrelname = strdup(PQgetvalue(res, i, i_indrelname)); @@ -2755,6 +2747,7 @@ getIndices(int *numIndices) indinfo[i].indclass, INDEX_MAX_KEYS); indinfo[i].indisunique = strdup(PQgetvalue(res, i, i_indisunique)); + indinfo[i].indisprimary = strdup(PQgetvalue(res, i, i_indisprimary)); } PQclear(res); return indinfo; @@ -3551,6 +3544,7 @@ dumpACL(Archive *fout, TableInfo tbinfo) void dumpTables(Archive *fout, TableInfo *tblinfo, int numTables, + IndInfo *indinfo, int numIndices, InhInfo *inhinfo, int numInherits, TypeInfo *tinfo, int numTypes, const char *tablename, const bool aclsSkip, const bool oids, @@ -3651,6 +3645,8 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables, } } + + /* put the CONSTRAINTS inside the table def */ for (k = 0; k < tblinfo[i].ncheck; k++) { @@ -3661,17 +3657,36 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables, tblinfo[i].check_expr[k]); } - /* PRIMARY KEY */ - if (tblinfo[i].primary_key) + /* Primary Key */ + if (tblinfo[i].pkIndexOid != NULL) { - if (actual_atts + tblinfo[i].ncheck > 0) + PQExpBuffer consDef; + + /* Find the corresponding index */ + for (k = 0; k < numIndices; k++) + { + if (strcmp(indinfo[k].oid, tblinfo[i].pkIndexOid) == 0) + break; + } + + if (k >= numIndices) + { + fprintf(stderr, "dumpTables(): failed sanity check, could not find index (%s) for PK constraint\n", + tblinfo[i].pkIndexOid); + exit_nicely(g_conn); + } + + consDef = getPKconstraint(&tblinfo[i], &indinfo[k]); + + if ( (actual_atts + tblinfo[i].ncheck) > 0) appendPQExpBuffer(q, ",\n\t"); - appendPQExpBuffer(q, - "CONSTRAINT %s PRIMARY KEY (%s)", - tblinfo[i].primary_key_name, - tblinfo[i].primary_key); + + appendPQExpBuffer(q, "%s", consDef->data); + + destroyPQExpBuffer(consDef); } + appendPQExpBuffer(q, "\n)"); if (numParents > 0) @@ -3690,13 +3705,15 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables, } if (!dataOnly) { - ArchiveEntry(fout, tblinfo[i].oid, fmtId(tblinfo[i].relname, false), + + ArchiveEntry(fout, tblinfo[i].oid, fmtId(tblinfo[i].relname, false), reltypename, NULL, q->data, delq->data, "", tblinfo[i].usename, NULL, NULL); - } - if (!dataOnly && !aclsSkip) - dumpACL(fout, tblinfo[i]); + if (!aclsSkip) + dumpACL(fout, tblinfo[i]); + + } /* Dump Field Comments */ @@ -3719,6 +3736,41 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables, } } +static PQExpBuffer getPKconstraint(TableInfo *tblInfo, IndInfo *indInfo) +{ + PQExpBuffer pkBuf = createPQExpBuffer(); + int k; + int indkey; + + resetPQExpBuffer(pkBuf); + + appendPQExpBuffer(pkBuf, "Constraint %s Primary Key (", + tblInfo->primary_key_name); + + + for (k = 0; k < INDEX_MAX_KEYS; k++) + { + char *attname; + + indkey = atoi(indInfo->indkey[k]); + if (indkey == InvalidAttrNumber) + break; + indkey--; + if (indkey == ObjectIdAttributeNumber - 1) + attname = "oid"; + else + attname = tblInfo->attnames[indkey]; + + appendPQExpBuffer(pkBuf, "%s%s", + (k == 0) ? "" : ", ", + fmtId(attname, force_quotes)); + } + + appendPQExpBuffer(pkBuf, ")"); + + return pkBuf; +} + /* * dumpIndices: * write out to fout all the user-define indices @@ -3755,6 +3807,31 @@ dumpIndices(Archive *fout, IndInfo *indinfo, int numIndices, exit(1); } + /* Handle PK indexes */ + if (strcmp(indinfo[i].indisprimary, "t") == 0) + { +/* + * ***PK: Enable this code when ALTER TABLE supports PK constraints. *** + * + * PQExpBuffer consDef = getPKconstraint(&tblinfo[tableInd], &indinfo[i]); + * + * resetPQExpBuffer(attlist); + * + * appendPQExpBuffer(attlist, "Alter Table %s Add %s;", + * fmtId(tblinfo[tableInd].relname, force_quotes), + * consDef->data); + * + * ArchiveEntry(fout, indinfo[i].oid, tblinfo[tableInd].primary_key_name, "CONSTRAINT", NULL, + * attlist->data, "", + * "", tblinfo[tableInd].usename, NULL, NULL); + * + * destroyPQExpBuffer(consDef); + */ + /* Don't need to do anything else for this system-generated index */ + continue; + } + + if (strcmp(indinfo[i].indproc, "0") == 0) funcname = NULL; else diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 1871ed3e2f..c734cf2c77 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-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_dump.h,v 1.55 2000/11/27 20:51:40 momjian Exp $ + * $Id: pg_dump.h,v 1.56 2001/01/12 15:41:29 pjw Exp $ * * Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2 * @@ -116,7 +116,7 @@ typedef struct _tableInfo char **check_expr; /* [CONSTRAINT name] CHECK expressions */ int ntrig; /* # of triggers */ TrigInfo *triggers; /* Triggers on the table */ - char *primary_key; /* PRIMARY KEY of the table, if any */ + char *pkIndexOid; /* Primary Key index OID */ char *primary_key_name; /* PRIMARY KEY name, if any */ } TableInfo; @@ -128,6 +128,7 @@ typedef struct _inhInfo typedef struct _indInfo { + char *oid; /* Oid of the pg_index entry */ char *indoid; /* oid of the pg_class entry for the index */ char *indexrelname; /* name of the secondary index class */ char *indrelname; /* name of the indexed heap class */ @@ -139,6 +140,7 @@ typedef struct _indInfo * attributes */ char *indclass[INDEX_MAX_KEYS]; /* opclass of the keys */ char *indisunique; /* is this index unique? */ + char *indisprimary; /* is this a PK index? */ } IndInfo; typedef struct _aggInfo @@ -253,6 +255,7 @@ extern void dumpAggs(Archive *fout, AggInfo *agginfo, int numAggregates, extern void dumpOprs(Archive *fout, OprInfo *agginfo, int numOperators, TypeInfo *tinfo, int numTypes); extern void dumpTables(Archive *fout, TableInfo *tbinfo, int numTables, + IndInfo *indinfo, int numIndices, InhInfo *inhinfo, int numInherits, TypeInfo *tinfo, int numTypes, const char *tablename, const bool acls, const bool oids,