Skip to content

Commit 6431061

Browse files
authored
Merge pull request #3249 from sysown/v2.0.16-collation
Do not search charset in mysql_real_connect if already set
2 parents 15088fe + 92e82cb commit 6431061

File tree

11 files changed

+309
-33
lines changed

11 files changed

+309
-33
lines changed

deps/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ mariadb-client-library/mariadb_client/libmariadb/libmariadbclient.a: libssl/open
172172
# cd mariadb-client-library/mariadb_client && cmake . -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl # this is needed on MacOSX
173173
cd mariadb-client-library/mariadb_client && patch libmariadb/mariadb_stmt.c < ../mariadb_stmt.c.patch
174174
cd mariadb-client-library/mariadb_client && patch libmariadb/mariadb_lib.c < ../mariadb_lib.c.patch
175+
cd mariadb-client-library/mariadb_client && patch libmariadb/mariadb_lib.c < ../mariadb_lib.c.collation.patch # make sure this path is applied after mariadb_lib.c.patch
175176
# cd mariadb-client-library/mariadb_client && patch libmariadb/net.c < ../net.c.patch
176177
cd mariadb-client-library/mariadb_client && patch libmariadb/mariadb_async.c < ../mariadb_async.c.patch
177178
cd mariadb-client-library/mariadb_client && patch libmariadb/ma_password.c < ../ma_password.c.patch
@@ -180,6 +181,7 @@ mariadb-client-library/mariadb_client/libmariadb/libmariadbclient.a: libssl/open
180181
cd mariadb-client-library/mariadb_client && patch include/mariadb_com.h < ../mariadb_com.h.patch
181182
cd mariadb-client-library/mariadb_client && patch libmariadb/ma_alloc.c < ../ma_alloc.c.patch
182183
cd mariadb-client-library/mariadb_client && patch libmariadb/ma_charset.c < ../ma_charset.c.patch
184+
cd mariadb-client-library/mariadb_client && patch libmariadb/ma_charset.c < ../ma_charset.c.german1.patch
183185
# cd mariadb-client-library/mariadb_client && patch libmariadb/ma_pvio.c < ../ma_pvio.c.patch
184186
cd mariadb-client-library/mariadb_client && patch unittest/libmariadb/basic-t.c < ../unittest_basic-t.c.patch
185187
cd mariadb-client-library/mariadb_client && patch unittest/libmariadb/charset.c < ../unittest_charset.c.patch
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
@@ -583,7 +583,7 @@ const MARIADB_CHARSET_INFO mariadb_compi
2+
{ 95, 1, "cp932", "cp932_japanese_ci", "", 932, "CP932", 1, 2, mysql_mbcharlen_cp932, check_mb_cp932},
3+
{ 97, 1, "eucjpms", "eucjpms_japanese_ci", "", 932, "EUC-JP-MS", 1, 3, mysql_mbcharlen_eucjpms, check_mb_eucjpms},
4+
{ 2, 1, "latin2", "latin2_czech_cs", "", 852, "LATIN2", 1, 1, NULL, NULL},
5+
- { 5, 1, "latin1", "latin1_german_ci", "", 1252, "LATIN1", 1, 1, NULL, NULL},
6+
+ { 5, 1, "latin1", "latin1_german1_ci", "", 1252, "LATIN1", 1, 1, NULL, NULL},
7+
{ 14, 1, "cp1251", "cp1251_bulgarian_ci", "", 1251, "CP1251", 1, 1, NULL, NULL},
8+
{ 15, 1, "latin1", "latin1_danish_ci", "", 1252, "LATIN1", 1, 1, NULL, NULL},
9+
{ 17, 1, "filename", "filename", "", 0, "", 1, 5, NULL, NULL},
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
@@ -1017,7 +1017,10 @@ mysql_init(MYSQL *mysql)
2+
goto error;
3+
mysql->options.report_data_truncation= 1;
4+
mysql->options.connect_timeout=CONNECT_TIMEOUT;
5+
- mysql->charset= mysql_find_charset_name(MARIADB_DEFAULT_CHARSET);
6+
+ // in proxysql we set mysql->charset to NULL during mysql_init()
7+
+ // proxysql will explicitly set it a value if needed
8+
+ mysql->charset = NULL;
9+
+ //mysql->charset= mysql_find_charset_name(MARIADB_DEFAULT_CHARSET);
10+
mysql->methods= &MARIADB_DEFAULT_METHODS;
11+
strcpy(mysql->net.sqlstate, "00000");
12+
mysql->net.last_error[0]= mysql->net.last_errno= 0;
13+
@@ -1497,11 +1500,15 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql
14+
}
15+
}
16+
17+
- /* Set character set */
18+
- if (mysql->options.charset_name)
19+
- mysql->charset= mysql_find_charset_name(mysql->options.charset_name);
20+
- else
21+
- mysql->charset=mysql_find_charset_name(MARIADB_DEFAULT_CHARSET);
22+
+ if (!mysql->charset) { // in proxysql we do not set charset during mysql_init
23+
+ /* Set character set */
24+
+ if (mysql->options.charset_name)
25+
+ mysql->charset= mysql_find_charset_name(mysql->options.charset_name);
26+
+ else
27+
+ mysql->charset=mysql_find_charset_name(MARIADB_DEFAULT_CHARSET);
28+
+ } else {
29+
+ // proxysql has explicitly set charset
30+
+ }
31+
32+
if (!mysql->charset)
33+
{
34+
@@ -1759,10 +1766,16 @@ my_bool STDCALL mysql_change_user(MYSQL
35+
*s_db= mysql->db;
36+
int rc;
37+
38+
- if (mysql->options.charset_name)
39+
- mysql->charset= mysql_find_charset_name(mysql->options.charset_name);
40+
- else
41+
- mysql->charset=mysql_find_charset_name(MARIADB_DEFAULT_CHARSET);
42+
+ // in proxysql we set charset directly,
43+
+ // therefore this code should never be called in proxysql.
44+
+ // we keep the code because compatibility (for example, an app using mysql_change_user)
45+
+ // we also change mysql_optionsv() for MYSQL_SET_CHARSET_NAME
46+
+ if (!mysql->charset) {
47+
+ if (mysql->options.charset_name)
48+
+ mysql->charset= mysql_find_charset_name(mysql->options.charset_name);
49+
+ else
50+
+ mysql->charset=mysql_find_charset_name(MARIADB_DEFAULT_CHARSET);
51+
+ }
52+
53+
mysql->user= strdup(user ? user : "");
54+
mysql->passwd= strdup(passwd ? passwd : "");
55+
@@ -2767,6 +2780,12 @@ mysql_optionsv(MYSQL *mysql,enum mysql_o
56+
OPT_SET_VALUE_STR(&mysql->options, charset_dir, arg1);
57+
break;
58+
case MYSQL_SET_CHARSET_NAME:
59+
+ {
60+
+ // this is for applications other than proxysql.
61+
+ // This because proxysql doesn't use mysql_options() with MYSQL_SET_CHARSET_NAME ,
62+
+ // but instead set mysql->charset directly
63+
+ mysql->charset = NULL;
64+
+ }
65+
OPT_SET_VALUE_STR(&mysql->options, charset_name, arg1);
66+
break;
67+
case MYSQL_OPT_RECONNECT:

lib/MySQL_HostGroups_Manager.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,11 @@ static void * HGCU_thread_run() {
674674
}
675675
}
676676
//async_exit_status = mysql_change_user_start(&ret_bool,mysql,_ui->username, auth_password, _ui->schemaname);
677+
// we first reset the charset to a default one.
678+
// this to solve the problem described here:
679+
// https://github.com/sysown/proxysql/pull/3249#issuecomment-761887970
680+
if (myconn->mysql->charset->nr >= 255)
681+
mysql_options(myconn->mysql, MYSQL_SET_CHARSET_NAME, myconn->mysql->charset->csname);
677682
statuses[i]=mysql_change_user_start(&ret[i], myconn->mysql, myconn->userinfo->username, auth_password, myconn->userinfo->schemaname);
678683
if (myconn->mysql->net.pvio==NULL || myconn->mysql->net.fd==0 || myconn->mysql->net.buff==NULL) {
679684
statuses[i]=0; ret[i]=1;
@@ -3156,7 +3161,9 @@ SQLite3_result * MySQL_HostGroups_Manager::SQL3_Free_Connections() {
31563161
j["thread_id"] = _my->thread_id;
31573162
j["server_status"] = _my->server_status;
31583163
j["charset"] = _my->charset->nr;
3159-
j["options"]["charset_name"] = _my->options.charset_name;
3164+
j["charset_name"] = _my->charset->csname;
3165+
3166+
j["options"]["charset_name"] = ( _my->options.charset_name ? _my->options.charset_name : "" );
31603167
j["options"]["use_ssl"] = _my->options.use_ssl;
31613168
j["client_flag"]["client_found_rows"] = (_my->client_flag & CLIENT_FOUND_ROWS ? 1 : 0);
31623169
j["client_flag"]["client_multi_statements"] = (_my->client_flag & CLIENT_MULTI_STATEMENTS ? 1 : 0);

lib/MySQL_Session.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,7 @@ void MySQL_Session::generate_proxysql_internal_session_json(json &j) {
10631063
j["backends"][i]["conn"]["mysql"]["thread_id"] = _my->thread_id;
10641064
j["backends"][i]["conn"]["mysql"]["server_status"] = _my->server_status;
10651065
j["backends"][i]["conn"]["mysql"]["charset"] = _my->charset->nr;
1066+
j["backends"][i]["conn"]["mysql"]["charset_name"] = _my->charset->csname;
10661067
//j["backends"][i]["conn"]["mysql"][""] = _my->;
10671068
//j["backends"][i]["conn"]["mysql"][""] = _my->;
10681069
j["backends"][i]["conn"]["mysql"]["options"]["charset_name"] = ( _my->options.charset_name ? _my->options.charset_name : "" );

lib/MySQL_Variables.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,38 @@ void MySQL_Variables::server_set_hash_and_value(MySQL_Session* session, int idx,
8686
}
8787

8888

89+
/**
90+
* @brief Set the supplied value for the session variable specified by the supplied
91+
* index into the supplied client session.
92+
*
93+
* @details There are two session variables which require special handling:
94+
* - 'SET NAMES'
95+
* - 'SET CHARACTER SET'
96+
*
97+
* For the second case 'SET CHARACTER SET' we forget about the values for:
98+
* - 'SQL_CHARACTER_SET_CONNECTION'
99+
* - 'SQL_COLLATION_CONNECTION'
100+
*
101+
* This is done because 'character_set_database' is not known when the set happens and
102+
* because we work under the assumption that if a client request 'SET CHARACTER SET'
103+
* doesn't require a specific 'collation_connection' and 'character_set_connection".
104+
* Furthermore, 'character_set_database' is deprecated since MySQL 5.7 and will only
105+
* be usable as an immutable session variable in the future. For reference see:
106+
*
107+
* - 'https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_character_set_database
108+
*
109+
* Due to this, *it's expected behavior* to see that a connection that sets 'SET CHARACTER SET'
110+
* has a variant 'collation_connection' and 'character_set_connection' depending on the
111+
* backend connection that is retrieved from the connection pool. If the 'collation_connection'
112+
* and 'character_set_connection' variables are relevant and should never change,
113+
* 'SET NAMES' should be used.
114+
*
115+
* @param session The client session which variable value is going to be modified.
116+
* @param idx The index of the session variable to modify.
117+
* @param value The session variable value to be set.
118+
*
119+
* @return 'true' in case of success, 'false' otherwise.
120+
*/
89121
bool MySQL_Variables::client_set_value(MySQL_Session* session, int idx, const std::string& value) {
90122
if (!session || !session->client_myds || !session->client_myds->myconn) {
91123
proxy_warning("Session validation failed\n");

lib/mysql_connection.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,8 @@ void MySQL_Connection::connect_start() {
696696
mysql_variables.server_set_value(myds->sess, SQL_CHARACTER_SET_CONNECTION, ss.str().c_str());
697697
mysql_variables.server_set_value(myds->sess, SQL_COLLATION_CONNECTION, ss.str().c_str());
698698
}
699-
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, c->csname);
699+
//mysql_options(mysql, MYSQL_SET_CHARSET_NAME, c->csname);
700+
mysql->charset = c;
700701
unsigned long client_flags = 0;
701702
//if (mysql_thread___client_found_rows)
702703
// client_flags += CLIENT_FOUND_ROWS;
@@ -767,6 +768,11 @@ void MySQL_Connection::change_user_start() {
767768
auth_password=userinfo->password;
768769
}
769770
}
771+
// we first reset the charset to a default one.
772+
// this to solve the problem described here:
773+
// https://github.com/sysown/proxysql/pull/3249#issuecomment-761887970
774+
if (mysql->charset->nr >= 255)
775+
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, mysql->charset->csname);
770776
async_exit_status = mysql_change_user_start(&ret_bool,mysql,_ui->username, auth_password, _ui->schemaname);
771777
}
772778

test/tap/tap/command_line.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef COMMAND_LINE_H
22
#define COMMAND_LINE_H
33

4+
#include <string>
5+
46
class CommandLine {
57
public:
68
CommandLine();

test/tap/tests/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,6 @@ aurora: aurora.cpp $(TAP_LIBDIR)/libtap.a
105105

106106
create_connection_annotation: test_connection_annotation-t.cpp
107107
g++ -DTEST_AURORA -DDEBUG test_connection_annotation-t.cpp $(INCLUDEDIRS) $(LDIRS) $(OPT) -std=c++11 $(OBJ) $(MYLIBS) -ltap -ldl $(STATIC_LIBS) -o test_connection_annotation-t -DGITVERSION=\"$(GIT_VERSION)\"
108+
109+
test_set_collation-t: test_set_collation-t.cpp $(TAP_LIBDIR)/libtap.a
110+
g++ test_set_collation-t.cpp $(INCLUDEDIRS) $(LDIRS) $(OPT) -std=c++11 $(MYLIBS) -ltap -Wl,--no-as-needed -ldl -lpthread -o test_set_collation-t -DGITVERSION=\"$(GIT_VERSION)\"

test/tap/tests/test_ps_large_result-t.cpp

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,16 @@ int select_config_file(MYSQL* mysql, std::string& resultset) {
3434
fprintf(stderr, "error\n");
3535
}
3636

37+
return 0;
3738
}
3839

3940
int restore_admin(MYSQL* mysqladmin) {
4041
MYSQL_QUERY(mysqladmin, "load mysql query rules from disk");
4142
MYSQL_QUERY(mysqladmin, "load mysql query rules to runtime");
4243
MYSQL_QUERY(mysqladmin, "load mysql servers from disk");
4344
MYSQL_QUERY(mysqladmin, "load mysql servers to runtime");
45+
46+
return 0;
4447
}
4548

4649
int main(int argc, char** argv) {
@@ -119,25 +122,22 @@ int main(int argc, char** argv) {
119122
if (!stmt1)
120123
{
121124
ok(false, " mysql_stmt_init(), out of memory\n");
122-
restore_admin(mysqladmin);
123-
return exit_status();
125+
return restore_admin(mysqladmin);
124126
}
125127

126128
std::string query = "SELECT id FROM test.sbtest1 LIMIT 100";
127129
if (mysql_stmt_prepare(stmt1,query.c_str(), query.size())) {
128130
fprintf(stderr, "Query error %s\n", mysql_error(mysql));
129131
mysql_close(mysql);
130132
mysql_library_end();
131-
restore_admin(mysqladmin);
132-
return exit_status();
133+
return restore_admin(mysqladmin);
133134
}
134135

135136
if (mysql_stmt_execute(stmt1))
136137
{
137138
fprintf(stderr, " mysql_stmt_execute(), failed\n");
138139
ok(false, " %s\n", mysql_stmt_error(stmt1));
139-
restore_admin(mysqladmin);
140-
return exit_status();
140+
return restore_admin(mysqladmin);
141141
}
142142
ok(true, "100 rows result stored");
143143

@@ -159,16 +159,14 @@ int main(int argc, char** argv) {
159159
{
160160
fprintf(stderr, " mysql_stmt_bind_result() failed\n");
161161
ok(false, " %s\n", mysql_stmt_error(stmt1));
162-
restore_admin(mysqladmin);
163-
return exit_status();
162+
return restore_admin(mysqladmin);
164163
}
165164

166165
if (mysql_stmt_store_result(stmt1))
167166
{
168167
fprintf(stderr, " mysql_stmt_store_result() failed\n");
169168
ok(false, " %s\n", mysql_stmt_error(stmt1));
170-
restore_admin(mysqladmin);
171-
return exit_status();
169+
return restore_admin(mysqladmin);
172170
}
173171

174172
while (!mysql_stmt_fetch(stmt1))
@@ -180,31 +178,27 @@ int main(int argc, char** argv) {
180178
{
181179
fprintf(stderr, " failed while closing the statement\n");
182180
ok(false, " %s\n", mysql_error(mysql));
183-
restore_admin(mysqladmin);
184-
return exit_status();
181+
return restore_admin(mysqladmin);
185182
}
186183

187184
MYSQL_STMT *stmt2 = mysql_stmt_init(mysql);
188185
if (!stmt2)
189186
{
190187
ok(false, " mysql_stmt_init(), out of memory\n");
191-
restore_admin(mysqladmin);
192-
return exit_status();
188+
return restore_admin(mysqladmin);
193189
}
194190
query = "SELECT t1.id id1, t1.k k1, t1.c c1, t1.pad pad1, t2.id id2, t2.k k2, t2.c c2, t2.pad pad2 FROM test.sbtest1 t1 JOIN test.sbtest1 t2 LIMIT 10000000";
195191
if (mysql_stmt_prepare(stmt2,query.c_str(), query.size())) {
196192
fprintf(stderr, "Query error %s\n", mysql_error(mysql));
197193
mysql_close(mysql);
198194
mysql_library_end();
199-
restore_admin(mysqladmin);
200-
return exit_status();
195+
return restore_admin(mysqladmin);
201196
}
202197
if (mysql_stmt_execute(stmt2))
203198
{
204199
fprintf(stderr, " mysql_stmt_execute(), failed\n");
205200
ok(false, " %s\n", mysql_stmt_error(stmt2));
206-
restore_admin(mysqladmin);
207-
return exit_status();
201+
return restore_admin(mysqladmin);
208202
}
209203
ok(true, "4GB resultset stored");
210204

@@ -281,16 +275,14 @@ int main(int argc, char** argv) {
281275
{
282276
fprintf(stderr, " mysql_stmt_bind_result() failed\n");
283277
ok(false, " %s\n", mysql_stmt_error(stmt2));
284-
restore_admin(mysqladmin);
285-
return exit_status();
278+
return restore_admin(mysqladmin);
286279
}
287280

288281
if (mysql_stmt_store_result(stmt2))
289282
{
290283
fprintf(stderr, " mysql_stmt_store_result() failed\n");
291284
ok(false, " %s\n", mysql_stmt_error(stmt2));
292-
restore_admin(mysqladmin);
293-
return exit_status();
285+
return restore_admin(mysqladmin);
294286
}
295287

296288
while (!mysql_stmt_fetch(stmt2))
@@ -305,8 +297,7 @@ int main(int argc, char** argv) {
305297
{
306298
fprintf(stderr, " failed while closing the statement\n");
307299
ok(false, " %s\n", mysql_error(mysql));
308-
restore_admin(mysqladmin);
309-
return exit_status();
300+
return restore_admin(mysqladmin);
310301
}
311302

312303

@@ -315,8 +306,7 @@ int main(int argc, char** argv) {
315306
if (!stmt3)
316307
{
317308
ok(false, " mysql_stmt_init(), out of memory\n");
318-
restore_admin(mysqladmin);
319-
return exit_status();
309+
return restore_admin(mysqladmin);
320310
}
321311

322312
/* Test case #3. */
@@ -326,8 +316,7 @@ int main(int argc, char** argv) {
326316
fprintf(stderr, "Query error %s\n", mysql_error(mysql));
327317
mysql_close(mysql);
328318
mysql_library_end();
329-
restore_admin(mysqladmin);
330-
return exit_status();
319+
return restore_admin(mysqladmin);
331320
}
332321

333322
/* Execute the SELECT query */
@@ -414,14 +403,13 @@ int main(int argc, char** argv) {
414403
{
415404
fprintf(stderr, " failed while closing the statement\n");
416405
ok(false, " %s\n", mysql_error(mysql));
417-
restore_admin(mysqladmin);
418-
return exit_status();
406+
return restore_admin(mysqladmin);
419407
}
420408

421409
if (str_data32)
422410
free(str_data32);
423411

424-
restore_admin(mysqladmin);
412+
return restore_admin(mysqladmin);
425413

426414
mysql_close(mysql);
427415
mysql_library_end();

0 commit comments

Comments
 (0)