OSDN Git Service

- Check ntuples == 1 for various SELECT statements.
authorPhilip Warner <pjw@rhyme.com.au>
Fri, 12 Jan 2001 04:32:07 +0000 (04:32 +0000)
committerPhilip Warner <pjw@rhyme.com.au>
Fri, 12 Jan 2001 04:32:07 +0000 (04:32 +0000)
- Fix handling of --tables=* (multiple tables never worked properly, AFAICT)
- strdup() the current user in DB routines
- Check results of IO routines more carefully.
- Check results of PQ routines more carefully.

Have not fixed index output yet.

src/bin/pg_dump/pg_backup_archiver.c
src/bin/pg_dump/pg_backup_archiver.h
src/bin/pg_dump/pg_backup_custom.c
src/bin/pg_dump/pg_backup_db.c
src/bin/pg_dump/pg_backup_files.c
src/bin/pg_dump/pg_backup_null.c
src/bin/pg_dump/pg_backup_tar.c
src/bin/pg_dump/pg_dump.c

index 7f2bfe3..afbdcad 100644 (file)
  * Modifications - 30-Oct-2000 - pjw@rhyme.com.au
  *             Added {Start,End}RestoreBlobs to allow extended TX during BLOB restore.
  *
+ * Modifications - 04-Jan-2001 - pjw@rhyme.com.au
+ *       -     strdup() the current user just in case it's deallocated from it's TOC
+ *      entry. Should *never* happen, but that's what they said about the 
+ *      Titanic...
+ *
+ *       - Check results of IO routines more carefully.
+ *
  *-------------------------------------------------------------------------
  */
 
@@ -99,14 +106,18 @@ Archive* OpenArchive(const char* FileSpec, const ArchiveFormat fmt)
 /* Public */
 void   CloseArchive(Archive* AHX)
 {
+       int                                     res = 0;
     ArchiveHandle*      AH = (ArchiveHandle*)AHX;
     (*AH->ClosePtr)(AH);
 
     /* Close the output */
     if (AH->gzOut)
-               GZCLOSE(AH->OF);
+               res = GZCLOSE(AH->OF);
     else if (AH->OF != stdout)
-               fclose(AH->OF);
+               res = fclose(AH->OF);
+
+       if (res != 0)
+               die_horribly(AH, "%s: could not close the output file in CloseArchive\n", progname);
 }
 
 /* Public */
@@ -791,8 +802,8 @@ void SortTocFromFile(Archive* AHX, RestoreOptions *ropt)
 
     /* Setup the file */
     fh = fopen(ropt->tocFile, PG_BINARY_R);
-    if (!fh)
-       die_horribly(AH, "%s: could not open TOC file\n", progname);
+       if (!fh)
+               die_horribly(AH, "%s: could not open TOC file\n", progname);
 
     while (fgets(buf, 1024, fh) != NULL)
     {
@@ -828,7 +839,8 @@ void SortTocFromFile(Archive* AHX, RestoreOptions *ropt)
        tePrev = te;
     }
 
-    fclose(fh);
+    if (fclose(fh) != 0)
+               die_horribly(AH, "%s: could not close TOC file\n", progname);
 }
 
 /**********************
@@ -906,34 +918,42 @@ OutputContext SetOutput(ArchiveHandle* AH, char *filename, int compression)
 #ifdef HAVE_LIBZ
     if (compression != 0)
     {
-       sprintf(fmode, "wb%d", compression);
-       if (fn) {
-           AH->OF = gzdopen(dup(fn), fmode); /* Don't use PG_BINARY_x since this is zlib */
-       } else {
-           AH->OF = gzopen(filename, fmode);
-       }
-       AH->gzOut = 1;
+               sprintf(fmode, "wb%d", compression);
+               if (fn) {
+                       AH->OF = gzdopen(dup(fn), fmode); /* Don't use PG_BINARY_x since this is zlib */
+               } else {
+                       AH->OF = gzopen(filename, fmode);
+               }
+               AH->gzOut = 1;
     } else { /* Use fopen */
 #endif
-       if (fn) {
-           AH->OF = fdopen(dup(fn), PG_BINARY_W);
-       } else {
-           AH->OF = fopen(filename, PG_BINARY_W);
-       }
-       AH->gzOut = 0;
+               if (fn) {
+                       AH->OF = fdopen(dup(fn), PG_BINARY_W);
+               } else {
+                       AH->OF = fopen(filename, PG_BINARY_W);
+               }
+               AH->gzOut = 0;
 #ifdef HAVE_LIBZ
     }
 #endif
 
+       if (!AH->OF)
+               die_horribly(AH, "%s: could not set output\n", progname);
+
     return sav;
 }
 
 void ResetOutput(ArchiveHandle* AH, OutputContext sav)
 {
+       int                             res;
+
     if (AH->gzOut)
-       GZCLOSE(AH->OF);
+               res = GZCLOSE(AH->OF);
     else
-       fclose(AH->OF);
+               res = fclose(AH->OF);
+
+       if (res != 0)
+               die_horribly(AH, "%s: could not reset the output file\n", progname);
 
     AH->gzOut = sav.gzOut;
     AH->OF = sav.OF;
@@ -1012,9 +1032,19 @@ int ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle* AH)
                return res;
        }
     else if (AH->gzOut)
-               return GZWRITE((void*)ptr, size, nmemb, AH->OF);
+       {
+               res = GZWRITE((void*)ptr, size, nmemb, AH->OF);
+               if (res != (nmemb * size))
+                       die_horribly(AH, "%s: could not write to archive\n", progname);
+               return res;
+       }
     else if (AH->CustomOutPtr)
-               return AH->CustomOutPtr(AH, ptr, size * nmemb);
+       {
+               res = AH->CustomOutPtr(AH, ptr, size * nmemb);
+               if (res != (nmemb * size))
+                       die_horribly(AH, "%s: could not write to custom output routine\n", progname);
+               return res;
+       }
        else
        {
                /*
@@ -1022,9 +1052,14 @@ int ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle* AH)
             * then send it to the DB.
                 */     
                if (RestoringToDB(AH))
-                       return ExecuteSqlCommandBuf(AH, (void*)ptr, size*nmemb);
+                       return ExecuteSqlCommandBuf(AH, (void*)ptr, size*nmemb); /* Always 1, currently */
                else
-                       return fwrite((void*)ptr, size, nmemb, AH->OF);
+               {
+                       res = fwrite((void*)ptr, size, nmemb, AH->OF);
+                       if (res != nmemb)
+                               die_horribly(AH, "%s: could not write to output file (%d != %d)\n", progname, res, nmemb);
+                       return res;
+               }
        }
 }              
 
@@ -1299,7 +1334,8 @@ _discoverArchiveFormat(ArchiveHandle* AH)
 
     /* Close the file */
     if (wantClose)
-               fclose(fh);
+               if (fclose(fh) != 0)
+                       die_horribly(AH, "%s: could not close the input file after reading header\n", progname);
 
     return AH->format;
 }
@@ -1342,7 +1378,7 @@ static ArchiveHandle* _allocAH(const char* FileSpec, const ArchiveFormat fmt,
                AH->fSpec = NULL;
     } 
 
-    AH->currUser = "";
+    AH->currUser = strdup(""); /* So it's valid, but we can free() it later if necessary */ 
 
     AH->toc = (TocEntry*)calloc(1, sizeof(TocEntry));
     if (!AH->toc)
@@ -1455,7 +1491,7 @@ void WriteToc(ArchiveHandle* AH)
        if (AH->WriteExtraTocPtr) {
            (*AH->WriteExtraTocPtr)(AH, te);
        }
-       te = te->next;
+               te = te->next;
     }
 }
 
@@ -1585,7 +1621,12 @@ static void _reconnectAsUser(ArchiveHandle* AH, const char *dbname, char *user)
                {
                        ahprintf(AH, "\\connect %s %s\n", dbname, user);
                }
-               AH->currUser = user;
+               if (AH->currUser) 
+               {
+                       free(AH->currUser);
+               }
+
+               AH->currUser = strdup(user);
     } 
 }
 
index 2c7291e..9a9c2e7 100644 (file)
@@ -44,7 +44,7 @@
 #define GZREAD(p, s, n, fh) gzread(fh, p, n * s)
 #else
 #define GZCLOSE(fh) fclose(fh)
-#define GZWRITE(p, s, n, fh) fwrite(p, s, n, fh)
+#define GZWRITE(p, s, n, fh) (fwrite(p, s, n, fh) * s)
 #define GZREAD(p, s, n, fh) fread(p, s, n, fh)
 #define Z_DEFAULT_COMPRESSION -1
 
@@ -62,7 +62,7 @@ typedef z_stream *z_streamp;
 
 #define K_VERS_MAJOR 1
 #define K_VERS_MINOR 4 
-#define K_VERS_REV 22 
+#define K_VERS_REV 23 
 
 /* Data block types */
 #define BLK_DATA 1
index e44f022..6256257 100644 (file)
  *
  *     Initial version. 
  *
+ * Modifications - 04-Jan-2001 - pjw@rhyme.com.au
+ *
+ *    - Check results of IO routines more carefully.
+ *
  *-------------------------------------------------------------------------
  */
 
@@ -164,7 +168,7 @@ void InitArchiveFmt_Custom(ArchiveHandle* AH)
                        AH->FH = stdout;
                }
 
-               if (!AH)
+               if (!AH->FH)
                        die_horribly(AH, "%s: unable to open archive file %s",progname, AH->fSpec);
 
                ctx->hasSeek = (fseek(AH->FH, 0, SEEK_CUR) == 0);
@@ -176,7 +180,7 @@ void InitArchiveFmt_Custom(ArchiveHandle* AH)
                } else {
                        AH->FH = stdin;
                }
-               if (!AH)
+               if (!AH->FH)
                        die_horribly(AH, "%s: unable to open archive file %s",progname, AH->fSpec);
 
                ctx->hasSeek = (fseek(AH->FH, 0, SEEK_CUR) == 0);
@@ -666,6 +670,8 @@ static int  _WriteByte(ArchiveHandle* AH, const int i)
     res = fputc(i, AH->FH);
     if (res != EOF) {
                ctx->filePos += 1;
+       } else {
+               die_horribly(AH, "%s: could not write byte./n",progname);
     }
     return res;
 }
@@ -705,6 +711,10 @@ static int _WriteBuf(ArchiveHandle* AH, const void* buf, int len)
     lclContext*                ctx = (lclContext*)AH->formatData;
     int                        res;
     res = fwrite(buf, 1, len, AH->FH);
+
+       if (res != len)
+               die_horribly(AH, "%s: write error in _WriteBuf (%d != %d)\n", progname, res, len);
+
     ctx->filePos += res;
     return res;
 }
@@ -764,7 +774,9 @@ static void _CloseArchive(ArchiveHandle* AH)
                }
     }
 
-    fclose(AH->FH);
+    if (fclose(AH->FH) != 0)
+               die_horribly(AH, "%s: could not close archive file\n",progname);
+
     AH->FH = NULL; 
 }
 
@@ -873,7 +885,8 @@ static int  _DoDeflate(ArchiveHandle* AH, lclContext* ctx, int flush)
                        if (zp->avail_out < zlibOutSize) {
                                /* printf("Wrote %d byte deflated chunk\n", zlibOutSize - zp->avail_out); */
                                WriteInt(AH, zlibOutSize - zp->avail_out);
-                               fwrite(out, 1, zlibOutSize - zp->avail_out, AH->FH);
+                               if (fwrite(out, 1, zlibOutSize - zp->avail_out, AH->FH) != (zlibOutSize - zp->avail_out))
+                                       die_horribly(AH, "%s: could write compressed chunk\n",progname);
                                ctx->filePos += zlibOutSize - zp->avail_out;
                        }
                        zp->next_out = out;
@@ -884,7 +897,8 @@ static int  _DoDeflate(ArchiveHandle* AH, lclContext* ctx, int flush)
                if (zp->avail_in > 0)
                {
                        WriteInt(AH, zp->avail_in);
-                       fwrite(zp->next_in, 1, zp->avail_in, AH->FH);
+                       if (fwrite(zp->next_in, 1, zp->avail_in, AH->FH) != zp->avail_in)
+                               die_horribly(AH, "%s: could write uncompressed chunk\n", progname);
                        ctx->filePos += zp->avail_in;
                        zp->avail_in = 0;
                } else {
index d84e25e..763d94f 100644 (file)
@@ -1,5 +1,14 @@
 /*-------------------------------------------------------------------------
  *
+ * pg_backup_db.c
+ *
+ *  Implements the basic DB functions used by the archiver.
+ *
+ * IDENTIFICATION
+ *
+ * Modifications - 04-Jan-2001 - pjw@rhyme.com.au
+ *
+ *    - Check results of PQ routines more carefully.
  *
  *-------------------------------------------------------------------------
  */
@@ -449,14 +458,17 @@ int ExecuteSqlCommandBuf(ArchiveHandle* AH, void *qryv, int bufLen)
 
                                /* fprintf(stderr, "Sending '%s' via COPY (at end = %d)\n\n", AH->pgCopyBuf->data, isEnd); */ 
                                
-                               PQputline(AH->connection, AH->pgCopyBuf->data);
+                               if (PQputline(AH->connection, AH->pgCopyBuf->data) != 0)
+                                       die_horribly(AH, "%s: error returned by PQputline\n", progname);
 
                                resetPQExpBuffer(AH->pgCopyBuf);
 
                                /* fprintf(stderr, "Buffer is '%s'\n", AH->pgCopyBuf->data); */
 
                                if(isEnd) {
-                                       PQendcopy(AH->connection);
+                                       if (PQendcopy(AH->connection) != 0)
+                                               die_horribly(AH, "%s: error returned by PQendcopy\n", progname);
+
                                        AH->pgCopyIn = 0;
                                        break;
                                }
index 1624bf1..22c5d17 100644 (file)
  *
  *     Initial version. 
  *
+ * Modifications - 04-Jan-2001 - pjw@rhyme.com.au
+ *
+ *    - Check results of IO routines more carefully.
+ *
  *-------------------------------------------------------------------------
  */
 
@@ -123,6 +127,10 @@ void InitArchiveFmt_Files(ArchiveHandle* AH)
                } else {
                        AH->FH = stdout;
                }
+
+               if (AH->FH == NULL)
+                       die_horribly(NULL, "%s: Could not open output file\n", progname);
+
                ctx->hasSeek = (fseek(AH->FH, 0, SEEK_CUR) == 0);
 
                if (AH->compression < 0 || AH->compression > 9) {
@@ -137,6 +145,10 @@ void InitArchiveFmt_Files(ArchiveHandle* AH)
                } else {
                        AH->FH = stdin;
                }
+
+               if (AH->FH == NULL)
+                       die_horribly(NULL, "%s: Could not open input file\n", progname);
+
                ctx->hasSeek = (fseek(AH->FH, 0, SEEK_CUR) == 0);
 
                ReadHead(AH);
@@ -221,6 +233,10 @@ static void        _StartData(ArchiveHandle* AH, TocEntry* te)
 #else
     tctx->FH = fopen(tctx->filename, PG_BINARY_W);
 #endif
+
+       if (tctx->FH == NULL)
+               die_horribly(AH, "%s: Could not open data file for output\n", progname);
+
 }
 
 static int     _WriteData(ArchiveHandle* AH, const void* data, int dLen)
@@ -258,6 +274,9 @@ static void _PrintFileData(ArchiveHandle* AH, char *filename, RestoreOptions *ro
     AH->FH = fopen(filename,PG_BINARY_R);
 #endif
 
+       if (AH->FH == NULL)
+               die_horribly(AH, "%s: Could not open data file for input\n", progname);
+
     while ( (cnt = GZREAD(buf, 1, 4095, AH->FH)) > 0) {
                buf[cnt] = '\0';
                ahwrite(buf, 1, cnt, AH);
@@ -322,6 +341,9 @@ static void _LoadBlobs(ArchiveHandle* AH, RestoreOptions *ropt)
 
        ctx->blobToc = fopen("blobs.toc", PG_BINARY_R);
 
+       if (ctx->blobToc == NULL) 
+               die_horribly(AH, "%s: Could not open BLOB TOC for input\n", progname);
+
        _getBlobTocEntry(AH, &oid, fname);
 
     while(oid != 0)
@@ -341,13 +363,13 @@ static void       _LoadBlobs(ArchiveHandle* AH, RestoreOptions *ropt)
 static int     _WriteByte(ArchiveHandle* AH, const int i)
 {
     lclContext*                ctx = (lclContext*)AH->formatData;
-    int                        res;
 
-    res = fputc(i, AH->FH);
-    if (res != EOF) {
-               ctx->filePos += 1;
-    }
-    return res;
+    if (fputc(i, AH->FH) == EOF)
+               die_horribly(AH, "%s: could not write byte\n", progname);
+
+       ctx->filePos += 1;
+
+    return 1;
 }
 
 static int     _ReadByte(ArchiveHandle* AH)
@@ -367,6 +389,9 @@ static int  _WriteBuf(ArchiveHandle* AH, const void* buf, int len)
     lclContext*                ctx = (lclContext*)AH->formatData;
     int                        res;
     res = fwrite(buf, 1, len, AH->FH);
+       if (res != len)
+               die_horribly(AH, "%s: write error in _WriteBuf (%d != %d)\n", progname, res, len);
+
     ctx->filePos += res;
     return res;
 }
@@ -416,7 +441,10 @@ static void        _StartBlobs(ArchiveHandle* AH, TocEntry* te)
 
        sprintf(fname, "blobs.toc");
        ctx->blobToc = fopen(fname, PG_BINARY_W);
+
+       if (ctx->blobToc == NULL)
+               die_horribly(AH, "%s: could not open BLOB TOC for output\n", progname);
+
 }
 
 /*
@@ -453,6 +481,8 @@ static void _StartBlob(ArchiveHandle* AH, TocEntry* te, int oid)
     tctx->FH = fopen(fname, PG_BINARY_W);
 #endif
 
+       if (tctx->FH == NULL)
+               die_horribly(AH, "%s: Could not open BLOB file\n", progname);
 }
 
 /*
index e6f81bb..26c30bd 100644 (file)
  *
  *     Initial version. 
  *
+ * Modifications - 04-Jan-2001 - pjw@rhyme.com.au
+ *
+ *    - Check results of IO routines more carefully.
+ *
+ *
  *-------------------------------------------------------------------------
  */
 
index 8e16899..d9adffb 100644 (file)
  *
  *     Initial version. 
  *
+ * Modifications - 04-Jan-2001 - pjw@rhyme.com.au
+ *
+ *    - Check results of IO routines more carefully.
+ *
  *-------------------------------------------------------------------------
  */
 
@@ -156,6 +160,10 @@ void InitArchiveFmt_Tar(ArchiveHandle* AH)
                } else {
                        ctx->tarFH = stdout;
                }
+
+               if (ctx->tarFH == NULL) 
+                       die_horribly(NULL, "%s: Could not open TOC file for output.\n", progname);
+
                ctx->tarFHpos = 0;
 
                /* Make unbuffered since we will dup() it, and the buffers screw each other */
@@ -185,6 +193,9 @@ void InitArchiveFmt_Tar(ArchiveHandle* AH)
                        ctx->tarFH = stdin;
                }
 
+               if (ctx->tarFH == NULL)
+                       die_horribly(NULL, "%s: Could not open TOC file for input\n", progname);
+
                /* Make unbuffered since we will dup() it, and the buffers screw each other */
                /* setvbuf(ctx->tarFH, NULL, _IONBF, 0); */
 
@@ -311,12 +322,18 @@ static TAR_MEMBER* tarOpen(ArchiveHandle *AH, const char *filename, char mode)
 
                tm->tmpFH = tmpfile();
 
+               if (tm->tmpFH == NULL) 
+                       die_horribly(AH, "%s: could not generate temp file name.\n", progname);
+
 #ifdef HAVE_LIBZ
 
                if (AH->compression != 0)
                {
                        sprintf(fmode, "wb%d", AH->compression);
                        tm->zFH = gzdopen(dup(fileno(tm->tmpFH)), fmode);
+                       if (tm->zFH == NULL)
+                               die_horribly(AH, "%s: could not gzdopen temp file.\n", progname);
+
                } else 
                        tm->nFH = tm->tmpFH;
 
@@ -343,7 +360,8 @@ static void tarClose(ArchiveHandle *AH, TAR_MEMBER* th)
         * Close the GZ file since we dup'd. This will flush the buffers.
         */
        if (AH->compression != 0)
-               GZCLOSE(th->zFH);
+               if (GZCLOSE(th->zFH) != 0)
+                       die_horribly(AH, "%s: could not close tar member\n", progname);
 
        if (th->mode == 'w')
                _tarAddFile(AH, th); /* This will close the temp file */
@@ -477,6 +495,9 @@ static int tarWrite(const void *buf, int len, TAR_MEMBER *th)
        else
                res = fwrite(buf, 1, len, th->nFH);
 
+       if (res != len)
+               die_horribly(th->AH, "%s: could not write to tar member (%d != %d)\n", progname, res, len);
+
        th->pos += res;
        return res;
 }
@@ -485,9 +506,7 @@ static int  _WriteData(ArchiveHandle* AH, const void* data, int dLen)
 {
     lclTocEntry*       tctx = (lclTocEntry*)AH->currToc->formatData;
 
-       tarWrite((void*)data, dLen, tctx->TH);
-
-    /* GZWRITE((void*)data, 1, dLen, tctx->TH->FH); */
+       dLen = tarWrite((void*)data, dLen, tctx->TH);
 
     return dLen;
 }
@@ -767,7 +786,8 @@ static void _CloseArchive(ArchiveHandle* AH)
                /* Add a block of NULLs since it's de-rigeur. */
                for(i=0; i<512; i++) 
                {
-                       fputc(0, ctx->tarFH);
+                       if (fputc(0, ctx->tarFH) == EOF)
+                               die_horribly(AH, "%s: could not write null block at end of TAR archive.\n", progname);
                }
 
     }
@@ -928,6 +948,7 @@ static void _tarAddFile(ArchiveHandle *AH, TAR_MEMBER* th)
        char            buf[32768];
        int                     cnt;
        int                     len = 0;
+       int                     res;
        int                     i, pad;
 
        /*
@@ -941,19 +962,25 @@ static void _tarAddFile(ArchiveHandle *AH, TAR_MEMBER* th)
 
        while ( (cnt = fread(&buf[0], 1, 32767, tmp)) > 0)
        {
-               fwrite(&buf[0], 1, cnt, th->tarFH);
-               len += cnt;
+               res = fwrite(&buf[0], 1, cnt, th->tarFH);
+               if (res != cnt) 
+                       die_horribly(AH, "%s: write error appending to TAR archive (%d != %d).\n", progname, res, cnt);
+               len += res;
        }
 
-       fclose(tmp); /* This *should* delete it... */
+       if (fclose(tmp) != 0) /* This *should* delete it... */
+               die_horribly(AH, "%s: Could not close tar member (fclose failed).\n", progname);
 
        if (len != th->fileLen)
-               die_horribly(AH, "%s: Actual file length does not match expected (%d vs. %d)\n",
+               die_horribly(AH, "%s: Actual file length does not match expected (%d vs. %d).\n",
                                                progname, len, th->pos);
 
        pad = ((len + 511) & ~511) - len;
     for (i=0 ; i < pad ; i++)
-               fputc('\0',th->tarFH);  
+       {
+               if (fputc('\0',th->tarFH) == EOF) 
+                       die_horribly(AH, "%s: Could not output padding at end of tar member.\n", progname);
+       }       
 
        ctx->tarFHpos += len + pad;
 }
@@ -1131,5 +1158,8 @@ static void _tarWriteHeader(TAR_MEMBER* th)
                lastSum = sum;
        }
 
-       fwrite(h, 1, 512, th->tarFH);
+       if (fwrite(h, 1, 512, th->tarFH) != 512) {
+               die_horribly(th->AH, "%s: unable to write tar header\n", progname);
+       }
+
 }
index 69bd866..ba10354 100644 (file)
@@ -22,7 +22,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.185 2001/01/06 20:57:26 petere Exp $
+ *       $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.186 2001/01/12 04:32:07 pjw Exp $
  *
  * Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb
  *
  *             table with the currently implementation, and (b) it's not clear how to restore
  *             a partial BLOB backup (given the current OID-based BLOB implementation).
  *
+ * Modifications - 04-Jan-2000 - pjw@rhyme.com.au
+ *
+ *       - Check ntuples == 1 for various SELECT statements.
+ *       - Fix handling of --tables=* (multiple tables never worked properly, AFAICT)
+ *
  *-------------------------------------------------------------------------
  */
 
@@ -213,7 +218,7 @@ help(const char *progname)
                "  -s, --schema-only        dump out only the schema, no data\n"
                "  -S, --superuser=NAME     specify the superuser user name to use in plain\n"
                "                           text format\n"
-               "  -t, --table=TABLE        dump for this table only\n"
+               "  -t, --table=TABLE        dump for this table only (* for all)\n"
                "  -u, --password           use password authentication\n"
                "  -v, --verbose            verbose\n"
                "  -x, --no-acl             do not dump ACL's (grant/revoke)\n"
@@ -242,7 +247,7 @@ help(const char *progname)
                "  -s                       dump out only the schema, no data\n"
                "  -S NAME                  specify the superuser user name to use in plain\n"
                "                           text format\n"
-               "  -t TABLE                 dump for this table only\n"
+               "  -t TABLE                 dump for this table only (* for all)\n"
                "  -u                       use password authentication\n"
                "  -v                       verbose\n"
                "  -x                       do not dump ACL's (grant/revoke)\n"
@@ -562,7 +567,7 @@ dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
        char                    copyBuf[512];
        char                    *copyStmt;
 
-       if (onlytable == NULL)
+       if (onlytable == NULL || (strlen(onlytable) == 0) )
                all_only = "all";
        else
                all_only = "only";
@@ -576,8 +581,9 @@ dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
        if (g_verbose)
                fprintf(stderr, "%s preparing to dump out the contents of %s %d table%s/sequence%s %s\n",
                                g_comment_start, all_only,
-                               (onlytable == NULL) ? numTables : 1,
-                 (onlytable == NULL) ? "s" : "", (onlytable == NULL) ? "s" : "",
+                               (onlytable == NULL || (strlen(onlytable) == 0)) ? numTables : 1,
+                               (onlytable == NULL || (strlen(onlytable) == 0)) ? "s" : "", 
+                               (onlytable == NULL || (strlen(onlytable) == 0)) ? "s" : "",
                                g_comment_end);
 
        /* Dump SEQUENCEs first (if dataOnly) */
@@ -587,7 +593,7 @@ dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
                {
                        if (!(tblinfo[i].sequence))
                                continue;
-                       if (!onlytable || (!strcmp(tblinfo[i].relname, onlytable)))
+                       if (!onlytable || (strcmp(tblinfo[i].relname, onlytable) == 0) || (strlen(onlytable) == 0) )
                        {
                                if (g_verbose)
                                        fprintf(stderr, "%s dumping out schema of sequence '%s' %s\n",
@@ -609,7 +615,7 @@ dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
                if (tblinfo[i].sequence)/* already dumped */
                        continue;
 
-               if (!onlytable || (!strcmp(classname, onlytable)))
+               if (!onlytable || (strcmp(classname, onlytable) == 0) || (strlen(onlytable) == 0))
                {
                        if (g_verbose)
                                fprintf(stderr, "%s preparing to dump out the contents of Table '%s' %s\n",
@@ -847,6 +853,11 @@ main(int argc, char **argv)
                                                for (i = 0; tablename[i]; i++)
                                                        if (isupper((unsigned char) tablename[i]))
                                                                tablename[i] = tolower((unsigned char) tablename[i]);
+
+                                               /* '*' is a special case meaning ALL tables, but only if unquoted */
+                                               if (strcmp(tablename,"*") == 0)
+                                                       tablename[0] = '\0';
+
                                        }
                                }
                                break;
@@ -901,10 +912,10 @@ main(int argc, char **argv)
                exit(1);
        }
 
-       if (outputBlobs && (tablename != NULL) )
+       if (outputBlobs && tablename != NULL && strlen(tablename) > 0 )
        {
                fprintf(stderr,
-                               "%s: BLOB output is not supported for a single table. Use a full dump instead.\n",
+                               "%s: BLOB output is not supported for a single table. Use all tables or a full dump instead.\n",
                                progname);
                exit(1);
        }
@@ -2301,6 +2312,7 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
                                if (findx == numFuncs)
                                {
                                        PGresult   *r;
+                                       int                     numFuncs;
 
                                        /*
                                         * the funcname is an oid which we use to find the
@@ -2318,9 +2330,19 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
                                        r = PQexec(g_conn, query->data);
                                        if (!r || PQresultStatus(r) != PGRES_TUPLES_OK)
                                        {
-                                               fprintf(stderr, "getTables(): SELECT (funcname) failed.  Explanation from backend: '%s'.\n", PQerrorMessage(g_conn));
+                                               fprintf(stderr, "getTables(): SELECT (funcname) failed for trigger %s.  Explanation from backend: '%s'.\n", 
+                                                                       PQgetvalue(res2, i2, i_tgname), PQerrorMessage(g_conn));
+                                               exit_nicely(g_conn);
+                                       }
+
+                                       /* Sanity: Check we got only one tuple */
+                                       numFuncs = PQntuples(r);
+                                       if (numFuncs != 1) {
+                                               fprintf(stderr, "getTables(): SELECT (funcname) for trigger %s returned %d tuples. Expected 1.\n", 
+                                                                       PQgetvalue(res2, i2, i_tgname), numFuncs);
                                                exit_nicely(g_conn);
                                        }
+
                                        tgfunc = strdup(PQgetvalue(r, 0, PQfnumber(r, "proname")));
                                        PQclear(r);
                                }
@@ -2607,6 +2629,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                        if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
                        {
                                PGresult   *res2;
+                               int                     numAttr;
 
                                if (g_verbose)
                                        fprintf(stderr, "%s finding DEFAULT expression for attr: '%s' %s\n",
@@ -2626,6 +2649,15 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                                                        "Explanation from backend: '%s'.\n", PQerrorMessage(g_conn));
                                        exit_nicely(g_conn);
                                }
+
+                               /* Sanity: Check we got only one tuple */
+                               numAttr = PQntuples(res2);
+                               if (numAttr != 1) {
+                                       fprintf(stderr, "getTableAttrs(): SELECT (for DEFAULT) for attr %s returned %d tuples. Expected 1.\n", 
+                                                                               tblinfo[i].attnames[j], numAttr);
+                                       exit_nicely(g_conn);
+                               }
+
                                tblinfo[i].adef_expr[j] = strdup(PQgetvalue(res2, 0, PQfnumber(res2, "adsrc")));
                                PQclear(res2);
                        }
@@ -3539,7 +3571,7 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
        char       *reltypename;
 
        /* First - dump SEQUENCEs */
-       if (tablename)
+       if (tablename && strlen(tablename) > 0)
        {
                serialSeq = malloc(strlen(tablename) + strlen(serialSeqSuffix) + 1);
                strcpy(serialSeq, tablename);
@@ -3566,7 +3598,7 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
                if (tblinfo[i].sequence)/* already dumped */
                        continue;
 
-               if (!tablename || (!strcmp(tblinfo[i].relname, tablename)))
+               if (!tablename || (!strcmp(tblinfo[i].relname, tablename)) || (strlen(tablename) == 0))
                {
 
                        resetPQExpBuffer(delq);
@@ -3727,6 +3759,7 @@ dumpIndices(Archive *fout, IndInfo *indinfo, int numIndices,
                        funcname = NULL;
                else
                {
+                       int             numFuncs;
 
                        /*
                         * the funcname is an oid which we use to find the name of the
@@ -3746,6 +3779,15 @@ dumpIndices(Archive *fout, IndInfo *indinfo, int numIndices,
                                                "Explanation from backend: '%s'.\n", PQerrorMessage(g_conn));
                                exit_nicely(g_conn);
                        }
+
+                       /* Sanity: Check we got only one tuple */
+                       numFuncs = PQntuples(res);
+                       if (numFuncs != 1) {
+                               fprintf(stderr, "dumpIndices(): SELECT (funcname) for index %s returned %d tuples. Expected 1.\n", 
+                                                               indinfo[i].indrelname, numFuncs);
+                               exit_nicely(g_conn);
+                       }
+
                        funcname = strdup(PQgetvalue(res, 0, PQfnumber(res, "proname")));
                        PQclear(res);
                }
@@ -3753,6 +3795,8 @@ dumpIndices(Archive *fout, IndInfo *indinfo, int numIndices,
                /* convert opclass oid(s) into names */
                for (nclass = 0; nclass < INDEX_MAX_KEYS; nclass++)
                {
+                       int             numRows;
+
                        indclass = atoi(indinfo[i].indclass[nclass]);
                        if (indclass == 0)
                                break;
@@ -3768,6 +3812,15 @@ dumpIndices(Archive *fout, IndInfo *indinfo, int numIndices,
                                                                        "Explanation from backend: '%s'.\n", PQerrorMessage(g_conn));
                                exit_nicely(g_conn);
                        }
+
+                       /* Sanity: Check we got only one tuple */
+                       numRows = PQntuples(res);
+                       if (numRows != 1) {
+                               fprintf(stderr, "dumpIndices(): SELECT (classname) for index %s returned %d tuples. Expected 1.\n", 
+                                                                       indinfo[i].indrelname, numRows);
+                               exit_nicely(g_conn);
+                       }
+
                        classname[nclass] = strdup(PQgetvalue(res, 0, PQfnumber(res, "opcname")));
                        PQclear(res);
                }
@@ -3815,7 +3868,7 @@ dumpIndices(Archive *fout, IndInfo *indinfo, int numIndices,
                        }
                }
 
-               if (!tablename || (!strcmp(indinfo[i].indrelname, tablename)))
+               if (!tablename || (strcmp(indinfo[i].indrelname, tablename) == 0) || (strlen(tablename) == 0) )
                {
 
                        /*
@@ -4140,8 +4193,9 @@ dumpTriggers(Archive *fout, const char *tablename,
 
        for (i = 0; i < numTables; i++)
        {
-               if (tablename && strcmp(tblinfo[i].relname, tablename))
+               if (tablename && (strcmp(tblinfo[i].relname, tablename) != 0) && (strlen(tablename) > 0) )
                        continue;
+
                for (j = 0; j < tblinfo[i].ntrig; j++)
                {
                        ArchiveEntry(fout, tblinfo[i].triggers[j].oid, tblinfo[i].triggers[j].tgname,
@@ -4177,7 +4231,7 @@ dumpRules(Archive *fout, const char *tablename,
         */
        for (t = 0; t < numTables; t++)
        {
-               if (tablename && strcmp(tblinfo[t].relname, tablename))
+               if (tablename && (strcmp(tblinfo[t].relname, tablename) != 0) && (strlen(tablename) > 0) )
                        continue;
 
                /*