diff --git a/SQL/feedback_schema.sql b/SQL/feedback_schema.sql index a1071363728..bdc1f2c33a6 100644 --- a/SQL/feedback_schema.sql +++ b/SQL/feedback_schema.sql @@ -1,3 +1,4 @@ +-- Table structure for table `erro_admin` CREATE TABLE `erro_admin` ( `id` int(11) NOT NULL AUTO_INCREMENT, `ckey` varchar(32) NOT NULL, @@ -7,6 +8,7 @@ CREATE TABLE `erro_admin` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; +-- Table structure for table `erro_admin_log` CREATE TABLE `erro_admin_log` ( `id` int(11) NOT NULL AUTO_INCREMENT, `datetime` datetime NOT NULL, @@ -16,6 +18,7 @@ CREATE TABLE `erro_admin_log` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; +-- Table structure for table `erro_ban` CREATE TABLE `erro_ban` ( `id` int(11) NOT NULL AUTO_INCREMENT, `bantime` datetime NOT NULL, @@ -43,6 +46,18 @@ CREATE TABLE `erro_ban` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; +-- Table structure for table `erro_connection_log` +CREATE TABLE `erro_connection_log` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `datetime` datetime NOT NULL, + `serverip` varchar(32) NOT NULL, + `ckey` varchar(32) NOT NULL, + `ip` varchar(32) NOT NULL, + `computerid` varchar(32) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; + +-- Table structure for table `erro_feedback` CREATE TABLE `erro_feedback` ( `id` int(11) NOT NULL AUTO_INCREMENT, `time` datetime NOT NULL, @@ -53,6 +68,7 @@ CREATE TABLE `erro_feedback` ( PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; +-- Table structure for table `erro_player` CREATE TABLE `erro_player` ( `id` int(11) NOT NULL AUTO_INCREMENT, `ckey` varchar(32) NOT NULL, @@ -67,6 +83,7 @@ CREATE TABLE `erro_player` ( KEY `discord_id` (`discord_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; +-- Table structure for table `erro_poll_option` CREATE TABLE `erro_poll_option` ( `id` int(11) NOT NULL AUTO_INCREMENT, `pollid` int(11) NOT NULL, @@ -80,6 +97,7 @@ CREATE TABLE `erro_poll_option` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; +-- Table structure for table `erro_poll_question` CREATE TABLE `erro_poll_question` ( `id` int(11) NOT NULL AUTO_INCREMENT, `polltype` varchar(16) NOT NULL DEFAULT 'OPTION', @@ -90,6 +108,7 @@ CREATE TABLE `erro_poll_question` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; +-- Table structure for table `erro_poll_textreply` CREATE TABLE `erro_poll_textreply` ( `id` int(11) NOT NULL AUTO_INCREMENT, `datetime` datetime NOT NULL, @@ -101,6 +120,7 @@ CREATE TABLE `erro_poll_textreply` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; +-- Table structure for table `erro_poll_vote` CREATE TABLE `erro_poll_vote` ( `id` int(11) NOT NULL AUTO_INCREMENT, `datetime` datetime NOT NULL, @@ -113,6 +133,7 @@ CREATE TABLE `erro_poll_vote` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; +-- Table structure for table `erro_privacy` CREATE TABLE `erro_privacy` ( `id` int(11) NOT NULL AUTO_INCREMENT, `datetime` datetime NOT NULL, @@ -121,10 +142,92 @@ CREATE TABLE `erro_privacy` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; +-- Table structure for table `death` +CREATE TABLE `death` ( + `id` INT(11) NOT NULL AUTO_INCREMENT , + `pod` TEXT NOT NULL COMMENT 'Place of death' , + `coord` TEXT NOT NULL COMMENT 'X, Y, Z POD' , + `tod` DATETIME NOT NULL COMMENT 'Time of death' , + `job` TEXT NOT NULL , + `special` TEXT NOT NULL , + `name` TEXT NOT NULL , + `byondkey` TEXT NOT NULL , + `laname` TEXT NOT NULL COMMENT 'Last attacker name' , + `lakey` TEXT NOT NULL COMMENT 'Last attacker key' , + `gender` TEXT NOT NULL , + `bruteloss` INT(11) NOT NULL , + `brainloss` INT(11) NOT NULL , + `fireloss` INT(11) NOT NULL , + `oxyloss` INT(11) NOT NULL , + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; + + +-- Table structure for table `karma` +CREATE TABLE `karma` ( + `id` INT(11) NOT NULL AUTO_INCREMENT , + `spendername` TEXT NOT NULL , + `spenderkey` TEXT NOT NULL , + `receivername` TEXT NOT NULL , + `receiverkey` TEXT NOT NULL , + `receiverrole` TEXT NOT NULL , + `receiverspecial` TEXT NOT NULL , + `isnegative` TINYINT(1) NOT NULL , + `spenderip` TEXT NOT NULL , + `time` DATETIME NOT NULL , + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; + +-- Table structure for table `karmatotals` +CREATE TABLE `karmatotals` ( + `id` INT(11) NOT NULL AUTO_INCREMENT , + `byondkey` TEXT NOT NULL , + `karma` INT(11) NOT NULL , + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; + +-- Table structure for table `library` +CREATE TABLE `library` ( + `id` INT(11) NOT NULL AUTO_INCREMENT , + `author` TEXT NOT NULL , + `title` TEXT NOT NULL , + `content` TEXT NOT NULL , + `category` TEXT NOT NULL , + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; + +-- Table structure for table `population` +CREATE TABLE `population` ( + `id` INT(11) NOT NULL AUTO_INCREMENT , + `playercount` INT(11) NULL DEFAULT NULL , + `admincount` INT(11) NULL DEFAULT NULL , + `time` DATETIME NOT NULL , + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; + +-- Table structure for table `vr_player_hours` CREATE TABLE `vr_player_hours` ( `ckey` varchar(32) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL, `department` varchar(64) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL, `hours` double NOT NULL, `total_hours` double NOT NULL DEFAULT '0', PRIMARY KEY (`ckey`,`department`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; \ No newline at end of file +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +CREATE TABLE IF NOT EXISTS `round` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `initialize_datetime` DATETIME NOT NULL, + `start_datetime` DATETIME NULL, + `shutdown_datetime` DATETIME NULL, + `end_datetime` DATETIME NULL, + `server_ip` INT(10) UNSIGNED NOT NULL, + `server_port` SMALLINT(5) UNSIGNED NOT NULL, + `commit_hash` CHAR(40) NULL, + `game_mode` VARCHAR(32) NULL, + `game_mode_result` VARCHAR(64) NULL, + `end_state` VARCHAR(64) NULL, + `shuttle_name` VARCHAR(64) NULL, + `map_name` VARCHAR(32) NULL, + `station_name` VARCHAR(80) NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; diff --git a/SQL/tgstation_schema.sql b/SQL/tgstation_schema.sql deleted file mode 100644 index b7e2e501ce1..00000000000 --- a/SQL/tgstation_schema.sql +++ /dev/null @@ -1,100 +0,0 @@ -SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; -SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; -SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL'; - -CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ; -CREATE SCHEMA IF NOT EXISTS `tgstation` DEFAULT CHARACTER SET latin1 ; -USE `mydb` ; -USE `tgstation` ; - --- ----------------------------------------------------- --- Table `tgstation`.`death` --- ----------------------------------------------------- -CREATE TABLE IF NOT EXISTS `tgstation`.`death` ( - `id` INT(11) NOT NULL AUTO_INCREMENT , - `pod` TEXT NOT NULL COMMENT 'Place of death' , - `coord` TEXT NOT NULL COMMENT 'X, Y, Z POD' , - `tod` DATETIME NOT NULL COMMENT 'Time of death' , - `job` TEXT NOT NULL , - `special` TEXT NOT NULL , - `name` TEXT NOT NULL , - `byondkey` TEXT NOT NULL , - `laname` TEXT NOT NULL COMMENT 'Last attacker name' , - `lakey` TEXT NOT NULL COMMENT 'Last attacker key' , - `gender` TEXT NOT NULL , - `bruteloss` INT(11) NOT NULL , - `brainloss` INT(11) NOT NULL , - `fireloss` INT(11) NOT NULL , - `oxyloss` INT(11) NOT NULL , - PRIMARY KEY (`id`) ) -ENGINE = MyISAM -AUTO_INCREMENT = 3409 -DEFAULT CHARACTER SET = latin1; - - --- ----------------------------------------------------- --- Table `tgstation`.`karma` --- ----------------------------------------------------- -CREATE TABLE IF NOT EXISTS `tgstation`.`karma` ( - `id` INT(11) NOT NULL AUTO_INCREMENT , - `spendername` TEXT NOT NULL , - `spenderkey` TEXT NOT NULL , - `receivername` TEXT NOT NULL , - `receiverkey` TEXT NOT NULL , - `receiverrole` TEXT NOT NULL , - `receiverspecial` TEXT NOT NULL , - `isnegative` TINYINT(1) NOT NULL , - `spenderip` TEXT NOT NULL , - `time` DATETIME NOT NULL , - PRIMARY KEY (`id`) ) -ENGINE = MyISAM -AUTO_INCREMENT = 943 -DEFAULT CHARACTER SET = latin1; - - --- ----------------------------------------------------- --- Table `tgstation`.`karmatotals` --- ----------------------------------------------------- -CREATE TABLE IF NOT EXISTS `tgstation`.`karmatotals` ( - `id` INT(11) NOT NULL AUTO_INCREMENT , - `byondkey` TEXT NOT NULL , - `karma` INT(11) NOT NULL , - PRIMARY KEY (`id`) ) -ENGINE = MyISAM -AUTO_INCREMENT = 244 -DEFAULT CHARACTER SET = latin1; - - --- ----------------------------------------------------- --- Table `tgstation`.`library` --- ----------------------------------------------------- -CREATE TABLE IF NOT EXISTS `tgstation`.`library` ( - `id` INT(11) NOT NULL AUTO_INCREMENT , - `author` TEXT NOT NULL , - `title` TEXT NOT NULL , - `content` TEXT NOT NULL , - `category` TEXT NOT NULL , - PRIMARY KEY (`id`) ) -ENGINE = MyISAM -AUTO_INCREMENT = 184 -DEFAULT CHARACTER SET = latin1; - - --- ----------------------------------------------------- --- Table `tgstation`.`population` --- ----------------------------------------------------- -CREATE TABLE IF NOT EXISTS `tgstation`.`population` ( - `id` INT(11) NOT NULL AUTO_INCREMENT , - `playercount` INT(11) NULL DEFAULT NULL , - `admincount` INT(11) NULL DEFAULT NULL , - `time` DATETIME NOT NULL , - PRIMARY KEY (`id`) ) -ENGINE = MyISAM -AUTO_INCREMENT = 2544 -DEFAULT CHARACTER SET = latin1; - - - -SET SQL_MODE=@OLD_SQL_MODE; -SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS; -SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS; diff --git a/code/__defines/database.dm b/code/__defines/database.dm new file mode 100644 index 00000000000..3d20b3b9a3c --- /dev/null +++ b/code/__defines/database.dm @@ -0,0 +1,6 @@ +/// When a query has been queued up for execution/is being executed +#define DB_QUERY_STARTED 0 +/// When a query is finished executing +#define DB_QUERY_FINISHED 1 +/// When there was a problem with the execution of a query. +#define DB_QUERY_BROKEN 2 diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm index 8043562a579..0a5b9428e09 100644 --- a/code/__defines/subsystems.dm +++ b/code/__defines/subsystems.dm @@ -118,8 +118,9 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G // The numbers just define the ordering, they are meaningless otherwise. #define INIT_ORDER_SERVER_MAINT 93 #define INIT_ORDER_WEBHOOKS 50 -#define INIT_ORDER_SQLITE 40 -#define INIT_ORDER_GARBAGE 39 +#define INIT_ORDER_SQLITE 41 +#define INIT_ORDER_GARBAGE 40 +#define INIT_ORDER_DBCORE 39 #define INIT_ORDER_MEDIA_TRACKS 38 // Gotta get that lobby music up, yo #define INIT_ORDER_INPUT 37 #define INIT_ORDER_CHEMISTRY 35 diff --git a/code/_global_vars/logging.dm b/code/_global_vars/logging.dm new file mode 100644 index 00000000000..06a240822d9 --- /dev/null +++ b/code/_global_vars/logging.dm @@ -0,0 +1,2 @@ +GLOBAL_VAR(round_id) +GLOBAL_PROTECT(round_id) diff --git a/code/_helpers/logging.dm b/code/_helpers/logging.dm index 05b6ff61582..2157cf4e6da 100644 --- a/code/_helpers/logging.dm +++ b/code/_helpers/logging.dm @@ -30,6 +30,11 @@ if (CONFIG_GET(flag/log_admin)) WRITE_LOG(diary, "ADMIN: [text]") +/proc/log_admin_private(text) + admin_log.Add(text) + if (CONFIG_GET(flag/log_admin)) + WRITE_LOG(diary, "ADMINPRIVATE: [text]") + /proc/log_adminpm(text, client/source, client/dest) admin_log.Add(text) if (CONFIG_GET(flag/log_admin)) @@ -161,6 +166,12 @@ /proc/log_misc(text) WRITE_LOG(diary, "MISC: [text]") +/proc/log_sql(text) + WRITE_LOG(sql_error_log, "SQL: [text]") + +/proc/log_query_debug(text) + WRITE_LOG(query_debug_log, "SQL: [text]") + /proc/log_topic(text) if(Debug2) WRITE_LOG(diary, "TOPIC: [text]") diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm index 910644d63fa..077e4702e4e 100644 --- a/code/_helpers/text.dm +++ b/code/_helpers/text.dm @@ -15,8 +15,13 @@ // Run all strings to be used in an SQL query through this proc first to properly escape out injection attempts. /proc/sanitizeSQL(var/t as text) - var/sqltext = dbcon.Quote(t); - return copytext(sqltext, 2, length(sqltext));//Quote() adds quotes around input, we already do that + //var/sqltext = dbcon.Quote(t); + //return copytext(sqltext, 2, length(sqltext));//Quote() adds quotes around input, we already do that + return t + +/proc/format_table_name(table as text) + //return CONFIG_GET(string/feedback_tableprefix) + table + return table // We don't implement tableprefix /* * Text sanitization diff --git a/code/controllers/configuration/entries/dbconfig.dm b/code/controllers/configuration/entries/dbconfig.dm index d14ca42e68b..2dbc1fb075b 100644 --- a/code/controllers/configuration/entries/dbconfig.dm +++ b/code/controllers/configuration/entries/dbconfig.dm @@ -46,8 +46,8 @@ /datum/config_entry/number/max_concurrent_queries/ValidateAndSet(str_val) . = ..() - //if (.) TODO: ENABLE THIS IN FUTURE DB PRs - //SSdbcore.max_concurrent_queries = config_entry_value TODO: ENABLE THIS IN FUTURE DB PRs + if (.) + SSdbcore.max_concurrent_queries = config_entry_value /// The exe for mariadbd.exe. /// Shouldn't really be set on production servers, primarily for EZDB. diff --git a/code/controllers/subsystems/dbcore.dm b/code/controllers/subsystems/dbcore.dm new file mode 100644 index 00000000000..e800b4aaca3 --- /dev/null +++ b/code/controllers/subsystems/dbcore.dm @@ -0,0 +1,599 @@ +SUBSYSTEM_DEF(dbcore) + name = "Database" + flags = SS_TICKER + wait = 10 // Not seconds because we're running on SS_TICKER + init_order = INIT_ORDER_DBCORE + + var/failed_connection_timeout = 0 + + var/schema_mismatch = 0 + var/db_minor = 0 + var/db_major = 0 + var/failed_connections = 0 + + var/last_error + + var/max_concurrent_queries = 25 + + /// Number of all queries, reset to 0 when logged in SStime_track. Used by SStime_track + var/all_queries_num = 0 + /// Number of active queries, reset to 0 when logged in SStime_track. Used by SStime_track + var/queries_active_num = 0 + /// Number of standby queries, reset to 0 when logged in SStime_track. Used by SStime_track + var/queries_standby_num = 0 + + /// All the current queries that exist. + var/list/all_queries = list() + /// Queries being checked for timeouts. + var/list/processing_queries + + /// Queries currently being handled by database driver + var/list/datum/db_query/queries_active = list() + /// Queries pending execution, mapped to complete arguments + var/list/datum/db_query/queries_standby = list() + + /// We are in the process of shutting down and should not allow more DB connections + var/shutting_down = FALSE + + + var/connection // Arbitrary handle returned from rust_g. + + //var/db_daemon_started = FALSE + +/datum/controller/subsystem/dbcore/Initialize() + return SS_INIT_SUCCESS + +/datum/controller/subsystem/dbcore/stat_entry(msg) + msg = "P:[length(all_queries)]|Active:[length(queries_active)]|Standby:[length(queries_standby)]" + return ..() + +/// Resets the tracking numbers on the subsystem. Used by SStime_track. +/datum/controller/subsystem/dbcore/proc/reset_tracking() + all_queries_num = 0 + queries_active_num = 0 + queries_standby_num = 0 + +/datum/controller/subsystem/dbcore/fire(resumed = FALSE) + if(!IsConnected()) + return + + if(!resumed) + if(!length(queries_active) && !length(queries_standby) && !length(all_queries)) + processing_queries = null + return + processing_queries = all_queries.Copy() + + // First handle the already running queries + for (var/datum/db_query/query in queries_active) + if(!process_query(query)) + queries_active -= query + + // Now lets pull in standby queries if we have room. + if (length(queries_standby) > 0 && length(queries_active) < max_concurrent_queries) + var/list/queries_to_activate = queries_standby.Copy(1, min(length(queries_standby), max_concurrent_queries) + 1) + + for (var/datum/db_query/query in queries_to_activate) + queries_standby.Remove(query) + create_active_query(query) + + // And finally, let check queries for undeleted queries, check ticking if there is a lot of work to do. + while(length(processing_queries)) + var/datum/db_query/query = popleft(processing_queries) + if(world.time - query.last_activity_time > (5 MINUTES)) + stack_trace("Found undeleted query, check the sql.log for the undeleted query and add a delete call to the query datum.") + log_debug("Undeleted query: \"[query.sql]\" LA: [query.last_activity] LAT: [query.last_activity_time]") + qdel(query) + if(MC_TICK_CHECK) + return + + +/// Helper proc for handling activating queued queries +/datum/controller/subsystem/dbcore/proc/create_active_query(datum/db_query/query) + PRIVATE_PROC(TRUE) + SHOULD_NOT_SLEEP(TRUE) + if(IsAdminAdvancedProcCall()) + return FALSE + run_query(query) + queries_active_num++ + queries_active += query + return query + +/datum/controller/subsystem/dbcore/proc/process_query(datum/db_query/query) + PRIVATE_PROC(TRUE) + SHOULD_NOT_SLEEP(TRUE) + if(IsAdminAdvancedProcCall()) + return FALSE + if(QDELETED(query)) + return FALSE + if(query.process((TICKS2DS(wait)) / 10)) + queries_active -= query + return FALSE + return TRUE + +/datum/controller/subsystem/dbcore/proc/run_query_sync(datum/db_query/query) + if(IsAdminAdvancedProcCall()) + return + run_query(query) + UNTIL(query.process()) + return query + +/datum/controller/subsystem/dbcore/proc/run_query(datum/db_query/query) + if(IsAdminAdvancedProcCall()) + return + query.job_id = rustg_sql_query_async(connection, query.sql, json_encode(query.arguments)) + +/datum/controller/subsystem/dbcore/proc/queue_query(datum/db_query/query) + if(IsAdminAdvancedProcCall()) + return + + if (!length(queries_standby) && length(queries_active) < max_concurrent_queries) + create_active_query(query) + return + + queries_standby_num++ + queries_standby |= query + +/datum/controller/subsystem/dbcore/Recover() + connection = SSdbcore.connection + +/datum/controller/subsystem/dbcore/Shutdown() + shutting_down = TRUE + log_debug("Clearing DB queries standby:[length(queries_standby)] active: [length(queries_active)] all: [length(all_queries)]") + //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()) + //Execute all waiting queries + for(var/datum/db_query/query in queries_standby) + run_query_sync(query) + queries_standby -= query + for(var/datum/db_query/query in queries_active) + //Finish any remaining active qeries + UNTIL(query.process()) + queries_active -= query + + var/datum/db_query/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), + list("end_state" = "undefined", "round_id" = GLOB.round_id), // FIXME: end_state does not exist on ticker + TRUE + ) + query_round_shutdown.Execute(FALSE) + qdel(query_round_shutdown) + + log_debug("Done clearing DB queries standby:[length(queries_standby)] active: [length(queries_active)] all: [length(all_queries)]") + if(IsConnected()) + Disconnect() + //stop_db_daemon() + +//nu +/datum/controller/subsystem/dbcore/can_vv_get(var_name) + if(var_name == NAMEOF(src, connection)) + return FALSE + if(var_name == NAMEOF(src, all_queries)) + return FALSE + if(var_name == NAMEOF(src, queries_active)) + return FALSE + if(var_name == NAMEOF(src, queries_standby)) + return FALSE + if(var_name == NAMEOF(src, processing_queries)) + return FALSE + + return ..() + +/datum/controller/subsystem/dbcore/vv_edit_var(var_name, var_value) + if(var_name == NAMEOF(src, connection)) + return FALSE + if(var_name == NAMEOF(src, all_queries)) + return FALSE + if(var_name == NAMEOF(src, queries_active)) + return FALSE + if(var_name == NAMEOF(src, queries_standby)) + return FALSE + if(var_name == NAMEOF(src, processing_queries)) + return FALSE + return ..() + +/datum/controller/subsystem/dbcore/proc/Connect() + if(IsConnected()) + return TRUE + + if(failed_connection_timeout <= world.time) //it's been more than 5 seconds since we failed to connect, reset the counter + failed_connections = 0 + + if(failed_connections > 5) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to connect for 5 seconds. + failed_connection_timeout = world.time + 50 + return FALSE + + if(!CONFIG_GET(flag/sql_enabled)) + return FALSE + + //start_db_daemon() + + var/user = CONFIG_GET(string/feedback_login) + var/pass = CONFIG_GET(string/feedback_password) + 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/min_sql_connections = CONFIG_GET(number/pooling_min_sql_connections) + var/max_sql_connections = CONFIG_GET(number/pooling_max_sql_connections) + + var/result = json_decode(rustg_sql_connect_pool(json_encode(list( + "host" = address, + "port" = port, + "user" = user, + "pass" = pass, + "db_name" = db, + "read_timeout" = timeout, + "write_timeout" = timeout, + "min_threads" = min_sql_connections, + "max_threads" = max_sql_connections, + )))) + . = (result["status"] == "ok") + if (.) + connection = result["handle"] + else + connection = null + last_error = result["data"] + log_debug("Connect() failed | [last_error]") + ++failed_connections + +/datum/controller/subsystem/dbcore/proc/CheckSchemaVersion() + if(CONFIG_GET(flag/sql_enabled)) + if(Connect()) + log_world("Database connection established.") + else + log_debug("Your server failed to establish a connection with the database.") + else + log_debug("Database is not enabled in configuration.") + +/datum/controller/subsystem/dbcore/proc/InitializeRound() + if(!Connect()) + return + var/datum/db_query/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]" + qdel(query_round_initialize) + +/datum/controller/subsystem/dbcore/proc/SetRoundStart() + if(!Connect()) + return + var/datum/db_query/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/datum/db_query/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) + list("game_mode_result" = "extended", "station_name" = station_name(), "round_id" = GLOB.round_id) // FIXME: temporary solution as we only use extended so far + ) + query_round_end.Execute() + qdel(query_round_end) + +/datum/controller/subsystem/dbcore/proc/Disconnect() + failed_connections = 0 + if (connection) + rustg_sql_disconnect_pool(connection) + connection = null + +/datum/controller/subsystem/dbcore/proc/IsConnected() + if (!CONFIG_GET(flag/sql_enabled)) + return FALSE + 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)) + return "Database disabled by configuration" + return last_error + +/datum/controller/subsystem/dbcore/proc/ReportError(error) + last_error = error + +/datum/controller/subsystem/dbcore/proc/NewQuery(sql_query, arguments, allow_during_shutdown=FALSE) + //If the subsystem is shutting down, disallow new queries + if(!allow_during_shutdown && shutting_down) + CRASH("Attempting to create a new db query during the world shutdown") + + if(IsAdminAdvancedProcCall()) + log_admin("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/db_query(connection, sql_query, arguments) + +/** QuerySelect + Run a list of query datums in parallel, blocking until they all complete. + * queries - List of queries or single query datum to run. + * warn - Controls rather warn_execute() or Execute() is called. + * qdel - If you don't care about the result or checking for errors, you can have the queries be deleted afterwards. + This can be combined with invoke_async as a way of running queries async without having to care about waiting for them to finish so they can be deleted. +*/ +/datum/controller/subsystem/dbcore/proc/QuerySelect(list/queries, warn = FALSE, qdel = FALSE) + if (!islist(queries)) + if (!istype(queries, /datum/db_query)) + CRASH("Invalid query passed to QuerySelect: [queries]") + queries = list(queries) + else + queries = queries.Copy() //we don't want to hide bugs in the parent caller by removing invalid values from this list. + + for (var/datum/db_query/query as anything in queries) + if (!istype(query)) + queries -= query + stack_trace("Invalid query passed to QuerySelect: `[query]` [REF(query)]") + continue + + if (warn) + INVOKE_ASYNC(query, TYPE_PROC_REF(/datum/db_query, warn_execute)) + else + INVOKE_ASYNC(query, TYPE_PROC_REF(/datum/db_query, Execute)) + + for (var/datum/db_query/query as anything in queries) + query.sync() + if (qdel) + qdel(query) + + + +/* +Takes a list of rows (each row being an associated list of column => value) and inserts them via a single mass query. +Rows missing columns present in other rows will resolve to SQL NULL +You are expected to do your own escaping of the data, and expected to provide your own quotes for strings. +The duplicate_key arg can be true to automatically generate this part of the query + or set to a string that is appended to the end of the query +Ignore_errors instructes mysql to continue inserting rows if some of them have errors. + the erroneous row(s) aren't inserted and there isn't really any way to know why or why errored +*/ +/datum/controller/subsystem/dbcore/proc/MassInsert(table, list/rows, duplicate_key = FALSE, ignore_errors = FALSE, warn = FALSE, async = TRUE, special_columns = null) + if (!table || !rows || !istype(rows)) + return + + // Prepare column list + var/list/columns = list() + var/list/has_question_mark = list() + for (var/list/row in rows) + for (var/column in row) + 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], "?") + + // Prepare SQL query full of placeholders + var/list/query_parts = list("INSERT") + 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])" + query_parts += "\nON DUPLICATE KEY UPDATE [column_list.Join(", ")]" + else if (duplicate_key != FALSE) + query_parts += duplicate_key + + var/datum/db_query/Query = NewQuery(query_parts.Join(), arguments) + if (warn) + . = Query.warn_execute(async) + else + . = Query.Execute(async) + qdel(Query) + +/* +/datum/controller/subsystem/dbcore/proc/start_db_daemon() + set waitfor = FALSE + + if (db_daemon_started) + return + + db_daemon_started = TRUE + + var/daemon = CONFIG_GET(string/db_daemon) + if (!daemon) + return + + ASSERT(fexists(daemon)) + + var/list/result = world.shelleo("echo \"Starting ezdb daemon, do not close this window\" && [daemon]") + var/result_code = result[1] + if (!result_code || result_code == 1) + return + + stack_trace("Failed to start DB daemon: [result_code]\n[result[3]]") + +/datum/controller/subsystem/dbcore/proc/stop_db_daemon() + set waitfor = FALSE + + if (!db_daemon_started) + return + + db_daemon_started = FALSE + + var/daemon = CONFIG_GET(string/db_daemon) + if (!daemon) + return + + switch (world.system_type) + if (MS_WINDOWS) + var/list/result = world.shelleo("Get-Process | ? { $_.Path -eq '[daemon]' } | Stop-Process") + ASSERT(result[1]) + if (UNIX) + var/list/result = world.shelleo("kill $(pgrep -f '[daemon]')") + ASSERT(result[1]) +*/ + +/datum/db_query + // Inputs + var/connection + var/sql + var/arguments + + var/datum/callback/success_callback + var/datum/callback/fail_callback + + // Status information + /// Current status of the query. + var/status + /// Job ID of the query passed by rustg. + var/job_id + var/last_error + var/last_activity + var/last_activity_time + + // Output + var/list/list/rows + var/next_row_to_take = 1 + var/affected + var/last_insert_id + + var/list/item //list of data values populated by NextRow() + +/datum/db_query/New(connection, sql, arguments) + SSdbcore.all_queries += src + SSdbcore.all_queries_num++ + Activity("Created") + item = list() + + src.connection = connection + src.sql = sql + src.arguments = arguments + +/datum/db_query/Destroy() + Close() + SSdbcore.all_queries -= src + SSdbcore.queries_standby -= src + SSdbcore.queries_active -= src + return ..() + +/datum/db_query/CanProcCall(proc_name) + return FALSE + +/datum/db_query/proc/Activity(activity) + last_activity = activity + last_activity_time = world.time + +/datum/db_query/proc/warn_execute(async = TRUE) + . = Execute(async) + if(!.) + to_chat(usr, span_danger("A SQL error occurred during this operation, check the server logs.")) + +/datum/db_query/proc/Execute(async = TRUE, log_error = TRUE) + Activity("Execute") + if(status == DB_QUERY_STARTED) + CRASH("Attempted to start a new query while waiting on the old one") + + if(!SSdbcore.IsConnected()) + last_error = "No connection!" + return FALSE + + var/start_time + if(!async) + start_time = REALTIMEOFDAY + Close() + status = DB_QUERY_STARTED + if(async) + /*if(!MC_RUNNING(SSdbcore.init_stage)) + SSdbcore.run_query_sync(src) + else + SSdbcore.queue_query(src)*/ + SSdbcore.run_query_sync(src) + sync() + else + var/job_result_str = rustg_sql_query_blocking(connection, sql, json_encode(arguments)) + store_data(json_decode(job_result_str)) + + . = (status != DB_QUERY_BROKEN) + var/timed_out = !. && findtext(last_error, "Operation timed out") + if(!. && log_error) + log_debug("[last_error] | Query used: [sql] | Arguments: [json_encode(arguments)]") + if(!async && timed_out) + log_debug("Query execution started at [start_time]") + log_debug("Query execution ended at [REALTIMEOFDAY]") + log_debug("Slow query timeout detected.") + log_debug("Query used: [sql]") + slow_query_check() + +/// Sleeps until execution of the query has finished. +/datum/db_query/proc/sync() + while(status < DB_QUERY_FINISHED) + stoplag() + +/datum/db_query/process(seconds_per_tick) + if(status >= DB_QUERY_FINISHED) + return TRUE // we are done processing after all + + status = DB_QUERY_STARTED + var/job_result = rustg_sql_check_query(job_id) + if(job_result == RUSTG_JOB_NO_RESULTS_YET) + return FALSE //no results yet + + store_data(json_decode(job_result)) + return TRUE + +/datum/db_query/proc/store_data(result) + switch(result["status"]) + if("ok") + rows = result["rows"] + affected = result["affected"] + last_insert_id = result["last_insert_id"] + status = DB_QUERY_FINISHED + return + if("err") + last_error = result["data"] + status = DB_QUERY_BROKEN + return + if("offline") + last_error = "CONNECTION OFFLINE" + status = DB_QUERY_BROKEN + return + +/datum/db_query/proc/slow_query_check() + message_admins("HEY! A database query timed out. Did the server just hang? \[YES\]|\[NO\]") + +/datum/db_query/proc/NextRow(async = TRUE) + Activity("NextRow") + + if (rows && next_row_to_take <= rows.len) + item = rows[next_row_to_take] + next_row_to_take++ + return !!item + else + return FALSE + +/datum/db_query/proc/ErrorMsg() + return last_error + +/datum/db_query/proc/Close() + rows = null + item = null diff --git a/code/controllers/subsystems/persist_vr.dm b/code/controllers/subsystems/persist_vr.dm index d74b96f9603..c6eda65ef46 100644 --- a/code/controllers/subsystems/persist_vr.dm +++ b/code/controllers/subsystems/persist_vr.dm @@ -10,6 +10,7 @@ SUBSYSTEM_DEF(persist) flags = SS_BACKGROUND|SS_NO_INIT|SS_KEEP_TIMING runlevels = RUNLEVEL_GAME|RUNLEVEL_POSTGAME var/list/currentrun = list() + var/list/query_stack = list() /datum/controller/subsystem/persist/fire(var/resumed = FALSE) update_department_hours(resumed) @@ -20,7 +21,7 @@ SUBSYSTEM_DEF(persist) return establish_db_connection() - if(!dbcon.IsConnected()) + if(!SSdbcore.IsConnected()) src.currentrun.Cut() return if(!resumed) @@ -29,6 +30,7 @@ SUBSYSTEM_DEF(persist) //cache for sanic speed (lists are references anyways) var/list/currentrun = src.currentrun + var/list/query_stack = src.query_stack while (currentrun.len) var/mob/M = currentrun[currentrun.len] currentrun.len-- @@ -85,12 +87,21 @@ SUBSYSTEM_DEF(persist) var/sql_dpt = sql_sanitize_text(department_earning) var/sql_bal = text2num("[C.department_hours[department_earning]]") var/sql_total = text2num("[C.play_hours[department_earning]]") - var/DBQuery/query = dbcon.NewQuery("INSERT INTO vr_player_hours (ckey, department, hours, total_hours) VALUES ('[sql_ckey]', '[sql_dpt]', [sql_bal], [sql_total]) ON DUPLICATE KEY UPDATE hours = VALUES(hours), total_hours = VALUES(total_hours)") - query.Execute() + var/list/entry = list( + "ckey" = sql_ckey, + "department" = sql_dpt, + "hours" = sql_bal, + "total_hours" = sql_total + ) + query_stack += list(entry) if (MC_TICK_CHECK) return + if(query_stack.len) + SSdbcore.MassInsert(format_table_name("vr_player_hours"), query_stack, duplicate_key = "ON DUPLICATE KEY UPDATE hours = VALUES(hours), total_hours = VALUES(total_hours)") + query_stack.Cut() + // This proc tries to find the job datum of an arbitrary mob. /datum/controller/subsystem/persist/proc/detect_job(var/mob/M) // Records are usually the most reliable way to get what job someone is. diff --git a/code/controllers/subsystems/statpanel.dm b/code/controllers/subsystems/statpanel.dm index 8383f0a3d7d..fa045838ee7 100644 --- a/code/controllers/subsystems/statpanel.dm +++ b/code/controllers/subsystems/statpanel.dm @@ -31,7 +31,7 @@ SUBSYSTEM_DEF(statpanels) "Map: [using_map.name]", //cached ? "Next Map: [cached.map_name]" : null, //"Next Map: -- Not Available --", - // "Round ID: [GLOB.round_id ? GLOB.round_id : "NULL"]", + "Round ID: [GLOB.round_id ? GLOB.round_id : "NULL"]", "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]", "Round Time: [roundduration2text()]", "Station Date: [stationdate2text()]", // [capitalize(GLOB.world_time_season)]", diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm index 8a8e35d73d3..9df8da605f9 100644 --- a/code/controllers/subsystems/ticker.dm +++ b/code/controllers/subsystems/ticker.dm @@ -546,6 +546,8 @@ var/global/datum/controller/subsystem/ticker/ticker for(var/i in total_antagonists) log_game("[i]s[total_antagonists[i]].") + SSdbcore.SetRoundEnd() + return 1 /datum/controller/subsystem/ticker/stat_entry(msg) diff --git a/code/defines/procs/dbcore.dm b/code/defines/procs/dbcore.dm deleted file mode 100644 index 9367b269643..00000000000 --- a/code/defines/procs/dbcore.dm +++ /dev/null @@ -1,208 +0,0 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -//cursors -#define Default_Cursor 0 -#define Client_Cursor 1 -#define Server_Cursor 2 -//conversions -#define TEXT_CONV 1 -#define RSC_FILE_CONV 2 -#define NUMBER_CONV 3 -//column flag values: -#define IS_NUMERIC 1 -#define IS_BINARY 2 -#define IS_NOT_NULL 4 -#define IS_PRIMARY_KEY 8 -#define IS_UNSIGNED 16 -//types -#define TINYINT 1 -#define SMALLINT 2 -#define MEDIUMINT 3 -#define INTEGER 4 -#define BIGINT 5 -#define DECIMAL 6 -#define FLOAT 7 -#define DOUBLE 8 -#define DATE 9 -#define DATETIME 10 -#define TIMESTAMP 11 -#define TIME 12 -#define STRING 13 -#define BLOB 14 -// TODO: Investigate more recent type additions and see if I can handle them. - Nadrew - - -// Deprecated! See global.dm for new configuration vars -/* -var/DB_SERVER = "" // This is the location of your MySQL server (localhost is USUALLY fine) -var/DB_PORT = 3306 // This is the port your MySQL server is running on (3306 is the default) -*/ - -/DBConnection - var/_db_con // This variable contains a reference to the actual database connection. - var/dbi // This variable is a string containing the DBI MySQL requires. - var/user // This variable contains the username data. - var/password // This variable contains the password data. - var/default_cursor // This contains the default database cursor data. - // - var/server = "" - var/port = 3306 - -/DBConnection/New(dbi_handler,username,password_handler,cursor_handler) - src.dbi = dbi_handler - src.user = username - src.password = password_handler - src.default_cursor = cursor_handler - _db_con = _dm_db_new_con() - -/DBConnection/proc/Connect(dbi_handler=src.dbi,user_handler=src.user,password_handler=src.password,cursor_handler) - if(!CONFIG_GET(flag/sql_enabled)) - return 0 - if(!src) return 0 - cursor_handler = src.default_cursor - if(!cursor_handler) cursor_handler = Default_Cursor - return _dm_db_connect(_db_con,dbi_handler,user_handler,password_handler,cursor_handler,null) - -/DBConnection/proc/Disconnect() return _dm_db_close(_db_con) - -/DBConnection/proc/IsConnected() - if(!CONFIG_GET(flag/sql_enabled)) return 0 - var/success = _dm_db_is_connected(_db_con) - return success - -/DBConnection/proc/Quote(str) return _dm_db_quote(_db_con,str) - -/DBConnection/proc/ErrorMsg() return _dm_db_error_msg(_db_con) -/DBConnection/proc/SelectDB(database_name,dbi) - if(IsConnected()) Disconnect() - //return Connect("[dbi?"[dbi]":"dbi:mysql:[database_name]:[DB_SERVER]:[DB_PORT]"]",user,password) - return Connect("[dbi?"[dbi]":"dbi:mysql:[database_name]:[CONFIG_GET(string/address)]:[CONFIG_GET(number/port)]"]",user,password) -/DBConnection/proc/NewQuery(sql_query,cursor_handler=src.default_cursor) return new/DBQuery(sql_query,src,cursor_handler) - - -/DBQuery/New(sql_query,DBConnection/connection_handler,cursor_handler) - if(sql_query) src.sql = sql_query - if(connection_handler) src.db_connection = connection_handler - if(cursor_handler) src.default_cursor = cursor_handler - _db_query = _dm_db_new_query() - return ..() - - -/DBQuery - var/sql // The sql query being executed. - var/default_cursor - var/list/columns //list of DB Columns populated by Columns() - var/list/conversions - var/list/item[0] //list of data values populated by NextRow() - - var/DBConnection/db_connection - var/_db_query - -/DBQuery/proc/Connect(DBConnection/connection_handler) src.db_connection = connection_handler - -/DBQuery/proc/Execute(sql_query=src.sql,cursor_handler=default_cursor) - Close() - return _dm_db_execute(_db_query,sql_query,db_connection._db_con,cursor_handler,null) - -/DBQuery/proc/NextRow() return _dm_db_next_row(_db_query,item,conversions) - -/DBQuery/proc/RowsAffected() return _dm_db_rows_affected(_db_query) - -/DBQuery/proc/RowCount() return _dm_db_row_count(_db_query) - -/DBQuery/proc/ErrorMsg() return _dm_db_error_msg(_db_query) - -/DBQuery/proc/Columns() - if(!columns) - columns = _dm_db_columns(_db_query,/DBColumn) - return columns - -/DBQuery/proc/GetRowData() - var/list/columns = Columns() - var/list/results - if(columns.len) - results = list() - for(var/C in columns) - results+=C - var/DBColumn/cur_col = columns[C] - results[C] = src.item[(cur_col.position+1)] - return results - -/DBQuery/proc/Close() - item.len = 0 - columns = null - conversions = null - return _dm_db_close(_db_query) - -/DBQuery/proc/Quote(str) - return db_connection.Quote(str) - -/DBQuery/proc/SetConversion(column,conversion) - if(istext(column)) column = columns.Find(column) - if(!conversions) conversions = new/list(column) - else if(conversions.len < column) conversions.len = column - conversions[column] = conversion - - -/DBColumn - var/name - var/table - var/position //1-based index into item data - var/sql_type - var/flags - var/length - var/max_length - -/DBColumn/New(name_handler,table_handler,position_handler,type_handler,flag_handler,length_handler,max_length_handler) - src.name = name_handler - src.table = table_handler - src.position = position_handler - src.sql_type = type_handler - src.flags = flag_handler - src.length = length_handler - src.max_length = max_length_handler - return ..() - - -/DBColumn/proc/SqlTypeName(type_handler=src.sql_type) - switch(type_handler) - if(TINYINT) return "TINYINT" - if(SMALLINT) return "SMALLINT" - if(MEDIUMINT) return "MEDIUMINT" - if(INTEGER) return "INTEGER" - if(BIGINT) return "BIGINT" - if(FLOAT) return "FLOAT" - if(DOUBLE) return "DOUBLE" - if(DATE) return "DATE" - if(DATETIME) return "DATETIME" - if(TIMESTAMP) return "TIMESTAMP" - if(TIME) return "TIME" - if(STRING) return "STRING" - if(BLOB) return "BLOB" - - -#undef Default_Cursor -#undef Client_Cursor -#undef Server_Cursor -#undef TEXT_CONV -#undef RSC_FILE_CONV -#undef NUMBER_CONV -#undef IS_NUMERIC -#undef IS_BINARY -#undef IS_NOT_NULL -#undef IS_PRIMARY_KEY -#undef IS_UNSIGNED -#undef TINYINT -#undef SMALLINT -#undef MEDIUMINT -#undef INTEGER -#undef BIGINT -#undef DECIMAL -#undef FLOAT -#undef DOUBLE -#undef DATE -#undef DATETIME -#undef TIMESTAMP -#undef TIME -#undef STRING -#undef BLOB diff --git a/code/defines/procs/statistics.dm b/code/defines/procs/statistics.dm index d11864fc755..0f1278ee302 100644 --- a/code/defines/procs/statistics.dm +++ b/code/defines/procs/statistics.dm @@ -7,14 +7,15 @@ if(M.client) playercount += 1 establish_db_connection() - if(!dbcon.IsConnected()) + if(!SSdbcore.IsConnected()) log_game("SQL ERROR during population polling. Failed to connect.") else var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO `tgstation`.`population` (`playercount`, `admincount`, `time`) VALUES ([playercount], [admincount], '[sqltime]')") + var/datum/db_query/query = SSdbcore.NewQuery("INSERT INTO population ('playercount', 'admincount', 'time') VALUES ([playercount], [admincount], '[sqltime]')") if(!query.Execute()) var/err = query.ErrorMsg() log_game("SQL ERROR during population polling. Error : \[[err]\]\n") + qdel(query) /proc/sql_report_round_start() // TODO @@ -50,13 +51,14 @@ var/coord = "[H.x], [H.y], [H.z]" //to_world("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.bruteloss], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()])") establish_db_connection() - if(!dbcon.IsConnected()) + if(!SSdbcore.IsConnected()) log_game("SQL ERROR during death reporting. Failed to connect.") else - var/DBQuery/query = dbcon.NewQuery("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')") + var/datum/db_query/query = SSdbcore.NewQuery("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')") if(!query.Execute()) var/err = query.ErrorMsg() log_game("SQL ERROR during death reporting. Error : \[[err]\]\n") + qdel(query) /proc/sql_report_cyborg_death(var/mob/living/silicon/robot/H) @@ -84,13 +86,14 @@ var/coord = "[H.x], [H.y], [H.z]" //to_world("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.bruteloss], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()])") establish_db_connection() - if(!dbcon.IsConnected()) + if(!SSdbcore.IsConnected()) log_game("SQL ERROR during death reporting. Failed to connect.") else - var/DBQuery/query = dbcon.NewQuery("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')") + var/datum/db_query/query = SSdbcore.NewQuery("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')") if(!query.Execute()) var/err = query.ErrorMsg() log_game("SQL ERROR during death reporting. Error : \[[err]\]\n") + qdel(query) /proc/statistic_cycle() @@ -115,11 +118,11 @@ return establish_db_connection() - if(!dbcon.IsConnected()) + if(!SSdbcore.IsConnected()) log_game("SQL ERROR during feedback reporting. Failed to connect.") else - var/DBQuery/max_query = dbcon.NewQuery("SELECT MAX(roundid) AS max_round_id FROM erro_feedback") + var/datum/db_query/max_query = SSdbcore.NewQuery("SELECT MAX(roundid) AS max_round_id FROM erro_feedback") max_query.Execute() var/newroundid @@ -139,7 +142,7 @@ var/variable = item.get_variable() var/value = item.get_value() - var/DBQuery/query = dbcon.NewQuery("INSERT INTO erro_feedback (id, roundid, time, variable, value) VALUES (null, [newroundid], Now(), '[variable]', '[value]')") + var/datum/db_query/query = SSdbcore.NewQuery("INSERT INTO erro_feedback (id, roundid, time, variable, value) VALUES (null, [newroundid], Now(), '[variable]', '[value]')") if(!query.Execute()) var/err = query.ErrorMsg() log_game("SQL ERROR during death reporting. Error : \[[err]\]\n") diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 937cbb0777d..e67d622167d 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -218,6 +218,7 @@ var/global/list/additional_antag_types = list() emergency_shuttle.auto_recall = 1 feedback_set_details("round_start","[time2text(world.realtime)]") + INVOKE_ASYNC(SSdbcore, TYPE_PROC_REF(/datum/controller/subsystem/dbcore, SetRoundStart)) if(ticker && ticker.mode) feedback_set_details("game_mode","[ticker.mode]") feedback_set_details("server_ip","[world.internet_address]:[world.port]") diff --git a/code/game/machinery/records_scanner.dm b/code/game/machinery/records_scanner.dm index e6aeb521e5d..3ff97f160e5 100644 --- a/code/game/machinery/records_scanner.dm +++ b/code/game/machinery/records_scanner.dm @@ -51,7 +51,7 @@ var/age = user.age var/gender = user.gender /* no dbstuff yet - var/DBQuery/cquery = dbcon.NewQuery("SELECT * from jobban WHERE ckey='[user.ckey]'") + var/datum/DBQuery/cquery = SSdbcore.NewQuery("SELECT * from jobban WHERE ckey='[user.ckey]'") if(!cquery.Execute()) return else while(cquery.NextRow()) diff --git a/code/game/magic/archived_book.dm b/code/game/magic/archived_book.dm index 958c96e9224..86a9620c224 100644 --- a/code/game/magic/archived_book.dm +++ b/code/game/magic/archived_book.dm @@ -53,13 +53,13 @@ var/global/datum/book_manager/book_mgr = new() dat += "
| TITLE | \[Del\]" dat += " |
| TITLE | Now()")
+ var/datum/db_query/query1 = SSdbcore.NewQuery("SELECT ckey, job FROM erro_ban WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()")
query1.Execute()
while(query1.NextRow())
diff --git a/code/modules/admin/permissionverbs/permissionedit.dm b/code/modules/admin/permissionverbs/permissionedit.dm
index b85e76e4d54..cbb1e9f7290 100644
--- a/code/modules/admin/permissionverbs/permissionedit.dm
+++ b/code/modules/admin/permissionverbs/permissionedit.dm
@@ -56,7 +56,7 @@
establish_db_connection()
- if(!dbcon.IsConnected())
+ if(!SSdbcore.IsConnected())
to_chat(usr, span_filter_adminlog("[span_red("Failed to establish database connection")]"))
return
@@ -71,7 +71,7 @@
if(!istext(adm_ckey) || !istext(new_rank))
return
- var/DBQuery/select_query = dbcon.NewQuery("SELECT id FROM erro_admin WHERE ckey = '[adm_ckey]'")
+ var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT id FROM erro_admin WHERE ckey = '[adm_ckey]'")
select_query.Execute()
var/new_admin = 1
@@ -81,16 +81,16 @@
admin_id = text2num(select_query.item[1])
if(new_admin)
- var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO `erro_admin` (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)")
+ var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO `erro_admin` (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)")
insert_query.Execute()
- var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');")
+ var/datum/db_query/log_query = SSdbcore.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');")
log_query.Execute()
to_chat(usr, span_filter_adminlog("[span_blue("New admin added.")]"))
else
if(!isnull(admin_id) && isnum(admin_id))
- var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET rank = '[new_rank]' WHERE id = [admin_id]")
+ var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE `erro_admin` SET rank = '[new_rank]' WHERE id = [admin_id]")
insert_query.Execute()
- var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');")
+ var/datum/db_query/log_query = SSdbcore.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');")
log_query.Execute()
to_chat(usr, span_filter_adminlog("[span_blue("Admin rank changed.")]"))
@@ -105,7 +105,7 @@
return
establish_db_connection()
- if(!dbcon.IsConnected())
+ if(!SSdbcore.IsConnected())
to_chat(usr, span_filter_adminlog("[span_red("Failed to establish database connection!")]"))
return
@@ -123,7 +123,7 @@
if(!istext(adm_ckey) || !isnum(new_permission))
return
- var/DBQuery/select_query = dbcon.NewQuery("SELECT id, flags FROM erro_admin WHERE ckey = '[adm_ckey]'")
+ var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT id, flags FROM erro_admin WHERE ckey = '[adm_ckey]'")
select_query.Execute()
var/admin_id
@@ -136,14 +136,14 @@
return
if(admin_rights & new_permission) //This admin already has this permission, so we are removing it.
- var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]")
+ var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE `erro_admin` SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]")
insert_query.Execute()
- var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');")
+ var/datum/db_query/log_query = SSdbcore.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');")
log_query.Execute()
to_chat(usr, span_filter_adminlog("[span_blue("Permission removed.")]"))
else //This admin doesn't have this permission, so we are adding it.
- var/DBQuery/insert_query = dbcon.NewQuery("UPDATE `erro_admin` SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]")
+ var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE `erro_admin` SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]")
insert_query.Execute()
- var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')")
+ var/datum/db_query/log_query = SSdbcore.NewQuery("INSERT INTO `test`.`erro_admin_log` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')")
log_query.Execute()
to_chat(usr, span_filter_adminlog("[span_blue("Permission added.")]"))
diff --git a/code/modules/admin/verbs/check_customitem_activity.dm b/code/modules/admin/verbs/check_customitem_activity.dm
index 89be5ba6520..003a3da3776 100644
--- a/code/modules/admin/verbs/check_customitem_activity.dm
+++ b/code/modules/admin/verbs/check_customitem_activity.dm
@@ -30,7 +30,7 @@ var/inactive_keys = "None " return establish_db_connection() - if(!dbcon.IsConnected()) + if(!SSdbcore.IsConnected()) return //grab all ckeys associated with custom items @@ -55,7 +55,7 @@ var/inactive_keys = "None " //run a query to get all ckeys inactive for over 2 months var/list/inactive_ckeys = list() if(ckeys_with_customitems.len) - var/DBQuery/query_inactive = dbcon.NewQuery("SELECT ckey, lastseen FROM erro_player WHERE datediff(Now(), lastseen) > 60") + var/datum/db_query/query_inactive = SSdbcore.NewQuery("SELECT ckey, lastseen FROM erro_player WHERE datediff(Now(), lastseen) > 60") query_inactive.Execute() while(query_inactive.NextRow()) var/cur_ckey = query_inactive.item[1] @@ -67,9 +67,9 @@ var/inactive_keys = "None " //if there are ckeys left over, check whether they have a database entry at all if(ckeys_with_customitems.len) for(var/cur_ckey in ckeys_with_customitems) - var/DBQuery/query_inactive = dbcon.NewQuery("SELECT ckey FROM erro_player WHERE ckey = '[cur_ckey]'") + var/datum/db_query/query_inactive = SSdbcore.NewQuery("SELECT ckey FROM erro_player WHERE ckey = '[cur_ckey]'") query_inactive.Execute() - if(!query_inactive.RowCount()) + if(!query_inactive.rows) inactive_ckeys += cur_ckey if(inactive_ckeys.len) diff --git a/code/modules/admin/verbs/dbcon_fix.dm b/code/modules/admin/verbs/dbcon_fix.dm index 1d523145202..99deb034a72 100644 --- a/code/modules/admin/verbs/dbcon_fix.dm +++ b/code/modules/admin/verbs/dbcon_fix.dm @@ -10,30 +10,30 @@ return FALSE log_admin("Attempting to fix database connection") - if(dbcon.IsConnected()) - dbcon.Disconnect() + if(SSdbcore.IsConnected()) + SSdbcore.Disconnect() else log_admin("Database already disconnected") - + establish_db_connection() - var/errno = dbcon.ErrorMsg() + var/errno = SSdbcore.ErrorMsg() if(errno) log_admin("Database connection returned error message `[errno]`. Aborting.") return FALSE - if(!dbcon.IsConnected()) + if(!SSdbcore.IsConnected()) log_admin("Database could not be reconnected! Aborting.") return FALSE - log_admin("Database reconnected. Fixing player ages...") + log_admin("Database reconnected. Fixing player ages...") var/num = 0 for(var/client/C in GLOB.clients) C.log_client_to_db() - errno = dbcon.ErrorMsg() + errno = SSdbcore.ErrorMsg() if(errno) log_admin("Database connection returned error message `[errno]` after adjusting player ages for [num] players. [C] was being updated when the error struck. Aborting.") return FALSE if(C.player_age) num++ - + log_admin("Successfully updated non-0 player age for [num] clients.") - return FALSE \ No newline at end of file + return FALSE diff --git a/code/modules/admin/verbs/panicbunker.dm b/code/modules/admin/verbs/panicbunker.dm index c153eda9581..4b2722995e3 100644 --- a/code/modules/admin/verbs/panicbunker.dm +++ b/code/modules/admin/verbs/panicbunker.dm @@ -12,7 +12,7 @@ CONFIG_SET(flag/panic_bunker, !CONFIG_GET(flag/panic_bunker)) log_and_message_admins("has toggled the Panic Bunker, it is now [(CONFIG_GET(flag/panic_bunker) ? "on":"off")].", src) - if (CONFIG_GET(flag/panic_bunker) && (!dbcon || !dbcon.IsConnected())) + if (CONFIG_GET(flag/panic_bunker) && (!SSdbcore || !SSdbcore.IsConnected())) message_admins("The database is not connected! Panic bunker will not work until the connection is reestablished.") feedback_add_details("admin_verb","PANIC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -26,7 +26,7 @@ CONFIG_SET(flag/paranoia_logging, !CONFIG_GET(flag/paranoia_logging)) log_and_message_admins("has toggled Paranoia Logging, it is now [(CONFIG_GET(flag/paranoia_logging) ? "on":"off")].", src) - if (CONFIG_GET(flag/paranoia_logging) && (!dbcon || !dbcon.IsConnected())) + if (CONFIG_GET(flag/paranoia_logging) && (!SSdbcore || !SSdbcore.IsConnected())) message_admins("The database is not connected! Paranoia logging will not be able to give 'player age' (time since first connection) warnings, only Byond account warnings.") feedback_add_details("admin_verb","PARLOG") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -40,6 +40,6 @@ CONFIG_SET(flag/ip_reputation, !CONFIG_GET(flag/ip_reputation)) log_and_message_admins("has toggled IP reputation checks, it is now [(CONFIG_GET(flag/ip_reputation) ? "on":"off")].", src) - if (CONFIG_GET(flag/ip_reputation) && (!dbcon || !dbcon.IsConnected())) + if (CONFIG_GET(flag/ip_reputation) && (!SSdbcore || !SSdbcore.IsConnected())) message_admins("The database is not connected! IP reputation logging will not be able to allow existing players to bypass the reputation checks (if that is enabled).") feedback_add_details("admin_verb","IPREP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index e77285dc3be..cdb73164a8f 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -145,7 +145,7 @@ var/sql_discord = sql_sanitize_text(their_id) var/sql_ckey = sql_sanitize_text(ckey) - var/DBQuery/query = dbcon.NewQuery("UPDATE erro_player SET discord_id = '[sql_discord]' WHERE ckey = '[sql_ckey]'") + var/datum/db_query/query = SSdbcore.NewQuery("UPDATE erro_player SET discord_id = '[sql_discord]' WHERE ckey = '[sql_ckey]'") if(query.Execute()) to_chat(src, span_notice("Registration complete! Thank you for taking the time to register your Discord ID.")) log_and_message_admins("[ckey] has registered their Discord ID to obtain the Crew Member role. Their Discord snowflake ID is: [their_id]", src) @@ -391,12 +391,12 @@ /proc/get_player_age(key) establish_db_connection() - if(!dbcon.IsConnected()) + if(!SSdbcore.IsConnected()) return null var/sql_ckey = sql_sanitize_text(ckey(key)) - var/DBQuery/query = dbcon.NewQuery("SELECT datediff(Now(),firstseen) as age FROM erro_player WHERE ckey = '[sql_ckey]'") + var/datum/db_query/query = SSdbcore.NewQuery("SELECT datediff(Now(),firstseen) as age FROM erro_player WHERE ckey = '[sql_ckey]'") query.Execute() if(query.NextRow()) @@ -411,12 +411,12 @@ return establish_db_connection() - if(!dbcon.IsConnected()) + if(!SSdbcore.IsConnected()) return var/sql_ckey = sql_sanitize_text(src.ckey) - var/DBQuery/query = dbcon.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM erro_player WHERE ckey = '[sql_ckey]'") + var/datum/db_query/query = SSdbcore.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM erro_player WHERE ckey = '[sql_ckey]'") query.Execute() var/sql_id = 0 player_age = 0 // New players won't have an entry so knowing we have a connection we set this to zero to be updated if their is a record. @@ -426,24 +426,26 @@ break account_join_date = sanitizeSQL(findJoinDate()) - if(account_join_date && dbcon.IsConnected()) - var/DBQuery/query_datediff = dbcon.NewQuery("SELECT DATEDIFF(Now(),'[account_join_date]')") + if(account_join_date && SSdbcore.IsConnected()) + var/datum/db_query/query_datediff = SSdbcore.NewQuery("SELECT DATEDIFF(Now(),'[account_join_date]')") if(query_datediff.Execute() && query_datediff.NextRow()) account_age = text2num(query_datediff.item[1]) - var/DBQuery/query_ip = dbcon.NewQuery("SELECT ckey FROM erro_player WHERE ip = '[address]'") + var/datum/db_query/query_ip = SSdbcore.NewQuery("SELECT ckey FROM erro_player WHERE ip = '[address]'") query_ip.Execute() related_accounts_ip = "" while(query_ip.NextRow()) related_accounts_ip += "[query_ip.item[1]], " break + qdel(query_ip) - var/DBQuery/query_cid = dbcon.NewQuery("SELECT ckey FROM erro_player WHERE computerid = '[computer_id]'") + var/datum/db_query/query_cid = SSdbcore.NewQuery("SELECT ckey FROM erro_player WHERE computerid = '[computer_id]'") query_cid.Execute() related_accounts_cid = "" while(query_cid.NextRow()) related_accounts_cid += "[query_cid.item[1]], " break + qdel(query_cid) //Just the standard check to see if it's actually a number if(sql_id) @@ -494,7 +496,7 @@ log_admin("Couldn't perform IP check on [key] with [address]") // VOREStation Edit Start - Department Hours - var/DBQuery/query_hours = dbcon.NewQuery("SELECT department, hours, total_hours FROM vr_player_hours WHERE ckey = '[sql_ckey]'") + var/datum/db_query/query_hours = SSdbcore.NewQuery("SELECT department, hours, total_hours FROM vr_player_hours WHERE ckey = '[sql_ckey]'") if(query_hours.Execute()) while(query_hours.NextRow()) department_hours[query_hours.item[1]] = text2num(query_hours.item[2]) @@ -507,16 +509,16 @@ if(sql_id) //Player already identified previously, we need to just update the 'lastseen', 'ip' and 'computer_id' variables - var/DBQuery/query_update = dbcon.NewQuery("UPDATE erro_player SET lastseen = Now(), ip = '[sql_ip]', computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]' WHERE id = [sql_id]") + var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE erro_player SET lastseen = Now(), ip = '[sql_ip]', computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]' WHERE id = [sql_id]") query_update.Execute() else //New player!! Need to insert all the stuff - var/DBQuery/query_insert = dbcon.NewQuery("INSERT INTO erro_player (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[sql_ckey]', Now(), Now(), '[sql_ip]', '[sql_computerid]', '[sql_admin_rank]')") + var/datum/db_query/query_insert = SSdbcore.NewQuery("INSERT INTO erro_player (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[sql_ckey]', Now(), Now(), '[sql_ip]', '[sql_computerid]', '[sql_admin_rank]')") query_insert.Execute() //Logging player access var/serverip = "[world.internet_address]:[world.port]" - var/DBQuery/query_accesslog = dbcon.NewQuery("INSERT INTO `erro_connection_log`(`id`,`datetime`,`serverip`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),'[serverip]','[sql_ckey]','[sql_ip]','[sql_computerid]');") + var/datum/db_query/query_accesslog = SSdbcore.NewQuery("INSERT INTO `erro_connection_log`(`id`,`datetime`,`serverip`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),'[serverip]','[sql_ckey]','[sql_ip]','[sql_computerid]');") query_accesslog.Execute() #undef UPLOAD_LIMIT diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index 3e63722eb48..1c115ffac53 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -44,7 +44,7 @@ \[Start Search\] "} if(1) establish_db_connection() - if(!dbcon_old.IsConnected()) + if(!SSdbcore.IsConnected()) dat += span_red(span_bold("ERROR") + ": Unable to contact External Archive. Please contact your system administrator for assistance.") + " " else if(!SQLquery) dat += span_red(span_bold("ERROR") + ": Malformed search request. Please contact your system administrator for assistance.") + " " @@ -52,7 +52,7 @@ dat += {"
|