1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

Reduce usage of strlen()

Changes:
- To detect automatic strlen() I removed the methods in String that
  uses 'const char *' without a length:
  - String::append(const char*)
  - Binary_string(const char *str)
  - String(const char *str, CHARSET_INFO *cs)
  - append_for_single_quote(const char *)
  All usage of append(const char*) is changed to either use
  String::append(char), String::append(const char*, size_t length) or
  String::append(LEX_CSTRING)
- Added STRING_WITH_LEN() around constant string arguments to
  String::append()
- Added overflow argument to escape_string_for_mysql() and
  escape_quotes_for_mysql() instead of returning (size_t) -1 on overflow.
  This was needed as most usage of the above functions never tested the
  result for -1 and would have given wrong results or crashes in case
  of overflows.
- Added Item_func_or_sum::func_name_cstring(), which returns LEX_CSTRING.
  Changed all Item_func::func_name()'s to func_name_cstring()'s.
  The old Item_func_or_sum::func_name() is now an inline function that
  returns func_name_cstring().str.
- Changed Item::mode_name() and Item::func_name_ext() to return
  LEX_CSTRING.
- Changed for some functions the name argument from const char * to
  to const LEX_CSTRING &:
  - Item::Item_func_fix_attributes()
  - Item::check_type_...()
  - Type_std_attributes::agg_item_collations()
  - Type_std_attributes::agg_item_set_converter()
  - Type_std_attributes::agg_arg_charsets...()
  - Type_handler_hybrid_field_type::aggregate_for_result()
  - Type_handler_geometry::check_type_geom_or_binary()
  - Type_handler::Item_func_or_sum_illegal_param()
  - Predicant_to_list_comparator::add_value_skip_null()
  - Predicant_to_list_comparator::add_value()
  - cmp_item_row::prepare_comparators()
  - cmp_item_row::aggregate_row_elements_for_comparison()
  - Cursor_ref::print_func()
- Removes String_space() as it was only used in one cases and that
  could be simplified to not use String_space(), thanks to the fixed
  my_vsnprintf().
- Added some const LEX_CSTRING's for common strings:
  - NULL_clex_str, DATA_clex_str, INDEX_clex_str.
- Changed primary_key_name to a LEX_CSTRING
- Renamed String::set_quick() to String::set_buffer_if_not_allocated() to
  clarify what the function really does.
- Rename of protocol function:
  bool store(const char *from, CHARSET_INFO *cs) to
  bool store_string_or_null(const char *from, CHARSET_INFO *cs).
  This was done to both clarify the difference between this 'store' function
  and also to make it easier to find unoptimal usage of store() calls.
- Added Protocol::store(const LEX_CSTRING*, CHARSET_INFO*)
- Changed some 'const char*' arrays to instead be of type LEX_CSTRING.
- class Item_func_units now used LEX_CSTRING for name.

Other things:
- Fixed a bug in mysql.cc:construct_prompt() where a wrong escape character
  in the prompt would cause some part of the prompt to be duplicated.
- Fixed a lot of instances where the length of the argument to
  append is known or easily obtain but was not used.
- Removed some not needed 'virtual' definition for functions that was
  inherited from the parent. I added override to these.
- Fixed Ordered_key::print() to preallocate needed buffer. Old code could
  case memory overruns.
- Simplified some loops when adding char * to a String with delimiters.
This commit is contained in:
Monty
2020-08-12 20:29:55 +03:00
committed by Sergei Golubchik
parent b3bc02f923
commit b6ff139aa3
113 changed files with 3543 additions and 1764 deletions

View File

@ -32,6 +32,15 @@
#include "sql_admin.h"
#include "sql_statistics.h"
#include "wsrep_mysqld.h"
const LEX_CSTRING msg_repair= { STRING_WITH_LEN("repair") };
const LEX_CSTRING msg_assign_to_keycache=
{ STRING_WITH_LEN("assign_to_keycache") };
const LEX_CSTRING msg_analyze= { STRING_WITH_LEN("analyze") };
const LEX_CSTRING msg_check= { STRING_WITH_LEN("check") };
const LEX_CSTRING msg_preload_keys= { STRING_WITH_LEN("preload_keys") };
const LEX_CSTRING msg_optimize= { STRING_WITH_LEN("optimize") };
/* Prepare, run and cleanup for mysql_recreate_table() */
static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
@ -71,15 +80,16 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
static int send_check_errmsg(THD *thd, TABLE_LIST* table,
const char* operator_name, const char* errmsg)
const LEX_CSTRING *operator_name,
const char* errmsg)
{
Protocol *protocol= thd->protocol;
protocol->prepare_for_resend();
protocol->store(table->alias.str, table->alias.length, system_charset_info);
protocol->store((char*) operator_name, system_charset_info);
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
protocol->store(errmsg, system_charset_info);
protocol->store(operator_name, system_charset_info);
protocol->store(&error_clex_str, system_charset_info);
protocol->store(errmsg, strlen(errmsg), system_charset_info);
thd->clear_error();
if (protocol->write())
return -1;
@ -148,7 +158,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
*/
if (table->s->tmp_table)
{
error= send_check_errmsg(thd, table_list, "repair",
error= send_check_errmsg(thd, table_list, &msg_repair,
"Cannot repair temporary table from .frm file");
goto end;
}
@ -166,8 +176,12 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
if (table->s->frm_version < FRM_VER_TRUE_VARCHAR &&
table->s->varchar_fields)
{
error= send_check_errmsg(thd, table_list, "repair",
"Failed repairing a very old .frm file as the data file format has changed between versions. Please dump the table in your old system with mysqldump and read it into this system with mysql or mysqlimport");
error= send_check_errmsg(thd, table_list, &msg_repair,
"Failed repairing a very old .frm file as the "
"data file format has changed between versions. "
"Please dump the table in your old system with "
"mysqldump and read it into this system with "
"mysql or mysqlimport");
goto end;
}
@ -225,12 +239,12 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
if (my_rename(from, tmp, MYF(MY_WME)))
{
error= send_check_errmsg(thd, table_list, "repair",
error= send_check_errmsg(thd, table_list, &msg_repair,
"Failed renaming data file");
goto end;
}
if (dd_recreate_table(thd, table_list->db.str, table_list->table_name.str))
create_error= send_check_errmsg(thd, table_list, "repair",
create_error= send_check_errmsg(thd, table_list, &msg_repair,
"Failed generating table from .frm file");
/*
'FALSE' for 'using_transactions' means don't postpone
@ -240,7 +254,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
query_cache_invalidate3(thd, table_list, FALSE);
if (mysql_file_rename(key_file_misc, tmp, from, MYF(MY_WME)))
{
error= send_check_errmsg(thd, table_list, "repair",
error= send_check_errmsg(thd, table_list, &msg_repair,
"Failed restoring .MYD file");
goto end;
}
@ -262,7 +276,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
*/
if (open_table(thd, table_list, &ot_ctx))
{
error= send_check_errmsg(thd, table_list, "repair",
error= send_check_errmsg(thd, table_list, &msg_repair,
"Failed to open partially repaired table");
goto end;
}
@ -430,14 +444,17 @@ dbug_err:
}
#ifdef WITH_WSREP
/*
OPTIMIZE, REPAIR and ALTER may take MDL locks not only for the affected table, but
also for the table referenced by foreign key constraint.
This wsrep_toi_replication() function handles TOI replication for OPTIMIZE and REPAIR
so that certification keys for potential FK parent tables are also appended in the
write set.
ALTER TABLE case is handled elsewhere.
*/
/*
OPTIMIZE, REPAIR and ALTER may take MDL locks not only for the
affected table, but also for the table referenced by foreign key
constraint.
This wsrep_toi_replication() function handles TOI replication for
OPTIMIZE and REPAIR so that certification keys for potential FK
parent tables are also appended in the write set. ALTER TABLE
case is handled elsewhere.
*/
static bool wsrep_toi_replication(THD *thd, TABLE_LIST *tables)
{
LEX *lex= thd->lex;
@ -480,7 +497,7 @@ static bool wsrep_toi_replication(THD *thd, TABLE_LIST *tables)
*/
static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
HA_CHECK_OPT* check_opt,
const char *operator_name,
const LEX_CSTRING *operator_name,
thr_lock_type lock_type,
bool org_open_for_modify,
bool repair_table_use_frm,
@ -555,7 +572,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
for (table= tables; table; table= table->next_local)
{
char table_name[SAFE_NAME_LEN*2+2];
char table_name_buff[SAFE_NAME_LEN*2+2];
LEX_CSTRING table_name= { table_name_buff, 0};
const char *db= table->db.str;
bool fatal_error=0;
bool open_error;
@ -567,7 +585,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (thd->is_killed())
break;
strxmov(table_name, db, ".", table->table_name.str, NullS);
table_name.length= strxmov(table_name_buff, db, ".", table->table_name.str,
NullS) - table_name_buff;
thd->open_options|= extra_open_options;
table->lock_type= lock_type;
/*
@ -645,12 +664,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
size_t length;
DBUG_PRINT("admin", ("sending non existent partition error"));
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
protocol->store(&error_clex_str, system_charset_info);
length= my_snprintf(buff, sizeof(buff),
ER_THD(thd, ER_DROP_PARTITION_NON_EXISTENT),
table_name);
table_name.str);
protocol->store(buff, length, system_charset_info);
if(protocol->write())
goto err;
@ -734,11 +753,11 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
enum_sql_command save_sql_command= lex->sql_command;
DBUG_PRINT("admin", ("sending error message"));
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
protocol->store(&error_clex_str, system_charset_info);
length= my_snprintf(buff, sizeof(buff), ER_THD(thd, ER_OPEN_AS_READONLY),
table_name);
table_name.str);
protocol->store(buff, length, system_charset_info);
trans_commit_stmt(thd);
trans_commit(thd);
@ -794,7 +813,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
/* purecov: begin inspected */
DBUG_PRINT("admin", ("sending crashed warning"));
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
protocol->store(STRING_WITH_LEN("warning"), system_charset_info);
protocol->store(STRING_WITH_LEN("Table is marked as crashed"),
@ -856,7 +875,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (result_code == HA_ADMIN_OK)
{
DBUG_PRINT("admin", ("calling operator_func '%s'", operator_name));
DBUG_PRINT("admin", ("calling operator_func '%s'", operator_name->str));
THD_STAGE_INFO(thd, stage_executing);
result_code = (table->table->file->*operator_func)(thd, check_opt);
THD_STAGE_INFO(thd, stage_sending_data);
@ -972,7 +991,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
else
{
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
protocol->store(STRING_WITH_LEN("status"), system_charset_info);
protocol->store(STRING_WITH_LEN("Engine-independent statistics collected"),
@ -1000,20 +1019,21 @@ send_result:
const Sql_condition *err;
while ((err= it++))
{
const char *err_msg= err->get_message_text();
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store((char*) operator_name, system_charset_info);
protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
protocol->store(warning_level_names[err->get_level()].str,
warning_level_names[err->get_level()].length,
system_charset_info);
protocol->store(err->get_message_text(), system_charset_info);
protocol->store(err_msg, strlen(err_msg), system_charset_info);
if (protocol->write())
goto err;
}
thd->get_stmt_da()->clear_warning_info(thd->query_id);
}
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
send_result_message:
@ -1025,7 +1045,7 @@ send_result_message:
char buf[MYSQL_ERRMSG_SIZE];
size_t length=my_snprintf(buf, sizeof(buf),
ER_THD(thd, ER_CHECK_NOT_IMPLEMENTED),
operator_name);
operator_name->str);
protocol->store(STRING_WITH_LEN("note"), system_charset_info);
protocol->store(buf, length, system_charset_info);
}
@ -1036,7 +1056,7 @@ send_result_message:
char buf[MYSQL_ERRMSG_SIZE];
size_t length= my_snprintf(buf, sizeof(buf),
ER_THD(thd, ER_BAD_TABLE_ERROR),
table_name);
table_name.str);
protocol->store(STRING_WITH_LEN("note"), system_charset_info);
protocol->store(buf, length, system_charset_info);
}
@ -1067,13 +1087,13 @@ send_result_message:
break;
case HA_ADMIN_CORRUPT:
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
protocol->store(&error_clex_str, system_charset_info);
protocol->store(STRING_WITH_LEN("Corrupt"), system_charset_info);
fatal_error=1;
break;
case HA_ADMIN_INVALID:
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
protocol->store(&error_clex_str, system_charset_info);
protocol->store(STRING_WITH_LEN("Invalid argument"),
system_charset_info);
break;
@ -1141,7 +1161,7 @@ send_result_message:
}
/* Start a new row for the final status row */
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
if (result_code) // either mysql_recreate_table or analyze failed
{
@ -1156,13 +1176,13 @@ send_result_message:
else
{
/* Hijack the row already in-progress. */
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
protocol->store(err_msg, system_charset_info);
protocol->store(&error_clex_str, system_charset_info);
protocol->store(err_msg, strlen(err_msg), system_charset_info);
if (protocol->write())
goto err;
/* Start off another row for HA_ADMIN_FAILED */
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
}
thd->clear_error();
@ -1193,7 +1213,7 @@ send_result_message:
const char *what_to_upgrade= table->view ? "VIEW" :
table->table->file->ha_table_flags() & HA_CAN_REPAIR ? "TABLE" : 0;
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
protocol->store(&error_clex_str, system_charset_info);
if (what_to_upgrade)
length= my_snprintf(buf, sizeof(buf),
ER_THD(thd, ER_TABLE_NEEDS_UPGRADE),
@ -1213,7 +1233,7 @@ send_result_message:
size_t length=my_snprintf(buf, sizeof(buf),
"Unknown - internal error %d during operation",
result_code);
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
protocol->store(&error_clex_str, system_charset_info);
protocol->store(buf, length, system_charset_info);
fatal_error=1;
break;
@ -1363,8 +1383,9 @@ bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
}
check_opt.key_cache= key_cache;
DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt,
"assign_to_keycache", TL_READ_NO_INSERT, 0, 0,
0, 0, &handler::assign_to_keycache, 0, false));
&msg_assign_to_keycache, TL_READ_NO_INSERT, 0,
0, 0, 0,
&handler::assign_to_keycache, 0, false));
}
@ -1390,8 +1411,9 @@ bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
outdated information if parallel inserts into cache blocks happen.
*/
DBUG_RETURN(mysql_admin_table(thd, tables, 0,
"preload_keys", TL_READ_NO_INSERT, 0, 0, 0, 0,
&handler::preload_keys, 0, false));
&msg_preload_keys, TL_READ_NO_INSERT,
0, 0, 0, 0,
&handler::preload_keys, 0, false));
}
@ -1411,9 +1433,8 @@ bool Sql_cmd_analyze_table::execute(THD *thd)
WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table);
res= mysql_admin_table(thd, first_table, &m_lex->check_opt,
"analyze", lock_type, 1, 0, 0, 0,
&msg_analyze, lock_type, 1, 0, 0, 0,
&handler::ha_analyze, 0, true);
m_lex->first_select_lex()->table_list.first= first_table;
m_lex->query_tables= first_table;
@ -1437,7 +1458,7 @@ bool Sql_cmd_check_table::execute(THD *thd)
TRUE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "check",
res= mysql_admin_table(thd, first_table, &m_lex->check_opt, &msg_check,
lock_type, 0, 0, HA_OPEN_FOR_REPAIR, 0,
&handler::ha_check, &view_check, false);
@ -1463,9 +1484,8 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
res= (specialflag & SPECIAL_NO_NEW_FUNC) ?
mysql_recreate_table(thd, first_table, true) :
mysql_admin_table(thd, first_table, &m_lex->check_opt,
"optimize", TL_WRITE, 1, 0, 0, 0,
&msg_optimize, TL_WRITE, 1, 0, 0, 0,
&handler::ha_optimize, 0, true);
m_lex->first_select_lex()->table_list.first= first_table;
m_lex->query_tables= first_table;
@ -1484,7 +1504,7 @@ bool Sql_cmd_repair_table::execute(THD *thd)
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table,
FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "repair",
res= mysql_admin_table(thd, first_table, &m_lex->check_opt, &msg_repair,
TL_WRITE, 1,
MY_TEST(m_lex->check_opt.sql_flags & TT_USEFRM),
HA_OPEN_FOR_REPAIR, &prepare_for_repair,