mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-20 15:12:19 +00:00
259 lines
8.6 KiB
Plaintext
259 lines
8.6 KiB
Plaintext
// Set this to 1 if you want to debug the SQL saves.
|
|
// I got tired as hell from writing these debug lines and deleting them later.
|
|
|
|
/*
|
|
* A proc for dynamically loading a character from the database.
|
|
* See the category items for procs on what pieces are given.
|
|
*
|
|
* Each query is cached as well, after generation. Only things recompiled are the arguments and the finalized query text (with arguments in it).
|
|
*/
|
|
/datum/category_group/player_setup_category/proc/handle_sql_loading(var/role_type)
|
|
var/static/list/query_cache
|
|
|
|
// We aren't loading this category. Bye.
|
|
if (role_type && !(sql_role & role_type))
|
|
#ifdef SQL_PREF_DEBUG
|
|
log_debug("SQL CHARACTER LOAD: Bad role_type, returned. Looking for: [role_type], had: [sql_role]. Conjunction: [sql_role & role_type].")
|
|
#endif
|
|
return
|
|
|
|
if (isnull(query_cache))
|
|
query_cache = list()
|
|
|
|
// This handles the generation of queries. One per category, total of 5 UNLESS one category wants to query more than one table.
|
|
// It uses like, 3+ levels of lists. But it works, and is only run once per category in the global sense. So technically, efficient!
|
|
// :D - Skull132
|
|
if (!query_cache.len || isnull(query_cache[type]))
|
|
query_cache[type] = list()
|
|
var/list/tables = list()
|
|
|
|
// First, consolidate the different lists into one.
|
|
for (var/datum/category_item/player_setup_item/PI in items)
|
|
var/list/pi_tables = PI.gather_load_query()
|
|
// Expected layout: list("table A name" = list("vars" = list("column name" = "var name"), "args" = list()),
|
|
// "table B name" = list("vars" = list(), "args" = list()))
|
|
|
|
for (var/table in pi_tables)
|
|
var/list/A = pi_tables[table]
|
|
if (isnull(tables[table]))
|
|
tables[table] = list("vars" = list(), "args" = list())
|
|
|
|
tables[table]["vars"] |= A["vars"]
|
|
tables[table]["args"] |= A["args"]
|
|
|
|
// Second, create the queries and save them.
|
|
for (var/table in tables)
|
|
var/query = "SELECT "
|
|
var/list/var_names = tables[table]["vars"]
|
|
var/count = var_names.len
|
|
|
|
// Process the variables and rows we want.
|
|
var/i = 1
|
|
for (var/name in var_names)
|
|
query += name
|
|
|
|
if (!isnull(var_names[name]))
|
|
var/new_name = var_names[name]
|
|
var_names.Remove(name)
|
|
var_names.Insert(i, new_name)
|
|
|
|
if (i != count)
|
|
query += ", "
|
|
else
|
|
query += " "
|
|
|
|
i++
|
|
|
|
query += "FROM [table] WHERE "
|
|
|
|
// Process the args.
|
|
var/list/arg_names = tables[table]["args"]
|
|
count = arg_names.len
|
|
for (i = 1, i <= count, i++)
|
|
query += "[arg_names[i]] = :[arg_names[i]]:"
|
|
|
|
if (i != count)
|
|
query += " AND "
|
|
else
|
|
query += ";"
|
|
|
|
#ifdef SQL_PREF_DEBUG
|
|
log_debug("SQL CHARACTER LOAD: Cached query [query] with variables [json_encode(var_names)]")
|
|
#endif
|
|
// Save it.
|
|
query_cache[type][query] = var_names
|
|
|
|
// Need to typecast due to reasons.
|
|
var/datum/category_collection/player_setup_collection/cc = collection
|
|
|
|
// Actually utilize the queries.
|
|
var/list/arg_list = gather_load_parameters()
|
|
|
|
#ifdef SQL_PREF_DEBUG
|
|
log_debug("SQL CHARACTER LOAD: Started loading with arguments: [json_encode(arg_list)]. Role type: [role_type]")
|
|
#endif
|
|
|
|
for (var/query_text in query_cache[type])
|
|
var/DBQuery/query = dbcon.NewQuery(query_text)
|
|
query.Execute(arg_list)
|
|
if (query.ErrorMsg())
|
|
error("SQL CHARACTER LOAD: SQL query error: [query.ErrorMsg()]")
|
|
log_debug("SQL CHARACTER LOAD: SQL query error: [query.ErrorMsg()]")
|
|
log_debug("SQL CHARACTER LOAD: query args: [json_encode(arg_list)]")
|
|
|
|
continue
|
|
|
|
#ifdef SQL_PREF_DEBUG
|
|
else
|
|
log_debug("SQL CHARACTER LOAD: Successfully executed query: [query_text]")
|
|
#endif
|
|
|
|
// Each query should only return exactly 1 row.
|
|
var/list/var_names = query_cache[type][query_text]
|
|
if (query.NextRow())
|
|
for (var/i = 1, i <= var_names.len, i++)
|
|
var/list/layers = splittext(var_names[i], "/")
|
|
try
|
|
if (layers.len == 1)
|
|
cc.preferences.vars[var_names[i]] = query.item[i]
|
|
else
|
|
cc.preferences.vars[layers[1]][layers[2]] = query.item[i]
|
|
catch(var/exception/e)
|
|
error("SQL CHARACTER LOAD: bad variable name: [e.name]")
|
|
log_debug("SQL CHARACTER LOAD: bad variable name: [e.name]")
|
|
log_debug("SQL CHARACTER LOAD: var name: [var_names[i]]")
|
|
|
|
/datum/category_group/player_setup_category/proc/gather_load_parameters()
|
|
var/list/arg_list = list()
|
|
for (var/datum/category_item/player_setup_item/PI in items)
|
|
arg_list |= PI.gather_load_parameters()
|
|
|
|
return arg_list
|
|
|
|
/*
|
|
* A proc for dynamically inserting new character and preference records into the database.
|
|
* See the category items for procs on what pieces are given.
|
|
*
|
|
* Each query is cached as well, after generation. Only things recompiled are the arguments and the finalized query text (with arguments in it).
|
|
*/
|
|
/datum/category_group/player_setup_category/proc/handle_sql_saving(var/role_type)
|
|
var/static/list/query_cache
|
|
|
|
// We aren't loading this category. Bye.
|
|
if (role_type && !(sql_role & role_type))
|
|
#ifdef SQL_PREF_DEBUG
|
|
log_debug("SQL CHARACTER SAVE: Bad role_type, returned. Looking for: [role_type], had: [sql_role]. Conjunction: [sql_role & role_type].")
|
|
#endif
|
|
return
|
|
|
|
if (isnull(query_cache))
|
|
query_cache = list()
|
|
|
|
// This handles the generation of queries. One per category, total of 5 UNLESS one category wants to query more than one table.
|
|
// It uses like, 3+ levels of lists. But it works, and is only run once per category in the global sense. So technically, efficient!
|
|
// :D - Skull132
|
|
if (!query_cache.len || isnull(query_cache[type]))
|
|
query_cache[type] = list()
|
|
var/list/tables = list()
|
|
|
|
// First, consolidate the different lists into one.
|
|
for (var/datum/category_item/player_setup_item/PI in items)
|
|
var/list/pi_tables = PI.gather_save_query()
|
|
// Expected layout: list("table A name" = list("var1" = 1, "var2" = 0, "var3" = 1),
|
|
// "table B name" = list("var4" = 0, "var5" = 0, "var6" = 0))
|
|
|
|
for (var/table in pi_tables)
|
|
var/list/A = pi_tables[table]
|
|
if (isnull(tables[table]))
|
|
tables[table] = list()
|
|
|
|
tables[table] |= A
|
|
|
|
// Second, create the queries and save them.
|
|
for (var/table in tables)
|
|
var/query = "INSERT INTO [table] ("
|
|
var/list/var_names = tables[table]
|
|
|
|
query += "[jointext(var_names, ", ")]) VALUES ("
|
|
|
|
// Process the args.
|
|
var/list/arg_names = list()
|
|
for (var/variable in var_names)
|
|
arg_names += ":[variable]:"
|
|
|
|
query += "[jointext(arg_names, ", ")]) ON DUPLICATE KEY UPDATE"
|
|
|
|
var/i = 1
|
|
for (var/variable in var_names)
|
|
if (isnull(var_names[variable]))
|
|
query += " [variable] = [arg_names[i]]"
|
|
|
|
if (i < var_names.len)
|
|
query += ","
|
|
|
|
i++
|
|
|
|
// Remove any potentially damaging commas from the end.
|
|
query = replacetext(query, ",", "", length(query) - 1)
|
|
|
|
#ifdef SQL_PREF_DEBUG
|
|
log_debug("SQL CHARACTER SAVE: Cached query [query].")
|
|
#endif
|
|
|
|
// Save it.
|
|
query_cache[type] += query
|
|
|
|
// Actually utilize the queries.
|
|
var/list/arg_list = gather_save_parameters()
|
|
|
|
#ifdef SQL_PREF_DEBUG
|
|
log_debug("SQL CHARACTER SAVE: Started saving with arguments: [json_encode(arg_list)]. Role type: [role_type]")
|
|
#endif
|
|
|
|
// Typecast the collection so we can access its preferences var.
|
|
var/datum/category_collection/player_setup_collection/cc = collection
|
|
for (var/query_text in query_cache[type])
|
|
var/DBQuery/query = dbcon.NewQuery(query_text)
|
|
query.Execute(arg_list)
|
|
|
|
if (query.ErrorMsg())
|
|
error("SQL CHARACTER SAVE: SQL query error: [query.ErrorMsg()]")
|
|
log_debug("SQL CHARACTER SAVE: SQL query error: [query.ErrorMsg()]")
|
|
log_debug("SQL CHARACTER SAVE: query args: [json_encode(arg_list)]")
|
|
|
|
continue
|
|
|
|
#ifdef SQL_PREF_DEBUG
|
|
else
|
|
log_debug("SQL CHARACTER SAVE: Successfully executed query: [query_text]")
|
|
#endif
|
|
|
|
if ((role_type & SQL_CHARACTER) && !cc.preferences.current_character)
|
|
// No current character, means we're doing insert queries.
|
|
// Quickly nab the new ID and substitute it within the args.
|
|
query = dbcon.NewQuery("SELECT LAST_INSERT_ID() AS new_id")
|
|
query.Execute()
|
|
|
|
if (query.NextRow())
|
|
arg_list["id"] = text2num(query.item[1])
|
|
arg_list["char_id"] = text2num(query.item[1])
|
|
cc.preferences.current_character = text2num(query.item[1])
|
|
|
|
#ifdef SQL_PREF_DEBUG
|
|
log_debug("SQL CHARACTER SAVE: Successfully set character ID to [cc.preferences.current_character]")
|
|
#endif
|
|
|
|
else
|
|
error("SQL CHARACTER SAVE: New ID was not recovered.")
|
|
log_debug("SQL CHARACTER SAVE: New ID was not recovered.")
|
|
if (query.ErrorMsg())
|
|
error("SQL CHARACTER SAVE: SQL query error from last_insert_id: [query.ErrorMsg()]")
|
|
log_debug("SQL CHARACTER SAVE: SQL query error from last_insert_id: [query.ErrorMsg()]")
|
|
|
|
/datum/category_group/player_setup_category/proc/gather_save_parameters()
|
|
var/list/arg_list = list()
|
|
for (var/datum/category_item/player_setup_item/PI in items)
|
|
arg_list |= PI.gather_save_parameters()
|
|
|
|
return arg_list
|