diff options
Diffstat (limited to 'sql/sql_show.cc')
-rw-r--r-- | sql/sql_show.cc | 1483 |
1 files changed, 1033 insertions, 450 deletions
diff --git a/sql/sql_show.cc b/sql/sql_show.cc index a4ef735c715..80634c68ac7 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +/* Copyright (C) 2000 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,9 +31,11 @@ static const char *grant_names[]={ "select","insert","update","delete","create","drop","reload","shutdown", "process","file","grant","references","index","alter"}; +#ifndef NO_EMBEDDED_ACCESS_CHECKS static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **), "grant_types", grant_names}; +#endif static int mysql_find_files(THD *thd,List<char> *files, const char *db, const char *path, const char *wild, bool dir); @@ -41,25 +43,21 @@ static int mysql_find_files(THD *thd,List<char> *files, const char *db, static int store_create_info(THD *thd, TABLE *table, String *packet); -static void -append_identifier(THD *thd, String *packet, const char *name); - -extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd; - -/**************************************************************************** -** Send list of databases -** A database is a directory in the mysql_data_home directory -****************************************************************************/ +/* + Report list of databases + A database is a directory in the mysql_data_home directory +*/ int mysqld_show_dbs(THD *thd,const char *wild) { - Item_string *field=new Item_string("",0); + Item_string *field=new Item_string("",0,thd->charset()); List<Item> field_list; char *end; List<char> files; char *file_name; + Protocol *protocol= thd->protocol; DBUG_ENTER("mysqld_show_dbs"); field->name=(char*) thd->alloc(20+ (wild ? (uint) strlen(wild)+4: 0)); @@ -69,64 +67,66 @@ mysqld_show_dbs(THD *thd,const char *wild) strxmov(end," (",wild,")",NullS); field_list.push_back(field); - if (send_fields(thd,field_list,1)) + if (protocol->send_fields(&field_list,1)) DBUG_RETURN(1); if (mysql_find_files(thd,&files,NullS,mysql_data_home,wild,1)) DBUG_RETURN(1); List_iterator_fast<char> it(files); + while ((file_name=it++)) { +#ifndef NO_EMBEDDED_ACCESS_CHECKS if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) || - acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, - thd->priv_user, file_name) || + acl_get(thd->host, thd->ip, thd->priv_user, file_name,0) || (grant_option && !check_grant_db(thd, file_name))) +#endif { - thd->packet.length(0); - net_store_data(&thd->packet, thd->variables.convert_set, file_name); - if (my_net_write(&thd->net, (char*) thd->packet.ptr(), - thd->packet.length())) + protocol->prepare_for_resend(); + protocol->store(file_name, system_charset_info); + if (protocol->write()) DBUG_RETURN(-1); } } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } + /*************************************************************************** -** List all open tables in a database + List all open tables in a database ***************************************************************************/ int mysqld_show_open_tables(THD *thd,const char *wild) { List<Item> field_list; OPEN_TABLE_LIST *open_list; - CONVERT *convert=thd->variables.convert_set; + Protocol *protocol= thd->protocol; DBUG_ENTER("mysqld_show_open_tables"); field_list.push_back(new Item_empty_string("Database",NAME_LEN)); field_list.push_back(new Item_empty_string("Table",NAME_LEN)); - field_list.push_back(new Item_int("In_use",0, 4)); - field_list.push_back(new Item_int("Name_locked",0, 4)); + field_list.push_back(new Item_return_int("In_use", 1, MYSQL_TYPE_TINY)); + field_list.push_back(new Item_return_int("Name_locked", 4, MYSQL_TYPE_TINY)); - if (send_fields(thd,field_list,1)) + if (protocol->send_fields(&field_list,1)) DBUG_RETURN(1); - if (!(open_list=list_open_tables(thd,wild)) && thd->fatal_error) + if (!(open_list=list_open_tables(thd,wild)) && thd->is_fatal_error) DBUG_RETURN(-1); for (; open_list ; open_list=open_list->next) { - thd->packet.length(0); - net_store_data(&thd->packet,convert, open_list->db); - net_store_data(&thd->packet,convert, open_list->table); - net_store_data(&thd->packet,open_list->in_use); - net_store_data(&thd->packet,open_list->locked); - if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length())) + protocol->prepare_for_resend(); + protocol->store(open_list->db, system_charset_info); + protocol->store(open_list->table, system_charset_info); + protocol->store_tiny((longlong) open_list->in_use); + protocol->store_tiny((longlong) open_list->locked); + if (protocol->write()) { DBUG_RETURN(-1); } } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } @@ -138,14 +138,16 @@ int mysqld_show_open_tables(THD *thd,const char *wild) int mysqld_show_tables(THD *thd,const char *db,const char *wild) { - Item_string *field=new Item_string("",0); + Item_string *field=new Item_string("",0,thd->charset()); List<Item> field_list; char path[FN_LEN],*end; List<char> files; char *file_name; + Protocol *protocol= thd->protocol; DBUG_ENTER("mysqld_show_tables"); - field->name=(char*) thd->alloc(20+(uint) strlen(db)+(wild ? (uint) strlen(wild)+4:0)); + field->name=(char*) thd->alloc(20+(uint) strlen(db)+ + (wild ? (uint) strlen(wild)+4:0)); end=strxmov(field->name,"Tables_in_",db,NullS); if (wild && wild[0]) strxmov(end," (",wild,")",NullS); @@ -153,19 +155,208 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild) (void) sprintf(path,"%s/%s",mysql_data_home,db); (void) unpack_dirname(path,path); field_list.push_back(field); - if (send_fields(thd,field_list,1)) + if (protocol->send_fields(&field_list,1)) DBUG_RETURN(1); if (mysql_find_files(thd,&files,db,path,wild,0)) DBUG_RETURN(-1); List_iterator_fast<char> it(files); while ((file_name=it++)) { - thd->packet.length(0); - net_store_data(&thd->packet, thd->variables.convert_set, file_name); - if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length())) + protocol->prepare_for_resend(); + protocol->store(file_name, system_charset_info); + if (protocol->write()) DBUG_RETURN(-1); } - send_eof(&thd->net); + send_eof(thd); + DBUG_RETURN(0); +} + +/*************************************************************************** +** List all table types supported +***************************************************************************/ + +int mysqld_show_storage_engines(THD *thd) +{ + List<Item> field_list; + Protocol *protocol= thd->protocol; + DBUG_ENTER("mysqld_show_storage_engines"); + + field_list.push_back(new Item_empty_string("Engine",10)); + field_list.push_back(new Item_empty_string("Support",10)); + field_list.push_back(new Item_empty_string("Comment",80)); + + if (protocol->send_fields(&field_list,1)) + DBUG_RETURN(1); + + const char *default_type_name= + ha_get_storage_engine((enum db_type)thd->variables.table_type); + + show_table_type_st *types; + for (types= sys_table_types; types->type; types++) + { + protocol->prepare_for_resend(); + protocol->store(types->type, system_charset_info); + const char *option_name= show_comp_option_name[(int) *types->value]; + + if (*types->value == SHOW_OPTION_YES && + !my_strcasecmp(system_charset_info, default_type_name, types->type)) + option_name= "DEFAULT"; + protocol->store(option_name, system_charset_info); + protocol->store(types->comment, system_charset_info); + if (protocol->write()) + DBUG_RETURN(-1); + } + send_eof(thd); + DBUG_RETURN(0); +} + + +/*************************************************************************** + List all privileges supported +***************************************************************************/ + +struct show_privileges_st { + const char *privilege; + const char *context; + const char *comment; +}; + +static struct show_privileges_st sys_privileges[]= +{ + {"Alter", "Tables", "To alter the table"}, + {"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"}, + {"Create", "Databases,Tables,Indexes", "To create new databases and tables"}, + {"Delete", "Tables", "To delete existing rows"}, + {"Drop", "Databases,Tables", "To drop databases and tables"}, + {"File", "File access on server", "To read and write files on the server"}, + {"Grant option", "Databases,Tables", "To give to other users those privileges you possess"}, + {"Index", "Tables", "To create or drop indexes"}, + {"Insert", "Tables", "To insert data into tables"}, + {"Lock tables","Databases","To use LOCK TABLES (together with SELECT privilege)"}, + {"Process", "Server Admin", "To view the plain text of currently executing queries"}, + {"References", "Databases,Tables", "To have references on tables"}, + {"Reload", "Server Admin", "To reload or refresh tables, logs and privileges"}, + {"Replication client","Server Admin","To ask where the slave or master servers are"}, + {"Replication slave","Server Admin","To read binary log events from the master"}, + {"Select", "Tables", "To retrieve rows from table"}, + {"Show databases","Server Admin","To see all databases with SHOW DATABASES"}, + {"Shutdown","Server Admin", "To shutdown the server"}, + {"Super","Server Admin","To use KILL thread, SET GLOBAL, CHANGE MASTER, etc."}, + {"Update", "Tables", "To update existing rows"}, + {"Usage","Server Admin","No privileges - allow connect only"}, + {NullS, NullS, NullS} +}; + +int mysqld_show_privileges(THD *thd) +{ + List<Item> field_list; + Protocol *protocol= thd->protocol; + DBUG_ENTER("mysqld_show_privileges"); + + field_list.push_back(new Item_empty_string("Privilege",10)); + field_list.push_back(new Item_empty_string("Context",15)); + field_list.push_back(new Item_empty_string("Comment",NAME_LEN)); + + if (protocol->send_fields(&field_list,1)) + DBUG_RETURN(1); + + show_privileges_st *privilege= sys_privileges; + for (privilege= sys_privileges; privilege->privilege ; privilege++) + { + protocol->prepare_for_resend(); + protocol->store(privilege->privilege, system_charset_info); + protocol->store(privilege->context, system_charset_info); + protocol->store(privilege->comment, system_charset_info); + if (protocol->write()) + DBUG_RETURN(-1); + } + send_eof(thd); + DBUG_RETURN(0); +} + + +/*************************************************************************** + List all column types +***************************************************************************/ + +struct show_column_type_st +{ + const char *type; + uint size; + const char *min_value; + const char *max_value; + uint precision; + uint scale; + const char *nullable; + const char *auto_increment; + const char *unsigned_attr; + const char *zerofill; + const char *searchable; + const char *case_sensitivity; + const char *default_value; + const char *comment; +}; + +/* TODO: Add remaning types */ + +static struct show_column_type_st sys_column_types[]= +{ + {"tinyint", + 1, "-128", "127", 0, 0, "YES", "YES", + "NO", "YES", "YES", "NO", "NULL,0", + "A very small integer"}, + {"tinyint unsigned", + 1, "0" , "255", 0, 0, "YES", "YES", + "YES", "YES", "YES", "NO", "NULL,0", + "A very small integer"}, +}; + +int mysqld_show_column_types(THD *thd) +{ + List<Item> field_list; + Protocol *protocol= thd->protocol; + DBUG_ENTER("mysqld_show_column_types"); + + field_list.push_back(new Item_empty_string("Type",30)); + field_list.push_back(new Item_int("Size",(longlong) 1,21)); + field_list.push_back(new Item_empty_string("Min_Value",20)); + field_list.push_back(new Item_empty_string("Max_Value",20)); + field_list.push_back(new Item_return_int("Prec", 4, MYSQL_TYPE_SHORT)); + field_list.push_back(new Item_return_int("Scale", 4, MYSQL_TYPE_SHORT)); + field_list.push_back(new Item_empty_string("Nullable",4)); + field_list.push_back(new Item_empty_string("Auto_Increment",4)); + field_list.push_back(new Item_empty_string("Unsigned",4)); + field_list.push_back(new Item_empty_string("Zerofill",4)); + field_list.push_back(new Item_empty_string("Searchable",4)); + field_list.push_back(new Item_empty_string("Case_Sensitive",4)); + field_list.push_back(new Item_empty_string("Default",NAME_LEN)); + field_list.push_back(new Item_empty_string("Comment",NAME_LEN)); + + if (protocol->send_fields(&field_list,1)) + DBUG_RETURN(1); + + /* TODO: Change the loop to not use 'i' */ + for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++) + { + protocol->prepare_for_resend(); + protocol->store(sys_column_types[i].type, system_charset_info); + protocol->store((ulonglong) sys_column_types[i].size); + protocol->store(sys_column_types[i].min_value, system_charset_info); + protocol->store(sys_column_types[i].max_value, system_charset_info); + protocol->store_short((longlong) sys_column_types[i].precision); + protocol->store_short((longlong) sys_column_types[i].scale); + protocol->store(sys_column_types[i].nullable, system_charset_info); + protocol->store(sys_column_types[i].auto_increment, system_charset_info); + protocol->store(sys_column_types[i].unsigned_attr, system_charset_info); + protocol->store(sys_column_types[i].zerofill, system_charset_info); + protocol->store(sys_column_types[i].searchable, system_charset_info); + protocol->store(sys_column_types[i].case_sensitivity, system_charset_info); + protocol->store(sys_column_types[i].default_value, system_charset_info); + protocol->store(sys_column_types[i].comment, system_charset_info); + if (protocol->write()) + DBUG_RETURN(-1); + } + send_eof(thd); DBUG_RETURN(0); } @@ -178,7 +369,9 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, char *ext; MY_DIR *dirp; FILEINFO *file; +#ifndef NO_EMBEDDED_ACCESS_CHECKS uint col_access=thd->col_access; +#endif TABLE_LIST table_list; DBUG_ENTER("mysql_find_files"); @@ -214,14 +407,14 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, #endif { if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat->st_mode) || - (wild && wild_compare(file->name,wild))) + (wild && wild_compare(file->name,wild,0))) continue; } } else { // Return only .frm files which aren't temp files. - if (my_strcasecmp(ext=fn_ext(file->name),reg_ext) || + if (my_strcasecmp(system_charset_info, ext=fn_ext(file->name),reg_ext) || is_prefix(file->name,tmp_file_prefix)) continue; *ext=0; @@ -229,22 +422,24 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, { if (lower_case_table_names) { - if (wild_case_compare(file->name,wild)) + if (wild_case_compare(system_charset_info,file->name,wild)) continue; } - else if (wild_compare(file->name,wild)) + else if (wild_compare(file->name,wild,0)) continue; } } +#ifndef NO_EMBEDDED_ACCESS_CHECKS /* Don't show tables where we don't have any privileges */ if (db && !(col_access & TABLE_ACLS)) { table_list.db= (char*) db; table_list.real_name=file->name; table_list.grant.privilege=col_access; - if (check_grant(thd,TABLE_ACLS,&table_list,1,1)) + if (check_grant(thd, TABLE_ACLS, &table_list, 1, UINT_MAX, 1)) continue; } +#endif if (files->push_back(thd->strdup(file->name))) { my_dirend(dirp); @@ -256,8 +451,9 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, DBUG_RETURN(0); } + /*************************************************************************** -** Extended version of mysqld_show_tables + Extended version of mysqld_show_tables ***************************************************************************/ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild) @@ -268,16 +464,14 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild) char path[FN_LEN]; char *file_name; TABLE *table; - String *packet= &thd->packet; - CONVERT *convert=thd->variables.convert_set; + Protocol *protocol= thd->protocol; + TIME time; DBUG_ENTER("mysqld_extend_show_tables"); (void) sprintf(path,"%s/%s",mysql_data_home,db); (void) unpack_dirname(path,path); - field_list.push_back(item=new Item_empty_string("Name",NAME_LEN)); - item->maybe_null=1; - field_list.push_back(item=new Item_empty_string("Type",10)); + field_list.push_back(item=new Item_empty_string("Engine",10)); item->maybe_null=1; field_list.push_back(item=new Item_empty_string("Row_format",10)); item->maybe_null=1; @@ -301,11 +495,15 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild) item->maybe_null=1; field_list.push_back(item=new Item_datetime("Check_time")); item->maybe_null=1; + field_list.push_back(item=new Item_empty_string("Collation",32)); + item->maybe_null=1; + field_list.push_back(item=new Item_int("Checksum",(longlong) 1,21)); + item->maybe_null=1; field_list.push_back(item=new Item_empty_string("Create_options",255)); item->maybe_null=1; field_list.push_back(item=new Item_empty_string("Comment",80)); item->maybe_null=1; - if (send_fields(thd,field_list,1)) + if (protocol->send_fields(&field_list,1)) DBUG_RETURN(1); if (mysql_find_files(thd,&files,db,path,wild,0)) @@ -315,70 +513,81 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild) { TABLE_LIST table_list; bzero((char*) &table_list,sizeof(table_list)); - packet->length(0); - net_store_data(packet,convert, file_name); + protocol->prepare_for_resend(); + protocol->store(file_name, system_charset_info); table_list.db=(char*) db; table_list.real_name= table_list.alias= file_name; if (lower_case_table_names) - casedn_str(file_name); + my_casedn_str(files_charset_info, file_name); if (!(table = open_ltable(thd, &table_list, TL_READ))) { for (uint i=2 ; i < field_list.elements ; i++) - net_store_null(packet); - net_store_data(packet,convert, thd->net.last_error); - thd->net.last_error[0]=0; + protocol->store_null(); + // Send error to Comment field + protocol->store(thd->net.last_error, system_charset_info); + thd->clear_error(); } else { struct tm tm_tmp; + const char *str; handler *file=table->file; file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK); - net_store_data(packet, convert, file->table_type()); - net_store_data(packet, convert, - (table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ? - "Compressed" : - (table->db_options_in_use & HA_OPTION_PACK_RECORD) ? - "Dynamic" : "Fixed"); - net_store_data(packet, (longlong) file->records); - net_store_data(packet, (uint32) file->mean_rec_length); - net_store_data(packet, (longlong) file->data_file_length); + protocol->store(file->table_type(), system_charset_info); + str= ((table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ? + "Compressed" : + (table->db_options_in_use & HA_OPTION_PACK_RECORD) ? + "Dynamic" : "Fixed"); + protocol->store(str, system_charset_info); + protocol->store((ulonglong) file->records); + protocol->store((ulonglong) file->mean_rec_length); + protocol->store((ulonglong) file->data_file_length); if (file->max_data_file_length) - net_store_data(packet, (longlong) file->max_data_file_length); + protocol->store((ulonglong) file->max_data_file_length); else - net_store_null(packet); - net_store_data(packet, (longlong) file->index_file_length); - net_store_data(packet, (longlong) file->delete_length); + protocol->store_null(); + protocol->store((ulonglong) file->index_file_length); + protocol->store((ulonglong) file->delete_length); if (table->found_next_number_field) { table->next_number_field=table->found_next_number_field; table->next_number_field->reset(); file->update_auto_increment(); - net_store_data(packet, table->next_number_field->val_int()); + protocol->store(table->next_number_field->val_int()); table->next_number_field=0; } else - net_store_null(packet); + protocol->store_null(); if (!file->create_time) - net_store_null(packet); + protocol->store_null(); else { localtime_r(&file->create_time,&tm_tmp); - net_store_data(packet, &tm_tmp); + localtime_to_TIME(&time, &tm_tmp); + protocol->store(&time); } if (!file->update_time) - net_store_null(packet); + protocol->store_null(); else { localtime_r(&file->update_time,&tm_tmp); - net_store_data(packet, &tm_tmp); + localtime_to_TIME(&time, &tm_tmp); + protocol->store(&time); } if (!file->check_time) - net_store_null(packet); + protocol->store_null(); else { localtime_r(&file->check_time,&tm_tmp); - net_store_data(packet, &tm_tmp); + localtime_to_TIME(&time, &tm_tmp); + protocol->store(&time); } + str= (table->table_charset ? table->table_charset->name : "default"); + protocol->store(str, system_charset_info); + if (file->table_flags() & HA_HAS_CHECKSUM) + protocol->store((ulonglong)file->checksum()); + else + protocol->store_null(); // Checksum { char option_buff[350],*ptr; ptr=option_buff; @@ -415,27 +624,26 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild) my_raid_type(file->raid_type), file->raid_chunks, file->raid_chunksize/RAID_BLOCK_SIZE); ptr=strmov(ptr,buff); } - net_store_data(packet, convert, option_buff+1, - (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1)); + protocol->store(option_buff+1, + (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1) + , system_charset_info); } { char *comment=table->file->update_table_comment(table->comment); - net_store_data(packet, comment); + protocol->store(comment, system_charset_info); if (comment != table->comment) my_free(comment,MYF(0)); } close_thread_tables(thd,0); } - if (my_net_write(&thd->net,(char*) packet->ptr(), - packet->length())) + if (protocol->write()) DBUG_RETURN(-1); } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } - /*************************************************************************** ** List all columns in a table_list->real_name ***************************************************************************/ @@ -448,61 +656,61 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, handler *file; char tmp[MAX_FIELD_WIDTH]; Item *item; - CONVERT *convert=thd->variables.convert_set; + Protocol *protocol= thd->protocol; DBUG_ENTER("mysqld_show_fields"); DBUG_PRINT("enter",("db: %s table: %s",table_list->db, table_list->real_name)); if (!(table = open_ltable(thd, table_list, TL_UNLOCK))) { - send_error(&thd->net); + send_error(thd); DBUG_RETURN(1); } file=table->file; file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); +#ifndef NO_EMBEDDED_ACCESS_CHECKS (void) get_table_grant(thd, table_list); - +#endif List<Item> field_list; field_list.push_back(new Item_empty_string("Field",NAME_LEN)); field_list.push_back(new Item_empty_string("Type",40)); + if (verbose) + field_list.push_back(new Item_empty_string("Collation",40)); field_list.push_back(new Item_empty_string("Null",1)); field_list.push_back(new Item_empty_string("Key",3)); field_list.push_back(item=new Item_empty_string("Default",NAME_LEN)); item->maybe_null=1; field_list.push_back(new Item_empty_string("Extra",20)); if (verbose) - field_list.push_back(new Item_empty_string("Privileges",80)); - - // Send first number of fields and records { - char *pos; - pos=net_store_length(tmp, (uint) field_list.elements); - pos=net_store_length(pos,(ulonglong) file->records); - (void) my_net_write(&thd->net,tmp,(uint) (pos-tmp)); + field_list.push_back(new Item_empty_string("Privileges",80)); + field_list.push_back(new Item_empty_string("Comment",255)); } - - if (send_fields(thd,field_list,0)) + // Send first number of fields and records + if (protocol->send_records_num(&field_list, (ulonglong)file->records) || + protocol->send_fields(&field_list,0)) DBUG_RETURN(1); - restore_record(table,2); // Get empty record + restore_record(table,default_values); // Get empty record Field **ptr,*field; - String *packet= &thd->packet; for (ptr=table->field; (field= *ptr) ; ptr++) { - if (!wild || !wild[0] || !wild_case_compare(field->field_name,wild)) + if (!wild || !wild[0] || + !wild_case_compare(system_charset_info, field->field_name,wild)) { { byte *pos; uint flags=field->flags; - String type(tmp,sizeof(tmp)); + String type(tmp,sizeof(tmp), system_charset_info); uint col_access; - bool null_default_value=0; - packet->length(0); - net_store_data(packet,convert,field->field_name); + protocol->prepare_for_resend(); + protocol->store(field->field_name, system_charset_info); field->sql_type(type); - net_store_data(packet,convert,type.ptr(),type.length()); - + protocol->store(type.ptr(), type.length(), system_charset_info); + if (verbose) + protocol->store(field->has_charset() ? field->charset()->name : "NULL", + system_charset_info); /* Altough TIMESTAMP fields can't contain NULL as its value they will accept NULL if you will try to insert such value and will @@ -512,40 +720,45 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, pos=(byte*) ((flags & NOT_NULL_FLAG) && field->type() != FIELD_TYPE_TIMESTAMP ? "" : "YES"); - net_store_data(packet,convert,(const char*) pos); + protocol->store((const char*) pos, system_charset_info); pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" : (field->flags & UNIQUE_KEY_FLAG) ? "UNI" : (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":""); - net_store_data(packet,convert,(char*) pos); + protocol->store((char*) pos, system_charset_info); - /* - We handle first TIMESTAMP column in special way because its - default value is ignored and current timestamp used instead. - */ - if (table->timestamp_field == field || - field->unireg_check == Field::NEXT_NUMBER) - null_default_value=1; - if (!null_default_value && !field->is_null()) + if (table->timestamp_field == field && + field->unireg_check != Field::TIMESTAMP_UN_FIELD) + { + /* + We have NOW() as default value but we use CURRENT_TIMESTAMP form + because it is more SQL standard comatible + */ + protocol->store("CURRENT_TIMESTAMP", system_charset_info); + } + else if (field->unireg_check != Field::NEXT_NUMBER && + !field->is_null()) { // Not null by default - type.set(tmp,sizeof(tmp)); - field->val_str(&type,&type); - net_store_data(packet,convert,type.ptr(),type.length()); + type.set(tmp, sizeof(tmp), field->charset()); + field->val_str(&type); + protocol->store(type.ptr(),type.length(),type.charset()); } - else if (field->maybe_null() || null_default_value) - net_store_null(packet); // Null as default + else if (field->unireg_check == Field::NEXT_NUMBER || + field->maybe_null()) + protocol->store_null(); // Null as default else - net_store_data(packet,convert,tmp,0); + protocol->store("",0, system_charset_info); // empty string char *end=tmp; if (field->unireg_check == Field::NEXT_NUMBER) end=strmov(tmp,"auto_increment"); - net_store_data(packet,convert,tmp,(uint) (end-tmp)); + protocol->store(tmp,(uint) (end-tmp), system_charset_info); if (verbose) { - /* Add grant options */ - col_access= get_column_grant(thd,table_list,field) & COL_ACLS; + /* Add grant options & comments */ end=tmp; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + col_access= get_column_grant(thd,table_list,field) & COL_ACLS; for (uint bitnr=0; col_access ; col_access>>=1,bitnr++) { if (col_access & 1) @@ -554,22 +767,31 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, end=strmov(end,grant_types.type_names[bitnr]); } } - net_store_data(packet,convert, tmp+1,end == tmp ? 0 : (uint) (end-tmp-1)); +#else + end=strmov(end,""); +#endif + protocol->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), + system_charset_info); + protocol->store(field->comment.str, field->comment.length, + system_charset_info); } - if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) + if (protocol->write()) DBUG_RETURN(1); } } } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } + int mysqld_show_create(THD *thd, TABLE_LIST *table_list) { TABLE *table; - CONVERT *convert=thd->variables.convert_set; + Protocol *protocol= thd->protocol; + char buff[2048]; + String buffer(buff, sizeof(buff), system_charset_info); DBUG_ENTER("mysqld_show_create"); DBUG_PRINT("enter",("db: %s table: %s",table_list->db, table_list->real_name)); @@ -577,77 +799,144 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) /* Only one table for now */ if (!(table = open_ltable(thd, table_list, TL_UNLOCK))) { - send_error(&thd->net); + send_error(thd); DBUG_RETURN(1); } - char buff[1024]; - String packet(buff,sizeof(buff)); - packet.length(0); - net_store_data(&packet,convert, table->table_name); - /* - A hack - we need to reserve some space for the length before - we know what it is - let's assume that the length of create table - statement will fit into 3 bytes ( 16 MB max :-) ) - */ - ulong store_len_offset = packet.length(); - packet.length(store_len_offset + 4); - if (store_create_info(thd, table, &packet)) + if (store_create_info(thd, table, &buffer)) + DBUG_RETURN(-1); + + List<Item> field_list; + field_list.push_back(new Item_empty_string("Table",NAME_LEN)); + // 1024 is for not to confuse old clients + field_list.push_back(new Item_empty_string("Create Table", + max(buffer.length(),1024))); + + if (protocol->send_fields(&field_list, 1)) + DBUG_RETURN(1); + protocol->prepare_for_resend(); + protocol->store(table->table_name, system_charset_info); + buffer.length(0); + if (store_create_info(thd, table, &buffer)) DBUG_RETURN(-1); - ulong create_len = packet.length() - store_len_offset - 4; - if (create_len > 0x00ffffff) // better readable in HEX ... + protocol->store(buffer.ptr(), buffer.length(), buffer.charset()); + if (protocol->write()) + DBUG_RETURN(1); + send_eof(thd); + DBUG_RETURN(0); +} + +int mysqld_show_create_db(THD *thd, char *dbname, + HA_CREATE_INFO *create_info) +{ + int length; + char path[FN_REFLEN]; + char buff[2048]; + String buffer(buff, sizeof(buff), system_charset_info); +#ifndef NO_EMBEDDED_ACCESS_CHECKS + uint db_access; +#endif + bool found_libchar; + HA_CREATE_INFO create; + uint create_options = create_info ? create_info->options : 0; + Protocol *protocol=thd->protocol; + DBUG_ENTER("mysql_show_create_db"); + + if (check_db_name(dbname)) { - /* - Just in case somebody manages to create a table - with *that* much stuff in the definition - */ + net_printf(thd,ER_WRONG_DB_NAME, dbname); DBUG_RETURN(1); } - /* - Now we have to store the length in three bytes, even if it would fit - into fewer bytes, so we cannot use net_store_data() anymore, - and do it ourselves - */ - char* p = (char*)packet.ptr() + store_len_offset; - *p++ = (char) 253; // The client the length is stored using 3-bytes - int3store(p, create_len); +#ifndef NO_EMBEDDED_ACCESS_CHECKS + if (test_all_bits(thd->master_access,DB_ACLS)) + db_access=DB_ACLS; + else + db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) | + thd->master_access); + if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) + { + net_printf(thd,ER_DBACCESS_DENIED_ERROR, + thd->priv_user, thd->host_or_ip, dbname); + mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), + thd->priv_user, thd->host_or_ip, dbname); + DBUG_RETURN(1); + } +#endif + + (void) sprintf(path,"%s/%s",mysql_data_home, dbname); + length=unpack_dirname(path,path); // Convert if not unix + found_libchar= 0; + if (length && path[length-1] == FN_LIBCHAR) + { + found_libchar= 1; + path[length-1]=0; // remove ending '\' + } + if (access(path,F_OK)) + { + net_printf(thd,ER_BAD_DB_ERROR,dbname); + DBUG_RETURN(1); + } + if (found_libchar) + path[length-1]= FN_LIBCHAR; + strmov(path+length, MY_DB_OPT_FILE); + load_db_opt(thd, path, &create); List<Item> field_list; - field_list.push_back(new Item_empty_string("Table",NAME_LEN)); - field_list.push_back(new Item_empty_string("Create Table", - max(packet.length(),1024))); // 1024 is for not to confuse old clients + field_list.push_back(new Item_empty_string("Database",NAME_LEN)); + field_list.push_back(new Item_empty_string("Create Database",1024)); - if (send_fields(thd,field_list,1)) + if (protocol->send_fields(&field_list,1)) DBUG_RETURN(1); - if (my_net_write(&thd->net, (char*)packet.ptr(), packet.length())) - DBUG_RETURN(1); + protocol->prepare_for_resend(); + protocol->store(dbname, strlen(dbname), system_charset_info); + buffer.length(0); + buffer.append("CREATE DATABASE ", 16); + if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS) + buffer.append("/*!32312 IF NOT EXISTS*/ ", 25); + append_identifier(thd, &buffer, dbname, strlen(dbname)); - send_eof(&thd->net); + if (create.default_table_charset) + { + buffer.append(" /*!40100", 9); + buffer.append(" DEFAULT CHARACTER SET ", 23); + buffer.append(create.default_table_charset->csname); + if (!(create.default_table_charset->state & MY_CS_PRIMARY)) + { + buffer.append(" COLLATE ", 9); + buffer.append(create.default_table_charset->name); + } + buffer.append(" */", 3); + } + protocol->store(buffer.ptr(), buffer.length(), buffer.charset()); + + if (protocol->write()) + DBUG_RETURN(1); + send_eof(thd); DBUG_RETURN(0); } - int mysqld_show_logs(THD *thd) { + List<Item> field_list; + Protocol *protocol= thd->protocol; DBUG_ENTER("mysqld_show_logs"); - List<Item> field_list; field_list.push_back(new Item_empty_string("File",FN_REFLEN)); field_list.push_back(new Item_empty_string("Type",10)); field_list.push_back(new Item_empty_string("Status",10)); - if (send_fields(thd,field_list,1)) + if (protocol->send_fields(&field_list,1)) DBUG_RETURN(1); #ifdef HAVE_BERKELEY_DB - if (!berkeley_skip && berkeley_show_logs(thd)) + if ((have_berkeley_db == SHOW_OPTION_YES) && berkeley_show_logs(protocol)) DBUG_RETURN(-1); #endif - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } @@ -656,30 +945,30 @@ int mysqld_show_keys(THD *thd, TABLE_LIST *table_list) { TABLE *table; - char buff[256]; - CONVERT *convert=thd->variables.convert_set; + Protocol *protocol= thd->protocol; DBUG_ENTER("mysqld_show_keys"); DBUG_PRINT("enter",("db: %s table: %s",table_list->db, table_list->real_name)); if (!(table = open_ltable(thd, table_list, TL_UNLOCK))) { - send_error(&thd->net); + send_error(thd); DBUG_RETURN(1); } List<Item> field_list; Item *item; field_list.push_back(new Item_empty_string("Table",NAME_LEN)); - field_list.push_back(new Item_int("Non_unique",0,1)); + field_list.push_back(new Item_return_int("Non_unique",1, MYSQL_TYPE_TINY)); field_list.push_back(new Item_empty_string("Key_name",NAME_LEN)); - field_list.push_back(new Item_int("Seq_in_index",0,2)); + field_list.push_back(new Item_return_int("Seq_in_index",2, MYSQL_TYPE_TINY)); field_list.push_back(new Item_empty_string("Column_name",NAME_LEN)); field_list.push_back(item=new Item_empty_string("Collation",1)); item->maybe_null=1; field_list.push_back(item=new Item_int("Cardinality",0,21)); item->maybe_null=1; - field_list.push_back(item=new Item_int("Sub_part",0,3)); + field_list.push_back(item=new Item_return_int("Sub_part",3, + MYSQL_TYPE_TINY)); item->maybe_null=1; field_list.push_back(item=new Item_empty_string("Packed",10)); item->maybe_null=1; @@ -688,76 +977,69 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list) field_list.push_back(new Item_empty_string("Comment",255)); item->maybe_null=1; - if (send_fields(thd,field_list,1)) + if (protocol->send_fields(&field_list,1)) DBUG_RETURN(1); - String *packet= &thd->packet; KEY *key_info=table->key_info; table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); for (uint i=0 ; i < table->keys ; i++,key_info++) { KEY_PART_INFO *key_part= key_info->key_part; - char *end; + const char *str; for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) { - packet->length(0); - net_store_data(packet,convert,table->table_name); - net_store_data(packet,convert,((key_info->flags & HA_NOSAME) ? "0" :"1"), 1); - net_store_data(packet,convert,key_info->name); - end=int10_to_str((long) (j+1),(char*) buff,10); - net_store_data(packet,convert,buff,(uint) (end-buff)); - net_store_data(packet,convert, - key_part->field ? key_part->field->field_name : - "?unknown field?"); + protocol->prepare_for_resend(); + protocol->store(table->table_name, system_charset_info); + protocol->store_tiny((longlong) ((key_info->flags & HA_NOSAME) ? 0 :1)); + protocol->store(key_info->name, system_charset_info); + protocol->store_tiny((longlong) (j+1)); + str=(key_part->field ? key_part->field->field_name : + "?unknown field?"); + protocol->store(str, system_charset_info); if (table->file->index_flags(i) & HA_READ_ORDER) - net_store_data(packet,convert, - ((key_part->key_part_flag & HA_REVERSE_SORT) ? - "D" : "A"), 1); + protocol->store(((key_part->key_part_flag & HA_REVERSE_SORT) ? + "D" : "A"), 1, system_charset_info); else - net_store_null(packet); /* purecov: inspected */ + protocol->store_null(); /* purecov: inspected */ KEY *key=table->key_info+i; if (key->rec_per_key[j]) { ha_rows records=(table->file->records / key->rec_per_key[j]); - end=longlong10_to_str((longlong) records, buff, 10); - net_store_data(packet,convert,buff,(uint) (end-buff)); + protocol->store((ulonglong) records); } else - net_store_null(packet); + protocol->store_null(); /* Check if we have a key part that only uses part of the field */ if (!(key_info->flags & HA_FULLTEXT) && (!key_part->field || key_part->length != table->field[key_part->fieldnr-1]->key_length())) - { - end=int10_to_str((long) key_part->length, buff,10); /* purecov: inspected */ - net_store_data(packet,convert,buff,(uint) (end-buff)); /* purecov: inspected */ - } + protocol->store_tiny((longlong) key_part->length); else - net_store_null(packet); - net_store_null(packet); // No pack_information yet + protocol->store_null(); + protocol->store_null(); // No pack_information yet /* Null flag */ uint flags= key_part->field ? key_part->field->flags : 0; char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES"); - net_store_data(packet,convert,(const char*) pos); - net_store_data(packet,convert,table->file->index_type(i)); + protocol->store((const char*) pos, system_charset_info); + protocol->store(table->file->index_type(i), system_charset_info); /* Comment */ - if (!(table->keys_in_use & ((key_map) 1 << i))) - net_store_data(packet,convert,"disabled",8); + if (!table->keys_in_use.is_set(i)) + protocol->store("disabled",8, system_charset_info); else - net_store_data(packet,convert,""); - if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) + protocol->store("", 0, system_charset_info); + if (protocol->write()) DBUG_RETURN(1); /* purecov: inspected */ } } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); } /**************************************************************************** -** Return only fields for API mysql_list_fields -** Use "show table wildcard" in mysql instead of this + Return only fields for API mysql_list_fields + Use "show table wildcard" in mysql instead of this ****************************************************************************/ void @@ -769,7 +1051,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) if (!(table = open_ltable(thd, table_list, TL_UNLOCK))) { - send_error(&thd->net); + send_error(thd); DBUG_VOID_RETURN; } List<Item> field_list; @@ -777,35 +1059,37 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) Field **ptr,*field; for (ptr=table->field ; (field= *ptr); ptr++) { - if (!wild || !wild[0] || !wild_case_compare(field->field_name,wild)) + if (!wild || !wild[0] || + !wild_case_compare(system_charset_info, field->field_name,wild)) field_list.push_back(new Item_field(field)); } - restore_record(table,2); // Get empty record - if (send_fields(thd,field_list,2)) + restore_record(table,default_values); // Get empty record + if (thd->protocol->send_fields(&field_list,2)) DBUG_VOID_RETURN; - VOID(net_flush(&thd->net)); + net_flush(&thd->net); DBUG_VOID_RETURN; } + int mysqld_dump_create_info(THD *thd, TABLE *table, int fd) { - CONVERT *convert=thd->variables.convert_set; + Protocol *protocol= thd->protocol; + String *packet= protocol->storage_packet(); DBUG_ENTER("mysqld_dump_create_info"); DBUG_PRINT("enter",("table: %s",table->real_name)); - String* packet = &thd->packet; - packet->length(0); - if (store_create_info(thd,table,packet)) + protocol->prepare_for_resend(); + if (store_create_info(thd, table, packet)) DBUG_RETURN(-1); - if (convert) - convert->convert((char*) packet->ptr(), packet->length()); + //if (protocol->convert) + // protocol->convert->convert((char*) packet->ptr(), packet->length()); if (fd < 0) { - if (my_net_write(&thd->net, (char*)packet->ptr(), packet->length())) + if (protocol->write()) DBUG_RETURN(-1); - VOID(net_flush(&thd->net)); + net_flush(&thd->net); } else { @@ -816,19 +1100,85 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd) DBUG_RETURN(0); } -static void -append_identifier(THD *thd, String *packet, const char *name) +/* + Go through all character combinations and ensure that sql_lex.cc can + parse it as an identifer. + + SYNOPSIS + require_quotes() + name attribute name + name_length length of name + + RETURN + # Pointer to conflicting character + 0 No conflicting character +*/ + +static const char *require_quotes(const char *name, uint name_length) { - if (thd->options & OPTION_QUOTE_SHOW_CREATE) + uint length; + const char *end= name + name_length; + + for ( ; name < end ; name++) { - packet->append("`", 1); - packet->append(name); - packet->append("`", 1); + uchar chr= (uchar) *name; + length= my_mbcharlen(system_charset_info, chr); + if (length == 1 && !system_charset_info->ident_map[chr]) + return name; } + return 0; +} + + +static void append_quoted_simple_identifier(String *packet, char quote_char, + const char *name, uint length) +{ + packet->append("e_char, 1, system_charset_info); + packet->append(name, length, system_charset_info); + packet->append("e_char, 1, system_charset_info); +} + + +void +append_identifier(THD *thd, String *packet, const char *name, uint length) +{ + const char *name_end; + char quote_char; + + if (thd->variables.sql_mode & MODE_ANSI_QUOTES) + quote_char= '\"'; else + quote_char= '`'; + + if (is_keyword(name,length)) { - packet->append(name); + append_quoted_simple_identifier(packet, quote_char, name, length); + return; } + + if (!require_quotes(name, length)) + { + if (!(thd->options & OPTION_QUOTE_SHOW_CREATE)) + packet->append(name, length, system_charset_info); + else + append_quoted_simple_identifier(packet, quote_char, name, length); + return; + } + + /* The identifier must be quoted as it includes a quote character */ + + packet->reserve(length*2 + 2); + packet->append("e_char, 1, system_charset_info); + + for (name_end= name+length ; name < name_end ; name+= length) + { + char chr= *name; + length= my_mbcharlen(system_charset_info, chr); + if (length == 1 && chr == quote_char) + packet->append("e_char, 1, system_charset_info); + packet->append(name, length, packet->charset()); + } + packet->append("e_char, 1, system_charset_info); } @@ -838,7 +1188,7 @@ static void append_directory(THD *thd, String *packet, const char *dir_type, const char *filename) { uint length; - if (filename && !(thd->sql_mode & MODE_NO_DIR_IN_CREATE)) + if (filename && !(thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)) { length= dirname_length(filename); packet->append(' '); @@ -850,64 +1200,115 @@ static void append_directory(THD *thd, String *packet, const char *dir_type, } +#define LIST_PROCESS_HOST_LEN 64 + static int store_create_info(THD *thd, TABLE *table, String *packet) { List<Item> field_list; - char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end; - String type(tmp, sizeof(tmp)); + char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end, *alias; + String type(tmp, sizeof(tmp),&my_charset_bin); Field **ptr,*field; uint primary_key; KEY *key_info; handler *file= table->file; HA_CREATE_INFO create_info; + my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL | + MODE_ORACLE | + MODE_MSSQL | + MODE_DB2 | + MODE_MAXDB | + MODE_ANSI)) != 0; + my_bool limited_mysql_mode= (thd->variables.sql_mode & + (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 | + MODE_MYSQL40)) != 0; + DBUG_ENTER("store_create_info"); DBUG_PRINT("enter",("table: %s",table->real_name)); - restore_record(table,2); // Get empty record + restore_record(table,default_values); // Get empty record + if (table->tmp_table) packet->append("CREATE TEMPORARY TABLE ", 23); else packet->append("CREATE TABLE ", 13); - append_identifier(thd,packet, - (lower_case_table_names == 2 ? table->table_name : - table->real_name)); + alias= (lower_case_table_names == 2 ? table->table_name : + table->real_name); + append_identifier(thd, packet, alias, strlen(alias)); packet->append(" (\n", 3); for (ptr=table->field ; (field= *ptr); ptr++) { bool has_default; + bool has_now_default; uint flags = field->flags; if (ptr != table->field) packet->append(",\n", 2); + packet->append(" ", 2); - append_identifier(thd,packet,field->field_name); + append_identifier(thd,packet,field->field_name, strlen(field->field_name)); packet->append(' '); // check for surprises from the previous call to Field::sql_type() if (type.ptr() != tmp) - type.set(tmp, sizeof(tmp)); + type.set(tmp, sizeof(tmp),&my_charset_bin); field->sql_type(type); packet->append(type.ptr(),type.length()); - has_default= (field->type() != FIELD_TYPE_BLOB && - table->timestamp_field != field && - field->unireg_check != Field::NEXT_NUMBER); + if (field->has_charset() && !limited_mysql_mode && !foreign_db_mode) + { + if (field->charset() != table->table_charset) + { + packet->append(" character set ", 15); + packet->append(field->charset()->csname); + } + /* + For string types dump collation name only if + collation is not primary for the given charset + */ + if (!(field->charset()->state & MY_CS_PRIMARY)) + { + packet->append(" collate ", 9); + packet->append(field->charset()->name); + } + } + if (flags & NOT_NULL_FLAG) packet->append(" NOT NULL", 9); + + /* + Again we are using CURRENT_TIMESTAMP instead of NOW because it is + more standard + */ + has_now_default= table->timestamp_field == field && + field->unireg_check != Field::TIMESTAMP_UN_FIELD; + + has_default= (field->type() != FIELD_TYPE_BLOB && + field->unireg_check != Field::NEXT_NUMBER && + !((foreign_db_mode || limited_mysql_mode) && + has_now_default)); + if (has_default) { packet->append(" default ", 9); - if (!field->is_null()) + if (has_now_default) + packet->append("CURRENT_TIMESTAMP",17); + else if (!field->is_null()) { // Not null by default - type.set(tmp,sizeof(tmp)); - field->val_str(&type,&type); - packet->append('\''); + type.set(tmp, sizeof(tmp), field->charset()); + field->val_str(&type); if (type.length()) - append_unescaped(packet, type.c_ptr()); - packet->append('\''); + { + String def_val; + /* convert to system_charset_info == utf8 */ + def_val.copy(type.ptr(), type.length(), field->charset(), + system_charset_info); + append_unescaped(packet, def_val.ptr(), def_val.length()); + } + else + packet->append("''",2); } else if (field->maybe_null()) packet->append("NULL", 4); // Null as default @@ -915,8 +1316,19 @@ store_create_info(THD *thd, TABLE *table, String *packet) packet->append(tmp,0); } - if (field->unireg_check == Field::NEXT_NUMBER) - packet->append(" auto_increment", 15 ); + if (!foreign_db_mode && !limited_mysql_mode && + table->timestamp_field == field && + field->unireg_check != Field::TIMESTAMP_DN_FIELD) + packet->append(" on update CURRENT_TIMESTAMP",28); + + if (field->unireg_check == Field::NEXT_NUMBER && !foreign_db_mode) + packet->append(" auto_increment", 15 ); + + if (field->comment.length) + { + packet->append(" COMMENT ",9); + append_unescaped(packet, field->comment.str, field->comment.length); + } } key_info= table->key_info; @@ -931,7 +1343,7 @@ store_create_info(THD *thd, TABLE *table, String *packet) bool found_primary=0; packet->append(",\n ", 4); - if (i == primary_key && !strcmp(key_info->name,"PRIMARY")) + if (i == primary_key && !strcmp(key_info->name, primary_key_name)) { found_primary=1; packet->append("PRIMARY ", 8); @@ -940,11 +1352,25 @@ store_create_info(THD *thd, TABLE *table, String *packet) packet->append("UNIQUE ", 7); else if (key_info->flags & HA_FULLTEXT) packet->append("FULLTEXT ", 9); + else if (key_info->flags & HA_SPATIAL) + packet->append("SPATIAL ", 8); packet->append("KEY ", 4); if (!found_primary) - append_identifier(thd,packet,key_info->name); + append_identifier(thd, packet, key_info->name, strlen(key_info->name)); + if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) && + !limited_mysql_mode && !foreign_db_mode) + { + if (table->db_type == DB_TYPE_HEAP && + key_info->algorithm == HA_KEY_ALG_BTREE) + packet->append(" TYPE BTREE", 11); + + // +BAR: send USING only in non-default case: non-spatial rtree + if ((key_info->algorithm == HA_KEY_ALG_RTREE) && + !(key_info->flags & HA_SPATIAL)) + packet->append(" TYPE RTREE", 11); + } packet->append(" (", 2); for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) @@ -953,14 +1379,17 @@ store_create_info(THD *thd, TABLE *table, String *packet) packet->append(','); if (key_part->field) - append_identifier(thd,packet,key_part->field->field_name); + append_identifier(thd,packet,key_part->field->field_name, + strlen(key_part->field->field_name)); if (!key_part->field || (key_part->length != table->field[key_part->fieldnr-1]->key_length() && !(key_info->flags & HA_FULLTEXT))) { buff[0] = '('; - char* end=int10_to_str((long) key_part->length, buff + 1,10); + char* end=int10_to_str((long) key_part->length / + key_part->field->charset()->mbmaxlen, + buff + 1,10); *end++ = ')'; packet->append(buff,(uint) (end-buff)); } @@ -980,66 +1409,86 @@ store_create_info(THD *thd, TABLE *table, String *packet) } packet->append("\n)", 2); - packet->append(" TYPE=", 6); - packet->append(file->table_type()); - - if (table->min_rows) + if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode) { - packet->append(" MIN_ROWS="); - end= longlong10_to_str(table->min_rows, buff, 10); - packet->append(buff, (uint) (end- buff)); - } - if (table->max_rows) - { - packet->append(" MAX_ROWS="); - end= longlong10_to_str(table->max_rows, buff, 10); - packet->append(buff, (uint) (end - buff)); - } - if (table->avg_row_length) - { - packet->append(" AVG_ROW_LENGTH="); - end= longlong10_to_str(table->avg_row_length, buff,10); - packet->append(buff, (uint) (end - buff)); - } + if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) + packet->append(" TYPE=", 6); + else + packet->append(" ENGINE=", 8); + packet->append(file->table_type()); + + if (table->table_charset && + !(thd->variables.sql_mode & MODE_MYSQL323) && + !(thd->variables.sql_mode & MODE_MYSQL40)) + { + packet->append(" DEFAULT CHARSET=", 17); + packet->append(table->table_charset->csname); + if (!(table->table_charset->state & MY_CS_PRIMARY)) + { + packet->append(" COLLATE=", 9); + packet->append(table->table_charset->name); + } + } - if (table->db_create_options & HA_OPTION_PACK_KEYS) - packet->append(" PACK_KEYS=1", 12); - if (table->db_create_options & HA_OPTION_NO_PACK_KEYS) - packet->append(" PACK_KEYS=0", 12); - if (table->db_create_options & HA_OPTION_CHECKSUM) - packet->append(" CHECKSUM=1", 11); - if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE) - packet->append(" DELAY_KEY_WRITE=1",18); - if (table->row_type != ROW_TYPE_DEFAULT) - { - packet->append(" ROW_FORMAT=",12); - packet->append(ha_row_type[(uint) table->row_type]); - } - table->file->append_create_info(packet); - if (table->comment && table->comment[0]) - { - packet->append(" COMMENT='", 10); - append_unescaped(packet, table->comment); - packet->append('\''); - } - if (file->raid_type) - { - uint length; - length= my_snprintf(buff,sizeof(buff), - " RAID_TYPE=%s RAID_CHUNKS=%d RAID_CHUNKSIZE=%ld", - my_raid_type(file->raid_type), file->raid_chunks, - file->raid_chunksize/RAID_BLOCK_SIZE); - packet->append(buff, length); + if (table->min_rows) + { + packet->append(" MIN_ROWS=", 10); + end= longlong10_to_str(table->min_rows, buff, 10); + packet->append(buff, (uint) (end- buff)); + } + + if (table->max_rows) + { + packet->append(" MAX_ROWS=", 10); + end= longlong10_to_str(table->max_rows, buff, 10); + packet->append(buff, (uint) (end - buff)); + } + + if (table->avg_row_length) + { + packet->append(" AVG_ROW_LENGTH=", 16); + end= longlong10_to_str(table->avg_row_length, buff,10); + packet->append(buff, (uint) (end - buff)); + } + + if (table->db_create_options & HA_OPTION_PACK_KEYS) + packet->append(" PACK_KEYS=1", 12); + if (table->db_create_options & HA_OPTION_NO_PACK_KEYS) + packet->append(" PACK_KEYS=0", 12); + if (table->db_create_options & HA_OPTION_CHECKSUM) + packet->append(" CHECKSUM=1", 11); + if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE) + packet->append(" DELAY_KEY_WRITE=1",18); + if (table->row_type != ROW_TYPE_DEFAULT) + { + packet->append(" ROW_FORMAT=",12); + packet->append(ha_row_type[(uint) table->row_type]); + } + table->file->append_create_info(packet); + if (table->comment && table->comment[0]) + { + packet->append(" COMMENT=", 9); + append_unescaped(packet, table->comment, strlen(table->comment)); + } + if (file->raid_type) + { + uint length; + length= my_snprintf(buff,sizeof(buff), + " RAID_TYPE=%s RAID_CHUNKS=%d RAID_CHUNKSIZE=%ld", + my_raid_type(file->raid_type), file->raid_chunks, + file->raid_chunksize/RAID_BLOCK_SIZE); + packet->append(buff, length); + } + append_directory(thd, packet, "DATA", create_info.data_file_name); + append_directory(thd, packet, "INDEX", create_info.index_file_name); } - append_directory(thd, packet, "DATA", create_info.data_file_name); - append_directory(thd, packet, "INDEX", create_info.index_file_name); DBUG_RETURN(0); } /**************************************************************************** -** Return info about all processes -** returns for each thread: thread id, user, host, db, command, info + Return info about all processes + returns for each thread: thread id, user, host, db, command, info ****************************************************************************/ class thread_info :public ilink { @@ -1059,8 +1508,6 @@ public: template class I_List<thread_info>; #endif -#define LIST_PROCESS_HOST_LEN 64 - void mysqld_list_processes(THD *thd,const char *user, bool verbose) { Item *field; @@ -1068,21 +1515,21 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) I_List<thread_info> thread_infos; ulong max_query_length= (verbose ? thd->variables.max_allowed_packet : PROCESS_LIST_WIDTH); - CONVERT *convert=thd->variables.convert_set; + Protocol *protocol= thd->protocol; DBUG_ENTER("mysqld_list_processes"); - field_list.push_back(new Item_int("Id",0,7)); + field_list.push_back(new Item_int("Id",0,11)); field_list.push_back(new Item_empty_string("User",16)); field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN)); field_list.push_back(field=new Item_empty_string("db",NAME_LEN)); field->maybe_null=1; field_list.push_back(new Item_empty_string("Command",16)); - field_list.push_back(new Item_empty_string("Time",7)); + field_list.push_back(new Item_return_int("Time",7, FIELD_TYPE_LONG)); field_list.push_back(field=new Item_empty_string("State",30)); field->maybe_null=1; field_list.push_back(field=new Item_empty_string("Info",max_query_length)); field->maybe_null=1; - if (send_fields(thd,field_list,1)) + if (protocol->send_fields(&field_list,1)) DBUG_VOID_RETURN; VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list @@ -1093,8 +1540,13 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) while ((tmp=it++)) { struct st_my_thread_var *mysys_var; +#ifndef EMBEDDED_LIBRARY if ((tmp->net.vio || tmp->system_thread) && (!user || (tmp->user && !strcmp(tmp->user,user)))) +#else + if (tmp->system_thread && + (!user || (tmp->user && !strcmp(tmp->user,user)))) +#endif { thread_info *thd_info=new thread_info; @@ -1116,6 +1568,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) if ((mysys_var= tmp->mysys_var)) pthread_mutex_lock(&mysys_var->mutex); thd_info->proc_info= (char*) (tmp->killed ? "Killed" : 0); +#ifndef EMBEDDED_LIBRARY thd_info->state_info= (char*) (tmp->locked ? "Locked" : tmp->net.reading_or_writing ? (tmp->net.reading_or_writing == 2 ? @@ -1126,6 +1579,9 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) tmp->mysys_var && tmp->mysys_var->current_cond ? "Waiting on cond" : NullS); +#else + thd_info->state_info= (char*)"Writing to net"; +#endif if (mysys_var) pthread_mutex_unlock(&mysys_var->mutex); @@ -1156,308 +1612,435 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) VOID(pthread_mutex_unlock(&LOCK_thread_count)); thread_info *thd_info; - String *packet= &thd->packet; + time_t now= time(0); while ((thd_info=thread_infos.get())) { - char buff[20],*end; - packet->length(0); - end=int10_to_str((long) thd_info->thread_id, buff,10); - net_store_data(packet,convert,buff,(uint) (end-buff)); - net_store_data(packet,convert,thd_info->user); - net_store_data(packet,convert,thd_info->host); - if (thd_info->db) - net_store_data(packet,convert,thd_info->db); - else - net_store_null(packet); + protocol->prepare_for_resend(); + protocol->store((ulonglong) thd_info->thread_id); + protocol->store(thd_info->user, system_charset_info); + protocol->store(thd_info->host, system_charset_info); + protocol->store(thd_info->db, system_charset_info); if (thd_info->proc_info) - net_store_data(packet,convert,thd_info->proc_info); + protocol->store(thd_info->proc_info, system_charset_info); else - net_store_data(packet,convert,command_name[thd_info->command]); + protocol->store(command_name[thd_info->command], system_charset_info); if (thd_info->start_time) - net_store_data(packet, - (uint32) (time((time_t*) 0) - thd_info->start_time)); + protocol->store((uint32) (now - thd_info->start_time)); else - net_store_null(packet); - if (thd_info->state_info) - net_store_data(packet,convert,thd_info->state_info); - else - net_store_null(packet); - if (thd_info->query) - net_store_data(packet,convert,thd_info->query); - else - net_store_null(packet); - if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) + protocol->store_null(); + protocol->store(thd_info->state_info, system_charset_info); + protocol->store(thd_info->query, system_charset_info); + if (protocol->write()) break; /* purecov: inspected */ } - send_eof(&thd->net); + send_eof(thd); DBUG_VOID_RETURN; } - /***************************************************************************** -** Status functions + Status functions *****************************************************************************/ +static bool write_collation(Protocol *protocol, CHARSET_INFO *cs) +{ + protocol->prepare_for_resend(); + protocol->store(cs->name, system_charset_info); + protocol->store(cs->csname, system_charset_info); + protocol->store_short((longlong) cs->number); + protocol->store((cs->state & MY_CS_PRIMARY) ? "Yes" : "",system_charset_info); + protocol->store((cs->state & MY_CS_COMPILED)? "Yes" : "",system_charset_info); + protocol->store_short((longlong) cs->strxfrm_multiply); + return protocol->write(); +} + +int mysqld_show_collations(THD *thd, const char *wild) +{ + char buff[8192]; + String packet2(buff,sizeof(buff),thd->charset()); + List<Item> field_list; + CHARSET_INFO **cs; + Protocol *protocol= thd->protocol; + + DBUG_ENTER("mysqld_show_charsets"); + + field_list.push_back(new Item_empty_string("Collation",30)); + field_list.push_back(new Item_empty_string("Charset",30)); + field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT)); + field_list.push_back(new Item_empty_string("Default",30)); + field_list.push_back(new Item_empty_string("Compiled",30)); + field_list.push_back(new Item_return_int("Sortlen",3, FIELD_TYPE_SHORT)); + + if (protocol->send_fields(&field_list, 1)) + DBUG_RETURN(1); + + for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ ) + { + CHARSET_INFO **cl; + if (!cs[0] || !(cs[0]->state & MY_CS_AVAILABLE) || + !(cs[0]->state & MY_CS_PRIMARY)) + continue; + for ( cl= all_charsets; cl < all_charsets+255 ;cl ++) + { + if (!cl[0] || !(cl[0]->state & MY_CS_AVAILABLE) || + !my_charset_same(cs[0],cl[0])) + continue; + if (!(wild && wild[0] && + wild_case_compare(system_charset_info,cl[0]->name,wild))) + { + if (write_collation(protocol, cl[0])) + goto err; + } + } + } + send_eof(thd); + DBUG_RETURN(0); +err: + DBUG_RETURN(1); +} + +static bool write_charset(Protocol *protocol, CHARSET_INFO *cs) +{ + protocol->prepare_for_resend(); + protocol->store(cs->csname, system_charset_info); + protocol->store(cs->comment ? cs->comment : "", system_charset_info); + protocol->store(cs->name, system_charset_info); + protocol->store_short((longlong) cs->mbmaxlen); + return protocol->write(); +} + +int mysqld_show_charsets(THD *thd, const char *wild) +{ + char buff[8192]; + String packet2(buff,sizeof(buff),thd->charset()); + List<Item> field_list; + CHARSET_INFO **cs; + Protocol *protocol= thd->protocol; + + DBUG_ENTER("mysqld_show_charsets"); + + field_list.push_back(new Item_empty_string("Charset",30)); + field_list.push_back(new Item_empty_string("Description",60)); + field_list.push_back(new Item_empty_string("Default collation",60)); + field_list.push_back(new Item_return_int("Maxlen",3, FIELD_TYPE_SHORT)); + + if (protocol->send_fields(&field_list, 1)) + DBUG_RETURN(1); + + for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ ) + { + if (cs[0] && (cs[0]->state & MY_CS_PRIMARY) && + (cs[0]->state & MY_CS_AVAILABLE) && + !(wild && wild[0] && + wild_case_compare(system_charset_info,cs[0]->csname,wild))) + { + if (write_charset(protocol, cs[0])) + goto err; + } + } + send_eof(thd); + DBUG_RETURN(0); +err: + DBUG_RETURN(1); +} + + int mysqld_show(THD *thd, const char *wild, show_var_st *variables, enum enum_var_type value_type, pthread_mutex_t *mutex) { - char buff[8192]; - String packet2(buff,sizeof(buff)); + char buff[1024]; List<Item> field_list; - CONVERT *convert=thd->variables.convert_set; - + Protocol *protocol= thd->protocol; + LEX_STRING null_lex_str; DBUG_ENTER("mysqld_show"); + field_list.push_back(new Item_empty_string("Variable_name",30)); field_list.push_back(new Item_empty_string("Value",256)); - if (send_fields(thd,field_list,1)) + if (protocol->send_fields(&field_list,1)) DBUG_RETURN(1); /* purecov: inspected */ + null_lex_str.str= 0; // For sys_var->value_ptr() + null_lex_str.length= 0; pthread_mutex_lock(mutex); for (; variables->name; variables++) { - if (!(wild && wild[0] && wild_case_compare(variables->name,wild))) + if (!(wild && wild[0] && wild_case_compare(system_charset_info, + variables->name,wild))) { - packet2.length(0); - net_store_data(&packet2,convert,variables->name); + protocol->prepare_for_resend(); + protocol->store(variables->name, system_charset_info); SHOW_TYPE show_type=variables->type; char *value=variables->value; + const char *pos, *end; + long nr; + if (show_type == SHOW_SYS) { show_type= ((sys_var*) value)->type(); - value= (char*) ((sys_var*) value)->value_ptr(thd, value_type); + value= (char*) ((sys_var*) value)->value_ptr(thd, value_type, + &null_lex_str); } + pos= end= buff; switch (show_type) { case SHOW_LONG: case SHOW_LONG_CONST: - net_store_data(&packet2,(uint32) *(ulong*) value); + end= int10_to_str(*(long*) value, buff, 10); break; case SHOW_LONGLONG: - net_store_data(&packet2,(longlong) *(longlong*) value); - break; + end= longlong10_to_str(*(longlong*) value, buff, 10); + break; case SHOW_HA_ROWS: - net_store_data(&packet2,(longlong) *(ha_rows*) value); + end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10); break; case SHOW_BOOL: - net_store_data(&packet2,(ulong) *(bool*) value ? "ON" : "OFF"); + end= strmov(buff, *(bool*) value ? "ON" : "OFF"); break; case SHOW_MY_BOOL: - net_store_data(&packet2,(ulong) *(my_bool*) value ? "ON" : "OFF"); + end= strmov(buff, *(my_bool*) value ? "ON" : "OFF"); break; case SHOW_INT_CONST: case SHOW_INT: - net_store_data(&packet2,(uint32) *(int*) value); + end= int10_to_str((long) *(uint32*) value, buff, 10); break; case SHOW_HAVE: { SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value; - net_store_data(&packet2, (tmp == SHOW_OPTION_NO ? "NO" : - tmp == SHOW_OPTION_YES ? "YES" : - "DISABLED")); + pos= show_comp_option_name[(int) tmp]; + end= strend(pos); break; } case SHOW_CHAR: - net_store_data(&packet2,convert, value); + { + if (!(pos= value)) + pos= ""; + end= strend(pos); break; + } case SHOW_STARTTIME: - net_store_data(&packet2,(uint32) (thd->query_start() - start_time)); + nr= (long) (thd->query_start() - start_time); + end= int10_to_str(nr, buff, 10); break; case SHOW_QUESTION: - net_store_data(&packet2,(uint32) thd->query_id); + end= int10_to_str((long) thd->query_id, buff, 10); break; +#ifdef HAVE_REPLICATION case SHOW_RPL_STATUS: - net_store_data(&packet2, rpl_status_type[(int)rpl_status]); + end= strmov(buff, rpl_status_type[(int)rpl_status]); break; -#ifdef HAVE_REPLICATION case SHOW_SLAVE_RUNNING: { pthread_mutex_lock(&LOCK_active_mi); - net_store_data(&packet2, (active_mi->slave_running && - active_mi->rli.slave_running) - ? "ON" : "OFF"); + end= strmov(buff, (active_mi->slave_running && + active_mi->rli.slave_running) ? "ON" : "OFF"); pthread_mutex_unlock(&LOCK_active_mi); break; } -#endif +#endif /* HAVE_REPLICATION */ case SHOW_OPENTABLES: - net_store_data(&packet2,(uint32) cached_tables()); + end= int10_to_str((long) cached_tables(), buff, 10); break; case SHOW_CHAR_PTR: { - value= *(char**) value; - net_store_data(&packet2,convert, value ? value : ""); - break; + if (!(pos= *(char**) value)) + pos= ""; + end= strend(pos); + break; } #ifdef HAVE_OPENSSL /* First group - functions relying on CTX */ case SHOW_SSL_CTX_SESS_ACCEPT: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_accept(ssl_acceptor_fd-> + ssl_context)), + buff, 10); break; case SHOW_SSL_CTX_SESS_ACCEPT_GOOD: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_accept_good(ssl_acceptor_fd-> + ssl_context)), + buff, 10); break; case SHOW_SSL_CTX_SESS_CONNECT_GOOD: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_connect_good(ssl_acceptor_fd-> + ssl_context)), + buff, 10); break; case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context)), + buff, 10); break; case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context)), + buff, 10); break; case SHOW_SSL_CTX_SESS_CB_HITS: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_cb_hits(ssl_acceptor_fd-> + ssl_context)), + buff, 10); break; case SHOW_SSL_CTX_SESS_HITS: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_hits(ssl_acceptor_fd-> + ssl_context)), + buff, 10); break; case SHOW_SSL_CTX_SESS_CACHE_FULL: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_cache_full(ssl_acceptor_fd-> + ssl_context)), + buff, 10); break; case SHOW_SSL_CTX_SESS_MISSES: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_misses(ssl_acceptor_fd-> + ssl_context)), + buff, 10); break; case SHOW_SSL_CTX_SESS_TIMEOUTS: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context)), + buff,10); break; case SHOW_SSL_CTX_SESS_NUMBER: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context)), + buff,10); break; case SHOW_SSL_CTX_SESS_CONNECT: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)), + buff,10); break; case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context)), + buff,10); break; case SHOW_SSL_CTX_GET_VERIFY_MODE: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)), + buff,10); break; case SHOW_SSL_CTX_GET_VERIFY_DEPTH: - net_store_data(&packet2,(uint32) - (!ssl_acceptor_fd ? 0 : - SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context))); + end= int10_to_str((long) (!ssl_acceptor_fd ? 0 : + SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)), + buff,10); break; case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE: if (!ssl_acceptor_fd) { - net_store_data(&packet2,"NONE" ); + pos= "NONE"; + end= pos+4; break; } switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context)) { case SSL_SESS_CACHE_OFF: - net_store_data(&packet2,"OFF" ); + pos= "OFF"; break; case SSL_SESS_CACHE_CLIENT: - net_store_data(&packet2,"CLIENT" ); + pos= "CLIENT"; break; case SSL_SESS_CACHE_SERVER: - net_store_data(&packet2,"SERVER" ); + pos= "SERVER"; break; case SSL_SESS_CACHE_BOTH: - net_store_data(&packet2,"BOTH" ); + pos= "BOTH"; break; case SSL_SESS_CACHE_NO_AUTO_CLEAR: - net_store_data(&packet2,"NO_AUTO_CLEAR" ); + pos= "NO_AUTO_CLEAR"; break; case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP: - net_store_data(&packet2,"NO_INTERNAL_LOOKUP" ); + pos= "NO_INTERNAL_LOOKUP"; break; default: - net_store_data(&packet2,"Unknown"); + pos= "Unknown"; break; } + end= strend(pos); break; /* First group - functions relying on SSL */ case SHOW_SSL_GET_VERSION: - net_store_data(&packet2, thd->net.vio->ssl_arg ? - SSL_get_version((SSL*) thd->net.vio->ssl_arg) : ""); + pos= (thd->net.vio->ssl_arg ? + SSL_get_version((SSL*) thd->net.vio->ssl_arg) : ""); + end= strend(pos); break; case SHOW_SSL_SESSION_REUSED: - net_store_data(&packet2,(uint32) (thd->net.vio->ssl_arg ? - SSL_session_reused((SSL*) thd->net.vio->ssl_arg) : 0)); + end= int10_to_str((long) (thd->net.vio->ssl_arg ? + SSL_session_reused((SSL*) thd->net.vio-> + ssl_arg) : + 0), + buff, 10); break; case SHOW_SSL_GET_DEFAULT_TIMEOUT: - net_store_data(&packet2,(uint32) (thd->net.vio->ssl_arg ? - SSL_get_default_timeout((SSL*) thd->net.vio->ssl_arg) : - 0)); + end= int10_to_str((long) (thd->net.vio->ssl_arg ? + SSL_get_default_timeout((SSL*) thd->net.vio-> + ssl_arg) : + 0), + buff, 10); break; case SHOW_SSL_GET_VERIFY_MODE: - net_store_data(&packet2,(uint32) (thd->net.vio->ssl_arg ? - SSL_get_verify_mode((SSL*) thd->net.vio->ssl_arg):0)); + end= int10_to_str((long) (thd->net.vio->ssl_arg ? + SSL_get_verify_mode((SSL*) thd->net.vio-> + ssl_arg): + 0), + buff, 10); break; case SHOW_SSL_GET_VERIFY_DEPTH: - net_store_data(&packet2,(uint32) (thd->net.vio->ssl_arg ? - SSL_get_verify_depth((SSL*) thd->net.vio->ssl_arg):0)); + end= int10_to_str((long) (thd->net.vio->ssl_arg ? + SSL_get_verify_depth((SSL*) thd->net.vio-> + ssl_arg): + 0), + buff, 10); break; case SHOW_SSL_GET_CIPHER: - net_store_data(&packet2, thd->net.vio->ssl_arg ? - SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : ""); + pos= (thd->net.vio->ssl_arg ? + SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : "" ); + end= strend(pos); break; case SHOW_SSL_GET_CIPHER_LIST: if (thd->net.vio->ssl_arg) { - char buf[1024], *pos; - pos=buf; + char *to= buff; for (int i=0 ; i++ ;) { - const char *p=SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i); + const char *p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i); if (p == NULL) break; - pos=strmov(pos, p); - *pos++= ':'; + to= strmov(to, p); + *to++= ':'; } - if (pos != buf) - pos--; // Remove last ':' - *pos=0; - net_store_data(&packet2, buf); + if (to != buff) + to--; // Remove last ':' + end= to; } - else - net_store_data(&packet2, ""); break; #endif /* HAVE_OPENSSL */ + case SHOW_KEY_CACHE_LONG: + case SHOW_KEY_CACHE_CONST_LONG: + value= (value-(char*) &dflt_key_cache_var)+ (char*) sql_key_cache; + end= int10_to_str(*(long*) value, buff, 10); + break; case SHOW_UNDEF: // Show never happen case SHOW_SYS: - net_store_data(&packet2, ""); // Safety + break; // Return empty string + default: break; } - if (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length())) + if (protocol->store(pos, (uint32) (end - pos), system_charset_info) || + protocol->write()) goto err; /* purecov: inspected */ } } pthread_mutex_unlock(mutex); - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); err: |