Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 814f40c

Browse files
committed
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.
1 parent 545c669 commit 814f40c

File tree

1 file changed

+79
-51
lines changed

1 file changed

+79
-51
lines changed

src/bin/pg_dump/pg_dump.c

Lines changed: 79 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
*
2323
*
2424
* IDENTIFICATION
25-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.226 2001/08/27 01:09:59 tgl Exp $
25+
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.227 2001/08/27 20:33:07 tgl Exp $
2626
*
2727
*-------------------------------------------------------------------------
2828
*/
@@ -400,77 +400,105 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
400400

401401
if (fout->remoteVersion >= 70100)
402402
{
403-
appendPQExpBuffer(q, "SELECT * FROM ONLY %s", fmtId(classname, force_quotes));
403+
appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR SELECT * FROM ONLY %s", fmtId(classname, force_quotes));
404404
} else {
405-
appendPQExpBuffer(q, "SELECT * FROM %s", fmtId(classname, force_quotes));
405+
appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR SELECT * FROM %s", fmtId(classname, force_quotes));
406406
}
407407

408408
res = PQexec(g_conn, q->data);
409409
if (!res ||
410-
PQresultStatus(res) != PGRES_TUPLES_OK)
410+
PQresultStatus(res) != PGRES_COMMAND_OK)
411411
{
412412
write_msg(NULL, "dumpClasses(): SQL command failed\n");
413413
write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
414414
write_msg(NULL, "The command was: %s\n", q->data);
415415
exit_nicely();
416416
}
417-
for (tuple = 0; tuple < PQntuples(res); tuple++)
418-
{
419-
archprintf(fout, "INSERT INTO %s ", fmtId(classname, force_quotes));
420-
if (attrNames == true)
417+
418+
do {
419+
PQclear(res);
420+
421+
res = PQexec(g_conn, "FETCH 100 FROM _pg_dump_cursor");
422+
if (!res ||
423+
PQresultStatus(res) != PGRES_TUPLES_OK)
421424
{
422-
resetPQExpBuffer(q);
423-
appendPQExpBuffer(q, "(");
424-
for (field = 0; field < PQnfields(res); field++)
425-
{
426-
if (field > 0)
427-
appendPQExpBuffer(q, ",");
428-
appendPQExpBuffer(q, fmtId(PQfname(res, field), force_quotes));
429-
}
430-
appendPQExpBuffer(q, ") ");
431-
archprintf(fout, "%s", q->data);
425+
write_msg(NULL, "dumpClasses(): SQL command failed\n");
426+
write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
427+
write_msg(NULL, "The command was: FETCH 100 FROM _pg_dump_cursor\n");
428+
exit_nicely();
432429
}
433-
archprintf(fout, "VALUES (");
434-
for (field = 0; field < PQnfields(res); field++)
430+
431+
for (tuple = 0; tuple < PQntuples(res); tuple++)
435432
{
436-
if (field > 0)
437-
archprintf(fout, ",");
438-
if (PQgetisnull(res, tuple, field))
433+
archprintf(fout, "INSERT INTO %s ", fmtId(classname, force_quotes));
434+
if (attrNames == true)
439435
{
440-
archprintf(fout, "NULL");
441-
continue;
436+
resetPQExpBuffer(q);
437+
appendPQExpBuffer(q, "(");
438+
for (field = 0; field < PQnfields(res); field++)
439+
{
440+
if (field > 0)
441+
appendPQExpBuffer(q, ",");
442+
appendPQExpBuffer(q, fmtId(PQfname(res, field), force_quotes));
443+
}
444+
appendPQExpBuffer(q, ") ");
445+
archprintf(fout, "%s", q->data);
442446
}
443-
switch (PQftype(res, field))
447+
archprintf(fout, "VALUES (");
448+
for (field = 0; field < PQnfields(res); field++)
444449
{
445-
case INT2OID:
446-
case INT4OID:
447-
case OIDOID: /* int types */
448-
case FLOAT4OID:
449-
case FLOAT8OID:/* float types */
450-
/* These types are printed without quotes */
451-
archprintf(fout, "%s",
452-
PQgetvalue(res, tuple, field));
453-
break;
454-
case BITOID:
455-
case VARBITOID:
456-
archprintf(fout, "B'%s'",
457-
PQgetvalue(res, tuple, field));
458-
break;
459-
default:
460-
461-
/*
462-
* All other types are printed as string literals,
463-
* with appropriate escaping of special characters.
464-
*/
465-
resetPQExpBuffer(q);
466-
formatStringLiteral(q, PQgetvalue(res, tuple, field), CONV_ALL);
467-
archprintf(fout, "%s", q->data);
468-
break;
450+
if (field > 0)
451+
archprintf(fout, ",");
452+
if (PQgetisnull(res, tuple, field))
453+
{
454+
archprintf(fout, "NULL");
455+
continue;
456+
}
457+
switch (PQftype(res, field))
458+
{
459+
case INT2OID:
460+
case INT4OID:
461+
case OIDOID: /* int types */
462+
case FLOAT4OID:
463+
case FLOAT8OID:/* float types */
464+
/* These types are printed without quotes */
465+
archprintf(fout, "%s",
466+
PQgetvalue(res, tuple, field));
467+
break;
468+
case BITOID:
469+
case VARBITOID:
470+
archprintf(fout, "B'%s'",
471+
PQgetvalue(res, tuple, field));
472+
break;
473+
default:
474+
475+
/*
476+
* All other types are printed as string literals,
477+
* with appropriate escaping of special characters.
478+
*/
479+
resetPQExpBuffer(q);
480+
formatStringLiteral(q, PQgetvalue(res, tuple, field), CONV_ALL);
481+
archprintf(fout, "%s", q->data);
482+
break;
483+
}
469484
}
485+
archprintf(fout, ");\n");
470486
}
471-
archprintf(fout, ");\n");
487+
488+
} while( PQntuples(res) > 0 );
489+
PQclear(res);
490+
491+
res = PQexec(g_conn, "CLOSE _pg_dump_cursor");
492+
if (!res ||
493+
PQresultStatus(res) != PGRES_COMMAND_OK)
494+
{
495+
write_msg(NULL, "dumpClasses(): SQL command failed\n");
496+
write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
497+
write_msg(NULL, "The command was: CLOSE _pg_dump_cursor\n");
498+
exit_nicely();
472499
}
473500
PQclear(res);
501+
474502
destroyPQExpBuffer(q);
475503
return 1;
476504
}

0 commit comments

Comments
 (0)