Async SQL + SSdbcore (#15007)

* Initial Commit - Async SQL

* First batch of queries

* More progress

* Nukes DB Polls

* More work

* oops

* One push

* Notes work now

* Ok these work

* Watchlist done

* Async Bans!

* Async Permissions

* Async client procs

* I officially hate preference datums

* Also these

* Async Custom Items

* Async Karma

* Async Library

* Async TOS

* Cleans out the old SQL code

* CI Sanity

* Apparently MySQL doesnt support this

* What about this

* Maybe this

* Review pass 1

* This too

* Fixes job ban loading

* Fix undeleted queries

* Prevents sensitive queries being logged

* Documentation + tweaks

* Adds a verb to force reconnect the DB

* More review tweaks

* Farie tweaks

* Fixes this
This commit is contained in:
AffectedArc07
2020-12-16 20:46:25 +00:00
committed by GitHub
parent e003d552b0
commit 2bad70717c
55 changed files with 2251 additions and 2445 deletions
+80 -49
View File
@@ -1,7 +1,8 @@
/proc/add_note(target_ckey, notetext, timestamp, adminckey, logged = 1, server, checkrights = 1)
// Do not attemtp to remove the blank string from the server arg. It will break DB saving.
/proc/add_note(target_ckey, notetext, timestamp, adminckey, logged = 1, server = "", checkrights = 1)
if(checkrights && !check_rights(R_ADMIN|R_MOD))
return
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
if(usr)
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
return
@@ -14,17 +15,27 @@
else
target_ckey = ckey(target_ckey)
var/DBQuery/query_find_ckey = GLOB.dbcon.NewQuery("SELECT ckey, exp FROM [format_table_name("player")] WHERE ckey = '[target_ckey]'")
if(!query_find_ckey.Execute())
var/err = query_find_ckey.ErrorMsg()
log_game("SQL ERROR obtaining ckey from player table. Error : \[[err]\]\n")
var/datum/db_query/query_find_ckey = SSdbcore.NewQuery("SELECT ckey, exp FROM [format_table_name("player")] WHERE ckey=:ckey", list(
"ckey" = target_ckey
))
if(!query_find_ckey.warn_execute())
qdel(query_find_ckey)
return
if(!query_find_ckey.NextRow())
var/ckey_found = FALSE
var/exp_data
while(query_find_ckey.NextRow())
exp_data = query_find_ckey.item[2]
ckey_found = TRUE
qdel(query_find_ckey)
if(!ckey_found)
if(usr)
to_chat(usr, "<span class='redtext'>[target_ckey] has not been seen before, you can only add notes to known players.</span>")
return
var/exp_data = query_find_ckey.item[2]
var/crew_number = 0
if(exp_data)
var/list/play_records = params2list(exp_data)
@@ -34,25 +45,32 @@
notetext = input(usr,"Write your note","Add Note") as message|null
if(!notetext)
return
notetext = sanitizeSQL(notetext)
if(!timestamp)
timestamp = SQLtime()
if(!adminckey)
adminckey = usr.ckey
if(!adminckey)
return
else if(usr && (usr.ckey == ckey(adminckey))) // Don't ckeyize special note sources
adminckey = ckey(adminckey)
var/admin_sql_ckey = sanitizeSQL(adminckey)
if(!server)
if(config && config.server_name)
server = config.server_name
server = sanitizeSQL(server)
var/DBQuery/query_noteadd = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server, crew_playtime) VALUES ('[target_ckey]', '[timestamp]', '[notetext]', '[admin_sql_ckey]', '[server]', '[crew_number]')")
if(!query_noteadd.Execute())
var/err = query_noteadd.ErrorMsg()
log_game("SQL ERROR adding new note to table. Error : \[[err]\]\n")
var/datum/db_query/query_noteadd = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server, crew_playtime)
VALUES (:targetckey, NOW(), :notetext, :adminkey, :server, :crewnum)
"}, list(
"targetckey" = target_ckey,
"notetext" = notetext,
"adminkey" = adminckey,
"server" = server,
"crewnum" = crew_number
))
if(!query_noteadd.warn_execute())
qdel(query_noteadd)
return
qdel(query_noteadd)
if(logged)
log_admin("[usr ? key_name(usr) : adminckey] has added a note to [target_ckey]: [notetext]")
message_admins("[usr ? key_name_admin(usr) : adminckey] has added a note to [target_ckey]:<br>[notetext]")
@@ -64,27 +82,33 @@
var/ckey
var/notetext
var/adminckey
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
if(usr)
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
return
if(!note_id)
return
note_id = text2num(note_id)
var/DBQuery/query_find_note_del = GLOB.dbcon.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id = [note_id]")
if(!query_find_note_del.Execute())
var/err = query_find_note_del.ErrorMsg()
log_game("SQL ERROR obtaining ckey, notetext, adminckey from player table. Error : \[[err]\]\n")
var/datum/db_query/query_find_note_del = SSdbcore.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id=:note_id", list(
"note_id" = note_id
))
if(!query_find_note_del.warn_execute())
qdel(query_find_note_del)
return
if(query_find_note_del.NextRow())
ckey = query_find_note_del.item[1]
notetext = query_find_note_del.item[2]
adminckey = query_find_note_del.item[3]
var/DBQuery/query_del_note = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("notes")] WHERE id = [note_id]")
if(!query_del_note.Execute())
var/err = query_del_note.ErrorMsg()
log_game("SQL ERROR removing note from table. Error : \[[err]\]\n")
qdel(query_find_note_del)
var/datum/db_query/query_del_note = SSdbcore.NewQuery("DELETE FROM [format_table_name("notes")] WHERE id=:note_id", list(
"note_id" = note_id
))
if(!query_del_note.warn_execute())
qdel(query_del_note)
return
qdel(query_del_note)
log_admin("[usr ? key_name(usr) : "Bot"] has removed a note made by [adminckey] from [ckey]: [notetext]")
message_admins("[usr ? key_name_admin(usr) : "Bot"] has removed a note made by [adminckey] from [ckey]:<br>[notetext]")
show_note(ckey)
@@ -92,7 +116,7 @@
/proc/edit_note(note_id)
if(!check_rights(R_ADMIN|R_MOD))
return
if(!GLOB.dbcon.IsConnected())
if(!SSdbcore.IsConnected())
if(usr)
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
return
@@ -100,11 +124,11 @@
return
note_id = text2num(note_id)
var/target_ckey
var/sql_ckey = usr.ckey
var/DBQuery/query_find_note_edit = GLOB.dbcon.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id = [note_id]")
if(!query_find_note_edit.Execute())
var/err = query_find_note_edit.ErrorMsg()
log_game("SQL ERROR obtaining notetext from notes table. Error : \[[err]\]\n")
var/datum/db_query/query_find_note_edit = SSdbcore.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id=:note_id", list(
"note_id" = note_id
))
if(!query_find_note_edit.warn_execute())
qdel(query_find_note_edit)
return
if(query_find_note_edit.NextRow())
target_ckey = query_find_note_edit.item[1]
@@ -113,17 +137,20 @@
var/new_note = input("Input new note", "New Note", "[old_note]") as message|null
if(!new_note)
return
new_note = sanitizeSQL(new_note)
var/edit_text = "Edited by [sql_ckey] on [SQLtime()] from \"[old_note]\" to \"[new_note]\"<hr>"
edit_text = sanitizeSQL(edit_text)
var/DBQuery/query_update_note = GLOB.dbcon.NewQuery("UPDATE [format_table_name("notes")] SET notetext = '[new_note]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [note_id]")
if(!query_update_note.Execute())
var/err = query_update_note.ErrorMsg()
log_game("SQL ERROR editing note. Error : \[[err]\]\n")
var/edit_text = "Edited by [usr.ckey] on [SQLtime()] from \"[old_note]\" to \"[new_note]\"<hr>"
var/datum/db_query/query_update_note = SSdbcore.NewQuery("UPDATE [format_table_name("notes")] SET notetext=:new_note, last_editor=:akey, edits = CONCAT(IFNULL(edits,''),:edit_text) WHERE id=:note_id", list(
"new_note" = new_note,
"akey" = usr.ckey,
"edit_text" = edit_text,
"note_id" = note_id
))
if(!query_update_note.warn_execute())
qdel(query_update_note)
return
log_admin("[usr ? key_name(usr) : "Bot"] has edited [target_ckey]'s note made by [adminckey] from \"[old_note]\" to \"[new_note]\"")
message_admins("[usr ? key_name_admin(usr) : "Bot"] has edited [target_ckey]'s note made by [adminckey] from \"[old_note]\" to \"[new_note]\"")
show_note(target_ckey)
qdel(query_update_note)
/proc/show_note(target_ckey, index, linkless = 0)
if(!check_rights(R_ADMIN|R_MOD))
@@ -143,10 +170,13 @@
output = navbar
if(target_ckey)
var/target_sql_ckey = ckey(target_ckey)
var/DBQuery/query_get_notes = GLOB.dbcon.NewQuery("SELECT id, timestamp, notetext, adminckey, last_editor, server, crew_playtime FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp")
if(!query_get_notes.Execute())
var/err = query_get_notes.ErrorMsg()
log_game("SQL ERROR obtaining ckey, notetext, adminckey, last_editor, server, crew_playtime from notes table. Error : \[[err]\]\n")
var/datum/db_query/query_get_notes = SSdbcore.NewQuery({"
SELECT id, timestamp, notetext, adminckey, last_editor, server, crew_playtime
FROM [format_table_name("notes")] WHERE ckey=:targetkey ORDER BY timestamp"}, list(
"targetkey" = target_sql_ckey
))
if(!query_get_notes.warn_execute())
qdel(query_get_notes)
return
output += "<h2><center>Notes of [target_ckey]</center></h2>"
if(!linkless)
@@ -171,13 +201,12 @@
if(last_editor)
output += " <font size='2'>Last edit by [last_editor] <a href='?_src_=holder;noteedits=[id]'>(Click here to see edit log)</a></font>"
output += "<br>[notetext]<hr style='background:#000000; border:0; height:1px'>"
qdel(query_get_notes)
else if(index)
var/index_ckey
var/search
output += "<center><a href='?_src_=holder;addnoteempty=1'>\[Add Note\]</a></center>"
output += ruler
if(!isnum(index))
index = sanitizeSQL(index)
switch(index)
if(1)
search = "^."
@@ -185,10 +214,11 @@
search = "^\[^\[:alpha:\]\]"
else
search = "^[index]"
var/DBQuery/query_list_notes = GLOB.dbcon.NewQuery("SELECT DISTINCT ckey FROM [format_table_name("notes")] WHERE ckey REGEXP '[search]' ORDER BY ckey")
if(!query_list_notes.Execute())
var/err = query_list_notes.ErrorMsg()
log_game("SQL ERROR obtaining ckey from notes table. Error : \[[err]\]\n")
var/datum/db_query/query_list_notes = SSdbcore.NewQuery("SELECT DISTINCT ckey FROM [format_table_name("notes")] WHERE ckey REGEXP :search ORDER BY ckey", list(
"search" = search
))
if(!query_list_notes.warn_execute())
qdel(query_list_notes)
return
to_chat(usr, "<span class='notice'>Started regex note search for [search]. Please wait for results...</span>")
message_admins("[usr.ckey] has started a note search with the following regex: [search] | CPU usage may be higher.")
@@ -196,6 +226,7 @@
index_ckey = query_list_notes.item[1]
output += "<a href='?_src_=holder;shownoteckey=[index_ckey]'>[index_ckey]</a><br>"
CHECK_TICK
qdel(query_list_notes)
message_admins("The note search started by [usr.ckey] has complete. CPU should return to normal.")
else
output += "<center><a href='?_src_=holder;addnoteempty=1'>\[Add Note\]</a></center>"