5 # Debian-specific script to upgrade the database between releases
6 # Roland Mas <lolando@debian.org>
15 use vars qw/$dbh @reqlist $query/ ;
16 use vars qw/$sys_default_domain $sys_cvs_host $sys_download_host
17 $sys_shell_host $sys_users_host $sys_docs_host $sys_lists_host
18 $sys_dns1_host $sys_dns2_host $FTPINCOMING_DIR $FTPFILES_DIR
19 $sys_urlroot $sf_cache_dir $sys_name $sys_themeroot
20 $sys_news_group $sys_dbhost $sys_dbname $sys_dbuser $sys_dbpasswd
21 $sys_ldap_base_dn $sys_ldap_host $admin_login $admin_password
22 $server_admin $domain_name $newsadmin_groupid $statsadmin_groupid
25 sub is_lesser ( $$ ) ;
26 sub is_greater ( $$ ) ;
28 sub parse_sql_file ( $ ) ;
30 require ("/usr/lib/sourceforge/lib/include.pl") ; # Include a few predefined functions
31 require ("/usr/lib/sourceforge/lib/sqlparser.pm") ; # Our magic SQL parser
33 debug "You'll see some debugging info during this installation." ;
34 debug "Do not worry unless told otherwise." ;
38 # debug "Connected to the database OK." ;
40 $dbh->{AutoCommit} = 0;
41 $dbh->{RaiseError} = 1;
43 my ($sth, @array, $version, $action, $path, $target) ;
45 # Do we have at least the basic schema?
47 $query = "SELECT count(*) from pg_class where relname = 'groups' and relkind = 'r'";
49 $sth = $dbh->prepare ($query) ;
51 @array = $sth->fetchrow_array () ;
54 # Create Sourceforge database
56 if ($array [0] == 0) { # No 'groups' table
57 # Installing SF 2.6 from scratch
58 $action = "installation" ;
59 debug "Creating initial Sourceforge database from files." ;
61 &create_metadata_table ("2.5.9999") ;
63 debug "Updating debian_meta_data table." ;
64 $query = "INSERT INTO debian_meta_data (key, value) VALUES ('current-path', 'scratch-to-2.6')" ;
66 $sth = $dbh->prepare ($query) ;
72 } else { # A 'groups' table exists
75 $query = "SELECT count(*) from pg_class where relname = 'debian_meta_data' and relkind = 'r'";
77 $sth = $dbh->prepare ($query) ;
79 @array = $sth->fetchrow_array () ;
82 if ($array[0] == 0) { # No 'debian_meta_data' table
83 # If we're here, we're upgrading from 2.5-7 or earlier
84 # We therefore need to create the table
85 &create_metadata_table ("2.5-7+just+before+8") ;
88 $version = &get_db_version ;
89 if (is_lesser $version, "2.5.9999") {
90 debug "Found an old (2.5) database, will upgrade to 2.6" ;
92 $query = "SELECT count(*) from debian_meta_data where key = 'current-path'";
94 $sth = $dbh->prepare ($query) ;
96 @array = $sth->fetchrow_array () ;
100 # debug "Updating debian_meta_data table." ;
101 $query = "INSERT INTO debian_meta_data (key, value) VALUES ('current-path', '2.5-to-2.6')" ;
103 $sth = $dbh->prepare ($query) ;
106 debug "Committing." ;
112 $query = "SELECT count(*) from debian_meta_data where key = 'current-path'";
114 $sth = $dbh->prepare ($query) ;
116 @array = $sth->fetchrow_array () ;
119 if ($array[0] == 0) {
122 $query = "SELECT value from debian_meta_data where key = 'current-path'";
124 $sth = $dbh->prepare ($query) ;
126 @array = $sth->fetchrow_array () ;
133 ($path eq 'scratch-to-2.6') && do {
134 $version = &get_db_version ;
135 $target = "2.5.9999.1+global+data+done" ;
136 if (is_lesser $version, $target) {
137 my @filelist = qw{ /usr/lib/sourceforge/db/sf-2.6-complete.sql } ;
138 # TODO: user_rating.sql
140 foreach my $file (@filelist) {
141 debug "Processing $file" ;
142 @reqlist = @{ &parse_sql_file ($file) } ;
144 foreach my $s (@reqlist) {
147 $sth = $dbh->prepare ($query) ;
154 &update_db_version ($target) ;
155 debug "Committing." ;
159 $version = &get_db_version ;
160 $target = "2.5.9999.2+local+data+done" ;
161 if (is_lesser $version, $target) {
162 debug "Adding local data." ;
164 do "/etc/sourceforge/local.pl" or die "Cannot read /etc/sourceforge/local.pl" ;
166 my ($login, $pwd, $md5pwd, $email, $noreplymail, $date) ;
168 $login = $admin_login ;
169 $pwd = $admin_password ;
170 $md5pwd=qx/echo -n $pwd | md5sum/ ;
172 $md5pwd =~ s/(.{32}) .*/$1/ ;
173 $email = $server_admin ;
174 $noreplymail="noreply\@$domain_name" ;
178 "UPDATE groups SET homepage = '$domain_name/admin/' where group_id = 1",
179 "UPDATE groups SET homepage = '$domain_name/news/' where group_id = 2",
180 "UPDATE groups SET homepage = '$domain_name/stats/' where group_id = 3",
181 "UPDATE groups SET homepage = '$domain_name/peerrating/' where group_id = 4",
182 "UPDATE users SET email = '$noreplymail' where user_id = 100",
183 "INSERT INTO users VALUES (101,'$login','$email','$md5pwd','Sourceforge admin','A','/bin/bash','','N',2000,'shell',$date,'',1,0,NULL,NULL,0,'','GMT', 1, 0)",
184 "SELECT setval ('\"users_pk_seq\"', 102, 'f')",
185 "INSERT INTO user_group (user_id, group_id, admin_flags) VALUES (101, 1, 'A')",
186 "INSERT INTO user_group (user_id, group_id, admin_flags) VALUES (101, 2, 'A')",
187 "INSERT INTO user_group (user_id, group_id, admin_flags) VALUES (101, 3, 'A')",
188 "INSERT INTO user_group (user_id, group_id, admin_flags) VALUES (101, 4, 'A')"
191 foreach my $s (@reqlist) {
194 $sth = $dbh->prepare ($query) ;
200 &update_db_version ($target) ;
201 debug "Committing." ;
205 $version = &get_db_version ;
206 $target = "2.5.9999.3+skills+done" ;
207 if (is_lesser $version, $target) {
208 debug "Inserting skills." ;
210 foreach my $skill (split /;/, $skill_list) {
211 push @reqlist, "INSERT INTO people_skill (name) VALUES ('$skill')" ;
214 foreach my $s (@reqlist) {
217 $sth = $dbh->prepare ($query) ;
223 &update_db_version ($target) ;
224 debug "Committing." ;
228 $version = &get_db_version ;
229 $target = "2.6-0+checkpoint+1" ;
230 if (is_lesser $version, $target) {
231 debug "Updating debian_meta_data table." ;
232 $query = "DELETE FROM debian_meta_data WHERE key = 'current-path'" ;
234 $sth = $dbh->prepare ($query) ;
238 &update_db_version ($target) ;
239 debug "Committing." ;
246 ($path eq '2.5-to-2.6') && do {
248 $version = &get_db_version ;
250 if (is_lesser $version, $target) {
251 debug "Adding row to people_job_category." ;
252 $query = "INSERT INTO people_job_category VALUES (100, 'Undefined', 0)" ;
253 $sth = $dbh->prepare ($query) ;
257 &update_db_version ($target) ;
258 debug "Committing." ;
262 $version = &get_db_version ;
264 if (is_lesser $version, $target) {
265 debug "Adding row to supported_languages." ;
266 $query = "INSERT INTO supported_languages VALUES (15, 'Korean', 'Korean.class', 'Korean', 'kr')" ;
267 $sth = $dbh->prepare ($query) ;
271 &update_db_version ($target) ;
272 debug "Committing." ;
276 $version = &get_db_version ;
278 if (is_lesser $version, $target) {
279 debug "Fixing unix_box entries." ;
281 $query = "update groups set unix_box = 'shell'" ;
282 $sth = $dbh->prepare ($query) ;
286 $query = "update users set unix_box = 'shell'" ;
287 $sth = $dbh->prepare ($query) ;
291 debug "Also fixing a few sequences." ;
293 &bump_sequence_to ("bug_pk_seq", 100) ;
294 &bump_sequence_to ("project_task_pk_seq", 100) ;
296 &update_db_version ($target) ;
297 debug "Committing." ;
301 $version = &get_db_version ;
303 if (is_lesser $version, $target) {
304 debug "Adding rows to supported_languages." ;
306 "INSERT INTO supported_languages VALUES (16,'Bulgarian','Bulgarian.class','Bulgarian','bg')",
307 "INSERT INTO supported_languages VALUES (17,'Greek','Greek.class','Greek','el')",
308 "INSERT INTO supported_languages VALUES (18,'Indonesian','Indonesian.class','Indonesian','id')",
309 "INSERT INTO supported_languages VALUES (19,'Portuguese (Brazillian)','PortugueseBrazillian.class','PortugueseBrazillian', 'br')",
310 "INSERT INTO supported_languages VALUES (20,'Polish','Polish.class','Polish','pl')",
311 "INSERT INTO supported_languages VALUES (21,'Portuguese','Portuguese.class','Portuguese', 'pt')",
312 "INSERT INTO supported_languages VALUES (22,'Russian','Russian.class','Russian','ru')"
315 foreach my $s (@reqlist) {
318 $sth = $dbh->prepare ($query) ;
324 &update_db_version ($target) ;
325 debug "Committing." ;
329 $version = &get_db_version ;
331 if (is_lesser $version, $target) {
332 debug "Fixing unix_uid entries." ;
334 $query = "UPDATE users SET unix_uid = nextval ('unix_uid_seq') WHERE unix_status != 'N' AND status != 'P' AND unix_uid = 0" ;
335 $sth = $dbh->prepare ($query) ;
339 &update_db_version ($target) ;
340 debug "Committing." ;
344 $version = &get_db_version ;
345 $target = "2.5.9999.1+temp+data+dropped" ;
346 if (is_lesser $version, $target) {
347 debug "Preparing to upgrade your database - dropping temporary tables" ;
349 my @tables = qw/ user_metric_tmp1_1 user_metric_tmp1_2
350 user_metric_tmp1_3 user_metric_tmp1_4
351 user_metric_tmp1_5 user_metric_tmp1_6
352 user_metric_tmp1_7 user_metric_tmp1_8 user_metric1
353 user_metric2 user_metric3 user_metric4 user_metric5
354 user_metric6 user_metric7 user_metric8
355 project_counts_tmp project_metric_tmp
356 project_metric_tmp1 project_counts_weekly_tmp
357 project_metric_weekly_tmp project_metric_weekly_tmp1
360 my @sequences = qw/ user_metric1_ranking_seq
361 user_metric2_ranking_seq user_metric3_ranking_seq
362 user_metric4_ranking_seq user_metric5_ranking_seq
363 user_metric6_ranking_seq user_metric7_ranking_seq
364 user_metric8_ranking_seq project_metric_weekly_seq
365 trove_treesum_trove_treesum_seq
366 project_metric_tmp1_pk_seq / ;
368 my @indexes = qw/ idx_project_metric_group
369 idx_project_metric_weekly_group
370 user_metric_history_date_userid / ;
372 foreach my $table (@tables) {
373 &drop_table_if_exists ($table) ;
376 foreach my $sequence (@sequences) {
377 &drop_sequence_if_exists ($sequence) ;
380 foreach my $index (@indexes) {
381 &drop_index_if_exists ($index) ;
384 &update_db_version ($target) ;
385 debug "Committing." ;
389 $version = &get_db_version ;
390 $target = "2.5.9999.2+data+upgraded" ;
391 if (is_lesser $version, $target) {
392 debug "Upgrading your database scheme from 2.5" ;
394 @reqlist = @{ &parse_sql_file ("/usr/lib/sourceforge/db/sf2.5-to-sf2.6.sql") } ;
395 foreach my $s (@reqlist) {
398 $sth = $dbh->prepare ($query) ;
404 &update_db_version ($target) ;
405 debug "Committing." ;
409 $version = &get_db_version ;
410 $target = "2.5.9999.3+artifact+transcoded" ;
411 if (is_lesser $version, $target) {
412 debug "Transcoding the artifact data fields" ;
414 $query = "SELECT id,bin_data FROM artifact_file ORDER BY id ASC" ;
416 $sth = $dbh->prepare ($query) ;
418 while (@array = $sth->fetchrow_array) {
419 my $query2 = "UPDATE artifact_file SET bin_data='" ;
420 $query2 .= encode_base64 (decode_entities ($array [1])) ;
421 $query2 .= "' WHERE id=" ;
422 $query2 .= $array [0] ;
425 my $sth2 =$dbh->prepare ($query2) ;
432 &update_db_version ($target) ;
433 debug "Committing." ;
437 $version = &get_db_version ;
438 $target = "2.5.9999.4+groups+inserted" ;
439 if (is_lesser $version, $target) {
440 debug "Inserting missing groups" ;
443 "INSERT INTO groups (group_name, homepage,
444 is_public, status, unix_group_name,
445 unix_box, http_domain, short_description,
446 cvs_box, license, register_purpose,
447 license_other, register_time, rand_hash,
448 use_mail, use_survey, use_forum, use_pm,
449 use_cvs, use_news, type, use_docman,
450 new_task_address, send_all_tasks,
452 VALUES ('Stats', '$domain_name/top/', 0,
453 'A', 'stats', 'shell', NULL, NULL, 'cvs',
454 'website', NULL, NULL, 0, NULL, 1, 0, 0, 0, 0,
456 "INSERT INTO groups (group_name, homepage,
457 is_public, status, unix_group_name,
458 unix_box, http_domain, short_description,
459 cvs_box, license, register_purpose,
460 license_other, register_time, rand_hash,
461 use_mail, use_survey, use_forum, use_pm,
462 use_cvs, use_news, type, use_docman,
463 new_task_address, send_all_tasks,
465 VALUES ('Peer Ratings', '$domain_name/people/', 0,
466 'A', 'peerrating', 'shell', NULL, NULL, 'cvs1',
467 'website', NULL, NULL, 0, NULL, 1, 0, 0, 0, 0,
471 foreach my $s (@reqlist) {
474 $sth = $dbh->prepare ($query) ;
479 &update_db_version ($target) ;
480 debug "Committing." ;
484 $version = &get_db_version ;
485 $target = "2.6-0+checkpoint+1" ;
486 if (is_lesser $version, $target) {
487 debug "Database has successfully been converted." ;
488 $query = "DELETE FROM debian_meta_data WHERE key = 'current-path'" ;
490 $sth = $dbh->prepare ($query) ;
494 &update_db_version ($target) ;
495 debug "Committing." ;
503 $version = &get_db_version ;
504 $target = "2.6-0+checkpoint+2" ;
505 if (is_lesser $version, $target) {
506 debug "Updating permissions on system groups." ;
507 $query = "UPDATE groups SET group_name='Site Admin', is_public=1 WHERE group_id=1" ;
509 $sth = $dbh->prepare ($query) ;
512 $query = "UPDATE groups SET group_name='Site News Admin', is_public=1 WHERE group_id=$sys_news_group" ;
514 $sth = $dbh->prepare ($query) ;
518 &update_db_version ($target) ;
519 debug "Committing." ;
523 $version = &get_db_version ;
524 $target = "2.6-0+checkpoint+3" ;
525 if (is_lesser $version, $target) {
526 debug "Creating table group_cvs_history." ;
527 $query = "CREATE TABLE group_cvs_history (
528 id integer DEFAULT nextval('group_cvs_history_pk_seq'::text) NOT NULL,
529 group_id integer DEFAULT '0' NOT NULL,
530 user_name character varying(80) DEFAULT '' NOT NULL,
531 cvs_commits integer DEFAULT '0' NOT NULL,
532 cvs_commits_wk integer DEFAULT '0' NOT NULL,
533 cvs_adds integer DEFAULT '0' NOT NULL,
534 cvs_adds_wk integer DEFAULT '0' NOT NULL,
537 $sth = $dbh->prepare ($query) ;
541 &update_db_version ($target) ;
542 debug "Committing." ;
546 $version = &get_db_version ;
547 $target = "2.6-0+checkpoint+4" ;
548 if (is_lesser $version, $target) {
549 debug "Registering Savannah themes." ;
551 $query = "SELECT max(theme_id) FROM themes" ;
553 $sth = $dbh->prepare ($query) ;
555 @array = $sth->fetchrow_array () ;
557 my $maxid = $array [0] ;
559 &bump_sequence_to ("themes_pk_seq", $maxid) ;
562 "INSERT INTO themes (dirname, fullname) VALUES ('savannah_codex', 'Savannah CodeX')",
563 "INSERT INTO themes (dirname, fullname) VALUES ('savannah_forest', 'Savannah Forest')",
564 "INSERT INTO themes (dirname, fullname) VALUES ('savannah_reverse', 'Savannah Reverse')",
565 "INSERT INTO themes (dirname, fullname) VALUES ('savannah_sad', 'Savannah Sad')",
566 "INSERT INTO themes (dirname, fullname) VALUES ('savannah_savannah', 'Savannah Original')",
567 "INSERT INTO themes (dirname, fullname) VALUES ('savannah_slashd', 'Savannah SlashDot')",
568 "INSERT INTO themes (dirname, fullname) VALUES ('savannah_startrek', 'Savannah StarTrek')",
569 "INSERT INTO themes (dirname, fullname) VALUES ('savannah_transparent', 'Savannah Transparent')",
570 "INSERT INTO themes (dirname, fullname) VALUES ('savannah_water', 'Savannah Water')",
571 "INSERT INTO themes (dirname, fullname) VALUES ('savannah_www.gnu.org', 'Savannah www.gnu.org')"
573 foreach my $s (@reqlist) {
576 $sth = $dbh->prepare ($query) ;
583 $version = &get_db_version ;
584 $target = "2.6-0+checkpoint+5" ;
585 if (is_lesser $version, $target) {
586 debug "Registering yet another Savannah theme." ;
588 $query = "INSERT INTO themes (dirname, fullname) VALUES ('savannah_darkslate', 'Savannah Dark Slate')";
590 $sth = $dbh->prepare ($query) ;
594 &update_db_version ($target) ;
595 debug "Committing." ;
599 $version = &get_db_version ;
600 $target = "2.6-0+checkpoint+6" ;
601 if (is_lesser $version, $target) {
602 debug "Updating language code." ;
605 "UPDATE supported_languages SET language_code='en' where classname='English'",
606 "UPDATE supported_languages SET language_code='ja' where classname='Japanese'",
607 "UPDATE supported_languages SET language_code='iw' where classname='Hebrew'",
608 "UPDATE supported_languages SET language_code='es' where classname='Spanish'",
609 "UPDATE supported_languages SET language_code='th' where classname='Thai'",
610 "UPDATE supported_languages SET language_code='de' where classname='German'",
611 "UPDATE supported_languages SET language_code='it' where classname='Italian'",
612 "UPDATE supported_languages SET language_code='no' where classname='Norwegian'",
613 "UPDATE supported_languages SET language_code='sv' where classname='Swedish'",
614 "UPDATE supported_languages SET language_code='zh' where classname='Chinese'",
615 "UPDATE supported_languages SET language_code='nl' where classname='Dutch'",
616 "UPDATE supported_languages SET language_code='eo' where classname='Esperanto'",
617 "UPDATE supported_languages SET language_code='ca' where classname='Catalan'",
618 "UPDATE supported_languages SET language_code='ko' where classname='Korean'",
619 "UPDATE supported_languages SET language_code='bg' where classname='Bulgarian'",
620 "UPDATE supported_languages SET language_code='el' where classname='Greek'",
621 "UPDATE supported_languages SET language_code='id' where classname='Indonesian'",
622 "UPDATE supported_languages SET language_code='pt' where classname='Portuguese (Brazillian)'",
623 "UPDATE supported_languages SET language_code='pl' where classname='Polish'",
624 "UPDATE supported_languages SET language_code='pt' where classname='Portuguese'",
625 "UPDATE supported_languages SET language_code='ru' where classname='Russian'",
626 "UPDATE supported_languages SET language_code='fr' where classname='French'"
628 foreach my $s (@reqlist) {
631 $sth = $dbh->prepare ($query) ;
636 &update_db_version ($target) ;
637 debug "Committing." ;
641 debug "It seems your database $action went well and smoothly. That's cool." ;
642 debug "Please enjoy using Debian Sourceforge." ;
644 # There should be a commit at the end of every block above.
645 # If there is not, then it might be symptomatic of a problem.
646 # For safety, we roll back.
651 warn "Transaction aborted because $@" ;
652 debug "Transaction aborted because $@" ;
653 debug "Last SQL query was:\n$query\n(end of query)" ;
655 debug "Please report this bug on the Debian bug-tracking system." ;
656 debug "Please include the previous messages as well to help debugging." ;
657 debug "You should not worry too much about this," ;
658 debug "your DB is still in a consistent state and should be usable." ;
665 sub is_lesser ( $$ ) {
666 my $v1 = shift || 0 ;
667 my $v2 = shift || 0 ;
669 my $rc = system "dpkg --compare-versions $v1 lt $v2" ;
674 sub is_greater ( $$ ) {
675 my $v1 = shift || 0 ;
676 my $v2 = shift || 0 ;
678 my $rc = system "dpkg --compare-versions $v1 gt $v2" ;
686 print STDERR "$v\n" ;
689 sub create_metadata_table ( $ ) {
690 my $v = shift || "2.5-7+just+before+8" ;
691 # Do we have the metadata table?
693 $query = "SELECT count(*) FROM pg_class WHERE relname = 'debian_meta_data' and relkind = 'r'";
695 my $sth = $dbh->prepare ($query) ;
697 my @array = $sth->fetchrow_array () ;
700 # Let's create this table if we have it not
702 if ($array [0] == 0) {
703 debug "Creating debian_meta_data table." ;
704 $query = "CREATE TABLE debian_meta_data (key varchar primary key, value text not null)" ;
706 $sth = $dbh->prepare ($query) ;
711 $query = "SELECT count(*) FROM debian_meta_data WHERE key = 'db-version'";
713 $sth = $dbh->prepare ($query) ;
715 @array = $sth->fetchrow_array () ;
718 # Empty table? We'll have to fill it up a bit
720 if ($array [0] == 0) {
721 debug "Inserting first data into debian_meta_data table." ;
722 $query = "INSERT INTO debian_meta_data (key, value) VALUES ('db-version', '$v')" ;
724 $sth = $dbh->prepare ($query) ;
730 sub update_db_version ( $ ) {
731 my $v = shift or die "Not enough arguments" ;
733 debug "Updating debian_meta_data table." ;
734 $query = "UPDATE debian_meta_data SET value = '$v' WHERE key = 'db-version'" ;
736 my $sth = $dbh->prepare ($query) ;
741 sub get_db_version () {
742 $query = "SELECT value FROM debian_meta_data WHERE key = 'db-version'" ;
744 my $sth = $dbh->prepare ($query) ;
746 my @array = $sth->fetchrow_array () ;
749 my $version = $array [0] ;
754 sub drop_table_if_exists ( $ ) {
755 my $tname = shift or die "Not enough arguments" ;
756 $query = "SELECT count(*) FROM pg_class WHERE relname='$tname' AND relkind='r'" ;
757 my $sth = $dbh->prepare ($query) ;
759 my @array = $sth->fetchrow_array () ;
762 if ($array [0] != 0) {
763 # debug "Dropping table $tname" ;
764 $query = "DROP TABLE $tname" ;
766 $sth = $dbh->prepare ($query) ;
772 sub drop_sequence_if_exists ( $ ) {
773 my $sname = shift or die "Not enough arguments" ;
774 $query = "SELECT count(*) FROM pg_class WHERE relname='$sname' AND relkind='S'" ;
775 my $sth = $dbh->prepare ($query) ;
777 my @array = $sth->fetchrow_array () ;
780 if ($array [0] != 0) {
781 # debug "Dropping sequence $sname" ;
782 $query = "DROP SEQUENCE $sname" ;
784 $sth = $dbh->prepare ($query) ;
790 sub drop_index_if_exists ( $ ) {
791 my $iname = shift or die "Not enough arguments" ;
792 $query = "SELECT count(*) FROM pg_class WHERE relname='$iname' AND relkind='i'" ;
793 my $sth = $dbh->prepare ($query) ;
795 my @array = $sth->fetchrow_array () ;
798 if ($array [0] != 0) {
799 # debug "Dropping index $iname" ;
800 $query = "DROP INDEX $iname" ;
802 $sth = $dbh->prepare ($query) ;
808 sub bump_sequence_to ( $$ ) {
809 my ($sth, @array, $seqname, $targetvalue) ;
812 $targetvalue = shift ;
815 $query = "select nextval ('$seqname')" ;
816 $sth = $dbh->prepare ($query) ;
818 @array = $sth->fetchrow_array () ;
820 } until $array[0] >= $targetvalue ;