From 02f29377fdcecd29c7af13557dd078a25ae20305 Mon Sep 17 00:00:00 2001 From: "jani@ua141d10.elisa.omakaista.fi" <> Date: Mon, 16 Oct 2006 19:57:33 +0300 Subject: [PATCH] Changed several char* to LEX_STRING*. --- BUILD/SETUP.sh | 2 +- BUILD/compile-pentium-gcov | 19 +- mysql-test/r/create.result | 16 ++ mysql-test/r/ctype_create.result | 4 + mysql-test/r/events.result | 6 + mysql-test/r/grant.result | 4 +- mysql-test/t/alter_table.test | 1 - mysql-test/t/create.test | 21 ++ mysql-test/t/ctype_create.test | 5 + mysql-test/t/events.test | 11 + sql/item_timefunc.cc | 5 + sql/mysql_priv.h | 2 +- sql/mysqld.cc | 3 +- sql/sql_class.h | 9 +- sql/sql_db.cc | 46 ++-- sql/sql_lex.cc | 3 +- sql/sql_lex.h | 3 +- sql/sql_parse.cc | 356 +++++++++++++++++++------------ sql/sql_table.cc | 2 +- sql/sql_yacc.yy | 38 ++-- sql/table.cc | 42 ++-- tests/mysql_client_test.c | 34 ++- 22 files changed, 411 insertions(+), 221 deletions(-) diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 02d160158b3..ced9c7ec2df 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -183,7 +183,7 @@ fi # (http://samba.org/ccache) is installed, use it. # We use 'grep' and hope 'grep' will work as expected # (returns 0 if finds lines) -if ccache -V > /dev/null 2>&1 +if ccache -V > /dev/null 2>&1 && test "$CCACHE_GCOV_VERSION_ENABLED" == "1" then if ! (echo "$CC" | grep "ccache" > /dev/null) then diff --git a/BUILD/compile-pentium-gcov b/BUILD/compile-pentium-gcov index ca37f78e283..5633efaddf0 100755 --- a/BUILD/compile-pentium-gcov +++ b/BUILD/compile-pentium-gcov @@ -1,12 +1,21 @@ #! /bin/sh +# Need to disable ccache, or we loose the gcov-needed compiler output files. + +CCACHE_GCOV_VERSION_ENABLED=0 +if ccache -V > /dev/null 2>&1 +then + CCACHE_VER=`ccache -V | head -1 | sed s/"ccache version "//` + if test "$CCACHE_VER" == "2.4-gcov" + then + CCACHE_GCOV_VERSION_ENABLED=1 + fi +fi +export CCACHE_GCOV_VERSION_ENABLED + path=`dirname $0` . "$path/SETUP.sh" -# Need to disable ccache, or we loose the gcov-needed compiler output files. -CCACHE_DISABLE=1 -export CCACHE_DISABLE - # GCC4 needs -fprofile-arcs -ftest-coverage on the linker command line (as well # as on the compiler command line), and this requires setting LDFLAGS for BDB. export LDFLAGS="-fprofile-arcs -ftest-coverage" @@ -14,7 +23,7 @@ export LDFLAGS="-fprofile-arcs -ftest-coverage" # The -fprofile-arcs and -ftest-coverage options cause GCC to instrument the # code with profiling information used by gcov. # the -DDISABLE_TAO_ASM is needed to avoid build failures in Yassl. -extra_flags="$pentium_cflags -fprofile-arcs -ftest-coverage -DDISABLE_TAO_ASM -DHAVE_MUTEX_THREAD_ONLY" +extra_flags="$pentium_cflags -fprofile-arcs -ftest-coverage -DDISABLE_TAO_ASM -DHAVE_MUTEX_THREAD_ONLY $debug_extra_flags" extra_configs="$pentium_configs $debug_configs --disable-shared $static_link" extra_configs="$extra_configs $max_configs" diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 9ecaaa66cc3..2ed6d561b96 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -818,3 +818,19 @@ SELECT * from t2; a b 1 1 drop table t1,t2; +CREATE DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +DROP DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +RENAME DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa TO a; +ERROR 42000: Unknown database 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +RENAME DATABASE mysqltest TO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +create database mysqltest; +RENAME DATABASE mysqltest TO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +drop database mysqltest; +USE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +SHOW CREATE DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' diff --git a/mysql-test/r/ctype_create.result b/mysql-test/r/ctype_create.result index 8a81991ea78..35461fce45a 100644 --- a/mysql-test/r/ctype_create.result +++ b/mysql-test/r/ctype_create.result @@ -72,3 +72,7 @@ mysqltest2 CREATE DATABASE `mysqltest2` /*!40100 DEFAULT CHARACTER SET latin2 */ drop database mysqltest2; ALTER DATABASE DEFAULT CHARACTER SET latin2; ERROR 3D000: No database selected +ALTER DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEFAULT CHARACTER SET latin2; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +ALTER DATABASE `` DEFAULT CHARACTER SET latin2; +ERROR 42000: Incorrect database name '' diff --git a/mysql-test/r/events.result b/mysql-test/r/events.result index e115e077535..4fae7651311 100644 --- a/mysql-test/r/events.result +++ b/mysql-test/r/events.result @@ -386,4 +386,10 @@ create trigger t1_ai after insert on t1 for each row show create event e1; ERROR 0A000: Not allowed to return a result set from a trigger drop table t1; drop event e1; +SHOW EVENTS FROM aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +SHOW EVENTS FROM ``; +ERROR 42000: Incorrect database name '' +SHOW EVENTS FROM `events\\test`; +Db Name Definer Type Execute at Interval value Interval field Starts Ends Status drop database events_test; diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index b60d238c951..3ac48e4a01f 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -911,7 +911,7 @@ ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table ' SHOW CREATE TABLE mysqltest2.t_nn; Table Create Table t_nn CREATE TABLE `t_nn` ( - `c1` int(11) default NULL + `c1` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 SHOW CREATE VIEW mysqltest2.t_nn; ERROR HY000: 'mysqltest2.t_nn' is not VIEW @@ -930,7 +930,7 @@ v_nn CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER SHOW CREATE TABLE mysqltest2.t_nn; Table Create Table t_nn CREATE TABLE `t_nn` ( - `c1` int(11) default NULL + `c1` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 SHOW CREATE VIEW mysqltest2.t_nn; ERROR HY000: 'mysqltest2.t_nn' is not VIEW diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 168d011a2ac..78bbd23adf1 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -535,4 +535,3 @@ INSERT INTO `@0023sql1` VALUES (2); SHOW CREATE TABLE `#sql2`; SHOW CREATE TABLE `@0023sql1`; DROP TABLE `#sql2`, `@0023sql1`; - diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 140cdccc218..442120fae4a 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -706,3 +706,24 @@ TRUNCATE table t2; INSERT INTO t2 select * from t1; SELECT * from t2; drop table t1,t2; + +# +# Test incorrect database names +# + +--error 1102 +CREATE DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +--error 1102 +DROP DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +--error 1049 +RENAME DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa TO a; +--error 1102 +RENAME DATABASE mysqltest TO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +create database mysqltest; +--error 1102 +RENAME DATABASE mysqltest TO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +drop database mysqltest; +--error 1102 +USE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +--error 1102 +SHOW CREATE DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; diff --git a/mysql-test/t/ctype_create.test b/mysql-test/t/ctype_create.test index e88004bbb8c..060c09a0459 100644 --- a/mysql-test/t/ctype_create.test +++ b/mysql-test/t/ctype_create.test @@ -100,3 +100,8 @@ drop database mysqltest2; ALTER DATABASE DEFAULT CHARACTER SET latin2; # End of 4.1 tests + +--error 1102 +ALTER DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEFAULT CHARACTER SET latin2; +--error 1102 +ALTER DATABASE `` DEFAULT CHARACTER SET latin2; diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test index aac13a55dd3..b98f0f54130 100644 --- a/mysql-test/t/events.test +++ b/mysql-test/t/events.test @@ -378,4 +378,15 @@ drop event e1; ##show processlist; ##select count(*) from mysql.event; +# +# Test wrong syntax +# + +--error 1102 +SHOW EVENTS FROM aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +--error 1102 +SHOW EVENTS FROM ``; + +SHOW EVENTS FROM `events\\test`; + drop database events_test; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index f603cafd89d..c4f0fed88f7 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1249,6 +1249,9 @@ bool get_interval_value(Item *args,interval_type int_type, interval->second= array[0]; interval->second_part= array[1]; break; + case INTERVAL_LAST: /* purecov: begin deadcode */ + DBUG_ASSERT(0); + break; /* purecov: end */ } return 0; } @@ -2088,6 +2091,7 @@ void Item_extract::fix_length_and_dec() case INTERVAL_HOUR_MICROSECOND: max_length=13; date_value=0; break; case INTERVAL_MINUTE_MICROSECOND: max_length=11; date_value=0; break; case INTERVAL_SECOND_MICROSECOND: max_length=9; date_value=0; break; + case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */ } } @@ -2157,6 +2161,7 @@ longlong Item_extract::val_int() ltime.second_part)*neg; case INTERVAL_SECOND_MICROSECOND: return ((longlong)ltime.second*1000000L+ ltime.second_part)*neg; + case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */ } return 0; // Impossible } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 7de6f6d04e0..466a37c7d77 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1828,7 +1828,7 @@ int create_frm(THD *thd, const char *name, const char *db, const char *table, HA_CREATE_INFO *create_info, uint keys); void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form); int rename_file_ext(const char * from,const char * to,const char * ext); -bool check_db_name(char *db); +bool check_db_name(LEX_STRING *db); bool check_column_name(const char *name); bool check_table_name(const char *name, uint length); char *get_field(MEM_ROOT *mem, Field *field); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 419ea27b941..1f95939b895 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5310,7 +5310,8 @@ master-ssl", (gptr*) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"merge", OPT_MERGE, "Enable Merge storage engine. Disable with \ --skip-merge.", - (gptr*) &opt_merge, (gptr*) &opt_merge, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0}, + (gptr*) &opt_merge, (gptr*) &opt_merge, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, + 0}, {"myisam-recover", OPT_MYISAM_RECOVER, "Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP, FORCE or QUICK.", (gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0, diff --git a/sql/sql_class.h b/sql/sql_class.h index 6b46c9676f7..e577774a16f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -420,6 +420,12 @@ public: { return strdup_root(mem_root,str); } inline char *strmake(const char *str, uint size) { return strmake_root(mem_root,str,size); } + inline bool LEX_STRING_make(LEX_STRING *lex_str, const char *str, uint size) + { + return ((lex_str->str= + strmake_root(mem_root, str, (lex_str->length= size)))) == 0; + } + inline char *memdup(const char *str, uint size) { return memdup_root(mem_root,str,size); } inline char *memdup_w_gap(const char *str, uint size, uint gap) @@ -1617,8 +1623,7 @@ public: return TRUE; } *p_db= strmake(db, db_length); - if (p_db_length) - *p_db_length= db_length; + *p_db_length= db_length; return FALSE; } }; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 372a350566f..ac3ab0196bb 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1297,8 +1297,8 @@ err: bool mysql_change_db(THD *thd, const char *name, bool no_access_check) { - int path_length, db_length; - char *db_name; + int path_length; + LEX_STRING db_name; bool system_db= 0; #ifndef NO_EMBEDDED_ACCESS_CHECKS ulong db_access; @@ -1318,25 +1318,26 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) /* Called from SP to restore the original database, which was NULL */ DBUG_ASSERT(no_access_check); system_db= 1; - db_name= NULL; - db_length= 0; + db_name.str= NULL; + db_name.length= 0; goto end; } /* Now we need to make a copy because check_db_name requires a non-constant argument. TODO: fix check_db_name. */ - if ((db_name= my_strdup(name, MYF(MY_WME))) == NULL) + if ((db_name.str= my_strdup(name, MYF(MY_WME))) == NULL) DBUG_RETURN(1); /* the error is set */ - db_length= strlen(db_name); - if (check_db_name(db_name)) + db_name.length= strlen(db_name.str); + if (check_db_name(&db_name)) { - my_error(ER_WRONG_DB_NAME, MYF(0), db_name); - my_free(db_name, MYF(0)); + my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str); + my_free(db_name.str, MYF(0)); DBUG_RETURN(1); } - DBUG_PRINT("info",("Use database: %s", db_name)); - if (!my_strcasecmp(system_charset_info, db_name, information_schema_name.str)) + DBUG_PRINT("info",("Use database: %s", db_name.str)); + if (!my_strcasecmp(system_charset_info, db_name.str, + information_schema_name.str)) { system_db= 1; #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -1351,34 +1352,35 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) if (test_all_bits(sctx->master_access, DB_ACLS)) db_access=DB_ACLS; else - db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name, 0) | + db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, + db_name.str, 0) | sctx->master_access); if (!(db_access & DB_ACLS) && (!grant_option || - check_grant_db(thd,db_name))) + check_grant_db(thd, db_name.str))) { my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), sctx->priv_user, sctx->priv_host, - db_name); + db_name.str); general_log_print(thd, COM_INIT_DB, ER(ER_DBACCESS_DENIED_ERROR), - sctx->priv_user, sctx->priv_host, db_name); - my_free(db_name,MYF(0)); + sctx->priv_user, sctx->priv_host, db_name.str); + my_free(db_name.str, MYF(0)); DBUG_RETURN(1); } } #endif - if (check_db_dir_existence(db_name)) + if (check_db_dir_existence(db_name.str)) { - my_error(ER_BAD_DB_ERROR, MYF(0), db_name); - my_free(db_name, MYF(0)); + my_error(ER_BAD_DB_ERROR, MYF(0), db_name.str); + my_free(db_name.str, MYF(0)); DBUG_RETURN(1); } end: x_free(thd->db); - DBUG_ASSERT(db_name == NULL || db_name[0] != '\0'); - thd->reset_db(db_name, db_length); // THD::~THD will free this + DBUG_ASSERT(db_name.str == NULL || db_name.str[0] != '\0'); + thd->reset_db(db_name.str, db_name.length); // THD::~THD will free this #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!no_access_check) sctx->db_access= db_access; @@ -1392,7 +1394,7 @@ end: { HA_CREATE_INFO create; - load_db_opt_by_name(thd, db_name, &create); + load_db_opt_by_name(thd, db_name.str, &create); thd->db_charset= create.default_table_charset ? create.default_table_charset : diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index c5064df931b..99b99c1407c 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -175,7 +175,8 @@ void lex_start(THD *thd, const uchar *buf, uint length) lex->escape_used= lex->et_compile_phase= FALSE; lex->reset_query_tables_list(FALSE); - lex->name= 0; + lex->name.str= 0; + lex->name.length= 0; lex->et= NULL; lex->nest_level=0 ; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 9f6df9861e2..eae8bd1b81d 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -879,7 +879,8 @@ typedef struct st_lex : public Query_tables_list /* The values of tok_start/tok_end as they were one call of MYSQLlex before */ const uchar *tok_start_prev, *tok_end_prev; - char *length,*dec,*change,*name; + char *length,*dec,*change; + LEX_STRING name; Table_ident *like_name; char *help_arg; char *backup_dir; /* For RESTORE/BACKUP */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9217c147143..4be8c656bb5 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -68,6 +68,7 @@ static void decrease_user_connections(USER_CONN *uc); #endif /* NO_EMBEDDED_ACCESS_CHECKS */ static bool check_multi_update_lock(THD *thd); static void remove_escape(char *name); +static void remove_escape(LEX_STRING *str); static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables); const char *any_db="*any*"; // Special symbol for check_access @@ -1056,11 +1057,14 @@ static int check_connection(THD *thd) Old clients send null-terminated string as password; new clients send the size (1 byte) + string (not null-terminated). Hence in case of empty password both send '\0'. + + This strlen() can't be easily deleted without changing protocol. */ uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? *passwd++ : strlen(passwd); db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ? db + passwd_len + 1 : 0; + /* strlen() can't be easily deleted without changing protocol */ uint db_len= db ? strlen(db) : 0; if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len) @@ -1315,28 +1319,31 @@ pthread_handler_t handle_bootstrap(void *arg) thd->init_for_queries(); while (fgets(buff, thd->net.max_packet, file)) { - ulong length= (ulong) strlen(buff); - while (buff[length-1] != '\n' && !feof(file)) - { - /* - We got only a part of the current string. Will try to increase - net buffer then read the rest of the current string. - */ - if (net_realloc(&(thd->net), 2 * thd->net.max_packet)) - { - net_send_error(thd, ER_NET_PACKET_TOO_LARGE, NullS); - thd->fatal_error(); - break; - } - buff= (char*) thd->net.buff; - fgets(buff + length, thd->net.max_packet - length, file); - length+= (ulong) strlen(buff + length); - } - if (thd->is_fatal_error) - break; + /* strlen() can't be deleted because fgets() doesn't return length */ + ulong length= (ulong) strlen(buff); + while (buff[length-1] != '\n' && !feof(file)) + { + /* + We got only a part of the current string. Will try to increase + net buffer then read the rest of the current string. + */ + /* purecov: begin tested */ + if (net_realloc(&(thd->net), 2 * thd->net.max_packet)) + { + net_send_error(thd, ER_NET_PACKET_TOO_LARGE, NullS); + thd->fatal_error(); + break; + } + buff= (char*) thd->net.buff; + fgets(buff + length, thd->net.max_packet - length, file); + length+= (ulong) strlen(buff + length); + /* purecov: end */ + } + if (thd->is_fatal_error) + break; /* purecov: inspected */ while (length && (my_isspace(thd->charset(), buff[length-1]) || - buff[length-1] == ';')) + buff[length-1] == ';')) length--; buff[length]=0; thd->query_length=length; @@ -1421,24 +1428,30 @@ void cleanup_items(Item *item) */ static -int mysql_table_dump(THD* thd, char* db, char* tbl_name) +int mysql_table_dump(THD *thd, LEX_STRING *db, char *tbl_name) { TABLE* table; TABLE_LIST* table_list; int error = 0; DBUG_ENTER("mysql_table_dump"); - db = (db && db[0]) ? db : thd->db; + if (db->length == 0) + { + db->str= thd->db; /* purecov: inspected */ + db->length= thd->db_length; /* purecov: inspected */ + } if (!(table_list = (TABLE_LIST*) thd->calloc(sizeof(TABLE_LIST)))) DBUG_RETURN(1); // out of memory - table_list->db= db; + table_list->db= db->str; table_list->table_name= table_list->alias= tbl_name; table_list->lock_type= TL_READ_NO_INSERT; table_list->prev_global= &table_list; // can be removed after merge with 4.1 - if (!db || check_db_name(db)) + if (check_db_name(db)) { - my_error(ER_WRONG_DB_NAME ,MYF(0), db ? db : "NULL"); + /* purecov: begin inspected */ + my_error(ER_WRONG_DB_NAME ,MYF(0), db->str ? db->str : "NULL"); goto err; + /* purecov: end */ } if (lower_case_table_names) my_casedn_str(files_charset_info, tbl_name); @@ -1668,7 +1681,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, statistic_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB], &LOCK_status); thd->convert_string(&tmp, system_charset_info, - packet, strlen(packet), thd->charset()); + packet, packet_length-1, thd->charset()); if (!mysql_change_db(thd, tmp.str, FALSE)) { general_log_print(thd, command, "%s",thd->db); @@ -1686,7 +1699,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #endif case COM_TABLE_DUMP: { - char *db, *tbl_name; + char *tbl_name; + LEX_STRING db; uint db_len= *(uchar*) packet; if (db_len >= packet_length || db_len > NAME_LEN) { @@ -1702,25 +1716,27 @@ bool dispatch_command(enum enum_server_command command, THD *thd, statistic_increment(thd->status_var.com_other, &LOCK_status); thd->enable_slow_log= opt_log_slow_admin_statements; - db= thd->alloc(db_len + tbl_len + 2); - if (!db) + db.str= thd->alloc(db_len + tbl_len + 2); + db.length= db_len; + if (!db.str) { my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); break; } - tbl_name= strmake(db, packet + 1, db_len)+1; + tbl_name= strmake(db.str, packet + 1, db_len)+1; strmake(tbl_name, packet + db_len + 2, tbl_len); - mysql_table_dump(thd, db, tbl_name); + mysql_table_dump(thd, &db, tbl_name); break; } case COM_CHANGE_USER: { + statistic_increment(thd->status_var.com_other, &LOCK_status); + char *user= (char*) packet, *packet_end= packet+ packet_length; + char *passwd= strend(user)+1; + thd->change_user(); thd->clear_error(); // if errors from rollback - statistic_increment(thd->status_var.com_other, &LOCK_status); - char *user= (char*) packet; - char *passwd= strend(user)+1; /* Old clients send null-terminated string ('\0' for empty string) for password. New clients send the size (1 byte) + string (not null @@ -1728,8 +1744,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, */ char db_buff[NAME_LEN+1]; // buffer to store db in utf8 char *db= passwd; - uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? - *passwd++ : strlen(passwd); + char *save_db; + uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ? + *passwd++ : strlen(passwd)); + uint dummy_errors, save_db_length, db_length, res; + Security_context save_security_ctx= *thd->security_ctx; + USER_CONN *save_user_connect; + db+= passwd_len + 1; #ifndef EMBEDDED_LIBRARY /* Small check for incoming packet */ @@ -1740,17 +1761,22 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } #endif /* Convert database name to utf8 */ - uint dummy_errors; + /* + Handle problem with old bug in client protocol where db had an extra + \0 + */ + db_length= (packet_end - db); + if (db_length > 0 && db[db_length-1] == 0) + db_length--; db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, - system_charset_info, db, strlen(db), + system_charset_info, db, db_length, thd->charset(), &dummy_errors)]= 0; db= db_buff; /* Save user and privileges */ - uint save_db_length= thd->db_length; - char *save_db= thd->db; - Security_context save_security_ctx= *thd->security_ctx; - USER_CONN *save_user_connect= thd->user_connect; + save_db_length= thd->db_length; + save_db= thd->db; + save_user_connect= thd->user_connect; if (!(thd->security_ctx->user= my_strdup(user, MYF(0)))) { @@ -1761,7 +1787,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* Clear variables that are allocated */ thd->user_connect= 0; - int res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE); + res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE); if (res) { @@ -1871,29 +1897,31 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; #else { - char *fields, *pend; + char *fields, *packet_end= packet + packet_length - 1, *arg_end; /* Locked closure of all tables */ TABLE_LIST *locked_tables= NULL; TABLE_LIST table_list; LEX_STRING conv_name; /* Saved variable value */ my_bool old_innodb_table_locks= thd->variables.innodb_table_locks; - + uint dummy; /* used as fields initializator */ lex_start(thd, 0, 0); - statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS], &LOCK_status); bzero((char*) &table_list,sizeof(table_list)); - if (thd->copy_db_to(&table_list.db, 0)) + if (thd->copy_db_to(&table_list.db, &dummy)) break; - pend= strend(packet); + /* + We have name + wildcard in packet, separated by endzero + */ + arg_end= strend(packet); thd->convert_string(&conv_name, system_charset_info, - packet, (uint) (pend-packet), thd->charset()); + packet, (uint) (arg_end - packet), thd->charset()); table_list.alias= table_list.table_name= conv_name.str; - packet= pend+1; + packet= arg_end + 1; if (!my_strcasecmp(system_charset_info, table_list.db, information_schema_name.str)) @@ -1903,7 +1931,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, table_list.schema_table= schema_table; } - thd->query_length= strlen(packet); // for simplicity: don't optimize + thd->query_length= (uint) (packet_end - packet); // Don't count end \0 if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1))) break; general_log_print(thd, command, "%s %s", table_list.table_name, fields); @@ -1940,24 +1968,27 @@ bool dispatch_command(enum enum_server_command command, THD *thd, error=TRUE; // End server break; +#ifdef REMOVED case COM_CREATE_DB: // QQ: To be removed { - char *db=thd->strdup(packet), *alias; + LEX_STRING db, alias; HA_CREATE_INFO create_info; statistic_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB], &LOCK_status); - // null test to handle EOM - if (!db || !(alias= thd->strdup(db)) || check_db_name(db)) + if (thd->LEX_STRING_make(&db, packet, packet_length -1) || + thd->LEX_STRING_make(&alias, db.str, db.length) || + check_db_name(&db)) { - my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL"); + my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL"); break; } - if (check_access(thd,CREATE_ACL,db,0,1,0,is_schema_db(db))) + if (check_access(thd, CREATE_ACL, db.str , 0, 1, 0, + is_schema_db(db.str))) break; general_log_print(thd, command, packet); bzero(&create_info, sizeof(create_info)); - mysql_create_db(thd, (lower_case_table_names == 2 ? alias : db), + mysql_create_db(thd, (lower_case_table_names == 2 ? alias.str : db.str), &create_info, 0); break; } @@ -1965,14 +1996,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd, { statistic_increment(thd->status_var.com_stat[SQLCOM_DROP_DB], &LOCK_status); - char *db=thd->strdup(packet); - /* null test to handle EOM */ - if (!db || check_db_name(db)) + LEX_STRING db; + + if (thd->LEX_STRING_make(&db, packet, packet_length - 1) || + check_db_name(&db)) { - my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL"); + my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL"); break; } - if (check_access(thd,DROP_ACL,db,0,1,0,is_schema_db(db))) + if (check_access(thd, DROP_ACL, db.str, 0, 1, 0, is_schema_db(db.str))) break; if (thd->locked_tables || thd->active_transaction()) { @@ -1980,10 +2012,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); break; } - general_log_print(thd, command, db); - mysql_rm_db(thd, db, 0, 0); + general_log_print(thd, command, db.str); + mysql_rm_db(thd, db.str, 0, 0); break; } +#endif #ifndef EMBEDDED_LIBRARY case COM_BINLOG_DUMP: { @@ -2065,37 +2098,47 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #endif case COM_STATISTICS: { + STATUS_VAR current_global_status_var; + ulong uptime; + uint length; +#ifndef EMBEDDED_LIBRARY + char buff[250]; + uint buff_len= sizeof(buff); +#else + char *buff= thd->net.last_error; + uint buff_len= sizeof(thd->net.last_error); +#endif + general_log_print(thd, command, NullS); statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS], &LOCK_status); -#ifndef EMBEDDED_LIBRARY - char buff[200]; -#else - char *buff= thd->net.last_error; -#endif - - STATUS_VAR current_global_status_var; calc_sum_of_all_status(¤t_global_status_var); - - ulong uptime = (ulong) (thd->start_time - start_time); - sprintf((char*) buff, - "Uptime: %lu Threads: %d Questions: %lu Slow queries: %lu Opens: %lu Flush tables: %lu Open tables: %u Queries per second avg: %.3f", - uptime, - (int) thread_count, (ulong) thd->query_id, - current_global_status_var.long_query_count, - current_global_status_var.opened_tables, refresh_version, - cached_open_tables(), - (uptime ? (ulonglong2double(thd->query_id) / (double) uptime) : - (double) 0)); + uptime= (ulong) (thd->start_time - start_time); + length= my_snprintf((char*) buff, buff_len - 1, + "Uptime: %lu Threads: %d Questions: %lu " + "Slow queries: %lu Opens: %lu Flush tables: %lu " + "Open tables: %u Queries per second avg: %.3f", + uptime, + (int) thread_count, (ulong) thd->query_id, + current_global_status_var.long_query_count, + current_global_status_var.opened_tables, + refresh_version, + cached_open_tables(), + (uptime ? (ulonglong2double(thd->query_id) / + (double) uptime) : (double) 0)); #ifdef SAFEMALLOC if (sf_malloc_cur_memory) // Using SAFEMALLOC - sprintf(strend(buff), " Memory in use: %ldK Max memory used: %ldK", - (sf_malloc_cur_memory+1023L)/1024L, - (sf_malloc_max_memory+1023L)/1024L); + { + char *end= buff + length; + length+= my_snprintf(end, buff_len - length - 1, + end," Memory in use: %ldK Max memory used: %ldK", + (sf_malloc_cur_memory+1023L)/1024L, + (sf_malloc_max_memory+1023L)/1024L); + } #endif #ifndef EMBEDDED_LIBRARY - VOID(my_net_write(net, buff,(uint) strlen(buff))); - VOID(net_flush(net)); + VOID(my_net_write(net, buff, length)); + VOID(net_flush(net)); #endif break; } @@ -2292,27 +2335,29 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, DBUG_RETURN(1); #else { - char *db; + LEX_STRING db; + uint dummy; if (lex->select_lex.db == NULL && - thd->copy_db_to(&lex->select_lex.db, 0)) + thd->copy_db_to(&lex->select_lex.db, &dummy)) { DBUG_RETURN(1); } - db= lex->select_lex.db; - remove_escape(db); // Fix escaped '_' - if (check_db_name(db)) + db.str= lex->select_lex.db; + db.length= strlen(db.str); + remove_escape(&db); // Fix escaped '_' + if (check_db_name(&db)) { - my_error(ER_WRONG_DB_NAME, MYF(0), db); + my_error(ER_WRONG_DB_NAME, MYF(0), db.str); DBUG_RETURN(1); } - if (check_access(thd, SELECT_ACL, db, &thd->col_access, 0, 0, - is_schema_db(db))) + if (check_access(thd, SELECT_ACL, db.str, &thd->col_access, 0, 0, + is_schema_db(db.str))) DBUG_RETURN(1); /* purecov: inspected */ - if (!thd->col_access && check_grant_db(thd,db)) + if (!thd->col_access && check_grant_db(thd, db.str)) { my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), thd->security_ctx->priv_user, thd->security_ctx->priv_host, - db); + db.str); DBUG_RETURN(1); } break; @@ -2854,11 +2899,6 @@ mysql_execute_command(THD *thd) if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0)) goto error; } - if (strlen(first_table->table_name) > NAME_LEN) - { - my_error(ER_WRONG_TABLE_NAME, MYF(0), first_table->table_name); - break; - } pthread_mutex_lock(&LOCK_active_mi); /* fetch_master_table will send the error to the client on failure. @@ -3093,11 +3133,6 @@ end_with_restore_list: if (lex->alter_info.flags & ALTER_DROP_PARTITION) priv_needed|= DROP_ACL; - if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN)) - { - my_error(ER_WRONG_TABLE_NAME, MYF(0), lex->name); - goto error; - } /* Must be set in the parser */ DBUG_ASSERT(select_lex->db); if (check_access(thd, priv_needed, first_table->db, @@ -3113,11 +3148,11 @@ end_with_restore_list: { if (check_grant(thd, priv_needed, all_tables, 0, UINT_MAX, 0)) goto error; - if (lex->name && !test_all_bits(priv,INSERT_ACL | CREATE_ACL)) + if (lex->name.str && !test_all_bits(priv,INSERT_ACL | CREATE_ACL)) { // Rename of table TABLE_LIST tmp_table; bzero((char*) &tmp_table,sizeof(tmp_table)); - tmp_table.table_name=lex->name; + tmp_table.table_name= lex->name.str; tmp_table.db=select_lex->db; tmp_table.grant.privilege=priv; if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0, @@ -3145,7 +3180,7 @@ end_with_restore_list: } thd->enable_slow_log= opt_log_slow_admin_statements; - res= mysql_alter_table(thd, select_lex->db, lex->name, + res= mysql_alter_table(thd, select_lex->db, lex->name.str, &lex->create_info, first_table, lex->create_list, lex->key_list, @@ -3740,9 +3775,10 @@ end_with_restore_list: break; } char *alias; - if (!(alias=thd->strdup(lex->name)) || check_db_name(lex->name)) + if (!(alias=thd->strmake(lex->name.str, lex->name.length)) || + check_db_name(&lex->name)) { - my_error(ER_WRONG_DB_NAME, MYF(0), lex->name); + my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str); break; } /* @@ -3754,17 +3790,18 @@ end_with_restore_list: */ #ifdef HAVE_REPLICATION if (thd->slave_thread && - (!rpl_filter->db_ok(lex->name) || - !rpl_filter->db_ok_with_wild_table(lex->name))) + (!rpl_filter->db_ok(lex->name.str) || + !rpl_filter->db_ok_with_wild_table(lex->name.str))) { my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); break; } #endif - if (check_access(thd,CREATE_ACL,lex->name,0,1,0,is_schema_db(lex->name))) + if (check_access(thd,CREATE_ACL,lex->name.str, 0, 1, 0, + is_schema_db(lex->name.str))) break; - res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name), - &lex->create_info, 0); + res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : + lex->name.str), &lex->create_info, 0); break; } case SQLCOM_DROP_DB: @@ -3774,9 +3811,9 @@ end_with_restore_list: res= -1; break; } - if (check_db_name(lex->name)) + if (check_db_name(&lex->name)) { - my_error(ER_WRONG_DB_NAME, MYF(0), lex->name); + my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str); break; } /* @@ -3788,14 +3825,15 @@ end_with_restore_list: */ #ifdef HAVE_REPLICATION if (thd->slave_thread && - (!rpl_filter->db_ok(lex->name) || - !rpl_filter->db_ok_with_wild_table(lex->name))) + (!rpl_filter->db_ok(lex->name.str) || + !rpl_filter->db_ok_with_wild_table(lex->name.str))) { my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); break; } #endif - if (check_access(thd,DROP_ACL,lex->name,0,1,0,is_schema_db(lex->name))) + if (check_access(thd,DROP_ACL,lex->name.str,0,1,0, + is_schema_db(lex->name.str))) break; if (thd->locked_tables || thd->active_transaction()) { @@ -3803,7 +3841,7 @@ end_with_restore_list: ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); goto error; } - res= mysql_rm_db(thd, lex->name, lex->drop_if_exists, 0); + res= mysql_rm_db(thd, lex->name.str, lex->drop_if_exists, 0); break; } case SQLCOM_RENAME_DB: @@ -3829,6 +3867,11 @@ end_with_restore_list: break; } #endif + if (check_db_name(newdb)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), newdb->str); + break; + } if (check_access(thd,ALTER_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) || check_access(thd,DROP_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) || check_access(thd,CREATE_ACL,newdb->str,0,1,0,is_schema_db(newdb->str))) @@ -3850,11 +3893,10 @@ end_with_restore_list: } case SQLCOM_ALTER_DB: { - char *db= lex->name; - DBUG_ASSERT(db); /* Must be set in the parser */ - if (!strip_sp(db) || check_db_name(db)) + LEX_STRING *db= &lex->name; + if (check_db_name(db)) { - my_error(ER_WRONG_DB_NAME, MYF(0), db); + my_error(ER_WRONG_DB_NAME, MYF(0), db->str); break; } /* @@ -3866,14 +3908,14 @@ end_with_restore_list: */ #ifdef HAVE_REPLICATION if (thd->slave_thread && - (!rpl_filter->db_ok(db) || - !rpl_filter->db_ok_with_wild_table(db))) + (!rpl_filter->db_ok(db->str) || + !rpl_filter->db_ok_with_wild_table(db->str))) { my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); break; } #endif - if (check_access(thd, ALTER_ACL, db, 0, 1, 0, is_schema_db(db))) + if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0, is_schema_db(db->str))) break; if (thd->locked_tables || thd->active_transaction()) { @@ -3881,17 +3923,17 @@ end_with_restore_list: ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); goto error; } - res= mysql_alter_db(thd, db, &lex->create_info); + res= mysql_alter_db(thd, db->str, &lex->create_info); break; } case SQLCOM_SHOW_CREATE_DB: { - if (!strip_sp(lex->name) || check_db_name(lex->name)) + if (check_db_name(&lex->name)) { - my_error(ER_WRONG_DB_NAME, MYF(0), lex->name); + my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str); break; } - res=mysqld_show_create_db(thd,lex->name,&lex->create_info); + res= mysqld_show_create_db(thd, lex->name.str, &lex->create_info); break; } case SQLCOM_CREATE_EVENT: @@ -6276,9 +6318,38 @@ add_proc_to_list(THD* thd, Item *item) /* Fix escaping of _, % and \ in database and table names (for ODBC) */ +static void remove_escape(LEX_STRING *str) +{ + if (!str->length) // For empty DB names + return; + char *to, *end; + char *name= str->str; + + for (to= name, end= name + str->length; name != end; ) + { +#ifdef USE_MB + int l; + if (use_mb(system_charset_info) && + (l= my_ismbchar(system_charset_info, name, end))) + { + while (l--) + *to++ = *name++; + continue; + } +#endif + if (*name == '\\' && name + 1 != end) + name++; // Skip '\\' + *to++= *name++; + } + *to= 0; // Add end \0 for compability + str->length= (uint) (to - str->str); +} + +/* To be removed after next iteration of LEX_STRING replacements */ + static void remove_escape(char *name) { - if (!*name) // For empty DB names + if (!*name) // For empty DB names return; char *to; #ifdef USE_MB @@ -6291,19 +6362,20 @@ static void remove_escape(char *name) if (use_mb(system_charset_info) && (l = my_ismbchar(system_charset_info, name, strend))) { - while (l--) - *to++ = *name++; - name--; - continue; + while (l--) + *to++ = *name++; + name--; + continue; } #endif if (*name == '\\' && name[1]) - name++; // Skip '\\' + name++; // Skip '\\' /* purecov: inspected */ *to++= *name; } *to=0; } + /**************************************************************************** ** save order by and tables in own lists ****************************************************************************/ @@ -6371,7 +6443,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, } if (table->is_derived_table() == FALSE && table->db.str && - check_db_name(table->db.str)) + check_db_name(&table->db)) { my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str); DBUG_RETURN(0); @@ -7659,7 +7731,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, #ifdef NOT_NECESSARY_TO_CHECK_CREATE_TABLE_EXIST_WHEN_PREPARING_STATEMENT /* This code throws an ill error for CREATE TABLE t1 SELECT * FROM t1 */ /* - Only do the check for PS, becasue we on execute we have to check that + Only do the check for PS, because we on execute we have to check that against the opened tables to ensure we don't use a table that is part of the view (which can only be done after the table has been opened). */ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f0f69676ed2..3b221c67854 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4579,7 +4579,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table); DBUG_RETURN(TRUE); } - if (!src_db || check_db_name(src_db)) + if (!src_db || check_db_name(&table_ident->db)) { my_error(ER_WRONG_DB_NAME, MYF(0), src_db ? src_db : "NULL"); DBUG_RETURN(-1); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 8b60eefe4ea..3655ee99087 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -724,7 +724,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal NCHAR_STRING opt_component key_cache_name - sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem + sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty %type opt_table_alias @@ -734,7 +734,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type remember_name remember_end opt_ident opt_db text_or_password - opt_constraint constraint ident_or_empty + opt_constraint constraint %type text_string opt_gconcat_separator @@ -1213,7 +1213,8 @@ create: lex->create_info.options=$2 | $4; lex->create_info.db_type= lex->thd->variables.table_type; lex->create_info.default_table_charset= NULL; - lex->name= 0; + lex->name.str= 0; + lex->name.length= 0; lex->like_name= 0; } create2 @@ -1253,7 +1254,7 @@ create: { LEX *lex=Lex; lex->sql_command=SQLCOM_CREATE_DB; - lex->name=$4.str; + lex->name= $4; lex->create_info.options=$3; } | CREATE EVENT_SYM opt_if_not_exists sp_name @@ -1578,7 +1579,7 @@ clear_privileges: sp_name: ident '.' ident { - if (!$1.str || check_db_name($1.str)) + if (!$1.str || check_db_name(&$1)) { my_error(ER_WRONG_DB_NAME, MYF(0), $1.str); YYABORT; @@ -3163,7 +3164,7 @@ size_number: uint text_shift_number= 0; longlong prefix_number; char *start_ptr= $1.str; - uint str_len= strlen(start_ptr); + uint str_len= $1.length; char *end_ptr= start_ptr + str_len; int error; prefix_number= my_strtoll10(start_ptr, &end_ptr, &error); @@ -4674,7 +4675,8 @@ alter: { THD *thd= YYTHD; LEX *lex= thd->lex; - lex->name= 0; + lex->name.str= 0; + lex->name.length= 0; lex->sql_command= SQLCOM_ALTER_TABLE; lex->duplicates= DUP_ERROR; if (!lex->select_lex.add_table_to_list(thd, $4, NULL, @@ -4684,7 +4686,6 @@ alter: lex->key_list.empty(); lex->col_list.empty(); lex->select_lex.init_order(); - lex->name= 0; lex->like_name= 0; lex->select_lex.db= ((TABLE_LIST*) lex->select_lex.table_list.first)->db; @@ -4709,7 +4710,8 @@ alter: THD *thd= Lex->thd; lex->sql_command=SQLCOM_ALTER_DB; lex->name= $3; - if (lex->name == NULL && thd->copy_db_to(&lex->name, NULL)) + if (lex->name.str == NULL && + thd->copy_db_to(&lex->name.str, &lex->name.length)) YYABORT; } | ALTER PROCEDURE sp_name @@ -4867,8 +4869,8 @@ opt_ev_sql_stmt: /* empty*/ { $$= 0;} ident_or_empty: - /* empty */ { $$= 0; } - | ident { $$= $1.str; }; + /* empty */ { $$.str= 0; $$.length= 0; } + | ident { $$= $1; }; alter_commands: | DISCARD TABLESPACE { Lex->alter_info.tablespace_op= DISCARD_TABLESPACE; } @@ -5146,19 +5148,20 @@ alter_list_item: { LEX *lex=Lex; THD *thd= lex->thd; + uint dummy; lex->select_lex.db=$3->db.str; if (lex->select_lex.db == NULL && - thd->copy_db_to(&lex->select_lex.db, NULL)) + thd->copy_db_to(&lex->select_lex.db, &dummy)) { YYABORT; } if (check_table_name($3->table.str,$3->table.length) || - $3->db.str && check_db_name($3->db.str)) + $3->db.str && check_db_name(&$3->db)) { my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str); YYABORT; } - lex->name= $3->table.str; + lex->name= $3->table; lex->alter_info.flags|= ALTER_RENAME; } | CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate @@ -7705,7 +7708,7 @@ drop: LEX *lex=Lex; lex->sql_command= SQLCOM_DROP_DB; lex->drop_if_exists=$3; - lex->name=$4.str; + lex->name= $4; } | DROP FUNCTION_SYM if_exists sp_name { @@ -8378,7 +8381,7 @@ show_param: { Lex->sql_command=SQLCOM_SHOW_CREATE_DB; Lex->create_info.options=$3; - Lex->name=$4.str; + Lex->name= $4; } | CREATE TABLE_SYM table_ident { @@ -10368,7 +10371,8 @@ grant_ident: { LEX *lex= Lex; THD *thd= lex->thd; - if (thd->copy_db_to(&lex->current_select->db, NULL)) + uint dummy; + if (thd->copy_db_to(&lex->current_select->db, &dummy)) YYABORT; if (lex->grant == GLOBAL_ACLS) lex->grant = DB_ACLS & ~GRANT_ACL; diff --git a/sql/table.cc b/sql/table.cc index dec4901807d..71a6d09730f 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2234,7 +2234,7 @@ char *get_field(MEM_ROOT *mem, Field *field) SYNPOSIS check_db_name() - name Name of database + org_name Name of database and length NOTES If lower_case_table_names is set then database is converted to lower case @@ -2244,35 +2244,35 @@ char *get_field(MEM_ROOT *mem, Field *field) 1 error */ -bool check_db_name(char *name) +bool check_db_name(LEX_STRING *org_name) { - char *start=name; - /* Used to catch empty names and names with end space */ - bool last_char_is_space= TRUE; + char *name= org_name->str; + + if (!org_name->length || org_name->length > NAME_LEN) + return 1; if (lower_case_table_names && name != any_db) my_casedn_str(files_charset_info, name); - while (*name) - { #if defined(USE_MB) && defined(USE_MB_IDENT) - last_char_is_space= my_isspace(system_charset_info, *name); - if (use_mb(system_charset_info)) + if (use_mb(system_charset_info)) + { + bool last_char_is_space= TRUE; + char *end= name + org_name->length; + while (name < end) { - int len=my_ismbchar(system_charset_info, name, - name+system_charset_info->mbmaxlen); - if (len) - { - name += len; - continue; - } + int len; + last_char_is_space= my_isspace(system_charset_info, *name); + len= my_ismbchar(system_charset_info, name, end); + if (!len) + len= 1; + name+= len; } -#else - last_char_is_space= *name==' '; -#endif - name++; + return last_char_is_space; } - return last_char_is_space || (uint) (name - start) > NAME_LEN; + else +#endif + return org_name->str[org_name->length - 1] != ' '; /* purecov: inspected */ } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 02170f6aacb..669a6b74ba6 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -33,6 +33,7 @@ #include #include #include +#include #define VER "2.1" #define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */ @@ -11990,13 +11991,21 @@ static void test_bug6081() rc= simple_command(mysql, COM_DROP_DB, current_db, (ulong)strlen(current_db), 0); - myquery(rc); + if (rc == 0 && mysql_errno(mysql) != ER_UNKNOWN_COM_ERROR) + { + myerror(NULL); /* purecov: inspected */ + die(__FILE__, __LINE__, "COM_DROP_DB failed"); /* purecov: inspected */ + } rc= simple_command(mysql, COM_DROP_DB, current_db, (ulong)strlen(current_db), 0); myquery_r(rc); rc= simple_command(mysql, COM_CREATE_DB, current_db, (ulong)strlen(current_db), 0); - myquery(rc); + if (rc == 0 && mysql_errno(mysql) != ER_UNKNOWN_COM_ERROR) + { + myerror(NULL); /* purecov: inspected */ + die(__FILE__, __LINE__, "COM_CREATE_DB failed"); /* purecov: inspected */ + } rc= simple_command(mysql, COM_CREATE_DB, current_db, (ulong)strlen(current_db), 0); myquery_r(rc); @@ -15297,7 +15306,7 @@ static void test_bug15752() MYSQL mysql_local; int rc, i; const int ITERATION_COUNT= 100; - char *query= "CALL p1()"; + const char *query= "CALL p1()"; myheader("test_bug15752"); @@ -15392,6 +15401,24 @@ static void test_bug21206() DBUG_VOID_RETURN; } +/* + Ensure we execute the status code while testing +*/ + +static void test_status() +{ + const char *status; + DBUG_ENTER("test_status"); + myheader("test_status"); + + if (!(status= mysql_stat(mysql))) + { + myerror("mysql_stat failed"); /* purecov: inspected */ + die(__FILE__, __LINE__, "mysql_stat failed"); /* purecov: inspected */ + } + DBUG_VOID_RETURN; +} + /* Read and parse arguments and MySQL options from my.cnf @@ -15669,6 +15696,7 @@ static struct my_tests_st my_tests[]= { { "test_mysql_insert_id", test_mysql_insert_id }, { "test_bug19671", test_bug19671}, { "test_bug21206", test_bug21206}, + { "test_status", test_status}, { 0, 0 } };