Commit 97e1ec46 authored by Tom Lane's avatar Tom Lane

Speed up printing of INSERT statements in pg_dump.

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
parent 3172eea0
...@@ -1550,6 +1550,7 @@ dumpTableData_insert(Archive *fout, void *dcontext) ...@@ -1550,6 +1550,7 @@ dumpTableData_insert(Archive *fout, void *dcontext)
TableInfo *tbinfo = tdinfo->tdtable; TableInfo *tbinfo = tdinfo->tdtable;
const char *classname = tbinfo->dobj.name; const char *classname = tbinfo->dobj.name;
PQExpBuffer q = createPQExpBuffer(); PQExpBuffer q = createPQExpBuffer();
PQExpBuffer insertStmt = NULL;
PGresult *res; PGresult *res;
int tuple; int tuple;
int nfields; int nfields;
...@@ -1591,34 +1592,57 @@ dumpTableData_insert(Archive *fout, void *dcontext) ...@@ -1591,34 +1592,57 @@ dumpTableData_insert(Archive *fout, void *dcontext)
nfields = PQnfields(res); nfields = PQnfields(res);
for (tuple = 0; tuple < PQntuples(res); tuple++) 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 */ /* corner case for zero-column table */
archprintf(fout, "DEFAULT VALUES;\n"); if (nfields == 0)
continue;
}
if (column_inserts)
{
resetPQExpBuffer(q);
appendPQExpBuffer(q, "(");
for (field = 0; field < nfields; field++)
{ {
if (field > 0) appendPQExpBufferStr(insertStmt, "DEFAULT VALUES;\n");
appendPQExpBuffer(q, ", "); }
appendPQExpBufferStr(q, fmtId(PQfname(res, field))); 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++) for (field = 0; field < nfields; field++)
{ {
if (field > 0) if (field > 0)
archprintf(fout, ", "); archputs(", ", fout);
if (PQgetisnull(res, tuple, field)) if (PQgetisnull(res, tuple, field))
{ {
archprintf(fout, "NULL"); archputs("NULL", fout);
continue; continue;
} }
...@@ -1647,7 +1671,7 @@ dumpTableData_insert(Archive *fout, void *dcontext) ...@@ -1647,7 +1671,7 @@ dumpTableData_insert(Archive *fout, void *dcontext)
const char *s = PQgetvalue(res, tuple, field); const char *s = PQgetvalue(res, tuple, field);
if (strspn(s, "0123456789 +-eE.") == strlen(s)) if (strspn(s, "0123456789 +-eE.") == strlen(s))
archprintf(fout, "%s", s); archputs(s, fout);
else else
archprintf(fout, "'%s'", s); archprintf(fout, "'%s'", s);
} }
...@@ -1661,9 +1685,9 @@ dumpTableData_insert(Archive *fout, void *dcontext) ...@@ -1661,9 +1685,9 @@ dumpTableData_insert(Archive *fout, void *dcontext)
case BOOLOID: case BOOLOID:
if (strcmp(PQgetvalue(res, tuple, field), "t") == 0) if (strcmp(PQgetvalue(res, tuple, field), "t") == 0)
archprintf(fout, "true"); archputs("true", fout);
else else
archprintf(fout, "false"); archputs("false", fout);
break; break;
default: default:
...@@ -1676,7 +1700,7 @@ dumpTableData_insert(Archive *fout, void *dcontext) ...@@ -1676,7 +1700,7 @@ dumpTableData_insert(Archive *fout, void *dcontext)
break; break;
} }
} }
archprintf(fout, ");\n"); archputs(");\n", fout);
} }
if (PQntuples(res) <= 0) if (PQntuples(res) <= 0)
...@@ -1687,11 +1711,14 @@ dumpTableData_insert(Archive *fout, void *dcontext) ...@@ -1687,11 +1711,14 @@ dumpTableData_insert(Archive *fout, void *dcontext)
PQclear(res); PQclear(res);
} }
archprintf(fout, "\n\n"); archputs("\n\n", fout);
ExecuteSqlStatement(fout, "CLOSE _pg_dump_cursor"); ExecuteSqlStatement(fout, "CLOSE _pg_dump_cursor");
destroyPQExpBuffer(q); destroyPQExpBuffer(q);
if (insertStmt != NULL)
destroyPQExpBuffer(insertStmt);
return 1; return 1;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment