Change SSPRISM to use the new DBCore (#21543)

Ported almost all of it from TG

Co-authored-by: Werner <Arrow768@users.noreply.github.com>
This commit is contained in:
Werner
2025-11-10 07:40:41 +00:00
committed by GitHub
co-authored by Werner
parent 2572494d6b
commit cd065ed6ba
3 changed files with 197 additions and 22 deletions
+102 -1
View File
@@ -370,7 +370,7 @@ SUBSYSTEM_DEF(dbcore)
*
*/
/datum/db_query_template/proc/Execute(arguments, allow_during_shutdown=FALSE)
var/datum/db_query/query = SSdbcore.NewQuery(sql, arguments, allow_during_shutdown)
var/datum/db_query/query = SSdbcore.NewQuery(sql, arguments, allow_during_shutdown)
return query.Execute()
/datum/db_query
@@ -548,6 +548,107 @@ SUBSYSTEM_DEF(dbcore)
while(status < DB_QUERY_FINISHED)
stoplag()
/** QuerySelect
Run a list of query datums in parallel, blocking until they all complete.
* queries - List of queries or single query datum to run.
* warn - Controls rather warn_execute() or Execute() is called.
* qdel - If you don't care about the result or checking for errors, you can have the queries be deleted afterwards.
This can be combined with invoke_async as a way of running queries async without having to care about waiting for them to finish so they can be deleted,
however you should probably just use FireAndForget instead if it's just a single query.
*/
/datum/controller/subsystem/dbcore/proc/QuerySelect(list/queries, warn = FALSE, qdel = FALSE)
if (!islist(queries))
if (!istype(queries, /datum/db_query))
CRASH("Invalid query passed to QuerySelect: [queries]")
queries = list(queries)
else
queries = queries.Copy() //we don't want to hide bugs in the parent caller by removing invalid values from this list.
for (var/datum/db_query/query as anything in queries)
if (!istype(query))
queries -= query
stack_trace("Invalid query passed to QuerySelect: `[query]` [REF(query)]")
continue
if (warn)
INVOKE_ASYNC(query, TYPE_PROC_REF(/datum/db_query, warn_execute))
else
INVOKE_ASYNC(query, TYPE_PROC_REF(/datum/db_query, Execute))
for (var/datum/db_query/query as anything in queries)
query.sync()
if (qdel)
qdel(query)
/*
Takes a list of rows (each row being an associated list of column => value) and inserts them via a single mass query.
Rows missing columns present in other rows will resolve to SQL NULL
You are expected to do your own escaping of the data, and expected to provide your own quotes for strings.
The duplicate_key arg can be true to automatically generate this part of the query
or set to a string that is appended to the end of the query
Ignore_errors instructes mysql to continue inserting rows if some of them have errors.
the erroneous row(s) aren't inserted and there isn't really any way to know why or why errored
*/
/datum/controller/subsystem/dbcore/proc/MassInsert(table, list/rows, duplicate_key = FALSE, ignore_errors = FALSE, warn = FALSE, async = TRUE, special_columns = null)
if (!table || !rows || !istype(rows))
return
// Prepare column list
var/list/columns = list()
var/list/has_question_mark = list()
for (var/list/row in rows)
for (var/column in row)
columns[column] = "?"
has_question_mark[column] = TRUE
for (var/column in special_columns)
columns[column] = special_columns[column]
has_question_mark[column] = findtext(special_columns[column], "?")
// Prepare SQL query full of placeholders
var/list/query_parts = list("INSERT")
if (ignore_errors)
query_parts += " IGNORE"
query_parts += " INTO "
query_parts += table
query_parts += "\n([columns.Join(", ")])\nVALUES"
var/list/arguments = list()
var/has_row = FALSE
for (var/list/row in rows)
if (has_row)
query_parts += ","
query_parts += "\n ("
var/has_col = FALSE
for (var/column in columns)
if (has_col)
query_parts += ", "
if (has_question_mark[column])
var/name = "p[arguments.len]"
query_parts += replacetext(columns[column], "?", ":[name]")
arguments[name] = row[column]
else
query_parts += columns[column]
has_col = TRUE
query_parts += ")"
has_row = TRUE
if (duplicate_key == TRUE)
var/list/column_list = list()
for (var/column in columns)
column_list += "[column] = VALUES([column])"
query_parts += "\nON DUPLICATE KEY UPDATE [column_list.Join(", ")]"
else if (duplicate_key != FALSE)
query_parts += duplicate_key
var/datum/db_query/Query = NewQuery(query_parts.Join(), arguments)
if (warn)
. = Query.warn_execute(async)
else
. = Query.Execute(async)
qdel(Query)
/**
* process
*
+37 -21
View File
@@ -53,12 +53,18 @@ SUBSYSTEM_DEF(stickyban)
/datum/controller/subsystem/stickyban/proc/Populatedbcache()
var/newdbcache = list() //so if we runtime or the db connection dies we don't kill the existing cache
var/DBQuery/query_stickybans = GLOB.dbcon.NewQuery("SELECT ckey, reason, banning_admin, datetime FROM ss13_stickyban ORDER BY ckey")
var/DBQuery/query_ckey_matches = GLOB.dbcon.NewQuery("SELECT stickyban, matched_ckey, first_matched, last_matched, exempt FROM ss13_stickyban_matched_ckey ORDER BY first_matched")
var/DBQuery/query_cid_matches = GLOB.dbcon.NewQuery("SELECT stickyban, matched_cid, first_matched, last_matched FROM ss13_stickyban_matched_cid ORDER BY first_matched")
var/DBQuery/query_ip_matches = GLOB.dbcon.NewQuery("SELECT stickyban, INET_NTOA(matched_ip), first_matched, last_matched FROM ss13_stickyban_matched_ip ORDER BY first_matched")
var/datum/db_query/query_stickybans = SSdbcore.NewQuery("SELECT ckey, reason, banning_admin, datetime FROM ss13_stickyban ORDER BY ckey")
var/datum/db_query/query_ckey_matches = SSdbcore.NewQuery("SELECT stickyban, matched_ckey, first_matched, last_matched, exempt FROM ss13_stickyban_matched_ckey ORDER BY first_matched")
var/datum/db_query/query_cid_matches = SSdbcore.NewQuery("SELECT stickyban, matched_cid, first_matched, last_matched FROM ss13_stickyban_matched_cid ORDER BY first_matched")
var/datum/db_query/query_ip_matches = SSdbcore.NewQuery("SELECT stickyban, INET_NTOA(matched_ip), first_matched, last_matched FROM ss13_stickyban_matched_ip ORDER BY first_matched")
if (!query_stickybans.Execute())
SSdbcore.QuerySelect(list(query_stickybans, query_ckey_matches, query_cid_matches, query_ip_matches))
if (query_stickybans.last_error)
qdel(query_stickybans)
qdel(query_ckey_matches)
qdel(query_cid_matches)
qdel(query_ip_matches)
return
while (query_stickybans.NextRow())
@@ -74,7 +80,7 @@ SUBSYSTEM_DEF(stickyban)
newdbcache["[query_stickybans.item[1]]"] = ban
if (query_ckey_matches.Execute())
if (!query_ckey_matches.last_error)
while (query_ckey_matches.NextRow())
var/list/match = list()
@@ -92,7 +98,7 @@ SUBSYSTEM_DEF(stickyban)
keys = ban[text2num(query_ckey_matches.item[5]) ? "whitelist" : "keys"] = list()
keys[query_ckey_matches.item[2]] = match
if (query_cid_matches.Execute())
if (!query_cid_matches.last_error)
while (query_cid_matches.NextRow())
var/list/match = list()
@@ -110,7 +116,7 @@ SUBSYSTEM_DEF(stickyban)
computer_ids[query_cid_matches.item[2]] = match
if (query_ip_matches.Execute())
if (!query_ip_matches.last_error)
while (query_ip_matches.NextRow())
var/list/match = list()
@@ -130,6 +136,11 @@ SUBSYSTEM_DEF(stickyban)
dbcache = newdbcache
dbcacheexpire = world.time+STICKYBAN_DB_CACHE_TIME
qdel(query_stickybans)
qdel(query_ckey_matches)
qdel(query_cid_matches)
qdel(query_ip_matches)
/datum/controller/subsystem/stickyban/proc/import_raw_stickyban_to_db(ckey, list/ban)
. = FALSE
if (!ban["admin"])
@@ -137,9 +148,14 @@ SUBSYSTEM_DEF(stickyban)
if (!ban["message"])
ban["message"] = "Evasion"
var/DBQuery/query_create_stickyban = GLOB.dbcon.NewQuery("INSERT IGNORE INTO ss13_stickyban (ckey, reason, banning_admin) VALUES ('[sanitizeSQL(ckey)]', '[sanitizeSQL(ban["message"])]', '[sanitizeSQL(ban["admin"])]')")
if (!query_create_stickyban.Execute())
var/datum/db_query/query_create_stickyban = SSdbcore.NewQuery(
"INSERT IGNORE INTO ss13_stickyban (ckey, reason, banning_admin) VALUES (:ckey, :message, :admin)",
list("ckey" = ckey, "message" = ban["message"], "admin" = ban["admin"])
)
if (!query_create_stickyban.warn_execute())
qdel(query_create_stickyban)
return
qdel(query_create_stickyban)
var/list/sqlckeys = list()
var/list/sqlcids = list()
@@ -149,8 +165,8 @@ SUBSYSTEM_DEF(stickyban)
var/list/keys = splittext(ban["keys"], ",")
for (var/key in keys)
var/list/sqlckey = list()
sqlckey["stickyban"] = "'[sanitizeSQL(ckey)]'"
sqlckey["matched_ckey"] = "'[sanitizeSQL(ckey(key))]'"
sqlckey["stickyban"] = ckey
sqlckey["matched_ckey"] = ckey(key)
sqlckey["exempt"] = FALSE
sqlckeys[++sqlckeys.len] = sqlckey
@@ -158,8 +174,8 @@ SUBSYSTEM_DEF(stickyban)
var/list/keys = splittext(ban["whitelist"], ",")
for (var/key in keys)
var/list/sqlckey = list()
sqlckey["stickyban"] = "'[sanitizeSQL(ckey)]'"
sqlckey["matched_ckey"] = "'[sanitizeSQL(ckey(key))]'"
sqlckey["stickyban"] = ckey
sqlckey["matched_ckey"] = ckey(key)
sqlckey["exempt"] = TRUE
sqlckeys[++sqlckeys.len] = sqlckey
@@ -167,26 +183,26 @@ SUBSYSTEM_DEF(stickyban)
var/list/cids = splittext(ban["computer_id"], ",")
for (var/cid in cids)
var/list/sqlcid = list()
sqlcid["stickyban"] = "'[sanitizeSQL(ckey)]'"
sqlcid["matched_cid"] = "'[sanitizeSQL(cid)]'"
sqlcid["stickyban"] = ckey
sqlcid["matched_cid"] = cid
sqlcids[++sqlcids.len] = sqlcid
if (ban["IP"])
var/list/ips = splittext(ban["IP"], ",")
for (var/ip in ips)
var/list/sqlip = list()
sqlip["stickyban"] = "'[sanitizeSQL(ckey)]'"
sqlip["matched_ip"] = "'[sanitizeSQL(ip)]'"
sqlip["stickyban"] = ckey
sqlip["matched_ip"] = ip
sqlips[++sqlips.len] = sqlip
if (length(sqlckeys))
GLOB.dbcon.MassInsert("ss13_stickyban_matched_ckey", sqlckeys, FALSE, TRUE)
SSdbcore.MassInsert("ss13_stickyban_matched_ckey", sqlckeys, ignore_errors = TRUE)
if (length(sqlcids))
GLOB.dbcon.MassInsert("ss13_stickyban_matched_cid", sqlcids, FALSE, TRUE)
SSdbcore.MassInsert("ss13_stickyban_matched_cid", sqlcids, ignore_errors = TRUE)
if (length(sqlips))
GLOB.dbcon.MassInsert("ss13_stickyban_matched_ip", sqlips, FALSE, TRUE)
SSdbcore.MassInsert("ss13_stickyban_matched_ip", sqlips, ignore_errors = TRUE)
return TRUE