From a0f603e77bc5db81ea2cbe50bbf6b71e16ab3461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Sat, 25 Jun 2022 16:31:01 +0000 Subject: [PATCH] More code coverage for Clickhouse server Also it includes som minor bug fixes --- include/ClickHouse_Authentication.hpp | 6 +- lib/ClickHouse_Authentication.cpp | 7 ++ lib/ClickHouse_Server.cpp | 44 +++++------- lib/MySQL_Protocol.cpp | 4 +- test/tap/tests/test_clickhouse_server-t.cpp | 79 ++++++++++++++++++++- 5 files changed, 105 insertions(+), 35 deletions(-) diff --git a/include/ClickHouse_Authentication.hpp b/include/ClickHouse_Authentication.hpp index 62b9a31c33..1faf18078e 100644 --- a/include/ClickHouse_Authentication.hpp +++ b/include/ClickHouse_Authentication.hpp @@ -67,7 +67,7 @@ class ClickHouse_Authentication { bool set_lock = true); bool reset(); void print_version(); - bool exists(char *username); +// bool exists(char *username); char *lookup(char *username, enum cred_username_type usertype, bool *use_ssl, int *default_hostgroup, char **default_schema, bool *schema_locked, bool *transaction_persistent, @@ -77,8 +77,8 @@ class ClickHouse_Authentication { void decrease_frontend_user_connections(char *username); void set_all_inactive(enum cred_username_type usertype); void remove_inactives(enum cred_username_type usertype); - bool set_SHA1(char *username, enum cred_username_type usertype, - void *sha_pass); +// bool set_SHA1(char *username, enum cred_username_type usertype, +// void *sha_pass); }; #endif // CLASS_PROXYSQL_CLICKHOUSE_AUTHENTICATION_H diff --git a/lib/ClickHouse_Authentication.cpp b/lib/ClickHouse_Authentication.cpp index a7ecfeb5b9..7bf86dcbb7 100644 --- a/lib/ClickHouse_Authentication.cpp +++ b/lib/ClickHouse_Authentication.cpp @@ -318,6 +318,7 @@ bool ClickHouse_Authentication::del(char * username, enum cred_username_type use return ret; }; +/* unused? bool ClickHouse_Authentication::set_SHA1(char * username, enum cred_username_type usertype, void *sha_pass) { bool ret=false; uint64_t hash1, hash2; @@ -352,7 +353,12 @@ bool ClickHouse_Authentication::set_SHA1(char * username, enum cred_username_typ #endif return ret; }; +*/ +/* +// REMOVING THIS FUNCTION BECAUSE IT IS USED ONLY FOR LDAP +// AND CLICKHOUSE MODULE DOESN'T SUPPORT LDAP. +// See also MySQL_Protocol::process_pkt_handshake_response() bool ClickHouse_Authentication::exists(char * username) { bool ret = false; uint64_t hash1, hash2; @@ -371,6 +377,7 @@ bool ClickHouse_Authentication::exists(char * username) { pthread_rwlock_unlock(&cg.lock); return ret; } +*/ char * ClickHouse_Authentication::lookup(char * username, enum cred_username_type usertype, bool *use_ssl, int *default_hostgroup, char **default_schema, bool *schema_locked, bool *transaction_persistent, bool *fast_forward, int *max_connections, void **sha1_pass) { char *ret=NULL; diff --git a/lib/ClickHouse_Server.cpp b/lib/ClickHouse_Server.cpp index f4c19cfbb8..979868b5d5 100644 --- a/lib/ClickHouse_Server.cpp +++ b/lib/ClickHouse_Server.cpp @@ -266,7 +266,7 @@ inline void ClickHouse_to_MySQL(const Block& block) { free(p); } - +/* struct cpu_timer { cpu_timer() { @@ -282,7 +282,7 @@ struct cpu_timer }; unsigned long long begin; }; - +*/ static char *s_strdup(char *s) { char *ret=NULL; if (s) { @@ -471,6 +471,7 @@ void ClickHouse_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t if ( !strncasecmp("SET AUTOCOMMIT", query_no_space, 14) || !strncasecmp("SET NAMES ", query_no_space, 10) || + !strncasecmp("SET FOREIGN_KEY_CHECKS",query_no_space,22) || !strncasecmp("SET CHARACTER", query_no_space, 13) || !strncasecmp("SET COLLATION", query_no_space, 13) || !strncasecmp("SET SQL_AUTO_", query_no_space, 13) || @@ -636,16 +637,7 @@ void ClickHouse_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t goto __run_query_sqlite; } if ( - (pkt->size==(strlen("SELECT @@storage_engine;")+5) && strncasecmp((char *)"SELECT @@storage_engine;",(char *)pkt->ptr+5,pkt->size-5)==0) - ) { - l_free(query_length,query); - query=l_strdup("SELECT 'MergeTree' AS '@@storage_engine'"); - query_length=strlen(query)+1; - run_query_sqlite = true; - goto __run_query_sqlite; - } - if ( - (pkt->size==(strlen("SELECT @@storage_engine;")+5) && strncasecmp((char *)"SELECT @@storage_engine;",(char *)pkt->ptr+5,pkt->size-5)==0) + (pkt->size==(strlen("SELECT @@storage_engine")+5) && strncasecmp((char *)"SELECT @@storage_engine",(char *)pkt->ptr+5,pkt->size-5)==0) ) { l_free(query_length,query); query=l_strdup("SELECT 'MergeTree' AS '@@storage_engine'"); @@ -808,6 +800,7 @@ void ClickHouse_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t run_query=false; goto __run_query; } +/* if ( (pkt->size==(strlen("SELECT current_user()")+5) && strncasecmp((char *)"SELECT current_user()",(char *)pkt->ptr+5,pkt->size-5)==0) ) { @@ -837,6 +830,7 @@ void ClickHouse_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t run_query=false; goto __run_query; } +*/ } if (query_no_space_length==SELECT_VERSION_COMMENT_LEN) { @@ -851,7 +845,7 @@ void ClickHouse_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t if (query_no_space_length==SELECT_DB_USER_LEN) { if (!strncasecmp(SELECT_DB_USER, query_no_space, query_no_space_length)) { l_free(query_length,query); - char *query1=(char *)"SELECT \"admin\" AS 'DATABASE()', \"%s\" AS 'USER()'"; + char *query1=(char *)"SELECT 'admin' AS \"DATABASE()\", '%s' AS \"USER()\""; char *query2=(char *)malloc(strlen(query1)+strlen(sess->client_myds->myconn->userinfo->username)+10); sprintf(query2,query1,sess->client_myds->myconn->userinfo->username); query=l_strdup(query2); @@ -864,25 +858,16 @@ void ClickHouse_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t if (query_no_space_length==SELECT_CHARSET_VARIOUS_LEN) { if (!strncasecmp(SELECT_CHARSET_VARIOUS, query_no_space, query_no_space_length)) { l_free(query_length,query); - char *query1=(char *)"select 'utf8' as '@@character_set_client', 'utf8' as '@@character_set_connection', 'utf8' as '@@character_set_server', 'utf8' as '@@character_set_database' limit 1"; + char *query1=(char *)"select 'utf8' as \"@@character_set_client\", 'utf8' as \"@@character_set_connection\", 'utf8' as \"@@character_set_server\", 'utf8' as \"@@character_set_database\" limit 1"; query=l_strdup(query1); query_length=strlen(query1)+1; goto __run_query; } } - if (!strncasecmp("SELECT @@version", query_no_space, strlen("SELECT @@version"))) { - l_free(query_length,query); - char *q=(char *)"SELECT '%s' AS '@@version'"; - query_length=strlen(q)+20; - query=(char *)l_alloc(query_length); - sprintf(query,q,PROXYSQL_VERSION); - goto __run_query; - } - if (!strncasecmp("SELECT version()", query_no_space, strlen("SELECT version()"))) { l_free(query_length,query); - char *q=(char *)"SELECT '%s' AS 'version()'"; + char *q=(char *)"SELECT '%s' AS \"version()\""; query_length=strlen(q)+20; query=(char *)l_alloc(query_length); sprintf(query,q,PROXYSQL_VERSION); @@ -948,11 +933,12 @@ void ClickHouse_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t // see issue #1022 if (query_no_space_length==strlen("SELECT DATABASE() AS name") && !strncasecmp("SELECT DATABASE() AS name",query_no_space, query_no_space_length)) { l_free(query_length,query); - query=l_strdup("SELECT \"main\" AS 'DATABASE()'"); + query=l_strdup("SELECT 'main' AS \"DATABASE()\""); query_length=strlen(query)+1; goto __run_query; } +/* if (sess->session_type == PROXYSQL_SESSION_SQLITE) { // no admin if ( (strncasecmp("PRAGMA",query_no_space,6)==0) @@ -965,8 +951,9 @@ void ClickHouse_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t goto __run_query; } } - +*/ if (sess->session_type == PROXYSQL_SESSION_CLICKHOUSE) { // no admin +/* if ( (strncasecmp("SHOW SESSION VARIABLES",query_no_space,22)==0) || @@ -982,6 +969,7 @@ void ClickHouse_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t run_query_sqlite = true; goto __run_query_sqlite; } +*/ if ( (strncasecmp("SET NAMES",query_no_space,9)==0) || @@ -1446,7 +1434,7 @@ void ClickHouse_Server::print_version() { }; bool ClickHouse_Server::init() { - cpu_timer cpt; +// cpu_timer cpt; child_func[0]=child_mysql; main_shutdown=0; @@ -1472,9 +1460,11 @@ bool ClickHouse_Server::init() { perror("Thread creation"); exit(EXIT_FAILURE); } +/* #ifdef DEBUG std::cerr << "SQLite3 Server initialized in "; #endif +*/ return true; }; diff --git a/lib/MySQL_Protocol.cpp b/lib/MySQL_Protocol.cpp index 26e66cb0d4..c33bafac01 100644 --- a/lib/MySQL_Protocol.cpp +++ b/lib/MySQL_Protocol.cpp @@ -1829,7 +1829,7 @@ bool MySQL_Protocol::process_pkt_handshake_response(unsigned char *pkt, unsigned if (GloMyLdapAuth) { // we check if user exists only if GloMyLdapAuth is enabled #ifdef PROXYSQLCLICKHOUSE if (session_type == PROXYSQL_SESSION_CLICKHOUSE) { - user_exists = GloClickHouseAuth->exists((char *)user); + //user_exists = GloClickHouseAuth->exists((char *)user); // for clickhouse, we currently do not support clear text or LDAP user_exists = true; } else { @@ -1859,7 +1859,7 @@ bool MySQL_Protocol::process_pkt_handshake_response(unsigned char *pkt, unsigned bool user_exists = true; #ifdef PROXYSQLCLICKHOUSE if (session_type == PROXYSQL_SESSION_CLICKHOUSE) { - user_exists = GloClickHouseAuth->exists((char *)user); + //user_exists = GloClickHouseAuth->exists((char *)user); // for clickhouse, we currently do not support clear text or LDAP user_exists = true; } else { diff --git a/test/tap/tests/test_clickhouse_server-t.cpp b/test/tap/tests/test_clickhouse_server-t.cpp index e5c9fc8110..cb01bb59f1 100644 --- a/test/tap/tests/test_clickhouse_server-t.cpp +++ b/test/tap/tests/test_clickhouse_server-t.cpp @@ -216,8 +216,8 @@ int execute_and_check_queries(MYSQL* proxysql_clickhouse, const std::vector queries_set1 { std::make_tuple("SHOW SCHEMAS", 0, 4), std::make_tuple("SHOW DATABASES", 0, 4), std::make_tuple("SELECT DATABASE()", 0, 1), + std::make_tuple("SELECT USER()", 0, 1), + std::make_tuple("SELECT CURRENT_USER()", 0, 1), std::make_tuple("SELECT VERSION()", 0, 1), std::make_tuple("SELECT CONCAT(version(),'')", 0, 1), std::make_tuple("SELECT 1", 0, 1), @@ -263,9 +265,66 @@ std::vector queries_set1 { std::make_tuple("INSERT INTO table1 SELECT * FROM table1", 0, -1), std::make_tuple("SELECT CounterID, EventDate, SUM(col1) s FROM table1 GROUP BY CounterID,EventDate ORDER BY CounterID", 0, 4), std::make_tuple("SELECT * FROM table1 t1 JOIN table1 t2 ON t1.CounterID==t2.CounterID ORDER BY t1.CounterID", 0, 64), - + std::make_tuple("DESC table1", 0, 3), + std::make_tuple("SHOW COLUMNS FROM table1", 0, 3), + std::make_tuple("LOCK TABLE table1", 0, -1), + std::make_tuple("UNLOCK TABLE table1", 0, -1), +}; +std::vector queries_set2 { + std::make_tuple("DROP TABLE IF EXISTS table2", 0, -1), + std::make_tuple("CREATE TABLE table2 (CounterID INT, EventDate DATE, col0 INT, col1 Nullable(INT), col2 Nullable(UInt8), col3 Nullable(UInt16), col4 Nullable(UInt32), col5 Nullable(UInt64), col6 Nullable(Float32), col7 Nullable(Float64), col8 Nullable(Enum8('hello' = 1, 'world' = 2)) , col9 Nullable(Enum16('hello' = 1, 'world' = 2))) ENGINE=MergeTree(EventDate, (CounterID, EventDate), 8192)", 0, -1), + std::make_tuple("INSERT INTO table2 SELECT 1,'2022-06-23', 0, 1, 2, 3, 4, 5, 6, 7, 'hello', 'world'", 0, -1), + std::make_tuple("INSERT INTO table2 SELECT 1,'2022-06-23', 1, 2, 3, 4, 5, 6, 7, 'hello', 'world'", 1148, -1), // incorrect number of values + std::make_tuple("INSERT INTO table2 SELECT 1,'2022-06-23', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL", 1148, -1), // col0 can't be null + std::make_tuple("INSERT INTO table2 SELECT 1,'2022-06-23', 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL", 0, -1), + std::make_tuple("SELECT * FROM table2 ORDER BY CounterID", 0, 2), + std::make_tuple("DESC table2", 0, 12), + std::make_tuple("SHOW COLUMNS FROM table2", 0, 12), }; +std::vector queries_set3 { + std::make_tuple("SHOW FULL TABLES FROM `default`", 0, 2), // table1 and table2 + std::make_tuple("SHOW CHARSET", 0, 42), + std::make_tuple("SET AUTOCOMMIT=0", 0, -1), + std::make_tuple("SET foreign_key_checks=0", 0, -1), + std::make_tuple("/*!40101 SET whatever", 0, -1), + std::make_tuple("SET NAMES utf8", 0, -1), + std::make_tuple("SET WAIT_TIMEOUT=10", 0, -1), + std::make_tuple("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED", 0, -1), + std::make_tuple("SET SQL_SAFE_UPDATES = OFF", 0, -1), + std::make_tuple("SET SQL_AUTO_IS_NULL = OFF", 0, -1), + std::make_tuple("SHOW GLOBAL VARIABLES", 0, 6), + std::make_tuple("SHOW ALL VARIABLES", 0, 6), + std::make_tuple("SHOW GLOBAL STATUS", 0, 6), + std::make_tuple("SHOW ENGINES", 0, 1), + std::make_tuple("SHOW VARIABLES LIKE 'lower_case_table_names'", 0, 1), + std::make_tuple("SELECT * FROM INFORMATION_SCHEMA.COLLATIONS", 0, 375), + std::make_tuple("SHOW COLLATION", 0, 375), + std::make_tuple("SHOW CHARSET", 0, 42), + std::make_tuple("SELECT * FROM INFORMATION_SCHEMA.CHARACTER_SETS", 0, 42), + std::make_tuple("SELECT @@collation_server", 0, 1), + std::make_tuple("SELECT @@character_set_results", 0, 1), + std::make_tuple("SELECT @@have_profiling", 0, 1), + std::make_tuple("SELECT @@lower_case_table_names", 0, 1), + std::make_tuple("SELECT @@version, @@version_comment", 0, 1), + std::make_tuple("SELECT @@storage_engine", 0, 1), + std::make_tuple("SELECT `SCHEMA_NAME` FROM `INFORMATION_SCHEMA`.`SCHEMATA`", 0, 4), + std::make_tuple("select name, type FROM mysql.proc where db='default'", 0, 0), + std::make_tuple("SELECT logfile_group_name FROM information_schema.FILES", 0, 0), + std::make_tuple("SELECT tablespace_name FROM information_schema.FILES", 0, 0), + std::make_tuple("SELECT CONNECTION_ID()", 0, 1), + std::make_tuple("select @@version_comment limit 1", 0, 1), + std::make_tuple("select DATABASE(), USER() limit 1", 0, 1), + std::make_tuple("select @@character_set_client, @@character_set_connection, @@character_set_server, @@character_set_database limit 1", 0, 1), + std::make_tuple("SELECT @@version", 0, 1), + std::make_tuple("SHOW TABLES FROM default", 0, 2), + std::make_tuple("SELECT DATABASE() AS name", 0, 1), + std::make_tuple("SHOW MASTER STATUS", 1045, -1), + std::make_tuple("SHOW SLAVE STATUS", 1045, -1), + std::make_tuple("SHOW MASTER LOGS", 1045, -1), + std::make_tuple("LOCK TABLE table1", 0, -1), + std::make_tuple("UNLOCK TABLE table1", 0, -1), +}; /** * @brief Perform several admin queries to exercise more paths. */ @@ -292,7 +351,10 @@ int main(int argc, char** argv) { crash_loops + 2 /* Fail to connect with wrong username and password */ + 4 // during LOAD USERS TO RUNTIME + + 4 // during LOAD USERS TO RUNTIME , second time + queries_set1.size() + + queries_set2.size() + + queries_set3.size() + admin_queries.size() + ch_intf_queries.size() + 1 /* Connect to new setup interface */ ); @@ -320,6 +382,7 @@ int main(int argc, char** argv) { create_users(proxysql_admin); + create_users(proxysql_admin); // to trigger more code coverage { @@ -401,6 +464,16 @@ int main(int argc, char** argv) { return exit_status(); } + diag("Started performing queries set 2"); + if (execute_and_check_queries(proxysql_clickhouse, queries_set2)) { + return exit_status(); + } + + diag("Started performing queries set 3"); + if (execute_and_check_queries(proxysql_clickhouse, queries_set3)) { + return exit_status(); + } + // Reinitialize MYSQL handle mysql_close(proxysql_clickhouse); proxysql_clickhouse = mysql_init(NULL);