aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2002-01-18 17:13:51 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2002-01-18 17:13:51 +0000
commitbb698c25c70153a71a63a9e3925350b444322085 (patch)
tree2388ea5350158a55d751ae7f05ece7dd5a8e7da8 /src
parent3dfe80243c5ccf00e27dfa03a8d7e61279175503 (diff)
downloadpostgresql-bb698c25c70153a71a63a9e3925350b444322085.tar.gz
postgresql-bb698c25c70153a71a63a9e3925350b444322085.zip
Fix pg_restore to handle the 'set max oid' entry correctly in archives
dumped by pg_dump -o. Per bug report posted by Bruce; fix is from Philip Warner, reviewed by Tom Lane.
Diffstat (limited to 'src')
-rw-r--r--src/bin/pg_dump/pg_backup_archiver.c14
-rw-r--r--src/bin/pg_dump/pg_backup_db.c355
2 files changed, 207 insertions, 162 deletions
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 4c99d51bfed..675da67d9c8 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.38 2001/11/08 04:05:12 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.39 2002/01/18 17:13:50 tgl Exp $
*
* Modifications - 28-Jun-2000 - pjw@rhyme.com.au
*
@@ -62,6 +62,11 @@
* backup file; prior version was restoring schema in data-only
* restores. Added enum to make code easier to understand.
*
+ * Modifications - 18-Jan-2002 - pjw@rhyme.com.au
+ * - Modified _tocEntryRequired to handle '<Init>/Max OID' as a special
+ * case (ie. as a DATA item) as per bugs reported by Bruce Momjian
+ * around 17-Jan-2002.
+ *
*-------------------------------------------------------------------------
*/
@@ -1917,6 +1922,13 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt)
res = res & ~REQ_DATA;
}
+ /* Special case: <Init> type with <Max OID> name; this is part of
+ * a DATA restore even though it has SQL.
+ */
+ if ( ( strcmp(te->desc, "<Init>") == 0 ) && ( strcmp(te->name, "Max OID") == 0) ) {
+ res = REQ_DATA;
+ }
+
/* Mask it if we only want schema */
if (ropt->schemaOnly)
res = res & REQ_SCHEMA;
diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c
index aeea9d02c88..ff31b4789e7 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.29 2001/10/25 05:49:52 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.30 2002/01/18 17:13:51 tgl Exp $
*
* NOTES
*
@@ -17,6 +17,14 @@
*
* - Avoid forcing table name to lower case in FixupBlobXrefs!
*
+ *
+ * Modifications - 18-Jan-2002 - pjw@rhyme.com.au
+ *
+ * - Split ExecuteSqlCommandBuf into 3 routines for (slightly) improved
+ * clarity. Modify loop to cater for COPY commands buried in the SQL
+ * command buffer (prev version assumed COPY command was executed
+ * in prior call). This was to fix the buf in the 'set max oid' code.
+ *
*-------------------------------------------------------------------------
*/
@@ -43,6 +51,8 @@ static void _check_database_version(ArchiveHandle *AH, bool ignoreVersion);
static PGconn *_connectDB(ArchiveHandle *AH, const char *newdbname, const char *newUser);
static int _executeSqlCommand(ArchiveHandle *AH, PGconn *conn, PQExpBuffer qry, char *desc);
static void notice_processor(void *arg, const char *message);
+static char* _sendSQLLine( ArchiveHandle *AH, char *qry, char *eos);
+static char* _sendCopyLine( ArchiveHandle *AH, char *qry, char *eos);
/*
@@ -534,206 +544,229 @@ _executeSqlCommand(ArchiveHandle *AH, PGconn *conn, PQExpBuffer qry, char *desc)
return strlen(qry->data);
}
-/* Convenience function to send one or more queries. Monitors result to handle COPY statements */
-int
-ExecuteSqlCommandBuf(ArchiveHandle *AH, void *qryv, int bufLen)
+/*
+ * Used by ExecuteSqlCommandBuf to send one buffered line when running a COPY command.
+ */
+static char*
+_sendCopyLine( ArchiveHandle *AH, char *qry, char *eos)
{
- int loc;
- int pos = 0;
- int sPos = 0;
- char *qry = (char *) qryv;
- int isEnd = 0;
- char *eos = qry + bufLen;
+ int loc; /* Location of next newline */
+ int pos = 0; /* Current position */
+ int sPos = 0; /* Last pos of a slash char */
+ int isEnd = 0;
- /*
- * fprintf(stderr, "\n\n*****\n
- * Buffer:\n\n%s\n*******************\n\n", qry);
- */
+ /* loop to find unquoted newline ending the line of COPY data */
+ for (;;) {
+ loc = strcspn(&qry[pos], "\n") + pos;
- /* If we're in COPY IN mode, then just break it into lines and send... */
- if (AH->pgCopyIn)
- {
- for (;;)
+ /* If no match, then wait */
+ if (loc >= (eos - qry)) /* None found */
{
+ appendBinaryPQExpBuffer(AH->pgCopyBuf, qry, (eos - qry));
+ return eos;
+ }
- /* Find a lf */
- loc = strcspn(&qry[pos], "\n") + pos;
- pos = 0;
-
- /* If no match, then wait */
- if (loc >= (eos - qry)) /* None found */
- {
- appendBinaryPQExpBuffer(AH->pgCopyBuf, qry, (eos - qry));
- break;
- };
-
- /*
- * fprintf(stderr, "Found cr at %d, prev char was %c, next was
- * %c\n", loc, qry[loc-1], qry[loc+1]);
- */
+ /*
+ * fprintf(stderr, "Found cr at %d, prev char was %c, next was
+ * %c\n", loc, qry[loc-1], qry[loc+1]);
+ */
- /* Count the number of preceding slashes */
- sPos = loc;
- while (sPos > 0 && qry[sPos - 1] == '\\')
- sPos--;
+ /* Count the number of preceding slashes */
+ sPos = loc;
+ while (sPos > 0 && qry[sPos - 1] == '\\')
+ sPos--;
- sPos = loc - sPos;
+ sPos = loc - sPos;
- /*
- * If an odd number of preceding slashes, then \n was escaped
- * so set the next search pos, and restart (if any left).
- */
- if ((sPos & 1) == 1)
+ /*
+ * If an odd number of preceding slashes, then \n was escaped
+ * so set the next search pos, and loop (if any left).
+ */
+ if ((sPos & 1) == 1)
+ {
+ /* fprintf(stderr, "cr was escaped\n"); */
+ pos = loc + 1;
+ if (pos >= (eos - qry))
{
- /* fprintf(stderr, "cr was escaped\n"); */
- pos = loc + 1;
- if (pos >= (eos - qry))
- {
- appendBinaryPQExpBuffer(AH->pgCopyBuf, qry, (eos - qry));
- break;
- }
+ appendBinaryPQExpBuffer(AH->pgCopyBuf, qry, (eos - qry));
+ return eos;
}
- else
- {
- /* We got a good cr */
- qry[loc] = '\0';
- appendPQExpBuffer(AH->pgCopyBuf, "%s\n", qry);
- qry += loc + 1;
- isEnd = (strcmp(AH->pgCopyBuf->data, "\\.\n") == 0);
+ } else {
+ break;
+ }
+ }
- /*---------
- * fprintf(stderr, "Sending '%s' via
- * COPY (at end = %d)\n\n", AH->pgCopyBuf->data, isEnd);
- *---------
- */
+ /* We found an unquoted newline */
+ qry[loc] = '\0';
+ appendPQExpBuffer(AH->pgCopyBuf, "%s\n", qry);
+ isEnd = (strcmp(AH->pgCopyBuf->data, "\\.\n") == 0);
- if (PQputline(AH->connection, AH->pgCopyBuf->data) != 0)
- die_horribly(AH, modulename, "error returned by PQputline\n");
+ /*---------
+ * fprintf(stderr, "Sending '%s' via
+ * COPY (at end = %d)\n\n", AH->pgCopyBuf->data, isEnd);
+ *---------
+ */
- resetPQExpBuffer(AH->pgCopyBuf);
+ if (PQputline(AH->connection, AH->pgCopyBuf->data) != 0)
+ die_horribly(AH, modulename, "error returned by PQputline\n");
- /*
- * fprintf(stderr, "Buffer is '%s'\n",
- * AH->pgCopyBuf->data);
- */
+ resetPQExpBuffer(AH->pgCopyBuf);
- if (isEnd)
- {
- if (PQendcopy(AH->connection) != 0)
- die_horribly(AH, modulename, "error returned by PQendcopy\n");
+ /*
+ * fprintf(stderr, "Buffer is '%s'\n",
+ * AH->pgCopyBuf->data);
+ */
- AH->pgCopyIn = 0;
- break;
- }
+ if (isEnd)
+ {
+ if (PQendcopy(AH->connection) != 0)
+ die_horribly(AH, modulename, "error returned by PQendcopy\n");
- }
+ AH->pgCopyIn = 0;
+ }
- /* Make sure we're not past the original buffer end */
- if (qry >= eos)
- break;
+ return qry + loc + 1;
+}
- }
- }
+/*
+ * Used by ExecuteSqlCommandBuf to send one buffered line of SQL (not data for the copy command).
+ */
+static char*
+_sendSQLLine( ArchiveHandle *AH, char *qry, char *eos)
+{
+ int pos = 0; /* Current position */
- /* We may have finished Copy In, and have a non-empty buffer */
- if (!AH->pgCopyIn)
- {
- /*
- * The following is a mini state machine to assess then of of an
- * SQL statement. It really only needs to parse good SQL, or at
- * least that's the theory... End-of-statement is assumed to be an
- * unquoted, un commented semi-colon.
- */
+ /*
+ * The following is a mini state machine to assess the end of an
+ * SQL statement. It really only needs to parse good SQL, or at
+ * least that's the theory... End-of-statement is assumed to be an
+ * unquoted, un commented semi-colon.
+ */
- /*
- * fprintf(stderr, "Buffer at start is: '%s'\n\n",
- * AH->sqlBuf->data);
- */
+ /*
+ * fprintf(stderr, "Buffer at start is: '%s'\n\n",
+ * AH->sqlBuf->data);
+ */
- for (pos = 0; pos < (eos - qry); pos++)
- {
- appendPQExpBufferChar(AH->sqlBuf, qry[pos]);
- /* fprintf(stderr, " %c",qry[pos]); */
+ for (pos = 0; pos < (eos - qry); pos++)
+ {
+ appendPQExpBufferChar(AH->sqlBuf, qry[pos]);
+ /* fprintf(stderr, " %c",qry[pos]); */
- switch (AH->sqlparse.state)
- {
+ switch (AH->sqlparse.state)
+ {
- case SQL_SCAN: /* Default state == 0, set in _allocAH */
+ case SQL_SCAN: /* Default state == 0, set in _allocAH */
- if (qry[pos] == ';' && AH->sqlparse.braceDepth == 0)
- {
- /* Send It & reset the buffer */
-
- /*
- * fprintf(stderr, " sending: '%s'\n\n",
- * AH->sqlBuf->data);
- */
- ExecuteSqlCommand(AH, AH->sqlBuf, "could not execute query", false);
- resetPQExpBuffer(AH->sqlBuf);
- AH->sqlparse.lastChar = '\0';
- }
- else
+ if (qry[pos] == ';' && AH->sqlparse.braceDepth == 0)
+ {
+ /* Send It & reset the buffer */
+
+ /*
+ * fprintf(stderr, " sending: '%s'\n\n",
+ * AH->sqlBuf->data);
+ */
+ ExecuteSqlCommand(AH, AH->sqlBuf, "could not execute query", false);
+ resetPQExpBuffer(AH->sqlBuf);
+ AH->sqlparse.lastChar = '\0';
+
+ /* Remove any following newlines - so that embedded COPY commands don't get a
+ * starting newline.
+ */
+ pos++;
+ for ( ; pos < (eos - qry) && qry[pos] == '\n' ; pos++ ) ;
+
+ /* We've got our line, so exit */
+ return qry + pos;
+ }
+ else
+ {
+ if (qry[pos] == '"' || qry[pos] == '\'')
{
- if (qry[pos] == '"' || qry[pos] == '\'')
- {
- /* fprintf(stderr,"[startquote]\n"); */
- AH->sqlparse.state = SQL_IN_QUOTE;
- AH->sqlparse.quoteChar = qry[pos];
- AH->sqlparse.backSlash = 0;
- }
- else if (qry[pos] == '-' && AH->sqlparse.lastChar == '-')
- AH->sqlparse.state = SQL_IN_SQL_COMMENT;
- else if (qry[pos] == '*' && AH->sqlparse.lastChar == '/')
- AH->sqlparse.state = SQL_IN_EXT_COMMENT;
- else if (qry[pos] == '(')
- AH->sqlparse.braceDepth++;
- else if (qry[pos] == ')')
- AH->sqlparse.braceDepth--;
-
- AH->sqlparse.lastChar = qry[pos];
+ /* fprintf(stderr,"[startquote]\n"); */
+ AH->sqlparse.state = SQL_IN_QUOTE;
+ AH->sqlparse.quoteChar = qry[pos];
+ AH->sqlparse.backSlash = 0;
}
+ else if (qry[pos] == '-' && AH->sqlparse.lastChar == '-')
+ AH->sqlparse.state = SQL_IN_SQL_COMMENT;
+ else if (qry[pos] == '*' && AH->sqlparse.lastChar == '/')
+ AH->sqlparse.state = SQL_IN_EXT_COMMENT;
+ else if (qry[pos] == '(')
+ AH->sqlparse.braceDepth++;
+ else if (qry[pos] == ')')
+ AH->sqlparse.braceDepth--;
+
+ AH->sqlparse.lastChar = qry[pos];
+ }
- break;
+ break;
- case SQL_IN_SQL_COMMENT:
+ case SQL_IN_SQL_COMMENT:
- if (qry[pos] == '\n')
- AH->sqlparse.state = SQL_SCAN;
- break;
+ if (qry[pos] == '\n')
+ AH->sqlparse.state = SQL_SCAN;
+ break;
- case SQL_IN_EXT_COMMENT:
+ case SQL_IN_EXT_COMMENT:
- if (AH->sqlparse.lastChar == '*' && qry[pos] == '/')
- AH->sqlparse.state = SQL_SCAN;
- break;
+ if (AH->sqlparse.lastChar == '*' && qry[pos] == '/')
+ AH->sqlparse.state = SQL_SCAN;
+ break;
- case SQL_IN_QUOTE:
+ case SQL_IN_QUOTE:
- if (!AH->sqlparse.backSlash && AH->sqlparse.quoteChar == qry[pos])
- {
- /* fprintf(stderr,"[endquote]\n"); */
- AH->sqlparse.state = SQL_SCAN;
- }
- else
- {
+ if (!AH->sqlparse.backSlash && AH->sqlparse.quoteChar == qry[pos])
+ {
+ /* fprintf(stderr,"[endquote]\n"); */
+ AH->sqlparse.state = SQL_SCAN;
+ }
+ else
+ {
- if (qry[pos] == '\\')
- {
- if (AH->sqlparse.lastChar == '\\')
- AH->sqlparse.backSlash = !AH->sqlparse.backSlash;
- else
- AH->sqlparse.backSlash = 1;
- }
+ if (qry[pos] == '\\')
+ {
+ if (AH->sqlparse.lastChar == '\\')
+ AH->sqlparse.backSlash = !AH->sqlparse.backSlash;
else
- AH->sqlparse.backSlash = 0;
+ AH->sqlparse.backSlash = 1;
}
- break;
+ else
+ AH->sqlparse.backSlash = 0;
+ }
+ break;
- }
- AH->sqlparse.lastChar = qry[pos];
- /* fprintf(stderr, "\n"); */
}
+ AH->sqlparse.lastChar = qry[pos];
+ /* fprintf(stderr, "\n"); */
+ }
+ /* If we get here, we've processed entire string with no complete SQL stmt */
+ return eos;
+
+}
+
+
+/* Convenience function to send one or more queries. Monitors result to handle COPY statements */
+int
+ExecuteSqlCommandBuf(ArchiveHandle *AH, void *qryv, int bufLen)
+{
+ char *qry = (char *) qryv;
+ char *eos = qry + bufLen;
+
+ /*
+ * fprintf(stderr, "\n\n*****\n
+ * Buffer:\n\n%s\n*******************\n\n", qry);
+ */
+
+ /* Could switch between command and COPY IN mode at each line */
+ while (qry < eos)
+ {
+ if (AH->pgCopyIn) {
+ qry = _sendCopyLine(AH, qry, eos);
+ } else {
+ qry = _sendSQLLine(AH, qry, eos);
+ }
}
return 1;