From: miker Date: Mon, 9 Oct 2006 00:53:17 +0000 (+0000) Subject: pile of reporting updates X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=dc06f950c579aeb6bcad8dfaf07085bccc915572;p=evergreen%2Fpines.git pile of reporting updates git-svn-id: svn://svn.open-ils.org/ILS/trunk@6408 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 0286c97c1b..9f98580571 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -163,18 +163,18 @@ - + - - - - - - - + + + + + + + @@ -210,16 +210,16 @@ - + - - - - - + + + + + @@ -227,16 +227,16 @@ - + - - - - - + + + + + @@ -480,7 +480,7 @@ - + @@ -712,36 +712,36 @@ - + - - - - - - - + + + + + + + - + - - - - - - - + + + + + + + @@ -857,26 +857,26 @@ - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + @@ -911,23 +911,23 @@ - + - - - - - - - - - - - - + + + + + + + + + + + + @@ -998,7 +998,7 @@ - + @@ -1060,17 +1060,17 @@ - + - - - - - - + + + + + + @@ -1179,34 +1179,34 @@ - + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - + + + + - + @@ -1218,11 +1218,11 @@ - - - - - + + + + + @@ -1520,15 +1520,15 @@ - + - - - - + + + + @@ -1563,14 +1563,14 @@ - + - - - + + + @@ -1994,37 +1994,37 @@ - + - - - - + + + + - + - - - - - - - - - - - + + + + + + + + + + + @@ -2243,4 +2243,17 @@ + + + + + + + + + + + + + diff --git a/Open-ILS/examples/reporter-sql-builder-test.pl b/Open-ILS/examples/reporter-sql-builder-test.pl index 8672673fbf..10c135988e 100755 --- a/Open-ILS/examples/reporter-sql-builder-test.pl +++ b/Open-ILS/examples/reporter-sql-builder-test.pl @@ -18,8 +18,8 @@ my $report = { column => 'barcode', alias => 'User Barcode', }, - { relation=> 'circ', - column => { transform => count => colname => 'id' }, + { relation=> 'circ-id-mb', + column => { transform => sum => colname => 'amount' }, alias => '::PARAM3', }, ], @@ -30,11 +30,13 @@ my $report = { checkin_staff => { table => 'actor.usr', alias => 'circ-circ_staff-au', + type => 'inner', key => 'id', join => { card => { table => 'actor.card', alias => 'circ-circ_staff-au-card-ac', + type => 'inner', key => 'id', }, }, @@ -42,11 +44,13 @@ my $report = { checkin_lib => { table => 'actor.org_unit', alias => 'circ-checkin_lib-aou', + type => 'inner', key => 'id', }, 'id-billings' => { table => 'money.billing', alias => 'circ-id-mb', + type => 'left', key => 'xact', }, }, @@ -65,17 +69,8 @@ my $report = { condition => { '=' => '::PARAM7' }, }, ], - having => [ - { relation => 'circ', - column => { transform => count => colname => 'id' }, - condition => { 'between' => '::PARAM5' }, - }, - ], + having => [], order_by => [ - { relation=> 'circ', - column => { transform => count => colname => 'id' }, - direction => 'descending', - }, { relation=> 'circ-checkin_lib-aou', column => { colname => 'shortname', transform => 'Bare' }, }, @@ -96,7 +91,7 @@ my $params = { PARAM1 => [ 18, 19, 20, 21, 22, 23 ], #PARAM2 => ['2006-07','2006-08','2006-09'], PARAM2 => [{transform => 'relative_month', params => [-2]},{transform => 'relative_month', params => [-3]}], - PARAM3 => 'Circ Count', + PARAM3 => 'Billed Amount', PARAM4 => 'Checkin Date', PARAM5 => [{ transform => 'Bare', params => [10] },{ transform => 'Bare', params => [100] }], PARAM6 => [ 1, 4 ], @@ -112,3 +107,8 @@ $rs->relative_time('2006-10-01T00:00:00-4'); print "Column Labels: " . join(', ', $rs->column_label_list) . "\n"; print $rs->toSQL; +print "\n\n"; + +print "SQL group by list: ".join(',',$rs->group_by_list)."\n"; +print "Perl group by list: ".join(',',$rs->group_by_list(0))."\n"; + diff --git a/Open-ILS/src/perlmods/OpenILS/Reporter/SQLBuilder.pm b/Open-ILS/src/perlmods/OpenILS/Reporter/SQLBuilder.pm index c2bfb96311..d00f214c9e 100644 --- a/Open-ILS/src/perlmods/OpenILS/Reporter/SQLBuilder.pm +++ b/Open-ILS/src/perlmods/OpenILS/Reporter/SQLBuilder.pm @@ -26,6 +26,12 @@ sub set_builder { return $self; } +sub find_relation { + my $self = shift; + my $rel = shift; + return $self->builder->{_rels}->{$rel}; +} + sub builder { my $self = shift; return $self->{_builder}; @@ -94,37 +100,37 @@ sub is_subquery { sub pivot_data { my $self = shift; - return $self->{_pivot_data}; + return $self->builder->{_pivot_data}; } sub pivot_label { my $self = shift; - return $self->{_pivot_label}; + return $self->builder->{_pivot_label}; } sub pivot_default { my $self = shift; - return $self->{_pivot_label}; + return $self->builder->{_pivot_default}; } sub set_pivot_default { my $self = shift; my $p = shift; - $self->{_pivot_default} = $p if (defined $p); + $self->builder->{_pivot_default} = $p if (defined $p); return $self; } sub set_pivot_data { my $self = shift; my $p = shift; - $self->{_pivot_data} = $p if (defined $p); + $self->builder->{_pivot_data} = $p if (defined $p); return $self; } sub set_pivot_label { my $self = shift; my $p = shift; - $self->{_pivot_label} = $p if (defined $p); + $self->builder->{_pivot_label} = $p if (defined $p); return $self; } @@ -153,7 +159,7 @@ sub set_from { my $self = shift; my $f = shift; - $self->{_from} = OpenILS::Reporter::SQLBuilder::Relation->parse( $f ); + $self->{_from} = OpenILS::Reporter::SQLBuilder::Relation->parse( $f, $self ); return $self; } @@ -213,9 +219,14 @@ sub group_by_list { my $base = shift; $base = 1 unless (defined $base); + my $seen_label = 0; my $gcount = $base; my @group_by; for my $c ( @{ $self->{_select} } ) { + if ($base == 0 && !$seen_label && defined($self->pivot_label) && $gcount == $self->pivot_label - 1) { + $seen_label++; + next; + } push @group_by, $gcount if (!$c->is_aggregate); $gcount++; } @@ -897,7 +908,16 @@ sub toSQL { my $self = shift; return $self->{_sql} if ($self->{_sql}); - my $sql = $self->SUPER::toSQL; + + my $sql; + + my $rel = $self->find_relation($self->{_relation}); + warn $self->builder; + if ($rel && $rel->is_join && $rel->join_type ne 'inner') { + $sql = "($sql IS NULL OR "; + } + + $sql .= $self->SUPER::toSQL; my ($op) = keys %{ $self->{_condition} }; my $val = _flesh_conditions( $self->resolve_param( $self->{_condition}->{$op} ), $self->builder ); @@ -927,6 +947,10 @@ sub toSQL { $sql .= " $op " . $val->toSQL; } + if ($rel && $rel->is_join && $rel->join_type ne 'inner') { + $sql .= ")"; + } + return $self->{_sql} = $sql; } @@ -944,15 +968,19 @@ sub parse { $self = $self->SUPER::new if (!ref($self)); my $rel_data = shift; + my $b = shift; + $self->set_builder($b); $self->{_table} = $rel_data->{table}; $self->{_alias} = $rel_data->{alias} || $self->name; $self->{_join} = []; $self->{_columns} = []; + $self->builder->{_rels}{$self->{_alias}} = $self; + if ($rel_data->{join}) { $self->add_join( - $_ => OpenILS::Reporter::SQLBuilder::Relation->parse( $rel_data->{join}->{$_} ) => $rel_data->{join}->{$_}->{key} + $_ => OpenILS::Reporter::SQLBuilder::Relation->parse( $rel_data->{join}->{$_}, $b ) => $rel_data->{join}->{$_}->{key} => $rel_data->{join}->{$_}->{type} ) for ( keys %{ $rel_data->{join} } ); } @@ -977,11 +1005,12 @@ sub add_join { my $col = shift; my $frel = shift; my $fkey = shift; + my $type = lc(shift()) || 'inner'; - if (ref($col) eq 'OpenILS::Reporter::SQLBuilder::Join') { + if (UNIVERSAL::isa($col,'OpenILS::Reporter::SQLBuilder::Join')) { push @{ $self->{_join} }, $col; } else { - push @{ $self->{_join} }, OpenILS::Reporter::SQLBuilder::Join->build( $self => $col, $frel => $fkey ); + push @{ $self->{_join} }, OpenILS::Reporter::SQLBuilder::Join->build( $self => $col, $frel => $fkey, $type ); } return $self; @@ -994,6 +1023,13 @@ sub is_join { return $self->{_is_join}; } +sub join_type { + my $self = shift; + my $j = shift; + $self->{_join_type} = $j if ($j); + return $self->{_join_type}; +} + sub toSQL { my $self = shift; return $self->{_sql} if ($self->{_sql}); @@ -1014,8 +1050,8 @@ package OpenILS::Reporter::SQLBuilder::Join; use base qw/OpenILS::Reporter::SQLBuilder/; sub build { - my $self = shift; - $self = $self->SUPER::new if (!ref($self)); + my $class = shift; + my $self = $class->SUPER::new if (!ref($class)); $self->{_left_rel} = shift; ($self->{_left_col}) = split(/-/,shift()); @@ -1023,21 +1059,85 @@ sub build { $self->{_right_rel} = shift; $self->{_right_col} = shift; + $self->{_join_type} = shift; + $self->{_right_rel}->is_join(1); + $self->{_right_rel}->join_type($self->{_join_type}); + + bless $self => "OpenILS::Reporter::SQLBuilder::Join::$self->{_join_type}"; return $self; } sub toSQL { my $self = shift; - return $self->{_sql} if ($self->{_sql}); - my $sql = "\n\tJOIN " . $self->{_right_rel}->toSQL . + my $sql = "JOIN " . $self->{_right_rel}->toSQL . ' ON ("' . $self->{_left_rel}->{_alias} . '"."' . $self->{_left_col} . '" = "' . $self->{_right_rel}->{_alias} . '"."' . $self->{_right_col} . '")'; $sql .= $_->toSQL for (@{ $self->{_right_rel}->{_join} }); + return $sql; +} + +#------------------------------------------------------------------------------------------------- +package OpenILS::Reporter::SQLBuilder::Join::left; +use base qw/OpenILS::Reporter::SQLBuilder::Join/; + +sub toSQL { + my $self = shift; + #return $self->{_sql} if ($self->{_sql}); + + my $sql = "\n\tLEFT OUTER ". $self->SUPER::toSQL; + + #$sql .= $_->toSQL for (@{ $self->{_right_rel}->{_join} }); + + return $self->{_sql} = $sql; +} + +#------------------------------------------------------------------------------------------------- +package OpenILS::Reporter::SQLBuilder::Join::right; +use base qw/OpenILS::Reporter::SQLBuilder::Join/; + +sub toSQL { + my $self = shift; + #return $self->{_sql} if ($self->{_sql}); + + my $sql = "\n\tRIGHT OUTER ". $self->SUPER::toSQL; + + #$sql .= $_->toSQL for (@{ $self->{_right_rel}->{_join} }); + + return $self->{_sql} = $sql; +} + +#------------------------------------------------------------------------------------------------- +package OpenILS::Reporter::SQLBuilder::Join::inner; +use base qw/OpenILS::Reporter::SQLBuilder::Join/; + +sub toSQL { + my $self = shift; + #return $self->{_sql} if ($self->{_sql}); + + my $sql = "\n\tINNER ". $self->SUPER::toSQL; + + #$sql .= $_->toSQL for (@{ $self->{_right_rel}->{_join} }); + + return $self->{_sql} = $sql; +} + +#------------------------------------------------------------------------------------------------- +package OpenILS::Reporter::SQLBuilder::Join::cross; +use base qw/OpenILS::Reporter::SQLBuilder::Join/; + +sub toSQL { + my $self = shift; + #return $self->{_sql} if ($self->{_sql}); + + my $sql = "\n\tFULL OUTER ". $self->SUPER::toSQL; + + #$sql .= $_->toSQL for (@{ $self->{_right_rel}->{_join} }); + return $self->{_sql} = $sql; } diff --git a/Open-ILS/src/reporter/clark-kent.pl b/Open-ILS/src/reporter/clark-kent.pl index 82c8bb7ca7..0624b23bfb 100755 --- a/Open-ILS/src/reporter/clark-kent.pl +++ b/Open-ILS/src/reporter/clark-kent.pl @@ -173,6 +173,9 @@ for my $r ( @reports ) { $r->{column_labels} = $newdata->{columns}; $r->{data} = $newdata->{data}; + $r->{group_by_list} = $newdata->{group_by_list}; + } else { + $r->{group_by_list} = [$r->{resultset}->group_by_list(0)]; } my $s2 = $r->{report}->{template}->{id}; @@ -470,7 +473,7 @@ sub draw_pie { my $data = $r->{data}; - my @groups = $r->{resultset}->group_by_list(0); + my @groups = @{ $r->{group_by_list} }; my @values = (0 .. (scalar(@{$r->{column_labels}}) - 1)); delete @values[@groups]; @@ -556,7 +559,7 @@ sub draw_bars { #my $logo = $doc->findvalue('/reporter/setup/files/chart_logo'); - my @groups = $r->{resultset}->group_by_list(0); + my @groups = @{ $r->{group_by_list} }; my @values = (0 .. (scalar(@{$r->{column_labels}}) - 1)); @@ -670,7 +673,7 @@ sub draw_lines { #my $logo = $doc->findvalue('/reporter/setup/files/chart_logo'); - my @groups = $r->{resultset}->group_by_list(0); + my @groups = @{ $r->{group_by_list} }; my @values = (0 .. (scalar(@{$r->{column_labels}}) - 1)); splice(@values,$_,1) for (reverse @groups); @@ -784,6 +787,8 @@ sub pivot_data { my @keep_cols = (0 .. @$cols - 1); splice(@keep_cols, $_ - 1, 1) for (reverse sort ($pivot_label, $pivot_data)); + my @gb = ( 0 .. @keep_cols - 1); + #first, find the unique list of pivot values my %tmp; for my $row (@$data) { @@ -822,7 +827,7 @@ sub pivot_data { push @keep_labels, @new_cols; - return { columns => \@keep_labels, data => [ values %new_data ] }; + return { columns => \@keep_labels, data => [ values %new_data ], group_by_list => \@gb }; } diff --git a/Open-ILS/src/sql/Pg/reporter-schema.sql b/Open-ILS/src/sql/Pg/reporter-schema.sql index 4046bff63d..46ea188aca 100644 --- a/Open-ILS/src/sql/Pg/reporter-schema.sql +++ b/Open-ILS/src/sql/Pg/reporter-schema.sql @@ -132,6 +132,17 @@ SELECT r.id, WHERE r.deleted IS FALSE GROUP BY 1,2,3,4,5,6,7,8,9,10,11,12,13,14; +CREATE OR REPLACE VIEW reporter.demographic AS +SELECT u.id, + u.dob, + CASE + WHEN u.dob IS NULL + THEN 'Adult' + WHEN AGE(u.dob) > '18 years'::INTERVAL + THEN 'Adult' + ELSE 'Juvenile' + END AS general_division + FROM actor.usr u; COMMIT;