Subject: | Bug in Data-Pivot 0.04, causing headings to get mis-ordered |
While working on something that might make use of Data::Pivot, I ran across a bug related to the re-assembly of "headings"... The "sort keys..." takes precendence over the ",", which causes the "row_sum" heading to get slurped into the sort (which I don't think was your original intention). I've confirmed this with Perl-5.8.3, but I don't think that it affects earlier Perl's.
The attached diff provides three changes:
1) fixes the bug in "Pivot.pm",
2) updates "test.pl" to use Test::More for its testing (so that "is_deeply()" can be used to test the results of the pivot),
3) updates "test.pl" with a new test to exercise the bug, and verify that the provided fix works as intended.
It'd be appreciated if you would consider this fix for a new release of Data-Pivot. If you feel that this patch isn't useful or you don't wish to maintain Data-Pivot, please do let me know. Many thanks,
Graham TerMarsch.
diff -rc Data-Pivot-0.04.orig/Pivot.pm Data-Pivot-0.04/Pivot.pm
*** Data-Pivot-0.04.orig/Pivot.pm 2002-10-08 12:44:35.000000000 -0700
--- Data-Pivot-0.04/Pivot.pm 2004-11-12 01:49:12.414008302 -0800
***************
*** 266,272 ****
}
}
! splice @$headings, $pivot_column, @sum_columns + 1, ($row_titles ? '' : (), sort keys %pivot_cols, $row_sum ? $row_sum : ());
return @newtable;
}
--- 266,272 ----
}
}
! splice @$headings, $pivot_column, @sum_columns + 1, ($row_titles ? '' : (), (sort keys %pivot_cols), $row_sum ? $row_sum : ());
return @newtable;
}
diff -rc Data-Pivot-0.04.orig/test.pl Data-Pivot-0.04/test.pl
*** Data-Pivot-0.04.orig/test.pl 2002-04-30 01:47:19.000000000 -0700
--- Data-Pivot-0.04/test.pl 2004-11-12 01:49:28.769350775 -0800
***************
*** 3,20 ****
#########################
! # change 'tests => 1' to 'tests => last_test_to_print';
!
! use Test;
! BEGIN { plan tests => 1 };
use Data::Pivot;
- ok(1); # If we made it this far, we're ok.
-
- #########################
-
- # Insert your test code below, the Test module is use()ed here so read
- # its man page ( perldoc Test ) for help writing this test script.
my @table = ( [ 'a', 'b', 'c', 1, 10 ],
[ 'a', 'b', 'c', 2, 20 ],
[ 'a', 'b', 'c', 3, 30 ],
--- 3,12 ----
#########################
! use Test::More tests => 8;
use Data::Pivot;
+ ###############################################################################
my @table = ( [ 'a', 'b', 'c', 1, 10 ],
[ 'a', 'b', 'c', 2, 20 ],
[ 'a', 'b', 'c', 3, 30 ],
***************
*** 27,34 ****
my $pivot_col = 3;
my @sum_cols = ( 4 );
! print "Before:\n";
! out(\@headings, \@table);
my @newtable = pivot( table => \@table,
headings => \@headings,
fix_columns => \@fix_cols,
--- 19,30 ----
my $pivot_col = 3;
my @sum_cols = ( 4 );
! my @expect_table = (
! [ 'a', 'b', 'c', '10.00', '20.00', '30.00' ],
! [ 'x', 'y', 'z', ' 1.00', ' 2.00', ' 3.00' ],
! );
! my @expect_headings = ('A', 'B', 'C', 1, 2, 3);
!
my @newtable = pivot( table => \@table,
headings => \@headings,
fix_columns => \@fix_cols,
***************
*** 38,47 ****
row_titles => 0,
format => '%5.2f'
);
! print "\nAfter:\n";
! out(\@headings, \@newtable);
!
@table = ( [ 'a', 'b', 'c', 1, 10, 1, 12 ],
[ 'a', 'b', 'c', 2, 20, 2, 24 ],
[ 'a', 'b', 'c', 3, 30, 3, 36 ],
--- 34,43 ----
row_titles => 0,
format => '%5.2f'
);
! is_deeply( \@headings, \@expect_headings, 'headings ok' );
! is_deeply( \@newtable, \@expect_table, 'pivot ok' );
+ ###############################################################################
@table = ( [ 'a', 'b', 'c', 1, 10, 1, 12 ],
[ 'a', 'b', 'c', 2, 20, 2, 24 ],
[ 'a', 'b', 'c', 3, 30, 3, 36 ],
***************
*** 54,61 ****
$pivot_col = 3;
@sum_cols = ( 4, 5, 6 );
! print "\n\nBefore:\n";
! out(\@headings, \@table);
@newtable = pivot( table => \@table,
headings => \@headings,
fix_columns => \@fix_cols,
--- 50,65 ----
$pivot_col = 3;
@sum_cols = ( 4, 5, 6 );
! @expect_table = (
! ['a', 'b', 'c', 'V1', '10.00', '20.00', '30.00', '60.00'],
! ['', '', '', 'V 2', ' 1.00', ' 2.00', ' 3.00', ' 6.00'],
! ['', '', '', 'V 3', '12.00', '24.00', '36.00', '72.00'],
! ['x', 'y', 'z', 'V1', ' 1.00', ' 2.00', ' 3.00', ' 6.00'],
! ['', '', '', 'V 2', ' 9.00', ' 8.00', ' 7.00', '24.00'],
! ['', '', '', 'V 3', '23.00', '34.00', '45.00', '102.00'],
! );
! @expect_headings = ('A', 'B', 'C', '', '1', '2', '3', 'Sum');
!
@newtable = pivot( table => \@table,
headings => \@headings,
fix_columns => \@fix_cols,
***************
*** 65,73 ****
row_titles => 1,
format => '%5.2f'
);
! print "\nAfter:\n";
! out(\@headings, \@newtable);
@table = ( [ 'a', 'b', 'c', 1, 10000, 1, 12000 ],
[ 'a', 'b', 'c', 2, 20, 2, 24000 ],
[ 'a', 'b', 'c', 3, 30, 3, 36000 ],
--- 69,78 ----
row_titles => 1,
format => '%5.2f'
);
! is_deeply( \@headings, \@expect_headings, 'headings ok' );
! is_deeply( \@newtable, \@expect_table, 'pivot ok' );
+ ###############################################################################
@table = ( [ 'a', 'b', 'c', 1, 10000, 1, 12000 ],
[ 'a', 'b', 'c', 2, 20, 2, 24000 ],
[ 'a', 'b', 'c', 3, 30, 3, 36000 ],
***************
*** 76,81 ****
--- 81,98 ----
[ 'x', 'y', 'z', 3, 3, 7, 45000 ],
);
@headings = ( 'A', 'B', 'C', 'P', 'V1', 'V 2', 'V 3' );
+
+ @expect_table = (
+ ['a', 'b', 'c', ' 10.000,00', ' 1,00', ' 12.000,00', ' 20,00', ' 2,00', ' 24.000,00', ' 30,00', ' 3,00', ' 36.000,00'],
+ ['x', 'y', 'z', ' 1,00', ' 9,00', ' 23.000,00', ' 2,00', ' 8,00', ' 34.000,00', ' 3,00', ' 7,00', ' 45.000,00'],
+ );
+ @expect_headings = (
+ 'A', 'B', 'C',
+ 'V1 1', 'V 2 1', 'V 3 1',
+ 'V1 2', 'V 2 2', 'V 3 2',
+ 'V1 3', 'V 2 3', 'V 3 3',
+ );
+
@newtable = pivot( table => \@table,
headings => \@headings,
fix_columns => \@fix_cols,
***************
*** 86,107 ****
row_titles => 1,
format => \&format
);
! print "\nAfter (vertical):\n";
! out(\@headings, \@newtable);
! sub out {
! my ($headings, $table) = @_;
- print $_, "\t" foreach @$headings;
- print "\n\n";
- foreach (@$table) {
- print $_, "\t" foreach @$_;
- print "\n";
- }
- }
sub format {
my $v = sprintf('%10.2f', $_[0]);
--- 103,136 ----
row_titles => 1,
format => \&format
);
! is_deeply( \@headings, \@expect_headings, 'headings ok' );
! is_deeply( \@newtable, \@expect_table, 'pivot ok' );
+ ###############################################################################
+ # Test list concatenation for headers.
+ @table = ( [ 'a', 'x', 1 ],
+ [ 'a', 'y', 2 ],
+ [ 'a', 'z', 3 ],
+ );
+ @headings = ( 'A', 'B', 'C' );
+ @expect_table = (
+ ['a', 1, 2, 3, 6],
+ );
+ @expect_headings = ( 'A', 'x', 'y', 'z', 'Sum' );
! @newtable = pivot( table => \@table,
! headings => \@headings,
! pivot_column => 1,
! layout => 'horizontal',
! row_sum => 'Sum',
! );
!
! is_deeply( \@headings, \@expect_headings, 'headings ok - list concat test' );
! is_deeply( \@newtable, \@expect_table, 'pivot ok - list concat test' );
+ ###############################################################################
sub format {
my $v = sprintf('%10.2f', $_[0]);