diff --git a/include/mysql.h b/include/mysql.h index 76b168303..44ce6d0f8 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -227,6 +227,8 @@ extern const char *SQLSTATE_UNKNOWN; /* MariaDB specific */ MYSQL_PROGRESS_CALLBACK=5999, MYSQL_OPT_NONBLOCK, + MARIADB_OPT_FOLLOW_INSTANT_FAILOVERS, + /* MariaDB Connector/C specific */ MYSQL_DATABASE_DRIVER=7000, MARIADB_OPT_SSL_FP, /* deprecated, use MARIADB_OPT_TLS_PEER_FP instead */ @@ -337,12 +339,19 @@ struct st_mysql_options { char *bind_address; my_bool secure_auth; my_bool report_data_truncation; + my_bool follow_instant_failovers; + /* function pointers for local infile support */ int (*local_infile_init)(void **, const char *, void *); int (*local_infile_read)(void *, char *, unsigned int); void (*local_infile_end)(void *); int (*local_infile_error)(void *, char *, unsigned int); void *local_infile_userdata; + + /* WHY are some options relegated to this "extension" structure? + * What is the logic for distinguishing the "main" options from + * the extension options? + */ struct st_mysql_options_extension *extension; }; diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 4a5ecabf3..6c9ffaaf7 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -668,6 +668,7 @@ struct st_default_options mariadb_defaults[] = {{MYSQL_SET_CHARSET_NAME}, MARIADB_OPTION_STR, "default-character-set"}, {{MARIADB_OPT_INTERACTIVE}, MARIADB_OPTION_NONE, "interactive-timeout"}, {{MYSQL_OPT_CONNECT_TIMEOUT}, MARIADB_OPTION_INT, "connect-timeout"}, + {{MARIADB_OPT_FOLLOW_INSTANT_FAILOVERS}, MARIADB_OPTION_BOOL, "follow-instant-failovers"}, {{MYSQL_OPT_LOCAL_INFILE}, MARIADB_OPTION_BOOL, "local-infile"}, {{0}, 0 ,"disable-local-infile",}, {{MYSQL_OPT_SSL_CIPHER}, MARIADB_OPTION_STR, "ssl-cipher"}, @@ -1294,6 +1295,7 @@ mysql_init(MYSQL *mysql) goto error; mysql->options.report_data_truncation= 1; mysql->options.connect_timeout=CONNECT_TIMEOUT; + mysql->options.follow_instant_failovers= TRUE; mysql->charset= mysql_find_charset_name(MARIADB_DEFAULT_CHARSET); mysql->methods= &MARIADB_DEFAULT_METHODS; strcpy(mysql->net.sqlstate, "00000"); @@ -1995,23 +1997,31 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, { if (mysql->net.last_errno == ER_INSTANT_FAILOVER) { - char *p= mysql->net.last_error; /* Should look like '|message|host[:port]' */ - if (p && p[0] == '|') - p= strchr(p + 1, '|') ? : NULL; - if (p && *++p) { - host= p; - p= strchr(p, ':') ? : NULL; - if (p) { - *p++ = '\0'; - port= atoi(p); - } - else - { - /* Restore to the default port, rather than reusing our current one */ - port= 0; - } + if (!mysql->options.follow_instant_failovers) + { + /* Client has disabled instant failover. Fall through and treat this + * as a "normal" error. */ + } + else + { + char *p= mysql->net.last_error; /* Should look like '|message|host[:port]' */ + if (p && p[0] == '|') + p= strchr(p + 1, '|') ? : NULL; + if (p && *++p) { + host= p; + p= strchr(p, ':') ? : NULL; + if (p) { + *p++ = '\0'; + port= atoi(p); + } + else + { + /* Restore to the default port, rather than reusing our current one */ + port= 0; + } fprintf(stderr, "Got instant failover to '%s' (port %d)\n", host, port); - goto tcp_redirect; + goto tcp_redirect; + } } } goto error; @@ -3521,6 +3531,9 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) case MYSQL_OPT_RECONNECT: mysql->options.reconnect= *(my_bool *)arg1; break; + case MARIADB_OPT_FOLLOW_INSTANT_FAILOVERS: + mysql->options.follow_instant_failovers= *(my_bool *)arg1; + break; case MYSQL_OPT_PROTOCOL: mysql->options.protocol= *((uint *)arg1); break;