Author: spadkins
Date: Fri Nov 17 20:36:07 2006
New Revision: 8085
Modified:
p5ee/trunk/App-Repository/lib/App/Repository.pm
Log:
summarize_rows() and appropriate changes for extend_columns
Modified: p5ee/trunk/App-Repository/lib/App/Repository.pm
==============================================================================
--- p5ee/trunk/App-Repository/lib/App/Repository.pm (original)
+++ p5ee/trunk/App-Repository/lib/App/Repository.pm Fri Nov 17 20:36:07 2006
@@ -864,7 +864,12 @@
#}
}
if ($contains_expr) {
- $cols = $self->extend_columns($table, $cols);
+ my $new_cols = $self->extend_columns($table, $cols);
+ # the caller wanted his column list extended
+ if ($#$new_cols > $#$cols && $options->{extend_columns}) {
+ @$cols = @$new_cols; # so copy the columns
+ }
+ $cols = $new_cols; # then point to the new columns
regardless
}
$rows = $self->_get_rows($table, $params, $cols, $options);
@@ -896,7 +901,7 @@
# case, we need to add them.
sub extend_columns {
&App::sub_entry if ($App::trace);
- my ($self, $table, $cols) = @_;
+ my ($self, $table, $cols, $options) = @_;
my (%colidx, $expr_columns, $expr, $extended, $col);
# Take note of which columns are alread in the list of requested columns.
for (my $i = 0; $i <= $#$cols; $i++) {
@@ -928,8 +933,10 @@
foreach my $expr_col (@$expr_columns) {
if (! defined $colidx{$expr_col}) {
if (!$extended) {
- $cols = [ @$cols ]; # make a copy. don't extend original.
$extended = 1;
+ if (!$options->{extend_columns}) {
+ $cols = [ @$cols ]; # make a copy. don't extend
original.
+ }
}
push(@$cols, $expr_col); # extend the column list.
$colidx{$expr_col} = $#$cols;
@@ -942,6 +949,22 @@
return($cols);
}
+sub _contains_expr {
+ my ($self, $table, $columns) = @_;
+ my $contains_expr = 0;
+ my ($column);
+ my $column_defs = $self->{table}{$table}{column};
+ for (my $i = 0; $i <= $#$columns; $i++) {
+ $column = $columns->[$i];
+ if ($column_defs->{$column}{expr}) {
+ $contains_expr = 1;
+ last;
+ }
+ }
+ &App::sub_exit($contains_expr) if ($App::trace);
+ return($contains_expr);
+}
+
#############################################################################
# set_rows()
#############################################################################
@@ -2632,15 +2655,16 @@
=cut
#############################################################################
-# summarize()
+# summarize_rows()
#############################################################################
-=head2 summarize()
+=head2 summarize_rows()
- * Signature: $summarized_rows = $rep->summarize($rows, $columns,
$summcolidx, $formulas);
+ * Signature: $summarized_rows = $rep->summarize_rows($table, $rows,
$columns, $summary_keys, $options);
+ * Param: $table string
* Param: $rows [][]
* Param: $columns []
- * Param: $summcolidx []
+ * Param: $summary_keys []
* Param: $formulas {}
* Return: $summarized_rows []
* Throws: App::Exception::Repository
@@ -2657,90 +2681,147 @@
[ 1, "Ben", "Blue", 22.6, 195, ],
);
@columns = ( "id", "name", "team", "rating", "score" );
- @summcolidx = ( 2 ); # "team"
- %formulas = (
- rating => "{sum(rating)}/{count(rating)}",
+ @summary_keys = ( "team" );
+
+ $summarized_rows = $rep->summarize_rows([EMAIL PROTECTED], [EMAIL
PROTECTED], [EMAIL PROTECTED], \%formulas);
+
+ @rows = (
+ { id=>5, "Jim", "Green", 13.5, 320, },
+ { id=>3, "Bob", "Green", 4.2, 230, },
+ { id=>9, "Ken", "Green", 27.4, 170, },
+ { id=>2, "Kim", "Blue", 11.7, 440, },
+ { id=>7, "Jan", "Blue", 55.1, 90, },
+ { id=>1, "Ben", "Blue", 22.6, 195, },
);
+ @columns = ( "rating", "score" ); # summarize a subset of the columns
+ @summary_keys = ( "team" );
+ %options = ();
- $summarized_rows = $rep->summarize([EMAIL PROTECTED], [EMAIL PROTECTED],
[EMAIL PROTECTED], \%formulas);
+ $summarized_rows = $rep->summarize_rows([EMAIL PROTECTED], [EMAIL
PROTECTED], [EMAIL PROTECTED], \%options);
=cut
-sub summarize {
+sub summarize_rows {
&App::sub_entry if ($App::trace);
- my ($self, $rows, $columns, $summcolidx, $formulas) = @_;
+ my ($self, $table, $rows, $columns, $summary_keys, $options) = @_;
- my (@summary_rows, $summary_row, $create_summary);
- my ($key, $nextkey, $row, $rowidx, $colidx, $numcols, $column, $elem);
- my (%total, $formula);
+ $summary_keys = [] if (!$summary_keys);
- $numcols = $#$columns + 1;
+ my $column_def = $self->{table}{$table}{column};
- for ($rowidx = 0; $rowidx <= $#$rows; $rowidx++) {
- $row = $rows->[$rowidx];
+ my (@summary_rows, $summary_row, %summary_row);
+ my ($key, $row, $hash_rows, $hash_row, $i, $rowidx, $colidx, $column,
$value);
+ my $row_type = "ARRAY";
- $key = "Total";
- $key = join(",", @{$row->[EMAIL PROTECTED])
- if (defined $summcolidx);
+ if (!$rows || $#$rows == -1) {
+ # do nothing
+ }
+ else {
+ $row_type = (ref($rows->[0]) eq "ARRAY") ? "ARRAY" : "HASH";
- # accumulate totals
- for ($colidx = 0; $colidx < $numcols; $colidx++) {
- $column = $columns->[$colidx];
- $elem = $rows->[$rowidx][$colidx];
- if (defined $elem && $elem ne "") {
- if (defined $total{$column}) {
- $total{"sum($column)"} += ($elem+0);
+ # if we are summarizing HASH rows, convert to ARRAY
+ if ($row_type eq "HASH") {
+ $row = $rows->[0];
+ if (!$columns) {
+ $columns = [ ];
+ foreach $column (sort keys %$row) {
+ push(@$columns, $column) if (defined
$column_def->{$column});
+ }
+ }
+ $hash_rows = $rows;
+ $rows = [];
+ foreach $hash_row (@$hash_rows) {
+ $row = [ @[EMAIL PROTECTED] ];
+ push(@$rows, $row);
+ }
+ }
+
+ # find the indexes for each of the columns
+ my (%colidx);
+ for ($i = 0; $i <= $#$columns; $i++) {
+ $colidx{$columns->[$i]} = $i;
+ }
+
+ # get the indexes for the summary keys
+ my (@summary_key_idx, @summary_key_values);
+ if ($summary_keys) {
+ for ($i = 0; $i <= $#$summary_keys; $i++) {
+ $colidx = $colidx{$summary_keys->[$i]};
+ push(@summary_key_idx, $colidx) if (defined $colidx);
+ }
+ }
+
+ # determine which columns should be summable and which have expressions
+ my $sum_column_idx = [];
+ my $expr_column_idx = [];
+ my $contains_expr = 0;
+ $row = $rows->[0];
+ for ($i = 0; $i <= $#$columns; $i++) {
+ $column = $columns->[$i];
+ $value = $row->[$i];
+ if ($column_def->{$column}{expr}) {
+ push(@$expr_column_idx, $i);
+ $contains_expr = 1;
+ }
+ elsif ($column_def->{$column}{is_key}) {
+ # do nothing
+ }
+ elsif (defined $value && $value =~ /^-?[0-9\.]+$/) {
+ push(@$sum_column_idx, $i);
+ }
+ }
+
+ # accumulate the sums of the summable columns
+ for ($rowidx = 0; $rowidx <= $#$rows; $rowidx++) {
+ $row = $rows->[$rowidx];
+ $key = ($#summary_key_idx > -1) ? join("|", @[EMAIL PROTECTED]) :
"";
+ $summary_row = $summary_row{$key};
+ if (!$summary_row) {
+ $summary_row = [];
+ if ($#summary_key_idx > -1) {
+ foreach $i (@summary_key_idx) {
+ $summary_row->[$i] = $row->[$i];
+ }
}
- else {
- $total{"sum($column)"} = ($elem+0);
+ foreach $i (@$sum_column_idx) {
+ $summary_row->[$i] = 0;
}
- $total{"$column"} = $elem;
+ $summary_row{$key} = $summary_row;
+ push(@summary_key_values, $key);
+ }
+ foreach $i (@$sum_column_idx) {
+ $summary_row->[$i] += $row->[$i];
}
- }
- if (defined $total{"count(*)"}) {
- $total{"count(*)"} ++;
- }
- else {
- $total{"count(*)"} = 1;
}
- # look ahead to see if we need to produce a summary row yet
- $create_summary = 0;
- if ($rowidx == $#$rows) {
- $create_summary = 1;
+ # put the summarized rows in the results array
+ foreach $key (@summary_key_values) {
+ push(@summary_rows, $summary_row{$key});
}
- else {
- $nextkey = "Total";
- $nextkey = join(",", @{$rows->[EMAIL PROTECTED])
- if (defined $summcolidx);
- $create_summary = 1 if ($nextkey ne $key);
- }
-
- if ($create_summary) {
- $summary_row = [];
+ # evaluate the expressions of the summarized rows (if they exist)
+ if ($contains_expr) {
+ my $params = {};
+ $self->evaluate_expressions($table, $params, $columns, [EMAIL
PROTECTED], $options);
+ }
- for ($colidx = 0; $colidx < $numcols; $colidx++) {
- $column = $columns->[$colidx];
- $formula = $formulas->{$column};
-
- $elem = "";
- if (defined $formula) { # match {
- $formula =~ s/\{([^\}]+)\}/\$total{"$1"}/g;
- $formula = "\$elem = $formula;";
- eval $formula;
- #$elem = "[$formula] $@" if ($@);
- }
- else {
- $elem = $total{"sum($column)"};
+ # if we started out summarizing HASH rows, convert back from ARRAY to
HASH
+ if ($row_type eq "HASH") {
+ $rows = [ @summary_rows ];
+ $hash_rows = [];
+ @summary_rows = ();
+ foreach $row (@$rows) {
+ $hash_row = {};
+ for ($i = 0; $i <= $#$columns; $i++) {
+ $hash_row->{$columns->[$i]} = $row->[$i];
}
+ push(@summary_rows, $hash_row);
}
-
- push (@summary_rows, $summary_row);
}
}
+
&App::sub_exit([EMAIL PROTECTED]) if ($App::trace);
- [EMAIL PROTECTED];
+ return([EMAIL PROTECTED]);
}
#############################################################################
@@ -3550,3 +3631,60 @@
1;
+__END__
+
+ if (0) { # HASH (or object of some type)
+ # determine which columns should be summable and which have expressions
+ my $agg_columns = [];
+ my $sum_columns = [];
+ my $expr_columns = [];
+ my $contains_expr = 0;
+ my (@summary_keys);
+ $row = $rows->[0];
+ foreach $column (keys %$row) {
+ $value = $row->{$column};
+ if ($column_def->{$column}{expr}) {
+ push(@$agg_columns, $column);
+ push(@$expr_columns, $column);
+ $contains_expr = 1;
+ }
+ elsif ($column_def->{$column}{is_key}) {
+ # do nothing
+ }
+ elsif (defined $value && $value =~ /^-?[0-9\.]+$/) {
+ push(@$agg_columns, $column);
+ push(@$sum_columns, $column);
+ }
+ }
+ # accumulate the sums of the summable columns
+ for ($rowidx = 0; $rowidx <= $#$rows; $rowidx++) {
+ $row = $rows->[$rowidx];
+ $key = ($#$summary_keys > -1) ? join("|", @[EMAIL PROTECTED]) : "";
+ $summary_row = $summary_row{$key};
+ if (!$summary_row) {
+ $summary_row = {};
+ if ($#$summary_keys > -1) {
+ foreach $column (@$summary_keys) {
+ $summary_row->{$column} = $row->{$column};
+ }
+ foreach $column (@$sum_columns) {
+ $summary_row->{$column} = 0;
+ }
+ }
+ $summary_row{$key} = $summary_row;
+ push(@summary_keys, $key);
+ }
+ foreach $column (@$sum_columns) {
+ $summary_row->{$column} += $row->{$column};
+ }
+ }
+ # put the summarized rows in the results array
+ foreach $key (@summary_keys) {
+ push(@summary_rows, $summary_row{$key});
+ }
+ # evaluate the expressions of the summarized rows (if they exist)
+ if ($contains_expr) {
+ my $params = {};
+ $self->evaluate_expressions($table, $params, $columns, [EMAIL
PROTECTED], $options);
+ }
+ }