diff options
Diffstat (limited to 'src/common/sql.c')
-rw-r--r-- | src/common/sql.c | 331 |
1 files changed, 193 insertions, 138 deletions
diff --git a/src/common/sql.c b/src/common/sql.c index 1eae1b29b..bd00619eb 100644 --- a/src/common/sql.c +++ b/src/common/sql.c @@ -2,8 +2,8 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team - * Copyright (C) Athena Dev Teams + * Copyright (C) 2012-2020 Hercules Dev Team + * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,7 +23,9 @@ #include "sql.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/memmgr.h" +#include "common/nullpo.h" #include "common/showmsg.h" #include "common/strlib.h" #include "common/timer.h" @@ -35,12 +37,12 @@ #include <stdio.h> #include <stdlib.h> // strtoul -void hercules_mysql_error_handler(unsigned int ecode); +static void hercules_mysql_error_handler(unsigned int ecode); -int mysql_reconnect_type; -unsigned int mysql_reconnect_count; +static int mysql_reconnect_type = 2; +static int mysql_reconnect_count = 1; -struct sql_interface sql_s; +static struct sql_interface sql_s; struct sql_interface *SQL; /// Sql handle @@ -79,7 +81,7 @@ struct SqlStmt { /////////////////////////////////////////////////////////////////////////////// /// Allocates and initializes a new Sql handle. -struct Sql *Sql_Malloc(void) +static struct Sql *Sql_Malloc(void) { struct Sql *self; @@ -89,14 +91,20 @@ struct Sql *Sql_Malloc(void) self->lengths = NULL; self->result = NULL; self->keepalive = INVALID_TIMER; - self->handle.reconnect = 1; + { + my_bool reconnect = 1; + mysql_options(&self->handle, MYSQL_OPT_RECONNECT, &reconnect); +#ifdef WIN32 + mysql_optionsv(&self->handle, MYSQL_PLUGIN_DIR, MARIADB_PLUGINDIR); +#endif + } return self; } static int Sql_P_Keepalive(struct Sql *self); /// Establishes a connection. -int Sql_Connect(struct Sql *self, const char *user, const char *passwd, const char *host, uint16 port, const char *db) +static int Sql_Connect(struct Sql *self, const char *user, const char *passwd, const char *host, uint16 port, const char *db) { if( self == NULL ) return SQL_ERROR; @@ -119,7 +127,7 @@ int Sql_Connect(struct Sql *self, const char *user, const char *passwd, const ch } /// Retrieves the timeout of the connection. -int Sql_GetTimeout(struct Sql *self, uint32 *out_timeout) +static int Sql_GetTimeout(struct Sql *self, uint32 *out_timeout) { if( self && out_timeout && SQL_SUCCESS == SQL->Query(self, "SHOW VARIABLES LIKE 'wait_timeout'") ) { char* data; @@ -136,12 +144,13 @@ int Sql_GetTimeout(struct Sql *self, uint32 *out_timeout) } /// Retrieves the name of the columns of a table into out_buf, with the separator after each name. -int Sql_GetColumnNames(struct Sql *self, const char *table, char *out_buf, size_t buf_len, char sep) +static int Sql_GetColumnNames(struct Sql *self, const char *table, char *out_buf, size_t buf_len, char sep) { char* data; size_t len; size_t off = 0; + nullpo_retr(SQL_ERROR, out_buf); if( self == NULL || SQL_ERROR == SQL->Query(self, "EXPLAIN `%s`", table) ) return SQL_ERROR; @@ -164,7 +173,7 @@ int Sql_GetColumnNames(struct Sql *self, const char *table, char *out_buf, size_ } /// Changes the encoding of the connection. -int Sql_SetEncoding(struct Sql *self, const char *encoding) +static int Sql_SetEncoding(struct Sql *self, const char *encoding) { if( self && mysql_set_character_set(&self->handle, encoding) == 0 ) return SQL_SUCCESS; @@ -172,7 +181,7 @@ int Sql_SetEncoding(struct Sql *self, const char *encoding) } /// Pings the connection. -int Sql_Ping(struct Sql *self) +static int Sql_Ping(struct Sql *self) { if( self && mysql_ping(&self->handle) == 0 ) return SQL_SUCCESS; @@ -214,7 +223,7 @@ static int Sql_P_Keepalive(struct Sql *self) } /// Escapes a string. -size_t Sql_EscapeString(struct Sql *self, char *out_to, const char *from) +static size_t Sql_EscapeString(struct Sql *self, char *out_to, const char *from) { if (self != NULL) return (size_t)mysql_real_escape_string(&self->handle, out_to, from, (unsigned long)strlen(from)); @@ -223,7 +232,7 @@ size_t Sql_EscapeString(struct Sql *self, char *out_to, const char *from) } /// Escapes a string. -size_t Sql_EscapeStringLen(struct Sql *self, char *out_to, const char *from, size_t from_len) +static size_t Sql_EscapeStringLen(struct Sql *self, char *out_to, const char *from, size_t from_len) { if (self != NULL) return (size_t)mysql_real_escape_string(&self->handle, out_to, from, (unsigned long)from_len); @@ -232,8 +241,8 @@ size_t Sql_EscapeStringLen(struct Sql *self, char *out_to, const char *from, siz } /// Executes a query. -int Sql_Query(struct Sql *self, const char *query, ...) __attribute__((format(printf, 2, 3))); -int Sql_Query(struct Sql *self, const char *query, ...) +static int Sql_Query(struct Sql *self, const char *query, ...) __attribute__((format(printf, 2, 3))); +static int Sql_Query(struct Sql *self, const char *query, ...) { int res; va_list args; @@ -246,7 +255,7 @@ int Sql_Query(struct Sql *self, const char *query, ...) } /// Executes a query. -int Sql_QueryV(struct Sql *self, const char *query, va_list args) +static int Sql_QueryV(struct Sql *self, const char *query, va_list args) { if( self == NULL ) return SQL_ERROR; @@ -271,7 +280,7 @@ int Sql_QueryV(struct Sql *self, const char *query, va_list args) } /// Executes a query. -int Sql_QueryStr(struct Sql *self, const char *query) +static int Sql_QueryStr(struct Sql *self, const char *query) { if( self == NULL ) return SQL_ERROR; @@ -296,7 +305,7 @@ int Sql_QueryStr(struct Sql *self, const char *query) } /// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE query. -uint64 Sql_LastInsertId(struct Sql *self) +static uint64 Sql_LastInsertId(struct Sql *self) { if (self != NULL) return (uint64)mysql_insert_id(&self->handle); @@ -305,7 +314,7 @@ uint64 Sql_LastInsertId(struct Sql *self) } /// Returns the number of columns in each row of the result. -uint32 Sql_NumColumns(struct Sql *self) +static uint32 Sql_NumColumns(struct Sql *self) { if (self != NULL && self->result != NULL) return (uint32)mysql_num_fields(self->result); @@ -313,7 +322,7 @@ uint32 Sql_NumColumns(struct Sql *self) } /// Returns the number of rows in the result. -uint64 Sql_NumRows(struct Sql *self) +static uint64 Sql_NumRows(struct Sql *self) { if (self != NULL && self->result != NULL) return (uint64)mysql_num_rows(self->result); @@ -321,7 +330,7 @@ uint64 Sql_NumRows(struct Sql *self) } /// Fetches the next row. -int Sql_NextRow(struct Sql *self) +static int Sql_NextRow(struct Sql *self) { if (self != NULL && self->result != NULL) { self->row = mysql_fetch_row(self->result); @@ -337,7 +346,7 @@ int Sql_NextRow(struct Sql *self) } /// Gets the data of a column. -int Sql_GetData(struct Sql *self, size_t col, char **out_buf, size_t *out_len) +static int Sql_GetData(struct Sql *self, size_t col, char **out_buf, size_t *out_len) { if( self && self->row ) { if( col < SQL->NumColumns(self) ) { @@ -353,7 +362,7 @@ int Sql_GetData(struct Sql *self, size_t col, char **out_buf, size_t *out_len) } /// Frees the result of the query. -void Sql_FreeResult(struct Sql *self) +static void Sql_FreeResult(struct Sql *self) { if( self && self->result ) { mysql_free_result(self->result); @@ -364,7 +373,7 @@ void Sql_FreeResult(struct Sql *self) } /// Shows debug information (last query). -void Sql_ShowDebug_(struct Sql *self, const char *debug_file, const unsigned long debug_line) +static void Sql_ShowDebug_(struct Sql *self, const char *debug_file, const unsigned long debug_line) { if( self == NULL ) ShowDebug("at %s:%lu - self is NULL\n", debug_file, debug_line); @@ -375,7 +384,8 @@ void Sql_ShowDebug_(struct Sql *self, const char *debug_file, const unsigned lon } /// Frees a Sql handle returned by Sql_Malloc. -void Sql_Free(struct Sql *self) { +static void Sql_Free(struct Sql *self) +{ if( self ) { SQL->FreeResult(self); @@ -410,64 +420,105 @@ static enum enum_field_types Sql_P_SizeToMysqlIntType(int sz) /// Binds a parameter/result. /// /// @private -static int Sql_P_BindSqlDataType(MYSQL_BIND* bind, enum SqlDataType buffer_type, void* buffer, size_t buffer_len, unsigned long* out_length, int8* out_is_null) +static int Sql_P_BindSqlDataType(MYSQL_BIND *bind, enum SqlDataType buffer_type, void *buffer, size_t buffer_len, unsigned long *out_length, int8 *out_is_null) { + nullpo_retr(SQL_ERROR, bind); memset(bind, 0, sizeof(MYSQL_BIND)); switch( buffer_type ) { - case SQLDT_NULL: bind->buffer_type = MYSQL_TYPE_NULL; + case SQLDT_NULL: + bind->buffer_type = MYSQL_TYPE_NULL; buffer_len = 0;// FIXME length = ? [FlavioJS] break; // fixed size - case SQLDT_UINT8: bind->is_unsigned = 1; - case SQLDT_INT8: bind->buffer_type = MYSQL_TYPE_TINY; - buffer_len = 1; + case SQLDT_UINT8: + bind->is_unsigned = 1; + FALLTHROUGH + case SQLDT_INT8: + bind->buffer_type = MYSQL_TYPE_TINY; + Assert_retr(SQL_ERROR, buffer_len == 1); break; - case SQLDT_UINT16: bind->is_unsigned = 1; - case SQLDT_INT16: bind->buffer_type = MYSQL_TYPE_SHORT; - buffer_len = 2; + case SQLDT_UINT16: + bind->is_unsigned = 1; + FALLTHROUGH + case SQLDT_INT16: + bind->buffer_type = MYSQL_TYPE_SHORT; + Assert_retr(SQL_ERROR, buffer_len == 2); break; - case SQLDT_UINT32: bind->is_unsigned = 1; - case SQLDT_INT32: bind->buffer_type = MYSQL_TYPE_LONG; - buffer_len = 4; + case SQLDT_UINT32: + bind->is_unsigned = 1; + FALLTHROUGH + case SQLDT_INT32: + bind->buffer_type = MYSQL_TYPE_LONG; + Assert_retr(SQL_ERROR, buffer_len == 4); break; - case SQLDT_UINT64: bind->is_unsigned = 1; - case SQLDT_INT64: bind->buffer_type = MYSQL_TYPE_LONGLONG; - buffer_len = 8; + case SQLDT_UINT64: + bind->is_unsigned = 1; + FALLTHROUGH + case SQLDT_INT64: + bind->buffer_type = MYSQL_TYPE_LONGLONG; + Assert_retr(SQL_ERROR, buffer_len == 8); break; // platform dependent size - case SQLDT_UCHAR: bind->is_unsigned = 1; - case SQLDT_CHAR: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(char)); - buffer_len = sizeof(char); + case SQLDT_UCHAR: + bind->is_unsigned = 1; + FALLTHROUGH + case SQLDT_CHAR: + bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(char)); + Assert_retr(SQL_ERROR, buffer_len == sizeof(char)); break; - case SQLDT_USHORT: bind->is_unsigned = 1; - case SQLDT_SHORT: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(short)); - buffer_len = sizeof(short); + case SQLDT_USHORT: + bind->is_unsigned = 1; + FALLTHROUGH + case SQLDT_SHORT: + bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(short)); + Assert_retr(SQL_ERROR, buffer_len == sizeof(short)); break; - case SQLDT_UINT: bind->is_unsigned = 1; - case SQLDT_INT: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(int)); - buffer_len = sizeof(int); + case SQLDT_UINT: + bind->is_unsigned = 1; + FALLTHROUGH + case SQLDT_INT: + bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(int)); + Assert_retr(SQL_ERROR, buffer_len == sizeof(int)); break; - case SQLDT_ULONG: bind->is_unsigned = 1; - case SQLDT_LONG: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(long)); - buffer_len = sizeof(long); + case SQLDT_ULONG: + bind->is_unsigned = 1; + FALLTHROUGH + case SQLDT_LONG: + bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(long)); + Assert_retr(SQL_ERROR, buffer_len == sizeof(long)); break; - case SQLDT_ULONGLONG: bind->is_unsigned = 1; - case SQLDT_LONGLONG: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(int64)); - buffer_len = sizeof(int64); + case SQLDT_ULONGLONG: + bind->is_unsigned = 1; + FALLTHROUGH + case SQLDT_LONGLONG: + bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(long long)); + Assert_retr(SQL_ERROR, buffer_len == sizeof(long long)); + break; + case SQLDT_BOOL: + bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(bool)); + Assert_retr(SQL_ERROR, buffer_len == sizeof(bool)); + break; + case SQLDT_TIME: + bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(time_t)); + Assert_retr(SQL_ERROR, buffer_len == sizeof(time_t)); break; // floating point - case SQLDT_FLOAT: bind->buffer_type = MYSQL_TYPE_FLOAT; - buffer_len = 4; + case SQLDT_FLOAT: + bind->buffer_type = MYSQL_TYPE_FLOAT; + Assert_retr(SQL_ERROR, buffer_len == 4); break; - case SQLDT_DOUBLE: bind->buffer_type = MYSQL_TYPE_DOUBLE; - buffer_len = 8; + case SQLDT_DOUBLE: + bind->buffer_type = MYSQL_TYPE_DOUBLE; + Assert_retr(SQL_ERROR, buffer_len == 8); break; // other case SQLDT_STRING: - case SQLDT_ENUM: bind->buffer_type = MYSQL_TYPE_STRING; + case SQLDT_ENUM: + bind->buffer_type = MYSQL_TYPE_STRING; break; - case SQLDT_BLOB: bind->buffer_type = MYSQL_TYPE_BLOB; + case SQLDT_BLOB: + bind->buffer_type = MYSQL_TYPE_BLOB; break; default: ShowDebug("Sql_P_BindSqlDataType: unsupported buffer type (%u)\n", buffer_type); @@ -483,7 +534,8 @@ static int Sql_P_BindSqlDataType(MYSQL_BIND* bind, enum SqlDataType buffer_type, /// Prints debug information about a field (type and length). /// /// @private -static void Sql_P_ShowDebugMysqlFieldInfo(const char* prefix, enum enum_field_types type, int is_unsigned, unsigned long length, const char* length_postfix) { +static void Sql_P_ShowDebugMysqlFieldInfo(const char *prefix, enum enum_field_types type, int is_unsigned, unsigned long length, const char *length_postfix) +{ const char *sign = (is_unsigned ? "UNSIGNED " : ""); const char *type_string = NULL; switch (type) { @@ -524,6 +576,7 @@ static void SqlStmt_P_ShowDebugTruncatedColumn(struct SqlStmt *self, size_t i) MYSQL_FIELD* field; MYSQL_BIND* column; + nullpo_retv(self); meta = mysql_stmt_result_metadata(self->stmt); field = mysql_fetch_field_direct(meta, (unsigned int)i); ShowSQL("DB error - data of field '%s' was truncated.\n", field->name); @@ -538,7 +591,7 @@ static void SqlStmt_P_ShowDebugTruncatedColumn(struct SqlStmt *self, size_t i) } /// Allocates and initializes a new SqlStmt handle. -struct SqlStmt *SqlStmt_Malloc(struct Sql *sql) +static struct SqlStmt *SqlStmt_Malloc(struct Sql *sql) { struct SqlStmt *self; MYSQL_STMT* stmt; @@ -566,8 +619,8 @@ struct SqlStmt *SqlStmt_Malloc(struct Sql *sql) } /// Prepares the statement. -int SqlStmt_Prepare(struct SqlStmt *self, const char *query, ...) __attribute__((format(printf, 2, 3))); -int SqlStmt_Prepare(struct SqlStmt *self, const char *query, ...) +static int SqlStmt_Prepare(struct SqlStmt *self, const char *query, ...) __attribute__((format(printf, 2, 3))); +static int SqlStmt_Prepare(struct SqlStmt *self, const char *query, ...) { int res; va_list args; @@ -580,7 +633,7 @@ int SqlStmt_Prepare(struct SqlStmt *self, const char *query, ...) } /// Prepares the statement. -int SqlStmt_PrepareV(struct SqlStmt *self, const char *query, va_list args) +static int SqlStmt_PrepareV(struct SqlStmt *self, const char *query, va_list args) { if( self == NULL ) return SQL_ERROR; @@ -600,7 +653,7 @@ int SqlStmt_PrepareV(struct SqlStmt *self, const char *query, va_list args) } /// Prepares the statement. -int SqlStmt_PrepareStr(struct SqlStmt *self, const char *query) +static int SqlStmt_PrepareStr(struct SqlStmt *self, const char *query) { if( self == NULL ) return SQL_ERROR; @@ -620,7 +673,7 @@ int SqlStmt_PrepareStr(struct SqlStmt *self, const char *query) } /// Returns the number of parameters in the prepared statement. -size_t SqlStmt_NumParams(struct SqlStmt *self) +static size_t SqlStmt_NumParams(struct SqlStmt *self) { if( self ) return (size_t)mysql_stmt_param_count(self->stmt); @@ -629,7 +682,7 @@ size_t SqlStmt_NumParams(struct SqlStmt *self) } /// Binds a parameter to a buffer. -int SqlStmt_BindParam(struct SqlStmt *self, size_t idx, enum SqlDataType buffer_type, const void *buffer, size_t buffer_len) +static int SqlStmt_BindParam(struct SqlStmt *self, size_t idx, enum SqlDataType buffer_type, const void *buffer, size_t buffer_len) { if( self == NULL ) return SQL_ERROR; @@ -653,8 +706,8 @@ int SqlStmt_BindParam(struct SqlStmt *self, size_t idx, enum SqlDataType buffer_ if (idx >= self->max_params) return SQL_SUCCESS; // out of range - ignore -PRAGMA_GCC45(GCC diagnostic push) -PRAGMA_GCC45(GCC diagnostic ignored "-Wcast-qual") +PRAGMA_GCC46(GCC diagnostic push) +PRAGMA_GCC46(GCC diagnostic ignored "-Wcast-qual") /* * MySQL uses the same struct with a non-const buffer for both * parameters (input) and columns (output). @@ -662,11 +715,11 @@ PRAGMA_GCC45(GCC diagnostic ignored "-Wcast-qual") * dropping a const qualifier here. */ return Sql_P_BindSqlDataType(self->params+idx, buffer_type, (void *)buffer, buffer_len, NULL, NULL); -PRAGMA_GCC45(GCC diagnostic pop) +PRAGMA_GCC46(GCC diagnostic pop) } /// Executes the prepared statement. -int SqlStmt_Execute(struct SqlStmt *self) +static int SqlStmt_Execute(struct SqlStmt *self) { if( self == NULL ) return SQL_ERROR; @@ -691,7 +744,7 @@ int SqlStmt_Execute(struct SqlStmt *self) } /// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE statement. -uint64 SqlStmt_LastInsertId(struct SqlStmt *self) +static uint64 SqlStmt_LastInsertId(struct SqlStmt *self) { if( self ) return (uint64)mysql_stmt_insert_id(self->stmt); @@ -700,7 +753,7 @@ uint64 SqlStmt_LastInsertId(struct SqlStmt *self) } /// Returns the number of columns in each row of the result. -size_t SqlStmt_NumColumns(struct SqlStmt *self) +static size_t SqlStmt_NumColumns(struct SqlStmt *self) { if( self ) return (size_t)mysql_stmt_field_count(self->stmt); @@ -709,7 +762,7 @@ size_t SqlStmt_NumColumns(struct SqlStmt *self) } /// Binds the result of a column to a buffer. -int SqlStmt_BindColumn(struct SqlStmt *self, size_t idx, enum SqlDataType buffer_type, void *buffer, size_t buffer_len, uint32 *out_length, int8 *out_is_null) +static int SqlStmt_BindColumn(struct SqlStmt *self, size_t idx, enum SqlDataType buffer_type, void *buffer, size_t buffer_len, uint32 *out_length, int8 *out_is_null) { if (self == NULL) return SQL_ERROR; @@ -751,7 +804,7 @@ int SqlStmt_BindColumn(struct SqlStmt *self, size_t idx, enum SqlDataType buffer } /// Returns the number of rows in the result. -uint64 SqlStmt_NumRows(struct SqlStmt *self) +static uint64 SqlStmt_NumRows(struct SqlStmt *self) { if (self != NULL) return (uint64)mysql_stmt_num_rows(self->stmt); @@ -760,7 +813,7 @@ uint64 SqlStmt_NumRows(struct SqlStmt *self) } /// Fetches the next row. -int SqlStmt_NextRow(struct SqlStmt *self) +static int SqlStmt_NextRow(struct SqlStmt *self) { int err; size_t i; @@ -778,8 +831,6 @@ int SqlStmt_NextRow(struct SqlStmt *self) // check for errors if (err == MYSQL_NO_DATA) return SQL_NO_DATA; -#if defined(MYSQL_DATA_TRUNCATED) - // MySQL 5.0/5.1 defines and returns MYSQL_DATA_TRUNCATED [FlavioJS] if (err == MYSQL_DATA_TRUNCATED) { my_bool truncated; @@ -804,7 +855,6 @@ int SqlStmt_NextRow(struct SqlStmt *self) ShowSQL("DB error - data truncated (unknown source)\n"); return SQL_ERROR; } -#endif if (err) { ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); hercules_mysql_error_handler(mysql_stmt_errno(self->stmt)); @@ -816,18 +866,6 @@ int SqlStmt_NextRow(struct SqlStmt *self) for (i = 0; i < cols; ++i) { unsigned long length = self->column_lengths[i].length; MYSQL_BIND *column = &self->columns[i]; -#if !defined(MYSQL_DATA_TRUNCATED) - // MySQL 4.1/(below?) returns success even if data is truncated, so we test truncation manually [FlavioJS] - if (column->buffer_length < length) { - // report truncated column - if (column->buffer_type == MYSQL_TYPE_STRING || column->buffer_type == MYSQL_TYPE_BLOB) { - // string/enum/blob column - SqlStmt_P_ShowDebugTruncatedColumn(self, i); - return SQL_ERROR; - } - // FIXME numeric types and null [FlavioJS] - } -#endif if (self->column_lengths[i].out_length) *self->column_lengths[i].out_length = (uint32)length; if (column->buffer_type == MYSQL_TYPE_STRING) { @@ -843,14 +881,14 @@ int SqlStmt_NextRow(struct SqlStmt *self) } /// Frees the result of the statement execution. -void SqlStmt_FreeResult(struct SqlStmt *self) +static void SqlStmt_FreeResult(struct SqlStmt *self) { if( self ) mysql_stmt_free_result(self->stmt); } /// Shows debug information (with statement). -void SqlStmt_ShowDebug_(struct SqlStmt *self, const char *debug_file, const unsigned long debug_line) +static void SqlStmt_ShowDebug_(struct SqlStmt *self, const char *debug_file, const unsigned long debug_line) { if( self == NULL ) ShowDebug("at %s:%lu - self is NULL\n", debug_file, debug_line); @@ -861,7 +899,7 @@ void SqlStmt_ShowDebug_(struct SqlStmt *self, const char *debug_file, const unsi } /// Frees a SqlStmt returned by SqlStmt_Malloc. -void SqlStmt_Free(struct SqlStmt *self) +static void SqlStmt_Free(struct SqlStmt *self) { if( self ) { @@ -878,60 +916,74 @@ void SqlStmt_Free(struct SqlStmt *self) aFree(self); } } + /* receives mysql error codes during runtime (not on first-time-connects) */ -void hercules_mysql_error_handler(unsigned int ecode) { - static unsigned int retry = 1; +static void hercules_mysql_error_handler(unsigned int ecode) +{ switch( ecode ) { case 2003:/* Can't connect to MySQL (this error only happens here when failing to reconnect) */ if( mysql_reconnect_type == 1 ) { + static int retry = 1; if( ++retry > mysql_reconnect_count ) { - ShowFatalError("MySQL has been unreachable for too long, %u reconnects were attempted. Shutting Down\n", retry); + ShowFatalError("MySQL has been unreachable for too long, %d reconnects were attempted. Shutting Down\n", retry); exit(EXIT_FAILURE); } } break; } } -void Sql_inter_server_read(const char* cfgName, bool first) { - char line[1024], w1[1024], w2[1024]; - FILE* fp; - - fp = fopen(cfgName, "r"); - if(fp == NULL) { - if( first ) { - ShowFatalError("File not found: %s\n", cfgName); - exit(EXIT_FAILURE); - } else - ShowError("File not found: %s\n", cfgName); - return; + +/** + * Parses mysql_reconnect from inter_configuration. + * + * @param filename Path to configuration file. + * @param imported Whether the current config is imported from another file. + * + * @retval false in case of error. + */ +static bool Sql_inter_server_read(const char *filename, bool imported) +{ + struct config_t config; + const struct config_setting_t *setting = NULL; + const char *import = NULL; + bool retval = true; + + nullpo_retr(false, filename); + + if (!libconfig->load_file(&config, filename)) + return false; + + if ((setting = libconfig->lookup(&config, "inter_configuration/mysql_reconnect")) == NULL) { + config_destroy(&config); + if (imported) + return true; + ShowError("Sql_inter_server_read: inter_configuration/mysql_reconnect was not found in %s!\n", filename); + return false; } - while (fgets(line, sizeof(line), fp)) { - int i = sscanf(line, "%1023[^:]: %1023[^\r\n]", w1, w2); - if (i != 2) - continue; + if (libconfig->setting_lookup_int(setting, "type", &mysql_reconnect_type) == CONFIG_TRUE) { + if (mysql_reconnect_type != 1 && mysql_reconnect_type != 2) { + ShowError("%s::inter_configuration/mysql_reconnect/type is set to %d which is not valid, defaulting to 1...\n", filename, mysql_reconnect_type); + mysql_reconnect_type = 1; + } + } + if (libconfig->setting_lookup_int(setting, "count", &mysql_reconnect_count) == CONFIG_TRUE) { + if (mysql_reconnect_count < 1) + mysql_reconnect_count = 1; + } - if(!strcmpi(w1,"mysql_reconnect_type")) { - mysql_reconnect_type = atoi(w2); - switch( mysql_reconnect_type ) { - case 1: - case 2: - break; - default: - ShowError("%s::mysql_reconnect_type is set to %d which is not valid, defaulting to 1...\n", cfgName, mysql_reconnect_type); - mysql_reconnect_type = 1; - break; - } - } else if(!strcmpi(w1,"mysql_reconnect_count")) { - mysql_reconnect_count = atoi(w2); - if( mysql_reconnect_count < 1 ) - mysql_reconnect_count = 1; - } else if(!strcmpi(w1,"import")) - Sql_inter_server_read(w2,false); + // import should overwrite any previous configuration, so it should be called last + if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) { + if (strcmp(import, filename) == 0 || strcmp(import, "conf/common/inter-server.conf") == 0) { // FIXME: Hardcoded path + ShowWarning("Sql_inter_server_read: Loop detected in %s! Skipping 'import'...\n", filename); + } else { + if (!Sql_inter_server_read(import, true)) + retval = false; + } } - fclose(fp); - return; + libconfig->destroy(&config); + return retval; } void Sql_HerculesUpdateCheck(struct Sql *self) @@ -1033,10 +1085,13 @@ void Sql_HerculesUpdateSkip(struct Sql *self, const char *filename) return; } -void Sql_Init(void) { - Sql_inter_server_read("conf/inter-server.conf",true); +void Sql_Init(void) +{ + Sql_inter_server_read("conf/common/inter-server.conf", false); // FIXME: Hardcoded path } -void sql_defaults(void) { + +void sql_defaults(void) +{ SQL = &sql_s; SQL->Connect = Sql_Connect; |