mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-14 17:36:52 +01:00
Better SQL prepared statements (#2474)
The system used to be of complexity O(n^2). Essentially two for loops running per every argument. Which ended up being surprisingly slow (there were instances where I saw the argument parser as using quite a lot of CPU time).
This replaces it with a more linear algorithm. It's somewhere near O(n) where n is the length of the unparsed query. Which is more stable and faaaster. This comes with two changes, however:
Parameters inside the query now have to be delimited from both sides with : (colons). The alternative to this would be to use something like $n or just assume that space marks the end of a marker. Only the former is workable, the latter would break a few queries already.
Arguments in the argument array no longer have to be prefixed by : (colons). So, while in the query you would write :thing:, you'd initialize the array of args as: list("thing" = somevar). It could be made to work without it, but eh, I think this is fine.
Argument validation is slightly weaker. What I mean by this is that with the old system, unused keys would result in an error. This is no longer a thing. Missing keys will still result in an error, however.
One more improvement: double delimiting removes an edge case where if key A partially covers key B, depending on the order, key A would mangle key B.
Updated and tested all queries that I could find. So this should be good.
This commit is contained in:
@@ -36,15 +36,15 @@
|
||||
warned_computerid = C.computer_id
|
||||
warned_ip = C.address
|
||||
else
|
||||
var/DBQuery/lookup_query = dbcon.NewQuery("SELECT ip, computerid FROM ss13_player WHERE ckey = :ckey")
|
||||
lookup_query.Execute(list(":ckey" = warned_ckey))
|
||||
var/DBQuery/lookup_query = dbcon.NewQuery("SELECT ip, computerid FROM ss13_player WHERE ckey = :ckey:")
|
||||
lookup_query.Execute(list("ckey" = warned_ckey))
|
||||
|
||||
if (lookup_query.NextRow())
|
||||
warned_ip = lookup_query.item[1]
|
||||
warned_computerid = lookup_query.item[2]
|
||||
|
||||
var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO ss13_warnings (id, time, severity, reason, notes, ckey, computerid, ip, a_ckey, a_ip, a_computerid) VALUES (null, Now(), :warning_severity, :warning_reason, :warning_notes, :warned_ckey, :warned_computerid, :warned_ip, :a_ckey, :a_ip, :a_computerid)")
|
||||
insert_query.Execute(list(":warning_severity" = warning_severity, ":warning_reason" = warning_reason, ":warning_notes" = warning_notes, ":warned_ckey" = warned_ckey, ":warned_computerid" = warned_computerid, ":warned_ip" = warned_ip, ":a_ckey" = ckey, ":a_ip" = address, ":a_computerid" = computer_id))
|
||||
var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO ss13_warnings (id, time, severity, reason, notes, ckey, computerid, ip, a_ckey, a_ip, a_computerid) VALUES (null, Now(), :warning_severity:, :warning_reason:, :warning_notes:, :warned_ckey:, :warned_computerid:, :warned_ip:, :a_ckey:, :a_ip:, :a_computerid:)")
|
||||
insert_query.Execute(list("warning_severity" = warning_severity, "warning_reason" = warning_reason, "warning_notes" = warning_notes, "warned_ckey" = warned_ckey, "warned_computerid" = warned_computerid, "warned_ip" = warned_ip, "a_ckey" = ckey, "a_ip" = address, "a_computerid" = computer_id))
|
||||
|
||||
notes_add_sql(warned_ckey, "Warning added by [ckey], for: [warning_reason]. || Notes regarding the warning: [warning_notes].", src, warned_ip, warned_computerid)
|
||||
|
||||
@@ -124,8 +124,8 @@
|
||||
dat += "<th width='60%'>REASON</th>"
|
||||
dat += "</tr>"
|
||||
|
||||
var/DBQuery/search_query = dbcon.NewQuery("SELECT id, time, severity, reason, a_ckey, acknowledged, expired FROM ss13_warnings WHERE visible = 1 AND (ckey = :ckey OR computerid = :computer_id OR ip = :address) ORDER BY time DESC;")
|
||||
search_query.Execute(list(":ckey" = ckey, ":computer_id" = computer_id, ":address" = address))
|
||||
var/DBQuery/search_query = dbcon.NewQuery("SELECT id, time, severity, reason, a_ckey, acknowledged, expired FROM ss13_warnings WHERE visible = 1 AND (ckey = :ckey: OR computerid = :computer_id: OR ip = :address:) ORDER BY time DESC;")
|
||||
search_query.Execute(list("ckey" = ckey, "computer_id" = computer_id, "address" = address))
|
||||
|
||||
while (search_query.NextRow())
|
||||
var/id = text2num(search_query.item[1])
|
||||
@@ -177,8 +177,8 @@
|
||||
alert("Connection to SQL database failed while attempting to update your warning's status!")
|
||||
return
|
||||
|
||||
var/DBQuery/query = dbcon.NewQuery("UPDATE ss13_warnings SET acknowledged = 1 WHERE id = :warning_id;")
|
||||
query.Execute(list(":warning_id" = warning_id))
|
||||
var/DBQuery/query = dbcon.NewQuery("UPDATE ss13_warnings SET acknowledged = 1 WHERE id = :warning_id:;")
|
||||
query.Execute(list("warning_id" = warning_id))
|
||||
|
||||
warnings_check()
|
||||
|
||||
@@ -194,17 +194,17 @@
|
||||
if (!dbcon.IsConnected())
|
||||
return
|
||||
|
||||
var/list/client_details = list(":ckey" = ckey, ":computer_id" = computer_id, ":address" = address)
|
||||
var/list/client_details = list("ckey" = ckey, "computer_id" = computer_id, "address" = address)
|
||||
|
||||
var/DBQuery/expire_query = dbcon.NewQuery("SELECT id FROM ss13_warnings WHERE (acknowledged = 1 AND expired = 0 AND DATE_SUB(CURDATE(),INTERVAL 3 MONTH) > time) AND (ckey = :ckey OR computerid = :computer_id OR ip = :address)")
|
||||
var/DBQuery/expire_query = dbcon.NewQuery("SELECT id FROM ss13_warnings WHERE (acknowledged = 1 AND expired = 0 AND DATE_SUB(CURDATE(),INTERVAL 3 MONTH) > time) AND (ckey = :ckey: OR computerid = :computer_id: OR ip = :address:)")
|
||||
expire_query.Execute(client_details)
|
||||
while (expire_query.NextRow())
|
||||
var/warning_id = text2num(expire_query.item[1])
|
||||
var/DBQuery/update_query = dbcon.NewQuery("UPDATE ss13_warnings SET expired = 1 WHERE id = :warning_id")
|
||||
update_query.Execute(list(":warning_id" = warning_id))
|
||||
var/DBQuery/update_query = dbcon.NewQuery("UPDATE ss13_warnings SET expired = 1 WHERE id = :warning_id:")
|
||||
update_query.Execute(list("warning_id" = warning_id))
|
||||
count_expire++
|
||||
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT id FROM ss13_warnings WHERE (visible = 1 AND acknowledged = 0 AND expired = 0) AND (ckey = :ckey OR computerid = :computer_id OR ip = :address)")
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT id FROM ss13_warnings WHERE (visible = 1 AND acknowledged = 0 AND expired = 0) AND (ckey = :ckey: OR computerid = :computer_id: OR ip = :address:)")
|
||||
query.Execute(client_details)
|
||||
while (query.NextRow())
|
||||
count++
|
||||
@@ -265,18 +265,18 @@
|
||||
dat += "<th width='60%'>REASON</th>"
|
||||
dat += "</tr>"
|
||||
|
||||
var/list/query_details = list(":a_ckey", ":ckey")
|
||||
var/list/query_details = list("a_ckey", "ckey")
|
||||
var/paramone = ""
|
||||
var/paramtwo = ""
|
||||
if(adminckey)
|
||||
paramone = "AND a_ckey = :a_ckey "
|
||||
query_details[":a_ckey"] = adminckey
|
||||
paramone = "AND a_ckey = :a_ckey: "
|
||||
query_details["a_ckey"] = adminckey
|
||||
if(playerckey)
|
||||
paramtwo = "AND ckey = :ckey "
|
||||
query_details[":ckey"] = playerckey
|
||||
paramtwo = "AND ckey = :ckey: "
|
||||
query_details["ckey"] = playerckey
|
||||
|
||||
var/DBQuery/search_query = dbcon.NewQuery("SELECT id, time, severity, reason, notes, ckey, a_ckey, acknowledged, expired, edited, lasteditor, lasteditdate FROM ss13_warnings WHERE visible = 1 [paramone] [paramtwo] ORDER BY time DESC;")
|
||||
search_query.Execute(query_details, 1)
|
||||
search_query.Execute(query_details)
|
||||
|
||||
while (search_query.NextRow())
|
||||
var/id = text2num(search_query.item[1])
|
||||
@@ -351,10 +351,10 @@
|
||||
var/ckey
|
||||
var/reason
|
||||
var/notes
|
||||
var/list/query_details = list(":warning_id" = warning_id, ":a_ckey" = usr.ckey)
|
||||
var/list/query_details = list("warning_id" = warning_id, "a_ckey" = usr.ckey)
|
||||
|
||||
var/DBQuery/initial_query = dbcon.NewQuery("SELECT ckey, reason, notes FROM ss13_warnings WHERE id = :warning_id")
|
||||
initial_query.Execute(query_details, 1)
|
||||
var/DBQuery/initial_query = dbcon.NewQuery("SELECT ckey, reason, notes FROM ss13_warnings WHERE id = :warning_id:")
|
||||
initial_query.Execute(query_details)
|
||||
while (initial_query.NextRow())
|
||||
ckey = initial_query.item[1]
|
||||
reason = initial_query.item[2]
|
||||
@@ -374,8 +374,8 @@
|
||||
switch (warning_edit)
|
||||
if ("delete")
|
||||
if(alert("Delete this warning?", "Delete?", "Yes", "No") == "Yes")
|
||||
var/DBQuery/deleteQuery = dbcon.NewQuery("UPDATE ss13_warnings SET visible = 0 WHERE id = :warning_id")
|
||||
deleteQuery.Execute(query_details, 1)
|
||||
var/DBQuery/deleteQuery = dbcon.NewQuery("UPDATE ss13_warnings SET visible = 0 WHERE id = :warning_id:")
|
||||
deleteQuery.Execute(query_details)
|
||||
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] deleted one of [ckey]'s warnings.</span>")
|
||||
log_admin("[key_name(usr)] deleted one of [ckey]'s warnings.", admin_key=key_name(usr), ckey=ckey)
|
||||
@@ -384,29 +384,27 @@
|
||||
return
|
||||
|
||||
if ("editReason")
|
||||
query_details += ":new_reason"
|
||||
query_details[":new_reason"] = input("Edit this warning's reason.", "New Reason", reason, null) as null|text
|
||||
query_details["new_reason"] = input("Edit this warning's reason.", "New Reason", reason, null) as null|text
|
||||
|
||||
if(!query_details[":new_reason"] || query_details[":new_reason"] == reason)
|
||||
if(!query_details["new_reason"] || query_details["new_reason"] == reason)
|
||||
usr << "Cancelled"
|
||||
return
|
||||
|
||||
var/DBQuery/reason_query = dbcon.NewQuery("UPDATE ss13_warnings SET reason = :new_reason, edited = 1, lasteditor = :a_ckey, lasteditdate = NOW() WHERE id = :warning_id")
|
||||
reason_query.Execute(query_details, 1)
|
||||
var/DBQuery/reason_query = dbcon.NewQuery("UPDATE ss13_warnings SET reason = :new_reason:, edited = 1, lasteditor = :a_ckey:, lasteditdate = NOW() WHERE id = :warning_id:")
|
||||
reason_query.Execute(query_details)
|
||||
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] edited one of [ckey]'s warning reasons.</span>")
|
||||
log_admin("[key_name(usr)] edited one of [ckey]'s warning reasons.", admin_key=key_name(usr), ckey=ckey)
|
||||
|
||||
if("editNotes")
|
||||
query_details += ":new_notes"
|
||||
query_details[":new_notes"] = input("Edit this warning's notes.", "New Notes", notes, null) as null|text
|
||||
query_details["new_notes"] = input("Edit this warning's notes.", "New Notes", notes, null) as null|text
|
||||
|
||||
if(!query_details[":new_notes"] || query_details[":new_notes"] == notes)
|
||||
if(!query_details["new_notes"] || query_details["new_notes"] == notes)
|
||||
usr << "Cancelled"
|
||||
return
|
||||
|
||||
var/DBQuery/notes_query = dbcon.NewQuery("UPDATE ss13_warnings SET notes = :new_notes, edited = 1, lasteditor = :a_ckey, lasteditdate = NOW() WHERE id = :warning_id")
|
||||
notes_query.Execute(query_details, 1)
|
||||
var/DBQuery/notes_query = dbcon.NewQuery("UPDATE ss13_warnings SET notes = :new_notes:, edited = 1, lasteditor = :a_ckey:, lasteditdate = NOW() WHERE id = :warning_id:")
|
||||
notes_query.Execute(query_details)
|
||||
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] edited one of [ckey]'s warning notes.</span>")
|
||||
log_admin("[key_name(usr)] edited one of [ckey]'s warning notes.", admin_key=key_name(usr), ckey=ckey)
|
||||
|
||||
Reference in New Issue
Block a user