Removes BSQL (#8697)

* Update rust_g.dm

* thing

* thing

* thing

* thing

* thing

* t

* t

* Update random_books.dm

* Update new_player.dm

* Update client_procs.dm

* f

* uwu

* Update dbcore.dm

* uwu

* Update permissionedit.dm

* Update dbcore.dm

* Update dbcore.dm

* Update blackbox.dm

* Update dbcore.dm

* d

* uwu

* Parameterize ipintel

* Update lib_machines.dm

* Parameterize stickyban

* Update sql_message_system.dm

* f

* thing

* thing

* polls

* Parameterize some of sql_ban_system

* f

* Update dbcore.dm

* Parameterize ban check

* Parameterize jobban creation

* uwu

* uwu

* Parameterize edit ban

* git

* uwu

* uwu

* Update install_rust_g.sh

* Remove libmariadb.dll

* Update deploy.sh

* uwu

* Avoid extra __detect_rust_g proccalls

* uwu

* ree

* Remove libmariadb.so download script

* boom

* Turdis

* finally

* sneaky

* night night

* list(

* token

* Update dbcore.dm

* uwu

* Improve readability on a query

* uwu

* Update sql_message_system.dm

* Update sql_message_system.dm

* Fix Malformed SQL Queries When Editing Admin Permissions (#51625)

* fixes

* s

* Update antag_token.dm

* Update create_poll.dm

* Update lib_machines.dm

* Update lib_machines.dm

* Update client_procs.dm

* Update rust_g.dm

* Update code/__DEFINES/rust_g.dm

Co-authored-by: alexkar598 <25136265+alexkar598@users.noreply.github.com>

* Update sql_message_system.dm

* Update sql_message_system.dm

* Update sql_message_system.dm

* Update sql_message_system.dm

* Update code/controllers/subsystem/blackbox.dm

Co-authored-by: alexkar598 <25136265+alexkar598@users.noreply.github.com>

* Update code/controllers/subsystem/blackbox.dm

Co-authored-by: alexkar598 <25136265+alexkar598@users.noreply.github.com>

* Update turdis.yml

* Update client_procs.dm

* Update client_procs.dm

* debug logging

* Update client_procs.dm

* Update client_procs.dm

* Update yogstation/code/modules/client/client_procs.dm

Co-authored-by: alexkar598 <25136265+alexkar598@users.noreply.github.com>

* Update sql_ban_system.dm

Co-authored-by: Tad Hardesty <tad@platymuus.com>
Co-authored-by: Bobbahbrown <bobbahbrown@gmail.com>
Co-authored-by: alexkar598 <25136265+alexkar598@users.noreply.github.com>
This commit is contained in:
TheGamerdk
2020-07-03 01:46:37 +02:00
committed by GitHub
parent 0d2e3f4bea
commit 9f66ed674e
52 changed files with 1161 additions and 1085 deletions

View File

@@ -12,20 +12,20 @@ SUBSYSTEM_DEF(achievements)
var/datum/achievement/A = new i
achievements[A] = A.id
var/datum/DBQuery/medalQuery = SSdbcore.NewQuery("SELECT name, descr FROM [format_table_name("achievements")] WHERE id = '[A.id]'") // No sanitation of A is needed for these calls because we instantiated A right here in this proc.
var/datum/DBQuery/medalQuery = SSdbcore.NewQuery("SELECT name, descr FROM [format_table_name("achievements")] WHERE id = :id", list("id" = A.id)) // No sanitation of A is needed for these calls because we instantiated A right here in this proc.
medalQuery.Execute()
if(!medalQuery.NextRow())
var/datum/DBQuery/medalQuery2 = SSdbcore.NewQuery("INSERT INTO [format_table_name("achievements")] (name, id, descr) VALUES ('[A.name]', '[A.id]', '[A.desc]')")
var/datum/DBQuery/medalQuery2 = SSdbcore.NewQuery("INSERT INTO [format_table_name("achievements")] (name, id, descr) VALUES (:name, :id, :desc)", list("name" = A.name, "id" = A.id, "desc" = A.desc))
medalQuery2.Execute()
qdel(medalQuery2)
else if(medalQuery.item[1] != A.name || medalQuery.item[2] != A.desc)
var/datum/DBQuery/medalQuery2 = SSdbcore.NewQuery("UPDATE [format_table_name("achievements")] SET name = '[A.name]', descr = '[A.desc]' WHERE id = '[A.id]'")
var/datum/DBQuery/medalQuery2 = SSdbcore.NewQuery("UPDATE [format_table_name("achievements")] SET name = :name, descr = :desc WHERE id = :id", list("name" = A.name, "desc" = A.desc, "id" = A.id))
medalQuery2.Execute()
qdel(medalQuery2)
qdel(medalQuery)
var/datum/DBQuery/ridOldChieves = SSdbcore.NewQuery("SELECT id FROM [format_table_name("achievements")]")
ridOldChieves.Execute()
while(ridOldChieves.NextRow())
@@ -38,9 +38,9 @@ SUBSYSTEM_DEF(achievements)
break
if(!found_achievement)
log_sql("Old achievement [id] found in database, removing")
var/datum/DBQuery/getRidOfOldStuff = SSdbcore.NewQuery("DELETE FROM [format_table_name("achievements")] WHERE id = '[id]'")
var/datum/DBQuery/getRidOfOldStuff = SSdbcore.NewQuery("DELETE FROM [format_table_name("achievements")] WHERE id = :id", list("id" = id))
getRidOfOldStuff.Execute()
var/datum/DBQuery/ridTheOtherTableAsWell = SSdbcore.NewQuery("DELETE FROM [format_table_name("earned_achievements")] WHERE id = '[id]'")
var/datum/DBQuery/ridTheOtherTableAsWell = SSdbcore.NewQuery("DELETE FROM [format_table_name("earned_achievements")] WHERE id = :id", list("id" = id))
ridTheOtherTableAsWell.Execute()
qdel(ridTheOtherTableAsWell)
qdel(getRidOfOldStuff)
@@ -75,7 +75,7 @@ SUBSYSTEM_DEF(achievements)
if(istype(achievement,/datum/achievement/greentext) && achievementPath != /datum/achievement/greentext)
unlock_achievement(/datum/achievement/greentext,C) // Oooh, a little bit recursive!
if(!has_achievement(achievementPath, C))
var/datum/DBQuery/medalQuery = SSdbcore.NewQuery("INSERT INTO [format_table_name("earned_achievements")] (ckey, id) VALUES ('[ckey(C.ckey)]', '[initial(achievement.id)]')")
var/datum/DBQuery/medalQuery = SSdbcore.NewQuery("INSERT INTO [format_table_name("earned_achievements")] (ckey, id) VALUES (:ckey, :id)", list("ckey" = ckey(C.ckey), "id" = initial(achievement.id)))
medalQuery.Execute()
qdel(medalQuery)
cached_achievements[C.ckey] += achievement
@@ -88,7 +88,7 @@ SUBSYSTEM_DEF(achievements)
/datum/controller/subsystem/achievements/proc/has_achievement(achievementPath, client/C)
var/datum/achievement/achievement = get_achievement(achievementPath)
if(!achievement)
log_sql("Achievement [achievementPath] not found in list of achievements when checking for [C.ckey]")
log_sql("Achievement [achievementPath] not found in list of achievements when checking for [C.ckey]")
return FALSE
if(!cached_achievements[C.ckey])
cache_achievements(C)
@@ -96,7 +96,7 @@ SUBSYSTEM_DEF(achievements)
return (achievement in cached_achievements[C.ckey])
/datum/controller/subsystem/achievements/proc/cache_achievements(client/C)
var/datum/DBQuery/cacheQuery = SSdbcore.NewQuery("SELECT id FROM [format_table_name("earned_achievements")] WHERE ckey = '[ckey(C.ckey)]'")
var/datum/DBQuery/cacheQuery = SSdbcore.NewQuery("SELECT id FROM [format_table_name("earned_achievements")] WHERE ckey = :ckey", list("ckey" = ckey(C.ckey)))
cacheQuery.Execute()
cached_achievements[C.ckey] = list()
while(cacheQuery.NextRow())

View File

@@ -45,7 +45,17 @@ SUBSYSTEM_DEF(blackbox)
if(M.client)
playercount += 1
var/admincount = GLOB.admins.len
var/datum/DBQuery/query_record_playercount = SSdbcore.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time, server_ip, server_port, round_id) VALUES ([playercount], [admincount], '[SQLtime()]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', '[GLOB.round_id]')")
var/datum/DBQuery/query_record_playercount = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time, server_ip, server_port, round_id)
VALUES (:playercount, :admincount, :time, INET_ATON(:server_ip), :server_port, :round_id)
"}, list(
"playercount" = playercount,
"admincount" = admincount,
"time" = SQLtime(),
"server_ip" = world.internet_address || "0",
"server_port" = world.port,
"round_id" = GLOB.round_id,
))
query_record_playercount.Execute()
qdel(query_record_playercount)
@@ -89,18 +99,23 @@ SUBSYSTEM_DEF(blackbox)
if (!SSdbcore.Connect())
return
var/list/special_columns = list(
"datetime" = "NOW()"
)
var/list/sqlrowlist = list()
for (var/datum/feedback_variable/FV in feedback)
var/sqlversion = 1
if(FV.key in versions)
sqlversion = versions[FV.key]
sqlrowlist += list(list("datetime" = "Now()", "round_id" = GLOB.round_id, "key_name" = "'[sanitizeSQL(FV.key)]'", "key_type" = "'[FV.key_type]'", "version" = "[sqlversion]", "json" = "'[sanitizeSQL(json_encode(FV.json))]'"))
sqlrowlist += list(list(
"key_type" = FV.key_type,
"round_id" = GLOB.round_id,
"key_name" = FV.key,
"version" = versions[FV.key] || 1,
"json" = json_encode(FV.json)
))
if (!length(sqlrowlist))
return
SSdbcore.MassInsert(format_table_name("feedback"), sqlrowlist, ignore_errors = TRUE, delayed = TRUE)
SSdbcore.MassInsert(format_table_name("feedback"), sqlrowlist, ignore_errors = TRUE, delayed = TRUE, special_columns = special_columns)
/datum/controller/subsystem/blackbox/proc/Seal()
if(sealed)
@@ -286,51 +301,36 @@ Versioning
first_death["area"] = "[AREACOORD(L)]"
first_death["damage"] = "<font color='#FF5555'>[L.getBruteLoss()]</font>/<font color='orange'>[L.getFireLoss()]</font>/<font color='lightgreen'>[L.getToxLoss()]</font>/<font color='lightblue'>[L.getOxyLoss()]</font>/<font color='pink'>[L.getCloneLoss()]</font>"
first_death["last_words"] = L.last_words
var/sqlname = L.real_name
var/sqlkey = L.ckey
var/sqljob = L.mind.assigned_role
var/sqlspecial = L.mind.special_role
var/sqlpod = get_area_name(L, TRUE)
var/laname = L.lastattacker
var/lakey = L.lastattackerckey
var/sqlbrute = L.getBruteLoss()
var/sqlfire = L.getFireLoss()
var/sqlbrain = L.getOrganLoss(ORGAN_SLOT_BRAIN)
var/sqloxy = L.getOxyLoss()
var/sqltox = L.getToxLoss()
var/sqlclone = L.getCloneLoss()
var/sqlstamina = L.getStaminaLoss()
var/x_coord = L.x
var/y_coord = L.y
var/z_coord = L.z
var/last_words = L.last_words
var/suicide = L.suiciding
var/map = SSmapping.config.map_name
if(!SSdbcore.Connect())
return
sqlname = sanitizeSQL(sqlname)
sqlkey = sanitizeSQL(sqlkey)
sqljob = sanitizeSQL(sqljob)
sqlspecial = sanitizeSQL(sqlspecial)
sqlpod = sanitizeSQL(sqlpod)
laname = sanitizeSQL(laname)
lakey = sanitizeSQL(lakey)
sqlbrute = sanitizeSQL(sqlbrute)
sqlfire = sanitizeSQL(sqlfire)
sqlbrain = sanitizeSQL(sqlbrain)
sqloxy = sanitizeSQL(sqloxy)
sqltox = sanitizeSQL(sqltox)
sqlclone = sanitizeSQL(sqlclone)
sqlstamina = sanitizeSQL(sqlstamina)
x_coord = sanitizeSQL(x_coord)
y_coord = sanitizeSQL(y_coord)
z_coord = sanitizeSQL(z_coord)
last_words = sanitizeSQL(last_words)
suicide = sanitizeSQL(suicide)
map = sanitizeSQL(map)
var/datum/DBQuery/query_report_death = SSdbcore.NewQuery("INSERT INTO [format_table_name("death")] (pod, x_coord, y_coord, z_coord, mapname, server_ip, server_port, round_id, tod, job, special, name, byondkey, laname, lakey, bruteloss, fireloss, brainloss, oxyloss, toxloss, cloneloss, staminaloss, last_words, suicide) VALUES ('[sqlpod]', '[x_coord]', '[y_coord]', '[z_coord]', '[map]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', [GLOB.round_id], '[SQLtime()]', '[sqljob]', '[sqlspecial]', '[sqlname]', '[sqlkey]', '[laname]', '[lakey]', [sqlbrute], [sqlfire], [sqlbrain], [sqloxy], [sqltox], [sqlclone], [sqlstamina], '[last_words]', [suicide])")
var/datum/DBQuery/query_report_death = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("death")] (pod, x_coord, y_coord, z_coord, mapname, server_ip, server_port, round_id, tod, job, special, name, byondkey, laname, lakey, bruteloss, fireloss, brainloss, oxyloss, toxloss, cloneloss, staminaloss, last_words, suicide)
VALUES (:pod, :x_coord, :y_coord, :z_coord, :map, INET_ATON(:internet_address), :port, :round_id, :time, :job, :special, :name, :key, :laname, :lakey, :brute, :fire, :brain, :oxy, :tox, :clone, :stamina, :last_words, :suicide)
"}, list(
"name" = L.real_name,
"key" = L.ckey,
"job" = L.mind.assigned_role,
"special" = L.mind.special_role,
"pod" = get_area_name(L, TRUE),
"laname" = L.lastattacker,
"lakey" = L.lastattackerckey,
"brute" = L.getBruteLoss(),
"fire" = L.getFireLoss(),
"brain" = L.getOrganLoss(ORGAN_SLOT_BRAIN) || BRAIN_DAMAGE_DEATH, //getOrganLoss returns null without a brain but a value is required for this column
"oxy" = L.getOxyLoss(),
"tox" = L.getToxLoss(),
"clone" = L.getCloneLoss(),
"stamina" = L.getStaminaLoss(),
"x_coord" = L.x,
"y_coord" = L.y,
"z_coord" = L.z,
"last_words" = L.last_words,
"suicide" = L.suiciding,
"map" = SSmapping.config.map_name,
"internet_address" = world.internet_address || "0",
"port" = world.port,
"round_id" = GLOB.round_id,
"time" = SQLtime(),
))
if(query_report_death)
query_report_death.Execute(async = TRUE)
qdel(query_report_death)

View File

@@ -14,8 +14,7 @@ SUBSYSTEM_DEF(dbcore)
var/last_error
var/list/active_queries = list()
var/datum/BSQL_Connection/connection
var/datum/BSQL_Operation/connectOperation
var/connection // Arbitrary handle returned from rust_g.
/datum/controller/subsystem/dbcore/Initialize()
//We send warnings to the admins during subsystem init, as the clients will be New'd and messages
@@ -40,24 +39,25 @@ SUBSYSTEM_DEF(dbcore)
/datum/controller/subsystem/dbcore/Recover()
connection = SSdbcore.connection
connectOperation = SSdbcore.connectOperation
/datum/controller/subsystem/dbcore/Shutdown()
//This is as close as we can get to the true round end before Disconnect() without changing where it's called, defeating the reason this is a subsystem
if(SSdbcore.Connect())
var/datum/DBQuery/query_round_shutdown = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET shutdown_datetime = Now(), end_state = '[sanitizeSQL(SSticker.end_state)]' WHERE id = [GLOB.round_id]")
var/datum/DBQuery/query_round_shutdown = SSdbcore.NewQuery(
"UPDATE [format_table_name("round")] SET shutdown_datetime = Now(), end_state = :end_state WHERE id = :round_id",
list("end_state" = SSticker.end_state, "round_id" = GLOB.round_id)
)
query_round_shutdown.Execute()
qdel(query_round_shutdown)
if(IsConnected())
Disconnect()
world.BSQL_Shutdown()
//nu
/datum/controller/subsystem/dbcore/can_vv_get(var_name)
return var_name != NAMEOF(src, connection) && var_name != NAMEOF(src, active_queries) && var_name != NAMEOF(src, connectOperation) && ..()
return var_name != NAMEOF(src, connection) && var_name != NAMEOF(src, active_queries) && ..()
/datum/controller/subsystem/dbcore/vv_edit_var(var_name, var_value)
if(var_name == NAMEOF(src, connection) || var_name == NAMEOF(src, connectOperation))
if(var_name == NAMEOF(src, connection))
return FALSE
return ..()
@@ -80,26 +80,28 @@ SUBSYSTEM_DEF(dbcore)
var/db = CONFIG_GET(string/feedback_database)
var/address = CONFIG_GET(string/address)
var/port = CONFIG_GET(number/port)
var/timeout = max(CONFIG_GET(number/async_query_timeout), CONFIG_GET(number/blocking_query_timeout))
var/thread_limit = CONFIG_GET(number/bsql_thread_limit)
connection = new /datum/BSQL_Connection(BSQL_CONNECTION_TYPE_MARIADB, CONFIG_GET(number/async_query_timeout), CONFIG_GET(number/blocking_query_timeout), CONFIG_GET(number/bsql_thread_limit))
var/error
if(QDELETED(connection))
connection = null
error = last_error
var/result = json_decode(rustg_sql_connect_pool(json_encode(list(
"host" = address,
"port" = port,
"user" = user,
"pass" = pass,
"db_name" = db,
"max_threads" = 5,
"read_timeout" = timeout,
"write_timeout" = timeout,
"max_threads" = thread_limit,
))))
. = (result["status"] == "ok")
if (.)
connection = result["handle"]
else
SSdbcore.last_error = null
connectOperation = connection.BeginConnect(address, port, user, pass, db)
if(SSdbcore.last_error)
CRASH(SSdbcore.last_error)
UNTIL(connectOperation.IsComplete())
error = connectOperation.GetError()
. = !error
if (!.)
last_error = error
log_sql("Connect() failed | [error]")
connection = null
last_error = result["data"]
log_sql("Connect() failed | [last_error]")
++failed_connections
QDEL_NULL(connection)
QDEL_NULL(connectOperation)
/datum/controller/subsystem/dbcore/proc/CheckSchemaVersion()
if(CONFIG_GET(flag/sql_enabled))
@@ -125,50 +127,49 @@ SUBSYSTEM_DEF(dbcore)
/datum/controller/subsystem/dbcore/proc/SetRoundID()
if(!Connect())
return
var/datum/DBQuery/query_round_initialize = SSdbcore.NewQuery("INSERT INTO [format_table_name("round")] (initialize_datetime, server_ip, server_port) VALUES (Now(), INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]')")
var/datum/DBQuery/query_round_initialize = SSdbcore.NewQuery(
"INSERT INTO [format_table_name("round")] (initialize_datetime, server_ip, server_port) VALUES (Now(), INET_ATON(:internet_address), :port)",
list("internet_address" = world.internet_address || "0", "port" = "[world.port]")
)
query_round_initialize.Execute(async = FALSE)
GLOB.round_id = "[query_round_initialize.last_insert_id]"
var/datum/DBQuery/query_fix_connections = SSdbcore.NewQuery("UPDATE [format_table_name("connection_log")] SET 'left' = NOW() WHERE 'left' IS NULL AND round_id = :id", list("id" = text2num(GLOB.round_id) - 1))
query_fix_connections.Execute()
qdel(query_fix_connections)
qdel(query_round_initialize)
var/datum/DBQuery/query_round_last_id = SSdbcore.NewQuery("SELECT LAST_INSERT_ID()")
query_round_last_id.Execute(async = FALSE)
if(query_round_last_id.NextRow(async = FALSE))
GLOB.round_id = query_round_last_id.item[1]
var/datum/DBQuery/query_fix_connections = SSdbcore.NewQuery("UPDATE [format_table_name("connection_log")] SET 'left' = NOW() WHERE 'left' IS NULL AND round_id = [text2num(GLOB.round_id) - 1]")
query_fix_connections.Execute()
qdel(query_fix_connections)
qdel(query_round_last_id)
/datum/controller/subsystem/dbcore/proc/SetRoundStart()
if(!Connect())
return
var/datum/DBQuery/query_round_start = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET start_datetime = Now() WHERE id = [GLOB.round_id]")
var/datum/DBQuery/query_round_start = SSdbcore.NewQuery(
"UPDATE [format_table_name("round")] SET start_datetime = Now() WHERE id = :round_id",
list("round_id" = GLOB.round_id)
)
query_round_start.Execute()
qdel(query_round_start)
/datum/controller/subsystem/dbcore/proc/SetRoundEnd()
if(!Connect())
return
var/sql_station_name = sanitizeSQL(station_name())
var/datum/DBQuery/query_round_end = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET end_datetime = Now(), game_mode_result = '[sanitizeSQL(SSticker.mode_result)]', station_name = '[sql_station_name]' WHERE id = [GLOB.round_id]")
var/datum/DBQuery/query_round_end = SSdbcore.NewQuery(
"UPDATE [format_table_name("round")] SET end_datetime = Now(), game_mode_result = :game_mode_result, station_name = :station_name WHERE id = :round_id",
list("game_mode_result" = SSticker.mode_result, "station_name" = station_name(), "round_id" = GLOB.round_id)
)
query_round_end.Execute()
qdel(query_round_end)
/datum/controller/subsystem/dbcore/proc/Disconnect()
failed_connections = 0
QDEL_NULL(connectOperation)
QDEL_NULL(connection)
if (connection)
rustg_sql_disconnect_pool(connection)
connection = null
/datum/controller/subsystem/dbcore/proc/IsConnected()
if(!CONFIG_GET(flag/sql_enabled))
if (!CONFIG_GET(flag/sql_enabled))
return FALSE
//block until any connect operations finish
var/datum/BSQL_Connection/_connection = connection
var/datum/BSQL_Operation/op = connectOperation
UNTIL(QDELETED(_connection) || op.IsComplete())
return !QDELETED(connection) && !op.GetError()
/datum/controller/subsystem/dbcore/proc/Quote(str)
if(connection)
return connection.Quote(str)
if (!connection)
return FALSE
return json_decode(rustg_sql_connected(connection))["status"] == "online"
/datum/controller/subsystem/dbcore/proc/ErrorMsg()
if(!CONFIG_GET(flag/sql_enabled))
@@ -178,12 +179,12 @@ SUBSYSTEM_DEF(dbcore)
/datum/controller/subsystem/dbcore/proc/ReportError(error)
last_error = error
/datum/controller/subsystem/dbcore/proc/NewQuery(sql_query)
/datum/controller/subsystem/dbcore/proc/NewQuery(sql_query, arguments)
if(IsAdminAdvancedProcCall())
log_admin_private("ERROR: Advanced admin proc call led to sql query: [sql_query]. Query has been blocked")
message_admins("ERROR: Advanced admin proc call led to sql query. Query has been blocked")
return FALSE
return new /datum/DBQuery(sql_query, connection)
return new /datum/DBQuery(connection, sql_query, arguments)
/datum/controller/subsystem/dbcore/proc/QuerySelect(list/querys, warn = FALSE, qdel = FALSE)
if (!islist(querys))
@@ -218,55 +219,60 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
It was included because it is still supported in mariadb.
It does not work with duplicate_key and the mysql server ignores it in those cases
*/
/datum/controller/subsystem/dbcore/proc/MassInsert(table, list/rows, duplicate_key = FALSE, ignore_errors = FALSE, delayed = FALSE, warn = FALSE, async = TRUE)
/datum/controller/subsystem/dbcore/proc/MassInsert(table, list/rows, duplicate_key = FALSE, ignore_errors = FALSE, delayed = FALSE, warn = FALSE, async = TRUE, special_columns = null)
if (!table || !rows || !istype(rows))
return
// Prepare column list
var/list/columns = list()
var/list/sorted_rows = list()
var/list/has_question_mark = list()
for (var/list/row in rows)
var/list/sorted_row = list()
sorted_row.len = columns.len
for (var/column in row)
var/idx = columns[column]
if (!idx)
idx = columns.len + 1
columns[column] = idx
sorted_row.len = columns.len
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], "?")
sorted_row[idx] = row[column]
sorted_rows[++sorted_rows.len] = sorted_row
// Prepare SQL query full of placeholders
var/list/query_parts = list("INSERT")
if (delayed)
query_parts += " DELAYED"
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])"
duplicate_key = "ON DUPLICATE KEY UPDATE [column_list.Join(", ")]\n"
else if (duplicate_key == FALSE)
duplicate_key = null
query_parts += "\nON DUPLICATE KEY UPDATE [column_list.Join(", ")]"
else if (duplicate_key != FALSE)
query_parts += duplicate_key
if (ignore_errors)
ignore_errors = " IGNORE"
else
ignore_errors = null
if (delayed)
delayed = " DELAYED"
else
delayed = null
var/list/sqlrowlist = list()
var/len = columns.len
for (var/list/row in sorted_rows)
if (length(row) != len)
row.len = len
for (var/value in row)
if (value == null)
value = "NULL"
sqlrowlist += "([row.Join(", ")])"
sqlrowlist = " [sqlrowlist.Join(",\n ")]"
var/datum/DBQuery/Query = NewQuery("INSERT[delayed][ignore_errors] INTO [table]\n([columns.Join(", ")])\nVALUES\n[sqlrowlist]\n[duplicate_key]")
var/datum/DBQuery/Query = NewQuery(query_parts.Join(), arguments)
if (warn)
. = Query.warn_execute(async)
else
@@ -274,24 +280,33 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
qdel(Query)
/datum/DBQuery
var/sql // The sql query being executed.
var/list/item //list of data values populated by NextRow()
// Inputs
var/connection
var/sql
var/arguments
// Status information
var/in_progress
var/last_error
var/last_activity
var/last_activity_time
var/last_error
var/skip_next_is_complete
var/in_progress
var/datum/BSQL_Connection/connection
var/datum/BSQL_Operation/Query/query
// Output
var/list/list/rows
var/next_row_to_take = 1
var/affected
var/last_insert_id
/datum/DBQuery/New(sql_query, datum/BSQL_Connection/connection)
var/list/item //list of data values populated by NextRow()
/datum/DBQuery/New(connection, sql, arguments)
SSdbcore.active_queries[src] = TRUE
Activity("Created")
item = list()
src.connection = connection
sql = sql_query
src.sql = sql
src.arguments = arguments
/datum/DBQuery/Destroy()
Close()
@@ -302,12 +317,6 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
//fuck off kevinz
return FALSE
/datum/DBQuery/proc/SetQuery(new_sql)
if(in_progress)
CRASH("Attempted to set new sql while waiting on active query")
Close()
sql = new_sql
/datum/DBQuery/proc/Activity(activity)
last_activity = activity
last_activity_time = world.time
@@ -322,30 +331,18 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
if(in_progress)
CRASH("Attempted to start a new query while waiting on the old one")
if(QDELETED(connection))
if(!SSdbcore.IsConnected())
last_error = "No connection!"
return FALSE
var/start_time
var/timed_out
if(!async)
start_time = REALTIMEOFDAY
Close()
timed_out = run_query(async)
if(query.GetErrorCode() == 2006) //2006 is the return code for "MySQL server has gone away" time-out error, meaning the connection has been lost to the server (if it's still alive)
log_sql("Executing query encountered returned a lost database connection (2006).")
SSdbcore.Disconnect()
if(SSdbcore.Connect()) //connection was restablished, reattempt the query
log_sql("Connection restablished")
timed_out = run_query(async)
else
log_sql("Executing query failed to restablish database connection.")
skip_next_is_complete = TRUE
var/error = QDELETED(query) ? "Query object deleted!" : query.GetError()
last_error = error
. = !error
. = run_query(async)
var/timed_out = !. && findtext(last_error, "Operation timed out")
if(!. && log_error)
log_sql("[error] | Query used: [sql]")
log_sql("[last_error] | Query used: [sql]")
if(!async && timed_out)
log_query_debug("Query execution started at [start_time]")
log_query_debug("Query execution ended at [REALTIMEOFDAY]")
@@ -354,52 +351,50 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
slow_query_check()
/datum/DBQuery/proc/run_query(async)
query = connection.BeginQuery(sql)
if(!async)
. = !query.WaitForCompletion()
else
var/job_result_str
if (async)
var/job_id = rustg_sql_query_async(connection, sql, json_encode(arguments))
in_progress = TRUE
UNTIL(query.IsComplete())
UNTIL((job_result_str = rustg_sql_check_query(job_id)) != RUSTG_JOB_NO_RESULTS_YET)
in_progress = FALSE
if (job_result_str == RUSTG_JOB_ERROR)
last_error = job_result_str
return FALSE
else
job_result_str = rustg_sql_query_blocking(connection, sql, json_encode(arguments))
var/result = json_decode(job_result_str)
switch (result["status"])
if ("ok")
rows = result["rows"]
affected = result["affected"]
last_insert_id = result["last_insert_id"]
return TRUE
if ("err")
last_error = result["data"]
return FALSE
if ("offline")
last_error = "offline"
return FALSE
/datum/DBQuery/proc/slow_query_check()
message_admins("HEY! A database query timed out. Did the server just hang? <a href='?_src_=holder;[HrefToken()];slowquery=yes'>\[YES\]</a>|<a href='?_src_=holder;[HrefToken()];slowquery=no'>\[NO\]</a>")
/datum/DBQuery/proc/NextRow(async = TRUE)
Activity("NextRow")
UNTIL(!in_progress)
if(!skip_next_is_complete)
if(!async)
query.WaitForCompletion()
else
in_progress = TRUE
UNTIL(query.IsComplete())
in_progress = FALSE
if (rows && next_row_to_take <= rows.len)
item = rows[next_row_to_take]
next_row_to_take++
return !!item
else
skip_next_is_complete = FALSE
last_error = query.GetError()
var/list/results = query.CurrentRow()
. = results != null
item.Cut()
//populate item array
for(var/I in results)
item += results[I]
return FALSE
/datum/DBQuery/proc/ErrorMsg()
return last_error
/datum/DBQuery/proc/Close()
item.Cut()
QDEL_NULL(query)
/world/BSQL_Debug(message)
if(!CONFIG_GET(flag/bsql_debug))
return
//strip sensitive stuff
if(findtext(message, ": OpenConnection("))
message = "OpenConnection CENSORED"
log_sql("BSQL_DEBUG: [message]")
rows = null
item = null

View File

@@ -19,7 +19,10 @@ SUBSYSTEM_DEF(discord)
// Returns ID from ckey
/datum/controller/subsystem/discord/proc/lookup_id(lookup_ckey)
var/datum/DBQuery/query_get_discord_id = SSdbcore.NewQuery("SELECT discord_id FROM [format_table_name("player")] WHERE ckey = '[sanitizeSQL(lookup_ckey)]'")
var/datum/DBQuery/query_get_discord_id = SSdbcore.NewQuery(
"SELECT discord_id FROM [format_table_name("player")] WHERE ckey = :ckey",
list("ckey" = lookup_ckey)
)
if(!query_get_discord_id.Execute())
qdel(query_get_discord_id)
return
@@ -29,7 +32,10 @@ SUBSYSTEM_DEF(discord)
// Returns ckey from ID
/datum/controller/subsystem/discord/proc/lookup_ckey(lookup_id)
var/datum/DBQuery/query_get_discord_ckey = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE discord_id = '[sanitizeSQL(lookup_id)]'")
var/datum/DBQuery/query_get_discord_ckey = SSdbcore.NewQuery(
"SELECT ckey FROM [format_table_name("player")] WHERE discord_id = :discord_id",
list("discord_id" = lookup_id)
)
if(!query_get_discord_ckey.Execute())
qdel(query_get_discord_ckey)
return
@@ -39,14 +45,20 @@ SUBSYSTEM_DEF(discord)
// Finalises link
/datum/controller/subsystem/discord/proc/link_account(ckey)
var/datum/DBQuery/link_account = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET discord_id = '[sanitizeSQL(account_link_cache[ckey])]' WHERE ckey = '[sanitizeSQL(ckey)]'")
var/datum/DBQuery/link_account = SSdbcore.NewQuery(
"UPDATE [format_table_name("player")] SET discord_id = :discord_id WHERE ckey = :ckey",
list("discord_id" = account_link_cache[ckey], "ckey" = ckey)
)
link_account.Execute()
qdel(link_account)
account_link_cache -= ckey
// Unlink account (Admin verb used)
/datum/controller/subsystem/discord/proc/unlink_account(ckey)
var/datum/DBQuery/unlink_account = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET discord_id = NULL WHERE ckey = '[sanitizeSQL(ckey)]'")
var/datum/DBQuery/unlink_account = SSdbcore.NewQuery(
"UPDATE [format_table_name("player")] SET discord_id = NULL WHERE ckey = :ckey",
list("ckey" = ckey)
)
unlink_account.Execute()
qdel(unlink_account)

View File

@@ -264,7 +264,9 @@ SUBSYSTEM_DEF(mapping)
LoadGroup(FailedZs, "Station", config.map_path, config.map_file, config.traits, ZTRAITS_STATION)
if(SSdbcore.Connect())
var/datum/DBQuery/query_round_map_name = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET map_name = '[config.map_name]' WHERE id = [GLOB.round_id]")
var/datum/DBQuery/query_round_map_name = SSdbcore.NewQuery({"
UPDATE [format_table_name("round")] SET map_name = :map_name WHERE id = :round_id
"}, list("map_name" = config.map_name, "round_id" = GLOB.round_id))
query_round_map_name.Execute()
qdel(query_round_map_name)

View File

@@ -150,7 +150,10 @@ SUBSYSTEM_DEF(stickyban)
if (!ban["message"])
ban["message"] = "Evasion"
var/datum/DBQuery/query_create_stickyban = SSdbcore.NewQuery("INSERT IGNORE INTO [format_table_name("stickyban")] (ckey, reason, banning_admin) VALUES ('[sanitizeSQL(ckey)]', '[sanitizeSQL(ban["message"])]', '[sanitizeSQL(ban["admin"])]')")
var/datum/DBQuery/query_create_stickyban = SSdbcore.NewQuery(
"INSERT IGNORE INTO [format_table_name("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
@@ -164,8 +167,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
@@ -173,8 +176,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
@@ -182,26 +185,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))
SSdbcore.MassInsert(format_table_name("stickyban_matched_ckey"), sqlckeys, FALSE, TRUE)
SSdbcore.MassInsert(format_table_name("stickyban_matched_ckey"), sqlckeys, ignore_errors = TRUE)
if (length(sqlcids))
SSdbcore.MassInsert(format_table_name("stickyban_matched_cid"), sqlcids, FALSE, TRUE)
SSdbcore.MassInsert(format_table_name("stickyban_matched_cid"), sqlcids, ignore_errors = TRUE)
if (length(sqlips))
SSdbcore.MassInsert(format_table_name("stickyban_matched_ip"), sqlips, FALSE, TRUE)
SSdbcore.MassInsert(format_table_name("stickyban_matched_ip"), sqlips, ignore_errors = TRUE)
return TRUE