昨天晚上遇到这么个问题,客户反映我们的一个页面的排序不正确,对方反映了几次,可是我们就是什么问题都没查出来,看看查询的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大虾不要笑话。
另外,本次事件也让我再次深刻的认识到,软件上的很多问题,其实都是可以经过更广泛的测试来避免的,这就体现出引入自动化测试的必要性了,对于有些页面之类很难用自动化来完成的测试工作,则应该使用相对比较无序的数据来进行测试。

|