mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 18:32:03 +00:00
Ports TG's BSQL library (#26455)
* Ports TG's BSQL * write perms * my mistake * Missing migrations, fixes mistakes, removes unneeded logs * Missing migrations, fixes mistakes, removes unneeded logs * haha * Final missing migration, actually fix runtime * Fucked up this doesn't throw a warning * sql fixes; polls
This commit is contained in:
16
.travis.yml
16
.travis.yml
@@ -1,5 +1,6 @@
|
||||
language: generic
|
||||
dist: bionic
|
||||
os: linux
|
||||
dist: xenial
|
||||
sudo: false
|
||||
|
||||
env:
|
||||
@@ -53,27 +54,36 @@ matrix:
|
||||
env:
|
||||
DM_UNIT_TESTS="1"
|
||||
addons:
|
||||
mariadb: '10.2'
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- libstdc++6:i386
|
||||
- libc6-i386
|
||||
- libgcc1:i386
|
||||
- gcc-multilib
|
||||
- g++-7
|
||||
- g++-7-multilib
|
||||
- rustc
|
||||
- cargo
|
||||
- moreutils
|
||||
- libmariadb-client-lgpl-dev:i386
|
||||
- libmariadbd-dev
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}
|
||||
- $TRAVIS_BUILD_DIR/libvg/target
|
||||
- $HOME/.cargo
|
||||
- $HOME/libmariadb
|
||||
install:
|
||||
- tools/travis/install-byond.sh
|
||||
- tools/travis/install_libmariadb.sh
|
||||
- source $HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}/byond/bin/byondsetup
|
||||
- cd libvg
|
||||
# --jobs 1 to prevent threading problems with the BYOND crate.
|
||||
- cargo test --jobs 1 --verbose
|
||||
- cd -
|
||||
- tools/travis/build.py
|
||||
- tools/travis/build_bsql.sh
|
||||
- cp tools/travis/config/config.txt config/
|
||||
- tools/travis/run_tests.py 2>&1 | tee /dev/stderr | sponge | awk '/UNIT TEST FAIL/ { exit 1 }'
|
||||
|
||||
|
||||
126
__DEFINES/BSQL.dm
Normal file
126
__DEFINES/BSQL.dm
Normal file
@@ -0,0 +1,126 @@
|
||||
//BSQL - DMAPI
|
||||
#define BSQL_VERSION "v1.3.0.0"
|
||||
|
||||
//types of connections
|
||||
#define BSQL_CONNECTION_TYPE_MARIADB "MySql"
|
||||
#define BSQL_CONNECTION_TYPE_SQLSERVER "SqlServer"
|
||||
|
||||
#define BSQL_DEFAULT_TIMEOUT 5
|
||||
#define BSQL_DEFAULT_THREAD_LIMIT 50
|
||||
|
||||
//Call this before rebooting or shutting down your world to clean up gracefully. This invalidates all active connection and operation datums
|
||||
/world/proc/BSQL_Shutdown()
|
||||
return
|
||||
|
||||
/*
|
||||
Called whenever a library call is made with verbose information, override and do with as you please
|
||||
message: English debug message
|
||||
*/
|
||||
/world/proc/BSQL_Debug(msg)
|
||||
return
|
||||
|
||||
/*
|
||||
Create a new database connection, does not perform the actual connect
|
||||
connection_type: The BSQL connection_type to use
|
||||
asyncTimeout: The timeout to use for normal operations, 0 for infinite, defaults to BSQL_DEFAULT_TIMEOUT
|
||||
blockingTimeout: The timeout to use for blocking operations, must be less than or equal to asyncTimeout, 0 for infinite, defaults to asyncTimeout
|
||||
threadLimit: The limit of additional threads BSQL will run simultaneously, defaults to BSQL_DEFAULT_THREAD_LIMIT
|
||||
*/
|
||||
/datum/BSQL_Connection/New(connection_type, asyncTimeout, blockingTimeout, threadLimit)
|
||||
return ..()
|
||||
|
||||
/*
|
||||
Starts an operation to connect to a database. Should only have 1 successful call
|
||||
ipaddress: The ip/hostname of the target server
|
||||
port: The port of the target server
|
||||
username: The username to login to the target server
|
||||
password: The password for the target server
|
||||
database: Optional database to connect to. Must be used when trying to do database operations, `USE x` is not sufficient
|
||||
Returns: A /datum/BSQL_Operation representing the connection or null if an error occurred
|
||||
*/
|
||||
/datum/BSQL_Connection/proc/BeginConnect(ipaddress, port, username, password, database)
|
||||
return
|
||||
|
||||
/*
|
||||
Properly quotes a string for use by the database. The connection must be open for this proc to succeed
|
||||
str: The string to quote
|
||||
Returns: The string quoted on success, null on error
|
||||
*/
|
||||
/datum/BSQL_Connection/proc/Quote(str)
|
||||
return
|
||||
|
||||
/*
|
||||
Starts an operation for a query
|
||||
query: The text of the query. Only one query allowed per invocation, no semicolons
|
||||
Returns: A /datum/BSQL_Operation/Query representing the running query and subsequent result set or null if an error occurred
|
||||
Note for MariaDB: The underlying connection is pooled. In order to use connection state based properties (i.e. LAST_INSERT_ID()) you can guarantee multiple queries will use the same connection by running BSQL_DEL_CALL(query) on the finished /datum/BSQL_Operation/Query and then creating the next one with another call to BeginQuery() with no sleeps in between
|
||||
*/
|
||||
/datum/BSQL_Connection/proc/BeginQuery(query)
|
||||
return
|
||||
|
||||
/*
|
||||
Checks if the operation is complete. This, in some cases must be called multiple times with false return before a result is present regardless of timespan. For best performance check it once per tick
|
||||
Returns: TRUE if the operation is complete, FALSE if it's not, null on error
|
||||
*/
|
||||
/datum/BSQL_Operation/proc/IsComplete()
|
||||
return
|
||||
|
||||
/*
|
||||
Blocks the entire game until the given operation completes. IsComplete should not be checked after calling this to avoid potential side effects.
|
||||
Returns: TRUE on success, FALSE if the operation wait time exceeded the connection's blockingTimeout setting
|
||||
*/
|
||||
/datum/BSQL_Operation/proc/WaitForCompletion()
|
||||
return
|
||||
|
||||
/*
|
||||
Get the error message associated with an operation. Should not be used while IsComplete() returns FALSE
|
||||
Returns: The error message, if any. null otherwise
|
||||
*/
|
||||
/datum/BSQL_Operation/proc/GetError()
|
||||
return
|
||||
|
||||
/*
|
||||
Get the error code associated with an operation. Should not be used while IsComplete() returns FALSE
|
||||
Returns: The error code, if any. null otherwise
|
||||
*/
|
||||
/datum/BSQL_Operation/proc/GetErrorCode()
|
||||
return
|
||||
|
||||
/*
|
||||
Gets an associated list of column name -> value representation of the most recent row in the query. Only valid if IsComplete() returns TRUE. If this returns null and no errors are present there are no more results in the query. Important to note that once IsComplete() returns TRUE it must not be called again without checking this or the row values may be lost
|
||||
Returns: An associated list of column name -> value for the row. Values will always be either strings or null
|
||||
*/
|
||||
/datum/BSQL_Operation/Query/proc/CurrentRow()
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
Code configuration options below
|
||||
Define this to avoid modifying this file but the following defines must be declared somewhere else before BSQL/includes.dm is included
|
||||
*/
|
||||
#ifndef BSQL_EXTERNAL_CONFIGURATION
|
||||
|
||||
//Modify this if you disagree with byond's GC schemes. Ensure this is called for all connections and operations when they are deleted or they will leak native resources until /world/proc/BSQL_Shutdown() is called
|
||||
#define BSQL_DEL_PROC(path) ##path/Del()
|
||||
|
||||
//The equivalent of calling del() in your codebase
|
||||
// Must not be changed to "qdel()".
|
||||
#define BSQL_DEL_CALL(obj) del(##obj)
|
||||
|
||||
//Returns TRUE if an object is delete
|
||||
#define BSQL_IS_DELETED(obj) (obj == null)
|
||||
|
||||
//Modify this to add protections to the connection and query datums
|
||||
#define BSQL_PROTECT_DATUM(path)
|
||||
|
||||
//Modify this to change up error handling for the library
|
||||
#define BSQL_ERROR(message) CRASH("BSQL: [##message]")
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
Copyright 2018 Jordan Brown
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
@@ -1,7 +1,26 @@
|
||||
var/list/protected_global_vars = list(
|
||||
"sqlfdbklogin",
|
||||
"sqlfdbkpass",
|
||||
"sqlfdbkdb",
|
||||
"sqladdress",
|
||||
"sqlport",
|
||||
"sqllogin",
|
||||
"sqlpass",
|
||||
"sqlfdbkdb",
|
||||
|
||||
"forbidden_varedit_object_types",
|
||||
"unviewable_varedit_object_types",
|
||||
"protected_global_vars", // Hhaha!
|
||||
)
|
||||
|
||||
/proc/writeglobal(var/which, var/what)
|
||||
if (which in protected_global_vars)
|
||||
return "Cannot write variable."
|
||||
global.vars[which] = what
|
||||
|
||||
/proc/readglobal(var/which)
|
||||
if (which in protected_global_vars)
|
||||
return "Cannot read variable."
|
||||
return global.vars[which]
|
||||
|
||||
#define DNA_SE_LENGTH 58
|
||||
@@ -209,11 +228,6 @@ var/forum_authenticated_group = "10"
|
||||
var/fileaccess_timer = 0
|
||||
var/custom_event_msg = null
|
||||
|
||||
//Database connections
|
||||
//A connection is established on world creation. Ideally, the connection dies when the server restarts (After feedback logging.).
|
||||
var/DBConnection/dbcon //Feedback database (New database)
|
||||
var/DBConnection/dbcon_old //Tgstation database (Old database) - See the files in the SQL folder for information what goes where.
|
||||
|
||||
#define MIDNIGHT_ROLLOVER 864000 //number of deciseconds in a day
|
||||
|
||||
//Recall time limit: 2 hours
|
||||
@@ -477,4 +491,4 @@ var/list/variables_not_to_be_copied = list(
|
||||
var/global/list/ties = list(/obj/item/clothing/accessory/tie/blue,/obj/item/clothing/accessory/tie/red,/obj/item/clothing/accessory/tie/horrible)
|
||||
|
||||
//Observers
|
||||
var/global_poltergeist_cooldown = 300 //30s by default, badmins can var-edit this to reduce the poltergeist cooldown globally
|
||||
var/global_poltergeist_cooldown = 300 //30s by default, badmins can var-edit this to reduce the poltergeist cooldown globally
|
||||
|
||||
@@ -1304,6 +1304,11 @@ var/default_colour_matrix = list(1,0,0,0,\
|
||||
#define astar_debug(text)
|
||||
#endif
|
||||
|
||||
#define BSQL_DEBUG_CONNECTION 0
|
||||
#if BSQL_DEBUG_CONNECTION == 1
|
||||
#warn "BSQL_DEBUG_CONNECTION MUST BE SET TO 0 BEFORE COMMITING."
|
||||
#endif
|
||||
|
||||
//#define JUSTFUCKMYSHITUP 1
|
||||
#ifdef JUSTFUCKMYSHITUP
|
||||
#define writepanic(a) if(ticker && ticker.current_state >= 3 && world.cpu > 100) write_panic(a)
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// All in one file so it's easier to see what everything is relative to.
|
||||
|
||||
#define SS_INIT_TICKER_SPAWN 999
|
||||
#define SS_INIT_DBCORE 900
|
||||
#define SS_INIT_SSdbcore 800
|
||||
#define SS_INIT_RUST 26
|
||||
#define SS_INIT_SUPPLY_SHUTTLE 25
|
||||
#define SS_INIT_SUN 24
|
||||
@@ -48,6 +50,7 @@
|
||||
#define SS_PRIORITY_UNSPECIFIED 30
|
||||
#define SS_PRIORITY_LIGHTING 20
|
||||
#define SS_PRIORITY_AMBIENCE 19
|
||||
#define SS_PRIORITY_DBCORE 18
|
||||
#define SS_PRIORITY_SUN 3
|
||||
#define SS_PRIORITY_GARBAGE 2
|
||||
#define SS_PRIORITY_INACTIVITY 1
|
||||
@@ -74,8 +77,9 @@
|
||||
#define SS_DISPLAY_POWER -20
|
||||
#define SS_DISPLAY_TICKER -10
|
||||
#define SS_DISPLAY_UNSPECIFIED 0
|
||||
#define SS_DISPLAY_SUN 10
|
||||
#define SS_DISPLAY_WEATHER 5
|
||||
#define SS_DISPLAY_SUN 10
|
||||
#define SS_DISPLAY_DBCORE 15
|
||||
|
||||
#define SS_TRASH "trash"
|
||||
#define SS_CLEANABLE "cleanable_decals"
|
||||
|
||||
@@ -7,3 +7,6 @@
|
||||
var/global/internal_tick_usage = 0.2 * world.tick_lag // default value. extools-updated value, see extools maptick
|
||||
#define TICK_CHECK ( world.tick_usage > CURRENT_TICKLIMIT ? stoplag() : 0 )
|
||||
#define CHECK_TICK if (world.tick_usage > CURRENT_TICKLIMIT) stoplag()
|
||||
|
||||
// Do X until it's done, while looking for lag.
|
||||
#define UNTIL(X) while(!(X)) stoplag()
|
||||
|
||||
@@ -54,8 +54,17 @@
|
||||
if(C.prefs.toggles & CHAT_DEBUGLOGS)
|
||||
to_chat(C, "DEBUG: [text]")
|
||||
|
||||
/proc/log_sql(text)
|
||||
if (!config || (config && config.log_sql))
|
||||
diary << html_decode("\[[time_stamp()]]SQL: [text]")
|
||||
|
||||
/proc/log_query_debug(text)
|
||||
if (!config || (config && config.log_sql_queries))
|
||||
diary << html_decode("\[[time_stamp()]]SQL QUERY: [text]")
|
||||
|
||||
/proc/log_world(text)
|
||||
log_game(text)
|
||||
to_chat(world, "<span class='notice'>[text]</span>")
|
||||
|
||||
/proc/log_adminghost(text)
|
||||
if (config.log_adminghost)
|
||||
|
||||
@@ -31,11 +31,9 @@ forLineInText(text)
|
||||
/proc/sanitizeSQL(var/t as text)
|
||||
//var/sanitized_text = replacetext(t, "'", "\\'")
|
||||
//sanitized_text = replacetext(sanitized_text, "\"", "\\\"")
|
||||
|
||||
var/sqltext = dbcon.Quote(t)
|
||||
//testing("sanitizeSQL(): BEFORE copytext(): [sqltext]")
|
||||
sqltext = copytext(sqltext, 2, length(sqltext))//Quote() adds quotes around input, we already do that
|
||||
//testing("sanitizeSQL(): AFTER copytext(): [sqltext]")
|
||||
var/sqltext = SSdbcore.Quote(t)
|
||||
//to_chat(world, "sanitizeSQL(): BEFORE Quote(): [t]")
|
||||
//to_chat(world, "sanitizeSQL(): AFTER Quote(): [sqltext]")
|
||||
return sqltext
|
||||
|
||||
/*
|
||||
@@ -588,4 +586,4 @@ proc/sql_sanitize_text(var/text)
|
||||
speech = nya_lowercase.Replace(speech, "ny")
|
||||
speech = nya_uppercase.Replace(speech, "NY")
|
||||
speech = nya_Ny.Replace(speech, "Ny")
|
||||
return speech
|
||||
return speech
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#define TimeOfGame (get_game_time())
|
||||
#define TimeOfTick (world.tick_usage*0.01*world.tick_lag)
|
||||
|
||||
//#define REALTIMEOFDAY (world.timeofday + (MIDNIGHT_ROLLOVER * MIDNIGHT_ROLLOVER_CHECK))
|
||||
|
||||
/proc/get_game_time()
|
||||
var/global/time_offset = 0
|
||||
var/global/last_time = 0
|
||||
@@ -119,4 +121,17 @@ var/global/obj/effect/statclick/time/time_statclick
|
||||
/proc/timeStatEntry()
|
||||
if(!time_statclick)
|
||||
time_statclick = new /obj/effect/statclick/time("loading...")
|
||||
stat("Station Time:", time_statclick.update("[worldtime2text()]"))
|
||||
stat("Station Time:", time_statclick.update("[worldtime2text()]"))
|
||||
|
||||
|
||||
var/midnight_rollovers = 0
|
||||
var/rollovercheck_last_timeofday = 0
|
||||
/proc/update_midnight_rollover()
|
||||
if (world.timeofday < rollovercheck_last_timeofday) //TIME IS GOING BACKWARDS!
|
||||
midnight_rollovers++
|
||||
rollovercheck_last_timeofday = world.timeofday
|
||||
return midnight_rollovers
|
||||
|
||||
#define MIDNIGHT_ROLLOVER_CHECK (rollovercheck_last_timeofday != world.timeofday ? update_midnight_rollover() : midnight_rollovers)
|
||||
#define MIDNIGHT_ROLLOVER 864000 //number of deciseconds in a day
|
||||
#define REALTIMEOFDAY (world.timeofday + (MIDNIGHT_ROLLOVER * MIDNIGHT_ROLLOVER_CHECK))
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
var/log_admin = 0 // log admin actions
|
||||
var/log_admin_only = FALSE
|
||||
var/log_debug = 1 // log debug output
|
||||
var/log_sql = 0 // log SQL events
|
||||
var/log_sql_queries = 0 // debug info SQL queries
|
||||
var/log_game = 0 // log game events
|
||||
var/log_vote = 0 // log voting
|
||||
var/log_whisper = 0 // log client whisper
|
||||
@@ -26,7 +28,7 @@
|
||||
var/log_rc = 0 // log requests consoles
|
||||
var/log_hrefs = 0 // logs all links clicked in-game. Could be used for debugging and tracking down exploits
|
||||
var/log_runtimes = 0 // Logs all runtimes.
|
||||
var/sql_enabled = 1 // for sql switching
|
||||
var/sql_enabled = 0 // for sql switching
|
||||
var/allow_admin_ooccolor = 0 // Allows admins with relevant permissions to have their own ooc colour
|
||||
var/allow_vote_restart = 0 // allow votes to restart
|
||||
var/allow_vote_mode = 0 // allow votes to change mode
|
||||
@@ -71,6 +73,12 @@
|
||||
var/jobs_have_minimal_access = 0 //determines whether jobs use minimal access or expanded access.
|
||||
var/copy_logs = null
|
||||
|
||||
// BSQL things
|
||||
var/bsql_debug = 0
|
||||
var/async_query_timeout = 10
|
||||
var/blocking_query_timeout = 5
|
||||
var/bsql_thread_limit = 50
|
||||
|
||||
var/cult_ghostwriter = 1 //Allows ghosts to write in blood in cult rounds...
|
||||
var/cult_ghostwriter_req_cultists = 10 //...so long as this many cultists are active.
|
||||
|
||||
@@ -286,6 +294,12 @@
|
||||
if ("log_debug")
|
||||
config.log_debug = text2num(value)
|
||||
|
||||
if ("log_sql")
|
||||
config.log_sql = 1
|
||||
|
||||
if ("log_sql_queries")
|
||||
config.log_sql_queries = 1
|
||||
|
||||
if ("log_game")
|
||||
config.log_game = 1
|
||||
|
||||
@@ -546,6 +560,17 @@
|
||||
config.assistantratio = text2num(value)
|
||||
if("copy_logs")
|
||||
copy_logs = value
|
||||
|
||||
// BSQL
|
||||
if("bsql_debug")
|
||||
bsql_debug = value
|
||||
if("async_query_timeout")
|
||||
async_query_timeout = value
|
||||
if("blocking_query_timeout")
|
||||
blocking_query_timeout = value
|
||||
if("bsql_thread_limit")
|
||||
bsql_thread_limit = value
|
||||
|
||||
if("media_base_url")
|
||||
media_base_url = value
|
||||
if("media_secret_key")
|
||||
|
||||
449
code/controllers/subsystem/dbcore.dm
Normal file
449
code/controllers/subsystem/dbcore.dm
Normal file
@@ -0,0 +1,449 @@
|
||||
// Original code from /tg/station at https://github.com/tgstation/tgstation
|
||||
|
||||
var/datum/subsystem/dbcore/SSdbcore
|
||||
|
||||
#define DB_MAJOR_VERSION 0
|
||||
#define DB_MINOR_VERSION 1
|
||||
|
||||
/datum/subsystem/dbcore
|
||||
name = "feedback Database"
|
||||
wait = 1 MINUTES
|
||||
flags = SS_NO_INIT
|
||||
priority = SS_PRIORITY_DBCORE
|
||||
display_order = SS_DISPLAY_DBCORE
|
||||
var/const/FAILED_DB_CONNECTION_CUTOFF = 5
|
||||
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/list/active_queries = list()
|
||||
|
||||
var/datum/BSQL_Connection/connection
|
||||
var/datum/BSQL_Operation/connectOperation
|
||||
|
||||
/datum/subsystem/dbcore/New()
|
||||
NEW_SS_GLOBAL(SSdbcore)
|
||||
|
||||
/datum/subsystem/dbcore/proc/get_db_ids()
|
||||
var/list/ids = list()
|
||||
ids["user"] = sqlfdbklogin
|
||||
ids["pass"] = sqlfdbkpass
|
||||
ids["db"] = sqlfdbkdb
|
||||
ids["address"] = sqladdress
|
||||
ids["port"] = sqlport
|
||||
return ids
|
||||
|
||||
/datum/subsystem/dbcore/Initialize()
|
||||
//We send warnings to the admins during subsystem init, as the clients will be New'd and messages
|
||||
//will queue properly with goonchat
|
||||
if(!Connect())
|
||||
world.log << "Your server failed to establish a connection with the [name]."
|
||||
else
|
||||
world.log << "[name] connection established."
|
||||
|
||||
migration_controller_sqlite = new ("players2.sqlite", "players2_empty.sqlite")
|
||||
|
||||
switch(schema_mismatch)
|
||||
if(1)
|
||||
message_admins("Database schema ([db_major].[db_minor]) doesn't match the latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors")
|
||||
if(2)
|
||||
message_admins("Could not get schema version from database")
|
||||
|
||||
. = ..()
|
||||
|
||||
// All connections established, migrations can start.
|
||||
migration_controller_mysql = new
|
||||
|
||||
/datum/subsystem/dbcore/fire()
|
||||
for(var/I in active_queries)
|
||||
var/datum/DBQuery/Q = I
|
||||
if(world.time - Q.last_activity_time > (5 MINUTES))
|
||||
message_admins("Found undeleted query, please check the server logs and notify coders.")
|
||||
log_sql("Undeleted query: \"[Q.sql]\" LA: [Q.last_activity] LAT: [Q.last_activity_time]")
|
||||
qdel(Q)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
/datum/subsystem/dbcore/Recover()
|
||||
connection = SSdbcore.connection
|
||||
connectOperation = SSdbcore.connectOperation
|
||||
|
||||
/datum/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())
|
||||
ShutdownQuery()
|
||||
if(IsConnected())
|
||||
Disconnect()
|
||||
world.BSQL_Shutdown()
|
||||
|
||||
/datum/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 > FAILED_DB_CONNECTION_CUTOFF) //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 + 5 SECONDS
|
||||
return FALSE
|
||||
|
||||
if(!config.sql_enabled)
|
||||
return FALSE
|
||||
|
||||
var/list/ids = get_db_ids()
|
||||
|
||||
var/user = ids["user"]
|
||||
var/pass = ids["pass"]
|
||||
var/db = ids["db"]
|
||||
var/address = ids["address"]
|
||||
var/port = ids["port"]
|
||||
|
||||
connection = new /datum/BSQL_Connection(BSQL_CONNECTION_TYPE_MARIADB, config.async_query_timeout, config.blocking_query_timeout, config.bsql_thread_limit)
|
||||
var/error
|
||||
if(!connection || connection.gcDestroyed)
|
||||
connection = null
|
||||
error = last_error
|
||||
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]")
|
||||
++failed_connections
|
||||
qdel(connection)
|
||||
qdel(connectOperation)
|
||||
connection = null
|
||||
connectOperation = null
|
||||
|
||||
/datum/subsystem/dbcore/proc/CheckSchemaVersion()
|
||||
if(config.sql_enabled)
|
||||
if(Connect())
|
||||
log_world("Database connection established.")
|
||||
/*
|
||||
var/datum/DBQuery/query_db_version = NewQuery("SELECT major, minor FROM schema_revision ORDER BY date DESC LIMIT 1")
|
||||
query_db_version.Execute()
|
||||
if(query_db_version.NextRow())
|
||||
db_major = text2num(query_db_version.item[1])
|
||||
db_minor = text2num(query_db_version.item[2])
|
||||
if(db_major != DB_MAJOR_VERSION || db_minor != DB_MINOR_VERSION)
|
||||
schema_mismatch = 1 // flag admin message about mismatch
|
||||
log_sql("Database schema ([db_major].[db_minor]) doesn't match the latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors")
|
||||
else
|
||||
schema_mismatch = 2 //flag admin message about no schema version
|
||||
log_sql("Could not get schema version from database")
|
||||
qdel(query_db_version)
|
||||
*/
|
||||
else
|
||||
log_sql("Your server failed to establish a connection with the [name].")
|
||||
else
|
||||
log_sql("Database is not enabled in configuration.")
|
||||
|
||||
/datum/subsystem/dbcore/proc/SetRoundID()
|
||||
return
|
||||
|
||||
/datum/subsystem/dbcore/proc/SetRoundStart()
|
||||
return
|
||||
|
||||
/datum/subsystem/dbcore/proc/SetRoundEnd()
|
||||
return
|
||||
|
||||
/datum/subsystem/dbcore/proc/ShutdownQuery()
|
||||
return
|
||||
|
||||
/*
|
||||
/datum/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]')")
|
||||
query_round_initialize.Execute(async = FALSE)
|
||||
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]
|
||||
qdel(query_round_last_id)
|
||||
|
||||
/datum/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]")
|
||||
query_round_start.Execute()
|
||||
qdel(query_round_start)
|
||||
|
||||
/datum/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]")
|
||||
query_round_end.Execute()
|
||||
qdel(query_round_end)
|
||||
|
||||
/datum/subsystem/dbcore/proc/ShutdownQuery()
|
||||
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]")
|
||||
query_round_shutdown.Execute()
|
||||
qdel(query_round_shutdown)
|
||||
*/
|
||||
|
||||
/datum/subsystem/dbcore/proc/Disconnect()
|
||||
failed_connections = 0
|
||||
qdel(connectOperation)
|
||||
qdel(connection)
|
||||
connectOperation = null
|
||||
connection = null
|
||||
|
||||
/datum/subsystem/dbcore/proc/IsConnected()
|
||||
if(!config.sql_enabled)
|
||||
return FALSE
|
||||
if (!initialized)
|
||||
return FALSE
|
||||
//block until any connect operations finish
|
||||
var/datum/BSQL_Connection/_connection = connection
|
||||
var/datum/BSQL_Operation/op = connectOperation
|
||||
while ( (!_connection || _connection.gcDestroyed) || !op.IsComplete() ) // Waiting we have a real connection and that it's complete
|
||||
stoplag()
|
||||
return connection && !(connection.gcDestroyed && !op.GetError()) // Connect
|
||||
|
||||
/datum/subsystem/dbcore/proc/Quote(str)
|
||||
if(connection)
|
||||
return connection.Quote(str)
|
||||
|
||||
/datum/subsystem/dbcore/proc/ErrorMsg()
|
||||
if(!config.sql_enabled)
|
||||
return "Database disabled by configuration"
|
||||
return last_error
|
||||
|
||||
/datum/subsystem/dbcore/proc/ReportError(error)
|
||||
last_error = error
|
||||
|
||||
//
|
||||
/datum/subsystem/dbcore/proc/NewQuery(sql_query)
|
||||
return new /datum/DBQuery(sql_query, connection)
|
||||
|
||||
/datum/subsystem/dbcore/proc/QuerySelect(list/querys, warn = FALSE, qdel = FALSE)
|
||||
if (!islist(querys))
|
||||
if (!istype(querys, /datum/DBQuery))
|
||||
CRASH("Invalid query passed to QuerySelect: [querys]")
|
||||
querys = list(querys)
|
||||
|
||||
for (var/thing in querys)
|
||||
var/datum/DBQuery/query = thing
|
||||
if (warn)
|
||||
call(query, /datum/DBQuery.proc/warn_execute)()
|
||||
else
|
||||
call(query, /datum/DBQuery.proc/Execute)()
|
||||
|
||||
for (var/thing in querys)
|
||||
var/datum/DBQuery/query = thing
|
||||
UNTIL(!query.in_progress)
|
||||
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
|
||||
Delayed insert mode was removed in mysql 7 and only works with MyISAM type tables,
|
||||
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/subsystem/dbcore/proc/MassInsert(table, list/rows, duplicate_key = FALSE, ignore_errors = FALSE, delayed = FALSE, warn = FALSE, async = TRUE)
|
||||
if (!table || !rows || !istype(rows))
|
||||
return
|
||||
var/list/columns = list()
|
||||
var/list/sorted_rows = 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
|
||||
|
||||
sorted_row[idx] = row[column]
|
||||
sorted_rows[++sorted_rows.len] = sorted_row
|
||||
|
||||
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
|
||||
|
||||
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]")
|
||||
if (warn)
|
||||
. = Query.warn_execute(async)
|
||||
else
|
||||
. = Query.Execute(async)
|
||||
qdel(Query)
|
||||
|
||||
/datum/DBQuery
|
||||
var/sql // The sql query being executed.
|
||||
var/list/item //list of data values populated by NextRow()
|
||||
|
||||
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
|
||||
|
||||
/datum/DBQuery/New(sql_query, datum/BSQL_Connection/connection)
|
||||
log_query_debug("new query with SQL : {[sql_query]} \n on [SSdbcore.name]")
|
||||
SSdbcore.active_queries[src] = TRUE
|
||||
Activity("Created")
|
||||
item = list()
|
||||
src.connection = connection
|
||||
sql = sql_query
|
||||
|
||||
/datum/DBQuery/Destroy()
|
||||
log_query_debug("query with [sql] being qdeleted. Will die any second now.")
|
||||
Close()
|
||||
SSdbcore.active_queries -= src
|
||||
return ..()
|
||||
|
||||
/datum/DBQuery/Del()
|
||||
log_query_debug("query with [sql] died.")
|
||||
return ..()
|
||||
|
||||
/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
|
||||
|
||||
/datum/DBQuery/proc/warn_execute(async = TRUE)
|
||||
. = Execute(async)
|
||||
if(!.)
|
||||
to_chat(usr, "<span class='danger'>A SQL error occurred during this operation, check the server logs.</span>")
|
||||
|
||||
/datum/DBQuery/proc/Execute(async = TRUE, log_error = TRUE)
|
||||
Activity("Execute")
|
||||
if(in_progress)
|
||||
CRASH("Attempted to start a new query while waiting on the old one")
|
||||
|
||||
if(!connection || connection.gcDestroyed)
|
||||
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 = (!query || query.gcDestroyed) ? "Query object deleted!" : query.GetError()
|
||||
last_error = error
|
||||
. = !error
|
||||
if(!. && log_error)
|
||||
log_sql("[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]")
|
||||
log_query_debug("Slow query timeout detected.")
|
||||
log_query_debug("Query used: [sql]")
|
||||
slow_query_check()
|
||||
|
||||
/datum/DBQuery/proc/run_query(async)
|
||||
query = connection.BeginQuery(sql)
|
||||
if(!async)
|
||||
. = !query.WaitForCompletion()
|
||||
else
|
||||
in_progress = TRUE
|
||||
UNTIL(query.IsComplete())
|
||||
in_progress = FALSE
|
||||
|
||||
/datum/DBQuery/proc/slow_query_check()
|
||||
message_admins("HEY! A database query timed out. Tell coders or Pomf what happened, please.")
|
||||
|
||||
/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
|
||||
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]
|
||||
|
||||
/datum/DBQuery/proc/ErrorMsg()
|
||||
return last_error
|
||||
|
||||
/datum/DBQuery/proc/Close()
|
||||
item.Cut()
|
||||
qdel(query)
|
||||
query = null
|
||||
|
||||
/world/BSQL_Debug(message)
|
||||
if(!config.bsql_debug)
|
||||
return
|
||||
|
||||
//strip sensitive stuff
|
||||
if(findtext(message, ": OpenConnection("))
|
||||
message = "OpenConnection CENSORED"
|
||||
|
||||
log_sql("BSQL_DEBUG: [message]")
|
||||
@@ -73,31 +73,25 @@ var/datum/blackbox/blackbox = new
|
||||
var/watch = start_watch()
|
||||
log_startup_progress("Storing Black Box data...")
|
||||
round_end_data_gathering() //round_end time logging and some other data processing
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
return
|
||||
var/round_id
|
||||
|
||||
var/nqueries = 0
|
||||
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT MAX(round_id) AS round_id FROM erro_feedback")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("SELECT MAX(round_id) AS round_id FROM erro_feedback")
|
||||
if(!query.Execute())
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
nqueries++
|
||||
while(query.NextRow())
|
||||
round_id = query.item[1]
|
||||
|
||||
qdel(query)
|
||||
if(!isnum(round_id))
|
||||
round_id = text2num(round_id)
|
||||
round_id++
|
||||
|
||||
/*
|
||||
for(var/datum/feedback_variable/FV in feedback)
|
||||
var/sql = "INSERT INTO erro_feedback VALUES (null, Now(), [round_id], \"[FV.get_variable()]\", [FV.get_value()], \"[FV.get_details()]\")"
|
||||
var/DBQuery/query_insert = dbcon.NewQuery(sql)
|
||||
query_insert.Execute()
|
||||
nqueries++
|
||||
sleep(1) // Let other shit do things
|
||||
*/
|
||||
// MySQL and MariaDB support compound inserts and this insert is slow as fuck.
|
||||
var/sql = "INSERT INTO erro_feedback VALUES "
|
||||
var/ninserts=0
|
||||
@@ -106,10 +100,13 @@ var/datum/blackbox/blackbox = new
|
||||
sql += ","
|
||||
ninserts++
|
||||
sql += "(null, Now(), [round_id], \"[FV.get_variable()]\", [FV.get_value()], \"[FV.get_details()]\")"
|
||||
var/DBQuery/query_insert = dbcon.NewQuery(sql)
|
||||
query_insert.Execute()
|
||||
var/datum/DBQuery/query_insert = SSdbcore.NewQuery(sql)
|
||||
if(!query_insert.Execute())
|
||||
log_sql("Error: [query_insert.ErrorMsg()]")
|
||||
qdel(query_insert)
|
||||
return
|
||||
nqueries++
|
||||
|
||||
qdel(query_insert)
|
||||
log_startup_progress(" Wrote Black Box data with [nqueries] queries in [stop_watch(watch)]s.")
|
||||
|
||||
|
||||
|
||||
@@ -5,30 +5,29 @@ proc/sql_poll_players()
|
||||
for(var/mob/M in player_list)
|
||||
if(M.client)
|
||||
playercount += 1
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
log_game("SQL ERROR during player polling. Failed to connect.")
|
||||
else
|
||||
var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
|
||||
var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO population (playercount, time) VALUES ([playercount], '[sqltime]')")
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("INSERT INTO population (playercount, time) VALUES ([playercount], '[sqltime]')")
|
||||
if(!query.Execute())
|
||||
var/err = query.ErrorMsg()
|
||||
log_game("SQL ERROR during player polling. Error : \[[err]\]\n")
|
||||
|
||||
qdel(query)
|
||||
|
||||
proc/sql_poll_admins()
|
||||
if(!sqllogging)
|
||||
return
|
||||
var/admincount = admins.len
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
log_game("SQL ERROR during admin polling. Failed to connect.")
|
||||
else
|
||||
var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
|
||||
var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO population (admincount, time) VALUES ([admincount], '[sqltime]')")
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("INSERT INTO population (admincount, time) VALUES ([admincount], '[sqltime]')")
|
||||
if(!query.Execute())
|
||||
var/err = query.ErrorMsg()
|
||||
log_game("SQL ERROR during admin polling. Error : \[[err]\]\n")
|
||||
qdel(query)
|
||||
|
||||
proc/sql_report_round_start()
|
||||
// TODO
|
||||
@@ -64,15 +63,14 @@ proc/sql_report_death(var/mob/living/carbon/human/H)
|
||||
var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
|
||||
var/coord = "[H.x], [H.y], [H.z]"
|
||||
// to_chat(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.Connect())
|
||||
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/DBQuery/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)
|
||||
if(!sqllogging)
|
||||
@@ -98,16 +96,14 @@ proc/sql_report_cyborg_death(var/mob/living/silicon/robot/H)
|
||||
lakey = sanitizeSQL(H.lastattacker:key)
|
||||
var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
|
||||
var/coord = "[H.x], [H.y], [H.z]"
|
||||
// to_chat(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.Connect())
|
||||
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/DBQuery/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()
|
||||
if(!sqllogging)
|
||||
@@ -130,14 +126,15 @@ proc/sql_commit_feedback()
|
||||
if(!content)
|
||||
log_game("Round ended without any feedback being generated. No feedback was sent to the database.")
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
|
||||
if(!SSdbcore.Connect())
|
||||
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")
|
||||
max_query.Execute()
|
||||
var/datum/DBQuery/max_query = SSdbcore.NewQuery("SELECT MAX(roundid) AS max_round_id FROM erro_feedback")
|
||||
if(!max_query.Execute())
|
||||
log_sql("Error: [max_query.ErrorMsg()]")
|
||||
qdel(max_query)
|
||||
|
||||
var/newroundid
|
||||
|
||||
@@ -156,7 +153,8 @@ proc/sql_commit_feedback()
|
||||
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/DBQuery/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")
|
||||
qdel(query)
|
||||
|
||||
7
code/libs/BSQL/LICENSE
Normal file
7
code/libs/BSQL/LICENSE
Normal file
@@ -0,0 +1,7 @@
|
||||
Copyright 2018 Jordan Brown
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
68
code/libs/BSQL/core/connection.dm
Normal file
68
code/libs/BSQL/core/connection.dm
Normal file
@@ -0,0 +1,68 @@
|
||||
/datum/BSQL_Connection
|
||||
var/id
|
||||
var/connection_type
|
||||
|
||||
BSQL_PROTECT_DATUM(/datum/BSQL_Connection)
|
||||
|
||||
/datum/BSQL_Connection/New(connection_type, asyncTimeout, blockingTimeout, threadLimit)
|
||||
if(asyncTimeout == null)
|
||||
asyncTimeout = BSQL_DEFAULT_TIMEOUT
|
||||
if(blockingTimeout == null)
|
||||
blockingTimeout = asyncTimeout
|
||||
if(threadLimit == null)
|
||||
threadLimit = BSQL_DEFAULT_THREAD_LIMIT
|
||||
|
||||
src.connection_type = connection_type
|
||||
|
||||
world._BSQL_InitCheck(src)
|
||||
|
||||
var/error = world._BSQL_Internal_Call("CreateConnection", connection_type, "[asyncTimeout]", "[blockingTimeout]", "[threadLimit]")
|
||||
if(error)
|
||||
BSQL_ERROR(error)
|
||||
return
|
||||
|
||||
id = world._BSQL_Internal_Call("GetConnection")
|
||||
if(!id)
|
||||
BSQL_ERROR("BSQL library failed to provide connect operation for connection id [id]([connection_type])!")
|
||||
|
||||
BSQL_DEL_PROC(/datum/BSQL_Connection)
|
||||
var/error
|
||||
if(id)
|
||||
error = world._BSQL_Internal_Call("ReleaseConnection", id)
|
||||
. = ..()
|
||||
if(error)
|
||||
BSQL_ERROR(error)
|
||||
|
||||
/datum/BSQL_Connection/BeginConnect(ipaddress, port, username, password, database)
|
||||
var/error = world._BSQL_Internal_Call("OpenConnection", id, ipaddress, "[port]", username, password, database)
|
||||
if(error)
|
||||
BSQL_ERROR(error)
|
||||
return
|
||||
|
||||
var/op_id = world._BSQL_Internal_Call("GetOperation")
|
||||
if(!op_id)
|
||||
BSQL_ERROR("Library failed to provide connect operation for connection id [id]([connection_type])!")
|
||||
return
|
||||
|
||||
return new /datum/BSQL_Operation(src, op_id)
|
||||
|
||||
|
||||
/datum/BSQL_Connection/BeginQuery(query)
|
||||
var/error = world._BSQL_Internal_Call("NewQuery", id, query)
|
||||
if(error)
|
||||
BSQL_ERROR(error)
|
||||
return
|
||||
|
||||
var/op_id = world._BSQL_Internal_Call("GetOperation")
|
||||
if(!op_id)
|
||||
BSQL_ERROR("Library failed to provide query operation for connection id [id]([connection_type])!")
|
||||
return
|
||||
|
||||
return new /datum/BSQL_Operation/Query(src, op_id)
|
||||
|
||||
/datum/BSQL_Connection/Quote(str)
|
||||
if(!str)
|
||||
return null;
|
||||
. = world._BSQL_Internal_Call("QuoteString", id, "[str]")
|
||||
if(!.)
|
||||
BSQL_ERROR("Library failed to provide quote for [str]!")
|
||||
43
code/libs/BSQL/core/library.dm
Normal file
43
code/libs/BSQL/core/library.dm
Normal file
@@ -0,0 +1,43 @@
|
||||
/world/proc/_BSQL_Internal_Call(func, ...)
|
||||
var/list/call_args = args.Copy(2)
|
||||
BSQL_Debug("[.....]: [args[1]]([call_args.Join(", ")])")
|
||||
. = call(_BSQL_Library_Path(), func)(arglist(call_args))
|
||||
BSQL_Debug("Result: [. == null ? "NULL" : "\"[.]\""]")
|
||||
|
||||
/world/proc/_BSQL_Library_Path()
|
||||
return system_type == MS_WINDOWS ? "BSQL.dll" : "libBSQL.so"
|
||||
|
||||
/world/proc/_BSQL_InitCheck(datum/BSQL_Connection/caller)
|
||||
var/static/library_initialized = FALSE
|
||||
if(_BSQL_Initialized())
|
||||
return
|
||||
var/libPath = _BSQL_Library_Path()
|
||||
if(!fexists(libPath))
|
||||
BSQL_DEL_CALL(caller)
|
||||
BSQL_ERROR("Could not find [libPath]!")
|
||||
return
|
||||
|
||||
var/version = _BSQL_Internal_Call("Version")
|
||||
if(version != BSQL_VERSION)
|
||||
BSQL_DEL_CALL(caller)
|
||||
BSQL_ERROR("BSQL DMAPI version mismatch! Expected [BSQL_VERSION], got [version == null ? "NULL" : version]!")
|
||||
return
|
||||
|
||||
var/result = _BSQL_Internal_Call("Initialize")
|
||||
if(result)
|
||||
BSQL_DEL_CALL(caller)
|
||||
BSQL_ERROR(result)
|
||||
return
|
||||
_BSQL_Initialized(TRUE)
|
||||
|
||||
/world/proc/_BSQL_Initialized(new_val)
|
||||
var/static/bsql_library_initialized = FALSE
|
||||
if(new_val != null)
|
||||
bsql_library_initialized = new_val
|
||||
return bsql_library_initialized
|
||||
|
||||
/world/BSQL_Shutdown()
|
||||
if(!_BSQL_Initialized())
|
||||
return
|
||||
_BSQL_Internal_Call("Shutdown")
|
||||
_BSQL_Initialized(FALSE)
|
||||
47
code/libs/BSQL/core/operation.dm
Normal file
47
code/libs/BSQL/core/operation.dm
Normal file
@@ -0,0 +1,47 @@
|
||||
/datum/BSQL_Operation
|
||||
var/datum/BSQL_Connection/connection
|
||||
var/id
|
||||
|
||||
BSQL_PROTECT_DATUM(/datum/BSQL_Operation)
|
||||
|
||||
/datum/BSQL_Operation/New(datum/BSQL_Connection/connection, id)
|
||||
src.connection = connection
|
||||
src.id = id
|
||||
|
||||
BSQL_DEL_PROC(/datum/BSQL_Operation)
|
||||
var/error
|
||||
if(!BSQL_IS_DELETED(connection))
|
||||
error = world._BSQL_Internal_Call("ReleaseOperation", connection.id, id)
|
||||
. = ..()
|
||||
if(error)
|
||||
BSQL_ERROR(error)
|
||||
|
||||
/datum/BSQL_Operation/IsComplete()
|
||||
if(BSQL_IS_DELETED(connection))
|
||||
return TRUE
|
||||
var/result = world._BSQL_Internal_Call("OpComplete", connection.id, id)
|
||||
if(!result)
|
||||
BSQL_ERROR("Error fetching operation [id] for connection [connection.id]!")
|
||||
return
|
||||
return result == "DONE"
|
||||
|
||||
/datum/BSQL_Operation/GetError()
|
||||
if(BSQL_IS_DELETED(connection))
|
||||
return "Connection deleted!"
|
||||
return world._BSQL_Internal_Call("GetError", connection.id, id)
|
||||
|
||||
/datum/BSQL_Operation/GetErrorCode()
|
||||
if(BSQL_IS_DELETED(connection))
|
||||
return -2
|
||||
return text2num(world._BSQL_Internal_Call("GetErrorCode", connection.id, id))
|
||||
|
||||
/datum/BSQL_Operation/WaitForCompletion()
|
||||
if(BSQL_IS_DELETED(connection))
|
||||
return
|
||||
var/error = world._BSQL_Internal_Call("BlockOnOperation", connection.id, id)
|
||||
if(error)
|
||||
if(error == "Operation timed out!") //match this with the implementation
|
||||
return FALSE
|
||||
BSQL_ERROR("Error waiting for operation [id] for connection [connection.id]! [error]")
|
||||
return
|
||||
return TRUE
|
||||
35
code/libs/BSQL/core/query.dm
Normal file
35
code/libs/BSQL/core/query.dm
Normal file
@@ -0,0 +1,35 @@
|
||||
/datum/BSQL_Operation/Query
|
||||
var/last_result_json
|
||||
var/list/last_result
|
||||
|
||||
BSQL_PROTECT_DATUM(/datum/BSQL_Operation/Query)
|
||||
|
||||
/datum/BSQL_Operation/Query/CurrentRow()
|
||||
return last_result
|
||||
|
||||
/datum/BSQL_Operation/Query/IsComplete()
|
||||
//whole different ballgame here
|
||||
if(BSQL_IS_DELETED(connection))
|
||||
return TRUE
|
||||
var/result = world._BSQL_Internal_Call("ReadyRow", connection.id, id)
|
||||
switch(result)
|
||||
if("DONE")
|
||||
//load the data
|
||||
LoadQueryResult()
|
||||
return TRUE
|
||||
if("NOTDONE")
|
||||
return FALSE
|
||||
else
|
||||
BSQL_ERROR(result)
|
||||
|
||||
/datum/BSQL_Operation/Query/WaitForCompletion()
|
||||
. = ..()
|
||||
if(.)
|
||||
LoadQueryResult()
|
||||
|
||||
/datum/BSQL_Operation/Query/proc/LoadQueryResult()
|
||||
last_result_json = world._BSQL_Internal_Call("GetRow", connection.id, id)
|
||||
if(last_result_json)
|
||||
last_result = json_decode(last_result_json)
|
||||
else
|
||||
last_result = null
|
||||
4
code/libs/BSQL/includes.dm
Normal file
4
code/libs/BSQL/includes.dm
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "core\connection.dm"
|
||||
#include "core\library.dm"
|
||||
#include "core\operation.dm"
|
||||
#include "core\query.dm"
|
||||
@@ -1,38 +0,0 @@
|
||||
// Contains all of the various defines and constants required by the library.
|
||||
|
||||
//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
|
||||
@@ -1,179 +0,0 @@
|
||||
//var/const
|
||||
//DB_SERVER = "localhost" // This is the location of your MySQL server (localhost is USUALLY fine)
|
||||
//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.
|
||||
//server = DB_SERVER // "localhost"
|
||||
var/server = "localhost"
|
||||
//port = DB_PORT // 3306
|
||||
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(!src) return 0
|
||||
if(!sqllogging || !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)
|
||||
|
||||
//IsConnected() return _dm_db_is_connected(_db_con)
|
||||
DBConnection/proc/IsConnected() return !sqllogging ? 0 : _dm_db_is_connected(_db_con)
|
||||
|
||||
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]:[sqladdress]:[sqlport]"]",user,password)
|
||||
|
||||
DBConnection/proc/NewQuery(sql_query,cursor_handler=src.default_cursor) return new/DBQuery(sql_query,src,cursor_handler)
|
||||
|
||||
|
||||
DBQuery
|
||||
var/closed = 0 // N3X: Explicitly closed?
|
||||
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/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 ..()
|
||||
|
||||
|
||||
// DO NOT CHANGE TO DESTROY() - N3X
|
||||
DBQuery/Del()
|
||||
Close()
|
||||
|
||||
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()
|
||||
if(closed)
|
||||
return // Don't do this twice.
|
||||
closed=1
|
||||
item.len = 0
|
||||
columns = null
|
||||
conversions = null
|
||||
return _dm_db_close(_db_query)
|
||||
|
||||
DBQuery/proc/Quote(str)
|
||||
return db_connection.Quote(str)
|
||||
|
||||
/* SetConversion(column,conversion)
|
||||
// This doesn't seem to be doing anything internally...
|
||||
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"
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
|
||||
Dantom.DB
|
||||
Created by BYOND for BYOND, 2002.
|
||||
|
||||
Release History:
|
||||
v0.6 Nov 22, 2013 (Nadrew)
|
||||
v0.5 Mar 23, 2008 (Nadrew)
|
||||
v0.4 Mar 19, 2008 (Nadrew)
|
||||
v0.3 Feb 08, 2006 (Nadrew)
|
||||
v0.2 Jan 31, 2003 (Dan)
|
||||
v0.1 Nov 30, 2002 (Dan)
|
||||
|
||||
Updates:
|
||||
|
||||
v0.6 - Updated the documentation.
|
||||
Commented out DBQuery.SetConversion(), my tests show it doing absolutely nothing to the resulting data.
|
||||
Moved the defines into their own file to reduce the clutter in core.dm
|
||||
Cleaned up the commenting of the code and the code itself a bit more.
|
||||
|
||||
v0.5 - Added DBConnection.SelectDB() see db.html for details.
|
||||
Changed all global constants to quicker #defines.
|
||||
Added global variables DB_SERVER and DB_PORT to help SelectDB() out.
|
||||
Moved this information and the core code into seperate files.
|
||||
|
||||
|
||||
v0.4 - Cleaned up the code even more.
|
||||
Rewrote the argument names for the procs to be less cryptic (you know, Dancode-y).
|
||||
Added a few comments here and there.
|
||||
Sped up various procs by "modernizing" some of the code inside of them.
|
||||
Wrote some actual documentation for the library, since as of 413.00 it should get a bit more usage.
|
||||
|
||||
v0.3 - Fixed long-standing bug with the connection process, adding a workaround to a strange BYOND bug.
|
||||
Updated all of the command arguments to not match local variables, as it was causing tons of issues.
|
||||
The arguments aren't named very well, but you can tell what they do.
|
||||
Added GetRowData() function to the DBQuery datum, this function will allow you to obtain a list of
|
||||
table data referenced by name and not by index number.
|
||||
|
||||
v0.2 - Cleaned up the code significantly.
|
||||
|
||||
See db.html for documentation.
|
||||
See core.dm for guts.
|
||||
See constants.dm for #defines and constants.
|
||||
|
||||
*/
|
||||
@@ -1,23 +0,0 @@
|
||||
// DM Environment file for Dantom.DB.dme.
|
||||
|
||||
// All manual changes should be made outside the BEGIN_ and END_ blocks.
|
||||
|
||||
// New source code should be placed in .dm files: choose File/New --> Code File.
|
||||
|
||||
|
||||
|
||||
// BEGIN_INTERNALS
|
||||
/*
|
||||
FILE: db.html
|
||||
*/
|
||||
// END_INTERNALS
|
||||
// BEGIN_FILE_DIR
|
||||
#define FILE_DIR .
|
||||
// END_FILE_DIR
|
||||
|
||||
|
||||
// BEGIN_PREFERENCES
|
||||
#define DEBUG
|
||||
// END_PREFERENCES
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
|
||||
<title>Dantom.DB Documentation</title>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<base target="contentframe">
|
||||
|
||||
<h2>Dantom.DB</h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<table width=100% height=100%><tr><td width=25% valign=top>
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href=dbinfo.html#DBConnection>DBConnection</a>
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href=dbinfo.html#DBConnection.Connect()>Connect()</a></li>
|
||||
|
||||
<li><a href=dbinfo.html#DBConnection.Disconnect()>Disconnect()</a></li>
|
||||
|
||||
<li><a href=dbinfo.html#DBConnection.IsConnected()>IsConnected()</a></li>
|
||||
|
||||
<li><a href=dbinfo.html#DBConnection.Quote()>Quote()</a></li>
|
||||
|
||||
<li><a href=dbinfo.html#DBConnection.ErrorMsg()>ErrorMsg()</a></li>
|
||||
|
||||
<li><a href=dbinfo.html#DBConnection.SelectDB()>SelectDB()</a></li>
|
||||
|
||||
<li><a href=dbinfo.html#DBConnection.NewQuery()>NewQuery()</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li><a href=dbinfo.html#DBQuery>DBQuery</a>
|
||||
@@ -1,142 +0,0 @@
|
||||
<b>Note:</b> I wrote this document to the best of my knowledge, I still don't know everything there is to know about this library or MySQL. - Nadrew<p>
|
||||
|
||||
<h2><a name="DBConnection">DBConnection</a></h2>
|
||||
|
||||
The DBConnection datum is what handles your connection to the MySQL database.
|
||||
|
||||
<br><b>A note on the DBI string's format, it's "dbi:mysql:[database_name]:[server]:[port]"</b>
|
||||
<p style="color:red;"><b>If libMySQL (.dll/.so) does not exist on the system DBConnection.ErrorMsg() will return 'The selected module could not be loaded.'</b></p>
|
||||
|
||||
<hr>
|
||||
|
||||
<font size=+1><b><a name="DBConnection.Connect()">Connect()</a></b></font><br>
|
||||
|
||||
Creates a new connection to your MySQL server.<br>
|
||||
|
||||
<b>Format:</b> Connect(dbi,username,password,cursor)<br>
|
||||
|
||||
<b>Arguments:</b>
|
||||
|
||||
<dd><b>dbi</b> The database interface string to send to MySQL.
|
||||
|
||||
<dd><b>username</b> The MySQL username to send.
|
||||
|
||||
<dd><b>password</b> The MySQL password associated with the username.
|
||||
|
||||
<dd><b>cursor</b> The MySQL cursor to connect with, best not to set this.<p>
|
||||
|
||||
<b>Example:</b><br>
|
||||
|
||||
<pre>
|
||||
|
||||
var/DBConnection/dbcon = new()
|
||||
|
||||
dbcon.Connect("dbi:mysql:database_name:localhost:3306","username","password")
|
||||
|
||||
if(!dbcon.IsConnected()) usr << dbcon.ErrorMsg()
|
||||
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<font size=+1><b><a name="DBConnection.Disconnect()">Disconnect()</a></b></font><br>
|
||||
|
||||
Disconnects the current MySQL database connection.
|
||||
|
||||
<hr>
|
||||
|
||||
<font size=+1><b><a name="DBConnection.IsConnected()">IsConnected()</a></b></font><br>
|
||||
|
||||
Returns true if the DBConnection object has a connection, false otherwise.
|
||||
|
||||
<hr>
|
||||
|
||||
<font size=+1><b><a name="DBConnection.Quote()">Quote()</a></b></font><br>
|
||||
|
||||
This will escape the string passed using the MySQL escaping function, this will prevent against things like data injection attacks<br>
|
||||
|
||||
<b>Format:</b> Quote(string)<br>
|
||||
|
||||
<b>Arguments:</b>
|
||||
|
||||
<dd><b>string</b> The string you want to escape.<hr>
|
||||
|
||||
<font size=+1><b><a name="DBConnection.ErrorMsg()">ErrorMsg()</a></b></font><br>
|
||||
|
||||
This will return the error message (if any) given by the MySQL server. For an example of the usage, check the example under <a href="#DBConnection.Connect()">Connect()</a>.<hr>
|
||||
|
||||
<font size=+1><b><a name="DBConnection.SelectDB()">SelectDB()</a></b></font><br>
|
||||
|
||||
This allows you to quickly change the database your DBConnection object is acting on.<br>
|
||||
|
||||
<b>Format:</b> SelectDB(database,dbi)<br>
|
||||
|
||||
<b>Arguments:</b>
|
||||
|
||||
<dd><b>database</b> The database you wish to switch to.
|
||||
|
||||
<dd><b>dbi</b> (Optional) The dbi string you want to use to make the switch.<hr>
|
||||
|
||||
<font size=+1><b><a name="DBConnection.NewQuery()">NewQuery()</a></b></font><br>
|
||||
|
||||
This is a nice handy function that'll handle the creation of new query objects for you and return the resulting object.<br>
|
||||
|
||||
<b>Format:</b> NewQuery(query,cursor)<br>
|
||||
|
||||
<b>Arguments:</b>
|
||||
|
||||
<dd><b>query</b> The SQL query you want to execute.
|
||||
|
||||
<dd><b>cursor</b> As usual, best to leave this one alone ;)<br>
|
||||
|
||||
<b>Example:</b><br>
|
||||
|
||||
<pre>
|
||||
|
||||
var/DBQuery/my_query = dbcon.NewQuery("SELECT * FROM `my_table`")
|
||||
|
||||
if(my_query.RowCount()) usr << "Got some data."
|
||||
|
||||
else usr << "No data there!"
|
||||
|
||||
</pre><hr>
|
||||
|
||||
<h2><a name="DBQuery">DBQuery</a></h2>
|
||||
|
||||
The DBQuery datum is what handles executing SQL queries and contains all of the various data given by that query.
|
||||
|
||||
<hr>
|
||||
|
||||
<font size=+1><b><a name="DBQuery.Connect()">Connect()</a></b></font><br>
|
||||
|
||||
This proc is a way of quickly changing the DBConnection object the query object is connected to.<br>
|
||||
|
||||
<b>Format:</b> Connect(DBConnection)<br>
|
||||
|
||||
<b>Arguments:</b>
|
||||
|
||||
<dd><b>DBConnection</b> The new /DBConnection object to associate with this query.<hr>
|
||||
|
||||
<font size=+1><b><a name="DBQuery.Execute()">Execute()</a></b></font><br>
|
||||
|
||||
Executes a SQL query and returns true if the query succeded or false otherwise. If no query is passed this will execute the last query sent to the object (which is set if a query is passed to NewQuery())<br>
|
||||
|
||||
<b>Format:</b> Execute(query,cursor)<br>
|
||||
|
||||
<b>Arguments:</b>
|
||||
|
||||
<dd><b>query</b> The SQL query to execute.
|
||||
|
||||
<dd><b>cursor</b> Seriously, if you don't know what this is, no touching!<br>
|
||||
|
||||
<b>Example:</b><br>
|
||||
|
||||
<pre>
|
||||
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT * FROM `my_table`")
|
||||
|
||||
if(!query.Execute()) usr << query.ErrorMsg()
|
||||
|
||||
else usr << "The query worked!"
|
||||
|
||||
</pre><hr>
|
||||
@@ -5,8 +5,7 @@
|
||||
if(!check_rights(R_BAN))
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
return
|
||||
|
||||
var/serverip = "[world.internet_address]:[world.port]"
|
||||
@@ -56,11 +55,16 @@
|
||||
else if(banckey)
|
||||
ckey = ckey(banckey)
|
||||
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT id FROM erro_player WHERE ckey = '[ckey]'")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("SELECT id FROM erro_player WHERE ckey = '[ckey]'")
|
||||
if(!query.Execute())
|
||||
message_admins("Error: [query.ErrorMsg()]")
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
var/validckey = 0
|
||||
if(query.NextRow())
|
||||
validckey = 1
|
||||
qdel(query)
|
||||
if(!validckey)
|
||||
if(!banned_mob || (banned_mob && !IsGuestKey(banned_mob.key)))
|
||||
message_admins("<span class='red'>[key_name_admin(usr)] attempted to ban [ckey], but [ckey] has not been seen yet. Please only ban actual players.</span>",1)
|
||||
@@ -92,8 +96,13 @@
|
||||
reason = sql_sanitize_text(reason)
|
||||
|
||||
var/sql = "INSERT INTO erro_ban (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`) VALUES (null, Now(), '[serverip]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], [(rounds)?"[rounds]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', '[ip]', '[a_ckey]', '[a_computerid]', '[a_ip]', '[who]', '[adminwho]', '', null, null, null, null, null)"
|
||||
var/DBQuery/query_insert = dbcon.NewQuery(sql)
|
||||
query_insert.Execute()
|
||||
var/datum/DBQuery/query_insert = SSdbcore.NewQuery(sql)
|
||||
if(!query_insert.Execute())
|
||||
message_admins("Error: [query_insert.ErrorMsg()]")
|
||||
log_sql("Error: [query_insert.ErrorMsg()]")
|
||||
qdel(query_insert)
|
||||
return
|
||||
qdel(query_insert)
|
||||
to_chat(usr, "<span class='notice'>Ban saved to database.</span>")
|
||||
message_admins("[key_name_admin(usr)] has added a [bantype_str] for [ckey] [(job)?"([job])":""] [(duration > 0)?"([duration] minutes)":""] with the reason: \"[reason]\" to the ban database.",1)
|
||||
|
||||
@@ -151,19 +160,22 @@ datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "")
|
||||
if(job)
|
||||
sql += " AND job = '[job]'"
|
||||
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
return
|
||||
|
||||
var/ban_id
|
||||
var/ban_number = 0 //failsafe
|
||||
|
||||
var/DBQuery/query = dbcon.NewQuery(sql)
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery(sql)
|
||||
if(!query.Execute())
|
||||
message_admins("Error: [query.ErrorMsg()]")
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
while(query.NextRow())
|
||||
ban_id = query.item[1]
|
||||
ban_number++;
|
||||
|
||||
qdel(query)
|
||||
if(ban_number == 0)
|
||||
to_chat(usr, "<span class='warning'>Database update failed due to no bans fitting the search criteria. If this is not a legacy ban you should contact the database admin.</span>")
|
||||
return
|
||||
@@ -190,8 +202,12 @@ datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
|
||||
to_chat(usr, "Cancelled")
|
||||
return
|
||||
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT ckey, duration, reason FROM erro_ban WHERE id = [banid]")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("SELECT ckey, duration, reason FROM erro_ban WHERE id = [banid]")
|
||||
if(!query.Execute())
|
||||
message_admins("Error: [query.ErrorMsg()]")
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
var/eckey = usr.ckey //Editing admin ckey
|
||||
var/pckey //(banned) Player ckey
|
||||
@@ -204,8 +220,9 @@ datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
|
||||
reason = query.item[3]
|
||||
else
|
||||
to_chat(usr, "Invalid ban id. Contact the database admin")
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
qdel(query)
|
||||
reason = sql_sanitize_text(reason)
|
||||
var/value
|
||||
|
||||
@@ -218,9 +235,14 @@ datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
|
||||
to_chat(usr, "Cancelled")
|
||||
return
|
||||
|
||||
var/DBQuery/update_query = dbcon.NewQuery("UPDATE erro_ban SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from <cite><b>\\\"[reason]\\\"</b></cite> to <cite><b>\\\"[value]\\\"</b></cite><BR>') WHERE id = [banid]")
|
||||
update_query.Execute()
|
||||
var/datum/DBQuery/update_query = SSdbcore.NewQuery("UPDATE erro_ban SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from <cite><b>\\\"[reason]\\\"</b></cite> to <cite><b>\\\"[value]\\\"</b></cite><BR>') WHERE id = [banid]")
|
||||
if(!update_query.Execute())
|
||||
message_admins("Error: [update_query.ErrorMsg()]")
|
||||
log_sql("Error: [update_query.ErrorMsg()]")
|
||||
qdel(update_query)
|
||||
return
|
||||
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s reason from [reason] to [value]",1)
|
||||
qdel(update_query)
|
||||
if("duration")
|
||||
if(!value)
|
||||
value = input("Insert the new duration (in minutes) for [pckey]'s ban", "New Duration", "[duration]", null) as null|num
|
||||
@@ -228,9 +250,14 @@ datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
|
||||
to_chat(usr, "Cancelled")
|
||||
return
|
||||
|
||||
var/DBQuery/update_query = dbcon.NewQuery("UPDATE erro_ban SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value]<br>'), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]")
|
||||
var/datum/DBQuery/update_query = SSdbcore.NewQuery("UPDATE erro_ban SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value]<br>'), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]")
|
||||
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s duration from [duration] to [value]",1)
|
||||
update_query.Execute()
|
||||
if(!update_query.Execute())
|
||||
message_admins("Error: [update_query.ErrorMsg()]")
|
||||
log_sql("Error: [update_query.ErrorMsg()]")
|
||||
qdel(update_query)
|
||||
return
|
||||
qdel(update_query)
|
||||
if("unban")
|
||||
if(alert("Unban [pckey]?", "Unban?", "Yes", "No") == "Yes")
|
||||
DB_ban_unban_by_id(banid)
|
||||
@@ -250,19 +277,22 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
|
||||
|
||||
var/sql = "SELECT ckey FROM erro_ban WHERE id = [id]"
|
||||
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
return
|
||||
|
||||
var/ban_number = 0 //failsafe
|
||||
|
||||
var/pckey
|
||||
var/DBQuery/query = dbcon.NewQuery(sql)
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery(sql)
|
||||
if(!query.Execute())
|
||||
message_admins("Error: [query.ErrorMsg()]")
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
while(query.NextRow())
|
||||
pckey = query.item[1]
|
||||
ban_number++;
|
||||
|
||||
qdel(query)
|
||||
if(ban_number == 0)
|
||||
to_chat(usr, "<span class='warning'>Database update failed due to a ban id not being present in the database.</span>")
|
||||
return
|
||||
@@ -281,8 +311,13 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
|
||||
var/sql_update = "UPDATE erro_ban SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey = '[unban_ckey]', unbanned_computerid = '[unban_computerid]', unbanned_ip = '[unban_ip]' WHERE id = [id]"
|
||||
message_admins("[key_name_admin(usr)] has lifted [pckey]'s ban.",1)
|
||||
|
||||
var/DBQuery/query_update = dbcon.NewQuery(sql_update)
|
||||
query_update.Execute()
|
||||
var/datum/DBQuery/query_update = SSdbcore.NewQuery(sql_update)
|
||||
if(!query_update.Execute())
|
||||
message_admins("Error: [query_update.ErrorMsg()]")
|
||||
log_sql("Error: [query_update.ErrorMsg()]")
|
||||
qdel(query_update)
|
||||
return
|
||||
qdel(query_update)
|
||||
|
||||
INVOKE_EVENT(on_unban,list(
|
||||
"id"=id,
|
||||
@@ -308,8 +343,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
|
||||
if(!check_rights(R_BAN))
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
to_chat(usr, "<span class='warning'>Failed to establish database connection</span>")
|
||||
return
|
||||
|
||||
@@ -383,8 +417,12 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
|
||||
if(playerckey)
|
||||
playersearch = "AND ckey = '[playerckey]' "
|
||||
|
||||
var/DBQuery/select_query = dbcon.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits FROM erro_ban WHERE 1 [playersearch] [adminsearch] ORDER BY bantime DESC")
|
||||
select_query.Execute()
|
||||
var/datum/DBQuery/select_query = SSdbcore.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits FROM erro_ban WHERE 1 [playersearch] [adminsearch] ORDER BY bantime DESC")
|
||||
if(!select_query.Execute())
|
||||
qdel(select_query)
|
||||
message_admins("Error: [select_query.ErrorMsg()]")
|
||||
log_sql("Error: [select_query.ErrorMsg()]")
|
||||
return
|
||||
|
||||
while(select_query.NextRow())
|
||||
var/banid = select_query.item[1]
|
||||
@@ -470,5 +508,6 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
|
||||
</tr>"}
|
||||
|
||||
output += "</table></div>"
|
||||
qdel(select_query)
|
||||
|
||||
usr << browse(output,"window=lookupbans;size=900x500")
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
|
||||
var/ckeytext = ckey(key)
|
||||
|
||||
if(!establish_db_connection())
|
||||
if(!SSdbcore.Connect())
|
||||
world.log << "Ban database connection failure. Key [ckeytext] not checked"
|
||||
diary << "Ban database connection failure. Key [ckeytext] not checked"
|
||||
return
|
||||
@@ -68,9 +68,13 @@
|
||||
failedcid = 0
|
||||
cidquery = " OR computerid = '[computer_id]' "
|
||||
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM erro_ban WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM erro_ban WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
|
||||
|
||||
query.Execute()
|
||||
if(!query.Execute())
|
||||
message_admins("Error: [query.ErrorMsg()]")
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
while(query.NextRow())
|
||||
var/pckey = query.item[1]
|
||||
//var/pip = query.item[2]
|
||||
@@ -92,9 +96,10 @@
|
||||
else
|
||||
desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime] \nBan type: [bantype] \nExpires: [expires] \nAppeal: <span class='warning'>No ban appeals link set</span>"
|
||||
log_access("Failed Login: [key] [computer_id] [address] - Banned [desc]")
|
||||
qdel(query)
|
||||
return list("reason"="[bantype]", "desc"="[desc]")
|
||||
//return "[bantype][desc]"
|
||||
|
||||
qdel(query)
|
||||
if (failedcid)
|
||||
message_admins("[key] has logged in with a blank computer id in the ban check.")
|
||||
if (failedip)
|
||||
@@ -113,4 +118,4 @@
|
||||
what.Remove("message")
|
||||
what["desc"] = "[desc]"
|
||||
what["reason"] = "PERMABAN"
|
||||
return . //default pager ban stuff
|
||||
return . //default pager ban stuff
|
||||
|
||||
@@ -131,17 +131,19 @@ var/list/admin_ranks = list() //list of all ranks with associated rights
|
||||
world.SetConfig("APP/admin", ckey, "role=admin")
|
||||
else
|
||||
//The current admin system uses SQL
|
||||
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
world.log << "Failed to connect to database in load_admins(). Reverting to legacy system."
|
||||
diary << "Failed to connect to database in load_admins(). Reverting to legacy system."
|
||||
config.admin_legacy_system = 1
|
||||
load_admins()
|
||||
return
|
||||
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank, level, flags FROM erro_admin")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("SELECT ckey, rank, level, flags FROM erro_admin")
|
||||
if(!query.Execute())
|
||||
message_admins("Error: [query.ErrorMsg()]")
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
while(query.NextRow())
|
||||
var/ckey = query.item[1]
|
||||
var/rank = query.item[2]
|
||||
@@ -158,7 +160,7 @@ var/list/admin_ranks = list() //list of all ranks with associated rights
|
||||
|
||||
if(D.rights & (R_DEBUG|R_SERVER)) // Grant profile/reboot access
|
||||
world.SetConfig("APP/admin", ckey, "role=admin")
|
||||
|
||||
qdel(query)
|
||||
if(!admin_datums)
|
||||
world.log << "The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system."
|
||||
diary << "The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system."
|
||||
|
||||
@@ -927,7 +927,7 @@ var/list/admin_verbs_mod = list(
|
||||
if(D.rights & (R_DEBUG|R_SERVER)) // Grant profile/reboot access
|
||||
world.SetConfig("APP/admin", ckey, "role=admin")
|
||||
else
|
||||
if(!dbcon.IsConnected())
|
||||
if(!SSdbcore.IsConnected())
|
||||
message_admins("Warning, mysql database is not connected.")
|
||||
to_chat(src, "Warning, mysql database is not connected.")
|
||||
return
|
||||
@@ -936,8 +936,11 @@ var/list/admin_verbs_mod = list(
|
||||
verbs -= /client/proc/readmin
|
||||
return
|
||||
var/sql_ckey = sanitizeSQL(ckey(ckey))
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank, level, flags FROM erro_admin WHERE ckey = '[sql_ckey]'")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("SELECT ckey, rank, level, flags FROM erro_admin WHERE ckey = '[sql_ckey]'")
|
||||
if(!query.Execute())
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
while(query.NextRow())
|
||||
var/dckey = query.item[1]
|
||||
var/rank = query.item[2]
|
||||
@@ -955,6 +958,7 @@ var/list/admin_verbs_mod = list(
|
||||
log_admin("[src] re-adminned themselves.")
|
||||
feedback_add_details("admin_verb","RAS")
|
||||
verbs -= /client/proc/readmin
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
/client/proc/achievement()
|
||||
|
||||
@@ -54,7 +54,7 @@ DEBUG
|
||||
appearance_keylist=list()
|
||||
log_admin("appearance_keylist was empty")
|
||||
else
|
||||
if(!establish_db_connection())
|
||||
if(!SSdbcore.Connect())
|
||||
world.log << "Database connection failed. Reverting to the legacy ban system."
|
||||
diary << "Database connection failed. Reverting to the legacy ban system."
|
||||
config.ban_legacy_system = 1
|
||||
@@ -62,13 +62,16 @@ DEBUG
|
||||
return
|
||||
|
||||
//appearance bans
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT ckey FROM erro_ban WHERE bantype = 'APPEARANCE_PERMABAN' AND isnull(unbanned)")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("SELECT ckey FROM erro_ban WHERE bantype = 'APPEARANCE_PERMABAN' AND isnull(unbanned)")
|
||||
if(!query.Execute())
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
while(query.NextRow())
|
||||
var/ckey = query.item[1]
|
||||
|
||||
appearance_keylist.Add("[ckey]")
|
||||
qdel(query)
|
||||
|
||||
/proc/appearance_savebanfile()
|
||||
var/savefile/S=new("data/appearance_full.ban")
|
||||
@@ -96,18 +99,3 @@ DEBUG
|
||||
appearance_savebanfile()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/*
|
||||
proc/DB_ban_isappearancebanned(var/playerckey)
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
return
|
||||
|
||||
var/sqlplayerckey = sql_sanitize_text(ckey(playerckey))
|
||||
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT id FROM erro_ban WHERE CKEY = '[sqlplayerckey]' AND ((bantype = 'APPEARANCE_PERMABAN') OR (bantype = 'APPEARANCE_TEMPBAN' AND expiration_time > Now())) AND unbanned != 1")
|
||||
query.Execute()
|
||||
while(query.NextRow())
|
||||
return 1
|
||||
return 0
|
||||
*/
|
||||
|
||||
@@ -62,7 +62,7 @@ DEBUG
|
||||
jobban_keylist=list()
|
||||
log_admin("jobban_keylist was empty")
|
||||
else
|
||||
if(!establish_db_connection())
|
||||
if(!SSdbcore.Connect())
|
||||
world.log << "Database connection failed. Reverting to the legacy ban system."
|
||||
diary << "Database connection failed. Reverting to the legacy ban system."
|
||||
config.ban_legacy_system = 1
|
||||
@@ -70,24 +70,31 @@ DEBUG
|
||||
return
|
||||
|
||||
//Job permabans
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT ckey, job FROM erro_ban WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("SELECT ckey, job FROM erro_ban WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)")
|
||||
if(!query.Execute())
|
||||
message_admins("Error: [query.ErrorMsg()]")
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
while(query.NextRow())
|
||||
var/ckey = query.item[1]
|
||||
var/job = query.item[2]
|
||||
|
||||
jobban_keylist.Add("[ckey] - [job]")
|
||||
|
||||
qdel(query)
|
||||
//Job tempbans
|
||||
var/DBQuery/query1 = dbcon.NewQuery("SELECT ckey, job FROM erro_ban WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()")
|
||||
query1.Execute()
|
||||
var/datum/DBQuery/query1 = SSdbcore.NewQuery("SELECT ckey, job FROM erro_ban WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()")
|
||||
if(!query1.Execute())
|
||||
log_sql("Error: [query1.ErrorMsg()]")
|
||||
qdel(query1)
|
||||
return
|
||||
|
||||
while(query1.NextRow())
|
||||
var/ckey = query1.item[1]
|
||||
var/job = query1.item[2]
|
||||
|
||||
jobban_keylist.Add("[ckey] - [job]")
|
||||
qdel(query1)
|
||||
|
||||
/proc/jobban_savebanfile()
|
||||
var/savefile/S = new("data/job_full.ban")
|
||||
|
||||
@@ -11,16 +11,20 @@ var/oocban_keylist[0]
|
||||
return oocban_keylist.Add("[M.ckey]")
|
||||
|
||||
/proc/oocban_loadbanfile()
|
||||
if(!establish_db_connection())
|
||||
if(!SSdbcore.Connect())
|
||||
world.log << "Database connection failed. Skipping ooc ban loading"
|
||||
diary << "Database connection failed. Skipping ooc ban loading"
|
||||
return
|
||||
|
||||
//OOC permabans
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT ckey FROM erro_ban WHERE (bantype = 'OOC_PERMABAN' OR (bantype = 'OOC_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("SELECT ckey FROM erro_ban WHERE (bantype = 'OOC_PERMABAN' OR (bantype = 'OOC_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
|
||||
if(!query.Execute())
|
||||
message_admins("Error: [query.ErrorMsg()]")
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
while(query.NextRow())
|
||||
var/ckey = query.item[1]
|
||||
|
||||
oocban_keylist.Add("[ckey]")
|
||||
oocban_keylist.Add("[ckey]")
|
||||
qdel(query)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
set category = "Special Verbs"
|
||||
if(!check_rights(R_POLLING))
|
||||
return
|
||||
if(!dbcon.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
src << "<span class='danger'>Failed to establish database connection.</span>"
|
||||
return
|
||||
var/polltype = input("Choose poll type.","Poll Type") in list("Single Option","Text Reply","Rating","Multiple Choice")
|
||||
@@ -21,28 +21,33 @@
|
||||
var/starttime = SQLtime()
|
||||
var/endtime = input("Set end time for poll as format YYYY-MM-DD HH:MM:SS. All times in server time. HH:MM:SS is optional and 24-hour. Must be later than starting time for obvious reasons.", "Set end time", SQLtime()) as text
|
||||
if(!endtime)
|
||||
to_chat(usr, "<span class='warning'>endtime is null!</span>")
|
||||
return
|
||||
endtime = sanitizeSQL(endtime)
|
||||
var/DBQuery/query_validate_time = dbcon.NewQuery("SELECT STR_TO_DATE('[endtime]','%Y-%c-%d %T')")
|
||||
var/datum/DBQuery/query_validate_time = SSdbcore.NewQuery("SELECT STR_TO_DATE('[endtime]','%Y-%c-%d %T')")
|
||||
if(!query_validate_time.Execute())
|
||||
var/err = query_validate_time.ErrorMsg()
|
||||
log_game("SQL ERROR validating endtime. Error : \[[err]\]\n")
|
||||
log_sql("SQL ERROR validating endtime. Error : \[[err]\]\n")
|
||||
qdel(query_validate_time)
|
||||
return
|
||||
if(query_validate_time.NextRow())
|
||||
endtime = query_validate_time.item[1]
|
||||
if(!endtime)
|
||||
to_chat(src, "Datetime entered is invalid.")
|
||||
return
|
||||
var/DBQuery/query_time_later = dbcon.NewQuery("SELECT DATE('[endtime]') < NOW()")
|
||||
qdel(query_validate_time)
|
||||
var/datum/DBQuery/query_time_later = SSdbcore.NewQuery("SELECT DATE('[endtime]') < NOW()")
|
||||
if(!query_time_later.Execute())
|
||||
var/err = query_time_later.ErrorMsg()
|
||||
log_game("SQL ERROR comparing endtime to NOW(). Error : \[[err]\]\n")
|
||||
log_sql("SQL ERROR comparing endtime to NOW(). Error : \[[err]\]\n")
|
||||
qdel(query_time_later)
|
||||
return
|
||||
if(query_time_later.NextRow())
|
||||
var/checklate = text2num(query_time_later.item[1])
|
||||
if(checklate)
|
||||
src << "Datetime entered is not later than current server time."
|
||||
return
|
||||
qdel(query_time_later)
|
||||
var/adminonly
|
||||
switch(alert("Admin only poll?",,"Yes","No","Cancel"))
|
||||
if("Yes")
|
||||
@@ -55,21 +60,25 @@
|
||||
var/question = input("Write your question","Question") as message
|
||||
if(!question)
|
||||
return
|
||||
question = replacetext(question, "'", "\'")
|
||||
question = sanitizeSQL(question)
|
||||
var/DBQuery/query_polladd_question = dbcon.NewQuery("INSERT INTO erro_poll_question (polltype, starttime, endtime, question, adminonly, multiplechoiceoptions, createdby_ckey, createdby_ip) VALUES ('[polltype]', '[starttime]', '[endtime]', '[question]', '[adminonly]', '[choice_amount]', '[sql_ckey]', '[address]')")
|
||||
var/datum/DBQuery/query_polladd_question = SSdbcore.NewQuery("INSERT INTO erro_poll_question (polltype, starttime, endtime, question, adminonly, multiplechoiceoptions, createdby_ckey, createdby_ip) VALUES ('[polltype]', '[starttime]', '[endtime]', '[question]', '[adminonly]', '[choice_amount]', '[sql_ckey]', '[address]')")
|
||||
if(!query_polladd_question.Execute())
|
||||
var/err = query_polladd_question.ErrorMsg()
|
||||
log_game("SQL ERROR adding new poll question to table. Error : \[[err]\]\n")
|
||||
qdel(query_polladd_question)
|
||||
log_sql("SQL ERROR adding new poll question to table. Error : \[[err]\]\n")
|
||||
return
|
||||
qdel(query_polladd_question)
|
||||
var/pollid = 0
|
||||
var/DBQuery/query_get_id = dbcon.NewQuery("SELECT id FROM erro_poll_question WHERE question = '[question]' AND starttime = '[starttime]' AND endtime = '[endtime]' AND createdby_ckey = '[sql_ckey]' AND createdby_ip = '[address]'")
|
||||
var/datum/DBQuery/query_get_id = SSdbcore.NewQuery("SELECT id FROM erro_poll_question WHERE question = '[question]' AND starttime = '[starttime]' AND endtime = '[endtime]' AND createdby_ckey = '[sql_ckey]' AND createdby_ip = '[address]'")
|
||||
if(!query_get_id.Execute())
|
||||
var/err = query_get_id.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining id from poll_question table. Error : \[[err]\]\n")
|
||||
qdel(query_get_id)
|
||||
log_sql("SQL ERROR obtaining id from poll_question table. Error : \[[err]\]\n")
|
||||
return
|
||||
if(query_get_id.NextRow())
|
||||
pollid = query_get_id.item[1]
|
||||
|
||||
qdel(query_get_id)
|
||||
log_admin("[key_name(src)] created the poll with id [pollid].")
|
||||
message_admins("<span class='notice'>[key_name_admin(src)] created the poll with id [pollid].</span>")
|
||||
|
||||
@@ -113,13 +122,15 @@
|
||||
descmax = input("Optional: Set description for maximum rating","Maximum rating description") as message
|
||||
if(descmax)
|
||||
descmax = sanitizeSQL(descmax)
|
||||
var/DBQuery/query_polladd_option = dbcon.NewQuery("INSERT INTO erro_poll_option (pollid, text, percentagecalc, minval, maxval, descmin, descmid, descmax) VALUES ('[pollid]', '[option]', '[percentagecalc]', '[minval]', '[maxval]', '[descmin]', '[descmid]', '[descmax]')")
|
||||
var/datum/DBQuery/query_polladd_option = SSdbcore.NewQuery("INSERT INTO erro_poll_option (pollid, text, percentagecalc, minval, maxval, descmin, descmid, descmax) VALUES ('[pollid]', '[option]', '[percentagecalc]', '[minval]', '[maxval]', '[descmin]', '[descmid]', '[descmax]')")
|
||||
if(!query_polladd_option.Execute())
|
||||
var/err = query_polladd_option.ErrorMsg()
|
||||
log_game("SQL ERROR adding new poll option to table. Error : \[[err]\]\n")
|
||||
log_sql("SQL ERROR adding new poll option to table. Error : \[[err]\]\n")
|
||||
qdel(query_polladd_option)
|
||||
return
|
||||
qdel(query_polladd_option)
|
||||
switch(alert(" ",,"Add option","Finish"))
|
||||
if("Add option")
|
||||
add_option = 1
|
||||
if("Finish")
|
||||
add_option = 0
|
||||
add_option = 0
|
||||
|
||||
@@ -131,19 +131,38 @@ you will have to do something like if(client.rights & R_ADMIN) yourself.
|
||||
if(recurse==5)
|
||||
return "\[BROKEN\]";
|
||||
recurse++
|
||||
var/DBQuery/query = dbcon.NewQuery("DELETE FROM admin_sessions WHERE expires < Now()")
|
||||
query.Execute()
|
||||
|
||||
query = dbcon.NewQuery("SELECT sessID FROM admin_sessions WHERE ckey = '[owner.ckey]' AND expires > Now()")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("DELETE FROM admin_sessions WHERE expires < Now()")
|
||||
if(!query.Execute())
|
||||
message_admins("Error: [query.ErrorMsg()]")
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
var/datum/DBQuery/sel_query = SSdbcore.NewQuery("SELECT sessID FROM admin_sessions WHERE ckey = '[owner.ckey]' AND expires > Now()")
|
||||
if(!sel_query.Execute())
|
||||
message_admins("Error: [sel_query.ErrorMsg()]")
|
||||
log_sql("Error: [sel_query.ErrorMsg()]")
|
||||
qdel(sel_query)
|
||||
return
|
||||
qdel(sel_query)
|
||||
|
||||
sessKey=0
|
||||
while(query.NextRow())
|
||||
sessKey = query.item[1]
|
||||
query=dbcon.NewQuery("UPDATE admin_sessions SET expires=DATE_ADD(NOW(), INTERVAL 24 HOUR), IP='[owner.address]' WHERE ckey = '[owner.ckey]")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/up_query=SSdbcore.NewQuery("UPDATE admin_sessions SET expires=DATE_ADD(NOW(), INTERVAL 24 HOUR), IP='[owner.address]' WHERE ckey = '[owner.ckey]")
|
||||
if(!up_query.Execute())
|
||||
message_admins("Error: [up_query.ErrorMsg()]")
|
||||
log_sql("Error: [up_query.ErrorMsg()]")
|
||||
qdel(up_query)
|
||||
return
|
||||
qdel(up_query)
|
||||
return sessKey
|
||||
qdel(query)
|
||||
|
||||
query=dbcon.NewQuery("INSERT INTO admin_sessions (sessID,ckey,expires, IP) VALUES (UUID(), '[owner.ckey]', DATE_ADD(NOW(), INTERVAL 24 HOUR), '[owner.address]')")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/insert_query=SSdbcore.NewQuery("INSERT INTO admin_sessions (sessID,ckey,expires, IP) VALUES (UUID(), '[owner.ckey]', DATE_ADD(NOW(), INTERVAL 24 HOUR), '[owner.address]')")
|
||||
if(!insert_query.Execute())
|
||||
message_admins("Error: [insert_query.ErrorMsg()]")
|
||||
log_sql("Error: [insert_query.ErrorMsg()]")
|
||||
qdel(insert_query)
|
||||
return
|
||||
qdel(insert_query)
|
||||
return checkSessionKey(recurse)
|
||||
|
||||
@@ -65,9 +65,7 @@
|
||||
to_chat(usr, "<span class='warning'>You do not have permission to do this!</span>")
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
|
||||
if(!dbcon.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
to_chat(usr, "<span class='warning'>Failed to establish database connection</span>")
|
||||
return
|
||||
|
||||
@@ -82,27 +80,51 @@
|
||||
if(!istext(adm_ckey) || !istext(new_rank))
|
||||
return
|
||||
|
||||
var/DBQuery/select_query = dbcon.NewQuery("SELECT id FROM erro_admin WHERE ckey = '[adm_ckey]'")
|
||||
select_query.Execute()
|
||||
var/datum/DBQuery/select_query = SSdbcore.NewQuery("SELECT id FROM erro_admin WHERE ckey = '[adm_ckey]'")
|
||||
if(!select_query.Execute())
|
||||
message_admins("Error: [select_query.ErrorMsg()]")
|
||||
log_sql("Error: [select_query.ErrorMsg()]")
|
||||
qdel(select_query)
|
||||
return
|
||||
|
||||
var/new_admin = 1
|
||||
var/admin_id
|
||||
while(select_query.NextRow())
|
||||
new_admin = 0
|
||||
admin_id = text2num(select_query.item[1])
|
||||
|
||||
qdel(select_query)
|
||||
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)")
|
||||
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]');")
|
||||
log_query.Execute()
|
||||
var/datum/DBQuery/insert_query = SSdbcore.NewQuery("INSERT INTO `erro_admin` (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)")
|
||||
if(!insert_query.Execute())
|
||||
message_admins("Error: [insert_query.ErrorMsg()]")
|
||||
log_sql("Error: [insert_query.ErrorMsg()]")
|
||||
qdel(insert_query)
|
||||
return
|
||||
qdel(insert_query)
|
||||
var/datum/DBQuery/log_query = SSdbcore.NewQuery("INSERT INTO [sqlfdbkdb].`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]');") // FIXME: [sqlfdbkdb] is the default name of the feedback DB.
|
||||
if(!log_query.Execute())
|
||||
message_admins("Error: [log_query.ErrorMsg()]")
|
||||
log_sql("Error: [log_query.ErrorMsg()]")
|
||||
qdel(log_query)
|
||||
return
|
||||
qdel(log_query)
|
||||
to_chat(usr, "<span class='notice'>New admin added.</span>")
|
||||
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]")
|
||||
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]');")
|
||||
log_query.Execute()
|
||||
var/datum/DBQuery/insert_query = SSdbcore.NewQuery("UPDATE `erro_admin` SET rank = '[new_rank]' WHERE id = [admin_id]")
|
||||
if(!insert_query.Execute())
|
||||
message_admins("Error: [insert_query.ErrorMsg()]")
|
||||
log_sql("Error: [insert_query.ErrorMsg()]")
|
||||
qdel(insert_query)
|
||||
return
|
||||
qdel(insert_query)
|
||||
var/datum/DBQuery/log_query = SSdbcore.NewQuery("INSERT INTO [sqlfdbkdb].`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]');") // FIXME: [sqlfdbkdb] is the default name of the feedback DB.
|
||||
if(!log_query.Execute())
|
||||
message_admins("Error: [log_query.ErrorMsg()]")
|
||||
log_sql("Error: [log_query.ErrorMsg()]")
|
||||
qdel(log_query)
|
||||
return
|
||||
qdel(log_query)
|
||||
to_chat(usr, "<span class='notice'>Admin rank changed.</span>")
|
||||
|
||||
/datum/admins/proc/log_admin_permission_modification(var/adm_ckey, var/new_permission)
|
||||
@@ -116,8 +138,7 @@
|
||||
to_chat(usr, "<span class='warning'>You do not have permission to do this!</span>")
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
to_chat(usr, "<span class='warning'>Failed to establish database connection</span>")
|
||||
return
|
||||
|
||||
@@ -135,27 +156,51 @@
|
||||
if(!istext(adm_ckey) || !isnum(new_permission))
|
||||
return
|
||||
|
||||
var/DBQuery/select_query = dbcon.NewQuery("SELECT id, flags FROM erro_admin WHERE ckey = '[adm_ckey]'")
|
||||
select_query.Execute()
|
||||
var/datum/DBQuery/select_query = SSdbcore.NewQuery("SELECT id, flags FROM erro_admin WHERE ckey = '[adm_ckey]'")
|
||||
if(!select_query.Execute())
|
||||
message_admins("Error: [select_query.ErrorMsg()]")
|
||||
log_sql("Error: [select_query.ErrorMsg()]")
|
||||
qdel(select_query)
|
||||
return
|
||||
|
||||
var/admin_id
|
||||
var/admin_rights
|
||||
while(select_query.NextRow())
|
||||
admin_id = text2num(select_query.item[1])
|
||||
admin_rights = text2num(select_query.item[2])
|
||||
|
||||
qdel(select_query)
|
||||
if(!admin_id)
|
||||
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]")
|
||||
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]');")
|
||||
log_query.Execute()
|
||||
var/datum/DBQuery/insert_query = SSdbcore.NewQuery("UPDATE `erro_admin` SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]")
|
||||
if(!insert_query.Execute())
|
||||
message_admins("Error: [insert_query.ErrorMsg()]")
|
||||
log_sql("Error: [insert_query.ErrorMsg()]")
|
||||
qdel(insert_query)
|
||||
return
|
||||
qdel(insert_query)
|
||||
var/datum/DBQuery/log_query = SSdbcore.NewQuery("INSERT INTO [sqlfdbkdb].`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]');")
|
||||
if(!log_query.Execute())
|
||||
message_admins("Error: [log_query.ErrorMsg()]")
|
||||
log_sql("Error: [log_query.ErrorMsg()]")
|
||||
qdel(log_query)
|
||||
return
|
||||
qdel(log_query)
|
||||
to_chat(usr, "<span class='notice'>Permission removed.</span>")
|
||||
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]")
|
||||
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]')")
|
||||
log_query.Execute()
|
||||
var/datum/DBQuery/insert_query = SSdbcore.NewQuery("UPDATE `erro_admin` SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]")
|
||||
if(!insert_query.Execute())
|
||||
message_admins("Error: [insert_query.ErrorMsg()]")
|
||||
log_sql("Error: [insert_query.ErrorMsg()]")
|
||||
qdel(insert_query)
|
||||
return
|
||||
qdel(insert_query)
|
||||
var/datum/DBQuery/log_query = SSdbcore.NewQuery("INSERT INTO [sqlfdbkdb].`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]')")
|
||||
if(!log_query.Execute())
|
||||
message_admins("Error: [log_query.ErrorMsg()]")
|
||||
log_sql("Error: [log_query.ErrorMsg()]")
|
||||
qdel(log_query)
|
||||
return
|
||||
qdel(log_query)
|
||||
to_chat(usr, "<span class='notice'>Permission added.</span>")
|
||||
|
||||
@@ -32,8 +32,7 @@ var/inactive_keys = "None<br>"
|
||||
if(checked_for_inactives)
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
return
|
||||
|
||||
//grab all ckeys associated with custom items
|
||||
@@ -58,22 +57,31 @@ var/inactive_keys = "None<br>"
|
||||
//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")
|
||||
query_inactive.Execute()
|
||||
var/datum/DBQuery/query_inactive = SSdbcore.NewQuery("SELECT ckey, lastseen FROM erro_player WHERE datediff(Now(), lastseen) > 60")
|
||||
if(!query_inactive.Execute())
|
||||
log_sql("Error: [query_inactive.ErrorMsg()]")
|
||||
qdel(query_inactive)
|
||||
return
|
||||
while(query_inactive.NextRow())
|
||||
var/cur_ckey = query_inactive.item[1]
|
||||
//if the ckey has a custom item attached, output it
|
||||
if(ckeys_with_customitems.Find(cur_ckey))
|
||||
ckeys_with_customitems.Remove(cur_ckey)
|
||||
inactive_ckeys[cur_ckey] = "last seen on [query_inactive.item[2]]"
|
||||
qdel(query_inactive)
|
||||
|
||||
//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/DBQuery/query_inactive = SSdbcore.NewQuery("SELECT ckey FROM erro_player WHERE ckey = '[cur_ckey]'")
|
||||
query_inactive.Execute()
|
||||
if(!query_inactive.RowCount())
|
||||
if(!query_inactive.Execute())
|
||||
log_sql("Error: [query_inactive.ErrorMsg()]")
|
||||
qdel(query_inactive)
|
||||
return
|
||||
if(!query_inactive.item.len)
|
||||
inactive_ckeys += cur_ckey
|
||||
qdel(query_inactive)
|
||||
|
||||
if(inactive_ckeys.len)
|
||||
inactive_keys = ""
|
||||
|
||||
@@ -70,6 +70,13 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
|
||||
if(!procname)
|
||||
return
|
||||
|
||||
// Do not make this a global reference. Global references can be cleared out.
|
||||
if (istype(target, /datum/subsystem/dbcore/))
|
||||
to_chat(usr, "<span class='red'>Never use atom proc call to inject SQL.</span>")
|
||||
message_admins("[key_name(usr)] used atom proc call on the db controller.")
|
||||
log_admin("[key_name(usr)] used atom proc call on the db controller.")
|
||||
return FALSE
|
||||
|
||||
if(target && !hascall(target, procname))
|
||||
to_chat(usr, "<span class='red'>Error: callproc(): target has no such call [procname].</span>")
|
||||
return
|
||||
|
||||
@@ -2,8 +2,14 @@ var/list/forbidden_varedit_object_types = list(
|
||||
/datum/admins, //Admins editing their own admin-power object? Yup, sounds like a good idea.
|
||||
/datum/blackbox, //Prevents people messing with feedback gathering
|
||||
/datum/feedback_variable, //Prevents people messing with feedback gathering
|
||||
/datum/subsystem/dbcore/, // No messing with the database.
|
||||
)
|
||||
|
||||
var/list/unviewable_varedit_object_types = list(
|
||||
/datum/BSQL_Connection/,
|
||||
/datum/BSQL_Operation/,
|
||||
)
|
||||
|
||||
//Interface for editing a variable. It returns its new value. If edited_datum, it automatically changes the edited datum's value
|
||||
//If called with just [user] argument, it allows you to create a value such as a string, a number, an empty list, a nearby object, etc...
|
||||
//If called with [edited_datum] and [edited_variable], you gain the ability to get the variable's initial value.
|
||||
@@ -23,6 +29,9 @@ var/list/forbidden_varedit_object_types = list(
|
||||
if(!C.can_edit_var(edited_variable, edited_datum?.type))
|
||||
return
|
||||
|
||||
if (is_type_in_list(edited_datum, unviewable_varedit_object_types) || BSQL_DEBUG_CONNECTION)
|
||||
return
|
||||
|
||||
//Special case for "appearance", because appearance values can't be stored anywhere.
|
||||
//It's impossible for this proc to return an appearance value, so just set it directly here
|
||||
if((isimage(edited_datum) || isatom(edited_datum)) && edited_variable == "appearance")
|
||||
|
||||
@@ -252,10 +252,9 @@
|
||||
if(IsGuestKey(key))
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
|
||||
if(!dbcon.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
return
|
||||
|
||||
var/list/http[] = world.Export("http://www.byond.com/members/[src.key]?format=text") // Retrieve information from BYOND
|
||||
var/Joined = 2550-01-01
|
||||
if(http && http.len && ("CONTENT" in http))
|
||||
@@ -267,32 +266,43 @@
|
||||
|
||||
var/sql_ckey = sanitizeSQL(ckey)
|
||||
var/age
|
||||
testing("sql_ckey = [sql_ckey]")
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT id, datediff(Now(),firstseen) as age, datediff(Now(),accountjoined) as age2 FROM erro_player WHERE ckey = '[sql_ckey]'")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("SELECT id, datediff(Now(),firstseen) as age, datediff(Now(),accountjoined) as age2 FROM erro_player WHERE ckey = '[sql_ckey]'")
|
||||
if(!query.Execute())
|
||||
message_admins("Error: [query.ErrorMsg()]")
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
var/sql_id = 0
|
||||
while(query.NextRow())
|
||||
sql_id = query.item[1]
|
||||
player_age = text2num(query.item[2])
|
||||
age = text2num(query.item[3])
|
||||
break
|
||||
qdel(query)
|
||||
|
||||
var/sql_address = sanitizeSQL(address)
|
||||
|
||||
var/DBQuery/query_ip = dbcon.NewQuery("SELECT distinct ckey FROM erro_connection_log WHERE ip = '[sql_address]'")
|
||||
query_ip.Execute()
|
||||
var/datum/DBQuery/query_ip = SSdbcore.NewQuery("SELECT distinct ckey FROM erro_connection_log WHERE ip = '[sql_address]'")
|
||||
if(!query_ip.Execute())
|
||||
log_sql("Error: [query_ip.ErrorMsg()]")
|
||||
qdel(query_ip)
|
||||
return
|
||||
related_accounts_ip = ""
|
||||
while(query_ip.NextRow())
|
||||
related_accounts_ip += "[query_ip.item[1]], "
|
||||
|
||||
qdel(query_ip)
|
||||
|
||||
var/sql_computerid = sanitizeSQL(computer_id)
|
||||
|
||||
var/DBQuery/query_cid = dbcon.NewQuery("SELECT distinct ckey FROM erro_connection_log WHERE computerid = '[sql_computerid]'")
|
||||
query_cid.Execute()
|
||||
var/datum/DBQuery/query_cid = SSdbcore.NewQuery("SELECT distinct ckey FROM erro_connection_log WHERE computerid = '[sql_computerid]'")
|
||||
if(!query_cid.Execute())
|
||||
log_sql("Error: [query_cid.ErrorMsg()]")
|
||||
qdel(query_cid)
|
||||
return
|
||||
related_accounts_cid = ""
|
||||
while(query_cid.NextRow())
|
||||
related_accounts_cid += "[query_cid.item[1]], "
|
||||
qdel(query_cid)
|
||||
|
||||
//Just the standard check to see if it's actually a number
|
||||
if(sql_id)
|
||||
@@ -310,27 +320,29 @@
|
||||
|
||||
if(sql_id)
|
||||
//Player already identified previously, we need to just update the 'lastseen', 'ip' and 'computer_id' variables
|
||||
var/DBQuery/query_update
|
||||
var/datum/DBQuery/query_update
|
||||
if(isnum(age))
|
||||
query_update = dbcon.NewQuery("UPDATE erro_player SET lastseen = Now(), ip = '[sql_address]', computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]' WHERE id = [sql_id]")
|
||||
query_update = SSdbcore.NewQuery("UPDATE erro_player SET lastseen = Now(), ip = '[sql_address]', computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]' WHERE id = [sql_id]")
|
||||
else
|
||||
query_update = dbcon.NewQuery("UPDATE erro_player SET lastseen = Now(), ip = '[sql_address]', computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]', accountjoined = '[Joined]' WHERE id = [sql_id]")
|
||||
query_update = SSdbcore.NewQuery("UPDATE erro_player SET lastseen = Now(), ip = '[sql_address]', computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]', accountjoined = '[Joined]' WHERE id = [sql_id]")
|
||||
query_update.Execute()
|
||||
if(query_update.ErrorMsg())
|
||||
WARNING("FINGERPRINT: [query_update.ErrorMsg()]")
|
||||
|
||||
qdel(query_update)
|
||||
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, accountjoined) VALUES (null, '[sql_ckey]', Now(), Now(), '[sql_address]', '[sql_computerid]', '[sql_admin_rank]', '[Joined]')")
|
||||
var/datum/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_player (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank, accountjoined) VALUES (null, '[sql_ckey]', Now(), Now(), '[sql_address]', '[sql_computerid]', '[sql_admin_rank]', '[Joined]')")
|
||||
query_insert.Execute()
|
||||
if(query_insert.ErrorMsg())
|
||||
WARNING("FINGERPRINT: [query_insert.ErrorMsg()]")
|
||||
|
||||
qdel(query_insert)
|
||||
if(!isnum(age))
|
||||
var/DBQuery/query_age = dbcon.NewQuery("SELECT datediff(Now(),accountjoined) as age2 FROM erro_player WHERE ckey = '[sql_ckey]'")
|
||||
query_age.Execute()
|
||||
var/datum/DBQuery/query_age = SSdbcore.NewQuery("SELECT datediff(Now(),accountjoined) as age2 FROM erro_player WHERE ckey = '[sql_ckey]'")
|
||||
if(!query_age.Execute())
|
||||
WARNING("FINGERPRINT: [query_age.ErrorMsg()]")
|
||||
while(query_age.NextRow())
|
||||
age = text2num(query_age.item[1])
|
||||
qdel(query_age)
|
||||
if(!isnum(player_age))
|
||||
player_age = 0
|
||||
if(age < 14)
|
||||
@@ -342,11 +354,12 @@
|
||||
// logging player access
|
||||
var/server_address_port = "[world.internet_address]:[world.port]"
|
||||
var/sql_server_address_port = sanitizeSQL(server_address_port)
|
||||
var/DBQuery/query_connection_log = dbcon.NewQuery("INSERT INTO `erro_connection_log`(`id`,`datetime`,`serverip`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),'[sql_server_address_port]','[sql_ckey]','[sql_address]','[sql_computerid]');")
|
||||
var/datum/DBQuery/query_connection_log = SSdbcore.NewQuery("INSERT INTO `erro_connection_log`(`id`,`datetime`,`serverip`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),'[sql_server_address_port]','[sql_ckey]','[sql_address]','[sql_computerid]');")
|
||||
|
||||
query_connection_log.Execute()
|
||||
if(query_connection_log.ErrorMsg())
|
||||
WARNING("FINGERPRINT: [query_connection_log.ErrorMsg()]")
|
||||
qdel(query_connection_log)
|
||||
|
||||
#undef TOPIC_SPAM_DELAY
|
||||
#undef UPLOAD_LIMIT
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
/proc/EquipCustomItems(mob/living/carbon/human/M)
|
||||
// testing("\[CustomItem\] Checking for custom items for [M.ckey] ([M.real_name])...")
|
||||
if(!establish_db_connection())
|
||||
if(!SSdbcore.Connect())
|
||||
return
|
||||
|
||||
// SCHEMA
|
||||
@@ -19,8 +19,12 @@
|
||||
*/
|
||||
|
||||
// Grab the info we want.
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT cuiPath, cuiPropAdjust, cuiJobMask FROM CustomUserItems WHERE cuiCKey='[M.ckey]' AND (cuiRealName='[M.real_name]' OR cuiRealName='*')")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("SELECT cuiPath, cuiPropAdjust, cuiJobMask FROM CustomUserItems WHERE cuiCKey='[M.ckey]' AND (cuiRealName='[M.real_name]' OR cuiRealName='*')")
|
||||
if(!query.Execute())
|
||||
message_admins("Error: [query.ErrorMsg()]")
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
while(query.NextRow())
|
||||
var/path = text2path(query.item[1])
|
||||
@@ -81,7 +85,7 @@
|
||||
Item.forceMove(get_turf(M.loc))
|
||||
|
||||
HackProperties(Item,propadjust)
|
||||
|
||||
qdel(query)
|
||||
|
||||
// This is hacky, but since it's difficult as fuck to make a proper parser in BYOND without killing the server, here it is. - N3X
|
||||
/proc/HackProperties(var/mob/living/carbon/human/M,var/obj/item/I,var/script)
|
||||
@@ -114,4 +118,4 @@
|
||||
if(typeChunks.len==2)
|
||||
I.vars[varname]=new /icon(typeChunks[2])
|
||||
if(typeChunks.len==3)
|
||||
I.vars[varname]=new /icon(typeChunks[2],typeChunks[3])
|
||||
I.vars[varname]=new /icon(typeChunks[2],typeChunks[3])
|
||||
|
||||
@@ -48,10 +48,12 @@
|
||||
//sql += " [query.toSQL()]"
|
||||
// Pagination
|
||||
// to_chat(world, sql)
|
||||
var/DBQuery/_query = dbcon_old.NewQuery(sql)
|
||||
var/datum/DBQuery/_query = SSdbcore.NewQuery(sql)
|
||||
_query.Execute()
|
||||
if(_query.ErrorMsg())
|
||||
world.log << _query.ErrorMsg()
|
||||
qdel(_query)
|
||||
return
|
||||
|
||||
var/list/results = list()
|
||||
while(_query.NextRow())
|
||||
@@ -64,6 +66,7 @@
|
||||
"ckey" =_query.item[5]
|
||||
))
|
||||
results += CB
|
||||
qdel(_query)
|
||||
return results
|
||||
|
||||
/obj/machinery/computer/library/proc/get_num_results()
|
||||
@@ -71,8 +74,11 @@
|
||||
//if(query)
|
||||
//sql += query.toSQL()
|
||||
|
||||
var/DBQuery/_query = dbcon_old.NewQuery(sql)
|
||||
_query.Execute()
|
||||
var/datum/DBQuery/_query = SSdbcore.NewQuery(sql)
|
||||
if(!_query.Execute())
|
||||
message_admins("Error: [_query.ErrorMsg()]")
|
||||
log_sql("Error: [_query.ErrorMsg()]")
|
||||
return
|
||||
while(_query.NextRow())
|
||||
return text2num(_query.item[1])
|
||||
return 0
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
<A href='?src=\ref[src];switchscreen=0'>(Return to main menu)</A><BR>"}
|
||||
if(4)
|
||||
dat += "<h3>External Archive</h3>"
|
||||
if(!dbcon_old.IsConnected())
|
||||
if(!SSdbcore.IsConnected())
|
||||
dat += "<font color=red><b>ERROR</b>: Unable to contact External Archive. Please contact your system administrator for assistance.</font>"
|
||||
else
|
||||
num_results = src.get_num_results()
|
||||
@@ -267,14 +267,16 @@
|
||||
var/datum/cachedbook/target = getBookByID(href_list["del"]) // Sanitized in getBookByID
|
||||
var/ans = alert(usr, "Are you sure you wish to delete \"[target.title]\", by [target.author]? This cannot be undone.", "Library System", "Yes", "No")
|
||||
if(ans=="Yes")
|
||||
var/DBQuery/query = dbcon_old.NewQuery("DELETE FROM library WHERE id=[target.id]")
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("DELETE FROM library WHERE id=[target.id]")
|
||||
var/response = query.Execute()
|
||||
if(!response)
|
||||
to_chat(usr, query.ErrorMsg())
|
||||
qdel(query)
|
||||
return
|
||||
log_admin("LIBRARY: [usr.name]/[usr.key] has deleted \"[target.title]\", by [target.author] ([target.ckey])!")
|
||||
message_admins("[key_name_admin(usr)] has deleted \"[target.title]\", by [target.author] ([target.ckey])!")
|
||||
src.updateUsrDialog()
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
if(href_list["delbyckey"])
|
||||
@@ -284,17 +286,19 @@
|
||||
var/tckey = ckey(href_list["delbyckey"])
|
||||
var/ans = alert(usr,"Are you sure you wish to delete all books by [tckey]? This cannot be undone.", "Library System", "Yes", "No")
|
||||
if(ans=="Yes")
|
||||
var/DBQuery/query = dbcon_old.NewQuery("DELETE FROM library WHERE ckey='[sanitizeSQL(tckey)]'")
|
||||
var/response = query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("DELETE FROM library WHERE ckey='[sanitizeSQL(tckey)]'")
|
||||
var/datum/DBQuery/response = query.Execute()
|
||||
if(!response)
|
||||
to_chat(usr, query.ErrorMsg())
|
||||
qdel(query)
|
||||
return
|
||||
var/affected=query.RowsAffected()
|
||||
if(affected==0)
|
||||
if(response.item.len==0)
|
||||
to_chat(usr, "<span class='danger'>Unable to find any matching rows.</span>")
|
||||
qdel(query)
|
||||
return
|
||||
log_admin("LIBRARY: [usr.name]/[usr.key] has deleted [affected] books written by [tckey]!")
|
||||
message_admins("[key_name_admin(usr)] has deleted [affected] books written by [tckey]!")
|
||||
log_admin("LIBRARY: [usr.name]/[usr.key] has deleted [response.item.len] books written by [tckey]!")
|
||||
message_admins("[key_name_admin(usr)] has deleted [response.item.len] books written by [tckey]!")
|
||||
qdel(query)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
@@ -390,15 +394,14 @@
|
||||
if(scanner.cache)
|
||||
var/choice = input("Are you certain you wish to upload this title to the Archive?") in list("Confirm", "Abort")
|
||||
if(choice == "Confirm")
|
||||
establish_old_db_connection()
|
||||
if(!dbcon_old.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
alert("Connection to Archive has been severed. Aborting.")
|
||||
else
|
||||
var/sqltitle = sanitizeSQL(scanner.cache.name)
|
||||
var/sqlauthor = sanitizeSQL(scanner.cache.author)
|
||||
var/sqlcontent = sanitizeSQL(scanner.cache.dat)
|
||||
var/sqlcategory = sanitizeSQL(upload_category)
|
||||
var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO library (author, title, content, category, ckey) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]', '[ckey(usr.key)]')")
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("INSERT INTO library (author, title, content, category, ckey) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]', '[ckey(usr.key)]')")
|
||||
var/response = query.Execute()
|
||||
if(!response)
|
||||
to_chat(usr, query.ErrorMsg())
|
||||
@@ -413,7 +416,7 @@
|
||||
if(!href_list["id"])
|
||||
return
|
||||
|
||||
if(!dbcon_old.IsConnected())
|
||||
if(!SSdbcore.IsConnected())
|
||||
alert("Connection to Archive has been severed. Aborting.")
|
||||
return
|
||||
|
||||
@@ -438,7 +441,7 @@
|
||||
return
|
||||
var/bookid = href_list["manual"]
|
||||
|
||||
if(!dbcon_old.IsConnected())
|
||||
if(!SSdbcore.IsConnected())
|
||||
alert("Connection to Archive has been severed. Aborting.")
|
||||
return
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
<A href='?src=\ref[src];setauthor=1'>Filter by Author: [query.author]</A><br />
|
||||
<A href='?src=\ref[src];search=1'>\[Start Search\]</A><br />"}
|
||||
if(1)
|
||||
establish_old_db_connection()
|
||||
if(!dbcon_old.IsConnected())
|
||||
if(!SSdbcore.Connect())
|
||||
dat += "<font color=red><b>ERROR</b>: Unable to contact External Archive. Please contact your system administrator for assistance.</font><br />"
|
||||
else if(num_results == 0)
|
||||
dat += "<em>No results found.</em>"
|
||||
|
||||
@@ -91,8 +91,11 @@
|
||||
var/sqlid = text2num(id)
|
||||
if(!sqlid)
|
||||
return
|
||||
var/DBQuery/query = dbcon_old.NewQuery("DELETE FROM library WHERE id=[sqlid]")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("DELETE FROM library WHERE id=[sqlid]")
|
||||
if(!query.Execute())
|
||||
message_admins("Error: [query.ErrorMsg()]")
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
|
||||
/datum/library_catalog/proc/getBookByID(var/id as text)
|
||||
if("[id]" in cached_books)
|
||||
@@ -101,8 +104,13 @@
|
||||
var/sqlid = text2num(id)
|
||||
if(!sqlid)
|
||||
return
|
||||
var/DBQuery/query = dbcon_old.NewQuery("SELECT id, author, title, category, ckey FROM library WHERE id=[sqlid]")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("SELECT id, author, title, category, ckey FROM library WHERE id=[sqlid]")
|
||||
if(!query.Execute())
|
||||
message_admins("Error: [query.ErrorMsg()]")
|
||||
log_sql("Error: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
qdel(query)
|
||||
|
||||
var/list/results=list()
|
||||
while(query.NextRow())
|
||||
|
||||
19
code/modules/migrations/SS13/010-add-hidden-poll-option.dm
Normal file
19
code/modules/migrations/SS13/010-add-hidden-poll-option.dm
Normal file
@@ -0,0 +1,19 @@
|
||||
/datum/migration/mysql/ss13/_010
|
||||
id = 10
|
||||
name = "Admin-only polls"
|
||||
|
||||
/datum/migration/mysql/ss13/_010/up()
|
||||
if(!hasColumn("erro_poll_question","hidden"))
|
||||
return execute("ALTER TABLE erro_poll_question ADD COLUMN `hidden` BOOLEAN NULL;");
|
||||
else
|
||||
warning("hidden column exists. Skipping addition.")
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/migration/mysql/ss13/_010/down()
|
||||
if(hasColumn("erro_poll_question","hidden"))
|
||||
return execute("ALTER TABLE erro_poll_question DROP COLUMN `hidden` BOOLEAN NULL;");
|
||||
else
|
||||
warning("hidden column does not exist. Skipping drop.")
|
||||
|
||||
return TRUE
|
||||
@@ -0,0 +1,30 @@
|
||||
/datum/migration/mysql/ss13/_011
|
||||
id = 11
|
||||
name = "Library in feedback DB"
|
||||
|
||||
/datum/migration/mysql/ss13/_011/up()
|
||||
if(!hasTable("library"))
|
||||
return execute({"CREATE TABLE IF NOT EXISTS `library` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT ,
|
||||
`author` TEXT NOT NULL ,
|
||||
`title` TEXT NOT NULL ,
|
||||
`content` TEXT NOT NULL ,
|
||||
`category` TEXT NOT NULL ,
|
||||
`ckey` VARCHAR(32) NULL ,
|
||||
PRIMARY KEY (`id`) )
|
||||
ENGINE = MyISAM
|
||||
AUTO_INCREMENT = 184
|
||||
DEFAULT CHARACTER SET = latin1;
|
||||
"});
|
||||
else
|
||||
warning("library table exists. Skipping addition.")
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/migration/mysql/ss13/_011/down()
|
||||
if(hasTable("library"))
|
||||
return execute("DROP TABLE library");
|
||||
else
|
||||
warning("library table doesn't exist. Skipping drop.")
|
||||
|
||||
return TRUE
|
||||
29
code/modules/migrations/SS13/012-add-customitems-table.dm
Normal file
29
code/modules/migrations/SS13/012-add-customitems-table.dm
Normal file
@@ -0,0 +1,29 @@
|
||||
/datum/migration/mysql/ss13/_012
|
||||
id = 12
|
||||
name = "Customitems in feedback DB"
|
||||
|
||||
/datum/migration/mysql/ss13/_012/up()
|
||||
if(!hasTable("customitems"))
|
||||
return execute({"CREATE TABLE IF NOT EXISTS `customitems` (
|
||||
cuiCKey VARCHAR(36) NOT NULL,
|
||||
cuiRealName VARCHAR(60) NOT NULL,
|
||||
cuiPath VARCHAR(255) NOT NULL,
|
||||
cuiDescription TEXT NOT NULL,
|
||||
cuiReason TEXT NOT NULL,
|
||||
cuiPropAdjust TEXT NOT NULL,
|
||||
cuiJobMask TEXT NOT NULL,
|
||||
PRIMARY KEY(cuiCkey,cuiRealName,cuiPath)
|
||||
)
|
||||
"});
|
||||
else
|
||||
warning("customitems table exists. Skipping addition.")
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/migration/mysql/ss13/_012/down()
|
||||
if(hasTable("customitems"))
|
||||
return execute("DROP TABLE customitems");
|
||||
else
|
||||
warning("customitems table doesn't exist. Skipping drop.")
|
||||
|
||||
return TRUE
|
||||
@@ -0,0 +1,19 @@
|
||||
/datum/migration/mysql/ss13/_013
|
||||
id = 13
|
||||
name = "Ckey creator in polls"
|
||||
|
||||
/datum/migration/mysql/ss13/_013/up()
|
||||
if(!hasColumn("erro_poll_question","createdby_ckey"))
|
||||
return execute("ALTER TABLE erro_poll_question ADD COLUMN `createdby_ckey` VARCHAR(32) NULL;");
|
||||
else
|
||||
warning("createdby_ckey column exists. Skipping addition.")
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/migration/mysql/ss13/_013/down()
|
||||
if(hasColumn("erro_poll_question","createdby_ckey"))
|
||||
return execute("ALTER TABLE erro_poll_question DROP COLUMN `createdby_ckey` VARCHAR(32) NULL;");
|
||||
else
|
||||
warning("createdby_ckey column does not exist. Skipping drop.")
|
||||
|
||||
return TRUE
|
||||
@@ -0,0 +1,19 @@
|
||||
/datum/migration/mysql/ss13/_014
|
||||
id = 14
|
||||
name = "IP creator in polls"
|
||||
|
||||
/datum/migration/mysql/ss13/_014/up()
|
||||
if(!hasColumn("erro_poll_question","createdby_ip"))
|
||||
return execute("ALTER TABLE erro_poll_question ADD COLUMN `createdby_ip` VARCHAR(32) NULL;");
|
||||
else
|
||||
warning("createdby_ip column exists. Skipping addition.")
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/migration/mysql/ss13/_013/down()
|
||||
if(hasColumn("erro_poll_question","createdby_ip"))
|
||||
return execute("ALTER TABLE erro_poll_question DROP COLUMN `createdby_ip` VARCHAR(32) NULL;");
|
||||
else
|
||||
warning("createdby_ip column does not exist. Skipping drop.")
|
||||
|
||||
return TRUE
|
||||
@@ -97,7 +97,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/migration_controller/proc/query(var/sql)
|
||||
var/DBQuery/query = execute(sql)
|
||||
var/datum/DBQuery/query = execute(sql)
|
||||
|
||||
var/list/rows=list()
|
||||
while(query.NextRow())
|
||||
|
||||
@@ -2,19 +2,19 @@ var/global/datum/migration_controller/mysql/migration_controller_mysql = null
|
||||
|
||||
/datum/migration_controller/mysql
|
||||
id="mysql"
|
||||
var/DBConnection/db
|
||||
var/datum/subsystem/dbcore/db
|
||||
|
||||
/datum/migration_controller/mysql/setup()
|
||||
if(!dbcon || !istype(dbcon) || !dbcon.IsConnected())
|
||||
warning("Something wrong with dbcon.")
|
||||
if(!SSdbcore || !istype(SSdbcore) || !SSdbcore.IsConnected())
|
||||
warning("Something wrong with SSdbcore.")
|
||||
return FALSE
|
||||
var/DBQuery/Q = dbcon.NewQuery()
|
||||
var/datum/DBQuery/Q = SSdbcore.NewQuery()
|
||||
if(!Q)
|
||||
warning("Something wrong with dbcon.NewQuery()")
|
||||
warning("Something wrong with SSdbcore.NewQuery()")
|
||||
return FALSE
|
||||
Q.Close()
|
||||
qdel(Q)
|
||||
//testing("MySQL is okay")
|
||||
db = dbcon
|
||||
db = SSdbcore
|
||||
return TRUE
|
||||
|
||||
/datum/migration_controller/mysql/createMigrationTable()
|
||||
@@ -27,25 +27,28 @@ CREATE TABLE IF NOT EXISTS [TABLE_NAME] (
|
||||
execute(tableSQL)
|
||||
|
||||
/datum/migration_controller/mysql/query(var/sql)
|
||||
var/DBQuery/query = execute(sql)
|
||||
var/datum/DBQuery/query = execute(sql)
|
||||
|
||||
var/list/rows=list()
|
||||
while(query.NextRow())
|
||||
rows[++rows.len] = query.item.Copy()
|
||||
|
||||
qdel(query)
|
||||
|
||||
return rows
|
||||
|
||||
/datum/migration_controller/mysql/hasResult(var/sql)
|
||||
var/DBQuery/query = execute(sql)
|
||||
|
||||
var/datum/DBQuery/query = execute(sql)
|
||||
if (query.NextRow())
|
||||
qdel(query)
|
||||
return TRUE
|
||||
qdel(query)
|
||||
return FALSE
|
||||
|
||||
/datum/migration_controller/mysql/execute(var/sql)
|
||||
var/DBQuery/query = db.NewQuery(sql)
|
||||
var/datum/DBQuery/query = db.NewQuery(sql)
|
||||
query.Execute()
|
||||
return query
|
||||
. = query
|
||||
|
||||
/datum/migration_controller/mysql/hasTable(var/tableName)
|
||||
return hasResult("SHOW TABLES LIKE '[tableName]")
|
||||
return hasResult("SHOW TABLES LIKE '[tableName]'")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/datum/migration/mysql
|
||||
var/DBConnection/db
|
||||
var/datum/subsystem/dbcore/db
|
||||
dbms="mysql"
|
||||
|
||||
/datum/migration/mysql/New(var/datum/migration_controller/mysql/mc)
|
||||
@@ -8,31 +8,38 @@
|
||||
db=mc.db
|
||||
|
||||
/datum/migration/mysql/query(var/sql)
|
||||
var/DBQuery/query = db.NewQuery(sql)
|
||||
var/datum/DBQuery/query = db.NewQuery(sql)
|
||||
if(!query.Execute())
|
||||
world.log << "Error in [package]#[id]: [query.ErrorMsg()]"
|
||||
qdel(query)
|
||||
return FALSE
|
||||
|
||||
var/list/rows=list()
|
||||
while(query.NextRow())
|
||||
rows += list(query.item)
|
||||
qdel(query)
|
||||
return rows
|
||||
|
||||
/datum/migration/mysql/hasResult(var/sql)
|
||||
var/DBQuery/query = db.NewQuery(sql)
|
||||
var/datum/DBQuery/query = db.NewQuery(sql)
|
||||
if(!query.Execute())
|
||||
world.log << "Error in [package]#[id]: [query.ErrorMsg()]"
|
||||
qdel(query)
|
||||
return FALSE
|
||||
|
||||
if (query.NextRow())
|
||||
qdel(query)
|
||||
return TRUE
|
||||
qdel(query)
|
||||
return FALSE
|
||||
|
||||
/datum/migration/mysql/execute(var/sql)
|
||||
var/DBQuery/query = db.NewQuery(sql)
|
||||
var/datum/DBQuery/query = db.NewQuery(sql)
|
||||
if(!query.Execute())
|
||||
world.log << "Error in [package]#[id]: [query.ErrorMsg()]"
|
||||
qdel(query)
|
||||
return FALSE
|
||||
qdel(query)
|
||||
return TRUE
|
||||
|
||||
/datum/migration/mysql/hasTable(var/tableName)
|
||||
|
||||
@@ -40,19 +40,20 @@
|
||||
|
||||
output += "<p><a href='byond://?src=\ref[src];observe=1'>Observe</A></p>"
|
||||
if(!IsGuestKey(src.key))
|
||||
establish_db_connection()
|
||||
|
||||
if(dbcon.IsConnected())
|
||||
if(SSdbcore.Connect())
|
||||
var/isadmin = 0
|
||||
if(src.client && src.client.holder)
|
||||
isadmin = 1
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT id FROM erro_poll_question WHERE [(isadmin ? "" : "adminonly = false AND")] hidden IS NULL AND Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM erro_poll_vote WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM erro_poll_textreply WHERE ckey = \"[ckey]\")")
|
||||
query.Execute()
|
||||
var/datum/DBQuery/query = SSdbcore.NewQuery("SELECT id FROM erro_poll_question WHERE [(isadmin ? "" : "adminonly = false AND")] hidden IS NULL AND Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM erro_poll_vote WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM erro_poll_textreply WHERE ckey = \"[ckey]\")")
|
||||
if(!query.Execute())
|
||||
log_sql("Error fetching poll question: [query.ErrorMsg()]")
|
||||
qdel(query)
|
||||
return
|
||||
var/newpoll = 0
|
||||
while(query.NextRow())
|
||||
newpoll = 1
|
||||
break
|
||||
|
||||
qdel(query)
|
||||
if(newpoll)
|
||||
output += "<p><b><a href='byond://?src=\ref[src];showpoll=1'>Show Player Polls</A> (NEW!)</b></p>"
|
||||
else
|
||||
|
||||
@@ -3,14 +3,17 @@
|
||||
var/optiontext
|
||||
|
||||
/mob/new_player/proc/handle_player_polling()
|
||||
establish_db_connection()
|
||||
if(dbcon.IsConnected())
|
||||
if(SSdbcore.Connect())
|
||||
var/isadmin = 0
|
||||
if(src.client && src.client.holder)
|
||||
isadmin = 1
|
||||
|
||||
var/DBQuery/select_query = dbcon.NewQuery("SELECT id, question FROM erro_poll_question WHERE [(isadmin ? "" : "adminonly = false AND")] hidden IS NULL AND Now() BETWEEN starttime AND endtime")
|
||||
select_query.Execute()
|
||||
var/datum/DBQuery/select_query = SSdbcore.NewQuery("SELECT id, question FROM erro_poll_question WHERE [(isadmin ? "" : "adminonly = false AND")] hidden IS NULL AND Now() BETWEEN starttime AND endtime")
|
||||
if(!select_query.Execute())
|
||||
message_admins("Error: [select_query.ErrorMsg()]")
|
||||
log_sql("Error: [select_query.ErrorMsg()]")
|
||||
qdel(select_query)
|
||||
return
|
||||
|
||||
|
||||
var/output = {"<div align='center'><B>Player polls</B>
|
||||
@@ -30,7 +33,7 @@
|
||||
i++
|
||||
|
||||
output += "</table>"
|
||||
|
||||
qdel(select_query)
|
||||
src << browse(output,"window=playerpolllist;size=500x300")
|
||||
|
||||
|
||||
@@ -38,11 +41,14 @@
|
||||
/mob/new_player/proc/poll_player(var/pollid = -1)
|
||||
if(pollid == -1)
|
||||
return
|
||||
establish_db_connection()
|
||||
if(dbcon.IsConnected())
|
||||
if(SSdbcore.Connect())
|
||||
|
||||
var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM erro_poll_question WHERE id = [pollid]")
|
||||
select_query.Execute()
|
||||
var/datum/DBQuery/select_query = SSdbcore.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM erro_poll_question WHERE id = [pollid]")
|
||||
if(!select_query.Execute())
|
||||
message_admins("Error: [select_query.ErrorMsg()]")
|
||||
log_sql("Error: [select_query.ErrorMsg()]")
|
||||
qdel(select_query)
|
||||
return
|
||||
|
||||
var/pollstarttime = ""
|
||||
var/pollendtime = ""
|
||||
@@ -58,6 +64,7 @@
|
||||
polltype = select_query.item[4]
|
||||
found = 1
|
||||
break
|
||||
qdel(select_query)
|
||||
|
||||
if(!found)
|
||||
to_chat(usr, "<span class='warning'>Poll question details not found.</span>")
|
||||
@@ -66,8 +73,12 @@
|
||||
switch(polltype)
|
||||
//Polls that have enumerated options
|
||||
if("OPTION")
|
||||
var/DBQuery/voted_query = dbcon.NewQuery("SELECT optionid FROM erro_poll_vote WHERE pollid = [pollid] AND ckey = '[usr.ckey]'")
|
||||
voted_query.Execute()
|
||||
var/datum/DBQuery/voted_query = SSdbcore.NewQuery("SELECT optionid FROM erro_poll_vote WHERE pollid = [pollid] AND ckey = '[usr.ckey]'")
|
||||
if(!voted_query.Execute())
|
||||
message_admins("Error: [voted_query.ErrorMsg()]")
|
||||
log_sql("Error: [voted_query.ErrorMsg()]")
|
||||
qdel(voted_query)
|
||||
return
|
||||
|
||||
var/voted = 0
|
||||
var/votedoptionid = 0
|
||||
@@ -75,11 +86,15 @@
|
||||
votedoptionid = text2num(voted_query.item[1])
|
||||
voted = 1
|
||||
break
|
||||
|
||||
qdel(voted_query)
|
||||
var/list/datum/polloption/options = list()
|
||||
|
||||
var/DBQuery/options_query = dbcon.NewQuery("SELECT id, text FROM erro_poll_option WHERE pollid = [pollid]")
|
||||
options_query.Execute()
|
||||
var/datum/DBQuery/options_query = SSdbcore.NewQuery("SELECT id, text FROM erro_poll_option WHERE pollid = [pollid]")
|
||||
if(!options_query.Execute())
|
||||
message_admins("Error: [options_query.ErrorMsg()]")
|
||||
log_sql("Error: [options_query.ErrorMsg()]")
|
||||
return
|
||||
|
||||
while(options_query.NextRow())
|
||||
var/datum/polloption/PO = new()
|
||||
PO.optionid = text2num(options_query.item[1])
|
||||
@@ -122,8 +137,12 @@
|
||||
|
||||
//Polls with a text input
|
||||
if("TEXT")
|
||||
var/DBQuery/voted_query = dbcon.NewQuery("SELECT replytext FROM erro_poll_textreply WHERE pollid = [pollid] AND ckey = '[usr.ckey]'")
|
||||
voted_query.Execute()
|
||||
var/datum/DBQuery/voted_query = SSdbcore.NewQuery("SELECT replytext FROM erro_poll_textreply WHERE pollid = [pollid] AND ckey = '[usr.ckey]'")
|
||||
if(!voted_query.Execute())
|
||||
message_admins("Error: [voted_query.ErrorMsg()]")
|
||||
log_sql("Error: [voted_query.ErrorMsg()]")
|
||||
qdel(voted_query)
|
||||
return
|
||||
|
||||
var/voted = 0
|
||||
var/vote_text = ""
|
||||
@@ -131,7 +150,7 @@
|
||||
vote_text = voted_query.item[1]
|
||||
voted = 1
|
||||
break
|
||||
|
||||
qdel(voted_query)
|
||||
|
||||
var/output = "<div align='center'><B>Player poll</B>"
|
||||
|
||||
@@ -164,8 +183,12 @@
|
||||
|
||||
//Polls with a text input
|
||||
if("NUMVAL")
|
||||
var/DBQuery/voted_query = dbcon.NewQuery("SELECT o.text, v.rating FROM erro_poll_option o, erro_poll_vote v WHERE o.pollid = [pollid] AND v.ckey = '[usr.ckey]' AND o.id = v.optionid")
|
||||
voted_query.Execute()
|
||||
var/datum/DBQuery/voted_query = SSdbcore.NewQuery("SELECT o.text, v.rating FROM erro_poll_option o, erro_poll_vote v WHERE o.pollid = [pollid] AND v.ckey = '[usr.ckey]' AND o.id = v.optionid")
|
||||
if(!voted_query.Execute())
|
||||
message_admins("Error: [voted_query.ErrorMsg()]")
|
||||
log_sql("Error: [voted_query.ErrorMsg()]")
|
||||
qdel(voted_query)
|
||||
return
|
||||
|
||||
var/output = "<div align='center'><B>Player poll</B>"
|
||||
|
||||
@@ -181,6 +204,7 @@
|
||||
var/rating = voted_query.item[2]
|
||||
|
||||
output += "<br><b>[optiontext] - [rating]</b>"
|
||||
qdel(voted_query)
|
||||
|
||||
if(!voted) //Only make this a form if we have not voted yet
|
||||
|
||||
@@ -192,8 +216,12 @@
|
||||
var/minid = 999999
|
||||
var/maxid = 0
|
||||
|
||||
var/DBQuery/option_query = dbcon.NewQuery("SELECT id, text, minval, maxval, descmin, descmid, descmax FROM erro_poll_option WHERE pollid = [pollid]")
|
||||
option_query.Execute()
|
||||
var/datum/DBQuery/option_query = SSdbcore.NewQuery("SELECT id, text, minval, maxval, descmin, descmid, descmax FROM erro_poll_option WHERE pollid = [pollid]")
|
||||
if(!option_query.Execute())
|
||||
message_admins("Error: [option_query.ErrorMsg()]")
|
||||
log_sql("Error: [option_query.ErrorMsg()]")
|
||||
qdel(option_query)
|
||||
return
|
||||
while(option_query.NextRow())
|
||||
var/optionid = text2num(option_query.item[1])
|
||||
var/optiontext = option_query.item[2]
|
||||
@@ -234,24 +262,33 @@
|
||||
<input type='hidden' name='maxid' value='[maxid]'>
|
||||
<p><input type='submit' value='Submit'>
|
||||
</form>"}
|
||||
|
||||
qdel(option_query)
|
||||
src << browse(output,"window=playerpoll;size=500x500")
|
||||
if("MULTICHOICE")
|
||||
var/DBQuery/voted_query = dbcon.NewQuery("SELECT optionid FROM erro_poll_vote WHERE pollid = [pollid] AND ckey = '[usr.ckey]'")
|
||||
voted_query.Execute()
|
||||
var/datum/DBQuery/voted_query = SSdbcore.NewQuery("SELECT optionid FROM erro_poll_vote WHERE pollid = [pollid] AND ckey = '[usr.ckey]'")
|
||||
if(!voted_query.Execute())
|
||||
message_admins("Error: [voted_query.ErrorMsg()]")
|
||||
log_sql("Error: [voted_query.ErrorMsg()]")
|
||||
qdel(voted_query)
|
||||
return
|
||||
|
||||
var/list/votedfor = list()
|
||||
var/voted = 0
|
||||
while(voted_query.NextRow())
|
||||
votedfor.Add(text2num(voted_query.item[1]))
|
||||
voted = 1
|
||||
qdel(voted_query)
|
||||
|
||||
var/list/datum/polloption/options = list()
|
||||
var/maxoptionid = 0
|
||||
var/minoptionid = 0
|
||||
|
||||
var/DBQuery/options_query = dbcon.NewQuery("SELECT id, text FROM erro_poll_option WHERE pollid = [pollid]")
|
||||
options_query.Execute()
|
||||
var/datum/DBQuery/options_query = SSdbcore.NewQuery("SELECT id, text FROM erro_poll_option WHERE pollid = [pollid]")
|
||||
if(!options_query.Execute())
|
||||
message_admins("Error: [options_query.ErrorMsg()]")
|
||||
log_sql("Error: [options_query.ErrorMsg()]")
|
||||
qdel(options_query)
|
||||
return
|
||||
while(options_query.NextRow())
|
||||
var/datum/polloption/PO = new()
|
||||
PO.optionid = text2num(options_query.item[1])
|
||||
@@ -309,11 +346,14 @@
|
||||
|
||||
if(!isnum(pollid) || !isnum(optionid))
|
||||
return
|
||||
establish_db_connection()
|
||||
if(dbcon.IsConnected())
|
||||
if(SSdbcore.Connect())
|
||||
|
||||
var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime")
|
||||
select_query.Execute()
|
||||
var/datum/DBQuery/select_query = SSdbcore.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime")
|
||||
if(!select_query.Execute())
|
||||
message_admins("Error: [select_query.ErrorMsg()]")
|
||||
log_sql("Error: [select_query.ErrorMsg()]")
|
||||
qdel(select_query)
|
||||
return
|
||||
|
||||
var/validpoll = 0
|
||||
var/multiplechoiceoptions = 0
|
||||
@@ -325,19 +365,25 @@
|
||||
if(select_query.item[5])
|
||||
multiplechoiceoptions = text2num(select_query.item[5])
|
||||
break
|
||||
qdel(select_query)
|
||||
|
||||
if(!validpoll)
|
||||
to_chat(usr, "<span class='warning'>Poll is not valid.</span>")
|
||||
return
|
||||
|
||||
var/DBQuery/select_query2 = dbcon.NewQuery("SELECT id FROM erro_poll_option WHERE id = [optionid] AND pollid = [pollid]")
|
||||
select_query2.Execute()
|
||||
var/datum/DBQuery/select_query2 = SSdbcore.NewQuery("SELECT id FROM erro_poll_option WHERE id = [optionid] AND pollid = [pollid]")
|
||||
if(!select_query2.Execute())
|
||||
message_admins("Error: [select_query.ErrorMsg()]")
|
||||
log_sql("Error: [select_query.ErrorMsg()]")
|
||||
qdel(select_query2)
|
||||
return
|
||||
|
||||
var/validoption = 0
|
||||
|
||||
while(select_query2.NextRow())
|
||||
validoption = 1
|
||||
break
|
||||
qdel(select_query2)
|
||||
|
||||
if(!validoption)
|
||||
to_chat(usr, "<span class='warning'>Poll option is not valid.</span>")
|
||||
@@ -345,8 +391,11 @@
|
||||
|
||||
var/alreadyvoted = 0
|
||||
|
||||
var/DBQuery/voted_query = dbcon.NewQuery("SELECT id FROM erro_poll_vote WHERE pollid = [pollid] AND ckey = '[usr.ckey]'")
|
||||
voted_query.Execute()
|
||||
var/datum/DBQuery/voted_query = SSdbcore.NewQuery("SELECT id FROM erro_poll_vote WHERE pollid = [pollid] AND ckey = '[usr.ckey]'")
|
||||
if(!voted_query.Execute())
|
||||
message_admins("Error: [voted_query.ErrorMsg()]")
|
||||
log_sql("Error: [voted_query.ErrorMsg()]")
|
||||
return
|
||||
|
||||
while(voted_query.NextRow())
|
||||
alreadyvoted += 1
|
||||
@@ -366,8 +415,13 @@
|
||||
adminrank = usr.client.holder.rank
|
||||
|
||||
|
||||
var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO erro_poll_vote (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank) VALUES (null, Now(), [pollid], [optionid], '[usr.ckey]', '[usr.client.address]', '[adminrank]')")
|
||||
insert_query.Execute()
|
||||
var/datum/DBQuery/insert_query = SSdbcore.NewQuery("INSERT INTO erro_poll_vote (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank) VALUES (null, Now(), [pollid], [optionid], '[usr.ckey]', '[usr.client.address]', '[adminrank]')")
|
||||
if(!insert_query.Execute())
|
||||
message_admins("Error: [insert_query.ErrorMsg()]")
|
||||
log_sql("Error: [insert_query.ErrorMsg()]")
|
||||
qdel(insert_query)
|
||||
return
|
||||
qdel(insert_query)
|
||||
|
||||
to_chat(usr, "<span class='notice'>Vote successful.</span>")
|
||||
usr << browse(null,"window=playerpoll")
|
||||
@@ -379,19 +433,24 @@
|
||||
|
||||
if(!isnum(pollid) || !istext(replytext))
|
||||
return
|
||||
establish_db_connection()
|
||||
if(dbcon.IsConnected())
|
||||
if(SSdbcore.Connect())
|
||||
|
||||
var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime")
|
||||
select_query.Execute()
|
||||
var/datum/DBQuery/select_query = SSdbcore.NewQuery("SELECT starttime, endtime, question, polltype FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime")
|
||||
if(!select_query.Execute())
|
||||
message_admins("Error: [select_query.ErrorMsg()]")
|
||||
log_sql("Error: [select_query.ErrorMsg()]")
|
||||
qdel(select_query)
|
||||
return
|
||||
|
||||
var/validpoll = 0
|
||||
|
||||
while(select_query.NextRow())
|
||||
if(select_query.item[4] != "TEXT")
|
||||
qdel(select_query)
|
||||
return
|
||||
validpoll = 1
|
||||
break
|
||||
qdel(select_query)
|
||||
|
||||
if(!validpoll)
|
||||
to_chat(usr, "<span class='warning'>Poll is not valid.</span>")
|
||||
@@ -399,12 +458,17 @@
|
||||
|
||||
var/alreadyvoted = 0
|
||||
|
||||
var/DBQuery/voted_query = dbcon.NewQuery("SELECT id FROM erro_poll_textreply WHERE pollid = [pollid] AND ckey = '[usr.ckey]'")
|
||||
voted_query.Execute()
|
||||
var/datum/DBQuery/voted_query = SSdbcore.NewQuery("SELECT id FROM erro_poll_textreply WHERE pollid = [pollid] AND ckey = '[usr.ckey]'")
|
||||
if(!voted_query.Execute())
|
||||
message_admins("Error: [voted_query.ErrorMsg()]")
|
||||
log_sql("Error: [voted_query.ErrorMsg()]")
|
||||
qdel(voted_query)
|
||||
return
|
||||
|
||||
while(voted_query.NextRow())
|
||||
alreadyvoted = 1
|
||||
break
|
||||
qdel(voted_query)
|
||||
|
||||
if(alreadyvoted)
|
||||
to_chat(usr, "<span class='warning'>You already sent your feedback for this poll.</span>")
|
||||
@@ -417,6 +481,7 @@
|
||||
|
||||
replytext = replacetext(replytext, "%BR%", "")
|
||||
replytext = replacetext(replytext, "\n", "%BR%")
|
||||
replytext = replacetext(replytext, "'", "\'")
|
||||
var/text_pass = reject_bad_text(replytext,8000)
|
||||
replytext = replacetext(replytext, "%BR%", "<BR>")
|
||||
|
||||
@@ -424,8 +489,13 @@
|
||||
to_chat(usr, "The text you entered was blank, contained illegal characters or was too long. Please correct the text and submit again.")
|
||||
return
|
||||
|
||||
var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO erro_poll_textreply (id ,datetime ,pollid ,ckey ,ip ,replytext ,adminrank) VALUES (null, Now(), [pollid], '[usr.ckey]', '[usr.client.address]', '[replytext]', '[adminrank]')")
|
||||
insert_query.Execute()
|
||||
var/datum/DBQuery/insert_query = SSdbcore.NewQuery("INSERT INTO erro_poll_textreply (id ,datetime ,pollid ,ckey ,ip ,replytext ,adminrank) VALUES (null, Now(), [pollid], '[usr.ckey]', '[usr.client.address]', '[replytext]', '[adminrank]')")
|
||||
if(!insert_query.Execute())
|
||||
message_admins("Error: [insert_query.ErrorMsg()]")
|
||||
log_sql("Error: [insert_query.ErrorMsg()]")
|
||||
qdel(insert_query)
|
||||
return
|
||||
qdel(insert_query)
|
||||
|
||||
to_chat(usr, "<span class='notice'>Feedback logging successful.</span>")
|
||||
usr << browse(null,"window=playerpoll")
|
||||
@@ -437,32 +507,43 @@
|
||||
|
||||
if(!isnum(pollid) || !isnum(optionid))
|
||||
return
|
||||
establish_db_connection()
|
||||
if(dbcon.IsConnected())
|
||||
SSdbcore.Connect()
|
||||
if(SSdbcore.IsConnected())
|
||||
|
||||
var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime")
|
||||
select_query.Execute()
|
||||
var/datum/DBQuery/select_query = SSdbcore.NewQuery("SELECT starttime, endtime, question, polltype FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime")
|
||||
if(!select_query.Execute())
|
||||
message_admins("Error: [select_query.ErrorMsg()]")
|
||||
log_sql("Error: [select_query.ErrorMsg()]")
|
||||
qdel(select_query)
|
||||
return
|
||||
|
||||
var/validpoll = 0
|
||||
|
||||
while(select_query.NextRow())
|
||||
if(select_query.item[4] != "NUMVAL")
|
||||
qdel(select_query)
|
||||
return
|
||||
validpoll = 1
|
||||
break
|
||||
qdel(select_query)
|
||||
|
||||
if(!validpoll)
|
||||
to_chat(usr, "<span class='warning'>Poll is not valid.</span>")
|
||||
return
|
||||
|
||||
var/DBQuery/select_query2 = dbcon.NewQuery("SELECT id FROM erro_poll_option WHERE id = [optionid] AND pollid = [pollid]")
|
||||
select_query2.Execute()
|
||||
var/datum/DBQuery/select_query2 = SSdbcore.NewQuery("SELECT id FROM erro_poll_option WHERE id = [optionid] AND pollid = [pollid]")
|
||||
if(!select_query2.Execute())
|
||||
message_admins("Error: [select_query.ErrorMsg()]")
|
||||
log_sql("Error: [select_query.ErrorMsg()]")
|
||||
qdel(select_query2)
|
||||
return
|
||||
|
||||
var/validoption = 0
|
||||
|
||||
while(select_query2.NextRow())
|
||||
validoption = 1
|
||||
break
|
||||
qdel(select_query2)
|
||||
|
||||
if(!validoption)
|
||||
to_chat(usr, "<span class='warning'>Poll is not valid.</span>")
|
||||
@@ -470,12 +551,18 @@
|
||||
|
||||
var/alreadyvoted = 0
|
||||
|
||||
var/DBQuery/voted_query = dbcon.NewQuery("SELECT id FROM erro_poll_vote WHERE optionid = [optionid] AND ckey = '[usr.ckey]'")
|
||||
voted_query.Execute()
|
||||
var/datum/DBQuery/voted_query = SSdbcore.NewQuery("SELECT id FROM erro_poll_vote WHERE optionid = [optionid] AND ckey = '[usr.ckey]'")
|
||||
if(!voted_query.Execute())
|
||||
message_admins("Error: [voted_query.ErrorMsg()]")
|
||||
log_sql("Error: [voted_query.ErrorMsg()]")
|
||||
qdel(voted_query)
|
||||
return
|
||||
|
||||
|
||||
while(voted_query.NextRow())
|
||||
alreadyvoted = 1
|
||||
break
|
||||
qdel(voted_query)
|
||||
|
||||
if(alreadyvoted)
|
||||
to_chat(usr, "<span class='warning'>You already voted in this poll.</span>")
|
||||
@@ -486,8 +573,13 @@
|
||||
adminrank = usr.client.holder.rank
|
||||
|
||||
|
||||
var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO erro_poll_vote (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank, rating) VALUES (null, Now(), [pollid], [optionid], '[usr.ckey]', '[usr.client.address]', '[adminrank]', [(isnull(rating)) ? "null" : rating])")
|
||||
insert_query.Execute()
|
||||
var/datum/DBQuery/insert_query = SSdbcore.NewQuery("INSERT INTO erro_poll_vote (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank, rating) VALUES (null, Now(), [pollid], [optionid], '[usr.ckey]', '[usr.client.address]', '[adminrank]', [(isnull(rating)) ? "null" : rating])")
|
||||
if(!insert_query.Execute())
|
||||
message_admins("Error: [insert_query.ErrorMsg()]")
|
||||
log_sql("Error: [insert_query.ErrorMsg()]")
|
||||
qdel(insert_query)
|
||||
return
|
||||
qdel(insert_query)
|
||||
|
||||
to_chat(usr, "<span class='notice'>Vote successful.</span>")
|
||||
usr << browse(null,"window=playerpoll")
|
||||
usr << browse(null,"window=playerpoll")
|
||||
|
||||
101
code/world.dm
101
code/world.dm
@@ -74,6 +74,9 @@ var/savefile/panicfile
|
||||
make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once)
|
||||
|
||||
load_configuration()
|
||||
|
||||
SSdbcore.Initialize() // Get a database running, first thing
|
||||
|
||||
load_mode()
|
||||
load_motd()
|
||||
load_admins()
|
||||
@@ -116,18 +119,6 @@ var/savefile/panicfile
|
||||
data_core = new /obj/effect/datacore()
|
||||
paiController = new /datum/paiController()
|
||||
|
||||
if(!setup_database_connection())
|
||||
world.log << "Your server failed to establish a connection with the feedback database."
|
||||
else
|
||||
world.log << "Feedback database connection established."
|
||||
migration_controller_mysql = new
|
||||
migration_controller_sqlite = new ("players2.sqlite", "players2_empty.sqlite")
|
||||
|
||||
if(!setup_old_database_connection())
|
||||
world.log << "Your server failed to establish a connection with the tgstation database."
|
||||
else
|
||||
world.log << "Tgstation database connection established."
|
||||
|
||||
plmaster = new /obj/effect/overlay()
|
||||
plmaster.icon = 'icons/effects/tile_effects.dmi'
|
||||
plmaster.icon_state = "plasma"
|
||||
@@ -417,89 +408,3 @@ var/savefile/panicfile
|
||||
/* does this help? I do not know */
|
||||
if (src.status != s)
|
||||
src.status = s
|
||||
|
||||
#define FAILED_DB_CONNECTION_CUTOFF 5
|
||||
var/failed_db_connections = 0
|
||||
var/failed_old_db_connections = 0
|
||||
|
||||
proc/setup_database_connection()
|
||||
|
||||
|
||||
if(failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to conenct anymore.
|
||||
return 0
|
||||
|
||||
if(!dbcon)
|
||||
dbcon = new()
|
||||
|
||||
var/user = sqlfdbklogin
|
||||
var/pass = sqlfdbkpass
|
||||
var/db = sqlfdbkdb
|
||||
var/address = sqladdress
|
||||
var/port = sqlport
|
||||
|
||||
dbcon.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]")
|
||||
. = dbcon.IsConnected()
|
||||
if ( . )
|
||||
failed_db_connections = 0 //If this connection succeeded, reset the failed connections counter.
|
||||
else
|
||||
world.log << "Database Error: [dbcon.ErrorMsg()]"
|
||||
failed_db_connections++ //If it failed, increase the failed connections counter.
|
||||
|
||||
return .
|
||||
|
||||
//This proc ensures that the connection to the feedback database (global variable dbcon) is established
|
||||
proc/establish_db_connection()
|
||||
if(failed_db_connections > FAILED_DB_CONNECTION_CUTOFF)
|
||||
return 0
|
||||
|
||||
var/DBQuery/q
|
||||
if(dbcon)
|
||||
q = dbcon.NewQuery("show global variables like 'wait_timeout'")
|
||||
q.Execute()
|
||||
if(q && q.ErrorMsg())
|
||||
dbcon.Disconnect()
|
||||
if(!dbcon || !dbcon.IsConnected())
|
||||
return setup_database_connection()
|
||||
else
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
|
||||
//These two procs are for the old database, while it's being phased out. See the tgstation.sql file in the SQL folder for more information.
|
||||
proc/setup_old_database_connection()
|
||||
|
||||
|
||||
if(failed_old_db_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to conenct anymore.
|
||||
return 0
|
||||
|
||||
if(!dbcon_old)
|
||||
dbcon_old = new()
|
||||
|
||||
var/user = sqllogin
|
||||
var/pass = sqlpass
|
||||
var/db = sqldb
|
||||
var/address = sqladdress
|
||||
var/port = sqlport
|
||||
|
||||
dbcon_old.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]")
|
||||
. = dbcon_old.IsConnected()
|
||||
if ( . )
|
||||
failed_old_db_connections = 0 //If this connection succeeded, reset the failed connections counter.
|
||||
else
|
||||
failed_old_db_connections++ //If it failed, increase the failed connections counter.
|
||||
world.log << dbcon_old.ErrorMsg()
|
||||
|
||||
return .
|
||||
|
||||
//This proc ensures that the connection to the feedback database (global variable dbcon) is established
|
||||
proc/establish_old_db_connection()
|
||||
if(failed_old_db_connections > FAILED_DB_CONNECTION_CUTOFF)
|
||||
return 0
|
||||
|
||||
if(!dbcon_old || !dbcon_old.IsConnected())
|
||||
return setup_old_database_connection()
|
||||
else
|
||||
return 1
|
||||
|
||||
#undef FAILED_DB_CONNECTION_CUTOFF
|
||||
|
||||
@@ -76,8 +76,14 @@ LOG_RC
|
||||
## log world.log and runtime errors to a file
|
||||
# LOG_RUNTIMES
|
||||
|
||||
## log sql status messages.
|
||||
# LOG_SQL
|
||||
|
||||
## log all sql queries.
|
||||
# LOG_SQL_QUERIES
|
||||
|
||||
## sql switching
|
||||
# SQL_ENABLED
|
||||
# SQL_ENABLED 1
|
||||
|
||||
## disconnect players who did nothing during 10 minutes
|
||||
# KICK_INACTIVE
|
||||
@@ -338,3 +344,18 @@ ENABLE_WAGES
|
||||
# HTTP URL to send Discord messages to.
|
||||
# DISCORD_URL
|
||||
# DISCORD_PASSWORD
|
||||
|
||||
## Time in seconds for asynchronous queries to timeout
|
||||
## Set to 0 for infinite
|
||||
ASYNC_QUERY_TIMEOUT 10
|
||||
|
||||
## Time in seconds for blocking queries to execute before slow query timeout
|
||||
## Set to 0 for infinite
|
||||
## Must be less than or equal to ASYNC_QUERY_TIMEOUT
|
||||
BLOCKING_QUERY_TIMEOUT 5
|
||||
|
||||
## The maximum number of additional threads BSQL is allowed to run at once
|
||||
BSQL_THREAD_LIMIT 50
|
||||
|
||||
## Uncomment to enable verbose BSQL communication logs
|
||||
#BSQL_DEBUG
|
||||
BIN
libmariadb.dll
Normal file
BIN
libmariadb.dll
Normal file
Binary file not shown.
22
tools/travis/build_bsql.sh
Executable file
22
tools/travis/build_bsql.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Variable.
|
||||
BSQL_VERSION=v1.4.0.0
|
||||
|
||||
mkdir -p BSQL
|
||||
cd BSQL
|
||||
git init
|
||||
git remote add origin https://github.com/tgstation/BSQL
|
||||
git fetch --depth 1 origin $BSQL_VERSION
|
||||
git checkout FETCH_HEAD
|
||||
|
||||
mkdir -p artifacts
|
||||
cd artifacts
|
||||
export CXX=g++-7
|
||||
# The -D will be unnecessary past BSQL v1.4.0.0
|
||||
cmake .. -DMARIA_LIBRARY=/usr/lib/i386-linux-gnu/libmariadb.so
|
||||
make
|
||||
|
||||
mkdir -p ~/.byond/bin
|
||||
ln -s $PWD/src/BSQL/libBSQL.so ../../libBSQL.so
|
||||
15
tools/travis/install_libmariadb.sh
Executable file
15
tools/travis/install_libmariadb.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# get libmariadb, cache it so limmex doesn't get angery
|
||||
if [ -f $HOME/libmariadb ]; then
|
||||
#travis likes to interpret the cache command as it being a file for some reason
|
||||
rm $HOME/libmariadb
|
||||
fi
|
||||
mkdir -p $HOME/libmariadb
|
||||
if [ ! -f $HOME/libmariadb/libmariadb.so ]; then
|
||||
wget http://www.byond.com/download/db/mariadb_client-2.0.0-linux.tgz
|
||||
tar -xvf mariadb_client-2.0.0-linux.tgz
|
||||
mv mariadb_client-2.0.0-linux/libmariadb.so $HOME/libmariadb/libmariadb.so
|
||||
rm -rf mariadb_client-2.0.0-linux.tgz mariadb_client-2.0.0-linux
|
||||
fi
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "__DEFINES\atom_locking_and_control.dm"
|
||||
#include "__DEFINES\atoms.dm"
|
||||
#include "__DEFINES\bots.dm"
|
||||
#include "__DEFINES\BSQL.dm"
|
||||
#include "__DEFINES\cameranet.dm"
|
||||
#include "__DEFINES\carbon_defines.dm"
|
||||
#include "__DEFINES\clothing.dm"
|
||||
@@ -203,6 +204,7 @@
|
||||
#include "code\controllers\subsystem\ambient_sound.dm"
|
||||
#include "code\controllers\subsystem\bots.dm"
|
||||
#include "code\controllers\subsystem\component.dm"
|
||||
#include "code\controllers\subsystem\dbcore.dm"
|
||||
#include "code\controllers\subsystem\disease.dm"
|
||||
#include "code\controllers\subsystem\emergency_shuttle.dm"
|
||||
#include "code\controllers\subsystem\event.dm"
|
||||
@@ -1204,9 +1206,7 @@
|
||||
#include "code\game\verbs\who.dm"
|
||||
#include "code\js\byjax.dm"
|
||||
#include "code\js\menus.dm"
|
||||
#include "code\libs\db\constants.dm"
|
||||
#include "code\libs\db\core.dm"
|
||||
#include "code\libs\db\db.dm"
|
||||
#include "code\libs\BSQL\includes.dm"
|
||||
#include "code\libs\Get Flat Icon\Get Flat Icon.dm"
|
||||
#include "code\libs\IconProcs\IconProcs.dm"
|
||||
#include "code\libs\s_html\hexadecimal.dm"
|
||||
@@ -1586,6 +1586,11 @@
|
||||
#include "code\modules\migrations\SS13\007-secret-fingerprints.dm"
|
||||
#include "code\modules\migrations\SS13\008-add-connection-log.dm"
|
||||
#include "code\modules\migrations\SS13\009-add-accountjoined.dm"
|
||||
#include "code\modules\migrations\SS13\010-add-hidden-poll-option.dm"
|
||||
#include "code\modules\migrations\SS13\011-port-library-to-feedback-db.dm"
|
||||
#include "code\modules\migrations\SS13\012-add-customitems-table.dm"
|
||||
#include "code\modules\migrations\SS13\013-add-createdby-ckey-to-polls.dm"
|
||||
#include "code\modules\migrations\SS13\014-add-createdby-ip-to-polls.dm"
|
||||
#include "code\modules\migrations\SS13\_base.dm"
|
||||
#include "code\modules\migrations\SS13_Prefs\001-create.dm"
|
||||
#include "code\modules\migrations\SS13_Prefs\002-add-progress-bars.dm"
|
||||
|
||||
Reference in New Issue
Block a user