1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-03 22:24:49 +03:00

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.
This commit is contained in:
Tom Lane 2001-08-27 20:33:07 +00:00
parent 545c6696a6
commit 814f40cf43

View File

@ -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)
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));
write_msg(NULL, "The command was: FETCH 100 FROM _pg_dump_cursor\n");
exit_nicely();
}
for (tuple = 0; tuple < PQntuples(res); tuple++)
{
archprintf(fout, "INSERT INTO %s ", fmtId(classname, force_quotes));
if (attrNames == true)
{
resetPQExpBuffer(q);
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);
}
archprintf(fout, "VALUES (");
for (field = 0; field < PQnfields(res); field++) for (field = 0; field < PQnfields(res); field++)
{ {
if (field > 0) if (field > 0)
appendPQExpBuffer(q, ","); archprintf(fout, ",");
appendPQExpBuffer(q, fmtId(PQfname(res, field), force_quotes)); if (PQgetisnull(res, tuple, field))
} {
appendPQExpBuffer(q, ") "); archprintf(fout, "NULL");
archprintf(fout, "%s", q->data); continue;
} }
archprintf(fout, "VALUES ("); switch (PQftype(res, field))
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));
break;
case BITOID:
case VARBITOID:
archprintf(fout, "B'%s'",
PQgetvalue(res, tuple, field));
break;
default:
/* /*
* All other types are printed as string literals, * All other types are printed as string literals,
* with appropriate escaping of special characters. * with appropriate escaping of special characters.
*/ */
resetPQExpBuffer(q); resetPQExpBuffer(q);
formatStringLiteral(q, PQgetvalue(res, tuple, field), CONV_ALL); formatStringLiteral(q, PQgetvalue(res, tuple, field), CONV_ALL);
archprintf(fout, "%s", q->data); archprintf(fout, "%s", q->data);
break; 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;
} }