Bug #80938 Can mysql_real_connect support multiple host address for failover?
Submitted: 2 Apr 2016 8:41 Modified: 4 May 2016 7:09
Reporter: Fangxin Flou (OCA) Email Updates:
Status: Open Impact on me:
None 
Category:Connector / C Severity:S4 (Feature request)
Version:All OS:Any
Assigned to: CPU Architecture:Any
Tags: client, MySQL

[2 Apr 2016 8:41] Fangxin Flou
Description:
Now the connect can only specify one host address.

mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0)

Can it support multiple host address for connect failover? As following.

mysql_real_connect(&mysql,"host1,host2,host3","user","passwd","database",0,NULL,0)

It will try to connect to host1 first, if failed try connect host2.

Thanks

How to repeat:
N/A

Suggested fix:
N/A

I think code is not big deal.
[4 May 2016 7:09] Fangxin Flou
patch code

diff -rc --exclude='*.orig' --exclude=sql_yacc.cc --exclude=sql_yacc.h mysql-5.6.28/sql-common/client.c mysql-5.6.28-patched/sql-common/client.c
*** mysql-5.6.28/sql-common/client.c	2015-11-16 17:38:05.000000000 +0800
--- mysql-5.6.28-patched/sql-common/client.c	2016-05-04 22:49:44.000000000 +0800
***************
*** 3178,3185 ****
  }

! MYSQL * STDCALL
! CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
  		       const char *passwd, const char *db,
  		       uint port, const char *unix_socket,ulong client_flag)
  {
--- 3178,3185 ----
  }

! MYSQL *
! CLI_MYSQL_REAL_CONNECT2(MYSQL *mysql,const char *host, const char *user,
  		       const char *passwd, const char *db,
  		       uint port, const char *unix_socket,ulong client_flag)
  {
***************
*** 3828,3833 ****
--- 3828,3880 ----
    DBUG_RETURN(0);
  }

+ MYSQL * STDCALL
+ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
+                        const char *passwd, const char *db,
+                        uint port, const char *unix_socket,ulong client_flag)
+ {
+ 	int rowcount = 0;
+ 	int arr_pos1[32], arr_pos2[32];
+ 	int pos1=0, pos2=0;
+ 	while(host != NULL && host[pos2])
+ 	{
+ 		while(host[pos2] && host[pos2] != ',') pos2 ++;
+ 		if (pos2 > pos1)
+ 		{
+ 			arr_pos1[rowcount] = pos1;
+ 			arr_pos2[rowcount] = pos2 - pos1;
+ 			rowcount ++;
+ 		}
+ 		if (host[pos2])
+ 		{
+ 			pos2 ++;
+ 			pos1 = pos2;
+ 		}
+ 	}
+
+         if (rowcount < 2)
+         {
+                 return CLI_MYSQL_REAL_CONNECT2(mysql, host, user, passwd, db, port, unix_socket, client_flag);
+         }
+         else
+         {
+ 		MYSQL *con_mysql = NULL;
+ 		char hostbuf[256];
+
+ 		my_rand_buffer(&pos1, sizeof(pos1));
+ 		pos1 = (pos1 >> 4);
+ 		pos1 = pos1 % rowcount;
+
+                 for(pos2 = pos1; pos2 < pos1 + rowcount; pos2++)
+                 {
+                         memcpy(hostbuf, host + arr_pos1[pos2 % rowcount], MY_MIN(arr_pos2[pos2 % rowcount],255));
+ 			hostbuf[MY_MIN(arr_pos2[pos2 % rowcount],255)] = 0;
+                         con_mysql = CLI_MYSQL_REAL_CONNECT2(mysql, hostbuf, user, passwd, db, port, unix_socket, client_flag);
+                         if(con_mysql != NULL) return con_mysql;
+                 }
+                 return con_mysql;
+         }
+ }

  my_bool mysql_reconnect(MYSQL *mysql)
  {