Speed up printing of INSERT statements in pg_dump.
authorTom Lane
Fri, 15 Nov 2013 23:02:06 +0000 (18:02 -0500)
committerTom Lane
Fri, 15 Nov 2013 23:02:06 +0000 (18:02 -0500)
In --inserts and especially --column-inserts mode, we can get a useful
speedup by generating the common prefix of all a table's INSERT commands
just once, and then printing the prebuilt string for each row.  This avoids
multiple invocations of fmtId() and other minor fooling around.

David Rowley

src/bin/pg_dump/pg_dump.c

index 769058d78b938736b04a0fa0c45c127b8926bed9..6c16b3ca49e6ad364117bf4d47c554476cd94cb5 100644 (file)
@@ -1550,6 +1550,7 @@ dumpTableData_insert(Archive *fout, void *dcontext)
    TableInfo  *tbinfo = tdinfo->tdtable;
    const char *classname = tbinfo->dobj.name;
    PQExpBuffer q = createPQExpBuffer();
+   PQExpBuffer insertStmt = NULL;
    PGresult   *res;
    int         tuple;
    int         nfields;
@@ -1591,34 +1592,57 @@ dumpTableData_insert(Archive *fout, void *dcontext)
        nfields = PQnfields(res);
        for (tuple = 0; tuple < PQntuples(res); tuple++)
        {
-           archprintf(fout, "INSERT INTO %s ", fmtId(classname));
-           if (nfields == 0)
+           /*
+            * First time through, we build as much of the INSERT statement as
+            * possible in "insertStmt", which we can then just print for each
+            * line. If the table happens to have zero columns then this will
+            * be a complete statement, otherwise it will end in "VALUES(" and
+            * be ready to have the row's column values appended.
+            */
+           if (insertStmt == NULL)
            {
+               insertStmt = createPQExpBuffer();
+               appendPQExpBuffer(insertStmt, "INSERT INTO %s ",
+                                 fmtId(classname));
+
                /* corner case for zero-column table */
-               archprintf(fout, "DEFAULT VALUES;\n");
-               continue;
-           }
-           if (column_inserts)
-           {
-               resetPQExpBuffer(q);
-               appendPQExpBuffer(q, "(");
-               for (field = 0; field < nfields; field++)
+               if (nfields == 0)
                {
-                   if (field > 0)
-                       appendPQExpBuffer(q, ", ");
-                   appendPQExpBufferStr(q, fmtId(PQfname(res, field)));
+                   appendPQExpBufferStr(insertStmt, "DEFAULT VALUES;\n");
+               }
+               else
+               {
+                   /* append the list of column names if required */
+                   if (column_inserts)
+                   {
+                       appendPQExpBufferStr(insertStmt, "(");
+                       for (field = 0; field < nfields; field++)
+                       {
+                           if (field > 0)
+                               appendPQExpBufferStr(insertStmt, ", ");
+                           appendPQExpBufferStr(insertStmt,
+                                                fmtId(PQfname(res, field)));
+                       }
+                       appendPQExpBufferStr(insertStmt, ") ");
+                   }
+
+                   appendPQExpBufferStr(insertStmt, "VALUES (");
                }
-               appendPQExpBuffer(q, ") ");
-               archputs(q->data, fout);
            }
-           archprintf(fout, "VALUES (");
+
+           archputs(insertStmt->data, fout);
+
+           /* if it is zero-column table then we're done */
+           if (nfields == 0)
+               continue;
+
            for (field = 0; field < nfields; field++)
            {
                if (field > 0)
-                   archprintf(fout, ", ");
+                   archputs(", ", fout);
                if (PQgetisnull(res, tuple, field))
                {
-                   archprintf(fout, "NULL");
+                   archputs("NULL", fout);
                    continue;
                }
 
@@ -1647,7 +1671,7 @@ dumpTableData_insert(Archive *fout, void *dcontext)
                            const char *s = PQgetvalue(res, tuple, field);
 
                            if (strspn(s, "0123456789 +-eE.") == strlen(s))
-                               archprintf(fout, "%s", s);
+                               archputs(s, fout);
                            else
                                archprintf(fout, "'%s'", s);
                        }
@@ -1661,9 +1685,9 @@ dumpTableData_insert(Archive *fout, void *dcontext)
 
                    case BOOLOID:
                        if (strcmp(PQgetvalue(res, tuple, field), "t") == 0)
-                           archprintf(fout, "true");
+                           archputs("true", fout);
                        else
-                           archprintf(fout, "false");
+                           archputs("false", fout);
                        break;
 
                    default:
@@ -1676,7 +1700,7 @@ dumpTableData_insert(Archive *fout, void *dcontext)
                        break;
                }
            }
-           archprintf(fout, ");\n");
+           archputs(");\n", fout);
        }
 
        if (PQntuples(res) <= 0)
@@ -1687,11 +1711,14 @@ dumpTableData_insert(Archive *fout, void *dcontext)
        PQclear(res);
    }
 
-   archprintf(fout, "\n\n");
+   archputs("\n\n", fout);
 
    ExecuteSqlStatement(fout, "CLOSE _pg_dump_cursor");
 
    destroyPQExpBuffer(q);
+   if (insertStmt != NULL)
+       destroyPQExpBuffer(insertStmt);
+
    return 1;
 }