sql_show.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:67k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000-2004 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /* Function with list databases, tables or fields */
  14. #include "mysql_priv.h"
  15. #include "sql_select.h"                         // For select_describe
  16. #include "repl_failsafe.h"
  17. #include <my_dir.h>
  18. #ifdef HAVE_BERKELEY_DB
  19. #include "ha_berkeley.h" // For berkeley_show_logs
  20. #endif
  21. static const char *grant_names[]={
  22.   "select","insert","update","delete","create","drop","reload","shutdown",
  23.   "process","file","grant","references","index","alter"};
  24. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  25. static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
  26.                                "grant_types",
  27.                                grant_names, NULL};
  28. #endif
  29. static int
  30. store_create_info(THD *thd, TABLE *table, String *packet);
  31. /*
  32.   Report list of databases
  33.   A database is a directory in the mysql_data_home directory
  34. */
  35. int
  36. mysqld_show_dbs(THD *thd,const char *wild)
  37. {
  38.   Item_string *field=new Item_string("",0,thd->charset());
  39.   List<Item> field_list;
  40.   char *end;
  41.   List<char> files;
  42.   char *file_name;
  43.   Protocol *protocol= thd->protocol;
  44.   DBUG_ENTER("mysqld_show_dbs");
  45.   field->name=(char*) thd->alloc(20+ (wild ? (uint) strlen(wild)+4: 0));
  46.   field->max_length=NAME_LEN;
  47.   end=strmov(field->name,"Database");
  48.   if (wild && wild[0])
  49.     strxmov(end," (",wild,")",NullS);
  50.   field_list.push_back(field);
  51.   if (protocol->send_fields(&field_list,1))
  52.     DBUG_RETURN(1);
  53.   if (mysql_find_files(thd,&files,NullS,mysql_data_home,wild,1))
  54.     DBUG_RETURN(1);
  55.   List_iterator_fast<char> it(files);
  56.   while ((file_name=it++))
  57.   {
  58. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  59.     if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
  60. acl_get(thd->host, thd->ip, thd->priv_user, file_name,0) ||
  61. (grant_option && !check_grant_db(thd, file_name)))
  62. #endif
  63.     {
  64.       protocol->prepare_for_resend();
  65.       protocol->store(file_name, system_charset_info);
  66.       if (protocol->write())
  67. DBUG_RETURN(-1);
  68.     }
  69.   }
  70.   send_eof(thd);
  71.   DBUG_RETURN(0);
  72. }
  73. /***************************************************************************
  74.   List all open tables in a database
  75. ***************************************************************************/
  76. int mysqld_show_open_tables(THD *thd,const char *wild)
  77. {
  78.   List<Item> field_list;
  79.   OPEN_TABLE_LIST *open_list;
  80.   Protocol *protocol= thd->protocol;
  81.   DBUG_ENTER("mysqld_show_open_tables");
  82.   field_list.push_back(new Item_empty_string("Database",NAME_LEN));
  83.   field_list.push_back(new Item_empty_string("Table",NAME_LEN));
  84.   field_list.push_back(new Item_return_int("In_use", 1, MYSQL_TYPE_TINY));
  85.   field_list.push_back(new Item_return_int("Name_locked", 4, MYSQL_TYPE_TINY));
  86.   if (protocol->send_fields(&field_list,1))
  87.     DBUG_RETURN(1);
  88.   if (!(open_list=list_open_tables(thd,wild)) && thd->is_fatal_error)
  89.     DBUG_RETURN(-1);
  90.   for (; open_list ; open_list=open_list->next)
  91.   {
  92.     protocol->prepare_for_resend();
  93.     protocol->store(open_list->db, system_charset_info);
  94.     protocol->store(open_list->table, system_charset_info);
  95.     protocol->store_tiny((longlong) open_list->in_use);
  96.     protocol->store_tiny((longlong) open_list->locked);
  97.     if (protocol->write())
  98.     {
  99.       DBUG_RETURN(-1);
  100.     }
  101.   }
  102.   send_eof(thd);
  103.   DBUG_RETURN(0);
  104. }
  105. /***************************************************************************
  106. ** List all tables in a database (fast version)
  107. ** A table is a .frm file in the current databasedir
  108. ***************************************************************************/
  109. int mysqld_show_tables(THD *thd,const char *db,const char *wild)
  110. {
  111.   Item_string *field=new Item_string("",0,thd->charset());
  112.   List<Item> field_list;
  113.   char path[FN_LEN],*end;
  114.   List<char> files;
  115.   char *file_name;
  116.   Protocol *protocol= thd->protocol;
  117.   DBUG_ENTER("mysqld_show_tables");
  118.   field->name=(char*) thd->alloc(20+(uint) strlen(db)+
  119.  (wild ? (uint) strlen(wild)+4:0));
  120.   end=strxmov(field->name,"Tables_in_",db,NullS);
  121.   if (wild && wild[0])
  122.     strxmov(end," (",wild,")",NullS);
  123.   field->max_length=NAME_LEN;
  124.   (void) sprintf(path,"%s/%s",mysql_data_home,db);
  125.   (void) unpack_dirname(path,path);
  126.   field_list.push_back(field);
  127.   if (protocol->send_fields(&field_list,1))
  128.     DBUG_RETURN(1);
  129.   if (mysql_find_files(thd,&files,db,path,wild,0))
  130.     DBUG_RETURN(-1);
  131.   List_iterator_fast<char> it(files);
  132.   while ((file_name=it++))
  133.   {
  134.     protocol->prepare_for_resend();
  135.     protocol->store(file_name, system_charset_info);
  136.     if (protocol->write())
  137.       DBUG_RETURN(-1);
  138.   }
  139.   send_eof(thd);
  140.   DBUG_RETURN(0);
  141. }
  142. /***************************************************************************
  143. ** List all table types supported 
  144. ***************************************************************************/
  145. int mysqld_show_storage_engines(THD *thd)
  146. {
  147.   List<Item> field_list;
  148.   Protocol *protocol= thd->protocol;
  149.   DBUG_ENTER("mysqld_show_storage_engines");
  150.   field_list.push_back(new Item_empty_string("Engine",10));
  151.   field_list.push_back(new Item_empty_string("Support",10));
  152.   field_list.push_back(new Item_empty_string("Comment",80));
  153.   if (protocol->send_fields(&field_list,1))
  154.     DBUG_RETURN(1);
  155.   const char *default_type_name= 
  156.     ha_get_storage_engine((enum db_type)thd->variables.table_type);
  157.   show_table_type_st *types;
  158.   for (types= sys_table_types; types->type; types++)
  159.   {
  160.     protocol->prepare_for_resend();
  161.     protocol->store(types->type, system_charset_info);
  162.     const char *option_name= show_comp_option_name[(int) *types->value];
  163.     if (*types->value == SHOW_OPTION_YES &&
  164. !my_strcasecmp(system_charset_info, default_type_name, types->type))
  165.       option_name= "DEFAULT";
  166.     protocol->store(option_name, system_charset_info);
  167.     protocol->store(types->comment, system_charset_info);
  168.     if (protocol->write())
  169.       DBUG_RETURN(-1);
  170.   }
  171.   send_eof(thd);
  172.   DBUG_RETURN(0);
  173. }
  174. /***************************************************************************
  175.  List all privileges supported
  176. ***************************************************************************/
  177. struct show_privileges_st {
  178.   const char *privilege;
  179.   const char *context;
  180.   const char *comment;
  181. };
  182. static struct show_privileges_st sys_privileges[]=
  183. {
  184.   {"Alter", "Tables",  "To alter the table"},
  185.   {"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"},
  186.   {"Create", "Databases,Tables,Indexes",  "To create new databases and tables"},
  187.   {"Delete", "Tables",  "To delete existing rows"},
  188.   {"Drop", "Databases,Tables", "To drop databases and tables"},
  189.   {"File", "File access on server",   "To read and write files on the server"},
  190.   {"Grant option",  "Databases,Tables", "To give to other users those privileges you possess"},
  191.   {"Index", "Tables",  "To create or drop indexes"},
  192.   {"Insert", "Tables",  "To insert data into tables"},
  193.   {"Lock tables","Databases","To use LOCK TABLES (together with SELECT privilege)"},
  194.   {"Process", "Server Admin", "To view the plain text of currently executing queries"},
  195.   {"References", "Databases,Tables", "To have references on tables"},
  196.   {"Reload", "Server Admin", "To reload or refresh tables, logs and privileges"},
  197.   {"Replication client","Server Admin","To ask where the slave or master servers are"},
  198.   {"Replication slave","Server Admin","To read binary log events from the master"},
  199.   {"Select", "Tables",  "To retrieve rows from table"},
  200.   {"Show databases","Server Admin","To see all databases with SHOW DATABASES"},
  201.   {"Shutdown","Server Admin", "To shutdown the server"},
  202.   {"Super","Server Admin","To use KILL thread, SET GLOBAL, CHANGE MASTER, etc."},
  203.   {"Update", "Tables",  "To update existing rows"},
  204.   {"Usage","Server Admin","No privileges - allow connect only"},
  205.   {NullS, NullS, NullS}
  206. };
  207. int mysqld_show_privileges(THD *thd)
  208. {
  209.   List<Item> field_list;
  210.   Protocol *protocol= thd->protocol;
  211.   DBUG_ENTER("mysqld_show_privileges");
  212.   field_list.push_back(new Item_empty_string("Privilege",10));
  213.   field_list.push_back(new Item_empty_string("Context",15));
  214.   field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
  215.   if (protocol->send_fields(&field_list,1))
  216.     DBUG_RETURN(1);
  217.   show_privileges_st *privilege= sys_privileges;
  218.   for (privilege= sys_privileges; privilege->privilege ; privilege++)
  219.   {
  220.     protocol->prepare_for_resend();
  221.     protocol->store(privilege->privilege, system_charset_info);
  222.     protocol->store(privilege->context, system_charset_info);
  223.     protocol->store(privilege->comment, system_charset_info);
  224.     if (protocol->write())
  225.       DBUG_RETURN(-1);
  226.   }
  227.   send_eof(thd);
  228.   DBUG_RETURN(0);
  229. }
  230. /***************************************************************************
  231.   List all column types
  232. ***************************************************************************/
  233. struct show_column_type_st
  234. {
  235.   const char *type;
  236.   uint size;
  237.   const char *min_value;
  238.   const char *max_value;
  239.   uint precision;
  240.   uint scale;
  241.   const char *nullable;
  242.   const char *auto_increment;
  243.   const char *unsigned_attr;
  244.   const char *zerofill;
  245.   const char *searchable;
  246.   const char *case_sensitivity;
  247.   const char *default_value;
  248.   const char *comment;
  249. };
  250. /* TODO: Add remaning types */
  251. static struct show_column_type_st sys_column_types[]=
  252. {
  253.   {"tinyint",
  254.     1,  "-128",  "127",  0,  0,  "YES",  "YES",
  255.     "NO",   "YES", "YES",  "NO",  "NULL,0",
  256.     "A very small integer"},
  257.   {"tinyint unsigned",
  258.     1,  "0"   ,  "255",  0,  0,  "YES",  "YES",
  259.     "YES",  "YES",  "YES",  "NO",  "NULL,0",
  260.     "A very small integer"},
  261. };
  262. int mysqld_show_column_types(THD *thd)
  263. {
  264.   List<Item> field_list;
  265.   Protocol *protocol= thd->protocol;
  266.   DBUG_ENTER("mysqld_show_column_types");
  267.   field_list.push_back(new Item_empty_string("Type",30));
  268.   field_list.push_back(new Item_int("Size",(longlong) 1,21));
  269.   field_list.push_back(new Item_empty_string("Min_Value",20));
  270.   field_list.push_back(new Item_empty_string("Max_Value",20));
  271.   field_list.push_back(new Item_return_int("Prec", 4, MYSQL_TYPE_SHORT));
  272.   field_list.push_back(new Item_return_int("Scale", 4, MYSQL_TYPE_SHORT));
  273.   field_list.push_back(new Item_empty_string("Nullable",4));
  274.   field_list.push_back(new Item_empty_string("Auto_Increment",4));
  275.   field_list.push_back(new Item_empty_string("Unsigned",4));
  276.   field_list.push_back(new Item_empty_string("Zerofill",4));
  277.   field_list.push_back(new Item_empty_string("Searchable",4));
  278.   field_list.push_back(new Item_empty_string("Case_Sensitive",4));
  279.   field_list.push_back(new Item_empty_string("Default",NAME_LEN));
  280.   field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
  281.   if (protocol->send_fields(&field_list,1))
  282.     DBUG_RETURN(1);
  283.   /* TODO: Change the loop to not use 'i' */
  284.   for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++)
  285.   {
  286.     protocol->prepare_for_resend();
  287.     protocol->store(sys_column_types[i].type, system_charset_info);
  288.     protocol->store((ulonglong) sys_column_types[i].size);
  289.     protocol->store(sys_column_types[i].min_value, system_charset_info);
  290.     protocol->store(sys_column_types[i].max_value, system_charset_info);
  291.     protocol->store_short((longlong) sys_column_types[i].precision);
  292.     protocol->store_short((longlong) sys_column_types[i].scale);
  293.     protocol->store(sys_column_types[i].nullable, system_charset_info);
  294.     protocol->store(sys_column_types[i].auto_increment, system_charset_info);
  295.     protocol->store(sys_column_types[i].unsigned_attr, system_charset_info);
  296.     protocol->store(sys_column_types[i].zerofill, system_charset_info);
  297.     protocol->store(sys_column_types[i].searchable, system_charset_info);
  298.     protocol->store(sys_column_types[i].case_sensitivity, system_charset_info);
  299.     protocol->store(sys_column_types[i].default_value, system_charset_info);
  300.     protocol->store(sys_column_types[i].comment, system_charset_info);
  301.     if (protocol->write())
  302.       DBUG_RETURN(-1);
  303.   }
  304.   send_eof(thd);
  305.   DBUG_RETURN(0);
  306. }
  307. int
  308. mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
  309.                  const char *wild, bool dir)
  310. {
  311.   uint i;
  312.   char *ext;
  313.   MY_DIR *dirp;
  314.   FILEINFO *file;
  315. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  316.   uint col_access=thd->col_access;
  317. #endif
  318.   TABLE_LIST table_list;
  319.   DBUG_ENTER("mysql_find_files");
  320.   if (wild && !wild[0])
  321.     wild=0;
  322.   bzero((char*) &table_list,sizeof(table_list));
  323.   if (!(dirp = my_dir(path,MYF(MY_WME | (dir ? MY_WANT_STAT : 0)))))
  324.     DBUG_RETURN(-1);
  325.   for (i=0 ; i < (uint) dirp->number_off_files  ; i++)
  326.   {
  327.     file=dirp->dir_entry+i;
  328.     if (dir)
  329.     {                                           /* Return databases */
  330. #ifdef USE_SYMDIR
  331.       char *ext;
  332.       char buff[FN_REFLEN];
  333.       if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym"))
  334.       {
  335. /* Only show the sym file if it points to a directory */
  336. char *end;
  337.         *ext=0;                                 /* Remove extension */
  338. unpack_dirname(buff, file->name);
  339. end= strend(buff);
  340. if (end != buff && end[-1] == FN_LIBCHAR)
  341.   end[-1]= 0; // Remove end FN_LIBCHAR
  342.         if (!my_stat(buff, file->mystat, MYF(0)))
  343.                continue;
  344.        }
  345. #endif
  346.         if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat->st_mode) ||
  347.             (wild && wild_compare(file->name,wild,0)))
  348.           continue;
  349.     }
  350.     else
  351.     {
  352.         // Return only .frm files which aren't temp files.
  353.       if (my_strcasecmp(system_charset_info, ext=fn_ext(file->name),reg_ext) ||
  354.           is_prefix(file->name,tmp_file_prefix))
  355.         continue;
  356.       *ext=0;
  357.       if (wild)
  358.       {
  359. if (lower_case_table_names)
  360. {
  361.   if (wild_case_compare(files_charset_info, file->name, wild))
  362.     continue;
  363. }
  364. else if (wild_compare(file->name,wild,0))
  365.   continue;
  366.       }
  367.     }
  368. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  369.     /* Don't show tables where we don't have any privileges */
  370.     if (db && !(col_access & TABLE_ACLS))
  371.     {
  372.       table_list.db= (char*) db;
  373.       table_list.real_name=file->name;
  374.       table_list.grant.privilege=col_access;
  375.       if (check_grant(thd, TABLE_ACLS, &table_list, 1, UINT_MAX, 1))
  376.         continue;
  377.     }
  378. #endif
  379.     if (files->push_back(thd->strdup(file->name)))
  380.     {
  381.       my_dirend(dirp);
  382.       DBUG_RETURN(-1);
  383.     }
  384.   }
  385.   DBUG_PRINT("info",("found: %d files", files->elements));
  386.   my_dirend(dirp);
  387.   VOID(ha_find_files(thd,db,path,wild,dir,files));
  388.   DBUG_RETURN(0);
  389. }
  390. /***************************************************************************
  391.  Extended version of mysqld_show_tables
  392. ***************************************************************************/
  393. int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
  394. {
  395.   Item *item;
  396.   List<char> files;
  397.   List<Item> field_list;
  398.   char path[FN_LEN];
  399.   char *file_name;
  400.   TABLE *table;
  401.   Protocol *protocol= thd->protocol;
  402.   TIME time;
  403.   int res= 0;
  404.   DBUG_ENTER("mysqld_extend_show_tables");
  405.   (void) sprintf(path,"%s/%s",mysql_data_home,db);
  406.   (void) unpack_dirname(path,path);
  407.   field_list.push_back(item=new Item_empty_string("Name",NAME_LEN));
  408.   field_list.push_back(item=new Item_empty_string("Engine",10));
  409.   item->maybe_null=1;
  410.   field_list.push_back(item=new Item_int("Version", (longlong) 0, 21));
  411.   item->maybe_null=1;
  412.   field_list.push_back(item=new Item_empty_string("Row_format",10));
  413.   item->maybe_null=1;
  414.   field_list.push_back(item=new Item_int("Rows",(longlong) 1,21));
  415.   item->maybe_null=1;
  416.   field_list.push_back(item=new Item_int("Avg_row_length",(int32) 0,21));
  417.   item->maybe_null=1;
  418.   field_list.push_back(item=new Item_int("Data_length",(longlong) 1,21));
  419.   item->maybe_null=1;
  420.   field_list.push_back(item=new Item_int("Max_data_length",(longlong) 1,21));
  421.   item->maybe_null=1;
  422.   field_list.push_back(item=new Item_int("Index_length",(longlong) 1,21));
  423.   item->maybe_null=1;
  424.   field_list.push_back(item=new Item_int("Data_free",(longlong) 1,21));
  425.   item->maybe_null=1;
  426.   field_list.push_back(item=new Item_int("Auto_increment",(longlong) 1,21));
  427.   item->maybe_null=1;
  428.   field_list.push_back(item=new Item_datetime("Create_time"));
  429.   item->maybe_null=1;
  430.   field_list.push_back(item=new Item_datetime("Update_time"));
  431.   item->maybe_null=1;
  432.   field_list.push_back(item=new Item_datetime("Check_time"));
  433.   item->maybe_null=1;
  434.   field_list.push_back(item=new Item_empty_string("Collation",32));
  435.   item->maybe_null=1;
  436.   field_list.push_back(item=new Item_int("Checksum",(longlong) 1,21));
  437.   item->maybe_null=1;
  438.   field_list.push_back(item=new Item_empty_string("Create_options",255));
  439.   item->maybe_null=1;
  440.   field_list.push_back(item=new Item_empty_string("Comment",80));
  441.   item->maybe_null=1;
  442.   if (protocol->send_fields(&field_list,1))
  443.     DBUG_RETURN(1);
  444.   if (mysql_find_files(thd,&files,db,path,wild,0))
  445.     DBUG_RETURN(-1);
  446.   List_iterator_fast<char> it(files);
  447.   while ((file_name=it++))
  448.   {
  449.     TABLE_LIST table_list;
  450.     bzero((char*) &table_list,sizeof(table_list));
  451.     protocol->prepare_for_resend();
  452.     protocol->store(file_name, system_charset_info);
  453.     table_list.db=(char*) db;
  454.     table_list.real_name= table_list.alias= file_name;
  455.     if (lower_case_table_names)
  456.       my_casedn_str(files_charset_info, file_name);
  457.     if (!(table = open_ltable(thd, &table_list, TL_READ)))
  458.     {
  459.       for (uint i=2 ; i < field_list.elements ; i++)
  460.         protocol->store_null();
  461.       // Send error to Comment field
  462.       protocol->store(thd->net.last_error, system_charset_info);
  463.       thd->clear_error();
  464.     }
  465.     else
  466.     {
  467.       const char *str;
  468.       handler *file=table->file;
  469.       file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK);
  470.       protocol->store(file->table_type(), system_charset_info);
  471.       protocol->store((ulonglong) table->frm_version);
  472.       str= ((table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ?
  473.     "Compressed" :
  474.     (table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
  475.     "Dynamic" : "Fixed");
  476.       protocol->store(str, system_charset_info);
  477.       protocol->store((ulonglong) file->records);
  478.       protocol->store((ulonglong) file->mean_rec_length);
  479.       protocol->store((ulonglong) file->data_file_length);
  480.       if (file->max_data_file_length)
  481.         protocol->store((ulonglong) file->max_data_file_length);
  482.       else
  483.         protocol->store_null();
  484.       protocol->store((ulonglong) file->index_file_length);
  485.       protocol->store((ulonglong) file->delete_length);
  486.       if (table->found_next_number_field)
  487.       {
  488.         table->next_number_field=table->found_next_number_field;
  489.         table->next_number_field->reset();
  490.         file->update_auto_increment();
  491.         protocol->store(table->next_number_field->val_int());
  492.         table->next_number_field=0;
  493.       }
  494.       else
  495.         protocol->store_null();
  496.       if (!file->create_time)
  497.         protocol->store_null();
  498.       else
  499.       {
  500.         thd->variables.time_zone->gmt_sec_to_TIME(&time, file->create_time);
  501.         protocol->store(&time);
  502.       }
  503.       if (!file->update_time)
  504.         protocol->store_null();
  505.       else
  506.       {
  507.         thd->variables.time_zone->gmt_sec_to_TIME(&time, file->update_time);
  508.         protocol->store(&time);
  509.       }
  510.       if (!file->check_time)
  511.         protocol->store_null();
  512.       else
  513.       {
  514.         thd->variables.time_zone->gmt_sec_to_TIME(&time, file->check_time);
  515.         protocol->store(&time);
  516.       }
  517.       str= (table->table_charset ? table->table_charset->name : "default");
  518.       protocol->store(str, system_charset_info);
  519.       if (file->table_flags() & HA_HAS_CHECKSUM)
  520.         protocol->store((ulonglong)file->checksum());
  521.       else
  522.         protocol->store_null(); // Checksum
  523.       {
  524.         char option_buff[350],*ptr;
  525.         ptr=option_buff;
  526.         if (table->min_rows)
  527.         {
  528.           ptr=strmov(ptr," min_rows=");
  529.           ptr=longlong10_to_str(table->min_rows,ptr,10);
  530.         }
  531.         if (table->max_rows)
  532.         {
  533.           ptr=strmov(ptr," max_rows=");
  534.           ptr=longlong10_to_str(table->max_rows,ptr,10);
  535.         }
  536.         if (table->avg_row_length)
  537.         {
  538.           ptr=strmov(ptr," avg_row_length=");
  539.           ptr=longlong10_to_str(table->avg_row_length,ptr,10);
  540.         }
  541.         if (table->db_create_options & HA_OPTION_PACK_KEYS)
  542.           ptr=strmov(ptr," pack_keys=1");
  543.         if (table->db_create_options & HA_OPTION_NO_PACK_KEYS)
  544.           ptr=strmov(ptr," pack_keys=0");
  545.         if (table->db_create_options & HA_OPTION_CHECKSUM)
  546.           ptr=strmov(ptr," checksum=1");
  547.         if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
  548.           ptr=strmov(ptr," delay_key_write=1");
  549.         if (table->row_type != ROW_TYPE_DEFAULT)
  550.           ptr=strxmov(ptr, " row_format=", ha_row_type[(uint) table->row_type],
  551.                       NullS);
  552.         if (file->raid_type)
  553.         {
  554.           char buff[100];
  555.           sprintf(buff," raid_type=%s raid_chunks=%d raid_chunksize=%ld",
  556.                   my_raid_type(file->raid_type), file->raid_chunks, file->raid_chunksize/RAID_BLOCK_SIZE);
  557.           ptr=strmov(ptr,buff);
  558.         }
  559.         protocol->store(option_buff+1,
  560. (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1)
  561. , system_charset_info);
  562.       }
  563.       {
  564. char *comment=table->file->update_table_comment(table->comment);
  565. protocol->store(comment, system_charset_info);
  566. if (comment != table->comment)
  567.   my_free(comment,MYF(0));
  568.       }
  569.       close_thread_tables(thd,0);
  570.     }
  571.     if (protocol->write())
  572.     {
  573.       res= -1;
  574.       break;
  575.     }
  576.   }
  577.   thd->insert_id(0);
  578.   if (!res)
  579.     send_eof(thd);
  580.   DBUG_RETURN(res);
  581. }
  582. /***************************************************************************
  583. ** List all columns in a table_list->real_name
  584. ***************************************************************************/
  585. int
  586. mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
  587.    bool verbose)
  588. {
  589.   TABLE *table;
  590.   handler *file;
  591.   char tmp[MAX_FIELD_WIDTH];
  592.   char tmp1[MAX_FIELD_WIDTH];
  593.   Item *item;
  594.   Protocol *protocol= thd->protocol;
  595.   DBUG_ENTER("mysqld_show_fields");
  596.   DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
  597.                       table_list->real_name));
  598.   if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  599.   {
  600.     send_error(thd);
  601.     DBUG_RETURN(1);
  602.   }
  603.   file=table->file;
  604.   file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
  605. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  606.   (void) get_table_grant(thd, table_list);
  607. #endif
  608.   List<Item> field_list;
  609.   field_list.push_back(new Item_empty_string("Field",NAME_LEN));
  610.   field_list.push_back(new Item_empty_string("Type", 40));
  611.   if (verbose)
  612.     field_list.push_back(new Item_empty_string("Collation",40));
  613.   field_list.push_back(new Item_empty_string("Null",1));
  614.   field_list.push_back(new Item_empty_string("Key",3));
  615.   field_list.push_back(item=new Item_empty_string("Default",NAME_LEN));
  616.   item->maybe_null=1;
  617.   field_list.push_back(new Item_empty_string("Extra",20));
  618.   if (verbose)
  619.   {
  620.     field_list.push_back(new Item_empty_string("Privileges",80));
  621.     field_list.push_back(new Item_empty_string("Comment",255));
  622.   }
  623.         // Send first number of fields and records
  624.   if (protocol->send_records_num(&field_list, (ulonglong)file->records) ||
  625.       protocol->send_fields(&field_list,0))
  626.     DBUG_RETURN(1);
  627.   restore_record(table,default_values);      // Get empty record
  628.   Field **ptr,*field;
  629.   for (ptr=table->field; (field= *ptr) ; ptr++)
  630.   {
  631.     if (!wild || !wild[0] || 
  632.         !wild_case_compare(system_charset_info, field->field_name,wild))
  633.     {
  634.       {
  635.         byte *pos;
  636.         uint flags=field->flags;
  637.         String type(tmp,sizeof(tmp), system_charset_info);
  638. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  639.         uint col_access;
  640. #endif
  641. protocol->prepare_for_resend();
  642.         protocol->store(field->field_name, system_charset_info);
  643.         field->sql_type(type);
  644.         protocol->store(type.ptr(), type.length(), system_charset_info);
  645. if (verbose)
  646.   protocol->store(field->has_charset() ? field->charset()->name : "NULL",
  647. system_charset_info);
  648.         /*
  649.           Even if TIMESTAMP field can't contain NULL as its value it
  650.           will accept NULL if you will try to insert such value and will
  651.           convert NULL value to current TIMESTAMP. So YES here means
  652.           that NULL is allowed for assignment (but may be won't be
  653.           returned).
  654.         */
  655.         pos=(byte*) ((flags & NOT_NULL_FLAG) &&
  656.                      field->type() != FIELD_TYPE_TIMESTAMP ?
  657.                      "" : "YES");
  658.         protocol->store((const char*) pos, system_charset_info);
  659.         pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
  660.                      (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
  661.                      (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
  662.         protocol->store((char*) pos, system_charset_info);
  663.         if (table->timestamp_field == field &&
  664.             field->unireg_check != Field::TIMESTAMP_UN_FIELD)
  665.         {
  666.           /*
  667.             We have NOW() as default value but we use CURRENT_TIMESTAMP form
  668.             because it is more SQL standard comatible
  669.           */
  670.           protocol->store("CURRENT_TIMESTAMP", system_charset_info);
  671.         }
  672.         else if (field->unireg_check != Field::NEXT_NUMBER &&
  673.                  !field->is_null())
  674.         {                                               // Not null by default
  675.           /*
  676.             Note: we have to convert the default value into
  677.             system_charset_info before sending.
  678.             This is necessary for "SET NAMES binary":
  679.             If the client character set is binary, we want to
  680.             send metadata in UTF8 rather than in the column's
  681.             character set.
  682.             This conversion also makes "SHOW COLUMNS" and
  683.             "SHOW CREATE TABLE" output consistent. Without
  684.             this conversion the default values were displayed
  685.             differently.
  686.           */
  687.           String def(tmp1,sizeof(tmp1), system_charset_info);
  688.           type.set(tmp, sizeof(tmp), field->charset());
  689.           field->val_str(&type);
  690.           uint dummy_errors;
  691.           def.copy(type.ptr(), type.length(), type.charset(), 
  692.                    system_charset_info, &dummy_errors);
  693.           protocol->store(def.ptr(), def.length(), def.charset());
  694.         }
  695.         else if (field->unireg_check == Field::NEXT_NUMBER ||
  696.                  field->maybe_null())
  697.           protocol->store_null();                       // Null as default
  698.         else
  699.           protocol->store("",0, system_charset_info); // empty string
  700.         char *end=tmp;
  701.         if (field->unireg_check == Field::NEXT_NUMBER)
  702.           end=strmov(tmp,"auto_increment");
  703.         protocol->store(tmp,(uint) (end-tmp), system_charset_info);
  704. if (verbose)
  705. {
  706.   /* Add grant options & comments */
  707.   end=tmp;
  708. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  709.   col_access= get_column_grant(thd,table_list,field) & COL_ACLS;
  710.   for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
  711.   {
  712.     if (col_access & 1)
  713.     {
  714.       *end++=',';
  715.       end=strmov(end,grant_types.type_names[bitnr]);
  716.     }
  717.   }
  718. #else
  719.   end=strmov(end,"");
  720. #endif
  721.   protocol->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1),
  722.   system_charset_info);
  723.   protocol->store(field->comment.str, field->comment.length,
  724.   system_charset_info);
  725. }
  726.         if (protocol->write())
  727.           DBUG_RETURN(1);
  728.       }
  729.     }
  730.   }
  731.   send_eof(thd);
  732.   DBUG_RETURN(0);
  733. }
  734. int
  735. mysqld_show_create(THD *thd, TABLE_LIST *table_list)
  736. {
  737.   TABLE *table;
  738.   Protocol *protocol= thd->protocol;
  739.   char buff[2048];
  740.   String buffer(buff, sizeof(buff), system_charset_info);
  741.   DBUG_ENTER("mysqld_show_create");
  742.   DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
  743.                       table_list->real_name));
  744.   /* Only one table for now */
  745.   if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  746.   {
  747.     send_error(thd);
  748.     DBUG_RETURN(1);
  749.   }
  750.   buffer.length(0);
  751.   if (store_create_info(thd, table, &buffer))
  752.     DBUG_RETURN(-1);
  753.   List<Item> field_list;
  754.   field_list.push_back(new Item_empty_string("Table",NAME_LEN));
  755.   // 1024 is for not to confuse old clients
  756.   field_list.push_back(new Item_empty_string("Create Table",
  757.      max(buffer.length(),1024)));
  758.   if (protocol->send_fields(&field_list, 1))
  759.     DBUG_RETURN(1);
  760.   protocol->prepare_for_resend();
  761.   protocol->store(table->table_name, system_charset_info);
  762.   protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
  763.   if (protocol->write())
  764.     DBUG_RETURN(1);
  765.   send_eof(thd);
  766.   DBUG_RETURN(0);
  767. }
  768. int mysqld_show_create_db(THD *thd, char *dbname,
  769.   HA_CREATE_INFO *create_info)
  770. {
  771.   int length;
  772.   char path[FN_REFLEN];
  773.   char buff[2048];
  774.   String buffer(buff, sizeof(buff), system_charset_info);
  775. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  776.   uint db_access;
  777. #endif
  778.   bool found_libchar;
  779.   HA_CREATE_INFO create;
  780.   uint create_options = create_info ? create_info->options : 0;
  781.   Protocol *protocol=thd->protocol;
  782.   DBUG_ENTER("mysql_show_create_db");
  783.   if (check_db_name(dbname))
  784.   {
  785.     net_printf(thd,ER_WRONG_DB_NAME, dbname);
  786.     DBUG_RETURN(1);
  787.   }
  788. #ifndef NO_EMBEDDED_ACCESS_CHECKS
  789.   if (test_all_bits(thd->master_access,DB_ACLS))
  790.     db_access=DB_ACLS;
  791.   else
  792.     db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) |
  793. thd->master_access);
  794.   if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
  795.   {
  796.     net_printf(thd,ER_DBACCESS_DENIED_ERROR,
  797.        thd->priv_user, thd->host_or_ip, dbname);
  798.     mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
  799.     thd->priv_user, thd->host_or_ip, dbname);
  800.     DBUG_RETURN(1);
  801.   }
  802. #endif
  803.   (void) sprintf(path,"%s/%s",mysql_data_home, dbname);
  804.   length=unpack_dirname(path,path); // Convert if not unix
  805.   found_libchar= 0;
  806.   if (length && path[length-1] == FN_LIBCHAR)
  807.   {
  808.     found_libchar= 1;
  809.     path[length-1]=0; // remove ending ''
  810.   }
  811.   if (access(path,F_OK))
  812.   {
  813.     net_printf(thd,ER_BAD_DB_ERROR,dbname);
  814.     DBUG_RETURN(1);
  815.   }
  816.   if (found_libchar)
  817.     path[length-1]= FN_LIBCHAR;
  818.   strmov(path+length, MY_DB_OPT_FILE);
  819.   load_db_opt(thd, path, &create);
  820.   List<Item> field_list;
  821.   field_list.push_back(new Item_empty_string("Database",NAME_LEN));
  822.   field_list.push_back(new Item_empty_string("Create Database",1024));
  823.   if (protocol->send_fields(&field_list,1))
  824.     DBUG_RETURN(1);
  825.   protocol->prepare_for_resend();
  826.   protocol->store(dbname, strlen(dbname), system_charset_info);
  827.   buffer.length(0);
  828.   buffer.append("CREATE DATABASE ", 16);
  829.   if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
  830.     buffer.append("/*!32312 IF NOT EXISTS*/ ", 25);
  831.   append_identifier(thd, &buffer, dbname, strlen(dbname));
  832.   if (create.default_table_charset)
  833.   {
  834.     buffer.append(" /*!40100", 9);
  835.     buffer.append(" DEFAULT CHARACTER SET ", 23);
  836.     buffer.append(create.default_table_charset->csname);
  837.     if (!(create.default_table_charset->state & MY_CS_PRIMARY))
  838.     {
  839.       buffer.append(" COLLATE ", 9);
  840.       buffer.append(create.default_table_charset->name);
  841.     }
  842.     buffer.append(" */", 3);
  843.   }
  844.   protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
  845.   if (protocol->write())
  846.     DBUG_RETURN(1);
  847.   send_eof(thd);
  848.   DBUG_RETURN(0);
  849. }
  850. int
  851. mysqld_show_logs(THD *thd)
  852. {
  853.   List<Item> field_list;
  854.   Protocol *protocol= thd->protocol;
  855.   DBUG_ENTER("mysqld_show_logs");
  856.   field_list.push_back(new Item_empty_string("File",FN_REFLEN));
  857.   field_list.push_back(new Item_empty_string("Type",10));
  858.   field_list.push_back(new Item_empty_string("Status",10));
  859.   if (protocol->send_fields(&field_list,1))
  860.     DBUG_RETURN(1);
  861. #ifdef HAVE_BERKELEY_DB
  862.   if ((have_berkeley_db == SHOW_OPTION_YES) && berkeley_show_logs(protocol))
  863.     DBUG_RETURN(-1);
  864. #endif
  865.   send_eof(thd);
  866.   DBUG_RETURN(0);
  867. }
  868. int
  869. mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
  870. {
  871.   TABLE *table;
  872.   Protocol *protocol= thd->protocol;
  873.   DBUG_ENTER("mysqld_show_keys");
  874.   DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
  875.                       table_list->real_name));
  876.   if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  877.   {
  878.     send_error(thd);
  879.     DBUG_RETURN(1);
  880.   }
  881.   List<Item> field_list;
  882.   Item *item;
  883.   field_list.push_back(new Item_empty_string("Table",NAME_LEN));
  884.   field_list.push_back(new Item_return_int("Non_unique",1, MYSQL_TYPE_TINY));
  885.   field_list.push_back(new Item_empty_string("Key_name",NAME_LEN));
  886.   field_list.push_back(new Item_return_int("Seq_in_index",2, MYSQL_TYPE_TINY));
  887.   field_list.push_back(new Item_empty_string("Column_name",NAME_LEN));
  888.   field_list.push_back(item=new Item_empty_string("Collation",1));
  889.   item->maybe_null=1;
  890.   field_list.push_back(item=new Item_int("Cardinality",0,21));
  891.   item->maybe_null=1;
  892.   field_list.push_back(item=new Item_return_int("Sub_part",3,
  893. MYSQL_TYPE_SHORT));
  894.   item->maybe_null=1;
  895.   field_list.push_back(item=new Item_empty_string("Packed",10));
  896.   item->maybe_null=1;
  897.   field_list.push_back(new Item_empty_string("Null",3));
  898.   field_list.push_back(new Item_empty_string("Index_type",16));
  899.   field_list.push_back(new Item_empty_string("Comment",255));
  900.   item->maybe_null=1;
  901.   if (protocol->send_fields(&field_list,1))
  902.     DBUG_RETURN(1);
  903.   KEY *key_info=table->key_info;
  904.   table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
  905.   for (uint i=0 ; i < table->keys ; i++,key_info++)
  906.   {
  907.     KEY_PART_INFO *key_part= key_info->key_part;
  908.     const char *str;
  909.     for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
  910.     {
  911.       protocol->prepare_for_resend();
  912.       protocol->store(table->table_name, system_charset_info);
  913.       protocol->store_tiny((longlong) ((key_info->flags & HA_NOSAME) ? 0 :1));
  914.       protocol->store(key_info->name, system_charset_info);
  915.       protocol->store_tiny((longlong) (j+1));
  916.       str=(key_part->field ? key_part->field->field_name :
  917.    "?unknown field?");
  918.       protocol->store(str, system_charset_info);
  919.       if (table->file->index_flags(i, j, 0) & HA_READ_ORDER)
  920.         protocol->store(((key_part->key_part_flag & HA_REVERSE_SORT) ?
  921.  "D" : "A"), 1, system_charset_info);
  922.       else
  923.         protocol->store_null(); /* purecov: inspected */
  924.       KEY *key=table->key_info+i;
  925.       if (key->rec_per_key[j])
  926.       {
  927.         ha_rows records=(table->file->records / key->rec_per_key[j]);
  928.         protocol->store((ulonglong) records);
  929.       }
  930.       else
  931.         protocol->store_null();
  932.       /* Check if we have a key part that only uses part of the field */
  933.       if (!(key_info->flags & HA_FULLTEXT) && (!key_part->field ||
  934.           key_part->length != table->field[key_part->fieldnr-1]->key_length()))
  935.         protocol->store_short((longlong) key_part->length / 
  936.                              key_part->field->charset()->mbmaxlen);
  937.       else
  938.         protocol->store_null();
  939.       protocol->store_null();                   // No pack_information yet
  940.       /* Null flag */
  941.       uint flags= key_part->field ? key_part->field->flags : 0;
  942.       char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
  943.       protocol->store((const char*) pos, system_charset_info);
  944.       protocol->store(table->file->index_type(i), system_charset_info);
  945.       /* Comment */
  946.       if (!table->keys_in_use.is_set(i))
  947. protocol->store("disabled",8, system_charset_info);
  948.       else
  949.         protocol->store("", 0, system_charset_info);
  950.       if (protocol->write())
  951.         DBUG_RETURN(1); /* purecov: inspected */
  952.     }
  953.   }
  954.   send_eof(thd);
  955.   DBUG_RETURN(0);
  956. }
  957. /****************************************************************************
  958.   Return only fields for API mysql_list_fields
  959.   Use "show table wildcard" in mysql instead of this
  960. ****************************************************************************/
  961. void
  962. mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
  963. {
  964.   TABLE *table;
  965.   DBUG_ENTER("mysqld_list_fields");
  966.   DBUG_PRINT("enter",("table: %s",table_list->real_name));
  967.   if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  968.   {
  969.     send_error(thd);
  970.     DBUG_VOID_RETURN;
  971.   }
  972.   List<Item> field_list;
  973.   Field **ptr,*field;
  974.   for (ptr=table->field ; (field= *ptr); ptr++)
  975.   {
  976.     if (!wild || !wild[0] || 
  977.         !wild_case_compare(system_charset_info, field->field_name,wild))
  978.       field_list.push_back(new Item_field(field));
  979.   }
  980.   restore_record(table,default_values);              // Get empty record
  981.   if (thd->protocol->send_fields(&field_list,2))
  982.     DBUG_VOID_RETURN;
  983.   thd->protocol->flush();
  984.   DBUG_VOID_RETURN;
  985. }
  986. int
  987. mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
  988. {
  989.   Protocol *protocol= thd->protocol;
  990.   String *packet= protocol->storage_packet();
  991.   DBUG_ENTER("mysqld_dump_create_info");
  992.   DBUG_PRINT("enter",("table: %s",table->real_name));
  993.   protocol->prepare_for_resend();
  994.   if (store_create_info(thd, table, packet))
  995.     DBUG_RETURN(-1);
  996.   if (fd < 0)
  997.   {
  998.     if (protocol->write())
  999.       DBUG_RETURN(-1);
  1000.     protocol->flush();
  1001.   }
  1002.   else
  1003.   {
  1004.     if (my_write(fd, (const byte*) packet->ptr(), packet->length(),
  1005.  MYF(MY_WME)))
  1006.       DBUG_RETURN(-1);
  1007.   }
  1008.   DBUG_RETURN(0);
  1009. }
  1010. /*
  1011.   Go through all character combinations and ensure that sql_lex.cc can
  1012.   parse it as an identifer.
  1013.   SYNOPSIS
  1014.   require_quotes()
  1015.   name attribute name
  1016.   name_length length of name
  1017.   RETURN
  1018.     # Pointer to conflicting character
  1019.     0 No conflicting character
  1020. */
  1021. static const char *require_quotes(const char *name, uint name_length)
  1022. {
  1023.   uint length;
  1024.   const char *end= name + name_length;
  1025.   for ( ; name < end ; name++)
  1026.   {
  1027.     uchar chr= (uchar) *name;
  1028.     length= my_mbcharlen(system_charset_info, chr);
  1029.     if (length == 1 && !system_charset_info->ident_map[chr])
  1030.       return name;
  1031.   }
  1032.   return 0;
  1033. }
  1034. void
  1035. append_identifier(THD *thd, String *packet, const char *name, uint length)
  1036. {
  1037.   const char *name_end;
  1038.   char quote_char;
  1039.   int q= get_quote_char_for_identifier(thd, name, length);
  1040.   if (q == EOF)
  1041.   {
  1042.     packet->append(name, length, system_charset_info);
  1043.     return;
  1044.   }
  1045.   /*
  1046.     The identifier must be quoted as it includes a quote character or
  1047.    it's a keyword
  1048.   */
  1049.   packet->reserve(length*2 + 2);
  1050.   quote_char= (char) q;
  1051.   packet->append(&quote_char, 1, system_charset_info);
  1052.   for (name_end= name+length ; name < name_end ; name+= length)
  1053.   {
  1054.     uchar chr= (uchar) *name;
  1055.     length= my_mbcharlen(system_charset_info, chr);
  1056.     /*
  1057.       my_mbcharlen can retur 0 on a wrong multibyte
  1058.       sequence. It is possible when upgrading from 4.0,
  1059.       and identifier contains some accented characters.
  1060.       The manual says it does not work. So we'll just
  1061.       change length to 1 not to hang in the endless loop.
  1062.     */
  1063.     if (!length)
  1064.       length= 1;
  1065.     if (length == 1 && chr == (uchar) quote_char)
  1066.       packet->append(&quote_char, 1, system_charset_info);
  1067.     packet->append(name, length, packet->charset());
  1068.   }
  1069.   packet->append(&quote_char, 1, system_charset_info);
  1070. }
  1071. /*
  1072.   Get the quote character for displaying an identifier.
  1073.   SYNOPSIS
  1074.     get_quote_char_for_identifier()
  1075.     thd Thread handler
  1076.     name name to quote
  1077.     length length of name
  1078.   IMPLEMENTATION
  1079.     If name is a keyword or includes a special character, then force
  1080.     quoting.
  1081.     Otherwise identifier is quoted only if the option OPTION_QUOTE_SHOW_CREATE
  1082.     is set.
  1083.   RETURN
  1084.     EOF   No quote character is needed
  1085.     #   Quote character
  1086. */
  1087. int get_quote_char_for_identifier(THD *thd, const char *name, uint length)
  1088. {
  1089.   if (!is_keyword(name,length) &&
  1090.       !require_quotes(name, length) &&
  1091.       !(thd->options & OPTION_QUOTE_SHOW_CREATE))
  1092.     return EOF;
  1093.   if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
  1094.     return '"';
  1095.   return '`';
  1096. }
  1097. /* Append directory name (if exists) to CREATE INFO */
  1098. static void append_directory(THD *thd, String *packet, const char *dir_type,
  1099.      const char *filename)
  1100. {
  1101.   if (filename && !(thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
  1102.   {
  1103.     uint length= dirname_length(filename);
  1104.     packet->append(' ');
  1105.     packet->append(dir_type);
  1106.     packet->append(" DIRECTORY='", 12);
  1107. #ifdef __WIN__
  1108.     char *winfilename = thd->memdup(filename, length);
  1109.     for (uint i=0; i < length; i++)
  1110.     if (winfilename[i] == '\')
  1111.     winfilename[i] = '/';
  1112.     packet->append(winfilename, length);
  1113. #else
  1114.     packet->append(filename, length);
  1115. #endif
  1116.     packet->append(''');
  1117.   }
  1118. }
  1119. #define LIST_PROCESS_HOST_LEN 64
  1120. static int
  1121. store_create_info(THD *thd, TABLE *table, String *packet)
  1122. {
  1123.   List<Item> field_list;
  1124.   char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end, *alias;
  1125.   String type(tmp, sizeof(tmp), system_charset_info);
  1126.   Field **ptr,*field;
  1127.   uint primary_key;
  1128.   KEY *key_info;
  1129.   handler *file= table->file;
  1130.   HA_CREATE_INFO create_info;
  1131.   my_bool foreign_db_mode=    (thd->variables.sql_mode & (MODE_POSTGRESQL |
  1132.   MODE_ORACLE |
  1133.   MODE_MSSQL |
  1134.   MODE_DB2 |
  1135.   MODE_MAXDB |
  1136.   MODE_ANSI)) != 0;
  1137.   my_bool limited_mysql_mode= (thd->variables.sql_mode &
  1138.        (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
  1139. MODE_MYSQL40)) != 0;
  1140.   DBUG_ENTER("store_create_info");
  1141.   DBUG_PRINT("enter",("table: %s",table->real_name));
  1142.   restore_record(table,default_values); // Get empty record
  1143.   if (table->tmp_table)
  1144.     packet->append("CREATE TEMPORARY TABLE ", 23);
  1145.   else
  1146.     packet->append("CREATE TABLE ", 13);
  1147.   alias= (lower_case_table_names == 2 ? table->table_name :
  1148.   table->real_name);
  1149.   append_identifier(thd, packet, alias, strlen(alias));
  1150.   packet->append(" (n", 3);
  1151.   for (ptr=table->field ; (field= *ptr); ptr++)
  1152.   {
  1153.     bool has_default;
  1154.     bool has_now_default;
  1155.     uint flags = field->flags;
  1156.     if (ptr != table->field)
  1157.       packet->append(",n", 2);
  1158.     packet->append("  ", 2);
  1159.     append_identifier(thd,packet,field->field_name, strlen(field->field_name));
  1160.     packet->append(' ');
  1161.     // check for surprises from the previous call to Field::sql_type()
  1162.     if (type.ptr() != tmp)
  1163.       type.set(tmp, sizeof(tmp), system_charset_info);
  1164.     else
  1165.       type.set_charset(system_charset_info);
  1166.     field->sql_type(type);
  1167.     packet->append(type.ptr(), type.length(), system_charset_info);
  1168.     if (field->has_charset() && 
  1169.         !(thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)))
  1170.     {
  1171.       if (field->charset() != table->table_charset)
  1172.       {
  1173. packet->append(" character set ", 15);
  1174. packet->append(field->charset()->csname);
  1175.       }
  1176.       /* 
  1177. For string types dump collation name only if 
  1178. collation is not primary for the given charset
  1179.       */
  1180.       if (!(field->charset()->state & MY_CS_PRIMARY))
  1181.       {
  1182. packet->append(" collate ", 9);
  1183. packet->append(field->charset()->name);
  1184.       }
  1185.     }
  1186.     if (flags & NOT_NULL_FLAG)
  1187.       packet->append(" NOT NULL", 9);
  1188.     else if (field->type() == FIELD_TYPE_TIMESTAMP)
  1189.     {
  1190.       /*
  1191.         TIMESTAMP field require explicit NULL flag, because unlike
  1192.         all other fields they are treated as NOT NULL by default.
  1193.       */
  1194.       packet->append(" NULL", 5);
  1195.     }
  1196.     /* 
  1197.       Again we are using CURRENT_TIMESTAMP instead of NOW because it is
  1198.       more standard 
  1199.     */
  1200.     has_now_default= table->timestamp_field == field && 
  1201.                      field->unireg_check != Field::TIMESTAMP_UN_FIELD;
  1202.     
  1203.     has_default= (field->type() != FIELD_TYPE_BLOB &&
  1204.   field->unireg_check != Field::NEXT_NUMBER &&
  1205.                   !((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
  1206.                     has_now_default));
  1207.     if (has_default)
  1208.     {
  1209.       packet->append(" default ", 9);
  1210.       if (has_now_default)
  1211.         packet->append("CURRENT_TIMESTAMP",17);
  1212.       else if (!field->is_null())
  1213.       {                                             // Not null by default
  1214.         type.set(tmp, sizeof(tmp), field->charset());
  1215.         field->val_str(&type);
  1216. if (type.length())
  1217. {
  1218.   String def_val;
  1219.           uint dummy_errors;
  1220.   /* convert to system_charset_info == utf8 */
  1221.   def_val.copy(type.ptr(), type.length(), field->charset(),
  1222.        system_charset_info, &dummy_errors);
  1223.           append_unescaped(packet, def_val.ptr(), def_val.length());
  1224. }
  1225.         else
  1226.   packet->append("''",2);
  1227.       }
  1228.       else if (field->maybe_null())
  1229.         packet->append("NULL", 4);                    // Null as default
  1230.       else
  1231.         packet->append(tmp);
  1232.     }
  1233.     if (!(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS) &&
  1234.         table->timestamp_field == field && 
  1235.         field->unireg_check != Field::TIMESTAMP_DN_FIELD)
  1236.       packet->append(" on update CURRENT_TIMESTAMP",28);
  1237.     if (field->unireg_check == Field::NEXT_NUMBER && 
  1238.         !(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS))
  1239.       packet->append(" auto_increment", 15 );
  1240.     if (field->comment.length)
  1241.     {
  1242.       packet->append(" COMMENT ",9);
  1243.       append_unescaped(packet, field->comment.str, field->comment.length);
  1244.     }
  1245.   }
  1246.   key_info= table->key_info;
  1247.   file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
  1248.   bzero((char*) &create_info, sizeof(create_info));
  1249.   file->update_create_info(&create_info);
  1250.   primary_key= table->primary_key;
  1251.   for (uint i=0 ; i < table->keys ; i++,key_info++)
  1252.   {
  1253.     KEY_PART_INFO *key_part= key_info->key_part;
  1254.     bool found_primary=0;
  1255.     packet->append(",n  ", 4);
  1256.     if (i == primary_key && !strcmp(key_info->name, primary_key_name))
  1257.     {
  1258.       found_primary=1;
  1259.       packet->append("PRIMARY ", 8);
  1260.     }
  1261.     else if (key_info->flags & HA_NOSAME)
  1262.       packet->append("UNIQUE ", 7);
  1263.     else if (key_info->flags & HA_FULLTEXT)
  1264.       packet->append("FULLTEXT ", 9);
  1265.     else if (key_info->flags & HA_SPATIAL)
  1266.       packet->append("SPATIAL ", 8);
  1267.     packet->append("KEY ", 4);
  1268.     if (!found_primary)
  1269.      append_identifier(thd, packet, key_info->name, strlen(key_info->name));
  1270.     if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) &&
  1271. !limited_mysql_mode && !foreign_db_mode)
  1272.     {
  1273.       if (key_info->algorithm == HA_KEY_ALG_BTREE)
  1274. packet->append(" USING BTREE", 12);
  1275.       
  1276.       if (key_info->algorithm == HA_KEY_ALG_HASH)
  1277. packet->append(" USING HASH", 11);
  1278.       
  1279.       // +BAR: send USING only in non-default case: non-spatial rtree
  1280.       if ((key_info->algorithm == HA_KEY_ALG_RTREE) &&
  1281.   !(key_info->flags & HA_SPATIAL))
  1282. packet->append(" USING RTREE", 12);
  1283.       // No need to send TYPE FULLTEXT, it is sent as FULLTEXT KEY
  1284.     }
  1285.     packet->append(" (", 2);
  1286.     for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
  1287.     {
  1288.       if (j)
  1289.         packet->append(',');
  1290.       if (key_part->field)
  1291.         append_identifier(thd,packet,key_part->field->field_name,
  1292.   strlen(key_part->field->field_name));
  1293.       if (!key_part->field ||
  1294.           (key_part->length !=
  1295.            table->field[key_part->fieldnr-1]->key_length() &&
  1296.            !(key_info->flags & HA_FULLTEXT)))
  1297.       {
  1298.         buff[0] = '(';
  1299.         char* end=int10_to_str((long) key_part->length / 
  1300.        key_part->field->charset()->mbmaxlen,
  1301.        buff + 1,10);
  1302.         *end++ = ')';
  1303.         packet->append(buff,(uint) (end-buff));
  1304.       }
  1305.     }
  1306.     packet->append(')');
  1307.   }
  1308.   /*
  1309.     Get possible foreign key definitions stored in InnoDB and append them
  1310.     to the CREATE TABLE statement
  1311.   */
  1312.   if ((for_str= file->get_foreign_key_create_info()))
  1313.   {
  1314.     packet->append(for_str, strlen(for_str));
  1315.     file->free_foreign_key_create_info(for_str);
  1316.   }
  1317.   packet->append("n)", 2);
  1318.   if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
  1319.   {
  1320.     if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
  1321.       packet->append(" TYPE=", 6);
  1322.     else
  1323.       packet->append(" ENGINE=", 8);
  1324.     packet->append(file->table_type());
  1325.     
  1326.     if (table->table_charset &&
  1327. !(thd->variables.sql_mode & MODE_MYSQL323) &&
  1328. !(thd->variables.sql_mode & MODE_MYSQL40))
  1329.     {
  1330.       packet->append(" DEFAULT CHARSET=", 17);
  1331.       packet->append(table->table_charset->csname);
  1332.       if (!(table->table_charset->state & MY_CS_PRIMARY))
  1333.       {
  1334. packet->append(" COLLATE=", 9);
  1335. packet->append(table->table_charset->name);
  1336.       }
  1337.     }
  1338.     if (table->min_rows)
  1339.     {
  1340.       packet->append(" MIN_ROWS=", 10);
  1341.       end= longlong10_to_str(table->min_rows, buff, 10);
  1342.       packet->append(buff, (uint) (end- buff));
  1343.     }
  1344.     if (table->max_rows)
  1345.     {
  1346.       packet->append(" MAX_ROWS=", 10);
  1347.       end= longlong10_to_str(table->max_rows, buff, 10);
  1348.       packet->append(buff, (uint) (end - buff));
  1349.     }
  1350.     if (table->avg_row_length)
  1351.     {
  1352.       packet->append(" AVG_ROW_LENGTH=", 16);
  1353.       end= longlong10_to_str(table->avg_row_length, buff,10);
  1354.       packet->append(buff, (uint) (end - buff));
  1355.     }
  1356.     if (table->db_create_options & HA_OPTION_PACK_KEYS)
  1357.       packet->append(" PACK_KEYS=1", 12);
  1358.     if (table->db_create_options & HA_OPTION_NO_PACK_KEYS)
  1359.       packet->append(" PACK_KEYS=0", 12);
  1360.     if (table->db_create_options & HA_OPTION_CHECKSUM)
  1361.       packet->append(" CHECKSUM=1", 11);
  1362.     if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
  1363.       packet->append(" DELAY_KEY_WRITE=1",18);
  1364.     if (table->row_type != ROW_TYPE_DEFAULT)
  1365.     {
  1366.       packet->append(" ROW_FORMAT=",12);
  1367.       packet->append(ha_row_type[(uint) table->row_type]);
  1368.     }
  1369.     table->file->append_create_info(packet);
  1370.     if (table->comment && table->comment[0])
  1371.     {
  1372.       packet->append(" COMMENT=", 9);
  1373.       append_unescaped(packet, table->comment, strlen(table->comment));
  1374.     }
  1375.     if (file->raid_type)
  1376.     {
  1377.       uint length;
  1378.       length= my_snprintf(buff,sizeof(buff),
  1379.   " RAID_TYPE=%s RAID_CHUNKS=%d RAID_CHUNKSIZE=%ld",
  1380.   my_raid_type(file->raid_type), file->raid_chunks,
  1381.   file->raid_chunksize/RAID_BLOCK_SIZE);
  1382.       packet->append(buff, length);
  1383.     }
  1384.     append_directory(thd, packet, "DATA",  create_info.data_file_name);
  1385.     append_directory(thd, packet, "INDEX", create_info.index_file_name);
  1386.   }
  1387.   DBUG_RETURN(0);
  1388. }
  1389. /****************************************************************************
  1390.   Return info about all processes
  1391.   returns for each thread: thread id, user, host, db, command, info
  1392. ****************************************************************************/
  1393. class thread_info :public ilink {
  1394. public:
  1395.   static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
  1396.   static void operator delete(void *ptr __attribute__((unused)),
  1397.                               size_t size __attribute__((unused))) {} /*lint -e715 */
  1398.   ulong thread_id;
  1399.   time_t start_time;
  1400.   uint   command;
  1401.   const char *user,*host,*db,*proc_info,*state_info;
  1402.   char *query;
  1403. };
  1404. #ifdef __GNUC__
  1405. template class I_List<thread_info>;
  1406. #endif
  1407. void mysqld_list_processes(THD *thd,const char *user, bool verbose)
  1408. {
  1409.   Item *field;
  1410.   List<Item> field_list;
  1411.   I_List<thread_info> thread_infos;
  1412.   ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
  1413.    PROCESS_LIST_WIDTH);
  1414.   Protocol *protocol= thd->protocol;
  1415.   DBUG_ENTER("mysqld_list_processes");
  1416.   field_list.push_back(new Item_int("Id",0,11));
  1417.   field_list.push_back(new Item_empty_string("User",16));
  1418.   field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
  1419.   field_list.push_back(field=new Item_empty_string("db",NAME_LEN));
  1420.   field->maybe_null=1;
  1421.   field_list.push_back(new Item_empty_string("Command",16));
  1422.   field_list.push_back(new Item_return_int("Time",7, FIELD_TYPE_LONG));
  1423.   field_list.push_back(field=new Item_empty_string("State",30));
  1424.   field->maybe_null=1;
  1425.   field_list.push_back(field=new Item_empty_string("Info",max_query_length));
  1426.   field->maybe_null=1;
  1427.   if (protocol->send_fields(&field_list,1))
  1428.     DBUG_VOID_RETURN;
  1429.   VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
  1430.   if (!thd->killed)
  1431.   {
  1432.     I_List_iterator<THD> it(threads);
  1433.     THD *tmp;
  1434.     while ((tmp=it++))
  1435.     {
  1436.       struct st_my_thread_var *mysys_var;
  1437.       if ((tmp->vio_ok() || tmp->system_thread) &&
  1438.           (!user || (tmp->user && !strcmp(tmp->user,user))))
  1439.       {
  1440.         thread_info *thd_info=new thread_info;
  1441.         thd_info->thread_id=tmp->thread_id;
  1442.         thd_info->user=thd->strdup(tmp->user ? tmp->user :
  1443.    (tmp->system_thread ?
  1444.     "system user" : "unauthenticated user"));
  1445. if (tmp->peer_port && (tmp->host || tmp->ip) && thd->host_or_ip[0])
  1446. {
  1447.   if ((thd_info->host= thd->alloc(LIST_PROCESS_HOST_LEN+1)))
  1448.     my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN,
  1449. "%s:%u", tmp->host_or_ip, tmp->peer_port);
  1450. }
  1451. else
  1452.   thd_info->host= thd->strdup(tmp->host_or_ip);
  1453.         if ((thd_info->db=tmp->db))             // Safe test
  1454.           thd_info->db=thd->strdup(thd_info->db);
  1455.         thd_info->command=(int) tmp->command;
  1456.         if ((mysys_var= tmp->mysys_var))
  1457.           pthread_mutex_lock(&mysys_var->mutex);
  1458.         thd_info->proc_info= (char*) (tmp->killed ? "Killed" : 0);
  1459. #ifndef EMBEDDED_LIBRARY
  1460.         thd_info->state_info= (char*) (tmp->locked ? "Locked" :
  1461.                                        tmp->net.reading_or_writing ?
  1462.                                        (tmp->net.reading_or_writing == 2 ?
  1463.                                         "Writing to net" :
  1464.                                         thd_info->command == COM_SLEEP ? "" :
  1465.                                         "Reading from net") :
  1466.                                        tmp->proc_info ? tmp->proc_info :
  1467.                                        tmp->mysys_var &&
  1468.                                        tmp->mysys_var->current_cond ?
  1469.                                        "Waiting on cond" : NullS);
  1470. #else
  1471.         thd_info->state_info= (char*)"Writing to net";
  1472. #endif
  1473.         if (mysys_var)
  1474.           pthread_mutex_unlock(&mysys_var->mutex);
  1475. #if !defined(DONT_USE_THR_ALARM) && ! defined(SCO)
  1476.         if (pthread_kill(tmp->real_id,0))
  1477.           tmp->proc_info="*** DEAD ***";        // This shouldn't happen
  1478. #endif
  1479. #ifdef EXTRA_DEBUG
  1480.         thd_info->start_time= tmp->time_after_lock;
  1481. #else
  1482.         thd_info->start_time= tmp->start_time;
  1483. #endif
  1484.         thd_info->query=0;
  1485.         if (tmp->query)
  1486.         {
  1487.   /* 
  1488.             query_length is always set to 0 when we set query = NULL; see
  1489.     the comment in sql_class.h why this prevents crashes in possible
  1490.             races with query_length
  1491.           */
  1492.           uint length= min(max_query_length, tmp->query_length);
  1493.           thd_info->query=(char*) thd->strmake(tmp->query,length);
  1494.         }
  1495.         thread_infos.append(thd_info);
  1496.       }
  1497.     }
  1498.   }
  1499.   VOID(pthread_mutex_unlock(&LOCK_thread_count));
  1500.   thread_info *thd_info;
  1501.   time_t now= time(0);
  1502.   while ((thd_info=thread_infos.get()))
  1503.   {
  1504.     protocol->prepare_for_resend();
  1505.     protocol->store((ulonglong) thd_info->thread_id);
  1506.     protocol->store(thd_info->user, system_charset_info);
  1507.     protocol->store(thd_info->host, system_charset_info);
  1508.     protocol->store(thd_info->db, system_charset_info);
  1509.     if (thd_info->proc_info)
  1510.       protocol->store(thd_info->proc_info, system_charset_info);
  1511.     else
  1512.       protocol->store(command_name[thd_info->command], system_charset_info);
  1513.     if (thd_info->start_time)
  1514.       protocol->store((uint32) (now - thd_info->start_time));
  1515.     else
  1516.       protocol->store_null();
  1517.     protocol->store(thd_info->state_info, system_charset_info);
  1518.     protocol->store(thd_info->query, system_charset_info);
  1519.     if (protocol->write())
  1520.       break; /* purecov: inspected */
  1521.   }
  1522.   send_eof(thd);
  1523.   DBUG_VOID_RETURN;
  1524. }
  1525. /*****************************************************************************
  1526.   Status functions
  1527. *****************************************************************************/
  1528. static bool write_collation(Protocol *protocol, CHARSET_INFO *cs)
  1529. {
  1530.   protocol->prepare_for_resend();
  1531.   protocol->store(cs->name, system_charset_info);
  1532.   protocol->store(cs->csname, system_charset_info);
  1533.   protocol->store_short((longlong) cs->number);
  1534.   protocol->store((cs->state & MY_CS_PRIMARY) ? "Yes" : "",system_charset_info);
  1535.   protocol->store((cs->state & MY_CS_COMPILED)? "Yes" : "",system_charset_info);
  1536.   protocol->store_short((longlong) cs->strxfrm_multiply);
  1537.   return protocol->write();
  1538. }
  1539. int mysqld_show_collations(THD *thd, const char *wild)
  1540. {
  1541.   char buff[8192];
  1542.   String packet2(buff,sizeof(buff),thd->charset());
  1543.   List<Item> field_list;
  1544.   CHARSET_INFO **cs;
  1545.   Protocol *protocol= thd->protocol;
  1546.   DBUG_ENTER("mysqld_show_charsets");
  1547.   field_list.push_back(new Item_empty_string("Collation",30));
  1548.   field_list.push_back(new Item_empty_string("Charset",30));
  1549.   field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT));
  1550.   field_list.push_back(new Item_empty_string("Default",30));
  1551.   field_list.push_back(new Item_empty_string("Compiled",30));
  1552.   field_list.push_back(new Item_return_int("Sortlen",3, FIELD_TYPE_SHORT));
  1553.   if (protocol->send_fields(&field_list, 1))
  1554.     DBUG_RETURN(1);
  1555.   for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ )
  1556.   {
  1557.     CHARSET_INFO **cl;
  1558.     if (!cs[0] || !(cs[0]->state & MY_CS_AVAILABLE) || 
  1559.         !(cs[0]->state & MY_CS_PRIMARY))
  1560.       continue;
  1561.     for ( cl= all_charsets; cl < all_charsets+255 ;cl ++)
  1562.     {
  1563.       if (!cl[0] || !(cl[0]->state & MY_CS_AVAILABLE) || 
  1564.           !my_charset_same(cs[0],cl[0]))
  1565. continue;
  1566.       if (!(wild && wild[0] &&
  1567.   wild_case_compare(system_charset_info,cl[0]->name,wild)))
  1568.       {
  1569.         if (write_collation(protocol, cl[0]))
  1570.   goto err;
  1571.       }
  1572.     }
  1573.   }
  1574.   send_eof(thd); 
  1575.   DBUG_RETURN(0);
  1576. err:
  1577.   DBUG_RETURN(1);
  1578. }
  1579. static bool write_charset(Protocol *protocol, CHARSET_INFO *cs)
  1580. {
  1581.   protocol->prepare_for_resend();
  1582.   protocol->store(cs->csname, system_charset_info);
  1583.   protocol->store(cs->comment ? cs->comment : "", system_charset_info);
  1584.   protocol->store(cs->name, system_charset_info);
  1585.   protocol->store_short((longlong) cs->mbmaxlen);
  1586.   return protocol->write();
  1587. }
  1588. int mysqld_show_charsets(THD *thd, const char *wild)
  1589. {
  1590.   char buff[8192];
  1591.   String packet2(buff,sizeof(buff),thd->charset());
  1592.   List<Item> field_list;
  1593.   CHARSET_INFO **cs;
  1594.   Protocol *protocol= thd->protocol;
  1595.   DBUG_ENTER("mysqld_show_charsets");
  1596.   field_list.push_back(new Item_empty_string("Charset",30));
  1597.   field_list.push_back(new Item_empty_string("Description",60));
  1598.   field_list.push_back(new Item_empty_string("Default collation",60));
  1599.   field_list.push_back(new Item_return_int("Maxlen",3, FIELD_TYPE_SHORT));
  1600.   if (protocol->send_fields(&field_list, 1))
  1601.     DBUG_RETURN(1);
  1602.   for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ )
  1603.   {
  1604.     if (cs[0] && (cs[0]->state & MY_CS_PRIMARY) && 
  1605.         (cs[0]->state & MY_CS_AVAILABLE) &&
  1606.         !(wild && wild[0] &&
  1607.         wild_case_compare(system_charset_info,cs[0]->csname,wild)))
  1608.     {
  1609.       if (write_charset(protocol, cs[0]))
  1610. goto err;
  1611.     }
  1612.   }
  1613.   send_eof(thd); 
  1614.   DBUG_RETURN(0);
  1615. err:
  1616.   DBUG_RETURN(1);
  1617. }
  1618.   
  1619. int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
  1620. enum enum_var_type value_type,
  1621. pthread_mutex_t *mutex)
  1622. {
  1623.   char buff[1024];
  1624.   List<Item> field_list;
  1625.   Protocol *protocol= thd->protocol;
  1626.   LEX_STRING null_lex_str;
  1627.   DBUG_ENTER("mysqld_show");
  1628.   field_list.push_back(new Item_empty_string("Variable_name",30));
  1629.   field_list.push_back(new Item_empty_string("Value",256));
  1630.   if (protocol->send_fields(&field_list,1))
  1631.     DBUG_RETURN(1); /* purecov: inspected */
  1632.   null_lex_str.str= 0; // For sys_var->value_ptr()
  1633.   null_lex_str.length= 0;
  1634.   pthread_mutex_lock(mutex);
  1635.   for (; variables->name; variables++)
  1636.   {
  1637.     if (!(wild && wild[0] && wild_case_compare(system_charset_info,
  1638.        variables->name,wild)))
  1639.     {
  1640.       protocol->prepare_for_resend();
  1641.       protocol->store(variables->name, system_charset_info);
  1642.       SHOW_TYPE show_type=variables->type;
  1643.       char *value=variables->value;
  1644.       const char *pos, *end;
  1645.       long nr;
  1646.       if (show_type == SHOW_SYS)
  1647.       {
  1648. show_type= ((sys_var*) value)->type();
  1649. value=     (char*) ((sys_var*) value)->value_ptr(thd, value_type,
  1650.  &null_lex_str);
  1651.       }
  1652.       pos= end= buff;
  1653.       switch (show_type) {
  1654.       case SHOW_LONG:
  1655.       case SHOW_LONG_CONST:
  1656. end= int10_to_str(*(long*) value, buff, 10);
  1657.         break;
  1658.       case SHOW_LONGLONG:
  1659. end= longlong10_to_str(*(longlong*) value, buff, 10);
  1660. break;
  1661.       case SHOW_HA_ROWS:
  1662.         end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
  1663.         break;
  1664.       case SHOW_BOOL:
  1665. end= strmov(buff, *(bool*) value ? "ON" : "OFF");
  1666.         break;
  1667.       case SHOW_MY_BOOL:
  1668. end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
  1669.         break;
  1670.       case SHOW_INT_CONST:
  1671.       case SHOW_INT:
  1672. end= int10_to_str((long) *(uint32*) value, buff, 10);
  1673.         break;
  1674.       case SHOW_HAVE:
  1675.       {
  1676. SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
  1677. pos= show_comp_option_name[(int) tmp];
  1678. end= strend(pos);
  1679.         break;
  1680.       }
  1681.       case SHOW_CHAR:
  1682.       {
  1683.         if (!(pos= value))
  1684.           pos= "";
  1685.         end= strend(pos);
  1686.         break;
  1687.        }
  1688.       case SHOW_STARTTIME:
  1689. nr= (long) (thd->query_start() - start_time);
  1690. end= int10_to_str(nr, buff, 10);
  1691.         break;
  1692.       case SHOW_QUESTION:
  1693. end= int10_to_str((long) thd->query_id, buff, 10);
  1694.         break;
  1695. #ifdef HAVE_REPLICATION
  1696.       case SHOW_RPL_STATUS:
  1697. end= strmov(buff, rpl_status_type[(int)rpl_status]);
  1698. break;
  1699.       case SHOW_SLAVE_RUNNING:
  1700.       {
  1701. pthread_mutex_lock(&LOCK_active_mi);
  1702. end= strmov(buff, (active_mi && active_mi->slave_running &&
  1703.    active_mi->rli.slave_running) ? "ON" : "OFF");
  1704. pthread_mutex_unlock(&LOCK_active_mi);
  1705. break;
  1706.       }
  1707.       case SHOW_SLAVE_RETRIED_TRANS:
  1708.       {
  1709.         /*
  1710.           TODO: in 5.1 with multimaster, have one such counter per line in SHOW
  1711.           SLAVE STATUS, and have the sum over all lines here.
  1712.         */
  1713. pthread_mutex_lock(&LOCK_active_mi);
  1714.         if (active_mi)
  1715.         {
  1716.           pthread_mutex_lock(&active_mi->rli.data_lock);
  1717.           end= int10_to_str(active_mi->rli.retried_trans, buff, 10);
  1718.           pthread_mutex_unlock(&active_mi->rli.data_lock);
  1719.         }
  1720. pthread_mutex_unlock(&LOCK_active_mi);
  1721. break;
  1722.       }
  1723. #endif /* HAVE_REPLICATION */
  1724.       case SHOW_OPENTABLES:
  1725. end= int10_to_str((long) cached_tables(), buff, 10);
  1726.         break;
  1727.       case SHOW_CHAR_PTR:
  1728.       {
  1729.         if (!(pos= *(char**) value))
  1730.           pos= "";
  1731.         end= strend(pos);
  1732.         break;
  1733.       }
  1734. #ifdef HAVE_OPENSSL
  1735. /* First group - functions relying on CTX */
  1736.       case SHOW_SSL_CTX_SESS_ACCEPT:
  1737. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1738.   SSL_CTX_sess_accept(ssl_acceptor_fd->
  1739.       ssl_context)),
  1740.   buff, 10);
  1741.         break;
  1742.       case SHOW_SSL_CTX_SESS_ACCEPT_GOOD:
  1743. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1744.   SSL_CTX_sess_accept_good(ssl_acceptor_fd->
  1745.    ssl_context)),
  1746.   buff, 10);
  1747.         break;
  1748.       case SHOW_SSL_CTX_SESS_CONNECT_GOOD:
  1749. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1750.   SSL_CTX_sess_connect_good(ssl_acceptor_fd->
  1751.     ssl_context)),
  1752.   buff, 10);
  1753.         break;
  1754.       case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE:
  1755. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1756.   SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context)),
  1757.   buff, 10);
  1758.         break;
  1759.       case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE:
  1760. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1761.   SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context)),
  1762.   buff, 10);
  1763.         break;
  1764.       case SHOW_SSL_CTX_SESS_CB_HITS:
  1765. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1766.   SSL_CTX_sess_cb_hits(ssl_acceptor_fd->
  1767.        ssl_context)),
  1768.   buff, 10);
  1769.         break;
  1770.       case SHOW_SSL_CTX_SESS_HITS:
  1771. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1772.   SSL_CTX_sess_hits(ssl_acceptor_fd->
  1773.     ssl_context)),
  1774.   buff, 10);
  1775.         break;
  1776.       case SHOW_SSL_CTX_SESS_CACHE_FULL:
  1777. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1778.   SSL_CTX_sess_cache_full(ssl_acceptor_fd->
  1779.   ssl_context)),
  1780.   buff, 10);
  1781.         break;
  1782.       case SHOW_SSL_CTX_SESS_MISSES:
  1783. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1784.   SSL_CTX_sess_misses(ssl_acceptor_fd->
  1785.       ssl_context)),
  1786.   buff, 10);
  1787.         break;
  1788.       case SHOW_SSL_CTX_SESS_TIMEOUTS:
  1789. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1790.   SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context)),
  1791.   buff,10);
  1792.         break;
  1793.       case SHOW_SSL_CTX_SESS_NUMBER:
  1794. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1795.   SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context)),
  1796.   buff,10);
  1797.         break;
  1798.       case SHOW_SSL_CTX_SESS_CONNECT:
  1799. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1800.   SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)),
  1801.   buff,10);
  1802.         break;
  1803.       case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE:
  1804. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1805.   SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context)),
  1806.   buff,10);
  1807.         break;
  1808.       case SHOW_SSL_CTX_GET_VERIFY_MODE:
  1809. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1810.   SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)),
  1811.   buff,10);
  1812.         break;
  1813.       case SHOW_SSL_CTX_GET_VERIFY_DEPTH:
  1814. end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
  1815.   SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)),
  1816.   buff,10);
  1817.         break;
  1818.       case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE:
  1819. if (!ssl_acceptor_fd)
  1820. {
  1821.   pos= "NONE";
  1822.   end= pos+4;
  1823.   break;
  1824. }
  1825. switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
  1826. {
  1827.           case SSL_SESS_CACHE_OFF:
  1828.             pos= "OFF";
  1829.     break;
  1830.           case SSL_SESS_CACHE_CLIENT:
  1831.             pos= "CLIENT";
  1832.     break;
  1833.           case SSL_SESS_CACHE_SERVER:
  1834.             pos= "SERVER";
  1835.     break;
  1836.           case SSL_SESS_CACHE_BOTH:
  1837.             pos= "BOTH";
  1838.     break;
  1839.           case SSL_SESS_CACHE_NO_AUTO_CLEAR:
  1840.             pos= "NO_AUTO_CLEAR";
  1841.     break;
  1842.           case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
  1843.             pos= "NO_INTERNAL_LOOKUP";
  1844.     break;
  1845.   default:
  1846.             pos= "Unknown";
  1847.     break;
  1848. }
  1849. end= strend(pos);
  1850.         break;
  1851. /* First group - functions relying on SSL */
  1852.       case SHOW_SSL_GET_VERSION:
  1853. pos= (thd->net.vio->ssl_arg ?
  1854.       SSL_get_version((SSL*) thd->net.vio->ssl_arg) : "");
  1855. end= strend(pos);
  1856.         break;
  1857.       case SHOW_SSL_SESSION_REUSED:
  1858. end= int10_to_str((long) (thd->net.vio->ssl_arg ?
  1859.   SSL_session_reused((SSL*) thd->net.vio->
  1860.      ssl_arg) :
  1861.   0),
  1862.   buff, 10);
  1863.         break;
  1864.       case SHOW_SSL_GET_DEFAULT_TIMEOUT:
  1865. end= int10_to_str((long) (thd->net.vio->ssl_arg ?
  1866.   SSL_get_default_timeout((SSL*) thd->net.vio->
  1867.   ssl_arg) :
  1868.   0),
  1869.   buff, 10);
  1870.         break;
  1871.       case SHOW_SSL_GET_VERIFY_MODE:
  1872. end= int10_to_str((long) (thd->net.vio->ssl_arg ?
  1873.   SSL_get_verify_mode((SSL*) thd->net.vio->
  1874.       ssl_arg):
  1875.   0),
  1876.   buff, 10);
  1877.         break;
  1878.       case SHOW_SSL_GET_VERIFY_DEPTH:
  1879. end= int10_to_str((long) (thd->net.vio->ssl_arg ?
  1880.   SSL_get_verify_depth((SSL*) thd->net.vio->
  1881.        ssl_arg):
  1882.   0),
  1883.   buff, 10);
  1884.         break;
  1885.       case SHOW_SSL_GET_CIPHER:
  1886. pos= (thd->net.vio->ssl_arg ?
  1887.       SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : "" );
  1888. end= strend(pos);
  1889. break;
  1890.       case SHOW_SSL_GET_CIPHER_LIST:
  1891. if (thd->net.vio->ssl_arg)
  1892. {
  1893.   char *to= buff;
  1894.   for (int i=0 ; i++ ;)
  1895.   {
  1896.     const char *p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i);
  1897.     if (p == NULL) 
  1898.       break;
  1899.     to= strmov(to, p);
  1900.     *to++= ':';
  1901.   }
  1902.   if (to != buff)
  1903.     to--; // Remove last ':'
  1904.   end= to;
  1905.         }
  1906.         break;
  1907. #endif /* HAVE_OPENSSL */
  1908.       case SHOW_KEY_CACHE_LONG:
  1909.       case SHOW_KEY_CACHE_CONST_LONG:
  1910. value= (value-(char*) &dflt_key_cache_var)+ (char*) dflt_key_cache;
  1911. end= int10_to_str(*(long*) value, buff, 10);
  1912.         break;
  1913.       case SHOW_KEY_CACHE_LONGLONG:
  1914. value= (value-(char*) &dflt_key_cache_var)+ (char*) dflt_key_cache;
  1915. end= longlong10_to_str(*(longlong*) value, buff, 10);
  1916. break;
  1917.       case SHOW_UNDEF: // Show never happen
  1918.       case SHOW_SYS:
  1919. break; // Return empty string
  1920.       default:
  1921. break;
  1922.       }
  1923.       if (protocol->store(pos, (uint32) (end - pos), system_charset_info) ||
  1924.   protocol->write())
  1925.         goto err;                               /* purecov: inspected */
  1926.     }
  1927.   }
  1928.   pthread_mutex_unlock(mutex);
  1929.   send_eof(thd);
  1930.   DBUG_RETURN(0);
  1931.  err:
  1932.   pthread_mutex_unlock(mutex);
  1933.   DBUG_RETURN(1);
  1934. }
  1935. #ifdef __GNUC__
  1936. template class List_iterator_fast<char>;
  1937. template class List<char>;
  1938. #endif