昨天晚上遇到这么个问题,客户反映我们的一个页面的排序不正确,对方反映了几次,可是我们就是什么问题都没查出来,看看查询的SQL命令,完全按照要求排序了呀,怎么会不正确呢。
对方看我们迟迟无法解决,也是非常着急,并把他们那里出现的错误画面发过来了,于是晚上我抱着试试看的想法,把用户提供的数据输入到我们的系统中,刚开始输了几个,排序完全正常,然后,当我输入了十几条数据后,竟然发现排序确实不正常的。而乍一看我们的代码也没有任何问题:
# データベースからデータを検索する。
# @param $query
# @return $recordset(HashのPointer)、または0。
# db_select_hashと違う点は:この関数の戻り値のKeyは順序の数字です
# ex:
# use chira::db;
# my $rset = db_select_hash2("select owner_id, owner_name from ec02");
# if (! $rset) {
# print "Error when select";
# }
# else {
# my $key;
# foreach $key (sort keys %$rset) {
# my $arrpoint = $$rset{$key};
# print "$key = $$arrpoint[0], $$arrpoint[1]\n";
# }
# }
sub db_select_hash2($)
{
my $query = shift;
my %aux;
$query = escapesql($query);
eval {
my $sth = $dbh -> prepare($query);
$sth->execute;
my @row;
my $id = 0;
while (@row = $sth->fetchrow_array) {
$aux{$id} = [@row];
$id ++;
}
};
if ($@) {
lg_adddebug("_select_hash2: " . $query, "db.pm");
return 0;
}
else {
return \%aux;
}
}
$rows = &db_select_hash2("select ec91.DISP_NO, ec91.CATEG_ID, ec91.CATEG_NAME, ec91.SHOP_CNT from ec91 where $owner_id=EC91.OWNER_ID order by EC91.DISP_NO ASC, EC91.CATEG_ID ASC");
foreach $key (sort keys %$rows) {
......
}
其中db_select_hash2()函数是对数据库进行查询,并将查询结果按照次序放在一个hash表中,hash表的key为一个自增型的数字。
在外部程序的foreach()循环中,自动按照这个key为顺序,一一返回所有查询得的纪录。
难道是foreach()的地方发生了问题?
于是我将foreach中的$key一一打印出来,一看,呵呵,原来问题出现在这里。。我们希望的结果应该是:
0,1,2,。。。,8,9,10,11,12
但实际却变为:
0,1,10,11,12,。。。,2,3
原来如此,foreach()中的sort按照ascii来对hash表进行排序了,当然,只要让它按照数字来排就能解决问题,可是,我在网上搜索了半天,又翻了本大砖头,还是一无所获,眼看一个晚上就要过去,今天可是必须release的,没办法,急中生智,我用了这么一招:
sub db_select_hash2($)
{
my $query = shift;
my %aux;
$query = escapesql($query);
eval {
my $sth = $dbh -> prepare($query);
$sth->execute;
my @row;
my $id = 0;
while (@row = $sth->fetchrow_array) {
#$aux{$id} = [@row];
#modified by tony
# else the foreach() will sort the key like (0, 1, 10, 11, 2, 3, 4 ...)
my $key = "00000" . $id;
$key = substr($key, length($key)-5, 5);
$aux{$key} = [@row];
$id ++;
}
};
if ($@) {
lg_adddebug("_select_hash2: " . $query, "db.pm");
return 0;
}
else {
return \%aux;
}
}
我将key
1,2,3。。。,9,10,11
变成了这样:
00001,00002,00003。。。,00009,00010,00011
这样在ascii排序方式下,也总能返回正确顺序了。
虽然问题暂时解决了,但是用了这种恶心的招数,实在是有愧于perl啊,只希望各位perl大虾不要笑话。
另外,本次事件也让我再次深刻的认识到,软件上的很多问题,其实都是可以经过更广泛的测试来避免的,这就体现出引入自动化测试的必要性了,对于有些页面之类很难用自动化来完成的测试工作,则应该使用相对比较无序的数据来进行测试。