Commit 814f40cf authored by Tom Lane's avatar Tom Lane

Use a cursor for fetching data in -d or -D mode, so that pg_dump doesn't

run out of memory with large tables in these modes.  Patch from
Martijn van Oosterhout.
parent 545c6696
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.226 2001/08/27 01:09:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.227 2001/08/27 20:33:07 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -400,77 +400,105 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv) ...@@ -400,77 +400,105 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
if (fout->remoteVersion >= 70100) if (fout->remoteVersion >= 70100)
{ {
appendPQExpBuffer(q, "SELECT * FROM ONLY %s", fmtId(classname, force_quotes)); appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR SELECT * FROM ONLY %s", fmtId(classname, force_quotes));
} else { } else {
appendPQExpBuffer(q, "SELECT * FROM %s", fmtId(classname, force_quotes)); appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR SELECT * FROM %s", fmtId(classname, force_quotes));
} }
res = PQexec(g_conn, q->data); res = PQexec(g_conn, q->data);
if (!res || if (!res ||
PQresultStatus(res) != PGRES_TUPLES_OK) PQresultStatus(res) != PGRES_COMMAND_OK)
{ {
write_msg(NULL, "dumpClasses(): SQL command failed\n"); write_msg(NULL, "dumpClasses(): SQL command failed\n");
write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn)); write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
write_msg(NULL, "The command was: %s\n", q->data); write_msg(NULL, "The command was: %s\n", q->data);
exit_nicely(); exit_nicely();
} }
for (tuple = 0; tuple < PQntuples(res); tuple++)
{ do {
archprintf(fout, "INSERT INTO %s ", fmtId(classname, force_quotes)); PQclear(res);
if (attrNames == true)
res = PQexec(g_conn, "FETCH 100 FROM _pg_dump_cursor");
if (!res ||
PQresultStatus(res) != PGRES_TUPLES_OK)
{ {
resetPQExpBuffer(q); write_msg(NULL, "dumpClasses(): SQL command failed\n");
appendPQExpBuffer(q, "("); write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
for (field = 0; field < PQnfields(res); field++) write_msg(NULL, "The command was: FETCH 100 FROM _pg_dump_cursor\n");
{ exit_nicely();
if (field > 0)
appendPQExpBuffer(q, ",");
appendPQExpBuffer(q, fmtId(PQfname(res, field), force_quotes));
}
appendPQExpBuffer(q, ") ");
archprintf(fout, "%s", q->data);
} }
archprintf(fout, "VALUES (");
for (field = 0; field < PQnfields(res); field++) for (tuple = 0; tuple < PQntuples(res); tuple++)
{ {
if (field > 0) archprintf(fout, "INSERT INTO %s ", fmtId(classname, force_quotes));
archprintf(fout, ","); if (attrNames == true)
if (PQgetisnull(res, tuple, field))
{ {
archprintf(fout, "NULL"); resetPQExpBuffer(q);
continue; appendPQExpBuffer(q, "(");
for (field = 0; field < PQnfields(res); field++)
{
if (field > 0)
appendPQExpBuffer(q, ",");
appendPQExpBuffer(q, fmtId(PQfname(res, field), force_quotes));
}
appendPQExpBuffer(q, ") ");
archprintf(fout, "%s", q->data);
} }
switch (PQftype(res, field)) archprintf(fout, "VALUES (");
for (field = 0; field < PQnfields(res); field++)
{ {
case INT2OID: if (field > 0)
case INT4OID: archprintf(fout, ",");
case OIDOID: /* int types */ if (PQgetisnull(res, tuple, field))
case FLOAT4OID: {
case FLOAT8OID:/* float types */ archprintf(fout, "NULL");
/* These types are printed without quotes */ continue;
archprintf(fout, "%s", }
PQgetvalue(res, tuple, field)); switch (PQftype(res, field))
break; {
case BITOID: case INT2OID:
case VARBITOID: case INT4OID:
archprintf(fout, "B'%s'", case OIDOID: /* int types */
PQgetvalue(res, tuple, field)); case FLOAT4OID:
break; case FLOAT8OID:/* float types */
default: /* These types are printed without quotes */
archprintf(fout, "%s",
/* PQgetvalue(res, tuple, field));
* All other types are printed as string literals, break;
* with appropriate escaping of special characters. case BITOID:
*/ case VARBITOID:
resetPQExpBuffer(q); archprintf(fout, "B'%s'",
formatStringLiteral(q, PQgetvalue(res, tuple, field), CONV_ALL); PQgetvalue(res, tuple, field));
archprintf(fout, "%s", q->data); break;
break; default:
/*
* All other types are printed as string literals,
* with appropriate escaping of special characters.
*/
resetPQExpBuffer(q);
formatStringLiteral(q, PQgetvalue(res, tuple, field), CONV_ALL);
archprintf(fout, "%s", q->data);
break;
}
} }
archprintf(fout, ");\n");
} }
archprintf(fout, ");\n");
} while( PQntuples(res) > 0 );
PQclear(res);
res = PQexec(g_conn, "CLOSE _pg_dump_cursor");
if (!res ||
PQresultStatus(res) != PGRES_COMMAND_OK)
{
write_msg(NULL, "dumpClasses(): SQL command failed\n");
write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
write_msg(NULL, "The command was: CLOSE _pg_dump_cursor\n");
exit_nicely();
} }
PQclear(res); PQclear(res);
destroyPQExpBuffer(q); destroyPQExpBuffer(q);
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