1
0
mirror of https://github.com/mariadb-corporation/mariadb-connector-c.git synced 2025-08-07 02:42:49 +03:00

Initial aurora implementation

This commit is contained in:
Georg Richter
2015-12-10 12:52:51 +01:00
parent ebe3cc9935
commit bec245a913
22 changed files with 1143 additions and 110 deletions

View File

@@ -21,6 +21,14 @@ IF(COMMAND CMAKE_POLICY)
CMAKE_POLICY(SET CMP0003 NEW) CMAKE_POLICY(SET CMP0003 NEW)
ENDIF() ENDIF()
#Allow access to non existing targets
IF(CMAKE_VERSION VERSION_GREATER "2.9.9")
CMAKE_POLICY(SET CMP0026 OLD)
CMAKE_POLICY(SET CMP0042 OLD)
CMAKE_POLICY(SET CMP0045 OLD)
ENDIF()
SET(MARIADB_CONNECTOR_C_COPYRIGHT "2013-2015 MariaDB Corporation Ab") SET(MARIADB_CONNECTOR_C_COPYRIGHT "2013-2015 MariaDB Corporation Ab")
### Options ### ### Options ###
@@ -149,6 +157,10 @@ IF(CMAKE_HAVE_PTHREAD_H)
SET(CMAKE_REQUIRED_INCLUDES pthread.h) SET(CMAKE_REQUIRED_INCLUDES pthread.h)
ENDIF() ENDIF()
IF(DBUG_OFF)
ADD_DEFINITIONS(-DDBUG_OFF=1)
ENDIF()
IF(WIN32) IF(WIN32)
SET(HAVE_THREADS 1) SET(HAVE_THREADS 1)
ADD_DEFINITIONS(-DHAVE_DLOPEN) ADD_DEFINITIONS(-DHAVE_DLOPEN)

View File

@@ -1,12 +1,16 @@
# plugin configuration # plugin configuration
MACRO(REGISTER_PLUGIN name source struct type target allow) MACRO(REGISTER_PLUGIN name source struct type target allow)
SET(PLUGIN_TYPE ${${name}})
IF(NOT PLUGIN_TYPE STREQUAL "OFF")
SET(PLUGIN_TYPE ${type})
ENDIF()
IF(PLUGINS) IF(PLUGINS)
LIST(REMOVE_ITEM PLUGINS ${name}) LIST(REMOVE_ITEM PLUGINS ${name})
ENDIF() ENDIF()
SET(${name}_PLUGIN_SOURCE ${source}) SET(${name}_PLUGIN_SOURCE ${source})
MARK_AS_ADVANCED(${name}_PLUGIN_SOURCE}) MARK_AS_ADVANCED(${name}_PLUGIN_SOURCE})
SET(${name}_PLUGIN_TYPE ${type}) SET(${name}_PLUGIN_TYPE ${PLUGIN_TYPE})
IF(NOT ${target} STREQUAL "") IF(NOT ${target} STREQUAL "")
SET(${name}_PLUGIN_TARGET ${target}) SET(${name}_PLUGIN_TARGET ${target})
ENDIF() ENDIF()
@@ -41,6 +45,7 @@ REGISTER_PLUGIN("TRACE_EXAMPLE" "${CMAKE_SOURCE_DIR}/plugins/trace/trace_example
#Connection #Connection
REGISTER_PLUGIN("REPLICATION" "${CMAKE_SOURCE_DIR}/plugins/connection/replication.c" "connection_replication_plugin" "STATIC" "" 1) REGISTER_PLUGIN("REPLICATION" "${CMAKE_SOURCE_DIR}/plugins/connection/replication.c" "connection_replication_plugin" "STATIC" "" 1)
REGISTER_PLUGIN("AURORA" "${CMAKE_SOURCE_DIR}/plugins/connection/aurora.c" "connection_aurora_plugin" "STATIC" "" 1)
# Allow registration of additional plugins # Allow registration of additional plugins
IF(PLUGIN_CONF_FILE) IF(PLUGIN_CONF_FILE)
@@ -50,7 +55,7 @@ ENDIF()
SET(LIBMARIADB_SOURCES "") SET(LIBMARIADB_SOURCES "")
MESSAGE(STATUS "Plugin configuration") MESSAGE(STATUS "Plugin configuration:")
FOREACH(PLUGIN ${PLUGINS}) FOREACH(PLUGIN ${PLUGINS})
IF(WITH_${PLUGIN}_PLUGIN AND ${${PLUGIN}_PLUGIN_CHG} GREATER 0) IF(WITH_${PLUGIN}_PLUGIN AND ${${PLUGIN}_PLUGIN_CHG} GREATER 0)
SET(${PLUGIN}_PLUGIN_TYPE ${WITH_${PLUGIN}_PLUGIN}) SET(${PLUGIN}_PLUGIN_TYPE ${WITH_${PLUGIN}_PLUGIN})
@@ -72,6 +77,6 @@ ENDIF()
LIST(REMOVE_DUPLICATES LIBMARIADB_SOURCES) LIST(REMOVE_DUPLICATES LIBMARIADB_SOURCES)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/libmariadb/client_plugin.c.in CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/libmariadb/client_plugin.c.in
${CMAKE_BINARY_DIR}/libmariadb/client_plugin.c) ${CMAKE_BINARY_DIR}/libmariadb/client_plugin.c)
MARK_AS_ADVANCED(LIBMARIADB_SOURCES) MARK_AS_ADVANCED(LIBMARIADB_SOURCES)

View File

@@ -48,10 +48,12 @@ struct st_mysql_options_extension {
double progress, double progress,
const char *proc_info, const char *proc_info,
unsigned int proc_info_length); unsigned int proc_info_length);
MARIADB_DB_DRIVER *db_driver; MARIADB_DB_DRIVER *db_driver;
char *ssl_fp; /* finger print of server certificate */ char *ssl_fp; /* finger print of server certificate */
char *ssl_fp_list; /* white list of finger prints */ char *ssl_fp_list; /* white list of finger prints */
char *ssl_pw; /* password for encrypted certificates */ char *ssl_pw; /* password for encrypted certificates */
char *url; /* for connection handler we need to save URL for reconnect */
my_bool read_only;
}; };
#define OPT_HAS_EXT_VAL(a,key) \ #define OPT_HAS_EXT_VAL(a,key) \

View File

@@ -482,8 +482,8 @@ const char * STDCALL mysql_get_client_info(void);
unsigned long STDCALL mysql_get_client_version(void); unsigned long STDCALL mysql_get_client_version(void);
my_bool STDCALL mariadb_connection(MYSQL *mysql); my_bool STDCALL mariadb_connection(MYSQL *mysql);
const char * STDCALL mysql_get_server_name(MYSQL *mysql); const char * STDCALL mysql_get_server_name(MYSQL *mysql);
CHARSET_INFO * STDCALL mysql_get_charset_by_name(const char *csname); CHARSET_INFO * STDCALL mariadb_get_charset_by_name(const char *csname);
CHARSET_INFO * STDCALL mysql_get_charset_by_nr(unsigned int csnr); CHARSET_INFO * STDCALL mariadb_get_charset_by_nr(unsigned int csnr);
size_t STDCALL mariadb_convert_string(const char *from, size_t *from_len, CHARSET_INFO *from_cs, size_t STDCALL mariadb_convert_string(const char *from, size_t *from_len, CHARSET_INFO *from_cs,
char *to, size_t *to_len, CHARSET_INFO *to_cs, int *errorcode); char *to, size_t *to_len, CHARSET_INFO *to_cs, int *errorcode);
int STDCALL mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...); int STDCALL mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...);
@@ -493,6 +493,7 @@ my_socket STDCALL mysql_get_socket(const MYSQL *mysql);
unsigned int STDCALL mysql_get_timeout_value(const MYSQL *mysql); unsigned int STDCALL mysql_get_timeout_value(const MYSQL *mysql);
unsigned int STDCALL mysql_get_timeout_value_ms(const MYSQL *mysql); unsigned int STDCALL mysql_get_timeout_value_ms(const MYSQL *mysql);
int STDCALL mariadb_get_connection_type(MYSQL *mysql); int STDCALL mariadb_get_connection_type(MYSQL *mysql);
my_bool STDCALL mysql_reconnect(MYSQL *mysql);
/* Async API */ /* Async API */
int STDCALL mysql_close_start(MYSQL *sock); int STDCALL mysql_close_start(MYSQL *sock);
@@ -628,6 +629,7 @@ struct st_mysql_methods {
int (*db_stmt_fetch_to_bind)(MYSQL_STMT *stmt, unsigned char *row); int (*db_stmt_fetch_to_bind)(MYSQL_STMT *stmt, unsigned char *row);
void (*db_stmt_flush_unbuffered)(MYSQL_STMT *stmt); void (*db_stmt_flush_unbuffered)(MYSQL_STMT *stmt);
void (*set_error)(MYSQL *mysql, unsigned int error_nr, const char *sqlstate, const char *format, ...); void (*set_error)(MYSQL *mysql, unsigned int error_nr, const char *sqlstate, const char *format, ...);
my_bool (*reconnect)(MYSQL *mysql);
}; };
/* synonyms/aliases functions */ /* synonyms/aliases functions */

View File

@@ -95,6 +95,7 @@ typedef struct st_ma_connection_plugin
int (*options)(MYSQL *mysql, enum mysql_option, void *arg); int (*options)(MYSQL *mysql, enum mysql_option, void *arg);
int (*set_connection)(MYSQL *mysql,enum enum_server_command command, const char *arg, int (*set_connection)(MYSQL *mysql,enum enum_server_command command, const char *arg,
size_t length, my_bool skipp_check, void *opt_arg); size_t length, my_bool skipp_check, void *opt_arg);
my_bool (*reconnect)(MYSQL *mysql);
} MARIADB_CONNECTION_PLUGIN; } MARIADB_CONNECTION_PLUGIN;
#define MARIADB_DB_DRIVER(a) ((a)->ext_db) #define MARIADB_DB_DRIVER(a) ((a)->ext_db)

View File

@@ -230,6 +230,7 @@ typedef struct st_connection_handler
{ {
struct st_ma_connection_plugin *plugin; struct st_ma_connection_plugin *plugin;
void *data; void *data;
my_bool active;
my_bool free_data; my_bool free_data;
} MA_CONNECTION_HANDLER; } MA_CONNECTION_HANDLER;

View File

@@ -34,6 +34,8 @@ SET(EXPORT_SYMBOLS
mariadb_dyncol_val_double mariadb_dyncol_val_double
mariadb_dyncol_val_long mariadb_dyncol_val_long
mariadb_dyncol_val_str mariadb_dyncol_val_str
mariadb_get_charset_by_name
mariadb_get_charset_by_nr
mariadb_get_connection_type mariadb_get_connection_type
mysql_affected_rows mysql_affected_rows
mysql_autocommit mysql_autocommit
@@ -124,6 +126,7 @@ SET(EXPORT_SYMBOLS
mysql_query mysql_query
mysql_query_cont mysql_query_cont
mysql_query_start mysql_query_start
mysql_reconnect
mysql_read_query_result mysql_read_query_result
mysql_read_query_result_cont mysql_read_query_result_cont
mysql_read_query_result_start mysql_read_query_result_start

View File

@@ -124,11 +124,14 @@ struct st_mysql_methods MARIADB_DEFAULT_METHODS;
#define native_password_plugin_name "mysql_native_password" #define native_password_plugin_name "mysql_native_password"
#define IS_CONNHDLR_ACTIVE(mysql)\
((mysql)->net.conn_hdlr && (mysql)->net.conn_hdlr->active)
static void end_server(MYSQL *mysql); static void end_server(MYSQL *mysql);
static void mysql_close_memory(MYSQL *mysql); static void mysql_close_memory(MYSQL *mysql);
void read_user_name(char *name); void read_user_name(char *name);
static void append_wild(char *to,char *end,const char *wild); static void append_wild(char *to,char *end,const char *wild);
static my_bool mysql_reconnect(MYSQL *mysql); my_bool mysql_reconnect(MYSQL *mysql);
static int cli_report_progress(MYSQL *mysql, uchar *packet, uint length); static int cli_report_progress(MYSQL *mysql, uchar *packet, uint length);
extern int mysql_client_plugin_init(); extern int mysql_client_plugin_init();
@@ -354,13 +357,6 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg,
DBUG_PRINT("info", ("server_command: %d packet_size: %u", command, length)); DBUG_PRINT("info", ("server_command: %d packet_size: %u", command, length));
if (mysql->net.conn_hdlr && mysql->net.conn_hdlr->data)
{
result= mysql->net.conn_hdlr->plugin->set_connection(mysql, command, arg, length, skipp_check, opt_arg);
if (result== -1)
DBUG_RETURN(result);
}
if (mysql->net.pvio == 0) if (mysql->net.pvio == 0)
{ /* Do reconnect if possible */ { /* Do reconnect if possible */
if (mysql_reconnect(mysql)) if (mysql_reconnect(mysql))
@@ -376,6 +372,14 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg,
goto end; goto end;
} }
if (IS_CONNHDLR_ACTIVE(mysql))
{
result= mysql->net.conn_hdlr->plugin->set_connection(mysql, command, arg, length, skipp_check, opt_arg);
if (result== -1)
DBUG_RETURN(result);
}
CLEAR_CLIENT_ERROR(mysql); CLEAR_CLIENT_ERROR(mysql);
mysql->info=0; mysql->info=0;
@@ -384,13 +388,6 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg,
if (!arg) if (!arg)
arg=""; arg="";
/* check if connection kills itself */
if (command == COM_PROCESS_KILL)
{
unsigned long thread_id= uint4korr(arg);
if (thread_id == mysql->thread_id)
skipp_check= 1;
}
if (net_write_command(net,(uchar) command,arg, if (net_write_command(net,(uchar) command,arg,
length ? length : (ulong) strlen(arg))) length ? length : (ulong) strlen(arg)))
{ {
@@ -660,7 +657,7 @@ enum option_val
#define OPT_SET_EXTENDED_VALUE_INT(OPTS, KEY, VAL) \ #define OPT_SET_EXTENDED_VALUE_INT(OPTS, KEY, VAL) \
CHECK_OPT_EXTENSION_SET(OPTS) \ CHECK_OPT_EXTENSION_SET(OPTS) \
+ (OPTS)->extension->KEY= (VAL) (OPTS)->extension->KEY= (VAL)
static TYPELIB option_types={array_elements(default_options)-1, static TYPELIB option_types={array_elements(default_options)-1,
@@ -1145,6 +1142,7 @@ mysql_init(MYSQL *mysql)
bzero((char*) (mysql),sizeof(*(mysql))); bzero((char*) (mysql),sizeof(*(mysql)));
mysql->options.connect_timeout=CONNECT_TIMEOUT; mysql->options.connect_timeout=CONNECT_TIMEOUT;
mysql->charset= default_charset_info; mysql->charset= default_charset_info;
mysql->methods= &MARIADB_DEFAULT_METHODS;
strmov(mysql->net.sqlstate, "00000"); strmov(mysql->net.sqlstate, "00000");
mysql->net.last_error[0]= mysql->net.last_errno= 0; mysql->net.last_error[0]= mysql->net.last_errno= 0;
@@ -1291,9 +1289,38 @@ mysql_real_connect(MYSQL *mysql, const char *host, const char *user,
const char *passwd, const char *db, const char *passwd, const char *db,
uint port, const char *unix_socket,unsigned long client_flag) uint port, const char *unix_socket,unsigned long client_flag)
{ {
char *end;
if (!mysql->methods) if (!mysql->methods)
mysql->methods= &MARIADB_DEFAULT_METHODS; mysql->methods= &MARIADB_DEFAULT_METHODS;
if (host && (end= strstr(host, "://")))
{
MARIADB_CONNECTION_PLUGIN *plugin;
char plugin_name[64];
bzero(plugin_name, 64);
strncpy(plugin_name, host, MIN(end - host, 63));
end+= 3;
if (!(plugin= (MARIADB_CONNECTION_PLUGIN *)mysql_client_find_plugin(mysql, plugin_name, MARIADB_CLIENT_CONNECTION_PLUGIN)))
return NULL;
if (!(mysql->net.conn_hdlr= (MA_CONNECTION_HANDLER *)my_malloc(sizeof(MA_CONNECTION_HANDLER), MYF(MY_ZEROFILL))))
{
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return NULL;
}
/* save URL for reconnect */
OPT_SET_EXTENDED_VALUE_STR(&mysql->options, url, host);
mysql->net.conn_hdlr->plugin= plugin;
if (plugin && plugin->connect)
return plugin->connect(mysql, end, user, passwd, db, port, unix_socket, client_flag);
}
return mysql->methods->db_connect(mysql, host, user, passwd, return mysql->methods->db_connect(mysql, host, user, passwd,
db, port, unix_socket, client_flag); db, port, unix_socket, client_flag);
} }
@@ -1320,32 +1347,6 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
if (!mysql->methods) if (!mysql->methods)
mysql->methods= &MARIADB_DEFAULT_METHODS; mysql->methods= &MARIADB_DEFAULT_METHODS;
/* special case:
* If hostname contains "://", e.g. "repl://localhost", we need to process connection
* by connection plugin
*/
if (host && (end= strstr(host, "://")))
{
MARIADB_CONNECTION_PLUGIN *plugin;
char plugin_name[64];
bzero(plugin_name, 64);
strncpy(plugin_name, host, MIN(end - host, 63));
end+= 3;
if (!(plugin= (MARIADB_CONNECTION_PLUGIN *)mysql_client_find_plugin(mysql, plugin_name, MARIADB_CLIENT_CONNECTION_PLUGIN)))
DBUG_RETURN(NULL);
if (!(mysql->net.conn_hdlr= (MA_CONNECTION_HANDLER *)my_malloc(sizeof(MA_CONNECTION_HANDLER), MYF(MY_ZEROFILL))))
{
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
DBUG_RETURN(NULL);
}
mysql->net.conn_hdlr->plugin= plugin;
if (plugin->connect)
return plugin->connect(mysql, end, user, passwd, db, port, unix_socket, client_flag);
}
ma_set_connect_attrs(mysql); ma_set_connect_attrs(mysql);
@@ -1659,7 +1660,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
mysql->reconnect= 0; mysql->reconnect= 0;
for (;begin < end; begin++) for (;begin < end; begin++)
{ {
if (mysql_real_query(mysql, *begin, (unsigned long)strlen(*begin))) if (mysql_real_query(mysql, *begin, (unsigned long)strlen(*begin)))
goto error; goto error;
@@ -1715,14 +1716,22 @@ my_suspend_hook(my_bool suspend, void *data)
} }
static my_bool mysql_reconnect(MYSQL *mysql) my_bool STDCALL mysql_reconnect(MYSQL *mysql)
{ {
MYSQL tmp_mysql; MYSQL tmp_mysql;
struct my_hook_data hook_data; struct my_hook_data hook_data;
struct mysql_async_context *ctxt= NULL; struct mysql_async_context *ctxt= NULL;
LIST *li_stmt= mysql->stmts;
DBUG_ENTER("mysql_reconnect"); DBUG_ENTER("mysql_reconnect");
/* check if connection handler is active */
if (IS_CONNHDLR_ACTIVE(mysql))
{
if (mysql->net.conn_hdlr->plugin && mysql->net.conn_hdlr->plugin->connect)
DBUG_RETURN(mysql->net.conn_hdlr->plugin->reconnect(mysql));
}
if (!mysql->reconnect || if (!mysql->reconnect ||
(mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info) (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info)
{ {
@@ -1734,6 +1743,13 @@ static my_bool mysql_reconnect(MYSQL *mysql)
mysql_init(&tmp_mysql); mysql_init(&tmp_mysql);
tmp_mysql.options=mysql->options; tmp_mysql.options=mysql->options;
if (mysql->net.conn_hdlr)
{
tmp_mysql.net.conn_hdlr= mysql->net.conn_hdlr;
mysql->net.conn_hdlr= 0;
}
/* don't reread options from configuration files */ /* don't reread options from configuration files */
tmp_mysql.options.my_cnf_group= tmp_mysql.options.my_cnf_file= NULL; tmp_mysql.options.my_cnf_group= tmp_mysql.options.my_cnf_file= NULL;
@@ -1762,6 +1778,17 @@ static my_bool mysql_reconnect(MYSQL *mysql)
DBUG_RETURN(1); DBUG_RETURN(1);
} }
for (;li_stmt;li_stmt= li_stmt->next)
{
MYSQL_STMT *stmt= (MYSQL_STMT *)li_stmt->data;
if (stmt->state != MYSQL_STMT_INITTED)
{
stmt->state= MYSQL_STMT_INITTED;
SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
}
}
tmp_mysql.reconnect= mysql->reconnect; tmp_mysql.reconnect= mysql->reconnect;
tmp_mysql.free_me= mysql->free_me; tmp_mysql.free_me= mysql->free_me;
tmp_mysql.stmts= mysql->stmts; tmp_mysql.stmts= mysql->stmts;
@@ -1923,6 +1950,7 @@ static void mysql_close_options(MYSQL *mysql)
my_free(mysql->options.extension->ssl_fp); my_free(mysql->options.extension->ssl_fp);
my_free(mysql->options.extension->ssl_fp_list); my_free(mysql->options.extension->ssl_fp_list);
my_free(mysql->options.extension->ssl_pw); my_free(mysql->options.extension->ssl_pw);
my_free(mysql->options.extension->url);
if(hash_inited(&mysql->options.extension->connect_attrs)) if(hash_inited(&mysql->options.extension->connect_attrs))
hash_free(&mysql->options.extension->connect_attrs); hash_free(&mysql->options.extension->connect_attrs);
if ((ctxt = mysql->options.extension->async_context) != 0) if ((ctxt = mysql->options.extension->async_context) != 0)
@@ -1985,7 +2013,8 @@ mysql_close(MYSQL *mysql)
DBUG_ENTER("mysql_close"); DBUG_ENTER("mysql_close");
if (mysql) /* Some simple safety */ if (mysql) /* Some simple safety */
{ {
if (mysql->net.conn_hdlr && mysql->net.conn_hdlr->data)
if (IS_CONNHDLR_ACTIVE(mysql))
{ {
void *p= (void *)mysql->net.conn_hdlr; void *p= (void *)mysql->net.conn_hdlr;
mysql->net.conn_hdlr->plugin->close(mysql); mysql->net.conn_hdlr->plugin->close(mysql);
@@ -1998,6 +2027,7 @@ mysql_close(MYSQL *mysql)
/* reset the connection in all active statements */ /* reset the connection in all active statements */
ma_invalidate_stmts(mysql, "mysql_close()"); ma_invalidate_stmts(mysql, "mysql_close()");
mysql_close_memory(mysql); mysql_close_memory(mysql);
mysql_close_options(mysql); mysql_close_options(mysql);
mysql->host_info=mysql->user=mysql->passwd=mysql->db=0; mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
@@ -2048,7 +2078,9 @@ int mthd_my_read_query_result(MYSQL *mysql)
DBUG_ENTER("mthd_my_read_query_result"); DBUG_ENTER("mthd_my_read_query_result");
if (!mysql || (length = net_safe_read(mysql)) == packet_error) if (!mysql || (length = net_safe_read(mysql)) == packet_error)
{
DBUG_RETURN(1); DBUG_RETURN(1);
}
free_old_query(mysql); /* Free old result */ free_old_query(mysql); /* Free old result */
get_info: get_info:
pos=(uchar*) mysql->net.read_pos; pos=(uchar*) mysql->net.read_pos;
@@ -2496,7 +2528,6 @@ mysql_stat(MYSQL *mysql)
DBUG_RETURN((char*) mysql->net.read_pos); DBUG_RETURN((char*) mysql->net.read_pos);
} }
int STDCALL int STDCALL
mysql_ping(MYSQL *mysql) mysql_ping(MYSQL *mysql)
{ {
@@ -2510,7 +2541,6 @@ mysql_ping(MYSQL *mysql)
return rc; return rc;
} }
char * STDCALL char * STDCALL
mysql_get_server_info(MYSQL *mysql) mysql_get_server_info(MYSQL *mysql)
{ {
@@ -2878,10 +2908,8 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_pw, (char *)arg1); OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_pw, (char *)arg1);
break; break;
case MARIADB_OPT_CONNECTION_READ_ONLY: case MARIADB_OPT_CONNECTION_READ_ONLY:
if (mysql->net.conn_hdlr) OPT_SET_EXTENDED_VALUE_INT(&mysql->options, read_only, *(my_bool *)arg1);
DBUG_RETURN(mysql->net.conn_hdlr->plugin->options(mysql, MARIADB_OPT_CONNECTION_READ_ONLY, arg1)); break;
else
return -1;
default: default:
va_end(ap); va_end(ap);
DBUG_RETURN(-1); DBUG_RETURN(-1);
@@ -3278,6 +3306,15 @@ int STDCALL mariadb_get_connection_type(MYSQL *mysql)
return (int)mysql->net.pvio->type; return (int)mysql->net.pvio->type;
} }
CHARSET_INFO * STDCALL mariadb_get_charset_by_name(const char *csname)
{
return (CHARSET_INFO *)mysql_find_charset_name(csname);
}
CHARSET_INFO * STDCALL mariadb_get_charset_by_nr(unsigned int csnr)
{
return (CHARSET_INFO *)mysql_find_charset_nr(csnr);
}
/* /*
* Default methods for a connection. These methods are * Default methods for a connection. These methods are
* stored in mysql->methods and can be overwritten by * stored in mysql->methods and can be overwritten by
@@ -3315,5 +3352,9 @@ struct st_mysql_methods MARIADB_DEFAULT_METHODS = {
/* store values in bind buffer */ /* store values in bind buffer */
mthd_stmt_fetch_to_bind, mthd_stmt_fetch_to_bind,
/* skip unbuffered stmt result */ /* skip unbuffered stmt result */
mthd_stmt_flush_unbuffered mthd_stmt_flush_unbuffered,
/* set error */
my_set_error,
/* reconnect */
mysql_reconnect
}; };

View File

@@ -416,7 +416,6 @@ int store_param(MYSQL_STMT *stmt, int column, unsigned char **p)
{ {
DBUG_ENTER("store_param"); DBUG_ENTER("store_param");
DBUG_PRINT("info", ("column: %d type: %d", column, stmt->params[column].buffer_type)); DBUG_PRINT("info", ("column: %d type: %d", column, stmt->params[column].buffer_type));
printf("type: %d\n", column, stmt->params[column].buffer_type);
switch (stmt->params[column].buffer_type) { switch (stmt->params[column].buffer_type) {
case MYSQL_TYPE_TINY: case MYSQL_TYPE_TINY:
int1store(*p, *(uchar *)stmt->params[column].buffer); int1store(*p, *(uchar *)stmt->params[column].buffer);

View File

@@ -182,7 +182,9 @@ static my_bool net_realloc(NET *net, size_t length)
/* Remove unwanted characters from connection */ /* Remove unwanted characters from connection */
void net_clear(NET *net) void net_clear(NET *net)
{ {
size_t len;
DBUG_ENTER("net_clear"); DBUG_ENTER("net_clear");
ma_pvio_has_data(net->pvio, &len);
net->compress_pkt_nr= net->pkt_nr=0; /* Ready for new command */ net->compress_pkt_nr= net->pkt_nr=0; /* Ready for new command */
net->write_pos=net->buff; net->write_pos=net->buff;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
@@ -193,6 +195,7 @@ int net_flush(NET *net)
{ {
int error=0; int error=0;
DBUG_ENTER("net_flush"); DBUG_ENTER("net_flush");
if (net->buff != net->write_pos) if (net->buff != net->write_pos)
{ {
error=net_real_write(net,(char*) net->buff, error=net_real_write(net,(char*) net->buff,

View File

@@ -13,10 +13,24 @@ IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC")
"FILE_DESCRIPTION:Connection plugin for master/slave environment") "FILE_DESCRIPTION:Connection plugin for master/slave environment")
ENDIF() ENDIF()
ADD_DEFINITIONS(-DHAVE_REPLICATION_DYNAMIC=1) ADD_DEFINITIONS(-DHAVE_REPLICATION_DYNAMIC=1)
ADD_LIBRARY(replication SHARED replication.c ${EXPORT_FILE}) ADD_LIBRARY(replication SHARED ${replication_RC} replication.c ${EXPORT_FILE})
SET(INSTALL_LIBS replication) SET(INSTALL_LIBS replication)
ENDIF() ENDIF()
IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC")
IF(WIN32)
SET_VERSION_INFO("TARGET:aurora"
"FILE_TYPE:VFT_DLL"
"SOURCE_FILE:plugins/connection/aurora.c"
"ORIGINAL_FILE_NAME:aurora.dll"
"FILE_DESCRIPTION:Connection plugin for Amazon AWS Aurora")
ENDIF()
ADD_DEFINITIONS(-DHAVE_AURORA_DYNAMIC=1)
ADD_LIBRARY(aurora SHARED ${aurora_RC} aurora.c ${EXPORT_FILE})
SET(INSTALL_LIBS ${INSTALL_LIBS} aurora)
ENDIF()
IF(INSTALL_LIBS) IF(INSTALL_LIBS)
INSTALL(TARGETS INSTALL(TARGETS
${INSTALL_LIBS} ${INSTALL_LIBS}

820
plugins/connection/aurora.c Normal file
View File

@@ -0,0 +1,820 @@
/************************************************************************************
Copyright (C) 2015 MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
Part of this code includes code from the PHP project which
is freely available from http://www.php.net
*************************************************************************************/
/* MariaDB Connection plugin for Aurora failover */
#include <my_global.h>
#include <my_sys.h>
#include <errmsg.h>
#include <ma_common.h>
#include <mysql.h>
#include <mysql/client_plugin.h>
#include <string.h>
#include <m_string.h>
#ifndef WIN32
#include <sys/time.h>
#endif
/* function prototypes */
int aurora_init(char *errormsg, size_t errormsg_size,
int unused __attribute__((unused)),
va_list unused1 __attribute__((unused)));
MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd,
const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag);
void aurora_close(MYSQL *mysql);
int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
size_t length, my_bool skipp_check, void *opt_arg);
int aurora_set_options(MYSQL *msql, enum mysql_option option, void *arg);
my_bool aurora_reconnect(MYSQL *mysql);
#define AURORA_MAX_INSTANCES 16
#define AURORA_UNKNOWN -1
#define AURORA_PRIMARY 0
#define AURORA_REPLICA 1
#define AURORA_UNAVAILABLE 2
#define ENABLE_AURORA(mysql)\
(mysql)->net.conn_hdlr->active= 1;
#define DISABLE_AURORA(mysql)\
(mysql)->net.conn_hdlr->active= 0;
#ifndef HAVE_REPLICATION_DYNAMIC
MARIADB_CONNECTION_PLUGIN connection_aurora_plugin =
#else
MARIADB_CONNECTION_PLUGIN _mysql_client_plugin_declaration_ =
#endif
{
MARIADB_CLIENT_CONNECTION_PLUGIN,
MARIADB_CLIENT_CONNECTION_PLUGIN_INTERFACE_VERSION,
"aurora",
"Georg Richter",
"MariaDB connection plugin for Aurora failover",
{1, 0, 0},
"LGPL",
aurora_init,
NULL,
aurora_connect,
aurora_close,
aurora_set_options,
aurora_command,
aurora_reconnect
};
typedef struct st_aurora_instance {
char *host;
int port;
time_t blacklisted;
int type;
} AURORA_INSTANCE;
typedef struct st_conn_aurora {
MARIADB_PVIO *pvio[2];
MYSQL *mysql[2];
my_bool active[2];
char *url;
unsigned int num_instances;
AURORA_INSTANCE instance[AURORA_MAX_INSTANCES];
char *username, *password, *database;
unsigned int port;
unsigned long client_flag;
unsigned int last_instance_type; /* Primary or Replica */
char primary_id[100];
} AURORA;
#define AURORA_BLACKLIST_TIMEOUT 150
#define AURORA_IS_BLACKLISTED(a, i) \
((time(NULL) - (a)->instance[(i)].blacklisted) < AURORA_BLACKLIST_TIMEOUT)
/* {{{ my_bool aurora_swutch_connection */
my_bool aurora_switch_connection(MYSQL *mysql, AURORA *aurora, int type)
{
switch (type)
{
case AURORA_REPLICA:
if (aurora->mysql[AURORA_REPLICA])
{
mysql->net.pvio= aurora->pvio[AURORA_REPLICA];
aurora->pvio[AURORA_REPLICA]->mysql= mysql;
mysql->thread_id= aurora->mysql[AURORA_REPLICA]->thread_id;
aurora->last_instance_type= AURORA_REPLICA;
}
break;
case AURORA_PRIMARY:
if (aurora->mysql[AURORA_PRIMARY])
{
if (aurora->mysql[AURORA_REPLICA])
aurora->mysql[AURORA_REPLICA]->net.pvio->mysql= aurora->mysql[AURORA_REPLICA];
mysql->net.pvio= aurora->pvio[AURORA_PRIMARY];
mysql->thread_id= aurora->mysql[AURORA_PRIMARY]->thread_id;
aurora->last_instance_type= AURORA_PRIMARY;
}
break;
}
}
/* }}} */
/* {{{ int aurora_init
*
* plugin initialization function
*/
int aurora_init(char *errormsg, size_t errormsg_size,
int unused __attribute__((unused)),
va_list unused1 __attribute__((unused)))
{
/* random generator initialization */
#ifndef WIN32
struct timeval tp;
gettimeofday(&tp,NULL);
srand(tp.tv_usec / 1000 + tp.tv_sec * 1000);
#else
srand(GetTickCount());
#endif
return 0;
}
/* }}} */
/* {{{ void aurora_close_memory */
void aurora_close_memory(AURORA *aurora)
{
free(aurora->url);
free(aurora->username);
free(aurora->password);
free(aurora->database);
free(aurora);
}
/* }}} */
/* {{{ my_bool aurora_parse_url
*
* parse url
* Url has the following format:
* instance1:port, instance2:port, .., instanceN:port
*
*/
my_bool aurora_parse_url(const char *url, AURORA *aurora)
{
char *p, *c;
int i;
if (!url || url[0] == 0)
return 1;
bzero(aurora->instance, (AURORA_MAX_INSTANCES + 1) * sizeof(char *));
bzero(&aurora->port, (AURORA_MAX_INSTANCES + 1) * sizeof(int));
if (aurora->url)
free(aurora->url);
aurora->url= strdup(url);
c= aurora->url;
/* get instances */
while((c))
{
if (p= strchr(c, ','))
{
*p= '\0';
p++;
}
if (*c)
{
aurora->instance[aurora->num_instances].host= c;
aurora->num_instances++;
}
c= p;
}
if (!aurora->num_instances)
return 0;
/* check ports */
for (i=0; i < aurora->num_instances && aurora->instance[i].host; i++)
{
aurora->instance[i].type= AURORA_UNKNOWN;
/* We need to be aware of IPv6 addresses: According to RFC3986 sect. 3.2.2
hostnames have to be enclosed in square brackets if a port is given */
if (aurora->instance[i].host[0]== '[' &&
strchr(aurora->instance[i].host, ':') &&
(p= strchr(aurora->instance[i].host,']')))
{
/* ignore first square bracket */
memmove(aurora->instance[i].host,
aurora->instance[i].host+1,
strlen(aurora->instance[i].host) - 1);
p= strchr(aurora->instance[i].host,']');
*p= 0;
p++;
}
else
p= aurora->instance[i].host;
if (p && (p= strchr(p, ':')))
{
*p= '\0';
p++;
aurora->instance[i].port= atoi(p);
}
}
return 0;
}
/* }}} */
/* {{{ int aurora_get_instance_type
*
* RETURNS:
*
* AURORA_PRIMARY
* AURORA_REPLICA
* -1 on error
*/
int aurora_get_instance_type(MYSQL *mysql)
{
int rc;
char *query= "select variable_value from information_schema.global_variables where variable_name='INNODB_READ_ONLY' AND variable_value='OFF'";
if (!mysql_query(mysql, query))
{
MYSQL_RES *res= mysql_store_result(mysql);
rc= mysql_num_rows(res) ? AURORA_PRIMARY : AURORA_REPLICA;
mysql_free_result(res);
return rc;
}
return -1;
}
/* }}} */
/* {{{ my_bool aurora_get_primary_id
*
* try to find primary instance from slave by retrieving
* primary_id information_schema.replica_host_status information
*
* If the function succeeds, primary_id will be copied into
* aurora->primary_id
*
* Returns:
* 1 on success
* 0 if an error occured or primary_id couldn't be
* found
*/
my_bool aurora_get_primary_id(MYSQL *mysql, AURORA *aurora)
{
my_bool rc= 0;
if (!mysql_query(mysql, "select server_id from information_schema.replica_host_status "
"where session_id = 'MASTER_SESSION_ID'"))
{
MYSQL_RES *res;
MYSQL_ROW row;
if ((res= mysql_store_result(mysql)))
{
if ((row= mysql_fetch_row(res)))
{
if (row[0])
{
strcpy(aurora->primary_id, row[0]);
rc= 1;
}
}
mysql_free_result(res);
}
}
return rc;
}
/* }}} */
/* {{{ unsigned int aurora_get_valid_instances
*
* returns the number of instances which are
* not blacklisted or don't have a type assigned.
*/
static unsigned int aurora_get_valid_instances(AURORA *aurora, AURORA_INSTANCE **instances)
{
int i, valid_instances= 0;
memset(instances, 0, sizeof(AURORA_INSTANCE *) * AURORA_MAX_INSTANCES);
for (i=0; i < aurora->num_instances; i++)
{
if (aurora->instance[i].type != AURORA_UNAVAILABLE)
{
if (aurora->instance[i].type == AURORA_PRIMARY && aurora->active[AURORA_PRIMARY])
continue;
instances[valid_instances]= &aurora->instance[i];
valid_instances++;
}
}
return valid_instances;
}
/* }}} */
/* {{{ void aurora_refresh_blacklist() */
void aurora_refresh_blacklist(AURORA *aurora)
{
int i;
for (i=0; i < aurora->num_instances; i++)
{
if (aurora->instance[i].blacklisted &&
!(AURORA_IS_BLACKLISTED(aurora, i)))
{
aurora->instance[i].blacklisted= 0;
aurora->instance[i].type= AURORA_UNKNOWN;
}
}
}
/* }}} */
/* {{{ MYSQL *aurora_connect_instance() */
MYSQL *aurora_connect_instance(AURORA *aurora, AURORA_INSTANCE *instance, MYSQL *mysql)
{
if (!mysql->methods->db_connect(mysql,
instance->host,
aurora->username,
aurora->password,
aurora->database,
instance->port ? instance->port : aurora->port,
NULL,
aurora->client_flag))
{
/* connection not available */
instance->blacklisted= time(NULL);
instance->type= AURORA_UNAVAILABLE;
return NULL;
}
/* check if we are slave or master */
switch (aurora_get_instance_type(mysql))
{
case AURORA_PRIMARY:
instance->type= AURORA_PRIMARY;
return mysql;
break;
case AURORA_REPLICA:
instance->type= AURORA_REPLICA;
break;
default:
instance->type= AURORA_UNAVAILABLE;
instance->blacklisted= time(NULL);
return NULL;
}
if (!aurora->primary_id[0])
aurora_get_primary_id(mysql, aurora);
return mysql;
}
/* }}} */
/* {{{ void aurora_copy_mysql() */
void aurora_copy_mysql(MYSQL *from, MYSQL *to)
{
LIST *li_stmt= to->stmts;
for (;li_stmt;li_stmt= li_stmt->next)
{
MYSQL_STMT *stmt= (MYSQL_STMT *)li_stmt->data;
if (stmt->state != MYSQL_STMT_INITTED)
{
stmt->state= MYSQL_STMT_INITTED;
SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
}
}
from->free_me= to->free_me;
from->reconnect= to->reconnect;
from->net.conn_hdlr= to->net.conn_hdlr;
from->stmts= to->stmts;
to->stmts= NULL;
memset(&to->options, 0, sizeof(to->options));
to->free_me= 0;
to->net.conn_hdlr= 0;
mysql_close(to);
*to= *from;
to->net.pvio= from->net.pvio;
to->net.pvio->mysql= to;
from->net.pvio= NULL;
}
/* }}} */
/* {{{ my_bool aurora_find_replica() */
my_bool aurora_find_replica(AURORA *aurora)
{
int valid_instances;
my_bool replica_found= 0;
AURORA_INSTANCE *instance[AURORA_MAX_INSTANCES];
MYSQL mysql;
// struct st_dynamic_array *init_command= aurora->mysql[AURORA_PRIMARY]->options.init_command;
if (aurora->num_instances < 2)
return 0;
mysql_init(&mysql);
mysql.options= aurora->mysql[AURORA_PRIMARY]->options;
/* don't execute init_command on slave */
mysql.net.conn_hdlr= aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr;
valid_instances= aurora_get_valid_instances(aurora, instance);
while (valid_instances && !replica_found)
{
int random_pick= rand() % valid_instances;
if ((aurora_connect_instance(aurora, instance[random_pick], &mysql)))
{
switch (instance[random_pick]->type) {
case AURORA_REPLICA:
if (!aurora->mysql[AURORA_REPLICA])
{
aurora->mysql[AURORA_REPLICA]= mysql_init(NULL);
}
aurora_copy_mysql(&mysql, aurora->mysql[AURORA_REPLICA]);
aurora->active[AURORA_REPLICA]= 1;
return 1;
break;
case AURORA_PRIMARY:
aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]);
aurora->pvio[AURORA_PRIMARY]= aurora->mysql[AURORA_PRIMARY]->net.pvio;
aurora->active[AURORA_PRIMARY]= 1;
continue;
break;
default:
mysql_close(&mysql);
return 0;
break;
}
}
valid_instances= aurora_get_valid_instances(aurora, instance);
}
return 0;
}
/* }}} */
/* {{{ AURORA_INSTANCE aurora_get_primary_id_instance() */
AURORA_INSTANCE *aurora_get_primary_id_instance(AURORA *aurora)
{
int i;
if (!aurora->primary_id[0])
return 0;
for (i=0; i < aurora->num_instances; i++)
{
if (!strncmp(aurora->instance[i].host, aurora->primary_id, strlen(aurora->primary_id)))
return &aurora->instance[i];
}
return NULL;
}
/* }}} */
/* {{{ my_bool aurora_find_primary() */
my_bool aurora_find_primary(AURORA *aurora)
{
int i;
AURORA_INSTANCE *instance= NULL;
MYSQL mysql;
my_bool check_primary= 1;
if (!aurora->num_instances)
return 0;
mysql_init(&mysql);
mysql.options= aurora->mysql[AURORA_PRIMARY]->options;
mysql.net.conn_hdlr= aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr;
for (i=0; i < aurora->num_instances; i++)
{
if (check_primary && aurora->primary_id[0])
{
if ((instance= aurora_get_primary_id_instance(aurora)) &&
aurora_connect_instance(aurora, instance, &mysql) &&
instance->type == AURORA_PRIMARY)
{
aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]);
aurora->active[AURORA_PRIMARY]= 1;
return 1;
}
/* primary id connect failed, don't try again */
aurora->primary_id[0]= 0;
check_primary= 0;
}
if (aurora->instance[i].type != AURORA_UNAVAILABLE)
{
if (aurora_connect_instance(aurora, &aurora->instance[i], &mysql)
&& aurora->instance[i].type == AURORA_PRIMARY)
{
aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]);
aurora->active[AURORA_PRIMARY]= 1;
return 1;
}
}
}
return 0;
}
/* }}} */
/* {{{ void aurora_close_replica() */
void aurora_close_replica(MYSQL *mysql, AURORA *aurora)
{
if (aurora->mysql[AURORA_REPLICA])
{
aurora->mysql[AURORA_REPLICA]->net.pvio->mysql= aurora->mysql[AURORA_REPLICA];
aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0;
mysql_close(aurora->mysql[AURORA_REPLICA]);
aurora->pvio[AURORA_REPLICA]= 0;
aurora->mysql[AURORA_REPLICA]= NULL;
}
}
/* }}} */
/* {{{ MYSQL *aurora_connect */
MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd,
const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag)
{
AURORA *aurora= NULL;
MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr;
my_bool is_reconnect= 0;
if ((aurora= (AURORA *)hdlr->data))
{
aurora_refresh_blacklist(aurora);
if (aurora->mysql[aurora->last_instance_type]->net.pvio)
{
SET_CLIENT_ERROR(mysql, CR_ALREADY_CONNECTED, SQLSTATE_UNKNOWN, 0);
return NULL;
}
is_reconnect= 1;
}
else
{
if (!(aurora= (AURORA *)my_malloc(sizeof(AURORA), MYF(MY_ZEROFILL))))
{
mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return NULL;
}
mysql->net.conn_hdlr->data= (void *)aurora;
aurora->mysql[AURORA_PRIMARY]= mysql;
if (aurora_parse_url(host, aurora))
{
goto error;
}
if (user)
aurora->username= strdup(user);
if (passwd)
aurora->password= strdup(passwd);
if (db)
aurora->database= strdup(db);
aurora->port= port;
aurora->client_flag= client_flag;
aurora->pvio[AURORA_PRIMARY]= aurora->pvio[AURORA_REPLICA]= NULL;
hdlr->data= aurora;
}
/* In case of reconnect, close broken connection first */
if (is_reconnect)
{
DISABLE_AURORA(mysql);
switch (aurora->last_instance_type) {
case AURORA_REPLICA:
aurora_close_replica(mysql, aurora);
aurora->pvio[AURORA_REPLICA]= NULL;
break;
case AURORA_PRIMARY:
/* pvio will be closed in mysql_reconnect() */
aurora->pvio[AURORA_PRIMARY]= NULL;
aurora->primary_id[0]= 0;
break;
}
aurora->active[aurora->last_instance_type]= 0;
}
if (!aurora->active[AURORA_REPLICA])
{
if (aurora_find_replica(aurora))
{
aurora->pvio[AURORA_REPLICA]= aurora->mysql[AURORA_REPLICA]->net.pvio;
aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= mysql->net.conn_hdlr;
}
else
aurora->pvio[AURORA_REPLICA]= NULL;
}
if (!aurora->active[AURORA_PRIMARY])
{
if (aurora_find_primary(aurora))
{
aurora->active[AURORA_PRIMARY]= 1;
aurora->pvio[AURORA_PRIMARY]= aurora->mysql[AURORA_PRIMARY]->net.pvio;
}
}
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
ENABLE_AURORA(mysql);
return mysql;
error:
aurora_close_memory(aurora);
return NULL;
}
/* }}} */
/* {{{ my_bool aurora_reconnect */
my_bool aurora_reconnect(MYSQL *mysql)
{
AURORA *aurora;
MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr;
my_bool rc= 1;
aurora= (AURORA *)hdlr->data;
DISABLE_AURORA(mysql);
switch (aurora->last_instance_type)
{
case AURORA_REPLICA:
if (!(rc= mysql->methods->reconnect(aurora->mysql[aurora->last_instance_type])))
aurora_switch_connection(mysql, aurora, AURORA_REPLICA);
break;
case AURORA_PRIMARY:
if (!(rc= mysql->methods->reconnect(aurora->mysql[aurora->last_instance_type])))
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
break;
default:
/* todo: error message */
break;
}
ENABLE_AURORA(mysql);
return rc;
}
/* }}} */
/* {{{ void aurora_close */
void aurora_close(MYSQL *mysql)
{
MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr;
AURORA *aurora= (AURORA *)hdlr->data;
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
/* if the connection is not active yet, just return */
if (!aurora->active[1])
return;
if (aurora->mysql[AURORA_REPLICA])
{
/* we got options from primary, so don't free it twice */
memset(&aurora->mysql[AURORA_REPLICA]->options, 0, sizeof(mysql->options));
/* connection handler wull be freed in mysql_close() */
aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0;
mysql_close(aurora->mysql[AURORA_REPLICA]);
}
if (aurora->mysql[AURORA_PRIMARY])
{
/* connection handler wull be freed in mysql_close() */
aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr= 0;
aurora->mysql[AURORA_PRIMARY]->net.pvio= aurora->pvio[AURORA_PRIMARY];
mysql_close(aurora->mysql[AURORA_PRIMARY]);
}
/*
if (aurora->mysql[AURORA_PRIMARY])
{
aurora->mysql[AURORA_PRIMARY]->net.pvio= aurora->pvio[AURORA_PRIMARY];
aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr= 0;
mysql_close(aurora->mysql[AURORA_PRIMARY]);
}
*/
/* free masrwe information */
aurora_close_memory(aurora);
}
/* }}} */
/* {{{ my_bool is_replica_command */
my_bool is_replica_command(const char *buffer, size_t buffer_len)
{
const char *buffer_end= buffer + buffer_len;
for (; buffer < buffer_end; ++buffer)
{
char c;
if (isalpha(c=*buffer))
{
if (tolower(c) == 's')
return 1;
return 0;
}
}
return 0;
}
/* }}} */
/* {{{ my_bool is_replica_stmt */
my_bool is_replica_stmt(MYSQL *mysql, const char *buffer)
{
unsigned long stmt_id= uint4korr(buffer);
LIST *stmt_list= mysql->stmts;
for (; stmt_list; stmt_list= stmt_list->next)
{
MYSQL_STMT *stmt= (MYSQL_STMT *)stmt_list->data;
if (stmt->stmt_id == stmt_id)
return 1;
}
return 0;
}
/* }}} */
/* {{{ int aurora_command */
int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
size_t length, my_bool skipp_check, void *opt_arg)
{
AURORA *aurora= (AURORA *)mysql->net.conn_hdlr->data;
/* if we don't have slave or slave became unavailable root traffic to master */
if (!aurora->mysql[AURORA_REPLICA] || !OPT_HAS_EXT_VAL(mysql, read_only))
{
if (command != COM_INIT_DB)
{
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
return 0;
}
}
switch(command) {
case COM_INIT_DB:
/* we need to change default database on primary and replica */
if (aurora->mysql[AURORA_REPLICA] && aurora->last_instance_type != AURORA_REPLICA)
{
aurora_switch_connection(mysql, aurora, AURORA_REPLICA);
DISABLE_AURORA(mysql);
mysql_select_db(aurora->mysql[AURORA_REPLICA], arg);
ENABLE_AURORA(mysql);
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
}
break;
case COM_QUERY:
case COM_STMT_PREPARE:
if (aurora->mysql[AURORA_REPLICA] && aurora->last_instance_type != AURORA_REPLICA)
aurora_switch_connection(mysql, aurora, AURORA_REPLICA);
break;
case COM_STMT_EXECUTE:
case COM_STMT_FETCH:
if (aurora->pvio[AURORA_REPLICA]->mysql->stmts && is_replica_stmt(aurora->pvio[AURORA_REPLICA]->mysql, arg))
{
if (aurora->last_instance_type != AURORA_REPLICA)
aurora_switch_connection(mysql, aurora, AURORA_REPLICA);
}
else
{
if (aurora->last_instance_type != AURORA_PRIMARY)
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
}
default:
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
break;
}
return 0;
}
/* }}} */
/* {{{ int aurora_set_options() */
int aurora_set_options(MYSQL *mysql, enum mysql_option option, void *arg)
{
switch(option) {
default:
return -1;
}
}
/* }}} */

View File

@@ -70,7 +70,8 @@ MARIADB_CONNECTION_PLUGIN _mysql_client_plugin_declaration_ =
repl_connect, repl_connect,
repl_close, repl_close,
repl_set_options, repl_set_options,
repl_command repl_command,
NULL
}; };
typedef struct st_conn_repl { typedef struct st_conn_repl {
@@ -81,10 +82,20 @@ typedef struct st_conn_repl {
char *url; char *url;
char *host[2]; char *host[2];
int port[2]; int port[2];
unsigned int current_type;
} REPL_DATA; } REPL_DATA;
#define SET_SLAVE(mysql, data) mysql->net.pvio= data->pvio[MARIADB_SLAVE] #define SET_SLAVE(mysql, data)\
#define SET_MASTER(mysql, data) mysql->net.pvio= data->pvio[MARIADB_MASTER] {\
mysql->net.pvio= data->pvio[MARIADB_SLAVE]; \
data->current_type= MARIADB_SLAVE;\
}
#define SET_MASTER(mysql, data)\
{\
mysql->net.pvio= data->pvio[MARIADB_MASTER];\
data->current_type= MARIADB_MASTER;\
}
/* parse url /* parse url
@@ -108,10 +119,8 @@ my_bool repl_parse_url(const char *url, REPL_DATA *data)
memset(data->host, 0, 2 * sizeof(char *)); memset(data->host, 0, 2 * sizeof(char *));
memset(data->port, 0, 2 * sizeof(int)); memset(data->port, 0, 2 * sizeof(int));
if (data->url) if (!data->url)
my_free(data->url); data->url= my_strdup(url, MYF(0));
data->url= my_strdup(url, MYF(0));
data->host[MARIADB_MASTER]= p= data->url; data->host[MARIADB_MASTER]= p= data->url;
/* get slaves */ /* get slaves */
@@ -150,10 +159,11 @@ my_bool repl_parse_url(const char *url, REPL_DATA *data)
{ {
/* We need to be aware of IPv6 addresses: According to RFC3986 sect. 3.2.2 /* We need to be aware of IPv6 addresses: According to RFC3986 sect. 3.2.2
hostnames have to be enclosed in square brackets if a port is given */ hostnames have to be enclosed in square brackets if a port is given */
if (data->host[i][0]= '[' && strchr(data->host[i], ':') && (p= strchr(data->host[i],']'))) if (data->host[i][0]== '[' && strchr(data->host[i], ':') && (p= strchr(data->host[i],']')))
{ {
/* ignore first square bracket */ /* ignore first square bracket */
data->host[i]++; memmove(data->host[i], data->host[i]+1, strlen(data->host[i]) - 1);
p= strchr(data->host[i],']');
*p= 0; *p= 0;
p++; p++;
} }
@@ -176,12 +186,18 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char
REPL_DATA *data= NULL; REPL_DATA *data= NULL;
MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr;
if ((data= (REPL_DATA *)hdlr->data))
{
ma_pvio_close(data->pvio[MARIADB_MASTER]);
data->pvio[MARIADB_MASTER]= 0;
repl_close(mysql);
}
if (!(data= calloc(1, sizeof(REPL_DATA)))) if (!(data= calloc(1, sizeof(REPL_DATA))))
{ {
mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return NULL; return NULL;
} }
memset(data->pvio, 0, 2 * sizeof(MARIADB_PVIO *)); memset(data->pvio, 0, 2 * sizeof(MARIADB_PVIO *));
if (repl_parse_url(host, data)) if (repl_parse_url(host, data))
@@ -194,6 +210,7 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char
data->pvio[MARIADB_MASTER]= mysql->net.pvio; data->pvio[MARIADB_MASTER]= mysql->net.pvio;
hdlr->data= data; hdlr->data= data;
SET_MASTER(mysql, data);
/* to allow immediate access without connection delay, we will start /* to allow immediate access without connection delay, we will start
* connecting to slave(s) in background */ * connecting to slave(s) in background */
@@ -245,7 +262,6 @@ void repl_close(MYSQL *mysql)
my_free(data->url); my_free(data->url);
my_free(data); my_free(data);
mysql->net.conn_hdlr->data= NULL; mysql->net.conn_hdlr->data= NULL;
mysql_close(mysql);
} }
static my_bool is_slave_command(const char *buffer, size_t buffer_len) static my_bool is_slave_command(const char *buffer, size_t buffer_len)
@@ -295,20 +311,20 @@ int repl_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
case COM_QUERY: case COM_QUERY:
case COM_STMT_PREPARE: case COM_STMT_PREPARE:
if (is_slave_command(arg, length)) if (is_slave_command(arg, length))
SET_SLAVE(mysql, data); SET_SLAVE(mysql, data)
else else
SET_MASTER(mysql,data); SET_MASTER(mysql,data)
break; break;
case COM_STMT_EXECUTE: case COM_STMT_EXECUTE:
case COM_STMT_FETCH: case COM_STMT_FETCH:
if (data->pvio[MARIADB_SLAVE]->mysql->stmts && is_slave_stmt(data->pvio[MARIADB_SLAVE]->mysql, arg)) if (data->pvio[MARIADB_SLAVE]->mysql->stmts && is_slave_stmt(data->pvio[MARIADB_SLAVE]->mysql, arg))
SET_SLAVE(mysql, data); SET_SLAVE(mysql, data)
else else
SET_MASTER(mysql,data); SET_MASTER(mysql,data)
break; break;
default: default:
SET_MASTER(mysql,data); SET_MASTER(mysql,data)
break; break;
} }
return 0; return 0;

View File

@@ -251,7 +251,7 @@ my_bool pvio_npipe_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
0, /* no sharing */ 0, /* no sharing */
NULL, /* default security attributes */ NULL, /* default security attributes */
OPEN_EXISTING, OPEN_EXISTING,
0, /* default attributes */ FILE_FLAG_OVERLAPPED,
NULL)) != INVALID_HANDLE_VALUE) NULL)) != INVALID_HANDLE_VALUE)
break; break;

View File

@@ -21,7 +21,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/unittest/mytap) ${CMAKE_SOURCE_DIR}/unittest/mytap)
ADD_DEFINITIONS(-DLIBMARIADB) ADD_DEFINITIONS(-DLIBMARIADB)
SET(API_TESTS "async" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" SET(API_TESTS "aurora" "async" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs"
"sp" "result" "connection" "misc" "ps_new" "sqlite3" "thread" "dyncol") "sp" "result" "connection" "misc" "ps_new" "sqlite3" "thread" "dyncol")
# Get finger print from server certificate # Get finger print from server certificate
@@ -61,7 +61,7 @@ ENDIF()
FOREACH(API_TEST ${API_TESTS}) FOREACH(API_TEST ${API_TESTS})
ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c) ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c)
TARGET_LINK_LIBRARIES(${API_TEST} mytap mariadbclient ) TARGET_LINK_LIBRARIES(${API_TEST} mytap libmariadb)
ADD_TEST(${API_TEST} ${EXECUTABLE_OUTPUT_PATH}/${API_TEST}) ADD_TEST(${API_TEST} ${EXECUTABLE_OUTPUT_PATH}/${API_TEST})
SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 120) SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 120)
ENDFOREACH(API_TEST) ENDFOREACH(API_TEST)

View File

@@ -0,0 +1,67 @@
/*
*/
#include "my_test.h"
static int aurora1(MYSQL *mysql)
{
int rc;
my_bool read_only= 1;
char *primary, *replica;
MYSQL_RES *res;
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
check_mysql_rc(rc, mysql);
rc= mysql_query(mysql, "CREATE TABLE t1 (a int, b varchar(20))");
check_mysql_rc(rc, mysql);
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1, 'foo'), (2, 'bar')");
check_mysql_rc(rc, mysql);
primary= mysql->host;
diag("primary: %s", primary);
mysql_options(mysql, MARIADB_OPT_CONNECTION_READ_ONLY, &read_only);
/* ensure, that this is a replica, so INSERT should fail */
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (3, 'error')");
if (rc)
diag("Expected error: %s", mysql_error(mysql));
rc= mysql_query(mysql, "SELECT a, b FROM t1");
check_mysql_rc(rc, mysql);
res= mysql_store_result(mysql);
diag("Num_rows: %d", mysql_num_rows(res));
mysql_free_result(res);
replica= mysql->host;
diag("replica: %s", replica);
diag("db: %s", mysql->db);
return OK;
}
struct my_tests_st my_tests[] = {
{"aurora1", aurora1, TEST_CONNECTION_NEW, 0, NULL, NULL},
{NULL, NULL, 0, 0, NULL, NULL}
};
int main(int argc, char **argv)
{
mysql_library_init(0,0,NULL);
if (argc > 1)
get_options(argc, argv);
get_envvars();
run_tests(my_tests);
mysql_server_end();
return(exit_status());
}

View File

@@ -55,13 +55,17 @@ static int test_conc75(MYSQL *my)
{ {
ulong thread_id= mysql_thread_id(mysql); ulong thread_id= mysql_thread_id(mysql);
/* force reconnect */ /* force reconnect */
mysql->reconnect= 1;
diag("killing connection");
mysql_kill(my, thread_id); mysql_kill(my, thread_id);
sleep(1); sleep(2);
mysql_ping(mysql);
rc= mysql_query(mysql, "load data local infile './nonexistingfile.csv' into table a (`a`)"); rc= mysql_query(mysql, "load data local infile './nonexistingfile.csv' into table a (`a`)");
FAIL_IF(!test(mysql->options.client_flag | CLIENT_LOCAL_FILES), "client_flags not correct"); FAIL_IF(!test(mysql->options.client_flag | CLIENT_LOCAL_FILES), "client_flags not correct");
diag("thread1: %d %d", thread_id, mysql_thread_id(mysql));
FAIL_IF(thread_id == mysql_thread_id(mysql), "new thread id expected"); FAIL_IF(thread_id == mysql_thread_id(mysql), "new thread id expected");
diag("cs: %s", mysql->charset->csname); //diag("cs: %s", mysql->charset->csname);
FAIL_IF(strcmp(mysql->charset->csname, "utf8"), "wrong character set"); //FAIL_IF(strcmp(mysql->charset->csname, "utf8"), "wrong character set");
} }
mysql_close(mysql); mysql_close(mysql);
return OK; return OK;
@@ -76,7 +80,12 @@ static int test_conc74(MYSQL *my)
mysql= mysql_init(NULL); mysql= mysql_init(NULL);
mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS); if (!mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS))
{
diag("Error: %s", mysql_error(mysql));
mysql_close(mysql);
return FAIL;
}
rc= mysql_query(mysql, "DROP TABLE IF EXISTS a"); rc= mysql_query(mysql, "DROP TABLE IF EXISTS a");
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
@@ -128,7 +137,11 @@ static int test_conc70(MYSQL *my)
int rc; int rc;
MYSQL_RES *res; MYSQL_RES *res;
MYSQL_ROW row; MYSQL_ROW row;
MYSQL *mysql= mysql_init(NULL); MYSQL *mysql;
SKIP_CONNECTION_HANDLER;
mysql= mysql_init(NULL);
rc= mysql_query(my, "SET @a:=@@max_allowed_packet"); rc= mysql_query(my, "SET @a:=@@max_allowed_packet");
check_mysql_rc(rc, my); check_mysql_rc(rc, my);
@@ -148,6 +161,14 @@ static int test_conc70(MYSQL *my)
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (REPEAT('A', 1024 * 1024 * 20))"); rc= mysql_query(mysql, "INSERT INTO t1 VALUES (REPEAT('A', 1024 * 1024 * 20))");
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
if (mysql_warning_count(mysql))
{
diag("server doesn't accept package size");
return SKIP;
}
sleep(20);
rc= mysql_query(mysql, "SELECT a FROM t1"); rc= mysql_query(mysql, "SELECT a FROM t1");
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
@@ -175,7 +196,11 @@ static int test_conc68(MYSQL *my)
int rc; int rc;
MYSQL_RES *res; MYSQL_RES *res;
MYSQL_ROW row; MYSQL_ROW row;
MYSQL *mysql= mysql_init(NULL); MYSQL *mysql;
SKIP_CONNECTION_HANDLER;
mysql= mysql_init(NULL);
rc= mysql_query(my, "SET @a:=@@max_allowed_packet"); rc= mysql_query(my, "SET @a:=@@max_allowed_packet");
check_mysql_rc(rc, my); check_mysql_rc(rc, my);
@@ -193,6 +218,11 @@ static int test_conc68(MYSQL *my)
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (REPEAT('A', 1024 * 1024 * 20))"); rc= mysql_query(mysql, "INSERT INTO t1 VALUES (REPEAT('A', 1024 * 1024 * 20))");
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
if (mysql_warning_count(mysql))
{
diag("server doesn't accept package size");
return SKIP;
}
rc= mysql_query(mysql, "SELECT a FROM t1"); rc= mysql_query(mysql, "SELECT a FROM t1");
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
@@ -504,6 +534,7 @@ static int test_mysql_insert_id(MYSQL *mysql)
according to the manual, this might be 20 or 300, but it looks like according to the manual, this might be 20 or 300, but it looks like
auto_increment column takes priority over last_insert_id(). auto_increment column takes priority over last_insert_id().
*/ */
diag("res: %d", res);
FAIL_UNLESS(res == 20, ""); FAIL_UNLESS(res == 20, "");
/* If first autogenerated number fails and 2nd works: */ /* If first autogenerated number fails and 2nd works: */
rc= mysql_query(mysql, "drop table t2"); rc= mysql_query(mysql, "drop table t2");
@@ -618,12 +649,9 @@ static int bug_conc1(MYSQL *mysql)
{ {
mysql_real_connect(mysql, hostname, username, password, schema, mysql_real_connect(mysql, hostname, username, password, schema,
port, socketname, 0); port, socketname, 0);
diag("errno: %d", mysql_errno(mysql));
FAIL_IF(mysql_errno(mysql) != CR_ALREADY_CONNECTED, FAIL_IF(mysql_errno(mysql) != CR_ALREADY_CONNECTED,
"Expected errno=CR_ALREADY_CONNECTED"); "Expected errno=CR_ALREADY_CONNECTED");
FAIL_IF(strcmp(mysql_error(mysql), ER(CR_ALREADY_CONNECTED)) != 0,
"Wrong error message");
FAIL_IF(strcmp(ER(CR_ALREADY_CONNECTED), "Can't connect twice. Already connected") != 0,
"wrong error message");
return OK; return OK;
} }
@@ -668,11 +696,14 @@ static int test_reconnect_maxpackage(MYSQL *my)
{ {
int rc; int rc;
ulong max_packet= 0; ulong max_packet= 0;
MYSQL *mysql= mysql_init(NULL); MYSQL *mysql;
MYSQL_RES *res; MYSQL_RES *res;
MYSQL_ROW row; MYSQL_ROW row;
char *query; char *query;
SKIP_CONNECTION_HANDLER;
mysql= mysql_init(NULL);
FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema, FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
port, socketname, port, socketname,
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql)); CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql));
@@ -770,6 +801,8 @@ int main(int argc, char **argv)
get_envvars(); get_envvars();
diag("user: %s", username);
run_tests(my_tests); run_tests(my_tests);
return(exit_status()); return(exit_status());

View File

@@ -679,7 +679,7 @@ static int test_utf16_utf32_noboms(MYSQL *mysql)
for (i= 0; i < sizeof(csname)/sizeof(char*); ++i) for (i= 0; i < sizeof(csname)/sizeof(char*); ++i)
{ {
csinfo[i]= mysql_find_charset_name(csname[i]); csinfo[i]= mariadb_get_charset_by_name(csname[i]);
if (csinfo[i] == NULL) if (csinfo[i] == NULL)
{ {

View File

@@ -32,6 +32,7 @@ static int test_conc66(MYSQL *my)
MYSQL *mysql= mysql_init(NULL); MYSQL *mysql= mysql_init(NULL);
int rc; int rc;
FILE *fp; FILE *fp;
char query[1024];
if (!(fp= fopen("./my.cnf", "w"))) if (!(fp= fopen("./my.cnf", "w")))
return FAIL; return FAIL;
@@ -47,7 +48,8 @@ static int test_conc66(MYSQL *my)
rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./my.cnf"); rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./my.cnf");
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
rc= mysql_query(my, "GRANT ALL ON test.* TO 'conc66'@'localhost' IDENTIFIED BY 'test\";#test'"); sprintf(query, "GRANT ALL ON %s.* TO 'conc66'@'%s' IDENTIFIED BY 'test\";#test'", schema, hostname);
rc= mysql_query(my, query);
check_mysql_rc(rc, my); check_mysql_rc(rc, my);
rc= mysql_query(my, "FLUSH PRIVILEGES"); rc= mysql_query(my, "FLUSH PRIVILEGES");
check_mysql_rc(rc, my); check_mysql_rc(rc, my);
@@ -57,7 +59,8 @@ static int test_conc66(MYSQL *my)
diag("Error: %s", mysql_error(mysql)); diag("Error: %s", mysql_error(mysql));
return FAIL; return FAIL;
} }
rc= mysql_query(my, "DROP USER conc66@localhost"); sprintf(query, "DROP user conc66@%s", hostname);
rc= mysql_query(my, query);
check_mysql_rc(rc, my); check_mysql_rc(rc, my);
mysql_close(mysql); mysql_close(mysql);
@@ -561,6 +564,8 @@ static int test_reconnect(MYSQL *mysql)
mysql_kill(mysql, mysql_thread_id(mysql1)); mysql_kill(mysql, mysql_thread_id(mysql1));
sleep(4); sleep(4);
mysql_ping(mysql1);
rc= mysql_query(mysql1, "SELECT 1 FROM DUAL LIMIT 0"); rc= mysql_query(mysql1, "SELECT 1 FROM DUAL LIMIT 0");
check_mysql_rc(rc, mysql1); check_mysql_rc(rc, mysql1);
diag("Thread_id after kill: %lu", mysql_thread_id(mysql1)); diag("Thread_id after kill: %lu", mysql_thread_id(mysql1));
@@ -649,6 +654,8 @@ static int test_conc118(MYSQL *mysql)
rc= mysql_kill(mysql, mysql_thread_id(mysql)); rc= mysql_kill(mysql, mysql_thread_id(mysql));
sleep(2); sleep(2);
mysql_ping(mysql);
rc= mysql_query(mysql, "SET @a:=1"); rc= mysql_query(mysql, "SET @a:=1");
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
@@ -657,12 +664,9 @@ static int test_conc118(MYSQL *mysql)
rc= mysql_kill(mysql, mysql_thread_id(mysql)); rc= mysql_kill(mysql, mysql_thread_id(mysql));
sleep(2); sleep(2);
mysql->host= "foo";
rc= mysql_query(mysql, "SET @a:=1"); rc= mysql_query(mysql, "SET @a:=1");
FAIL_IF(!rc, "error expected"); FAIL_IF(!rc, "error expected");
mysql->host= hostname;
rc= mysql_query(mysql, "SET @a:=1"); rc= mysql_query(mysql, "SET @a:=1");
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);

View File

@@ -82,6 +82,13 @@ if (!(expr))\
return FAIL;\ return FAIL;\
} }
#define SKIP_CONNECTION_HANDLER \
if (hostname && strstr(hostname, "://"))\
{\
diag("Test skipped (connection handler)");\
return SKIP;\
}
/* connection options */ /* connection options */
#define TEST_CONNECTION_DEFAULT 1 /* default connection */ #define TEST_CONNECTION_DEFAULT 1 /* default connection */
#define TEST_CONNECTION_NONE 2 /* tests creates own connection */ #define TEST_CONNECTION_NONE 2 /* tests creates own connection */
@@ -104,7 +111,7 @@ struct my_tests_st
char *skipmsg; char *skipmsg;
}; };
static char *schema = "test_c"; static char *schema = 0;
static char *hostname = 0; static char *hostname = 0;
static char *password = 0; static char *password = 0;
static unsigned int port = 0; static unsigned int port = 0;
@@ -368,18 +375,19 @@ int check_variable(MYSQL *mysql, char *variable, char *value)
MYSQL *test_connect(struct my_tests_st *test) { MYSQL *test_connect(struct my_tests_st *test) {
MYSQL *mysql; MYSQL *mysql;
char query[255]; char query[255];
int i= 1; int i= 0;
int timeout= 10;
int truncation_report= 1;
if (!(mysql = mysql_init(NULL))) { if (!(mysql = mysql_init(NULL))) {
diag("%s", "mysql_init failed - exiting"); diag("%s", "mysql_init failed - exiting");
return(NULL); return(NULL);
} }
mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, &i); mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, &truncation_report);
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&i); mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
/* option handling */ /* option handling */
if (test && test->options) { if (test && test->options) {
int i=0;
while (test->options[i].option) while (test->options[i].option)
{ {
@@ -403,6 +411,8 @@ MYSQL *test_connect(struct my_tests_st *test) {
/* change database or create if it doesn't exist */ /* change database or create if it doesn't exist */
if (mysql_select_db(mysql, schema)) { if (mysql_select_db(mysql, schema)) {
diag("Error number: %d", mysql_errno(mysql));
if(mysql_errno(mysql) == 1049) { if(mysql_errno(mysql) == 1049) {
sprintf(query, "CREATE DATABASE %s", schema); sprintf(query, "CREATE DATABASE %s", schema);
if (mysql_query(mysql, query)) { if (mysql_query(mysql, query)) {
@@ -425,11 +435,6 @@ static int reset_connection(MYSQL *mysql) {
rc= mysql_change_user(mysql, username, password, schema); rc= mysql_change_user(mysql, username, password, schema);
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
if (mysql_get_server_version(mysql) < 50400)
rc= mysql_query(mysql, "SET table_type='MyISAM'");
else
rc= mysql_query(mysql, "SET storage_engine='MyISAM'");
check_mysql_rc(rc, mysql);
rc= mysql_query(mysql, "SET sql_mode=''"); rc= mysql_query(mysql, "SET sql_mode=''");
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
@@ -452,6 +457,8 @@ void get_envvars() {
password= envvar; password= envvar;
if (!schema && (envvar= getenv("MYSQL_TEST_DB"))) if (!schema && (envvar= getenv("MYSQL_TEST_DB")))
schema= envvar; schema= envvar;
if (!schema)
schema= "testc";
if (!port && (envvar= getenv("MYSQL_TEST_PORT"))) if (!port && (envvar= getenv("MYSQL_TEST_PORT")))
port= atoi(envvar); port= atoi(envvar);
if (!socketname && (envvar= getenv("MYSQL_TEST_SOCKET"))) if (!socketname && (envvar= getenv("MYSQL_TEST_SOCKET")))
@@ -470,7 +477,8 @@ void run_tests(struct my_tests_st *test) {
if ((mysql_default= test_connect(NULL))) if ((mysql_default= test_connect(NULL)))
{ {
diag("Testing against MySQL Server %s", mysql_get_server_info(mysql_default)); diag("Testing against MySQL Server %s", mysql_get_server_info(mysql_default));
diag("Host %s", mysql_get_host_info(mysql_default)); diag("Host: %s", mysql_get_host_info(mysql_default));
diag("Client library: %s", mysql_get_client_info());
} }
else else
{ {

View File

@@ -64,7 +64,10 @@ static int test_conc83(MYSQL *my)
/* 1. Status is inited, so prepare should work */ /* 1. Status is inited, so prepare should work */
rc= mysql_kill(mysql, mysql_thread_id(mysql)); rc= mysql_kill(mysql, mysql_thread_id(mysql));
sleep(2); sleep(5);
rc= mysql_ping(mysql);
check_mysql_rc(rc, mysql);
rc= mysql_stmt_prepare(stmt, query, strlen(query)); rc= mysql_stmt_prepare(stmt, query, strlen(query));
check_stmt_rc(rc, stmt); check_stmt_rc(rc, stmt);

View File

@@ -528,9 +528,8 @@ static int test_bug12744(MYSQL *mysql)
rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, "1"); rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, "1");
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
rc= mysql_kill(mysql, mysql_thread_id(mysql)); rc= mysql_kill(mysql, mysql_thread_id(mysql));
check_mysql_rc(rc, mysql);
sleep(2); sleep(4);
rc= mysql_ping(mysql); rc= mysql_ping(mysql);
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);