mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-09-08 00:35:17 +00:00
refactor(contest): finalTest database transaction
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
c2fdca91cd
commit
d7741c2910
@ -185,7 +185,7 @@ CREATE TABLE `contests` (
|
|||||||
`zan` int NOT NULL DEFAULT '0',
|
`zan` int NOT NULL DEFAULT '0',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `status` (`status`,`id`) USING BTREE
|
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 */;
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -337,7 +337,7 @@ CREATE TABLE `contests_submissions` (
|
|||||||
`cnt` int DEFAULT NULL,
|
`cnt` int DEFAULT NULL,
|
||||||
`n_failures` int DEFAULT NULL,
|
`n_failures` int DEFAULT NULL,
|
||||||
PRIMARY KEY (`contest_id`,`submitter`,`problem_id`)
|
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 */;
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
--
|
--
|
||||||
|
@ -4,14 +4,14 @@ class DB {
|
|||||||
public static mysqli $conn;
|
public static mysqli $conn;
|
||||||
public static array $cache = [];
|
public static array $cache = [];
|
||||||
public static bool $in_transaction = false;
|
public static bool $in_transaction = false;
|
||||||
|
|
||||||
const WLOCK = "WRITE";
|
const WLOCK = "WRITE";
|
||||||
const RLOCK = "READ";
|
const RLOCK = "READ";
|
||||||
|
|
||||||
const ASSOC = MYSQLI_ASSOC;
|
const ASSOC = MYSQLI_ASSOC;
|
||||||
const NUM = MYSQLI_NUM;
|
const NUM = MYSQLI_NUM;
|
||||||
const BOTH = MYSQLI_BOTH;
|
const BOTH = MYSQLI_BOTH;
|
||||||
|
|
||||||
public static function init() {
|
public static function init() {
|
||||||
$server = UOJConfig::$data['database']['host'];
|
$server = UOJConfig::$data['database']['host'];
|
||||||
$username = UOJConfig::$data['database']['username'];
|
$username = UOJConfig::$data['database']['username'];
|
||||||
@ -19,7 +19,7 @@ class DB {
|
|||||||
$dbname = UOJConfig::$data['database']['database'];
|
$dbname = UOJConfig::$data['database']['database'];
|
||||||
DB::$conn = new mysqli($server, $username, $password, $dbname);
|
DB::$conn = new mysqli($server, $username, $password, $dbname);
|
||||||
if (DB::$conn->connect_error) {
|
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');
|
die('There is something wrong with the database >_<... Connection failed');
|
||||||
}
|
}
|
||||||
if (!DB::$conn->set_charset("utf8mb4")) {
|
if (!DB::$conn->set_charset("utf8mb4")) {
|
||||||
@ -27,113 +27,113 @@ class DB {
|
|||||||
die('There is something wrong with the database >_<.... Charset utf8 not supported');
|
die('There is something wrong with the database >_<.... Charset utf8 not supported');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// lc: local cache
|
// lc: local cache
|
||||||
public static function lc() {
|
public static function lc() {
|
||||||
return new DBUseLocalCache('');
|
return new DBUseLocalCache('');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function escape($str) {
|
public static function escape($str) {
|
||||||
return DB::$conn->real_escape_string($str);
|
return DB::$conn->real_escape_string($str);
|
||||||
}
|
}
|
||||||
public static function raw($str) {
|
public static function raw($str) {
|
||||||
return new DBRawString($str);
|
return new DBRawString($str);
|
||||||
}
|
}
|
||||||
public static function rawbracket($q) {
|
public static function rawbracket($q) {
|
||||||
return DB::raw(DB::bracket($q));
|
return DB::raw(DB::bracket($q));
|
||||||
}
|
}
|
||||||
public static function rawvalue($str) {
|
public static function rawvalue($str) {
|
||||||
return DB::raw(DB::value($str));
|
return DB::raw(DB::value($str));
|
||||||
}
|
}
|
||||||
public static function rawtuple(array $vals) {
|
public static function rawtuple(array $vals) {
|
||||||
return DB::raw(DB::tuple($vals));
|
return DB::raw(DB::tuple($vals));
|
||||||
}
|
}
|
||||||
public static function call($fun, ...$args) {
|
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() {
|
public static function now() {
|
||||||
return DB::call('now');
|
return DB::call('now');
|
||||||
}
|
}
|
||||||
public static function instr($str, $substr) {
|
public static function instr($str, $substr) {
|
||||||
return DB::call('instr', $str, $substr);
|
return DB::call('instr', $str, $substr);
|
||||||
}
|
}
|
||||||
public static function cast_as_json($value) {
|
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) {
|
public static function json_set($json_doc, ...$args) {
|
||||||
return DB::call('json_set', DB::raw($json_doc), ...$args);
|
return DB::call('json_set', DB::raw($json_doc), ...$args);
|
||||||
}
|
}
|
||||||
public static function json_insert($json_doc, ...$args) {
|
public static function json_insert($json_doc, ...$args) {
|
||||||
return DB::call('json_insert', DB::raw($json_doc), ...$args);
|
return DB::call('json_insert', DB::raw($json_doc), ...$args);
|
||||||
}
|
}
|
||||||
public static function json_replace($json_doc, ...$args) {
|
public static function json_replace($json_doc, ...$args) {
|
||||||
return DB::call('json_replace', DB::raw($json_doc), ...$args);
|
return DB::call('json_replace', DB::raw($json_doc), ...$args);
|
||||||
}
|
}
|
||||||
public static function json_remove($json_doc, ...$args) {
|
public static function json_remove($json_doc, ...$args) {
|
||||||
return DB::call('json_remove', DB::raw($json_doc), ...$args);
|
return DB::call('json_remove', DB::raw($json_doc), ...$args);
|
||||||
}
|
}
|
||||||
public static function json_array_append($json_doc, ...$args) {
|
public static function json_array_append($json_doc, ...$args) {
|
||||||
return DB::call('json_array_append', DB::raw($json_doc), ...$args);
|
return DB::call('json_array_append', DB::raw($json_doc), ...$args);
|
||||||
}
|
}
|
||||||
public static function json_array_insert($json_doc, ...$args) {
|
public static function json_array_insert($json_doc, ...$args) {
|
||||||
return DB::call('json_array_insert', DB::raw($json_doc), ...$args);
|
return DB::call('json_array_insert', DB::raw($json_doc), ...$args);
|
||||||
}
|
}
|
||||||
public static function json_unquote($json_doc) {
|
public static function json_unquote($json_doc) {
|
||||||
return DB::call('json_unquote', DB::raw($json_doc));
|
return DB::call('json_unquote', DB::raw($json_doc));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function table($table) {
|
public static function table($table) {
|
||||||
//return '`'.str_replace('`', '``', $table).'`';
|
//return '`'.str_replace('`', '``', $table).'`';
|
||||||
return $table;
|
return $table;
|
||||||
}
|
}
|
||||||
public static function fields($fields) {
|
public static function fields($fields) {
|
||||||
if (is_assoc($fields)) {
|
if (is_assoc($fields)) {
|
||||||
$new_fields = [];
|
$new_fields = [];
|
||||||
foreach ($fields as $name => $val) {
|
foreach ($fields as $name => $val) {
|
||||||
if (is_int($name)) {
|
if (is_int($name)) {
|
||||||
$new_fields[] = $val;
|
$new_fields[] = $val;
|
||||||
} else {
|
} else {
|
||||||
$new_fields[] = DB::field_as($val, $name);
|
$new_fields[] = DB::field_as($val, $name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$fields = $new_fields;
|
$fields = $new_fields;
|
||||||
}
|
}
|
||||||
return implode(',', $fields);
|
return implode(',', $fields);
|
||||||
}
|
}
|
||||||
public static function bracketed_fields($fields) {
|
public static function bracketed_fields($fields) {
|
||||||
return '('.DB::fields($fields).')';
|
return '(' . DB::fields($fields) . ')';
|
||||||
}
|
}
|
||||||
public static function value($str) {
|
public static function value($str) {
|
||||||
if ($str === null) {
|
if ($str === null) {
|
||||||
return 'NULL';
|
return 'NULL';
|
||||||
} elseif ($str === true) {
|
} elseif ($str === true) {
|
||||||
return 'true';
|
return 'true';
|
||||||
} elseif ($str === false) {
|
} elseif ($str === false) {
|
||||||
return 'false';
|
return 'false';
|
||||||
} elseif (is_int($str)|| is_float($str)) {
|
} elseif (is_int($str) || is_float($str)) {
|
||||||
return $str;
|
return $str;
|
||||||
} elseif (is_string($str)) {
|
} elseif (is_string($str)) {
|
||||||
return '\''.DB::escape($str).'\'';
|
return '\'' . DB::escape($str) . '\'';
|
||||||
} elseif ($str instanceof DBRawString) {
|
} elseif ($str instanceof DBRawString) {
|
||||||
return $str->str;
|
return $str->str;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static function field_as($field, $name) {
|
public static function field_as($field, $name) {
|
||||||
return "{$field} as {$name}";
|
return "{$field} as {$name}";
|
||||||
}
|
}
|
||||||
public static function value_as($value, $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) {
|
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) {
|
public static function setValue($field, $val) {
|
||||||
return $field.' = '.DB::value($val);
|
return $field . ' = ' . DB::value($val);
|
||||||
}
|
}
|
||||||
public static function setValues(array $arr) {
|
public static function setValues(array $arr) {
|
||||||
$all = [];
|
$all = [];
|
||||||
foreach ($arr as $key => $val) {
|
foreach ($arr as $key => $val) {
|
||||||
@ -152,16 +152,16 @@ class DB {
|
|||||||
$lhs = $cond[0] instanceof DBRawString ? $cond[0]->str : $cond[0];
|
$lhs = $cond[0] instanceof DBRawString ? $cond[0]->str : $cond[0];
|
||||||
$op = $cond[1];
|
$op = $cond[1];
|
||||||
$rhs = DB::value($cond[2]);
|
$rhs = DB::value($cond[2]);
|
||||||
return $lhs.' '.$op.' '.$rhs;
|
return $lhs . ' ' . $op . ' ' . $rhs;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $cond;
|
return $cond;
|
||||||
}
|
}
|
||||||
public static function conds($conds) {
|
public static function conds($conds) {
|
||||||
return is_array($conds) ? DB::land($conds) : $conds;
|
return is_array($conds) ? DB::land($conds) : $conds;
|
||||||
}
|
}
|
||||||
public static function land(array $conds) {
|
public static function land(array $conds) {
|
||||||
if (is_assoc($conds)) {
|
if (is_assoc($conds)) {
|
||||||
$new_conds = [];
|
$new_conds = [];
|
||||||
@ -178,7 +178,7 @@ class DB {
|
|||||||
}
|
}
|
||||||
$conds = $new_conds;
|
$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) {
|
public static function lor(array $conds) {
|
||||||
if (is_assoc($conds)) {
|
if (is_assoc($conds)) {
|
||||||
@ -196,7 +196,7 @@ class DB {
|
|||||||
}
|
}
|
||||||
$conds = $new_conds;
|
$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) {
|
public static function tuple(array $vals) {
|
||||||
$str = '(';
|
$str = '(';
|
||||||
@ -212,20 +212,20 @@ class DB {
|
|||||||
$str .= ')';
|
$str .= ')';
|
||||||
return $str;
|
return $str;
|
||||||
}
|
}
|
||||||
public static function tuples(array $tuples) {
|
public static function tuples(array $tuples) {
|
||||||
$all = [];
|
$all = [];
|
||||||
foreach ($tuples as $vals) {
|
foreach ($tuples as $vals) {
|
||||||
$all[] = DB::tuple($vals);
|
$all[] = DB::tuple($vals);
|
||||||
}
|
}
|
||||||
return implode(', ', $all);
|
return implode(', ', $all);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function fetch($res, $opt = DB::ASSOC) {
|
public static function fetch($res, $opt = DB::ASSOC) {
|
||||||
return $res->fetch_array($opt);
|
return $res->fetch_array($opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function bracket($q) {
|
public static function bracket($q) {
|
||||||
return '('.DB::query_str($q).')';
|
return '(' . DB::query_str($q) . ')';
|
||||||
}
|
}
|
||||||
public static function query_str($q) {
|
public static function query_str($q) {
|
||||||
if (is_array($q)) {
|
if (is_array($q)) {
|
||||||
@ -257,11 +257,11 @@ class DB {
|
|||||||
}
|
}
|
||||||
return $q;
|
return $q;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function exists($q) {
|
public static function exists($q) {
|
||||||
return 'exists '.DB::bracket($q);
|
return 'exists ' . DB::bracket($q);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function query($q) {
|
public static function query($q) {
|
||||||
return DB::$conn->query(DB::query_str($q));
|
return DB::$conn->query(DB::query_str($q));
|
||||||
}
|
}
|
||||||
@ -269,7 +269,7 @@ class DB {
|
|||||||
$ret = DB::$conn->query(DB::query_str($q));
|
$ret = DB::$conn->query(DB::query_str($q));
|
||||||
if ($ret === false) {
|
if ($ret === false) {
|
||||||
UOJLog::error(DB::query_str($q));
|
UOJLog::error(DB::query_str($q));
|
||||||
UOJLog::error('update failed: '.DB::$conn->error);
|
UOJLog::error('update failed: ' . DB::$conn->error);
|
||||||
}
|
}
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
@ -277,19 +277,19 @@ class DB {
|
|||||||
$ret = DB::$conn->query(DB::query_str($q));
|
$ret = DB::$conn->query(DB::query_str($q));
|
||||||
if ($ret === false) {
|
if ($ret === false) {
|
||||||
UOJLog::error(DB::query_str($q));
|
UOJLog::error(DB::query_str($q));
|
||||||
UOJLog::error('insert failed: '.DB::$conn->error);
|
UOJLog::error('insert failed: ' . DB::$conn->error);
|
||||||
}
|
}
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
public static function insert_id() {
|
public static function insert_id() {
|
||||||
return DB::$conn->insert_id;
|
return DB::$conn->insert_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function delete($q) {
|
public static function delete($q) {
|
||||||
$ret = DB::$conn->query(DB::query_str($q));
|
$ret = DB::$conn->query(DB::query_str($q));
|
||||||
if ($ret === false) {
|
if ($ret === false) {
|
||||||
UOJLog::error(DB::query_str($q));
|
UOJLog::error(DB::query_str($q));
|
||||||
UOJLog::error('delete failed: '.DB::$conn->error);
|
UOJLog::error('delete failed: ' . DB::$conn->error);
|
||||||
}
|
}
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
@ -323,7 +323,7 @@ class DB {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// return $qres->fetch_all($opt); not supported
|
// return $qres->fetch_all($opt); not supported
|
||||||
|
|
||||||
$res = [];
|
$res = [];
|
||||||
while ($row = $qres->fetch_array($opt)) {
|
while ($row = $qres->fetch_array($opt)) {
|
||||||
$res[] = $row;
|
$res[] = $row;
|
||||||
@ -337,21 +337,21 @@ class DB {
|
|||||||
}
|
}
|
||||||
return $res->fetch_array($opt);
|
return $res->fetch_array($opt);
|
||||||
}
|
}
|
||||||
public static function selectSingle($q) {
|
public static function selectSingle($q) {
|
||||||
$res = DB::select($q);
|
$res = DB::select($q);
|
||||||
if ($res === false) {
|
if ($res === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$row = $res->fetch_row();
|
$row = $res->fetch_row();
|
||||||
if (!$row) {
|
if (!$row) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return $row[0];
|
return $row[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* perform SQL query $q in the form of select count(*) from XXX where XXX;
|
* perform SQL query $q in the form of select count(*) from XXX where XXX;
|
||||||
*/
|
*/
|
||||||
public static function selectCount($q) {
|
public static function selectCount($q) {
|
||||||
$res = DB::select($q);
|
$res = DB::select($q);
|
||||||
if ($res === false) {
|
if ($res === false) {
|
||||||
@ -361,87 +361,87 @@ class DB {
|
|||||||
return $cnt;
|
return $cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* perform SQL query: select exists ($q);
|
* perform SQL query: select exists ($q);
|
||||||
*
|
*
|
||||||
* on success, returns 0 or 1
|
* on success, returns 0 or 1
|
||||||
* on failure, returns false
|
* on failure, returns false
|
||||||
*
|
*
|
||||||
* @return int|false
|
* @return int|false
|
||||||
*/
|
*/
|
||||||
public static function selectExists($q) {
|
public static function selectExists($q) {
|
||||||
$res = DB::select(["select", DB::exists($q)]);
|
$res = DB::select(["select", DB::exists($q)]);
|
||||||
if ($res === false) {
|
if ($res === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (int)($res->fetch_row()[0]);
|
return (int)($res->fetch_row()[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function limit() {
|
|
||||||
$num = func_get_args();
|
|
||||||
if (count($num) == 1) {
|
|
||||||
return "limit ".((int)$num[0]);
|
|
||||||
} elseif (count($num) == 2) {
|
|
||||||
return "limit ".((int)$num[0]).",".((int)$num[1]);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function for_share() {
|
public static function limit() {
|
||||||
return "for share";
|
$num = func_get_args();
|
||||||
}
|
if (count($num) == 1) {
|
||||||
public static function for_update() {
|
return "limit " . ((int)$num[0]);
|
||||||
return "for update";
|
} elseif (count($num) == 2) {
|
||||||
}
|
return "limit " . ((int)$num[0]) . "," . ((int)$num[1]);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static function startTransaction() {
|
public static function for_share() {
|
||||||
return DB::$conn->begin_transaction();
|
return "for share";
|
||||||
}
|
}
|
||||||
|
public static function for_update() {
|
||||||
|
return "for update";
|
||||||
|
}
|
||||||
|
|
||||||
public static function rollback() {
|
public static function startTransaction() {
|
||||||
return DB::$conn->rollback();
|
return DB::$conn->begin_transaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function commit() {
|
public static function rollback() {
|
||||||
return DB::$conn->commit();
|
return DB::$conn->rollback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function commit() {
|
||||||
|
return DB::$conn->commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function transaction($func) {
|
||||||
|
if (DB::$in_transaction) {
|
||||||
|
$ret = $func();
|
||||||
|
} else {
|
||||||
|
DB::$in_transaction = true;
|
||||||
|
DB::startTransaction();
|
||||||
|
$ret = $func();
|
||||||
|
DB::commit();
|
||||||
|
DB::$in_transaction = false;
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
public static function transaction($func) {
|
|
||||||
if (DB::$in_transaction) {
|
|
||||||
$ret = $func();
|
|
||||||
} else {
|
|
||||||
DB::$in_transaction = true;
|
|
||||||
DB::startTransaction();
|
|
||||||
$ret = $func();
|
|
||||||
DB::commit();
|
|
||||||
DB::$in_transaction = false;
|
|
||||||
}
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function lock($tables, $func) {
|
public static function lock($tables, $func) {
|
||||||
$q = [];
|
$q = [];
|
||||||
foreach ($tables as $table => $type) {
|
foreach ($tables as $table => $type) {
|
||||||
if ($type != DB::WLOCK && $type != DB::RLOCK) {
|
if ($type != DB::WLOCK && $type != DB::RLOCK) {
|
||||||
UOJLog::error('Unknown type: '.$type);
|
UOJLog::error('Unknown type: ' . $type);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$q[] = $table.' '.$type;
|
$q[] = $table . ' ' . $type;
|
||||||
}
|
}
|
||||||
$q = 'lock tables '.implode(',', $q);
|
$q = 'lock tables ' . implode(',', $q);
|
||||||
DB::query($q);
|
DB::query($q);
|
||||||
|
|
||||||
$ret = $func();
|
$ret = $func();
|
||||||
|
|
||||||
DB::query("unlock tables");
|
DB::query("unlock tables");
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
public static function checkTableExists($name) {
|
public static function checkTableExists($name) {
|
||||||
return DB::select(["select 1 from", DB::table($name)]) !== false;
|
return DB::select(["select 1 from", DB::table($name)]) !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function num_rows($res) {
|
public static function num_rows($res) {
|
||||||
return $res->num_rows;
|
return $res->num_rows;
|
||||||
}
|
}
|
||||||
|
@ -191,114 +191,127 @@ class UOJContest {
|
|||||||
ignore_user_abort(true);
|
ignore_user_abort(true);
|
||||||
set_time_limit(0);
|
set_time_limit(0);
|
||||||
|
|
||||||
DB::update([
|
DB::transaction(function () {
|
||||||
"update contests",
|
$status = DB::selectSingle([
|
||||||
"set", ["status" => 'testing'],
|
"select status from contests",
|
||||||
"where", ["id" => $this->info['id']]
|
"where", ["id" => $this->info['id']],
|
||||||
]);
|
DB::for_update(),
|
||||||
|
|
||||||
if (DB::affected_rows() !== 1) {
|
|
||||||
// 已经有其他人开始评测了,不进行任何操作
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$res = DB::selectAll([
|
|
||||||
"select id, problem_id, content, result, submitter, hide_score_to_others from submissions",
|
|
||||||
"where", ["contest_id" => $this->info['id']]
|
|
||||||
]);
|
|
||||||
foreach ($res as $submission) {
|
|
||||||
$content = json_decode($submission['content'], true);
|
|
||||||
|
|
||||||
if (isset($content['final_test_config'])) {
|
|
||||||
$content['config'] = $content['final_test_config'];
|
|
||||||
unset($content['final_test_config']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($content['first_test_config'])) {
|
|
||||||
unset($content['first_test_config']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$q = [
|
|
||||||
'content' => json_encode($content),
|
|
||||||
];
|
|
||||||
|
|
||||||
$problem_judge_type = $this->info['extra_config']["problem_{$submission['problem_id']}"] ?: $this->defaultProblemJudgeType();
|
|
||||||
$result = json_decode($submission['result'], true);
|
|
||||||
|
|
||||||
switch ($problem_judge_type) {
|
|
||||||
case 'sample':
|
|
||||||
if (isset($result['final_result']) && $result['final_result']['status'] == 'Judged') {
|
|
||||||
$q += [
|
|
||||||
'result' => json_encode($result['final_result']),
|
|
||||||
'score' => $result['final_result']['score'],
|
|
||||||
'used_time' => $result['final_result']['time'],
|
|
||||||
'used_memory' => $result['final_result']['memory'],
|
|
||||||
'judge_time' => $this->info['end_time_str'],
|
|
||||||
'status' => 'Judged',
|
|
||||||
];
|
|
||||||
|
|
||||||
if ($submission['hide_score_to_others']) {
|
|
||||||
$q['hidden_score'] = $q['score'];
|
|
||||||
$q['score'] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'no-details':
|
|
||||||
case 'full':
|
|
||||||
if ($result['status'] == 'Judged' && !isset($result['final_result'])) {
|
|
||||||
$q += [
|
|
||||||
'result' => $submission['result'],
|
|
||||||
'score' => $result['score'],
|
|
||||||
'used_time' => $result['time'],
|
|
||||||
'used_memory' => $result['memory'],
|
|
||||||
'judge_time' => $this->info['end_time_str'],
|
|
||||||
'status' => 'Judged',
|
|
||||||
];
|
|
||||||
|
|
||||||
if ($submission['hide_score_to_others']) {
|
|
||||||
$q['hidden_score'] = $q['score'];
|
|
||||||
$q['score'] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
UOJSubmission::rejudgeById($submission['id'], [
|
|
||||||
'reason_text' => HTML::stripTags($this->info['name']) . ' 最终测试',
|
|
||||||
'reason_url' => HTML::url(UOJContest::cur()->getUri()),
|
|
||||||
'set_q' => $q,
|
|
||||||
]);
|
]);
|
||||||
}
|
|
||||||
|
|
||||||
// warning: check if this command works well when the database is not MySQL
|
if ($status !== 'unfinished') {
|
||||||
DB::update([
|
// 已经有其他人开始评测了,不进行任何操作
|
||||||
"update submissions",
|
return;
|
||||||
"set", [
|
}
|
||||||
"score = hidden_score",
|
|
||||||
"hidden_score = NULL",
|
|
||||||
"hide_score_to_others = 0"
|
|
||||||
], "where", [
|
|
||||||
"contest_id" => $this->info['id'],
|
|
||||||
"hide_score_to_others" => 1
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
$updated = [];
|
$res = DB::selectAll([
|
||||||
foreach ($res as $submission) {
|
"select id, problem_id, content, result, submitter, hide_score_to_others from submissions",
|
||||||
$submitter = $submission['submitter'];
|
"where", ["contest_id" => $this->info['id']],
|
||||||
$pid = $submission['problem_id'];
|
DB::for_update(),
|
||||||
if (isset($updated[$submitter]) && isset($updated[$submitter][$pid])) {
|
]);
|
||||||
continue;
|
foreach ($res as $submission) {
|
||||||
|
$content = json_decode($submission['content'], true);
|
||||||
|
|
||||||
|
if (isset($content['final_test_config'])) {
|
||||||
|
$content['config'] = $content['final_test_config'];
|
||||||
|
unset($content['final_test_config']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($content['first_test_config'])) {
|
||||||
|
unset($content['first_test_config']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$q = [
|
||||||
|
'content' => json_encode($content),
|
||||||
|
];
|
||||||
|
|
||||||
|
$problem_judge_type = $this->info['extra_config']["problem_{$submission['problem_id']}"] ?: $this->defaultProblemJudgeType();
|
||||||
|
$result = json_decode($submission['result'], true);
|
||||||
|
|
||||||
|
switch ($problem_judge_type) {
|
||||||
|
case 'sample':
|
||||||
|
if (isset($result['final_result']) && $result['final_result']['status'] == 'Judged') {
|
||||||
|
$q += [
|
||||||
|
'result' => json_encode($result['final_result']),
|
||||||
|
'score' => $result['final_result']['score'],
|
||||||
|
'used_time' => $result['final_result']['time'],
|
||||||
|
'used_memory' => $result['final_result']['memory'],
|
||||||
|
'judge_time' => $this->info['end_time_str'],
|
||||||
|
'status' => 'Judged',
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($submission['hide_score_to_others']) {
|
||||||
|
$q['hidden_score'] = $q['score'];
|
||||||
|
$q['score'] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'no-details':
|
||||||
|
case 'full':
|
||||||
|
if ($result['status'] == 'Judged' && !isset($result['final_result'])) {
|
||||||
|
$q += [
|
||||||
|
'result' => $submission['result'],
|
||||||
|
'score' => $result['score'],
|
||||||
|
'used_time' => $result['time'],
|
||||||
|
'used_memory' => $result['memory'],
|
||||||
|
'judge_time' => $this->info['end_time_str'],
|
||||||
|
'status' => 'Judged',
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($submission['hide_score_to_others']) {
|
||||||
|
$q['hidden_score'] = $q['score'];
|
||||||
|
$q['score'] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
UOJSubmission::rejudgeById($submission['id'], [
|
||||||
|
'reason_text' => HTML::stripTags($this->info['name']) . ' 最终测试',
|
||||||
|
'reason_url' => HTML::url(UOJContest::cur()->getUri()),
|
||||||
|
'set_q' => $q,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
updateBestACSubmissions($submitter, $pid);
|
|
||||||
if (!isset($updated[$submitter])) {
|
// warning: check if this command works well when the database is not MySQL
|
||||||
$updated[$submitter] = [];
|
DB::update([
|
||||||
|
"update submissions",
|
||||||
|
"set", [
|
||||||
|
"score = hidden_score",
|
||||||
|
"hidden_score = NULL",
|
||||||
|
"hide_score_to_others = 0"
|
||||||
|
], "where", [
|
||||||
|
"contest_id" => $this->info['id'],
|
||||||
|
"hide_score_to_others" => 1
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
$updated = [];
|
||||||
|
foreach ($res as $submission) {
|
||||||
|
$submitter = $submission['submitter'];
|
||||||
|
$pid = $submission['problem_id'];
|
||||||
|
if (isset($updated[$submitter]) && isset($updated[$submitter][$pid])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
updateBestACSubmissions($submitter, $pid);
|
||||||
|
if (!isset($updated[$submitter])) {
|
||||||
|
$updated[$submitter] = [];
|
||||||
|
}
|
||||||
|
$updated[$submitter][$pid] = true;
|
||||||
}
|
}
|
||||||
$updated[$submitter][$pid] = true;
|
|
||||||
}
|
DB::update([
|
||||||
|
"update contests",
|
||||||
|
"set", [
|
||||||
|
"status" => "testing",
|
||||||
|
],
|
||||||
|
"where", [
|
||||||
|
"id" => $this->info['id'],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function queryJudgeProgress() {
|
public function queryJudgeProgress() {
|
||||||
|
@ -359,7 +359,7 @@ class UOJSubmission {
|
|||||||
])
|
])
|
||||||
])
|
])
|
||||||
], DB::for_update()
|
], DB::for_update()
|
||||||
]);
|
]);
|
||||||
DB::update(["update submissions", "set", $cfg['set_q'], "where", [$cond]]);
|
DB::update(["update submissions", "set", $cfg['set_q'], "where", [$cond]]);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
-- InnoDB
|
-- InnoDB
|
||||||
ALTER TABLE `best_ac_submissions` ENGINE=InnoDB TABLESPACE `innodb_system`;
|
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 `judger_info` COLLATE=utf8mb4_unicode_ci;
|
||||||
ALTER TABLE `problems_contents` COLLATE=utf8mb4_unicode_ci;
|
ALTER TABLE `problems_contents` COLLATE=utf8mb4_unicode_ci;
|
||||||
ALTER TABLE `submissions` ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
ALTER TABLE `submissions` ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
Loading…
Reference in New Issue
Block a user