teach Clark Kent how to limit the size of a resultset
authorGalen Charlton <gmc@esilibrary.com>
Fri, 20 Mar 2015 21:21:16 +0000 (21:21 +0000)
committerGalen Charlton <gmc@esilibrary.com>
Fri, 20 Mar 2015 21:21:16 +0000 (21:21 +0000)
A report that returns too many rows may consume memory
to not good effect.  This patch adds a new command-line
parameter to Clark Kent, --resultset-limit, to allow
report results to be truncated at the specified number of
rows.  Since the user cannot know how many results the
report would have had without the limit, the main
purpose of this patch is to reduce the chance that
clark-kent.pl will trigger OOM-killer.

Signed-off-by: Galen Charlton <gmc@esilibrary.com>
Open-ILS/src/perlmods/lib/OpenILS/Reporter/SQLBuilder.pm
Open-ILS/src/reporter/clark-kent.pl

index 940972a..3291a4f 100644 (file)
@@ -38,6 +38,13 @@ sub relative_time {
     return $self->builder->{_relative_time};
 }
 
+sub resultset_limit {
+    my $self = shift;
+    my $limit = shift;
+    $self->builder->{_resultset_limit} = $limit if (defined $limit);
+    return self->builder->{_resultset_limit};
+}
+
 sub resolve_param {
     my $self = shift;
     my $val = shift;
@@ -237,6 +244,8 @@ sub toSQL {
 
     if ($self->is_subquery) {
         $sql = '(';
+    } elsif ($self->resultset_limit) {
+        $sql = 'SELECT * FROM (';
     }
 
     $sql .= "SELECT\t" . join(",\n\t", map { $_->toSQL } @{ $self->{_select} }) . "\n" if (@{ $self->{_select} });
@@ -251,6 +260,9 @@ sub toSQL {
 
     if ($self->is_subquery) {
         $sql .= ') '. $self->{_alias} . "\n";
+    } elsif ($self->resultset_limit) {
+        $sql .= ') limited_to_' . $self->resultset_limit .
+                '_hits LIMIT ' . $self->resultset_limit . "\n";
     }
 
     return $self->{_sql} = $sql;
index 3821011..de8d806 100755 (executable)
@@ -35,12 +35,14 @@ my ($count, $config, $sleep_interval, $lockfile, $daemon) = (1, 'SYSCONFDIR/open
 # before Clark refuses to try to draw a chart
 my $max_rows_for_charts = 1000;
 my $statement_timeout = 10 * 60 * 1000;
+my $resultset_limit;
 
 GetOptions(
        "daemon"        => \$daemon,
        "sleep=i"       => \$sleep_interval,
        "concurrency=i" => \$count,
        "max-rows-for-charts=i" => \$max_rows_for_charts,
+       "resultset-limit=i" => \$resultset_limit,
        "statement-timeout=i" => \$statement_timeout,
        "bootstrap|boostrap=s"  => \$config,
        "lockfile=s"    => \$lockfile,
@@ -174,6 +176,7 @@ while (my $r = $sth->fetchrow_hashref) {
        $r->{resultset}->set_pivot_label($report_data->{__pivot_label}) if $report_data->{__pivot_label};
        $r->{resultset}->set_pivot_default($report_data->{__pivot_default}) if $report_data->{__pivot_default};
        $r->{resultset}->relative_time($r->{run_time});
+       $r->{resultset}->resultset_limit($resultset_limit) if $resultset_limit;
        push @reports, $r;
 }