sql_show.cc 57.8 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 34
static const char *grant_names[]={
  "select","insert","update","delete","create","drop","reload","shutdown",
  "process","file","grant","references","index","alter"};

static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
35 36
                               "grant_types",
                               grant_names};
unknown's avatar
unknown committed
37 38

static int mysql_find_files(THD *thd,List<char> *files, const char *db,
39
                            const char *path, const char *wild, bool dir);
unknown's avatar
unknown committed
40 41

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

unknown's avatar
unknown committed
44

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

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

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

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

unknown's avatar
unknown committed
74 75
  while ((file_name=it++))
  {
unknown's avatar
unknown committed
76
    if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
77
	acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
78
		thd->priv_user, file_name,0) ||
79
	(grant_option && !check_grant_db(thd, file_name)))
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 
***************************************************************************/

175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
struct show_table_type_st {
  const char *type;
  SHOW_COMP_OPTION *value;
  const char *comment;
};


SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES;

static struct show_table_type_st sys_table_types[]=
{
  {"MyISAM", &have_yes,
   "Default type from 3.23 with great performance"},
  {"HEAP"  , &have_yes,
   "Hash based, stored in memory, useful for temporary tables"},
  {"MERGE",  &have_yes,
   "Collection of identical MyISAM tables"},
  {"ISAM",   &have_isam,
   "Obsolete table type; Is replaced by MyISAM"},
  {"InnoDB", &have_innodb,
   "Supports transactions, row-level locking and foreign keys"},
  {"BDB",    &have_berkeley_db,
   "Supports transactions and page-level locking"},
  {NullS, NULL, NullS}
unknown's avatar
unknown committed
199 200
};

201

unknown's avatar
unknown committed
202 203 204
int mysqld_show_table_types(THD *thd)
{
  List<Item> field_list;
205
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
206 207 208 209
  DBUG_ENTER("mysqld_show_table_types");

  field_list.push_back(new Item_empty_string("Type",10));
  field_list.push_back(new Item_empty_string("Support",10));
210
  field_list.push_back(new Item_empty_string("Comment",80));
unknown's avatar
unknown committed
211

212
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
213 214
    DBUG_RETURN(1);

215 216
  const char *default_type_name=
    ha_table_typelib.type_names[thd->variables.table_type];
unknown's avatar
unknown committed
217

218 219
  show_table_type_st *types;
  for (types= sys_table_types; types->type; types++)
unknown's avatar
unknown committed
220
  {
221
    protocol->prepare_for_resend();
222
    protocol->store(types->type, system_charset_info);
223 224 225
    const char *option_name= show_comp_option_name[(int) *types->value];

    if (*types->value == SHOW_OPTION_YES &&
226
	!my_strcasecmp(system_charset_info, default_type_name, types->type))
227
      option_name= "DEFAULT";
228 229
    protocol->store(option_name, system_charset_info);
    protocol->store(types->comment, system_charset_info);
230
    if (protocol->write())
unknown's avatar
unknown committed
231 232
      DBUG_RETURN(-1);
  }
233
  send_eof(thd);
unknown's avatar
unknown committed
234 235 236
  DBUG_RETURN(0);
}

237

unknown's avatar
unknown committed
238
/***************************************************************************
239
 List all privileges supported
unknown's avatar
unknown committed
240 241
***************************************************************************/

242 243 244 245
struct show_privileges_st {
  const char *privilege;
  const char *context;
  const char *comment;
unknown's avatar
unknown committed
246 247
};

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

/*
  TODO:  Update with new privileges
*/
static struct show_privileges_st sys_privileges[]=
{
  {"Select", "Tables",  "To retrieve rows from table"},
  {"Insert", "Tables",  "To insert data into tables"},
  {"Update", "Tables",  "To update existing rows "},
  {"Delete", "Tables",  "To delete existing rows"},
  {"Index",  "Tables",  "To create or drop indexes"},
  {"Alter",  "Tables",  "To alter the table"},
  {"Create", "Databases,Tables,Indexes",  "To create new databases and tables"},
  {"Drop",   "Databases,Tables", "To drop databases and tables"},
  {"Grant",  "Databases,Tables", "To give to other users those privileges you possess"},
  {"References", "Databases,Tables", "To have references on tables"},
  {"Reload",  "Server Admin", "To reload or refresh tables, logs and privileges"},
  {"Shutdown","Server Admin", "To shutdown the server"},
  {"Process", "Server Admin", "To view the plain text of currently executing queries"},
  {"File",    "File access on server",   "To read and write files on the server"},
  {NullS, NullS, NullS}
};


unknown's avatar
unknown committed
272 273 274
int mysqld_show_privileges(THD *thd)
{
  List<Item> field_list;
275
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
276 277 278 279 280 281
  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));

282
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
283 284
    DBUG_RETURN(1);

285 286
  show_privileges_st *privilege= sys_privileges;
  for (privilege= sys_privileges; privilege->privilege ; privilege++)
unknown's avatar
unknown committed
287
  {
288
    protocol->prepare_for_resend();
289 290 291
    protocol->store(privilege->privilege, system_charset_info);
    protocol->store(privilege->context, system_charset_info);
    protocol->store(privilege->comment, system_charset_info);
292
    if (protocol->write())
unknown's avatar
unknown committed
293 294
      DBUG_RETURN(-1);
  }
295
  send_eof(thd);
unknown's avatar
unknown committed
296 297 298 299 300
  DBUG_RETURN(0);
}


/***************************************************************************
301
  List all column types
unknown's avatar
unknown committed
302 303
***************************************************************************/

304 305
struct show_column_type_st
{
unknown's avatar
unknown committed
306 307
  const char *type;
  uint size;
308 309 310 311 312 313 314 315 316 317 318 319
  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
320
};
321 322 323 324 325

/* TODO: Add remaning types */

static struct show_column_type_st sys_column_types[]=
{
unknown's avatar
unknown committed
326 327 328 329 330 331 332 333 334 335 336 337 338
  {"tinyint",
    1,  "-128",  "127",  0,  0,  "YES",  "YES",
    "NO",   "YES", "YES",  "NO",  "NULL,0",  
    "A very small integer"}, 
  {"tinyint unsigned",
    1,  "0"   ,  "255",  0,  0,  "YES",  "YES",  
    "YES",  "YES",  "YES",  "NO",  "NULL,0", 
    "A very small integer"},
};

int mysqld_show_column_types(THD *thd)
{
  List<Item> field_list;
339
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
340 341 342 343 344 345
  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));
346 347
  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
348 349 350 351 352 353 354 355 356
  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));

357
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
358 359
    DBUG_RETURN(1);

360
  /* TODO: Change the loop to not use 'i' */
unknown's avatar
unknown committed
361 362
  for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++)
  {
363
    protocol->prepare_for_resend();
364
    protocol->store(sys_column_types[i].type, system_charset_info);
365
    protocol->store((ulonglong) sys_column_types[i].size);
366 367
    protocol->store(sys_column_types[i].min_value, system_charset_info);
    protocol->store(sys_column_types[i].max_value, system_charset_info);
368 369
    protocol->store_short((longlong) sys_column_types[i].precision);
    protocol->store_short((longlong) sys_column_types[i].scale);
370 371 372 373 374 375 376 377
    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);
378
    if (protocol->write())
unknown's avatar
unknown committed
379 380
      DBUG_RETURN(-1);
  }
381
  send_eof(thd);
unknown's avatar
unknown committed
382 383 384 385 386 387
  DBUG_RETURN(0);
}


static int
mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
388
                 const char *wild, bool dir)
unknown's avatar
unknown committed
389 390 391 392 393 394 395 396 397
{
  uint i;
  char *ext;
  MY_DIR *dirp;
  FILEINFO *file;
  uint col_access=thd->col_access;
  TABLE_LIST table_list;
  DBUG_ENTER("mysql_find_files");

398 399
  if (wild && !wild[0])
    wild=0;
unknown's avatar
unknown committed
400 401 402 403 404
  bzero((char*) &table_list,sizeof(table_list));

  if (!(dirp = my_dir(path,MYF(MY_WME | (dir ? MY_WANT_STAT : 0)))))
    DBUG_RETURN(-1);

405
  for (i=0 ; i < (uint) dirp->number_off_files  ; i++)
unknown's avatar
unknown committed
406 407 408
  {
    file=dirp->dir_entry+i;
    if (dir)
409
    {                                           /* Return databases */
unknown's avatar
unknown committed
410 411 412
#ifdef USE_SYMDIR
      char *ext;
      if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym"))
413
        *ext=0;                                 /* Remove extension */
unknown's avatar
unknown committed
414 415 416
      else
#endif
      {
417
        if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat.st_mode) ||
418
            (wild && wild_compare(file->name,wild,0)))
419
          continue;
unknown's avatar
unknown committed
420 421 422 423
      }
    }
    else
    {
424
        // Return only .frm files which aren't temp files.
425
      if (my_strcasecmp(system_charset_info, ext=fn_ext(file->name),reg_ext) ||
426
          is_prefix(file->name,tmp_file_prefix))
427
        continue;
unknown's avatar
unknown committed
428
      *ext=0;
429 430 431 432
      if (wild)
      {
	if (lower_case_table_names)
	{
433
	  if (wild_case_compare(system_charset_info,file->name,wild))
434 435
	    continue;
	}
436
	else if (wild_compare(file->name,wild,0))
437 438
	  continue;
      }
unknown's avatar
unknown committed
439 440 441 442 443 444 445
    }
    /* 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
446
      if (check_grant(thd,TABLE_ACLS,&table_list,1,1))
447
        continue;
unknown's avatar
unknown committed
448
    }
449
    if (files->push_back(thd->strdup(file->name)))
unknown's avatar
unknown committed
450 451 452 453 454 455 456 457 458 459
    {
      my_dirend(dirp);
      DBUG_RETURN(-1);
    }
  }
  DBUG_PRINT("info",("found: %d files", files->elements));
  my_dirend(dirp);
  DBUG_RETURN(0);
}

460

unknown's avatar
unknown committed
461
/***************************************************************************
462
 Extended version of mysqld_show_tables
unknown's avatar
unknown committed
463 464 465 466 467 468 469 470 471 472
***************************************************************************/

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;
473 474
  Protocol *protocol= thd->protocol;
  TIME time;
unknown's avatar
unknown committed
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
  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));
  field_list.push_back(item=new Item_empty_string("Type",10));
  item->maybe_null=1;
  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
504
  field_list.push_back(item=new Item_empty_string("Collation",32));
505
  item->maybe_null=1;
unknown's avatar
unknown committed
506 507
  field_list.push_back(item=new Item_int("Checksum",(longlong) 1,21));
  item->maybe_null=1;
unknown's avatar
unknown committed
508 509 510
  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));
511
  item->maybe_null=1;
512
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
513 514 515 516
    DBUG_RETURN(1);

  if (mysql_find_files(thd,&files,db,path,wild,0))
    DBUG_RETURN(-1);
unknown's avatar
unknown committed
517
  List_iterator_fast<char> it(files);
unknown's avatar
unknown committed
518 519 520 521
  while ((file_name=it++))
  {
    TABLE_LIST table_list;
    bzero((char*) &table_list,sizeof(table_list));
522
    protocol->prepare_for_resend();
523
    protocol->store(file_name, system_charset_info);
unknown's avatar
unknown committed
524
    table_list.db=(char*) db;
525
    table_list.real_name= table_list.alias= file_name;
526
    if (lower_case_table_names)
527
      my_casedn_str(files_charset_info, file_name);
unknown's avatar
unknown committed
528 529
    if (!(table = open_ltable(thd, &table_list, TL_READ)))
    {
530
      for (uint i=2 ; i < field_list.elements ; i++)
531
        protocol->store_null();
532
      // Send error to Comment field
533
      protocol->store(thd->net.last_error, system_charset_info);
unknown's avatar
unknown committed
534 535 536 537 538
      thd->net.last_error[0]=0;
    }
    else
    {
      struct tm tm_tmp;
539
      const char *str;
unknown's avatar
unknown committed
540 541
      handler *file=table->file;
      file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK);
542
      protocol->store(file->table_type(), system_charset_info);
543 544 545 546
      str= ((table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ?
	    "Compressed" :
	    (table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
	    "Dynamic" : "Fixed");
547
      protocol->store(str, system_charset_info);
548 549 550
      protocol->store((ulonglong) file->records);
      protocol->store((ulonglong) file->mean_rec_length);
      protocol->store((ulonglong) file->data_file_length);
unknown's avatar
unknown committed
551
      if (file->max_data_file_length)
552
        protocol->store((ulonglong) file->max_data_file_length);
unknown's avatar
unknown committed
553
      else
554 555 556
        protocol->store_null();
      protocol->store((ulonglong) file->index_file_length);
      protocol->store((ulonglong) file->delete_length);
unknown's avatar
unknown committed
557 558
      if (table->found_next_number_field)
      {
559 560 561
        table->next_number_field=table->found_next_number_field;
        table->next_number_field->reset();
        file->update_auto_increment();
562
        protocol->store(table->next_number_field->val_int());
563
        table->next_number_field=0;
unknown's avatar
unknown committed
564 565
      }
      else
566
        protocol->store_null();
unknown's avatar
unknown committed
567
      if (!file->create_time)
568
        protocol->store_null();
unknown's avatar
unknown committed
569 570
      else
      {
571
        localtime_r(&file->create_time,&tm_tmp);
572 573
	localtime_to_TIME(&time, &tm_tmp);
        protocol->store(&time);
unknown's avatar
unknown committed
574 575
      }
      if (!file->update_time)
576
        protocol->store_null();
unknown's avatar
unknown committed
577 578
      else
      {
579
        localtime_r(&file->update_time,&tm_tmp);
580 581
	localtime_to_TIME(&time, &tm_tmp);
        protocol->store(&time);
unknown's avatar
unknown committed
582 583
      }
      if (!file->check_time)
584
        protocol->store_null();
unknown's avatar
unknown committed
585 586
      else
      {
587
        localtime_r(&file->check_time,&tm_tmp);
588 589
	localtime_to_TIME(&time, &tm_tmp);
        protocol->store(&time);
unknown's avatar
unknown committed
590
      }
591
      str= (table->table_charset ? table->table_charset->name : "default");
592
      protocol->store(str, system_charset_info);
unknown's avatar
unknown committed
593 594 595 596
      if (file->table_flags() & HA_HAS_CHECKSUM)
        protocol->store((ulonglong)file->checksum());
      else
        protocol->store_null(); // Checksum
unknown's avatar
unknown committed
597
      {
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
        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)
624
          ptr=strxmov(ptr, " row_format=", ha_row_type[(uint) table->row_type],
625 626 627 628 629 630 631 632
                      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);
        }
633
        protocol->store(option_buff+1,
634 635
			(ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1)
			, system_charset_info);
unknown's avatar
unknown committed
636
      }
637 638
      {
	char *comment=table->file->update_table_comment(table->comment);
639
	protocol->store(comment, system_charset_info);
640 641 642
	if (comment != table->comment)
	  my_free(comment,MYF(0));
      }
unknown's avatar
unknown committed
643 644
      close_thread_tables(thd,0);
    }
645
    if (protocol->write())
unknown's avatar
unknown committed
646 647
      DBUG_RETURN(-1);
  }
648
  send_eof(thd);
unknown's avatar
unknown committed
649 650 651 652 653
  DBUG_RETURN(0);
}


/***************************************************************************
654
** List all columns in a table_list->real_name
unknown's avatar
unknown committed
655
***************************************************************************/
unknown's avatar
SCRUM  
unknown committed
656

unknown's avatar
unknown committed
657
int
unknown's avatar
unknown committed
658 659
mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
		   bool verbose)
unknown's avatar
unknown committed
660 661 662 663
{
  TABLE *table;
  handler *file;
  char tmp[MAX_FIELD_WIDTH];
unknown's avatar
unknown committed
664
  Item *item;
665
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
666 667
  DBUG_ENTER("mysqld_show_fields");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
668
                      table_list->real_name));
unknown's avatar
unknown committed
669 670 671

  if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  {
672
    send_error(thd);
unknown's avatar
unknown committed
673 674 675 676 677 678 679 680 681
    DBUG_RETURN(1);
  }
  file=table->file;
  file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
  (void) get_table_grant(thd, table_list);

  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));
682 683
  if (verbose)
    field_list.push_back(new Item_empty_string("Collation",40));
unknown's avatar
unknown committed
684 685
  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
686 687
  field_list.push_back(item=new Item_empty_string("Default",NAME_LEN));
  item->maybe_null=1;
unknown's avatar
unknown committed
688
  field_list.push_back(new Item_empty_string("Extra",20));
unknown's avatar
unknown committed
689
  if (verbose)
690
  {
unknown's avatar
unknown committed
691
    field_list.push_back(new Item_empty_string("Privileges",80));
692 693
    field_list.push_back(new Item_empty_string("Comment",255));
  }
694
        // Send first number of fields and records
unknown's avatar
SCRUM  
unknown committed
695 696
  if (protocol->send_records_num(&field_list, (ulonglong)file->records) ||
      protocol->send_fields(&field_list,0))
unknown's avatar
unknown committed
697
    DBUG_RETURN(1);
unknown's avatar
unknown committed
698
  restore_record(table,default_values);      // Get empty record
unknown's avatar
unknown committed
699 700

  Field **ptr,*field;
unknown's avatar
unknown committed
701
  String *packet= &thd->packet;
unknown's avatar
unknown committed
702 703
  for (ptr=table->field; (field= *ptr) ; ptr++)
  {
704 705
    if (!wild || !wild[0] || 
        !wild_case_compare(system_charset_info, field->field_name,wild))
unknown's avatar
unknown committed
706 707 708
    {
#ifdef NOT_USED
      if (thd->col_access & TABLE_ACLS ||
709 710
          ! check_grant_column(thd,table,field->field_name,
                               (uint) strlen(field->field_name),1))
unknown's avatar
unknown committed
711 712
#endif
      {
713 714
        byte *pos;
        uint flags=field->flags;
715
        String type(tmp,sizeof(tmp), system_charset_info);
716 717 718
        uint col_access;
        bool null_default_value=0;

719
	protocol->prepare_for_resend();
720
        protocol->store(field->field_name, system_charset_info);
721
        field->sql_type(type);
722
        protocol->store(type.ptr(), type.length(), system_charset_info);
723 724
	if (verbose)
	  protocol->store(field->has_charset() ? field->charset()->name : "NULL",
725
			system_charset_info);
726 727 728
        pos=(byte*) ((flags & NOT_NULL_FLAG) &&
                     field->type() != FIELD_TYPE_TIMESTAMP ?
                     "" : "YES");
729
        protocol->store((const char*) pos, system_charset_info);
730 731 732
        pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
                     (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
                     (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
733
        protocol->store((char*) pos, system_charset_info);
734 735 736 737 738 739

        if (field->type() == FIELD_TYPE_TIMESTAMP ||
            field->unireg_check == Field::NEXT_NUMBER)
          null_default_value=1;
        if (!null_default_value && !field->is_null())
        {                                               // Not null by default
740
          type.set(tmp,sizeof(tmp),system_charset_info);
741
          field->val_str(&type,&type);
742
          protocol->store(type.ptr(),type.length(),type.charset());
743 744
        }
        else if (field->maybe_null() || null_default_value)
745
          protocol->store_null();                       // Null as default
746
        else
747
          protocol->store("",0, system_charset_info);	// empty string
748 749 750 751

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

unknown's avatar
unknown committed
754 755
	if (verbose)
	{
756
	  /* Add grant options & comments */
unknown's avatar
unknown committed
757
	  end=tmp;
758
	  col_access= get_column_grant(thd,table_list,field) & COL_ACLS;
unknown's avatar
unknown committed
759 760 761 762 763 764 765 766
	  for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
	  {
	    if (col_access & 1)
	    {
	      *end++=',';
	      end=strmov(end,grant_types.type_names[bitnr]);
	    }
	  }
767 768 769 770
	  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
771
	}
772
        if (protocol->write())
773
          DBUG_RETURN(1);
unknown's avatar
unknown committed
774 775 776
      }
    }
  }
777
  send_eof(thd);
unknown's avatar
unknown committed
778 779 780
  DBUG_RETURN(0);
}

781

unknown's avatar
unknown committed
782 783 784 785
int
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
  TABLE *table;
786 787 788
  Protocol *protocol= thd->protocol;
  char buff[2048];
  String buffer(buff, sizeof(buff), system_charset_info);
unknown's avatar
unknown committed
789 790
  DBUG_ENTER("mysqld_show_create");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
791
                      table_list->real_name));
unknown's avatar
unknown committed
792

unknown's avatar
unknown committed
793
  /* Only one table for now */
unknown's avatar
unknown committed
794 795
  if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  {
796
    send_error(thd);
unknown's avatar
unknown committed
797 798 799
    DBUG_RETURN(1);
  }

unknown's avatar
unknown committed
800
  if (store_create_info(thd, table, &buffer))
801 802
    DBUG_RETURN(-1);

unknown's avatar
unknown committed
803 804
  List<Item> field_list;
  field_list.push_back(new Item_empty_string("Table",NAME_LEN));
unknown's avatar
unknown committed
805
  // 1024 is for not to confuse old clients
806
  field_list.push_back(new Item_empty_string("Create Table",
unknown's avatar
unknown committed
807
					     max(buffer.length(),1024)));
unknown's avatar
unknown committed
808

809 810 811
  if (protocol->send_fields(&field_list, 1))
    DBUG_RETURN(1);
  protocol->prepare_for_resend();
812
  protocol->store(table->table_name, system_charset_info);
813
  buffer.length(0);
814 815
  if (store_create_info(thd, table, &buffer))
    DBUG_RETURN(-1);
816
  protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
817
  if (protocol->write())
unknown's avatar
unknown committed
818
    DBUG_RETURN(1);
819
  send_eof(thd);
unknown's avatar
unknown committed
820 821 822 823
  DBUG_RETURN(0);
}


unknown's avatar
unknown committed
824 825 826
int
mysqld_show_logs(THD *thd)
{
827 828
  List<Item> field_list;
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
829 830 831 832 833 834
  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));

835
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
836 837
    DBUG_RETURN(1);

838
#ifdef HAVE_BERKELEY_DB
839
  if (!berkeley_skip && berkeley_show_logs(protocol))
unknown's avatar
unknown committed
840
    DBUG_RETURN(-1);
841
#endif
unknown's avatar
unknown committed
842

843
  send_eof(thd);
unknown's avatar
unknown committed
844 845 846 847
  DBUG_RETURN(0);
}


unknown's avatar
unknown committed
848 849 850 851
int
mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
{
  TABLE *table;
852
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
853 854
  DBUG_ENTER("mysqld_show_keys");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
855
                      table_list->real_name));
unknown's avatar
unknown committed
856 857 858

  if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  {
859
    send_error(thd);
unknown's avatar
unknown committed
860 861 862 863 864 865
    DBUG_RETURN(1);
  }

  List<Item> field_list;
  Item *item;
  field_list.push_back(new Item_empty_string("Table",NAME_LEN));
866
  field_list.push_back(new Item_return_int("Non_unique",1, MYSQL_TYPE_TINY));
unknown's avatar
unknown committed
867
  field_list.push_back(new Item_empty_string("Key_name",NAME_LEN));
868
  field_list.push_back(new Item_return_int("Seq_in_index",2, MYSQL_TYPE_TINY));
unknown's avatar
unknown committed
869 870 871
  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;
872
  field_list.push_back(item=new Item_int("Cardinality",0,21));
unknown's avatar
unknown committed
873
  item->maybe_null=1;
874 875
  field_list.push_back(item=new Item_return_int("Sub_part",3,
						MYSQL_TYPE_TINY));
unknown's avatar
unknown committed
876 877 878
  item->maybe_null=1;
  field_list.push_back(item=new Item_empty_string("Packed",10));
  item->maybe_null=1;
879 880
  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
881 882 883
  field_list.push_back(new Item_empty_string("Comment",255));
  item->maybe_null=1;

884
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
885 886
    DBUG_RETURN(1);

unknown's avatar
unknown committed
887
  String *packet= &thd->packet;
unknown's avatar
unknown committed
888 889 890 891 892
  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;
893
    const char *str;
unknown's avatar
unknown committed
894 895
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
    {
896
      protocol->prepare_for_resend();
897
      protocol->store(table->table_name, system_charset_info);
898
      protocol->store_tiny((longlong) ((key_info->flags & HA_NOSAME) ? 0 :1));
899
      protocol->store(key_info->name, system_charset_info);
900 901 902
      protocol->store_tiny((longlong) (j+1));
      str=(key_part->field ? key_part->field->field_name :
	   "?unknown field?");
903
      protocol->store(str, system_charset_info);
904
      if (table->file->index_flags(i) & HA_READ_ORDER)
905
        protocol->store(((key_part->key_part_flag & HA_REVERSE_SORT) ?
906
			 "D" : "A"), 1, system_charset_info);
unknown's avatar
unknown committed
907
      else
908
        protocol->store_null(); /* purecov: inspected */
unknown's avatar
unknown committed
909 910 911
      KEY *key=table->key_info+i;
      if (key->rec_per_key[j])
      {
912
        ha_rows records=(table->file->records / key->rec_per_key[j]);
913
        protocol->store((ulonglong) records);
unknown's avatar
unknown committed
914 915
      }
      else
916
        protocol->store_null();
917 918

      /* Check if we have a key part that only uses part of the field */
unknown's avatar
unknown committed
919
      if (!key_part->field ||
920 921
          key_part->length !=
          table->field[key_part->fieldnr-1]->key_length())
922
        protocol->store_tiny((longlong) key_part->length);
unknown's avatar
unknown committed
923
      else
924 925
        protocol->store_null();
      protocol->store_null();                   // No pack_information yet
926 927 928

      /* Null flag */
      uint flags= key_part->field ? key_part->field->flags : 0;
unknown's avatar
unknown committed
929
      char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
930 931
      protocol->store((const char*) pos, system_charset_info);
      protocol->store(table->file->index_type(i), system_charset_info);
932
      /* Comment */
933
      if (!(table->keys_in_use & ((key_map) 1 << i)))
unknown's avatar
unknown committed
934
	protocol->store("disabled",8, system_charset_info);
935
      else
unknown's avatar
unknown committed
936
        protocol->store("", 0, system_charset_info);
937
      if (protocol->write())
938
        DBUG_RETURN(1); /* purecov: inspected */
unknown's avatar
unknown committed
939 940
    }
  }
941
  send_eof(thd);
unknown's avatar
unknown committed
942 943 944 945 946
  DBUG_RETURN(0);
}


/****************************************************************************
947 948
  Return only fields for API mysql_list_fields
  Use "show table wildcard" in mysql instead of this
unknown's avatar
unknown committed
949 950 951 952 953 954 955 956 957 958 959
****************************************************************************/

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)))
  {
960
    send_error(thd);
unknown's avatar
unknown committed
961 962 963 964 965 966 967
    DBUG_VOID_RETURN;
  }
  List<Item> field_list;

  Field **ptr,*field;
  for (ptr=table->field ; (field= *ptr); ptr++)
  {
968 969
    if (!wild || !wild[0] || 
        !wild_case_compare(system_charset_info, field->field_name,wild))
unknown's avatar
unknown committed
970 971
      field_list.push_back(new Item_field(field));
  }
unknown's avatar
unknown committed
972
  restore_record(table,default_values);              // Get empty record
973
  if (thd->protocol->send_fields(&field_list,2))
unknown's avatar
unknown committed
974
    DBUG_VOID_RETURN;
975
  net_flush(&thd->net);
unknown's avatar
unknown committed
976 977 978
  DBUG_VOID_RETURN;
}

979

unknown's avatar
unknown committed
980 981 982
int
mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
{
983 984
  Protocol *protocol= thd->protocol;
  String *packet= protocol->storage_packet();
unknown's avatar
unknown committed
985 986
  DBUG_ENTER("mysqld_dump_create_info");
  DBUG_PRINT("enter",("table: %s",table->real_name));
987

988 989
  protocol->prepare_for_resend();
  if (store_create_info(thd, table, packet))
unknown's avatar
unknown committed
990
    DBUG_RETURN(-1);
991

unknown's avatar
unknown committed
992 993
  //if (protocol->convert)
  //  protocol->convert->convert((char*) packet->ptr(), packet->length());
994
  if (fd < 0)
995
  {
996
    if (protocol->write())
997
      DBUG_RETURN(-1);
998
    net_flush(&thd->net);
999
  }
unknown's avatar
unknown committed
1000
  else
1001
  {
1002 1003
    if (my_write(fd, (const byte*) packet->ptr(), packet->length(),
		 MYF(MY_WME)))
1004 1005
      DBUG_RETURN(-1);
  }
unknown's avatar
unknown committed
1006 1007
  DBUG_RETURN(0);
}
1008

1009

1010 1011
void
append_identifier(THD *thd, String *packet, const char *name, uint length)
1012
{
1013
  char qtype;
1014
  if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
1015 1016 1017 1018
    qtype= '\"';
  else
    qtype= '`';

1019 1020
  if (thd->options & OPTION_QUOTE_SHOW_CREATE)
  {
1021
    packet->append(&qtype, 1);
1022
    packet->append(name, length, system_charset_info);
1023
    packet->append(&qtype, 1);
1024 1025 1026
  }
  else
  {
1027
    packet->append(name, length, system_charset_info);
1028 1029 1030
  }
}

1031 1032 1033 1034 1035 1036 1037

/* 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
1038
  if (filename && !(thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
  {
    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
1050
#define LIST_PROCESS_HOST_LEN 64
1051

unknown's avatar
unknown committed
1052
static int
1053
store_create_info(THD *thd, TABLE *table, String *packet)
unknown's avatar
unknown committed
1054
{
1055 1056
  List<Item> field_list;
  char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end;
unknown's avatar
unknown committed
1057
  String type(tmp, sizeof(tmp),&my_charset_bin);
1058 1059 1060 1061 1062
  Field **ptr,*field;
  uint primary_key;
  KEY *key_info;
  handler *file= table->file;
  HA_CREATE_INFO create_info;
1063 1064 1065 1066 1067 1068 1069 1070 1071
  my_bool foreign_db_mode=    (thd->variables.sql_mode & (MODE_POSTGRESQL |
							  MODE_ORACLE |
							  MODE_MSSQL |
							  MODE_DB2 |
							  MODE_SAPDB |
							  MODE_ANSI)) != 0;
  my_bool limited_mysql_mode= (thd->variables.sql_mode &
			       (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
				MODE_MYSQL40)) != 0;
1072

unknown's avatar
unknown committed
1073 1074 1075
  DBUG_ENTER("store_create_info");
  DBUG_PRINT("enter",("table: %s",table->real_name));

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

1078 1079 1080 1081
  if (table->tmp_table)
    packet->append("CREATE TEMPORARY TABLE ", 23);
  else
    packet->append("CREATE TABLE ", 13);
1082
  append_identifier(thd,packet, table->real_name, strlen(table->real_name));
1083
  packet->append(" (\n", 3);
1084

unknown's avatar
unknown committed
1085 1086
  for (ptr=table->field ; (field= *ptr); ptr++)
  {
1087 1088 1089
    bool has_default;
    uint flags = field->flags;

1090
    if (ptr != table->field)
1091
      packet->append(",\n", 2);
1092

1093
    packet->append("  ", 2);
1094
    append_identifier(thd,packet,field->field_name, strlen(field->field_name));
unknown's avatar
unknown committed
1095 1096
    packet->append(' ');
    // check for surprises from the previous call to Field::sql_type()
1097
    if (type.ptr() != tmp)
unknown's avatar
unknown committed
1098
      type.set(tmp, sizeof(tmp),&my_charset_bin);
1099

unknown's avatar
unknown committed
1100 1101
    field->sql_type(type);
    packet->append(type.ptr(),type.length());
1102

1103
    if (field->has_charset())
1104
    {
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
      if (field->charset() == &my_charset_bin)
        packet->append(" binary");
      else if (!limited_mysql_mode && !foreign_db_mode)
      {
	if (field->charset() != table->table_charset)
	{
	  packet->append(" character set ");
	  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);
	}
      }
1124
    }
1125

1126 1127
    if (flags & NOT_NULL_FLAG)
      packet->append(" NOT NULL", 9);
1128

1129 1130 1131
    has_default= (field->type() != FIELD_TYPE_BLOB &&
		  field->type() != FIELD_TYPE_TIMESTAMP &&
		  field->unireg_check != Field::NEXT_NUMBER);
1132

1133
    if (has_default)
1134 1135
    {
      packet->append(" default ", 9);
1136
      if (!field->is_null())
1137
      {                                             // Not null by default
unknown's avatar
unknown committed
1138
        type.set(tmp,sizeof(tmp),&my_charset_bin);
1139
        field->val_str(&type,&type);
1140
	if (type.length())
1141 1142 1143
          append_unescaped(packet, type.ptr(), type.length());
        else
	  packet->append("''",2);
unknown's avatar
unknown committed
1144
      }
1145
      else if (field->maybe_null())
1146 1147 1148 1149
        packet->append("NULL", 4);                    // Null as default
      else
        packet->append(tmp,0);
    }
1150

1151
    if (field->unireg_check == Field::NEXT_NUMBER && !foreign_db_mode)
1152 1153 1154 1155 1156 1157 1158
      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
1159 1160
  }

1161 1162
  key_info= table->key_info;
  file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
1163
  bzero((char*) &create_info, sizeof(create_info));
1164 1165
  file->update_create_info(&create_info);
  primary_key= table->primary_key;
1166

unknown's avatar
unknown committed
1167 1168
  for (uint i=0 ; i < table->keys ; i++,key_info++)
  {
1169 1170
    KEY_PART_INFO *key_part= key_info->key_part;
    bool found_primary=0;
1171
    packet->append(",\n  ", 4);
1172

1173 1174 1175
    if (i == primary_key && !strcmp(key_info->name,"PRIMARY"))
    {
      found_primary=1;
1176
      packet->append("PRIMARY ", 8);
1177
    }
1178
    else if (key_info->flags & HA_NOSAME)
1179
      packet->append("UNIQUE ", 7);
1180
    else if (key_info->flags & HA_FULLTEXT)
1181
      packet->append("FULLTEXT ", 9);
unknown's avatar
unknown committed
1182 1183
    else if (key_info->flags & HA_SPATIAL)
      packet->append("SPATIAL ", 8);
1184
    packet->append("KEY ", 4);
unknown's avatar
unknown committed
1185

1186
    if (!found_primary)
1187
     append_identifier(thd, packet, key_info->name, strlen(key_info->name));
unknown's avatar
unknown committed
1188

1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200
    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);
    }
1201
    packet->append(" (", 2);
1202

unknown's avatar
unknown committed
1203 1204
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
    {
1205
      if (j)
1206
        packet->append(',');
1207

1208
      if (key_part->field)
1209 1210
        append_identifier(thd,packet,key_part->field->field_name,
			  strlen(key_part->field->field_name));
unknown's avatar
unknown committed
1211
      if (!key_part->field ||
1212 1213 1214
          (key_part->length !=
           table->field[key_part->fieldnr-1]->key_length() &&
           !(key_info->flags & HA_FULLTEXT)))
unknown's avatar
unknown committed
1215
      {
1216
        buff[0] = '(';
1217 1218 1219
        char* end=int10_to_str((long) key_part->length / 
			       key_part->field->charset()->mbmaxlen,
			       buff + 1,10);
1220 1221
        *end++ = ')';
        packet->append(buff,(uint) (end-buff));
unknown's avatar
unknown committed
1222 1223 1224 1225
      }
    }
    packet->append(')');
  }
1226

1227 1228 1229 1230
  /*
    Get possible foreign key definitions stored in InnoDB and append them
    to the CREATE TABLE statement
  */
1231

1232
  if ((for_str= file->get_foreign_key_create_info()))
1233 1234 1235
  {
    packet->append(for_str, strlen(for_str));
    file->free_foreign_key_create_info(for_str);
1236 1237 1238
  }

  packet->append("\n)", 2);
1239
  if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
1240
  {
1241 1242 1243
    packet->append(" TYPE=", 6);
    packet->append(file->table_type());
    
1244 1245 1246
    if (table->table_charset &&
	!(thd->variables.sql_mode & MODE_MYSQL323) &&
	!(thd->variables.sql_mode & MODE_MYSQL40))
1247
    {
1248 1249 1250 1251 1252 1253 1254
      packet->append(" CHARSET=");
      packet->append(table->table_charset->csname);
      if (!(table->table_charset->state & MY_CS_PRIMARY))
      {
	packet->append(" COLLATE=");
	packet->append(table->table_charset->name);
      }
1255
    }
1256

1257 1258 1259
    if (table->min_rows)
    {
      packet->append(" MIN_ROWS=");
unknown's avatar
unknown committed
1260 1261
      end= longlong10_to_str(table->min_rows, buff, 10);
      packet->append(buff, (uint) (end- buff));
1262
    }
unknown's avatar
unknown committed
1263

1264 1265 1266
    if (table->max_rows)
    {
      packet->append(" MAX_ROWS=");
unknown's avatar
unknown committed
1267 1268
      end= longlong10_to_str(table->max_rows, buff, 10);
      packet->append(buff, (uint) (end - buff));
1269
    }
unknown's avatar
unknown committed
1270

1271 1272 1273
    if (table->avg_row_length)
    {
      packet->append(" AVG_ROW_LENGTH=");
unknown's avatar
unknown committed
1274 1275
      end= longlong10_to_str(table->avg_row_length, buff,10);
      packet->append(buff, (uint) (end - buff));
1276
    }
1277

1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
    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
1299 1300 1301 1302 1303 1304
      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);
1305
    }
unknown's avatar
unknown committed
1306 1307
    append_directory(thd, packet, "DATA",  create_info.data_file_name);
    append_directory(thd, packet, "INDEX", create_info.index_file_name);
1308
  }
unknown's avatar
unknown committed
1309 1310 1311 1312 1313
  DBUG_RETURN(0);
}


/****************************************************************************
1314 1315
  Return info about all processes
  returns for each thread: thread id, user, host, db, command, info
unknown's avatar
unknown committed
1316 1317 1318 1319
****************************************************************************/

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

unknown's avatar
unknown committed
1324 1325
  ulong thread_id;
  time_t start_time;
1326
  uint   command;
unknown's avatar
unknown committed
1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
  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
1340 1341
  ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
			   PROCESS_LIST_WIDTH);
1342
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
1343 1344
  DBUG_ENTER("mysqld_list_processes");

1345
  field_list.push_back(new Item_int("Id",0,11));
unknown's avatar
unknown committed
1346
  field_list.push_back(new Item_empty_string("User",16));
1347
  field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
unknown's avatar
unknown committed
1348 1349 1350
  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));
1351
  field_list.push_back(new Item_return_int("Time",7, FIELD_TYPE_LONG));
unknown's avatar
unknown committed
1352 1353 1354 1355
  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;
1356
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
1357 1358 1359 1360 1361 1362 1363 1364 1365
    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++))
    {
1366
      struct st_my_thread_var *mysys_var;
unknown's avatar
SCRUM  
unknown committed
1367
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
1368
      if ((tmp->net.vio || tmp->system_thread) &&
1369
          (!user || (tmp->user && !strcmp(tmp->user,user))))
unknown's avatar
SCRUM  
unknown committed
1370 1371 1372 1373
#else
      if (tmp->system_thread &&
          (!user || (tmp->user && !strcmp(tmp->user,user))))
#endif
unknown's avatar
unknown committed
1374
      {
1375 1376 1377
        thread_info *thd_info=new thread_info;

        thd_info->thread_id=tmp->thread_id;
1378 1379 1380
        thd_info->user=thd->strdup(tmp->user ? tmp->user :
				   (tmp->system_thread ?
				    "system user" : "unauthenticated user"));
1381
	if (tmp->peer_port && (tmp->host || tmp->ip) && thd->host_or_ip[0])
1382 1383
	{
	  if ((thd_info->host= thd->alloc(LIST_PROCESS_HOST_LEN+1)))
unknown's avatar
unknown committed
1384
	    my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN,
1385
			"%s:%u", tmp->host_or_ip, tmp->peer_port);
1386 1387
	}
	else
1388
	  thd_info->host= thd->strdup(tmp->host_or_ip);
1389 1390 1391
        if ((thd_info->db=tmp->db))             // Safe test
          thd_info->db=thd->strdup(thd_info->db);
        thd_info->command=(int) tmp->command;
1392 1393
        if ((mysys_var= tmp->mysys_var))
          pthread_mutex_lock(&mysys_var->mutex);
1394
        thd_info->proc_info= (char*) (tmp->killed ? "Killed" : 0);
unknown's avatar
SCRUM  
unknown committed
1395
#ifndef EMBEDDED_LIBRARY
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
        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
1406 1407 1408
#else
        thd_info->state_info= (char*)"Writing to net";
#endif
1409 1410
        if (mysys_var)
          pthread_mutex_unlock(&mysys_var->mutex);
unknown's avatar
unknown committed
1411 1412

#if !defined(DONT_USE_THR_ALARM) && ! defined(SCO)
1413 1414
        if (pthread_kill(tmp->real_id,0))
          tmp->proc_info="*** DEAD ***";        // This shouldn't happen
unknown's avatar
unknown committed
1415
#endif
unknown's avatar
unknown committed
1416 1417 1418
#ifdef EXTRA_DEBUG
        thd_info->start_time= tmp->time_after_lock;
#else
1419
        thd_info->start_time= tmp->start_time;
unknown's avatar
unknown committed
1420
#endif
1421 1422 1423
        thd_info->query=0;
        if (tmp->query)
        {
unknown's avatar
unknown committed
1424 1425
	  /* query_length is always set before tmp->query */
          uint length= min(max_query_length, tmp->query_length);
1426 1427 1428 1429
          thd_info->query=(char*) thd->memdup(tmp->query,length+1);
          thd_info->query[length]=0;
        }
        thread_infos.append(thd_info);
unknown's avatar
unknown committed
1430 1431 1432 1433 1434 1435
      }
    }
  }
  VOID(pthread_mutex_unlock(&LOCK_thread_count));

  thread_info *thd_info;
1436
  time_t now= time(0);
unknown's avatar
unknown committed
1437 1438
  while ((thd_info=thread_infos.get()))
  {
1439 1440
    protocol->prepare_for_resend();
    protocol->store((ulonglong) thd_info->thread_id);
1441 1442 1443
    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
1444
    if (thd_info->proc_info)
1445
      protocol->store(thd_info->proc_info, system_charset_info);
unknown's avatar
unknown committed
1446
    else
1447
      protocol->store(command_name[thd_info->command], system_charset_info);
unknown's avatar
unknown committed
1448
    if (thd_info->start_time)
1449
      protocol->store((uint32) (now - thd_info->start_time));
unknown's avatar
unknown committed
1450
    else
1451
      protocol->store_null();
1452 1453
    protocol->store(thd_info->state_info, system_charset_info);
    protocol->store(thd_info->query, system_charset_info);
1454
    if (protocol->write())
unknown's avatar
unknown committed
1455 1456
      break; /* purecov: inspected */
  }
1457
  send_eof(thd);
unknown's avatar
unknown committed
1458 1459 1460 1461
  DBUG_VOID_RETURN;
}

/*****************************************************************************
unknown's avatar
unknown committed
1462
  Status functions
unknown's avatar
unknown committed
1463 1464
*****************************************************************************/

1465 1466 1467 1468
static bool write_collation(Protocol *protocol, CHARSET_INFO *cs)
{
  protocol->prepare_for_resend();
  protocol->store(cs->name, system_charset_info);
1469
  protocol->store(cs->csname, system_charset_info);
1470
  protocol->store_short((longlong) cs->number);
1471 1472
  protocol->store((cs->state & MY_CS_PRIMARY) ? "Yes" : "",system_charset_info);
  protocol->store((cs->state & MY_CS_COMPILED)? "Yes" : "",system_charset_info);
1473 1474 1475 1476 1477
  protocol->store_short((longlong) cs->strxfrm_multiply);
  return protocol->write();
}

int mysqld_show_collations(THD *thd, const char *wild)
1478 1479
{
  char buff[8192];
unknown's avatar
unknown committed
1480
  String packet2(buff,sizeof(buff),thd->charset());
1481
  List<Item> field_list;
1482
  CHARSET_INFO **cs;
1483
  Protocol *protocol= thd->protocol;
1484

1485 1486
  DBUG_ENTER("mysqld_show_charsets");

1487
  field_list.push_back(new Item_empty_string("Collation",30));
1488
  field_list.push_back(new Item_empty_string("Charset",30));
1489
  field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT));
1490 1491
  field_list.push_back(new Item_empty_string("Default",30));
  field_list.push_back(new Item_empty_string("Compiled",30));
1492
  field_list.push_back(new Item_return_int("Sortlen",3, FIELD_TYPE_SHORT));
1493

1494
  if (protocol->send_fields(&field_list, 1))
1495 1496
    DBUG_RETURN(1);

1497
  for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ )
1498
  {
1499 1500 1501 1502 1503 1504
    CHARSET_INFO **cl;
    for ( cl= all_charsets; cl < all_charsets+255 ;cl ++)
    {
      if (!cs[0] || !cl[0] || !my_charset_same(cs[0],cl[0]) || !(cs[0]->state & MY_CS_PRIMARY))
	continue;
      if (cs[0] && !(wild && wild[0] &&
unknown's avatar
unknown committed
1505
	  wild_case_compare(system_charset_info,cl[0]->name,wild)))
1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521
      {
        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);
1522
  protocol->store(cs->comment ? cs->comment : "", system_charset_info);
1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538
  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));
1539
  field_list.push_back(new Item_empty_string("Description",60));
1540 1541 1542 1543 1544 1545 1546 1547 1548 1549
  field_list.push_back(new Item_empty_string("Default collation",60));
  field_list.push_back(new Item_return_int("Maxlen",3, FIELD_TYPE_SHORT));

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

  for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ )
  {
    if (cs[0] && (cs[0]->state & MY_CS_PRIMARY) && !(wild && wild[0] &&
       wild_case_compare(system_charset_info,cs[0]->name,wild)))
1550
    {
1551
      if (write_charset(protocol, cs[0]))
1552
	goto err;
1553 1554
    }
  }
1555
  send_eof(thd); 
1556 1557 1558 1559 1560
  DBUG_RETURN(0);
err:
  DBUG_RETURN(1);
}

unknown's avatar
unknown committed
1561
  
unknown's avatar
unknown committed
1562

1563
int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
1564 1565
		enum enum_var_type value_type,
		pthread_mutex_t *mutex)
unknown's avatar
unknown committed
1566
{
1567
  char buff[1024];
unknown's avatar
unknown committed
1568
  List<Item> field_list;
1569
  Protocol *protocol= thd->protocol;
1570
  LEX_STRING null_lex_str;
unknown's avatar
unknown committed
1571
  DBUG_ENTER("mysqld_show");
unknown's avatar
unknown committed
1572

unknown's avatar
unknown committed
1573 1574
  field_list.push_back(new Item_empty_string("Variable_name",30));
  field_list.push_back(new Item_empty_string("Value",256));
1575
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
1576
    DBUG_RETURN(1); /* purecov: inspected */
1577
  null_lex_str.str= 0;				// For sys_var->value_ptr()
unknown's avatar
unknown committed
1578

1579
  pthread_mutex_lock(mutex);
unknown's avatar
unknown committed
1580
  for (; variables->name; variables++)
unknown's avatar
unknown committed
1581
  {
unknown's avatar
unknown committed
1582
    if (!(wild && wild[0] && wild_case_compare(system_charset_info,
1583
					       variables->name,wild)))
unknown's avatar
unknown committed
1584
    {
1585
      protocol->prepare_for_resend();
1586
      protocol->store(variables->name, system_charset_info);
unknown's avatar
unknown committed
1587 1588
      SHOW_TYPE show_type=variables->type;
      char *value=variables->value;
1589 1590 1591
      const char *pos, *end;
      long nr;

unknown's avatar
unknown committed
1592 1593 1594
      if (show_type == SHOW_SYS)
      {
	show_type= ((sys_var*) value)->type();
1595 1596
	value=     (char*) ((sys_var*) value)->value_ptr(thd, value_type,
							 &null_lex_str);
unknown's avatar
unknown committed
1597 1598
      }

1599
      pos= end= buff;
unknown's avatar
unknown committed
1600
      switch (show_type) {
unknown's avatar
unknown committed
1601 1602
      case SHOW_LONG:
      case SHOW_LONG_CONST:
1603
	end= int10_to_str(*(long*) value, buff, 10);
unknown's avatar
unknown committed
1604 1605
        break;
      case SHOW_LONGLONG:
1606
	end= longlong10_to_str(*(longlong*) value, buff, 10);
unknown's avatar
unknown committed
1607
	break;
1608
      case SHOW_HA_ROWS:
unknown's avatar
unknown committed
1609
        end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
1610
        break;
unknown's avatar
unknown committed
1611
      case SHOW_BOOL:
1612
	end= strmov(buff, *(bool*) value ? "ON" : "OFF");
1613
        break;
unknown's avatar
unknown committed
1614
      case SHOW_MY_BOOL:
1615
	end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
1616
        break;
unknown's avatar
unknown committed
1617 1618
      case SHOW_INT_CONST:
      case SHOW_INT:
1619
	end= int10_to_str((long) *(uint32*) value, buff, 10);
1620
        break;
1621 1622
      case SHOW_HAVE:
      {
unknown's avatar
unknown committed
1623
	SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
1624 1625
	pos= show_comp_option_name[(int) tmp];
	end= strend(pos);
1626 1627
        break;
      }
unknown's avatar
unknown committed
1628
      case SHOW_CHAR:
1629 1630
	pos= value;
	end= strend(pos);
1631
        break;
unknown's avatar
unknown committed
1632
      case SHOW_STARTTIME:
1633 1634
	nr= (long) (thd->query_start() - start_time);
	end= int10_to_str(nr, buff, 10);
1635
        break;
unknown's avatar
unknown committed
1636
      case SHOW_QUESTION:
1637
	end= int10_to_str((long) thd->query_id, buff, 10);
1638
        break;
unknown's avatar
unknown committed
1639
#ifdef HAVE_REPLICATION
1640
      case SHOW_RPL_STATUS:
unknown's avatar
unknown committed
1641
	end= strmov(buff, rpl_status_type[(int)rpl_status]);
1642
	break;
1643 1644 1645
      case SHOW_SLAVE_RUNNING:
      {
	LOCK_ACTIVE_MI;
1646 1647
	end= strmov(buff, (active_mi->slave_running &&
			   active_mi->rli.slave_running) ? "ON" : "OFF");
1648 1649 1650
	UNLOCK_ACTIVE_MI;
	break;
      }
unknown's avatar
unknown committed
1651
#endif /* HAVE_REPLICATION */
unknown's avatar
unknown committed
1652
      case SHOW_OPENTABLES:
1653
	end= int10_to_str((long) cached_tables(), buff, 10);
1654
        break;
unknown's avatar
unknown committed
1655
      case SHOW_CHAR_PTR:
unknown's avatar
unknown committed
1656
      {
1657 1658 1659
	if (!(pos= *(char**) value))
	  pos= "";
	end= strend(pos);
unknown's avatar
unknown committed
1660 1661
	break;
      }
unknown's avatar
unknown committed
1662
#ifdef HAVE_OPENSSL
unknown's avatar
unknown committed
1663
	/* First group - functions relying on CTX */
unknown's avatar
unknown committed
1664
      case SHOW_SSL_CTX_SESS_ACCEPT:
1665 1666
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_accept(ssl_acceptor_fd->
unknown's avatar
unknown committed
1667
						      ssl_context)),
1668
			  buff, 10);
unknown's avatar
unknown committed
1669 1670
        break;
      case SHOW_SSL_CTX_SESS_ACCEPT_GOOD:
1671 1672
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_accept_good(ssl_acceptor_fd->
unknown's avatar
unknown committed
1673
							   ssl_context)),
1674
			  buff, 10);
unknown's avatar
unknown committed
1675
        break;
1676
      case SHOW_SSL_CTX_SESS_CONNECT_GOOD:
1677 1678
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_connect_good(ssl_acceptor_fd->
unknown's avatar
unknown committed
1679
							    ssl_context)),
1680
			  buff, 10);
1681
        break;
unknown's avatar
unknown committed
1682
      case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE:
1683
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
1684
				  SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context)),
1685
			  buff, 10);
unknown's avatar
unknown committed
1686
        break;
1687
      case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE:
1688
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
1689
				  SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context)),
1690
			  buff, 10);
1691
        break;
unknown's avatar
unknown committed
1692
      case SHOW_SSL_CTX_SESS_CB_HITS:
1693 1694
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_cb_hits(ssl_acceptor_fd->
unknown's avatar
unknown committed
1695
						       ssl_context)),
1696
			  buff, 10);
unknown's avatar
unknown committed
1697
        break;
1698
      case SHOW_SSL_CTX_SESS_HITS:
1699 1700
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_hits(ssl_acceptor_fd->
unknown's avatar
unknown committed
1701
						    ssl_context)),
1702
			  buff, 10);
1703 1704
        break;
      case SHOW_SSL_CTX_SESS_CACHE_FULL:
1705 1706
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_cache_full(ssl_acceptor_fd->
unknown's avatar
unknown committed
1707
							  ssl_context)),
1708
			  buff, 10);
1709 1710
        break;
      case SHOW_SSL_CTX_SESS_MISSES:
1711 1712
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_misses(ssl_acceptor_fd->
unknown's avatar
unknown committed
1713
						      ssl_context)),
1714
			  buff, 10);
1715 1716
        break;
      case SHOW_SSL_CTX_SESS_TIMEOUTS:
1717
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
1718
				  SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context)),
1719
			  buff,10);
1720
        break;
unknown's avatar
unknown committed
1721
      case SHOW_SSL_CTX_SESS_NUMBER:
1722
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
1723
				  SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context)),
1724
			  buff,10);
unknown's avatar
unknown committed
1725
        break;
1726
      case SHOW_SSL_CTX_SESS_CONNECT:
1727
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
1728
				  SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)),
1729
			  buff,10);
1730
        break;
unknown's avatar
unknown committed
1731
      case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE:
1732
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
1733
				  SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context)),
1734
				  buff,10);
unknown's avatar
unknown committed
1735 1736
        break;
      case SHOW_SSL_CTX_GET_VERIFY_MODE:
1737
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
1738
				  SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)),
1739
			  buff,10);
unknown's avatar
unknown committed
1740 1741
        break;
      case SHOW_SSL_CTX_GET_VERIFY_DEPTH:
1742
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
unknown's avatar
unknown committed
1743
				  SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)),
1744
			  buff,10);
unknown's avatar
unknown committed
1745 1746
        break;
      case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE:
1747 1748
	if (!ssl_acceptor_fd)
	{
1749 1750
	  pos= "NONE";
	  end= pos+4;
1751 1752
	  break;
	}
1753
	switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
unknown's avatar
unknown committed
1754 1755
	{
          case SSL_SESS_CACHE_OFF:
1756
            pos= "OFF";
unknown's avatar
unknown committed
1757 1758
	    break;
          case SSL_SESS_CACHE_CLIENT:
1759
            pos= "CLIENT";
unknown's avatar
unknown committed
1760 1761
	    break;
          case SSL_SESS_CACHE_SERVER:
1762
            pos= "SERVER";
unknown's avatar
unknown committed
1763 1764
	    break;
          case SSL_SESS_CACHE_BOTH:
1765
            pos= "BOTH";
unknown's avatar
unknown committed
1766 1767
	    break;
          case SSL_SESS_CACHE_NO_AUTO_CLEAR:
1768
            pos= "NO_AUTO_CLEAR";
unknown's avatar
unknown committed
1769 1770
	    break;
          case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
1771
            pos= "NO_INTERNAL_LOOKUP";
unknown's avatar
unknown committed
1772 1773
	    break;
	  default:
1774
            pos= "Unknown";
unknown's avatar
unknown committed
1775 1776
	    break;
	}
1777
	end= strend(pos);
unknown's avatar
unknown committed
1778
        break;
unknown's avatar
unknown committed
1779 1780
	/* First group - functions relying on SSL */
      case SHOW_SSL_GET_VERSION:
unknown's avatar
unknown committed
1781 1782
	pos= (thd->net.vio->ssl_arg ?
	      SSL_get_version((SSL*) thd->net.vio->ssl_arg) : "");
1783
	end= strend(pos);
unknown's avatar
unknown committed
1784 1785
        break;
      case SHOW_SSL_SESSION_REUSED:
unknown's avatar
unknown committed
1786 1787 1788 1789 1790
	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
1791 1792
        break;
      case SHOW_SSL_GET_DEFAULT_TIMEOUT:
unknown's avatar
unknown committed
1793 1794 1795 1796 1797
	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
1798 1799
        break;
      case SHOW_SSL_GET_VERIFY_MODE:
unknown's avatar
unknown committed
1800 1801 1802 1803 1804
	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
1805 1806
        break;
      case SHOW_SSL_GET_VERIFY_DEPTH:
unknown's avatar
unknown committed
1807 1808 1809 1810 1811
	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
1812 1813
        break;
      case SHOW_SSL_GET_CIPHER:
unknown's avatar
unknown committed
1814 1815
	pos= (thd->net.vio->ssl_arg ?
	      SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : "" );
1816
	end= strend(pos);
1817
	break;
1818
      case SHOW_SSL_GET_CIPHER_LIST:
1819
	if (thd->net.vio->ssl_arg)
1820
	{
1821
	  char *to= buff;
1822
	  for (int i=0 ; i++ ;)
1823
	  {
unknown's avatar
unknown committed
1824
	    const char *p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i);
1825 1826
	    if (p == NULL) 
	      break;
1827 1828
	    to= strmov(to, p);
	    *to++= ':';
1829
	  }
1830 1831 1832
	  if (to != buff)
	    to--;				// Remove last ':'
	  end= to;
1833
        }
unknown's avatar
unknown committed
1834
        break;
unknown's avatar
unknown committed
1835 1836

#endif /* HAVE_OPENSSL */
unknown's avatar
unknown committed
1837 1838
      case SHOW_UNDEF:				// Show never happen
      case SHOW_SYS:
1839
	break;					// Return empty string
unknown's avatar
SCRUM  
unknown committed
1840 1841
      default:
	break;
unknown's avatar
unknown committed
1842
      }
1843
      if (protocol->store(pos, (uint32) (end - pos), system_charset_info) ||
1844
	  protocol->write())
1845
        goto err;                               /* purecov: inspected */
unknown's avatar
unknown committed
1846 1847
    }
  }
unknown's avatar
unknown committed
1848
  pthread_mutex_unlock(mutex);
1849
  send_eof(thd);
unknown's avatar
unknown committed
1850 1851 1852
  DBUG_RETURN(0);

 err:
unknown's avatar
unknown committed
1853
  pthread_mutex_unlock(mutex);
unknown's avatar
unknown committed
1854 1855 1856 1857
  DBUG_RETURN(1);
}

#ifdef __GNUC__
unknown's avatar
unknown committed
1858
template class List_iterator_fast<char>;
unknown's avatar
unknown committed
1859 1860
template class List<char>;
#endif