From cc3f73c98e9010d63ed9bdedbb2a4dc5aeb41830 Mon Sep 17 00:00:00 2001 From: Paul Hoffman Date: Tue, 17 Sep 2019 13:00:03 -0400 Subject: [PATCH] Bug 23624: Count rows in report without (potentially) consuming all memory C4::Reports::Guided::nb_rows (called by get_prepped_report in reports/guided_reports.pl) uses DBI::fetchall_arrayref to retrieve all rows at once; counts them; and then discards the rows and returns the count. This has the potential, if the number of rows is very large, to exhaust all available memory. (Other code in guided_reports.pl has the same potential effect, but because the solution to that is much less straightforward it will be addressed in a separate bug report.) This patch uses the second ($max_rows) parameter to DBI::fetchall_arrayref to retrieve a smaller number (1,000) of rows at a time, looping until all results have been retrieved. This will only use as much memory as the maximum amount used by a single call to DBI::fetchall_arrayref. Test Plan: 1) Create a report the will generate a huge number of results 2) Run the report, watch your memory usage spike 3) Apply this patch 4) Restart all the things! 5) Run the report again, note your memory usage is much lower Signed-off-by: Kyle M Hall Signed-off-by: Tomas Cohen Arazi --- C4/Reports/Guided.pm | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/C4/Reports/Guided.pm b/C4/Reports/Guided.pm index 08c554f55d..aae069195f 100644 --- a/C4/Reports/Guided.pm +++ b/C4/Reports/Guided.pm @@ -420,8 +420,13 @@ sub nb_rows { my $sql = shift or return; my $sth = C4::Context->dbh->prepare($sql); $sth->execute(); - my $rows = $sth->fetchall_arrayref(); - return scalar (@$rows); + my $n = 0; + # Loop through the complete results, fetching 1,000 rows at a time. This + # lowers memory requirements but increases execution time. + while (my $rows = $sth->fetchall_arrayref(undef, 1000)) { + $n += @$rows; + } + return $n; } =head2 execute_query -- 2.23.0