1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-27 07:42:10 +03:00

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
This commit is contained in:
Tom Lane
2013-11-15 18:02:06 -05:00
parent 3172eea062
commit 97e1ec4670

View File

@@ -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)
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)
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)
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)
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)
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;
} }