[system] / branches / rel-2-4-patches / webwork-modperl / bin / wwdb_upgrade Repository:
ViewVC logotype

View of /branches/rel-2-4-patches/webwork-modperl/bin/wwdb_upgrade

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5734 - (download) (annotate)
Tue Jun 24 00:44:59 2008 UTC (4 years, 11 months ago)
File size: 19100 byte(s)
This commit was manufactured by cvs2svn to create branch 'rel-2-4-patches'.

    1 #!/usr/bin/env perl
    2 ################################################################################
    3 # WeBWorK Online Homework Delivery System
    4 # Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/
    5 # $CVSHeader: webwork2/bin/wwdb_upgrade,v 1.13 2007/04/04 15:05:25 glarose Exp $
    6 # 
    7 # This program is free software; you can redistribute it and/or modify it under
    8 # the terms of either: (a) the GNU General Public License as published by the
    9 # Free Software Foundation; either version 2, or (at your option) any later
   10 # version, or (b) the "Artistic License" which comes with this package.
   11 # 
   12 # This program is distributed in the hope that it will be useful, but WITHOUT
   13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   14 # FOR A PARTICULAR PURPOSE.  See either the GNU General Public License or the
   15 # Artistic License for more details.
   16 ################################################################################
   17 
   18 use strict;
   19 use warnings;
   20 use Getopt::Std;
   21 use DBI;
   22 use Data::Dumper;
   23 
   24 BEGIN {
   25 	die "WEBWORK_ROOT not found in environment.\n"
   26 		unless exists $ENV{WEBWORK_ROOT};
   27 }
   28 
   29 use lib "$ENV{WEBWORK_ROOT}/lib";
   30 use WeBWorK::CourseEnvironment;
   31 use WeBWorK::Utils qw/runtime_use/;
   32 use WeBWorK::Utils::CourseManagement qw/listCourses/;
   33 
   34 our ($opt_v);
   35 getopts("v");
   36 
   37 if ($opt_v) {
   38 	$| = 1;
   39 	*verbose = sub { print STDERR @_ };
   40 } else {
   41 	*verbose = sub {};
   42 }
   43 
   44 # global variables, hah hah.
   45 my ($dbh, %sql_tables);
   46 
   47 ################################################################################
   48 
   49 my $i = -1;
   50 our @DB_VERSIONS;
   51 
   52 $DB_VERSIONS[++$i]{desc} = "is the initial version of database, identical to database structure in WeBWorK 2.2.x.";
   53 
   54 $DB_VERSIONS[++$i]{desc} = "adds dbupgrade table to facilitate automatic database upgrades.";
   55 $DB_VERSIONS[  $i]{global_code} = sub {
   56 	$dbh->do("CREATE TABLE `dbupgrade` (`name` VARCHAR(255) NOT NULL PRIMARY KEY, `value` TEXT)");
   57 	$dbh->do("INSERT INTO `dbupgrade` (`name`, `value`) VALUES (?, ?)", {}, "db_version", 1);
   58 	$sql_tables{dbupgrade} = ();
   59 };
   60 
   61 $DB_VERSIONS[++$i]{desc} = "adds problems_per_page field to set and set_user tables of each course.";
   62 $DB_VERSIONS[  $i]{course_code} = sub {
   63 	my $course = shift;
   64 	$dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `problems_per_page` INT")
   65 		if exists $sql_tables{"${course}_set"};
   66 	$dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `problems_per_page` INT")
   67 		if exists $sql_tables{"${course}_set_user"};
   68 };
   69 
   70 $DB_VERSIONS[++$i]{desc} = "adds depths table to keep track of dvipng depth information.";
   71 $DB_VERSIONS[  $i]{global_code} = sub {
   72 	$dbh->do("CREATE TABLE depths (md5 CHAR(33) NOT NULL, depth SMALLINT, PRIMARY KEY (md5))");
   73 	$sql_tables{depths} = ();
   74 };
   75 
   76 $DB_VERSIONS[++$i]{desc} = "changes type of key timestamp field to BIGINT";
   77 $DB_VERSIONS[  $i]{course_code} = sub {
   78 	my $course = shift;
   79 	return unless exists $sql_tables{"${course}_key"};
   80 	$dbh->do("ALTER TABLE `${course}_key` CHANGE COLUMN `timestamp` `timestamp` BIGINT");
   81 };
   82 
   83 $DB_VERSIONS[++$i]{desc} = "changes type of problem_user status field to FLOAT";
   84 $DB_VERSIONS[  $i]{course_code} = sub {
   85 	my $course = shift;
   86 	return unless exists $sql_tables{"${course}_problem_user"};
   87 	$dbh->do("UPDATE `${course}_problem_user` SET `status`=NULL WHERE `status`=''");
   88 	$dbh->do("ALTER TABLE `${course}_problem_user` CHANGE COLUMN `status` `status` FLOAT");
   89 };
   90 
   91 $DB_VERSIONS[++$i]{desc} = "changes types of alphanumeric keyfields to TINYBLOB NOT NULL";
   92 $DB_VERSIONS[  $i]{course_code} = sub {
   93 	my $course = shift;
   94 	$dbh->do("ALTER TABLE `${course}_user` CHANGE COLUMN `user_id` `user_id` TINYBLOB NOT NULL")
   95 		if exists $sql_tables{"${course}_user"};
   96 	$dbh->do("ALTER TABLE `${course}_password` CHANGE COLUMN `user_id` `user_id` TINYBLOB NOT NULL")
   97 		if exists $sql_tables{"${course}_password"};
   98 	$dbh->do("ALTER TABLE `${course}_permission` CHANGE COLUMN `user_id` `user_id` TINYBLOB NOT NULL")
   99 		if exists $sql_tables{"${course}_permission"};
  100 	$dbh->do("ALTER TABLE `${course}_key` CHANGE COLUMN `user_id` `user_id` TINYBLOB NOT NULL")
  101 		if exists $sql_tables{"${course}_key"};
  102 	$dbh->do("ALTER TABLE `${course}_set` CHANGE COLUMN `set_id` `set_id` TINYBLOB NOT NULL")
  103 		if exists $sql_tables{"${course}_set"};
  104 	$dbh->do("ALTER TABLE `${course}_problem` CHANGE COLUMN `set_id` `set_id` TINYBLOB NOT NULL")
  105 		if exists $sql_tables{"${course}_problem"};
  106 	$dbh->do("ALTER TABLE `${course}_set_user` CHANGE COLUMN `user_id` `user_id` TINYBLOB NOT NULL")
  107 		if exists $sql_tables{"${course}_set_user"};
  108 	$dbh->do("ALTER TABLE `${course}_set_user` CHANGE COLUMN `set_id` `set_id` TINYBLOB NOT NULL")
  109 		if exists $sql_tables{"${course}_set_user"};
  110 	$dbh->do("ALTER TABLE `${course}_problem_user` CHANGE COLUMN `user_id` `user_id` TINYBLOB NOT NULL")
  111 		if exists $sql_tables{"${course}_problem_user"};
  112 	$dbh->do("ALTER TABLE `${course}_problem_user` CHANGE COLUMN `set_id` `set_id` TINYBLOB NOT NULL")
  113 		if exists $sql_tables{"${course}_problem_user"};
  114 };
  115 
  116 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for user table";
  117 $DB_VERSIONS[  $i]{course_code} = sub {
  118 	my $course = shift;
  119 	return unless exists $sql_tables{"${course}_user"};
  120 	$dbh->do("ALTER TABLE `${course}_user` DROP KEY `user_id`");
  121 	$dbh->do("ALTER TABLE `${course}_user` ADD UNIQUE KEY (`user_id`(255))");
  122 };
  123 
  124 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for password table";
  125 $DB_VERSIONS[  $i]{course_code} = sub {
  126 	my $course = shift;
  127 	return unless exists $sql_tables{"${course}_password"};
  128 	$dbh->do("ALTER TABLE `${course}_password` DROP KEY `user_id`");
  129 	$dbh->do("ALTER TABLE `${course}_password` ADD UNIQUE KEY (`user_id`(255))");
  130 };
  131 
  132 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for permission table";
  133 $DB_VERSIONS[  $i]{course_code} = sub {
  134 	my $course = shift;
  135 	return unless exists $sql_tables{"${course}_permission"};
  136 	$dbh->do("ALTER TABLE `${course}_permission` DROP KEY `user_id`");
  137 	$dbh->do("ALTER TABLE `${course}_permission` ADD UNIQUE KEY (`user_id`(255))");
  138 };
  139 
  140 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for key table";
  141 $DB_VERSIONS[  $i]{course_code} = sub {
  142 	my $course = shift;
  143 	return unless exists $sql_tables{"${course}_key"};
  144 	$dbh->do("ALTER TABLE `${course}_key` DROP KEY `user_id`");
  145 	$dbh->do("ALTER TABLE `${course}_key` ADD UNIQUE KEY (`user_id`(255))");
  146 };
  147 
  148 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for set table";
  149 $DB_VERSIONS[  $i]{course_code} = sub {
  150 	my $course = shift;
  151 	return unless exists $sql_tables{"${course}_set"};
  152 	$dbh->do("ALTER TABLE `${course}_set` DROP KEY `set_id`");
  153 	$dbh->do("ALTER TABLE `${course}_set` ADD UNIQUE KEY (`set_id`(255))");
  154 };
  155 
  156 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for problem table";
  157 $DB_VERSIONS[  $i]{course_code} = sub {
  158 	my $course = shift;
  159 	return unless exists $sql_tables{"${course}_problem"};
  160 	$dbh->do("ALTER TABLE `${course}_problem` DROP KEY `set_id`");
  161 	$dbh->do("ALTER TABLE `${course}_problem` ADD UNIQUE KEY (`set_id`(255), `problem_id`)");
  162 	$dbh->do("ALTER TABLE `${course}_problem` DROP KEY `problem_id`");
  163 	$dbh->do("ALTER TABLE `${course}_problem` ADD KEY (`problem_id`)");
  164 };
  165 
  166 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for set_user table";
  167 $DB_VERSIONS[  $i]{course_code} = sub {
  168 	my $course = shift;
  169 	return unless exists $sql_tables{"${course}_set_user"};
  170 	$dbh->do("ALTER TABLE `${course}_set_user` DROP KEY `user_id`");
  171 	$dbh->do("ALTER TABLE `${course}_set_user` ADD UNIQUE KEY (`user_id`(255), `set_id`(255))");
  172 	$dbh->do("ALTER TABLE `${course}_set_user` DROP KEY `set_id`");
  173 	$dbh->do("ALTER TABLE `${course}_set_user` ADD KEY (`set_id`(255))");
  174 };
  175 
  176 $DB_VERSIONS[++$i]{desc} = "fixes KEY length, adds UNIQUE KEY for problem_user table";
  177 $DB_VERSIONS[  $i]{course_code} = sub {
  178 	my $course = shift;
  179 	return unless exists $sql_tables{"${course}_problem_user"};
  180 	$dbh->do("ALTER TABLE `${course}_problem_user` DROP KEY `user_id`");
  181 	$dbh->do("ALTER TABLE `${course}_problem_user` ADD UNIQUE KEY (`user_id`(255), `set_id`(255), `problem_id`)");
  182 	$dbh->do("ALTER TABLE `${course}_problem_user` DROP KEY `set_id`");
  183 	$dbh->do("ALTER TABLE `${course}_problem_user` ADD KEY (`set_id`(255), `problem_id`)");
  184 	$dbh->do("ALTER TABLE `${course}_problem_user` DROP KEY `problem_id`");
  185 	$dbh->do("ALTER TABLE `${course}_problem_user` ADD KEY (`problem_id`)");
  186 };
  187 
  188 $DB_VERSIONS[++$i]{desc} = "changes psvn index from PRIMARY KEY to UNIQUE KEY";
  189 $DB_VERSIONS[  $i]{course_code} = sub {
  190 	my $course = shift;
  191 	return unless exists $sql_tables{"${course}_set_user"};
  192 	$dbh->do("ALTER TABLE `${course}_set_user` ADD UNIQUE KEY (`psvn`)");
  193 	$dbh->do("ALTER TABLE `${course}_set_user` DROP PRIMARY KEY");
  194 };
  195 
  196 $DB_VERSIONS[++$i]{desc} = "adds hide_score and hide_work fields to set and set_user";
  197 $DB_VERSIONS[  $i]{course_code} = sub {
  198 	my $course = shift;
  199 	if ( exists $sql_tables{"${course}_set"} ) {
  200 		$dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `hide_score` ENUM('0','1')");
  201 		$dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `hide_work` ENUM('0','1')");
  202 	}
  203 	if ( exists $sql_tables{"${course}_set_user"} ) {
  204 		$dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `hide_score` ENUM('0','1')");
  205 		$dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `hide_work` ENUM('0','1')");
  206 	}
  207 };
  208 
  209 $DB_VERSIONS[++$i]{desc} = "updates hide_score and hide_work in set and set_user tables to allow more (and more descriptive) possible values";
  210 $DB_VERSIONS[  $i]{course_code} = sub {
  211 	my $course = shift;
  212 	if ( exists $sql_tables{"${course}_set"} ) {
  213 		$dbh->do("ALTER TABLE `${course}_set` MODIFY COLUMN `hide_score` ENUM('0','1','2')");
  214 		$dbh->do("ALTER TABLE `${course}_set` MODIFY COLUMN `hide_work` ENUM('0','1','2')");
  215 	}
  216 	if ( exists $sql_tables{"${course}_set_user"} ) {
  217 		$dbh->do("ALTER TABLE `${course}_set_user` MODIFY COLUMN `hide_score` ENUM('0','1','2')");
  218 		$dbh->do("ALTER TABLE `${course}_set_user` MODIFY COLUMN `hide_work` ENUM('0','1','2')");
  219 	}
  220 };
  221 
  222 $DB_VERSIONS[++$i]{desc} = "adds time_limit_cap field to set and set_user tables";
  223 $DB_VERSIONS[  $i]{course_code} = sub {
  224 	my $course = shift;
  225 	if ( exists $sql_tables{"${course}_set"} ) {
  226 		$dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `time_limit_cap` ENUM('0','1')");
  227 	}
  228 	if ( exists $sql_tables{"${course}_set_user"} ) {
  229 		$dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `time_limit_cap` ENUM('0','1')");
  230 	}
  231 };
  232 
  233 $DB_VERSIONS[++$i]{desc} = "updates hide_score and hide_work in set and set_user tables to have more descriptive values, set default values";
  234 $DB_VERSIONS[  $i]{course_code} = sub {
  235 	my $course = shift;
  236 	if ( exists $sql_tables{"${course}_set"} ) {
  237 		$dbh->do("ALTER TABLE `${course}_set` MODIFY COLUMN `hide_score` ENUM('N','Y','BeforeAnswerDate') DEFAULT 'N'");
  238 		$dbh->do("ALTER TABLE `${course}_set` MODIFY COLUMN `hide_work` ENUM('N','Y','BeforeAnswerDate') DEFAULT 'N'");
  239 	}
  240 	if ( exists $sql_tables{"${course}_set_user"} ) {
  241 		$dbh->do("ALTER TABLE `${course}_set_user` MODIFY COLUMN `hide_score` ENUM('N','Y','BeforeAnswerDate') DEFAULT 'N'");
  242 		$dbh->do("ALTER TABLE `${course}_set_user` MODIFY COLUMN `hide_work` ENUM('N','Y','BeforeAnswerDate') DEFAULT 'N'");
  243 	}
  244 };
  245 
  246 $DB_VERSIONS[++$i]{desc} = "adds locations, location_addresses, set_locations and set_locations_user tables to database, and add restrict_ip to set and set_user.";
  247 $DB_VERSIONS[  $i]{global_code} = sub {
  248 	$dbh->do("CREATE TABLE locations (location_id TINYBLOB NOT NULL, description TEXT, PRIMARY KEY (location_id(1000)))");
  249 	$dbh->do("CREATE TABLE location_addresses (location_id TINYBLOB NOT NULL, ip_mask TINYBLOB NOT NULL, PRIMARY KEY (location_id(500),ip_mask(500)))");
  250 };
  251 $DB_VERSIONS[  $i]{course_code} = sub {
  252 	my $course = shift;
  253 	
  254 	$dbh->do("CREATE TABLE `${course}_set_locations` (set_id TINYBLOB NOT NULL, location_id TINYBLOB NOT NULL, PRIMARY KEY (set_id(500),location_id(500)))");
  255 	$dbh->do("CREATE TABLE `${course}_set_locations_user` (set_id TINYBLOB NOT NULL, user_id TINYBLOB NOT NULL, location_id TINYBLOB NOT NULL, PRIMARY KEY (set_id(300),user_id(300),location_id(300)))");
  256 
  257 	if ( exists $sql_tables{"${course}_set"} ) {
  258 		$dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `restrict_ip` enum('No','RestrictTo','DenyFrom') DEFAULT 'No'");
  259 	}
  260 	if ( exists $sql_tables{"${course}_set_user"} ) {
  261 		$dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `restrict_ip` enum('No','RestrictTo','DenyFrom')");
  262 	}
  263 };
  264 
  265 $DB_VERSIONS[++$i]{desc} = "updates defaults for hide_work and hide_score in set_user tables.";
  266 $DB_VERSIONS[  $i]{course_code} = sub {
  267 	my $course = shift;
  268 
  269 	if ( exists $sql_tables{"${course}_set_user"} ) {
  270 		$dbh->do("ALTER TABLE `${course}_set_user` MODIFY COLUMN `hide_score` ENUM('N','Y','BeforeAnswerDate')");
  271 		$dbh->do("ALTER TABLE `${course}_set_user` MODIFY COLUMN `hide_work` ENUM('N','Y','BeforeAnswerDate')");
  272 	}
  273 };
  274 
  275 $DB_VERSIONS[++$i]{desc} = "adds relax_restrict_ip, hide_problem_score columns to set and set_user tables.";
  276 $DB_VERSIONS[  $i]{course_code} = sub {
  277 	my $course = shift;
  278 
  279 	if ( exists $sql_tables{"${course}_set"} ) {
  280 		$dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `relax_restrict_ip` ENUM('No','AfterAnswerDate','AfterVersionAnswerDate') DEFAULT 'No'");
  281 		$dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `hide_score_by_problem` ENUM('N','Y') DEFAULT 'N'");
  282 	}
  283 	if ( exists $sql_tables{"${course}_set_user"} ) {
  284 		$dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `relax_restrict_ip` ENUM('No','AfterAnswerDate','AfterVersionAnswerDate')");
  285 		$dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `hide_score_by_problem` ENUM('N','Y')");
  286 	}
  287 };
  288 
  289 $DB_VERSIONS[++$i]{desc} = "adds set and set_user fields to allow set-level proctor, updates permissions to allow finer-grained regulation of proctoring.";
  290 $DB_VERSIONS[  $i]{course_code} = sub {
  291 	my $course = shift;
  292 	if ( exists $sql_tables{"${course}_permission"} ) {
  293 		$dbh->do("UPDATE `${course}_permission` SET `permission`=3 where `permission`=2");
  294 	}
  295 	if ( exists $sql_tables{"${course}_set"} ) {
  296 		$dbh->do("ALTER TABLE `${course}_set` ADD COLUMN `restricted_login_proctor` ENUM('No','Yes') DEFAULT 'No'");
  297 	}
  298 	if ( exists $sql_tables{"${course}_set_user"} ) {
  299 		$dbh->do("ALTER TABLE `${course}_set_user` ADD COLUMN `restricted_login_proctor` ENUM('No','Yes')");
  300 	}
  301 };
  302 
  303 our $THIS_DB_VERSION = $i;
  304 
  305 ################################################################################
  306 
  307 my $ce = WeBWorK::CourseEnvironment->new({
  308 	webwork_dir => $ENV{WEBWORK_ROOT},
  309 });
  310 
  311 my @ww_courses = listCourses($ce);
  312 
  313 $dbh = DBI->connect(
  314 	$ce->{database_dsn},
  315 	$ce->{database_username},
  316 	$ce->{database_password},
  317 	{
  318 		PrintError => 0,
  319 		RaiseError => 1,
  320 	},
  321 );
  322 
  323 {
  324 	verbose("Obtaining dbupgrade lock...\n");
  325 	my ($lock_status) = $dbh->selectrow_array("SELECT GET_LOCK('dbupgrade', 10)");
  326 	if (not defined $lock_status) {
  327 		print "Couldn't obtain lock because an error occurred.\n";
  328 		exit 2;
  329 	}
  330 	if ($lock_status) {
  331 		verbose("Got lock.\n");
  332 	} else {
  333 		print "Timed out while waiting for lock.\n";
  334 		exit 2;
  335 	}
  336 }
  337 
  338 %sql_tables = get_sql_tables();
  339 
  340 my $db_version = exists $sql_tables{dbupgrade} ? get_db_version() : 0;
  341 
  342 if (not defined $db_version) {
  343 	print "Failed to get db_version -- can't continue.\n";
  344 	exit 1;
  345 }
  346 
  347 verbose("Initial db_version is $db_version\n");
  348 
  349 if ($db_version > $THIS_DB_VERSION) {
  350 	print "db_version is $db_version, but the current database version is only $THIS_DB_VERSION. This database was probably used with a newer version of WeBWorK.\n";
  351 	exit;
  352 }
  353 
  354 while ($db_version < $THIS_DB_VERSION) {
  355 	$db_version++;
  356 	unless (upgrade_to_version($db_version)) {
  357 		print "\nUpgrading from version ".($db_version-1)." to $db_version failed.\n\n";
  358 		unless (ask_permission("Ignore this error and go on to the next version?", 0)) {
  359 			exit 3;
  360 		}
  361 	}
  362 	set_db_version($db_version);
  363 }
  364 
  365 print "\nDatabase is up-to-date at version $db_version.\n";
  366 
  367 END {
  368 	verbose("Releasing dbupgrade lock...\n");
  369 	my ($lock_status) = $dbh->selectrow_array("SELECT RELEASE_LOCK('dbupgrade')");
  370 	if (not defined $lock_status) {
  371 		print "Couldn't release lock because the lock does not exist.\n";
  372 		exit 2;
  373 	}
  374 	if ($lock_status) {
  375 		verbose("Released lock.\n");
  376 	} else {
  377 		print "Couldn't release lock because the lock is not held by this thread.\n";
  378 		exit 2;
  379 	}
  380 }
  381 
  382 ################################################################################
  383 
  384 sub get_sql_tables {
  385 	my $sql_tables_ref = $dbh->selectcol_arrayref("SHOW TABLES");
  386 	my %sql_tables; @sql_tables{@$sql_tables_ref} = ();
  387 	
  388 	return %sql_tables;
  389 }
  390 
  391 sub get_db_version {
  392 	my $vers_value_should_be = "This value should always be a positive integer.";
  393 	my $vers_stop_now = "You should stop now and take a closer look.";
  394 	
  395 	my @record = $dbh->selectrow_array("SELECT `value` FROM `dbupgrade` WHERE `name`='db_version'");
  396 	if (@record) {
  397 		my $db_version = $record[0];
  398 		if (not defined $db_version) {
  399 			print "'db_version' exists, but it has a NULL value. $vers_value_should_be $vers_stop_now\n";
  400 			return;
  401 		} elsif ($db_version !~ /^-?\d+$/) {
  402 			print "'db_version' is set to the non-numeric value '$db_version'. $vers_value_should_be $vers_stop_now\n";
  403 			return;
  404 		} elsif ($db_version < 0) {
  405 			print "'db_version' is set to the negative value '$db_version'. $vers_value_should_be $vers_stop_now\n";
  406 			return;
  407 		} elsif ($db_version == 0) {
  408 			print "'db_version' is set 0, which is reserved to indicate a pre-automatic-upgrade version. $vers_value_should_be $vers_stop_now\n";
  409 			return;
  410 		} else {
  411 			# db_version is positive! yay!
  412 			return $db_version;
  413 		}
  414 	} else {
  415 		print "The 'dbupgrade' table exists, but doesn't contain a 'db_version' setting. $vers_stop_now\n";
  416 		return;
  417 	}
  418 }
  419 
  420 sub set_db_version {
  421 	my $vers = shift;
  422 	$dbh->do("UPDATE `dbupgrade` SET `value`=? WHERE `name`='db_version'", {}, $vers);
  423 }
  424 
  425 sub upgrade_to_version {
  426 	my $vers = shift;
  427 	my %info = %{$DB_VERSIONS[$vers]};
  428 	
  429 	print "\nUpgrading database from version " . ($vers-1) . " to $vers...\n";
  430 	my $desc = $info{desc} || "has no description.";
  431 	print "(Version $vers $desc)\n";
  432 	
  433 	if (exists $info{global_code}) {
  434 		eval { $info{global_code}->() };
  435 		if ($@) {
  436 			print "\nAn error occured while running the system upgrade code for version $vers:\n";
  437 			print "$@";
  438 			return 0 unless ask_permission("Ignore this error and keep going?", 0);
  439 		}
  440 	}
  441 	
  442 	if (@ww_courses and exists $info{course_code}) {
  443 		foreach my $curr_course (@ww_courses) {
  444 			eval { $info{course_code}->($curr_course) };
  445 			if ($@) {
  446 				print "\nAn error occured while running the course upgrade code for version $vers on course $curr_course:\n";
  447 				print "$@";
  448 				next if ask_permission("Ignore this error and go on to the next course?", 0);
  449 			}
  450 		}
  451 	}
  452 	
  453 	print "Done.\n";
  454 	return 1;
  455 }
  456 
  457 ################################################################################
  458 
  459 sub ask_permission {
  460 	my ($prompt, $default) = @_;
  461 	
  462 	$default = 1 if not defined $default;
  463 	my $options = $default ? "[Y/n]" : "[y/N]";
  464 	
  465 	while (1) {
  466 		print "$prompt $options ";
  467 		my $resp = <STDIN>;
  468 		chomp $resp;
  469 		return $default if $resp eq "";
  470 		return 1 if lc $resp eq "y";
  471 		return 0 if lc $resp eq "n";
  472 		$prompt = 'Please enter "y" or "n".';
  473 	}
  474 }

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9