diff --git a/code/modules/admin/chat_commands.dm b/code/modules/admin/chat_commands.dm
index 650bcd475d..9a54d094e5 100644
--- a/code/modules/admin/chat_commands.dm
+++ b/code/modules/admin/chat_commands.dm
@@ -82,6 +82,22 @@ GLOBAL_LIST(round_end_notifiees)
GLOB.round_end_notifiees[sender] = TRUE
return "I will notify [sender] when the round ends."
+/datum/server_tools_command/sdql
+ name = "sdql"
+ help_text = "Runs an SDQL query"
+ admin_only = TRUE
+
+/datum/server_tools_command/sdql/Run(sender, params)
+ if(GLOB.AdminProcCaller)
+ return "Unable to run query, another admin proc call is in progress. Try again later."
+ GLOB.AdminProcCaller = "CHAT_[sender]" //_ won't show up in ckeys so it'll never match with a real admin
+ var/list/results = world.SDQL2_query(params, GLOB.AdminProcCaller, GLOB.AdminProcCaller)
+ if(!results)
+ return "Query produced no output"
+ var/list/text_res = results.Copy(1, 3)
+ var/list/refs = results.len > 3 ? results.Copy(4) : null
+ . = "[text_res.Join("\n")][refs ? "\nRefs: [refs.Join(" ")]" : ""]"
+
/datum/server_tools_command/reload_admins
name = "reload_admins"
help_text = "Forces the server to reload admins."
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
index e091001851..9e9e727b39 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
@@ -24,10 +24,14 @@
message_admins("ERROR: Non-admin [key_name(usr, usr.client)] attempted to execute a SDQL query!")
log_admin("Non-admin [usr.ckey]([usr]) attempted to execute a SDQL query!")
return FALSE
+ var/list/results = world.SDQL2_query(query_text, key_name_admin(usr), "[usr.ckey]([usr])")
+ for(var/I in 1 to 3)
+ to_chat(usr, results[I])
+/world/proc/SDQL2_query(query_text, log_entry1, log_entry2)
var/query_log = "executed SDQL query: \"[query_text]\"."
- message_admins("[key_name_admin(usr)] [query_log]")
- query_log = "[usr.ckey]([usr]) [query_log]"
+ message_admins("[log_entry1] [query_log]")
+ query_log = "[log_entry2] [query_log]"
log_game(query_log)
NOTICE(query_log)
var/objs_all = 0
@@ -49,6 +53,7 @@
if(!querys || querys.len < 1)
return
+ var/list/refs = list()
for(var/list/query_tree in querys)
var/list/from_objs = list()
var/list/select_types = list()
@@ -100,6 +105,7 @@
var/text = ""
for(var/datum/t in objs)
text += SDQL_gen_vv_href(t)
+ refs[REF(t)] = TRUE
CHECK_TICK
usr << browse(text, "window=SDQL-result")
@@ -112,9 +118,9 @@
var/end_time = REALTIMEOFDAY
end_time -= start_time
- to_chat(usr, "SDQL query results: [query_text]")
- to_chat(usr, "SDQL query completed: [objs_all] objects selected by path, and [objs_eligible] objects executed on after WHERE filtering if applicable.")
- to_chat(usr, "SDQL query took [DisplayTimeText(end_time)] to complete.")
+ return list("SDQL query results: [query_text]",\
+ "SDQL query completed: [objs_all] objects selected by path, and [objs_eligible] objects executed on after WHERE filtering if applicable.",\
+ "SDQL query took [DisplayTimeText(end_time)] to complete.") + refs
/proc/SDQL_qdel_datum(datum/d)
qdel(d)
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index e3c8c19c31..b96c8f4bdc 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -110,7 +110,9 @@ GLOBAL_PROTECT(LastAdminCalledProc)
/proc/WrapAdminProcCall(target, procname, list/arguments)
var/current_caller = GLOB.AdminProcCaller
- var/ckey = usr.client.ckey
+ var/ckey = usr ? usr.client.ckey : GLOB.AdminProcCaller
+ if(!ckey)
+ CRASH("WrapAdminProcCall with no ckey: [target] [procname] [english_list(arguments)]")
if(current_caller && current_caller != ckey)
to_chat(usr, "Another set of admin called procs are still running, your proc will be run after theirs finish.")
UNTIL(!GLOB.AdminProcCaller)