refactor(contest): finalTest database transaction
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Baoshuo Ren 2023-02-20 09:45:40 +08:00
parent c2fdca91cd
commit d7741c2910
Signed by: baoshuo
GPG Key ID: 00CB9680AB29F51A
5 changed files with 310 additions and 295 deletions

View File

@ -185,7 +185,7 @@ CREATE TABLE `contests` (
`zan` int NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `status` (`status`,`id`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
@ -337,7 +337,7 @@ CREATE TABLE `contests_submissions` (
`cnt` int DEFAULT NULL,
`n_failures` int DEFAULT NULL,
PRIMARY KEY (`contest_id`,`submitter`,`problem_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--

View File

@ -19,7 +19,7 @@ class DB {
$dbname = UOJConfig::$data['database']['database'];
DB::$conn = new mysqli($server, $username, $password, $dbname);
if (DB::$conn->connect_error) {
UOJLog::error('database initialization failed: '. DB::$conn->connect_error);
UOJLog::error('database initialization failed: ' . DB::$conn->connect_error);
die('There is something wrong with the database >_<... Connection failed');
}
if (!DB::$conn->set_charset("utf8mb4")) {
@ -49,7 +49,7 @@ class DB {
return DB::raw(DB::tuple($vals));
}
public static function call($fun, ...$args) {
return DB::raw("{$fun}(".implode(',', array_map('DB::value', $args)).')');
return DB::raw("{$fun}(" . implode(',', array_map('DB::value', $args)) . ')');
}
public static function now() {
return DB::call('now');
@ -58,7 +58,7 @@ class DB {
return DB::call('instr', $str, $substr);
}
public static function cast_as_json($value) {
return DB::raw('cast('.DB::value($value).' as json)');
return DB::raw('cast(' . DB::value($value) . ' as json)');
}
public static function json_set($json_doc, ...$args) {
return DB::call('json_set', DB::raw($json_doc), ...$args);
@ -101,7 +101,7 @@ class DB {
return implode(',', $fields);
}
public static function bracketed_fields($fields) {
return '('.DB::fields($fields).')';
return '(' . DB::fields($fields) . ')';
}
public static function value($str) {
if ($str === null) {
@ -110,10 +110,10 @@ class DB {
return 'true';
} elseif ($str === false) {
return 'false';
} elseif (is_int($str)|| is_float($str)) {
} elseif (is_int($str) || is_float($str)) {
return $str;
} elseif (is_string($str)) {
return '\''.DB::escape($str).'\'';
return '\'' . DB::escape($str) . '\'';
} elseif ($str instanceof DBRawString) {
return $str->str;
} else {
@ -124,15 +124,15 @@ class DB {
return "{$field} as {$name}";
}
public static function value_as($value, $name) {
return DB::value($value)." as {$name}";
return DB::value($value) . " as {$name}";
}
public static function if_func($conds, $val1, $val2) {
return 'if('.DB::conds($conds).','.DB::value($val1).','.DB::value($val2).')';
return 'if(' . DB::conds($conds) . ',' . DB::value($val1) . ',' . DB::value($val2) . ')';
}
public static function setValue($field, $val) {
return $field.' = '.DB::value($val);
return $field . ' = ' . DB::value($val);
}
public static function setValues(array $arr) {
$all = [];
@ -152,7 +152,7 @@ class DB {
$lhs = $cond[0] instanceof DBRawString ? $cond[0]->str : $cond[0];
$op = $cond[1];
$rhs = DB::value($cond[2]);
return $lhs.' '.$op.' '.$rhs;
return $lhs . ' ' . $op . ' ' . $rhs;
} else {
return false;
}
@ -178,7 +178,7 @@ class DB {
}
$conds = $new_conds;
}
return '('.implode(' and ', array_map('DB::cond', $conds)).')';
return '(' . implode(' and ', array_map('DB::cond', $conds)) . ')';
}
public static function lor(array $conds) {
if (is_assoc($conds)) {
@ -196,7 +196,7 @@ class DB {
}
$conds = $new_conds;
}
return '('.implode(' or ', array_map('DB::cond', $conds)).')';
return '(' . implode(' or ', array_map('DB::cond', $conds)) . ')';
}
public static function tuple(array $vals) {
$str = '(';
@ -225,7 +225,7 @@ class DB {
}
public static function bracket($q) {
return '('.DB::query_str($q).')';
return '(' . DB::query_str($q) . ')';
}
public static function query_str($q) {
if (is_array($q)) {
@ -259,7 +259,7 @@ class DB {
}
public static function exists($q) {
return 'exists '.DB::bracket($q);
return 'exists ' . DB::bracket($q);
}
public static function query($q) {
@ -269,7 +269,7 @@ class DB {
$ret = DB::$conn->query(DB::query_str($q));
if ($ret === false) {
UOJLog::error(DB::query_str($q));
UOJLog::error('update failed: '.DB::$conn->error);
UOJLog::error('update failed: ' . DB::$conn->error);
}
return $ret;
}
@ -277,7 +277,7 @@ class DB {
$ret = DB::$conn->query(DB::query_str($q));
if ($ret === false) {
UOJLog::error(DB::query_str($q));
UOJLog::error('insert failed: '.DB::$conn->error);
UOJLog::error('insert failed: ' . DB::$conn->error);
}
return $ret;
}
@ -289,7 +289,7 @@ class DB {
$ret = DB::$conn->query(DB::query_str($q));
if ($ret === false) {
UOJLog::error(DB::query_str($q));
UOJLog::error('delete failed: '.DB::$conn->error);
UOJLog::error('delete failed: ' . DB::$conn->error);
}
return $ret;
}
@ -380,9 +380,9 @@ class DB {
public static function limit() {
$num = func_get_args();
if (count($num) == 1) {
return "limit ".((int)$num[0]);
return "limit " . ((int)$num[0]);
} elseif (count($num) == 2) {
return "limit ".((int)$num[0]).",".((int)$num[1]);
return "limit " . ((int)$num[0]) . "," . ((int)$num[1]);
} else {
return false;
}
@ -424,12 +424,12 @@ class DB {
$q = [];
foreach ($tables as $table => $type) {
if ($type != DB::WLOCK && $type != DB::RLOCK) {
UOJLog::error('Unknown type: '.$type);
UOJLog::error('Unknown type: ' . $type);
return false;
}
$q[] = $table.' '.$type;
$q[] = $table . ' ' . $type;
}
$q = 'lock tables '.implode(',', $q);
$q = 'lock tables ' . implode(',', $q);
DB::query($q);
$ret = $func();

View File

@ -191,20 +191,22 @@ class UOJContest {
ignore_user_abort(true);
set_time_limit(0);
DB::update([
"update contests",
"set", ["status" => 'testing'],
"where", ["id" => $this->info['id']]
DB::transaction(function () {
$status = DB::selectSingle([
"select status from contests",
"where", ["id" => $this->info['id']],
DB::for_update(),
]);
if (DB::affected_rows() !== 1) {
if ($status !== 'unfinished') {
// 已经有其他人开始评测了,不进行任何操作
return;
}
$res = DB::selectAll([
"select id, problem_id, content, result, submitter, hide_score_to_others from submissions",
"where", ["contest_id" => $this->info['id']]
"where", ["contest_id" => $this->info['id']],
DB::for_update(),
]);
foreach ($res as $submission) {
$content = json_decode($submission['content'], true);
@ -299,6 +301,17 @@ class UOJContest {
}
$updated[$submitter][$pid] = true;
}
DB::update([
"update contests",
"set", [
"status" => "testing",
],
"where", [
"id" => $this->info['id'],
],
]);
});
}
public function queryJudgeProgress() {

View File

@ -1,5 +1,7 @@
-- InnoDB
ALTER TABLE `best_ac_submissions` ENGINE=InnoDB TABLESPACE `innodb_system`;
ALTER TABLE `contests` ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `contests_submissions` ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `judger_info` COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `problems_contents` COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `submissions` ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;