sql_show.cc 68.9 KB
Newer Older
1
/* Copyright (C) 2000 MySQL AB
2

unknown's avatar
unknown committed
3 4 5 6
   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
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
7

unknown's avatar
unknown committed
8 9 10 11
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
12

unknown's avatar
unknown committed
13 14 15 16 17 18 19 20
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


/* Function with list databases, tables or fields */

#include "mysql_priv.h"
21
#include "sql_select.h"                         // For select_describe
unknown's avatar
unknown committed
22
#include "sql_acl.h"
23
#include "repl_failsafe.h"
unknown's avatar
unknown committed
24
#include <my_dir.h>
unknown's avatar
unknown committed
25

unknown's avatar
unknown committed
26 27 28 29
#ifdef HAVE_BERKELEY_DB
#include "ha_berkeley.h"			// For berkeley_show_logs
#endif

unknown's avatar
unknown committed
30 31 32 33
static const char *grant_names[]={
  "select","insert","update","delete","create","drop","reload","shutdown",
  "process","file","grant","references","index","alter"};

unknown's avatar
unknown committed
34
#ifndef NO_EMBEDDED_ACCESS_CHECKS
unknown's avatar
unknown committed
35
static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
36 37
                               "grant_types",
                               grant_names};
unknown's avatar
unknown committed
38
#endif
unknown's avatar
unknown committed
39 40

static int
41 42
store_create_info(THD *thd, TABLE *table, String *packet);

unknown's avatar
unknown committed
43

44 45 46 47
/*
  Report list of databases
  A database is a directory in the mysql_data_home directory
*/
unknown's avatar
SCRUM  
unknown committed
48

unknown's avatar
unknown committed
49 50 51
int
mysqld_show_dbs(THD *thd,const char *wild)
{
unknown's avatar
unknown committed
52
  Item_string *field=new Item_string("",0,thd->charset());
unknown's avatar
unknown committed
53 54 55 56
  List<Item> field_list;
  char *end;
  List<char> files;
  char *file_name;
57
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
58 59
  DBUG_ENTER("mysqld_show_dbs");

unknown's avatar
unknown committed
60
  field->name=(char*) thd->alloc(20+ (wild ? (uint) strlen(wild)+4: 0));
unknown's avatar
unknown committed
61 62 63 64 65 66
  field->max_length=NAME_LEN;
  end=strmov(field->name,"Database");
  if (wild && wild[0])
    strxmov(end," (",wild,")",NullS);
  field_list.push_back(field);

67
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
68 69 70
    DBUG_RETURN(1);
  if (mysql_find_files(thd,&files,NullS,mysql_data_home,wild,1))
    DBUG_RETURN(1);
unknown's avatar
unknown committed
71
  List_iterator_fast<char> it(files);
72

unknown's avatar
unknown committed
73 74
  while ((file_name=it++))
  {
unknown's avatar
unknown committed
75
#ifndef NO_EMBEDDED_ACCESS_CHECKS
unknown's avatar
unknown committed
76
    if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
77
	acl_get(thd->host, thd->ip, thd->priv_user, file_name,0) ||
78
	(grant_option && !check_grant_db(thd, file_name)))
unknown's avatar
unknown committed
79
#endif
unknown's avatar
unknown committed
80
    {
81
      protocol->prepare_for_resend();
82
      protocol->store(file_name, system_charset_info);
83
      if (protocol->write())
84 85
	DBUG_RETURN(-1);
    }
unknown's avatar
unknown committed
86
  }
87
  send_eof(thd);
unknown's avatar
unknown committed
88 89 90
  DBUG_RETURN(0);
}

91

92
/***************************************************************************
93
  List all open tables in a database
94 95
***************************************************************************/

96
int mysqld_show_open_tables(THD *thd,const char *wild)
97 98
{
  List<Item> field_list;
99
  OPEN_TABLE_LIST *open_list;
100
  Protocol *protocol= thd->protocol;
101 102
  DBUG_ENTER("mysqld_show_open_tables");

103 104
  field_list.push_back(new Item_empty_string("Database",NAME_LEN));
  field_list.push_back(new Item_empty_string("Table",NAME_LEN));
105 106
  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));
107

108
  if (protocol->send_fields(&field_list,1))
109
    DBUG_RETURN(1);
110

111
  if (!(open_list=list_open_tables(thd,wild)) && thd->is_fatal_error)
112 113
    DBUG_RETURN(-1);

114
  for (; open_list ; open_list=open_list->next)
115
  {
116
    protocol->prepare_for_resend();
117 118
    protocol->store(open_list->db, system_charset_info);
    protocol->store(open_list->table, system_charset_info);
119 120 121
    protocol->store_tiny((longlong) open_list->in_use);
    protocol->store_tiny((longlong) open_list->locked);
    if (protocol->write())
122
    {
123
      DBUG_RETURN(-1);
124
    }
125
  }
126
  send_eof(thd);
127 128 129
  DBUG_RETURN(0);
}

130

unknown's avatar
unknown committed
131 132 133 134 135 136 137
/***************************************************************************
** List all tables in a database (fast version)
** A table is a .frm file in the current databasedir
***************************************************************************/

int mysqld_show_tables(THD *thd,const char *db,const char *wild)
{
unknown's avatar
unknown committed
138
  Item_string *field=new Item_string("",0,thd->charset());
unknown's avatar
unknown committed
139 140 141 142
  List<Item> field_list;
  char path[FN_LEN],*end;
  List<char> files;
  char *file_name;
143
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
144 145
  DBUG_ENTER("mysqld_show_tables");

146 147
  field->name=(char*) thd->alloc(20+(uint) strlen(db)+
				 (wild ? (uint) strlen(wild)+4:0));
unknown's avatar
unknown committed
148 149 150 151 152 153 154
  end=strxmov(field->name,"Tables_in_",db,NullS);
  if (wild && wild[0])
    strxmov(end," (",wild,")",NullS);
  field->max_length=NAME_LEN;
  (void) sprintf(path,"%s/%s",mysql_data_home,db);
  (void) unpack_dirname(path,path);
  field_list.push_back(field);
155
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
156 157 158
    DBUG_RETURN(1);
  if (mysql_find_files(thd,&files,db,path,wild,0))
    DBUG_RETURN(-1);
unknown's avatar
unknown committed
159
  List_iterator_fast<char> it(files);
unknown's avatar
unknown committed
160 161
  while ((file_name=it++))
  {
162
    protocol->prepare_for_resend();
163
    protocol->store(file_name, system_charset_info);
164
    if (protocol->write())
unknown's avatar
unknown committed
165 166
      DBUG_RETURN(-1);
  }
167
  send_eof(thd);
unknown's avatar
unknown committed
168 169 170
  DBUG_RETURN(0);
}

unknown's avatar
unknown committed
171 172 173 174
/***************************************************************************
** List all table types supported 
***************************************************************************/

unknown's avatar
unknown committed
175
int mysqld_show_storage_engines(THD *thd)
unknown's avatar
unknown committed
176 177
{
  List<Item> field_list;
178
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
179
  DBUG_ENTER("mysqld_show_storage_engines");
unknown's avatar
unknown committed
180

unknown's avatar
unknown committed
181
  field_list.push_back(new Item_empty_string("Engine",10));
unknown's avatar
unknown committed
182
  field_list.push_back(new Item_empty_string("Support",10));
183
  field_list.push_back(new Item_empty_string("Comment",80));
unknown's avatar
unknown committed
184

185
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
186 187
    DBUG_RETURN(1);

188
  const char *default_type_name= 
unknown's avatar
unknown committed
189
    ha_get_storage_engine((enum db_type)thd->variables.table_type);
unknown's avatar
unknown committed
190

191 192
  show_table_type_st *types;
  for (types= sys_table_types; types->type; types++)
unknown's avatar
unknown committed
193
  {
194
    protocol->prepare_for_resend();
195
    protocol->store(types->type, system_charset_info);
196 197 198
    const char *option_name= show_comp_option_name[(int) *types->value];

    if (*types->value == SHOW_OPTION_YES &&
199
	!my_strcasecmp(system_charset_info, default_type_name, types->type))
200
      option_name= "DEFAULT";
201 202
    protocol->store(option_name, system_charset_info);
    protocol->store(types->comment, system_charset_info);
203
    if (protocol->write())
unknown's avatar
unknown committed
204 205
      DBUG_RETURN(-1);
  }
206
  send_eof(thd);
unknown's avatar
unknown committed
207 208 209
  DBUG_RETURN(0);
}

210

unknown's avatar
unknown committed
211
/***************************************************************************
212
 List all privileges supported
unknown's avatar
unknown committed
213 214
***************************************************************************/

215 216 217 218
struct show_privileges_st {
  const char *privilege;
  const char *context;
  const char *comment;
unknown's avatar
unknown committed
219 220
};

221 222
static struct show_privileges_st sys_privileges[]=
{
unknown's avatar
unknown committed
223 224
  {"Alter", "Tables",  "To alter the table"},
  {"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"},
225
  {"Create", "Databases,Tables,Indexes",  "To create new databases and tables"},
unknown's avatar
unknown committed
226 227 228 229 230 231 232 233
  {"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"},
234
  {"References", "Databases,Tables", "To have references on tables"},
unknown's avatar
unknown committed
235 236 237 238 239
  {"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"},
240
  {"Shutdown","Server Admin", "To shutdown the server"},
unknown's avatar
unknown committed
241 242 243
  {"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"},
244 245 246
  {NullS, NullS, NullS}
};

unknown's avatar
unknown committed
247 248 249
int mysqld_show_privileges(THD *thd)
{
  List<Item> field_list;
250
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
251 252 253 254 255 256
  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));

257
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
258 259
    DBUG_RETURN(1);

260 261
  show_privileges_st *privilege= sys_privileges;
  for (privilege= sys_privileges; privilege->privilege ; privilege++)
unknown's avatar
unknown committed
262
  {
263
    protocol->prepare_for_resend();
264 265 266
    protocol->store(privilege->privilege, system_charset_info);
    protocol->store(privilege->context, system_charset_info);
    protocol->store(privilege->comment, system_charset_info);
267
    if (protocol->write())
unknown's avatar
unknown committed
268 269
      DBUG_RETURN(-1);
  }
270
  send_eof(thd);
unknown's avatar
unknown committed
271 272 273 274 275
  DBUG_RETURN(0);
}


/***************************************************************************
276
  List all column types
unknown's avatar
unknown committed
277 278
***************************************************************************/

279 280
struct show_column_type_st
{
unknown's avatar
unknown committed
281 282
  const char *type;
  uint size;
283 284 285 286 287 288 289 290 291 292 293 294
  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;
unknown's avatar
unknown committed
295
};
296 297 298 299 300

/* TODO: Add remaning types */

static struct show_column_type_st sys_column_types[]=
{
unknown's avatar
unknown committed
301 302
  {"tinyint",
    1,  "-128",  "127",  0,  0,  "YES",  "YES",
unknown's avatar
unknown committed
303 304
    "NO",   "YES", "YES",  "NO",  "NULL,0",
    "A very small integer"},
unknown's avatar
unknown committed
305
  {"tinyint unsigned",
unknown's avatar
unknown committed
306 307
    1,  "0"   ,  "255",  0,  0,  "YES",  "YES",
    "YES",  "YES",  "YES",  "NO",  "NULL,0",
unknown's avatar
unknown committed
308 309 310 311 312 313
    "A very small integer"},
};

int mysqld_show_column_types(THD *thd)
{
  List<Item> field_list;
314
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
315 316 317 318 319 320
  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));
321 322
  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));
unknown's avatar
unknown committed
323 324 325 326 327 328 329 330 331
  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));

332
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
333 334
    DBUG_RETURN(1);

335
  /* TODO: Change the loop to not use 'i' */
unknown's avatar
unknown committed
336 337
  for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++)
  {
338
    protocol->prepare_for_resend();
339
    protocol->store(sys_column_types[i].type, system_charset_info);
340
    protocol->store((ulonglong) sys_column_types[i].size);
341 342
    protocol->store(sys_column_types[i].min_value, system_charset_info);
    protocol->store(sys_column_types[i].max_value, system_charset_info);
343 344
    protocol->store_short((longlong) sys_column_types[i].precision);
    protocol->store_short((longlong) sys_column_types[i].scale);
345 346 347 348 349 350 351 352
    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);
353
    if (protocol->write())
unknown's avatar
unknown committed
354 355
      DBUG_RETURN(-1);
  }
356
  send_eof(thd);
unknown's avatar
unknown committed
357 358 359 360
  DBUG_RETURN(0);
}


361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391

/*
   Ask all engines if they can provide a list of available tables.
   Returns a list of available tables.
*/

int 
mysql_discover_tables(THD *thd, HASH *ha_tables, const char *db, bool dir)
{
  DBUG_ENTER("mysql_discover_files");
  
  if (dir)    
    DBUG_RETURN(0); // Discover of directories(databases) not supported yet
  
  // Get list of files in storage engine
  if (ha_list_tables(thd, ha_tables, db))
    DBUG_RETURN(-1);

  DBUG_PRINT("info",("discovered: %d files", ha_tables->records));
  DBUG_RETURN(0);
}


/*
  List all files or directories in a given location
  Returns
   files - list of files where wild card has been applied
   all_files - list of all files
   dsc_files - list of files which are discoverable
*/

392
int
393 394
mysql_list_files(THD *thd, const char *db, const char *path, const char *wild, 
		 bool dir, List<char> *files, HASH *all_files, HASH* dsc_files)
unknown's avatar
unknown committed
395 396
{
  uint i;
397
  char *ext, **dsc_ext;
unknown's avatar
unknown committed
398 399
  MY_DIR *dirp;
  FILEINFO *file;
unknown's avatar
unknown committed
400
#ifndef NO_EMBEDDED_ACCESS_CHECKS
unknown's avatar
unknown committed
401
  uint col_access=thd->col_access;
unknown's avatar
unknown committed
402
#endif
unknown's avatar
unknown committed
403
  TABLE_LIST table_list;
404
  DBUG_ENTER("mysql_list_files");
unknown's avatar
unknown committed
405 406

  bzero((char*) &table_list,sizeof(table_list));
407
  
unknown's avatar
unknown committed
408 409 410
  if (!(dirp = my_dir(path,MYF(MY_WME | (dir ? MY_WANT_STAT : 0)))))
    DBUG_RETURN(-1);

411
  for (i= 0; i < (uint)dirp->number_off_files; i++)
unknown's avatar
unknown committed
412
  {
413
    file= dirp->dir_entry+i;
unknown's avatar
unknown committed
414
    if (dir)
415
    {                                           /* Return databases */
unknown's avatar
unknown committed
416 417 418
#ifdef USE_SYMDIR
      char *ext;
      if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym"))
419 420 421 422
      {
	/* Only show the sym file if it points to a directory */
	char buff[FN_REFLEN], *end;
	MY_STAT status;
423
        *ext= 0;                                 /* Remove extension */
424 425 426 427 428 429 430 431
	unpack_dirname(buff, file->name);
	end= strend(buff);
	if (end != buff && end[-1] == FN_LIBCHAR)
	  end[-1]= 0;				// Remove end FN_LIBCHAR
	if (!my_stat(buff, &status, MYF(0)) ||
	    !MY_S_ISDIR(status.st_mode))
	  continue;
      }
unknown's avatar
unknown committed
432 433 434
      else
#endif
      {
unknown's avatar
unknown committed
435
        if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat->st_mode) ||
436
            (wild && wild_compare(file->name,wild,0)))
437
          continue;
unknown's avatar
unknown committed
438 439 440 441
      }
    }
    else
    {
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
      // Don't process temp files
      if (is_prefix(file->name, tmp_file_prefix))
	continue;

      ext= fn_ext(file->name);
      // Check for  files that indicates the table can be discovered
      if (ha_can_discover(thd, file->name))
      {
	DBUG_PRINT("info", ("Discoverable file found: %s", file->name));
	*ext= 0;
	if (my_hash_insert(dsc_files, (byte*)thd->strdup(file->name)))
	{
	  my_dirend(dirp);
	  DBUG_RETURN(-1);
	}
	continue;
      }

      // Return only .frm files
      if (my_strcasecmp(system_charset_info, ext,reg_ext))
	continue;
      *ext=0;	  

      // Insert into list of all .frm files
      if (my_hash_insert(all_files, (byte*)thd->strdup(file->name)))
      {
	my_dirend(dirp);
	DBUG_RETURN(-1);
      }

472 473 474 475
      if (wild)
      {
	if (lower_case_table_names)
	{
476
	  if (wild_case_compare(files_charset_info, file->name, wild))
477 478
	    continue;
	}
479
	else if (wild_compare(file->name,wild,0))
480 481
	  continue;
      }
unknown's avatar
unknown committed
482
    }
unknown's avatar
unknown committed
483
#ifndef NO_EMBEDDED_ACCESS_CHECKS
unknown's avatar
unknown committed
484 485 486 487 488 489
    /* 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;
unknown's avatar
unknown committed
490
      if (check_grant(thd, TABLE_ACLS, &table_list, 1, UINT_MAX, 1))
491
        continue;
unknown's avatar
unknown committed
492
    }
unknown's avatar
unknown committed
493
#endif
494
    if (files->push_back(thd->strdup(file->name)))
unknown's avatar
unknown committed
495 496 497 498 499 500 501 502 503
    {
      my_dirend(dirp);
      DBUG_RETURN(-1);
    }
  }
  my_dirend(dirp);
  DBUG_RETURN(0);
}

504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
extern "C" byte* ha_tables_get_key(const char *entry, uint *length,
				   my_bool not_used __attribute__((unused)))
{
  *length= strlen(entry);
  return (byte*) entry;
}


int
mysql_find_files(THD *thd,List<char> *files, const char *db,
		 const char *path, const char *wild, bool dir)
{
  int error= -1;
  uint i;
  bool discovery_performed= false;
  DBUG_ENTER("mysql_find_files");
  DBUG_PRINT("enter", ("db: %s, path: %s, wild: %s, dir: %d", 
	     db, path, wild, dir));

  if (wild && !wild[0])
    wild=0;

  HASH ha_tables, all_files, dsc_files;
  if (hash_init(&ha_tables,system_charset_info,32,0,0,
		(hash_get_key) ha_tables_get_key,0,0) || 
      hash_init(&all_files,system_charset_info,32,0,0,
		(hash_get_key) ha_tables_get_key,0,0) ||
      hash_init(&dsc_files,system_charset_info,32,0,0,
		(hash_get_key) ha_tables_get_key,0,0))
    goto err_end;
    
  if (mysql_discover_tables(thd, &ha_tables, db, dir))
    goto err_end;

  if (mysql_list_files(thd, db, path, wild, dir,
		       files, &all_files, &dsc_files))
    goto err_end;

  /*
    Discovery part 1
    Loop through handler files and see if any of them should be discovered
  */
  for (i= 0; i < ha_tables.records; i++)
  {
    const char *name = hash_element(&ha_tables, i);
    if (hash_search(&all_files, name, strlen(name)))
      continue;
    
    // Table was in handler, but not in list of all tables
    DBUG_PRINT("info", ("Table to discover[%d]: %s", i, name));
    pthread_mutex_lock(&LOCK_open);
    ha_create_table_from_engine(thd, db, name, true);
    pthread_mutex_unlock(&LOCK_open);      
    discovery_performed= true;
  }

  /*
    Discovery part2
    Loop through dsc files and see if any of them need to be deleted
  */
  for (i= 0; i < dsc_files.records; i++)
  {
    const char *name = hash_element(&dsc_files, i);
    if (hash_search(&ha_tables, name, strlen(name)))
      continue;

    //  Table was only on disk and not in handler
    DBUG_PRINT("info", ("Table[%d]: %s only exists on disk", i, name));

    // Verify that handler agrees table is gone.
    if (ha_table_exists(thd, db, name) == 0)
    {
      // Delete the table and all related files
      TABLE_LIST table_list;
      bzero((char*) &table_list,sizeof(table_list));
      table_list.db= (char*) db;
      table_list.real_name=(char*)name;
      (void)mysql_rm_table_part2_with_lock(thd, &table_list, 
					   /* if_exists */ true, 
					   /* drop_temporary */ false, 
					   /* dont_log_query*/ true);
      discovery_performed= true;
    }
  }
  
  if (discovery_performed)
  {
    // Call mysql_list_files one more time to get an updated list    
    DBUG_PRINT("info", ("Calling mysql_list_files one more time"));
    files->empty();
    if (mysql_list_files(thd, db, path, wild, dir,
			 files, &all_files, &dsc_files))
      goto err_end;    
  }

  DBUG_PRINT("info",("found: %d files", files->elements));
  error = 0;
err_end:
  hash_free(&ha_tables);
  hash_free(&all_files);
  hash_free(&dsc_files);
  DBUG_RETURN(error);
}

608

unknown's avatar
unknown committed
609
/***************************************************************************
610
 Extended version of mysqld_show_tables
unknown's avatar
unknown committed
611 612 613 614 615 616 617 618 619 620
***************************************************************************/

int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
{
  Item *item;
  List<char> files;
  List<Item> field_list;
  char path[FN_LEN];
  char *file_name;
  TABLE *table;
621 622
  Protocol *protocol= thd->protocol;
  TIME time;
unknown's avatar
unknown committed
623 624 625 626 627
  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));
unknown's avatar
unknown committed
628
  field_list.push_back(item=new Item_empty_string("Engine",10));
unknown's avatar
unknown committed
629
  item->maybe_null=1;
630 631
  field_list.push_back(item=new Item_int("Version", (longlong) 0, 21));
  item->maybe_null=1;
unknown's avatar
unknown committed
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653
  field_list.push_back(item=new Item_empty_string("Row_format",10));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Rows",(longlong) 1,21));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Avg_row_length",(int32) 0,21));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Data_length",(longlong) 1,21));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Max_data_length",(longlong) 1,21));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Index_length",(longlong) 1,21));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Data_free",(longlong) 1,21));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Auto_increment",(longlong) 1,21));
  item->maybe_null=1;
  field_list.push_back(item=new Item_datetime("Create_time"));
  item->maybe_null=1;
  field_list.push_back(item=new Item_datetime("Update_time"));
  item->maybe_null=1;
  field_list.push_back(item=new Item_datetime("Check_time"));
  item->maybe_null=1;
unknown's avatar
unknown committed
654
  field_list.push_back(item=new Item_empty_string("Collation",32));
655
  item->maybe_null=1;
unknown's avatar
unknown committed
656 657
  field_list.push_back(item=new Item_int("Checksum",(longlong) 1,21));
  item->maybe_null=1;
unknown's avatar
unknown committed
658 659 660
  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));
661
  item->maybe_null=1;
662
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
663 664 665 666
    DBUG_RETURN(1);

  if (mysql_find_files(thd,&files,db,path,wild,0))
    DBUG_RETURN(-1);
unknown's avatar
unknown committed
667
  List_iterator_fast<char> it(files);
unknown's avatar
unknown committed
668 669 670 671
  while ((file_name=it++))
  {
    TABLE_LIST table_list;
    bzero((char*) &table_list,sizeof(table_list));
672
    protocol->prepare_for_resend();
673
    protocol->store(file_name, system_charset_info);
unknown's avatar
unknown committed
674
    table_list.db=(char*) db;
675
    table_list.real_name= table_list.alias= file_name;
676
    if (lower_case_table_names)
677
      my_casedn_str(files_charset_info, file_name);
unknown's avatar
unknown committed
678 679
    if (!(table = open_ltable(thd, &table_list, TL_READ)))
    {
680
      for (uint i=2 ; i < field_list.elements ; i++)
681
        protocol->store_null();
682
      // Send error to Comment field
683
      protocol->store(thd->net.last_error, system_charset_info);
unknown's avatar
unknown committed
684
      thd->clear_error();
unknown's avatar
unknown committed
685 686 687
    }
    else
    {
688
      const char *str;
unknown's avatar
unknown committed
689 690
      handler *file=table->file;
      file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK);
691
      protocol->store(file->table_type(), system_charset_info);
692
      protocol->store((ulonglong) table->frm_version);
693 694 695 696
      str= ((table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ?
	    "Compressed" :
	    (table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
	    "Dynamic" : "Fixed");
697
      protocol->store(str, system_charset_info);
698 699 700
      protocol->store((ulonglong) file->records);
      protocol->store((ulonglong) file->mean_rec_length);
      protocol->store((ulonglong) file->data_file_length);
unknown's avatar
unknown committed
701
      if (file->max_data_file_length)
702
        protocol->store((ulonglong) file->max_data_file_length);
unknown's avatar
unknown committed
703
      else
704 705 706
        protocol->store_null();
      protocol->store((ulonglong) file->index_file_length);
      protocol->store((ulonglong) file->delete_length);
unknown's avatar
unknown committed
707 708
      if (table->found_next_number_field)
      {
709 710 711
        table->next_number_field=table->found_next_number_field;
        table->next_number_field->reset();
        file->update_auto_increment();
712
        protocol->store(table->next_number_field->val_int());
713
        table->next_number_field=0;
unknown's avatar
unknown committed
714 715
      }
      else
716
        protocol->store_null();
unknown's avatar
unknown committed
717
      if (!file->create_time)
718
        protocol->store_null();
unknown's avatar
unknown committed
719 720
      else
      {
721
        thd->variables.time_zone->gmt_sec_to_TIME(&time, file->create_time);
722
        protocol->store(&time);
unknown's avatar
unknown committed
723 724
      }
      if (!file->update_time)
725
        protocol->store_null();
unknown's avatar
unknown committed
726 727
      else
      {
728
        thd->variables.time_zone->gmt_sec_to_TIME(&time, file->update_time);
729
        protocol->store(&time);
unknown's avatar
unknown committed
730 731
      }
      if (!file->check_time)
732
        protocol->store_null();
unknown's avatar
unknown committed
733 734
      else
      {
735
        thd->variables.time_zone->gmt_sec_to_TIME(&time, file->check_time);
736
        protocol->store(&time);
unknown's avatar
unknown committed
737
      }
738
      str= (table->table_charset ? table->table_charset->name : "default");
739
      protocol->store(str, system_charset_info);
unknown's avatar
unknown committed
740 741 742 743
      if (file->table_flags() & HA_HAS_CHECKSUM)
        protocol->store((ulonglong)file->checksum());
      else
        protocol->store_null(); // Checksum
unknown's avatar
unknown committed
744
      {
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
        char option_buff[350],*ptr;
        ptr=option_buff;
        if (table->min_rows)
        {
          ptr=strmov(ptr," min_rows=");
          ptr=longlong10_to_str(table->min_rows,ptr,10);
        }
        if (table->max_rows)
        {
          ptr=strmov(ptr," max_rows=");
          ptr=longlong10_to_str(table->max_rows,ptr,10);
        }
        if (table->avg_row_length)
        {
          ptr=strmov(ptr," avg_row_length=");
          ptr=longlong10_to_str(table->avg_row_length,ptr,10);
        }
        if (table->db_create_options & HA_OPTION_PACK_KEYS)
          ptr=strmov(ptr," pack_keys=1");
        if (table->db_create_options & HA_OPTION_NO_PACK_KEYS)
          ptr=strmov(ptr," pack_keys=0");
        if (table->db_create_options & HA_OPTION_CHECKSUM)
          ptr=strmov(ptr," checksum=1");
        if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
          ptr=strmov(ptr," delay_key_write=1");
        if (table->row_type != ROW_TYPE_DEFAULT)
771
          ptr=strxmov(ptr, " row_format=", ha_row_type[(uint) table->row_type],
772 773 774 775 776 777 778 779
                      NullS);
        if (file->raid_type)
        {
          char buff[100];
          sprintf(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);
          ptr=strmov(ptr,buff);
        }
780
        protocol->store(option_buff+1,
781 782
			(ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1)
			, system_charset_info);
unknown's avatar
unknown committed
783
      }
784 785
      {
	char *comment=table->file->update_table_comment(table->comment);
786
	protocol->store(comment, system_charset_info);
787 788 789
	if (comment != table->comment)
	  my_free(comment,MYF(0));
      }
unknown's avatar
unknown committed
790 791
      close_thread_tables(thd,0);
    }
792
    if (protocol->write())
unknown's avatar
unknown committed
793 794
      DBUG_RETURN(-1);
  }
795
  send_eof(thd);
unknown's avatar
unknown committed
796 797 798 799 800
  DBUG_RETURN(0);
}


/***************************************************************************
801
** List all columns in a table_list->real_name
unknown's avatar
unknown committed
802
***************************************************************************/
unknown's avatar
SCRUM  
unknown committed
803

unknown's avatar
unknown committed
804
int
unknown's avatar
unknown committed
805 806
mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
		   bool verbose)
unknown's avatar
unknown committed
807 808 809 810
{
  TABLE *table;
  handler *file;
  char tmp[MAX_FIELD_WIDTH];
811
  char tmp1[MAX_FIELD_WIDTH];
unknown's avatar
unknown committed
812
  Item *item;
813
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
814 815
  DBUG_ENTER("mysqld_show_fields");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
816
                      table_list->real_name));
unknown's avatar
unknown committed
817 818 819

  if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  {
820
    send_error(thd);
unknown's avatar
unknown committed
821 822 823 824
    DBUG_RETURN(1);
  }
  file=table->file;
  file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
unknown's avatar
unknown committed
825
#ifndef NO_EMBEDDED_ACCESS_CHECKS
unknown's avatar
unknown committed
826
  (void) get_table_grant(thd, table_list);
unknown's avatar
unknown committed
827
#endif
unknown's avatar
unknown committed
828 829 830
  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));
831 832
  if (verbose)
    field_list.push_back(new Item_empty_string("Collation",40));
unknown's avatar
unknown committed
833 834
  field_list.push_back(new Item_empty_string("Null",1));
  field_list.push_back(new Item_empty_string("Key",3));
unknown's avatar
unknown committed
835 836
  field_list.push_back(item=new Item_empty_string("Default",NAME_LEN));
  item->maybe_null=1;
unknown's avatar
unknown committed
837
  field_list.push_back(new Item_empty_string("Extra",20));
unknown's avatar
unknown committed
838
  if (verbose)
839
  {
unknown's avatar
unknown committed
840
    field_list.push_back(new Item_empty_string("Privileges",80));
841 842
    field_list.push_back(new Item_empty_string("Comment",255));
  }
843
        // Send first number of fields and records
unknown's avatar
SCRUM  
unknown committed
844 845
  if (protocol->send_records_num(&field_list, (ulonglong)file->records) ||
      protocol->send_fields(&field_list,0))
unknown's avatar
unknown committed
846
    DBUG_RETURN(1);
unknown's avatar
unknown committed
847
  restore_record(table,default_values);      // Get empty record
unknown's avatar
unknown committed
848 849 850 851

  Field **ptr,*field;
  for (ptr=table->field; (field= *ptr) ; ptr++)
  {
852 853
    if (!wild || !wild[0] || 
        !wild_case_compare(system_charset_info, field->field_name,wild))
unknown's avatar
unknown committed
854 855
    {
      {
856 857
        byte *pos;
        uint flags=field->flags;
858
        String type(tmp,sizeof(tmp), system_charset_info);
859
#ifndef NO_EMBEDDED_ACCESS_CHECKS
860
        uint col_access;
861
#endif
862
	protocol->prepare_for_resend();
863
        protocol->store(field->field_name, system_charset_info);
864
        field->sql_type(type);
865
        protocol->store(type.ptr(), type.length(), system_charset_info);
866 867
	if (verbose)
	  protocol->store(field->has_charset() ? field->charset()->name : "NULL",
868
			system_charset_info);
869 870 871 872 873 874
        /*
          Altough TIMESTAMP fields can't contain NULL as its value they
          will accept NULL if you will try to insert such value and will
          convert it to current TIMESTAMP. So YES here means that NULL 
          is allowed for assignment but can't be returned.
        */
875 876 877
        pos=(byte*) ((flags & NOT_NULL_FLAG) &&
                     field->type() != FIELD_TYPE_TIMESTAMP ?
                     "" : "YES");
878
        protocol->store((const char*) pos, system_charset_info);
879 880 881
        pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
                     (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
                     (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
882
        protocol->store((char*) pos, system_charset_info);
883

884 885 886 887 888 889 890 891 892
        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);
        }
893
        else if (field->unireg_check != Field::NEXT_NUMBER &&
894
                 !field->is_null())
895
        {                                               // Not null by default
896 897 898 899 900 901 902 903 904 905 906 907 908
          /*
            Note: we have to convert the default value into
            system_charset_info before sending.
            This is necessary for "SET NAMES binary":
            If the client character set is binary, we want to
            send metadata in UTF8 rather than in the column's
            character set.
            This conversion also makes "SHOW COLUMNS" and
            "SHOW CREATE TABLE" output consistent. Without
            this conversion the default values were displayed
            differently.
          */
          String def(tmp1,sizeof(tmp1), system_charset_info);
909
          type.set(tmp, sizeof(tmp), field->charset());
910
          field->val_str(&type);
911 912 913
          def.copy(type.ptr(), type.length(), type.charset(), 
                   system_charset_info);
          protocol->store(def.ptr(), def.length(), def.charset());
914
        }
915 916
        else if (field->unireg_check == Field::NEXT_NUMBER ||
                 field->maybe_null())
917
          protocol->store_null();                       // Null as default
918
        else
919
          protocol->store("",0, system_charset_info);	// empty string
920 921 922 923

        char *end=tmp;
        if (field->unireg_check == Field::NEXT_NUMBER)
          end=strmov(tmp,"auto_increment");
924
        protocol->store(tmp,(uint) (end-tmp), system_charset_info);
925

unknown's avatar
unknown committed
926 927
	if (verbose)
	{
928
	  /* Add grant options & comments */
unknown's avatar
unknown committed
929
	  end=tmp;
unknown's avatar
unknown committed
930
#ifndef NO_EMBEDDED_ACCESS_CHECKS
931
	  col_access= get_column_grant(thd,table_list,field) & COL_ACLS;
unknown's avatar
unknown committed
932 933 934 935 936 937 938 939
	  for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
	  {
	    if (col_access & 1)
	    {
	      *end++=',';
	      end=strmov(end,grant_types.type_names[bitnr]);
	    }
	  }
unknown's avatar
unknown committed
940 941 942
#else
	  end=strmov(end,"");
#endif
943 944 945 946
	  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);
unknown's avatar
unknown committed
947
	}
948
        if (protocol->write())
949
          DBUG_RETURN(1);
unknown's avatar
unknown committed
950 951 952
      }
    }
  }
953
  send_eof(thd);
unknown's avatar
unknown committed
954 955 956
  DBUG_RETURN(0);
}

957

unknown's avatar
unknown committed
958 959 960 961
int
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
  TABLE *table;
962 963 964
  Protocol *protocol= thd->protocol;
  char buff[2048];
  String buffer(buff, sizeof(buff), system_charset_info);
unknown's avatar
unknown committed
965 966
  DBUG_ENTER("mysqld_show_create");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
967
                      table_list->real_name));
unknown's avatar
unknown committed
968

unknown's avatar
unknown committed
969
  /* Only one table for now */
unknown's avatar
unknown committed
970 971
  if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  {
972
    send_error(thd);
unknown's avatar
unknown committed
973 974 975
    DBUG_RETURN(1);
  }

unknown's avatar
unknown committed
976
  if (store_create_info(thd, table, &buffer))
977 978
    DBUG_RETURN(-1);

unknown's avatar
unknown committed
979 980
  List<Item> field_list;
  field_list.push_back(new Item_empty_string("Table",NAME_LEN));
unknown's avatar
unknown committed
981
  // 1024 is for not to confuse old clients
982
  field_list.push_back(new Item_empty_string("Create Table",
unknown's avatar
unknown committed
983
					     max(buffer.length(),1024)));
unknown's avatar
unknown committed
984

985 986 987
  if (protocol->send_fields(&field_list, 1))
    DBUG_RETURN(1);
  protocol->prepare_for_resend();
988
  protocol->store(table->table_name, system_charset_info);
989
  buffer.length(0);
990 991
  if (store_create_info(thd, table, &buffer))
    DBUG_RETURN(-1);
992
  protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
993
  if (protocol->write())
unknown's avatar
unknown committed
994
    DBUG_RETURN(1);
995
  send_eof(thd);
unknown's avatar
unknown committed
996 997 998
  DBUG_RETURN(0);
}

999 1000 1001 1002 1003 1004 1005
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);
unknown's avatar
unknown committed
1006
#ifndef NO_EMBEDDED_ACCESS_CHECKS
1007
  uint db_access;
unknown's avatar
unknown committed
1008
#endif
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088
  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))
  {
    net_printf(thd,ER_WRONG_DB_NAME, dbname);
    DBUG_RETURN(1);
  }

#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("Database",NAME_LEN));
  field_list.push_back(new Item_empty_string("Create Database",1024));

  if (protocol->send_fields(&field_list,1))
    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));

  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);
}
unknown's avatar
unknown committed
1089

unknown's avatar
unknown committed
1090 1091 1092
int
mysqld_show_logs(THD *thd)
{
1093 1094
  List<Item> field_list;
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
1095 1096 1097 1098 1099 1100
  DBUG_ENTER("mysqld_show_logs");

  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));

1101
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
1102 1103
    DBUG_RETURN(1);

1104
#ifdef HAVE_BERKELEY_DB
1105
  if ((have_berkeley_db == SHOW_OPTION_YES) && berkeley_show_logs(protocol))
unknown's avatar
unknown committed
1106
    DBUG_RETURN(-1);
1107
#endif
unknown's avatar
unknown committed
1108

1109
  send_eof(thd);
unknown's avatar
unknown committed
1110 1111 1112 1113
  DBUG_RETURN(0);
}


unknown's avatar
unknown committed
1114 1115 1116 1117
int
mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
{
  TABLE *table;
1118
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
1119 1120
  DBUG_ENTER("mysqld_show_keys");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
1121
                      table_list->real_name));
unknown's avatar
unknown committed
1122 1123 1124

  if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  {
1125
    send_error(thd);
unknown's avatar
unknown committed
1126 1127 1128 1129 1130 1131
    DBUG_RETURN(1);
  }

  List<Item> field_list;
  Item *item;
  field_list.push_back(new Item_empty_string("Table",NAME_LEN));
1132
  field_list.push_back(new Item_return_int("Non_unique",1, MYSQL_TYPE_TINY));
unknown's avatar
unknown committed
1133
  field_list.push_back(new Item_empty_string("Key_name",NAME_LEN));
1134
  field_list.push_back(new Item_return_int("Seq_in_index",2, MYSQL_TYPE_TINY));
unknown's avatar
unknown committed
1135 1136 1137
  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;
1138
  field_list.push_back(item=new Item_int("Cardinality",0,21));
unknown's avatar
unknown committed
1139
  item->maybe_null=1;
1140 1141
  field_list.push_back(item=new Item_return_int("Sub_part",3,
						MYSQL_TYPE_TINY));
unknown's avatar
unknown committed
1142 1143 1144
  item->maybe_null=1;
  field_list.push_back(item=new Item_empty_string("Packed",10));
  item->maybe_null=1;
1145 1146
  field_list.push_back(new Item_empty_string("Null",3));
  field_list.push_back(new Item_empty_string("Index_type",16));
unknown's avatar
unknown committed
1147 1148 1149
  field_list.push_back(new Item_empty_string("Comment",255));
  item->maybe_null=1;

1150
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
1151 1152 1153 1154 1155 1156 1157
    DBUG_RETURN(1);

  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;
1158
    const char *str;
unknown's avatar
unknown committed
1159 1160
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
    {
1161
      protocol->prepare_for_resend();
1162
      protocol->store(table->table_name, system_charset_info);
1163
      protocol->store_tiny((longlong) ((key_info->flags & HA_NOSAME) ? 0 :1));
1164
      protocol->store(key_info->name, system_charset_info);
1165 1166 1167
      protocol->store_tiny((longlong) (j+1));
      str=(key_part->field ? key_part->field->field_name :
	   "?unknown field?");
1168
      protocol->store(str, system_charset_info);
1169
      if (table->file->index_flags(i, j, 0) & HA_READ_ORDER)
1170
        protocol->store(((key_part->key_part_flag & HA_REVERSE_SORT) ?
1171
			 "D" : "A"), 1, system_charset_info);
unknown's avatar
unknown committed
1172
      else
1173
        protocol->store_null(); /* purecov: inspected */
unknown's avatar
unknown committed
1174 1175 1176
      KEY *key=table->key_info+i;
      if (key->rec_per_key[j])
      {
1177
        ha_rows records=(table->file->records / key->rec_per_key[j]);
1178
        protocol->store((ulonglong) records);
unknown's avatar
unknown committed
1179 1180
      }
      else
1181
        protocol->store_null();
1182 1183

      /* Check if we have a key part that only uses part of the field */
unknown's avatar
unknown committed
1184 1185
      if (!(key_info->flags & HA_FULLTEXT) && (!key_part->field ||
          key_part->length != table->field[key_part->fieldnr-1]->key_length()))
1186
        protocol->store_tiny((longlong) key_part->length);
unknown's avatar
unknown committed
1187
      else
1188 1189
        protocol->store_null();
      protocol->store_null();                   // No pack_information yet
1190 1191 1192

      /* Null flag */
      uint flags= key_part->field ? key_part->field->flags : 0;
unknown's avatar
unknown committed
1193
      char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
1194 1195
      protocol->store((const char*) pos, system_charset_info);
      protocol->store(table->file->index_type(i), system_charset_info);
1196
      /* Comment */
1197
      if (!table->keys_in_use.is_set(i))
unknown's avatar
unknown committed
1198
	protocol->store("disabled",8, system_charset_info);
1199
      else
unknown's avatar
unknown committed
1200
        protocol->store("", 0, system_charset_info);
1201
      if (protocol->write())
1202
        DBUG_RETURN(1); /* purecov: inspected */
unknown's avatar
unknown committed
1203 1204
    }
  }
1205
  send_eof(thd);
unknown's avatar
unknown committed
1206 1207 1208 1209 1210
  DBUG_RETURN(0);
}


/****************************************************************************
1211 1212
  Return only fields for API mysql_list_fields
  Use "show table wildcard" in mysql instead of this
unknown's avatar
unknown committed
1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
****************************************************************************/

void
mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
{
  TABLE *table;
  DBUG_ENTER("mysqld_list_fields");
  DBUG_PRINT("enter",("table: %s",table_list->real_name));

  if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  {
1224
    send_error(thd);
unknown's avatar
unknown committed
1225 1226 1227 1228 1229 1230 1231
    DBUG_VOID_RETURN;
  }
  List<Item> field_list;

  Field **ptr,*field;
  for (ptr=table->field ; (field= *ptr); ptr++)
  {
1232 1233
    if (!wild || !wild[0] || 
        !wild_case_compare(system_charset_info, field->field_name,wild))
unknown's avatar
unknown committed
1234
      field_list.push_back(new Item_field(field));
unknown's avatar
unknown committed
1235
  }
unknown's avatar
unknown committed
1236
  restore_record(table,default_values);              // Get empty record
1237
  if (thd->protocol->send_fields(&field_list,2))
unknown's avatar
unknown committed
1238
    DBUG_VOID_RETURN;
1239
  net_flush(&thd->net);
unknown's avatar
unknown committed
1240 1241 1242
  DBUG_VOID_RETURN;
}

1243

unknown's avatar
unknown committed
1244 1245 1246
int
mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
{
1247 1248
  Protocol *protocol= thd->protocol;
  String *packet= protocol->storage_packet();
unknown's avatar
unknown committed
1249 1250
  DBUG_ENTER("mysqld_dump_create_info");
  DBUG_PRINT("enter",("table: %s",table->real_name));
1251

1252 1253
  protocol->prepare_for_resend();
  if (store_create_info(thd, table, packet))
unknown's avatar
unknown committed
1254
    DBUG_RETURN(-1);
1255

unknown's avatar
unknown committed
1256 1257
  //if (protocol->convert)
  //  protocol->convert->convert((char*) packet->ptr(), packet->length());
1258
  if (fd < 0)
1259
  {
1260
    if (protocol->write())
1261
      DBUG_RETURN(-1);
1262
    net_flush(&thd->net);
1263
  }
unknown's avatar
unknown committed
1264
  else
1265
  {
1266 1267
    if (my_write(fd, (const byte*) packet->ptr(), packet->length(),
		 MYF(MY_WME)))
1268 1269
      DBUG_RETURN(-1);
  }
unknown's avatar
unknown committed
1270 1271
  DBUG_RETURN(0);
}
1272

1273
/*
1274 1275
  Go through all character combinations and ensure that sql_lex.cc can
  parse it as an identifer.
1276 1277

  SYNOPSIS
1278 1279 1280 1281 1282 1283 1284
  require_quotes()
  name			attribute name
  name_length		length of name

  RETURN
    #	Pointer to conflicting character
    0	No conflicting character
1285 1286
*/

1287
static const char *require_quotes(const char *name, uint name_length)
1288
{
1289 1290 1291 1292
  uint length;
  const char *end= name + name_length;

  for ( ; name < end ; name++)
1293
  {
1294 1295 1296 1297
    uchar chr= (uchar) *name;
    length= my_mbcharlen(system_charset_info, chr);
    if (length == 1 && !system_charset_info->ident_map[chr])
      return name;
1298 1299 1300
  }
  return 0;
}
1301

1302 1303 1304 1305 1306 1307 1308 1309 1310 1311

static void append_quoted_simple_identifier(String *packet, char quote_char,
					    const char *name, uint length)
{
  packet->append(&quote_char, 1, system_charset_info);
  packet->append(name, length, system_charset_info);
  packet->append(&quote_char, 1, system_charset_info);
}  


1312 1313
void
append_identifier(THD *thd, String *packet, const char *name, uint length)
1314
{
1315 1316 1317
  const char *name_end;
  char quote_char;

1318
  if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
1319
    quote_char= '\"';
1320
  else
1321
    quote_char= '`';
1322

1323
  if (is_keyword(name,length))
1324
  {
1325 1326
    append_quoted_simple_identifier(packet, quote_char, name, length);
    return;
1327
  }
1328 1329

  if (!require_quotes(name, length))
1330
  {
1331
    if (!(thd->options & OPTION_QUOTE_SHOW_CREATE))
1332
      packet->append(name, length, system_charset_info);
1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349
    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(&quote_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(&quote_char, 1, system_charset_info);
    packet->append(name, length, packet->charset());
1350
  }
1351
  packet->append(&quote_char, 1, system_charset_info);
1352 1353
}

1354 1355 1356 1357 1358 1359 1360

/* Append directory name (if exists) to CREATE INFO */

static void append_directory(THD *thd, String *packet, const char *dir_type,
			     const char *filename)
{
  uint length;
unknown's avatar
unknown committed
1361
  if (filename && !(thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372
  {
    length= dirname_length(filename);
    packet->append(' ');
    packet->append(dir_type);
    packet->append(" DIRECTORY='", 12);
    packet->append(filename, length);
    packet->append('\'');
  }
}


unknown's avatar
unknown committed
1373
#define LIST_PROCESS_HOST_LEN 64
1374

unknown's avatar
unknown committed
1375
static int
1376
store_create_info(THD *thd, TABLE *table, String *packet)
unknown's avatar
unknown committed
1377
{
1378
  List<Item> field_list;
unknown's avatar
unknown committed
1379
  char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end, *alias;
1380
  String type(tmp, sizeof(tmp), system_charset_info);
1381 1382 1383 1384 1385
  Field **ptr,*field;
  uint primary_key;
  KEY *key_info;
  handler *file= table->file;
  HA_CREATE_INFO create_info;
1386 1387 1388 1389
  my_bool foreign_db_mode=    (thd->variables.sql_mode & (MODE_POSTGRESQL |
							  MODE_ORACLE |
							  MODE_MSSQL |
							  MODE_DB2 |
1390
							  MODE_MAXDB |
1391 1392 1393 1394
							  MODE_ANSI)) != 0;
  my_bool limited_mysql_mode= (thd->variables.sql_mode &
			       (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
				MODE_MYSQL40)) != 0;
1395

unknown's avatar
unknown committed
1396 1397 1398
  DBUG_ENTER("store_create_info");
  DBUG_PRINT("enter",("table: %s",table->real_name));

unknown's avatar
unknown committed
1399
  restore_record(table,default_values); // Get empty record
1400

1401 1402 1403 1404
  if (table->tmp_table)
    packet->append("CREATE TEMPORARY TABLE ", 23);
  else
    packet->append("CREATE TABLE ", 13);
unknown's avatar
unknown committed
1405 1406 1407
  alias= (lower_case_table_names == 2 ? table->table_name :
	  table->real_name);
  append_identifier(thd, packet, alias, strlen(alias));
1408
  packet->append(" (\n", 3);
1409

unknown's avatar
unknown committed
1410 1411
  for (ptr=table->field ; (field= *ptr); ptr++)
  {
1412
    bool has_default;
1413
    bool has_now_default;
1414 1415
    uint flags = field->flags;

1416
    if (ptr != table->field)
1417
      packet->append(",\n", 2);
1418

1419
    packet->append("  ", 2);
1420
    append_identifier(thd,packet,field->field_name, strlen(field->field_name));
unknown's avatar
unknown committed
1421 1422
    packet->append(' ');
    // check for surprises from the previous call to Field::sql_type()
1423
    if (type.ptr() != tmp)
1424
      type.set(tmp, sizeof(tmp), system_charset_info);
1425

unknown's avatar
unknown committed
1426
    field->sql_type(type);
1427
    packet->append(type.ptr(), type.length(), system_charset_info);
1428

1429
    if (field->has_charset() && !limited_mysql_mode && !foreign_db_mode)
1430
    {
1431
      if (field->charset() != table->table_charset)
1432
      {
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443
	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);
1444
      }
1445
    }
1446

1447 1448
    if (flags & NOT_NULL_FLAG)
      packet->append(" NOT NULL", 9);
1449

1450 1451

    /* 
1452
      Again we are using CURRENT_TIMESTAMP instead of NOW because it is
1453 1454 1455 1456 1457
      more standard 
    */
    has_now_default= table->timestamp_field == field && 
                     field->unireg_check != Field::TIMESTAMP_UN_FIELD;
    
1458
    has_default= (field->type() != FIELD_TYPE_BLOB &&
1459 1460 1461
		  field->unireg_check != Field::NEXT_NUMBER &&
                  !((foreign_db_mode || limited_mysql_mode) &&
                    has_now_default));
1462

1463
    if (has_default)
1464 1465
    {
      packet->append(" default ", 9);
1466 1467 1468
      if (has_now_default)
        packet->append("CURRENT_TIMESTAMP",17);
      else if (!field->is_null())
1469
      {                                             // Not null by default
1470
        type.set(tmp, sizeof(tmp), field->charset());
1471
        field->val_str(&type);
1472
	if (type.length())
1473
	{
1474
	  String def_val;
1475 1476 1477 1478 1479
	  /* 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());
	}
1480 1481
        else
	  packet->append("''",2);
unknown's avatar
unknown committed
1482
      }
1483
      else if (field->maybe_null())
1484 1485
        packet->append("NULL", 4);                    // Null as default
      else
1486
        packet->append(tmp);
1487
    }
1488

1489 1490 1491 1492 1493
    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);

1494
    if (field->unireg_check == Field::NEXT_NUMBER && !foreign_db_mode)
1495 1496 1497 1498 1499 1500 1501
      packet->append(" auto_increment", 15 );

    if (field->comment.length)
    {
      packet->append(" COMMENT ",9);
      append_unescaped(packet, field->comment.str, field->comment.length);
    }
unknown's avatar
unknown committed
1502 1503
  }

1504 1505
  key_info= table->key_info;
  file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
1506
  bzero((char*) &create_info, sizeof(create_info));
1507 1508
  file->update_create_info(&create_info);
  primary_key= table->primary_key;
1509

unknown's avatar
unknown committed
1510 1511
  for (uint i=0 ; i < table->keys ; i++,key_info++)
  {
1512 1513
    KEY_PART_INFO *key_part= key_info->key_part;
    bool found_primary=0;
1514
    packet->append(",\n  ", 4);
1515

1516
    if (i == primary_key && !strcmp(key_info->name, primary_key_name))
1517 1518
    {
      found_primary=1;
1519
      packet->append("PRIMARY ", 8);
1520
    }
1521
    else if (key_info->flags & HA_NOSAME)
1522
      packet->append("UNIQUE ", 7);
1523
    else if (key_info->flags & HA_FULLTEXT)
1524
      packet->append("FULLTEXT ", 9);
unknown's avatar
unknown committed
1525 1526
    else if (key_info->flags & HA_SPATIAL)
      packet->append("SPATIAL ", 8);
1527
    packet->append("KEY ", 4);
unknown's avatar
unknown committed
1528

1529
    if (!found_primary)
1530
     append_identifier(thd, packet, key_info->name, strlen(key_info->name));
unknown's avatar
unknown committed
1531

1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543
    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);
    }
1544
    packet->append(" (", 2);
1545

unknown's avatar
unknown committed
1546 1547
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
    {
1548
      if (j)
1549
        packet->append(',');
1550

1551
      if (key_part->field)
1552 1553
        append_identifier(thd,packet,key_part->field->field_name,
			  strlen(key_part->field->field_name));
unknown's avatar
unknown committed
1554
      if (!key_part->field ||
1555 1556 1557
          (key_part->length !=
           table->field[key_part->fieldnr-1]->key_length() &&
           !(key_info->flags & HA_FULLTEXT)))
unknown's avatar
unknown committed
1558
      {
1559
        buff[0] = '(';
1560 1561 1562
        char* end=int10_to_str((long) key_part->length / 
			       key_part->field->charset()->mbmaxlen,
			       buff + 1,10);
1563 1564
        *end++ = ')';
        packet->append(buff,(uint) (end-buff));
unknown's avatar
unknown committed
1565 1566 1567 1568
      }
    }
    packet->append(')');
  }
1569

1570 1571 1572 1573
  /*
    Get possible foreign key definitions stored in InnoDB and append them
    to the CREATE TABLE statement
  */
1574

1575
  if ((for_str= file->get_foreign_key_create_info()))
1576 1577 1578
  {
    packet->append(for_str, strlen(for_str));
    file->free_foreign_key_create_info(for_str);
1579 1580 1581
  }

  packet->append("\n)", 2);
1582
  if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
1583
  {
unknown's avatar
unknown committed
1584 1585 1586 1587
    if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
      packet->append(" TYPE=", 6);
    else
      packet->append(" ENGINE=", 8);
1588 1589
    packet->append(file->table_type());
    
1590 1591 1592
    if (table->table_charset &&
	!(thd->variables.sql_mode & MODE_MYSQL323) &&
	!(thd->variables.sql_mode & MODE_MYSQL40))
1593
    {
1594
      packet->append(" DEFAULT CHARSET=", 17);
1595 1596 1597
      packet->append(table->table_charset->csname);
      if (!(table->table_charset->state & MY_CS_PRIMARY))
      {
1598
	packet->append(" COLLATE=", 9);
1599 1600
	packet->append(table->table_charset->name);
      }
1601
    }
1602

1603 1604
    if (table->min_rows)
    {
1605
      packet->append(" MIN_ROWS=", 10);
unknown's avatar
unknown committed
1606 1607
      end= longlong10_to_str(table->min_rows, buff, 10);
      packet->append(buff, (uint) (end- buff));
1608
    }
unknown's avatar
unknown committed
1609

1610 1611
    if (table->max_rows)
    {
1612
      packet->append(" MAX_ROWS=", 10);
unknown's avatar
unknown committed
1613 1614
      end= longlong10_to_str(table->max_rows, buff, 10);
      packet->append(buff, (uint) (end - buff));
1615
    }
unknown's avatar
unknown committed
1616

1617 1618
    if (table->avg_row_length)
    {
1619
      packet->append(" AVG_ROW_LENGTH=", 16);
unknown's avatar
unknown committed
1620 1621
      end= longlong10_to_str(table->avg_row_length, buff,10);
      packet->append(buff, (uint) (end - buff));
1622
    }
1623

1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644
    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)
    {
unknown's avatar
unknown committed
1645 1646 1647 1648 1649 1650
      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);
1651
    }
unknown's avatar
unknown committed
1652 1653
    append_directory(thd, packet, "DATA",  create_info.data_file_name);
    append_directory(thd, packet, "INDEX", create_info.index_file_name);
1654
  }
unknown's avatar
unknown committed
1655 1656 1657 1658 1659
  DBUG_RETURN(0);
}


/****************************************************************************
1660 1661
  Return info about all processes
  returns for each thread: thread id, user, host, db, command, info
unknown's avatar
unknown committed
1662 1663 1664 1665
****************************************************************************/

class thread_info :public ilink {
public:
unknown's avatar
unknown committed
1666
  static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
unknown's avatar
unknown committed
1667
  static void operator delete(void *ptr __attribute__((unused)),
1668
                              size_t size __attribute__((unused))) {} /*lint -e715 */
unknown's avatar
unknown committed
1669

unknown's avatar
unknown committed
1670 1671
  ulong thread_id;
  time_t start_time;
1672
  uint   command;
unknown's avatar
unknown committed
1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685
  const char *user,*host,*db,*proc_info,*state_info;
  char *query;
};

#ifdef __GNUC__
template class I_List<thread_info>;
#endif

void mysqld_list_processes(THD *thd,const char *user, bool verbose)
{
  Item *field;
  List<Item> field_list;
  I_List<thread_info> thread_infos;
unknown's avatar
unknown committed
1686 1687
  ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
			   PROCESS_LIST_WIDTH);
1688
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
1689 1690
  DBUG_ENTER("mysqld_list_processes");

1691
  field_list.push_back(new Item_int("Id",0,11));
unknown's avatar
unknown committed
1692
  field_list.push_back(new Item_empty_string("User",16));
1693
  field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
unknown's avatar
unknown committed
1694 1695 1696
  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));
1697
  field_list.push_back(new Item_return_int("Time",7, FIELD_TYPE_LONG));
unknown's avatar
unknown committed
1698 1699 1700 1701
  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;
1702
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
1703 1704 1705 1706 1707 1708 1709 1710 1711
    DBUG_VOID_RETURN;

  VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
  if (!thd->killed)
  {
    I_List_iterator<THD> it(threads);
    THD *tmp;
    while ((tmp=it++))
    {
1712
      struct st_my_thread_var *mysys_var;
1713
      if ((tmp->vio_ok() || tmp->system_thread) &&
1714
          (!user || (tmp->user && !strcmp(tmp->user,user))))
unknown's avatar
unknown committed
1715
      {
1716 1717 1718
        thread_info *thd_info=new thread_info;

        thd_info->thread_id=tmp->thread_id;
1719 1720 1721
        thd_info->user=thd->strdup(tmp->user ? tmp->user :
				   (tmp->system_thread ?
				    "system user" : "unauthenticated user"));
1722
	if (tmp->peer_port && (tmp->host || tmp->ip) && thd->host_or_ip[0])
1723 1724
	{
	  if ((thd_info->host= thd->alloc(LIST_PROCESS_HOST_LEN+1)))
unknown's avatar
unknown committed
1725
	    my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN,
1726
			"%s:%u", tmp->host_or_ip, tmp->peer_port);
1727 1728
	}
	else
1729
	  thd_info->host= thd->strdup(tmp->host_or_ip);
1730 1731 1732
        if ((thd_info->db=tmp->db))             // Safe test
          thd_info->db=thd->strdup(thd_info->db);
        thd_info->command=(int) tmp->command;
1733 1734
        if ((mysys_var= tmp->mysys_var))
          pthread_mutex_lock(&mysys_var->mutex);
1735
        thd_info->proc_info= (char*) (tmp->killed ? "Killed" : 0);
unknown's avatar
SCRUM  
unknown committed
1736
#ifndef EMBEDDED_LIBRARY
1737 1738 1739 1740 1741 1742 1743 1744 1745 1746
        thd_info->state_info= (char*) (tmp->locked ? "Locked" :
                                       tmp->net.reading_or_writing ?
                                       (tmp->net.reading_or_writing == 2 ?
                                        "Writing to net" :
                                        thd_info->command == COM_SLEEP ? "" :
                                        "Reading from net") :
                                       tmp->proc_info ? tmp->proc_info :
                                       tmp->mysys_var &&
                                       tmp->mysys_var->current_cond ?
                                       "Waiting on cond" : NullS);
unknown's avatar
SCRUM  
unknown committed
1747 1748 1749
#else
        thd_info->state_info= (char*)"Writing to net";
#endif
1750 1751
        if (mysys_var)
          pthread_mutex_unlock(&mysys_var->mutex);
unknown's avatar
unknown committed
1752 1753

#if !defined(DONT_USE_THR_ALARM) && ! defined(SCO)
1754 1755
        if (pthread_kill(tmp->real_id,0))
          tmp->proc_info="*** DEAD ***";        // This shouldn't happen
unknown's avatar
unknown committed
1756
#endif
unknown's avatar
unknown committed
1757 1758 1759
#ifdef EXTRA_DEBUG
        thd_info->start_time= tmp->time_after_lock;
#else
1760
        thd_info->start_time= tmp->start_time;
unknown's avatar
unknown committed
1761
#endif
1762 1763 1764
        thd_info->query=0;
        if (tmp->query)
        {
unknown's avatar
unknown committed
1765 1766 1767 1768 1769
	  /* 
            query_length is always set to 0 when we set query = NULL; see
	    the comment in sql_class.h why this prevents crashes in possible
            races with query_length
          */
unknown's avatar
unknown committed
1770
          uint length= min(max_query_length, tmp->query_length);
1771
          thd_info->query=(char*) thd->strmake(tmp->query,length);
1772 1773
        }
        thread_infos.append(thd_info);
unknown's avatar
unknown committed
1774 1775 1776 1777 1778 1779
      }
    }
  }
  VOID(pthread_mutex_unlock(&LOCK_thread_count));

  thread_info *thd_info;
1780
  time_t now= time(0);
unknown's avatar
unknown committed
1781 1782
  while ((thd_info=thread_infos.get()))
  {
1783 1784
    protocol->prepare_for_resend();
    protocol->store((ulonglong) thd_info->thread_id);
1785 1786 1787
    protocol->store(thd_info->user, system_charset_info);
    protocol->store(thd_info->host, system_charset_info);
    protocol->store(thd_info->db, system_charset_info);
unknown's avatar
unknown committed
1788
    if (thd_info->proc_info)
1789
      protocol->store(thd_info->proc_info, system_charset_info);
unknown's avatar
unknown committed
1790
    else
1791
      protocol->store(command_name[thd_info->command], system_charset_info);
unknown's avatar
unknown committed
1792
    if (thd_info->start_time)
1793
      protocol->store((uint32) (now - thd_info->start_time));
unknown's avatar
unknown committed
1794
    else
1795
      protocol->store_null();
1796 1797
    protocol->store(thd_info->state_info, system_charset_info);
    protocol->store(thd_info->query, system_charset_info);
1798
    if (protocol->write())
unknown's avatar
unknown committed
1799 1800
      break; /* purecov: inspected */
  }
1801
  send_eof(thd);
unknown's avatar
unknown committed
1802 1803 1804 1805
  DBUG_VOID_RETURN;
}

/*****************************************************************************
unknown's avatar
unknown committed
1806
  Status functions
unknown's avatar
unknown committed
1807 1808
*****************************************************************************/

1809 1810 1811 1812
static bool write_collation(Protocol *protocol, CHARSET_INFO *cs)
{
  protocol->prepare_for_resend();
  protocol->store(cs->name, system_charset_info);
1813
  protocol->store(cs->csname, system_charset_info);
1814
  protocol->store_short((longlong) cs->number);
1815 1816
  protocol->store((cs->state & MY_CS_PRIMARY) ? "Yes" : "",system_charset_info);
  protocol->store((cs->state & MY_CS_COMPILED)? "Yes" : "",system_charset_info);
1817 1818 1819 1820 1821
  protocol->store_short((longlong) cs->strxfrm_multiply);
  return protocol->write();
}

int mysqld_show_collations(THD *thd, const char *wild)
1822 1823
{
  char buff[8192];
unknown's avatar
unknown committed
1824
  String packet2(buff,sizeof(buff),thd->charset());
1825
  List<Item> field_list;
1826
  CHARSET_INFO **cs;
1827
  Protocol *protocol= thd->protocol;
1828

1829 1830
  DBUG_ENTER("mysqld_show_charsets");

1831
  field_list.push_back(new Item_empty_string("Collation",30));
1832
  field_list.push_back(new Item_empty_string("Charset",30));
1833
  field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT));
1834 1835
  field_list.push_back(new Item_empty_string("Default",30));
  field_list.push_back(new Item_empty_string("Compiled",30));
1836
  field_list.push_back(new Item_return_int("Sortlen",3, FIELD_TYPE_SHORT));
1837

1838
  if (protocol->send_fields(&field_list, 1))
1839 1840
    DBUG_RETURN(1);

1841
  for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ )
1842
  {
1843
    CHARSET_INFO **cl;
unknown's avatar
unknown committed
1844 1845 1846
    if (!cs[0] || !(cs[0]->state & MY_CS_AVAILABLE) || 
        !(cs[0]->state & MY_CS_PRIMARY))
      continue;
1847 1848
    for ( cl= all_charsets; cl < all_charsets+255 ;cl ++)
    {
unknown's avatar
unknown committed
1849 1850
      if (!cl[0] || !(cl[0]->state & MY_CS_AVAILABLE) || 
          !my_charset_same(cs[0],cl[0]))
1851
	continue;
unknown's avatar
unknown committed
1852
      if (!(wild && wild[0] &&
unknown's avatar
unknown committed
1853
	  wild_case_compare(system_charset_info,cl[0]->name,wild)))
1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869
      {
        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);
1870
  protocol->store(cs->comment ? cs->comment : "", system_charset_info);
1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886
  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));
1887
  field_list.push_back(new Item_empty_string("Description",60));
1888 1889 1890 1891 1892 1893 1894 1895
  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++ )
  {
unknown's avatar
unknown committed
1896 1897 1898 1899
    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)))
1900
    {
1901
      if (write_charset(protocol, cs[0]))
1902
	goto err;
1903 1904
    }
  }
1905
  send_eof(thd); 
1906 1907 1908 1909 1910
  DBUG_RETURN(0);
err:
  DBUG_RETURN(1);
}

unknown's avatar
unknown committed
1911
  
unknown's avatar
unknown committed
1912

1913
int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
1914 1915
		enum enum_var_type value_type,
		pthread_mutex_t *mutex)
unknown's avatar
unknown committed
1916
{
1917
  char buff[1024];
unknown's avatar
unknown committed
1918
  List<Item> field_list;
1919
  Protocol *protocol= thd->protocol;
1920
  LEX_STRING null_lex_str;
unknown's avatar
unknown committed
1921
  DBUG_ENTER("mysqld_show");
unknown's avatar
unknown committed
1922

unknown's avatar
unknown committed
1923 1924
  field_list.push_back(new Item_empty_string("Variable_name",30));
  field_list.push_back(new Item_empty_string("Value",256));
1925
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
1926
    DBUG_RETURN(1); /* purecov: inspected */
1927
  null_lex_str.str= 0;				// For sys_var->value_ptr()
1928
  null_lex_str.length= 0;
unknown's avatar
unknown committed
1929

1930
  pthread_mutex_lock(mutex);
unknown's avatar
unknown committed
1931
  for (; variables->name; variables++)
unknown's avatar
unknown committed
1932
  {
unknown's avatar
unknown committed
1933
    if (!(wild && wild[0] && wild_case_compare(system_charset_info,
1934
					       variables->name,wild)))
unknown's avatar
unknown committed
1935
    {
1936
      protocol->prepare_for_resend();
1937
      protocol->store(variables->name, system_charset_info);
unknown's avatar
unknown committed
1938 1939
      SHOW_TYPE show_type=variables->type;
      char *value=variables->value;
1940 1941 1942
      const char *pos, *end;
      long nr;

unknown's avatar
unknown committed
1943 1944 1945
      if (show_type == SHOW_SYS)
      {
	show_type= ((sys_var*) value)->type();
1946 1947
	value=     (char*) ((sys_var*) value)->value_ptr(thd, value_type,
							 &null_lex_str);
unknown's avatar
unknown committed
1948 1949
      }

1950
      pos= end= buff;
unknown's avatar
unknown committed
1951
      switch (show_type) {
unknown's avatar
unknown committed
1952 1953
      case SHOW_LONG:
      case SHOW_LONG_CONST:
1954
	end= int10_to_str(*(long*) value, buff, 10);
unknown's avatar
unknown committed
1955 1956
        break;
      case SHOW_LONGLONG:
1957
	end= longlong10_to_str(*(longlong*) value, buff, 10);
unknown's avatar
unknown committed
1958
	break;
1959
      case SHOW_HA_ROWS:
unknown's avatar
unknown committed
1960
        end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
1961
        break;
unknown's avatar
unknown committed
1962
      case SHOW_BOOL:
1963
	end= strmov(buff, *(bool*) value ? "ON" : "OFF");
1964
        break;
unknown's avatar
unknown committed
1965
      case SHOW_MY_BOOL:
1966
	end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
1967
        break;
unknown's avatar
unknown committed
1968 1969
      case SHOW_INT_CONST:
      case SHOW_INT:
1970
	end= int10_to_str((long) *(uint32*) value, buff, 10);
1971
        break;
1972 1973
      case SHOW_HAVE:
      {
unknown's avatar
unknown committed
1974
	SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
1975 1976
	pos= show_comp_option_name[(int) tmp];
	end= strend(pos);
1977 1978
        break;
      }
unknown's avatar
unknown committed
1979
      case SHOW_CHAR:
unknown's avatar
unknown committed
1980 1981 1982 1983
      {
        if (!(pos= value))
          pos= "";
        end= strend(pos);
1984
        break;
unknown's avatar
unknown committed
1985
       }
unknown's avatar
unknown committed
1986
      case SHOW_STARTTIME:
1987 1988
	nr= (long) (thd->query_start() - start_time);
	end= int10_to_str(nr, buff, 10);
1989
        break;
unknown's avatar
unknown committed
1990
      case SHOW_QUESTION:
1991
	end= int10_to_str((long) thd->query_id, buff, 10);
1992
        break;
unknown's avatar
unknown committed
1993
#ifdef HAVE_REPLICATION
1994
      case SHOW_RPL_STATUS:
unknown's avatar
unknown committed
1995
	end= strmov(buff, rpl_status_type[(int)rpl_status]);
1996
	break;
1997 1998
      case SHOW_SLAVE_RUNNING:
      {
1999
	pthread_mutex_lock(&LOCK_active_mi);
2000 2001
	end= strmov(buff, (active_mi->slave_running &&
			   active_mi->rli.slave_running) ? "ON" : "OFF");
2002
	pthread_mutex_unlock(&LOCK_active_mi);
2003 2004
	break;
      }
unknown's avatar
unknown committed
2005
#endif /* HAVE_REPLICATION */
unknown's avatar
unknown committed
2006
      case SHOW_OPENTABLES:
2007
	end= int10_to_str((long) cached_tables(), buff, 10);
2008
        break;
unknown's avatar
unknown committed
2009
      case SHOW_CHAR_PTR:
unknown's avatar
unknown committed
2010
      {
2011 2012 2013 2014
        if (!(pos= *(char**) value))
          pos= "";
        end= strend(pos);
        break;
unknown's avatar
unknown committed
2015
      }
unknown's avatar
unknown committed
2016
#ifdef HAVE_OPENSSL
unknown's avatar
unknown committed
2017
	/* First group - functions relying on CTX */
unknown's avatar
unknown committed
2018
      case SHOW_SSL_CTX_SESS_ACCEPT:
2019 2020
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_accept(ssl_acceptor_fd->
unknown's avatar
unknown committed
2021
						      ssl_context)),
2022
			  buff, 10);
unknown's avatar
unknown committed
2023 2024
        break;
      case SHOW_SSL_CTX_SESS_ACCEPT_GOOD:
2025 2026
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_accept_good(ssl_acceptor_fd->
unknown's avatar
unknown committed
2027
							   ssl_context)),
2028
			  buff, 10);
unknown's avatar
unknown committed
2029
        break;
2030
      case SHOW_SSL_CTX_SESS_CONNECT_GOOD:
2031 2032
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_connect_good(ssl_acceptor_fd->
unknown's avatar
unknown committed
2033
							    ssl_context)),
2034
			  buff, 10);
2035
        break;
unknown's avatar
unknown committed
2036
      case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE:
2037
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
2038
				  SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context)),
2039
			  buff, 10);
unknown's avatar
unknown committed
2040
        break;
2041
      case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE:
2042
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
2043
				  SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context)),
2044
			  buff, 10);
2045
        break;
unknown's avatar
unknown committed
2046
      case SHOW_SSL_CTX_SESS_CB_HITS:
2047 2048
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_cb_hits(ssl_acceptor_fd->
unknown's avatar
unknown committed
2049
						       ssl_context)),
2050
			  buff, 10);
unknown's avatar
unknown committed
2051
        break;
2052
      case SHOW_SSL_CTX_SESS_HITS:
2053 2054
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_hits(ssl_acceptor_fd->
unknown's avatar
unknown committed
2055
						    ssl_context)),
2056
			  buff, 10);
2057 2058
        break;
      case SHOW_SSL_CTX_SESS_CACHE_FULL:
2059 2060
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_cache_full(ssl_acceptor_fd->
unknown's avatar
unknown committed
2061
							  ssl_context)),
2062
			  buff, 10);
2063 2064
        break;
      case SHOW_SSL_CTX_SESS_MISSES:
2065 2066
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_misses(ssl_acceptor_fd->
unknown's avatar
unknown committed
2067
						      ssl_context)),
2068
			  buff, 10);
2069 2070
        break;
      case SHOW_SSL_CTX_SESS_TIMEOUTS:
2071
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
2072
				  SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context)),
2073
			  buff,10);
2074
        break;
unknown's avatar
unknown committed
2075
      case SHOW_SSL_CTX_SESS_NUMBER:
2076
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
2077
				  SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context)),
2078
			  buff,10);
unknown's avatar
unknown committed
2079
        break;
2080
      case SHOW_SSL_CTX_SESS_CONNECT:
2081
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
2082
				  SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)),
2083
			  buff,10);
2084
        break;
unknown's avatar
unknown committed
2085
      case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE:
2086
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
2087
				  SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context)),
2088
				  buff,10);
unknown's avatar
unknown committed
2089 2090
        break;
      case SHOW_SSL_CTX_GET_VERIFY_MODE:
2091
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
2092
				  SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)),
2093
			  buff,10);
unknown's avatar
unknown committed
2094 2095
        break;
      case SHOW_SSL_CTX_GET_VERIFY_DEPTH:
2096
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
2097
				  SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)),
2098
			  buff,10);
unknown's avatar
unknown committed
2099 2100
        break;
      case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE:
2101 2102
	if (!ssl_acceptor_fd)
	{
2103 2104
	  pos= "NONE";
	  end= pos+4;
2105 2106
	  break;
	}
2107
	switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
unknown's avatar
unknown committed
2108 2109
	{
          case SSL_SESS_CACHE_OFF:
2110
            pos= "OFF";
unknown's avatar
unknown committed
2111 2112
	    break;
          case SSL_SESS_CACHE_CLIENT:
2113
            pos= "CLIENT";
unknown's avatar
unknown committed
2114 2115
	    break;
          case SSL_SESS_CACHE_SERVER:
2116
            pos= "SERVER";
unknown's avatar
unknown committed
2117 2118
	    break;
          case SSL_SESS_CACHE_BOTH:
2119
            pos= "BOTH";
unknown's avatar
unknown committed
2120 2121
	    break;
          case SSL_SESS_CACHE_NO_AUTO_CLEAR:
2122
            pos= "NO_AUTO_CLEAR";
unknown's avatar
unknown committed
2123 2124
	    break;
          case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
2125
            pos= "NO_INTERNAL_LOOKUP";
unknown's avatar
unknown committed
2126 2127
	    break;
	  default:
2128
            pos= "Unknown";
unknown's avatar
unknown committed
2129 2130
	    break;
	}
2131
	end= strend(pos);
unknown's avatar
unknown committed
2132
        break;
unknown's avatar
unknown committed
2133 2134
	/* First group - functions relying on SSL */
      case SHOW_SSL_GET_VERSION:
unknown's avatar
unknown committed
2135 2136
	pos= (thd->net.vio->ssl_arg ?
	      SSL_get_version((SSL*) thd->net.vio->ssl_arg) : "");
2137
	end= strend(pos);
unknown's avatar
unknown committed
2138 2139
        break;
      case SHOW_SSL_SESSION_REUSED:
unknown's avatar
unknown committed
2140 2141 2142 2143 2144
	end= int10_to_str((long) (thd->net.vio->ssl_arg ?
				  SSL_session_reused((SSL*) thd->net.vio->
						     ssl_arg) :
				  0),
			  buff, 10);
unknown's avatar
unknown committed
2145 2146
        break;
      case SHOW_SSL_GET_DEFAULT_TIMEOUT:
unknown's avatar
unknown committed
2147 2148 2149 2150 2151
	end= int10_to_str((long) (thd->net.vio->ssl_arg ?
				  SSL_get_default_timeout((SSL*) thd->net.vio->
							  ssl_arg) :
				  0),
			  buff, 10);
unknown's avatar
unknown committed
2152 2153
        break;
      case SHOW_SSL_GET_VERIFY_MODE:
unknown's avatar
unknown committed
2154 2155 2156 2157 2158
	end= int10_to_str((long) (thd->net.vio->ssl_arg ?
				  SSL_get_verify_mode((SSL*) thd->net.vio->
						      ssl_arg):
				  0),
			  buff, 10);
unknown's avatar
unknown committed
2159 2160
        break;
      case SHOW_SSL_GET_VERIFY_DEPTH:
unknown's avatar
unknown committed
2161 2162 2163 2164 2165
	end= int10_to_str((long) (thd->net.vio->ssl_arg ?
				  SSL_get_verify_depth((SSL*) thd->net.vio->
						       ssl_arg):
				  0),
			  buff, 10);
unknown's avatar
unknown committed
2166 2167
        break;
      case SHOW_SSL_GET_CIPHER:
unknown's avatar
unknown committed
2168 2169
	pos= (thd->net.vio->ssl_arg ?
	      SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : "" );
2170
	end= strend(pos);
2171
	break;
2172
      case SHOW_SSL_GET_CIPHER_LIST:
2173
	if (thd->net.vio->ssl_arg)
2174
	{
2175
	  char *to= buff;
2176
	  for (int i=0 ; i++ ;)
2177
	  {
unknown's avatar
unknown committed
2178
	    const char *p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i);
2179 2180
	    if (p == NULL) 
	      break;
2181 2182
	    to= strmov(to, p);
	    *to++= ':';
2183
	  }
2184 2185 2186
	  if (to != buff)
	    to--;				// Remove last ':'
	  end= to;
2187
        }
unknown's avatar
unknown committed
2188
        break;
unknown's avatar
unknown committed
2189 2190

#endif /* HAVE_OPENSSL */
2191
      case SHOW_KEY_CACHE_LONG:
2192
      case SHOW_KEY_CACHE_CONST_LONG:
2193 2194 2195
	value= (value-(char*) &dflt_key_cache_var)+ (char*) sql_key_cache;
	end= int10_to_str(*(long*) value, buff, 10);
        break;
unknown's avatar
unknown committed
2196 2197
      case SHOW_UNDEF:				// Show never happen
      case SHOW_SYS:
2198
	break;					// Return empty string
unknown's avatar
SCRUM  
unknown committed
2199 2200
      default:
	break;
unknown's avatar
unknown committed
2201
      }
2202
      if (protocol->store(pos, (uint32) (end - pos), system_charset_info) ||
2203
	  protocol->write())
2204
        goto err;                               /* purecov: inspected */
unknown's avatar
unknown committed
2205 2206
    }
  }
unknown's avatar
unknown committed
2207
  pthread_mutex_unlock(mutex);
2208
  send_eof(thd);
unknown's avatar
unknown committed
2209 2210 2211
  DBUG_RETURN(0);

 err:
unknown's avatar
unknown committed
2212
  pthread_mutex_unlock(mutex);
unknown's avatar
unknown committed
2213 2214 2215 2216
  DBUG_RETURN(1);
}

#ifdef __GNUC__
unknown's avatar
unknown committed
2217
template class List_iterator_fast<char>;
unknown's avatar
unknown committed
2218 2219
template class List<char>;
#endif