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

bk@work.mysql.com's avatar
bk@work.mysql.com 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

bk@work.mysql.com's avatar
bk@work.mysql.com 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

bk@work.mysql.com's avatar
bk@work.mysql.com 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
bk@work.mysql.com's avatar
bk@work.mysql.com committed
22
#include "sql_acl.h"
23
#include "repl_failsafe.h"
bk@work.mysql.com's avatar
bk@work.mysql.com committed
24
#include <my_dir.h>
25

tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
26 27 28 29
#ifdef HAVE_BERKELEY_DB
#include "ha_berkeley.h"			// For berkeley_show_logs
#endif

30
/* extern "C" pthread_mutex_t THR_LOCK_keycache; */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
31 32 33 34 35 36

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 **),
37 38
                               "grant_types",
                               grant_names};
bk@work.mysql.com's avatar
bk@work.mysql.com committed
39 40

static int mysql_find_files(THD *thd,List<char> *files, const char *db,
41
                            const char *path, const char *wild, bool dir);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
42 43

static int
44 45 46 47
store_create_info(THD *thd, TABLE *table, String *packet);

static void
append_identifier(THD *thd, String *packet, const char *name);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
48

tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
49 50
extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
51 52 53 54 55 56 57 58 59
/****************************************************************************
** Send list of databases
** A database is a directory in the mysql_data_home directory
****************************************************************************/


int
mysqld_show_dbs(THD *thd,const char *wild)
{
60
  Item_string *field=new Item_string("",0,default_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
61 62 63 64 65 66
  List<Item> field_list;
  char *end;
  List<char> files;
  char *file_name;
  DBUG_ENTER("mysqld_show_dbs");

67
  field->name=(char*) thd->alloc(20+ (wild ? (uint) strlen(wild)+4: 0));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
68 69 70 71 72 73 74 75 76 77
  field->max_length=NAME_LEN;
  end=strmov(field->name,"Database");
  if (wild && wild[0])
    strxmov(end," (",wild,")",NullS);
  field_list.push_back(field);

  if (send_fields(thd,field_list,1))
    DBUG_RETURN(1);
  if (mysql_find_files(thd,&files,NullS,mysql_data_home,wild,1))
    DBUG_RETURN(1);
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
78
  List_iterator_fast<char> it(files);
79 80

  String *packet= &thd->packet;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
81 82
  while ((file_name=it++))
  {
83
    if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
84 85 86
	acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
		thd->priv_user, file_name) ||
	(grant_option && !check_grant_db(thd, file_name)))
87
    {
88 89 90 91
      packet->length(0);
      net_store_data(packet, thd->variables.convert_set, file_name);
      if (my_net_write(&thd->net, (char*) packet->ptr(),
		       packet->length()))
92 93
	DBUG_RETURN(-1);
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
94
  }
95
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
96 97 98
  DBUG_RETURN(0);
}

99

100
/***************************************************************************
101
  List all open tables in a database
102 103
***************************************************************************/

104
int mysqld_show_open_tables(THD *thd,const char *wild)
105 106
{
  List<Item> field_list;
107
  OPEN_TABLE_LIST *open_list;
108
  CONVERT *convert=thd->variables.convert_set;
109 110
  DBUG_ENTER("mysqld_show_open_tables");

111 112 113 114
  field_list.push_back(new Item_empty_string("Database",NAME_LEN));
  field_list.push_back(new Item_empty_string("Table",NAME_LEN));
  field_list.push_back(new Item_int("In_use",0, 4));
  field_list.push_back(new Item_int("Name_locked",0, 4));
115 116 117

  if (send_fields(thd,field_list,1))
    DBUG_RETURN(1);
118

monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
119
  if (!(open_list=list_open_tables(thd,wild)) && thd->fatal_error)
120 121
    DBUG_RETURN(-1);

122
  String *packet= &thd->packet;
123
  for (; open_list ; open_list=open_list->next)
124
  {
125 126 127 128 129 130
    packet->length(0);
    net_store_data(packet,convert, open_list->db);
    net_store_data(packet,convert, open_list->table);
    net_store_data(packet,open_list->in_use);
    net_store_data(packet,open_list->locked);
    if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
131
    {
132
      DBUG_RETURN(-1);
133
    }
134
  }
135
  send_eof(thd);
136 137 138
  DBUG_RETURN(0);
}

139

bk@work.mysql.com's avatar
bk@work.mysql.com committed
140 141 142 143 144 145 146
/***************************************************************************
** 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)
{
147
  Item_string *field=new Item_string("",0,default_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
148 149 150 151 152 153
  List<Item> field_list;
  char path[FN_LEN],*end;
  List<char> files;
  char *file_name;
  DBUG_ENTER("mysqld_show_tables");

154
  field->name=(char*) thd->alloc(20+(uint) strlen(db)+(wild ? (uint) strlen(wild)+4:0));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
155 156 157 158 159 160 161 162 163 164 165
  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);
  if (send_fields(thd,field_list,1))
    DBUG_RETURN(1);
  if (mysql_find_files(thd,&files,db,path,wild,0))
    DBUG_RETURN(-1);
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
166
  List_iterator_fast<char> it(files);
167
  String *packet= &thd->packet;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
168 169
  while ((file_name=it++))
  {
170 171 172
    packet->length(0);
    net_store_data(packet, thd->variables.convert_set, file_name);
    if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
173 174
      DBUG_RETURN(-1);
  }
175
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
176 177 178
  DBUG_RETURN(0);
}

179 180 181 182
/***************************************************************************
** List all table types supported 
***************************************************************************/

183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
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}
207 208
};

209

210 211 212 213 214 215 216
int mysqld_show_table_types(THD *thd)
{
  List<Item> field_list;
  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));
217
  field_list.push_back(new Item_empty_string("Comment",80));
218 219 220 221

  if (send_fields(thd,field_list,1))
    DBUG_RETURN(1);

222
  const char *default_type_name= ha_table_typelib.type_names[thd->variables.table_type];
223

224 225 226
  show_table_type_st *types;
  String *packet= &thd->packet;
  for (types= sys_table_types; types->type; types++)
227
  {
228 229 230 231 232 233 234 235 236 237
    packet->length(0);
    net_store_data(packet, types->type);
    const char *option_name= show_comp_option_name[(int) *types->value];

    if (*types->value == SHOW_OPTION_YES &&
	!strcasecmp(default_type_name, types->type))
      option_name= "DEFAULT";
    net_store_data(packet, option_name);
    net_store_data(packet, types->comment);
    if (my_net_write(&thd->net, (char*) packet->ptr(), packet->length()))
238 239
      DBUG_RETURN(-1);
  }
240
  send_eof(thd);
241 242 243
  DBUG_RETURN(0);
}

244

245
/***************************************************************************
246
 List all privileges supported
247 248
***************************************************************************/

249 250 251 252
struct show_privileges_st {
  const char *privilege;
  const char *context;
  const char *comment;
253 254
};

255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278

/*
  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}
};


279 280 281 282 283 284 285 286 287 288 289 290
int mysqld_show_privileges(THD *thd)
{
  List<Item> field_list;
  DBUG_ENTER("mysqld_show_privileges");

  field_list.push_back(new Item_empty_string("Privilege",10));
  field_list.push_back(new Item_empty_string("Context",15));
  field_list.push_back(new Item_empty_string("Comment",NAME_LEN));

  if (send_fields(thd,field_list,1))
    DBUG_RETURN(1);

291 292 293
  show_privileges_st *privilege= sys_privileges;
  String *packet= &thd->packet;
  for (privilege= sys_privileges; privilege->privilege ; privilege++)
294
  {
295 296 297 298 299
    packet->length(0);
    net_store_data(packet,privilege->privilege);
    net_store_data(packet,privilege->context);
    net_store_data(packet,privilege->comment);
    if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
300 301
      DBUG_RETURN(-1);
  }
302
  send_eof(thd);
303 304 305 306 307
  DBUG_RETURN(0);
}


/***************************************************************************
308
  List all column types
309 310
***************************************************************************/

311 312
struct show_column_type_st
{
313 314
  const char *type;
  uint size;
315 316 317 318 319 320 321 322 323 324 325 326
  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;
327
};
328 329 330 331 332

/* TODO: Add remaning types */

static struct show_column_type_st sys_column_types[]=
{
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
  {"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;
  DBUG_ENTER("mysqld_show_column_types");

  field_list.push_back(new Item_empty_string("Type",30));
  field_list.push_back(new Item_int("Size",(longlong) 1,21));
  field_list.push_back(new Item_empty_string("Min_Value",20));
  field_list.push_back(new Item_empty_string("Max_Value",20));
  field_list.push_back(new Item_int("Prec", 0,4));
  field_list.push_back(new Item_int("Scale", 0,4));
  field_list.push_back(new Item_empty_string("Nullable",4));
  field_list.push_back(new Item_empty_string("Auto_Increment",4));
  field_list.push_back(new Item_empty_string("Unsigned",4));
  field_list.push_back(new Item_empty_string("Zerofill",4));
  field_list.push_back(new Item_empty_string("Searchable",4));
  field_list.push_back(new Item_empty_string("Case_Sensitive",4));
  field_list.push_back(new Item_empty_string("Default",NAME_LEN));
  field_list.push_back(new Item_empty_string("Comment",NAME_LEN));

  if (send_fields(thd,field_list,1))
    DBUG_RETURN(1);

366 367
  /* TODO: Change the loop to not use 'i' */
  String *packet= &thd->packet;
368 369
  for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++)
  {
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
    packet->length(0);
    net_store_data(packet,sys_column_types[i].type);
    net_store_data(packet,(longlong)sys_column_types[i].size);
    net_store_data(packet,sys_column_types[i].min_value);
    net_store_data(packet,sys_column_types[i].max_value);
    net_store_data(packet,(uint32)sys_column_types[i].precision);
    net_store_data(packet,(uint32)sys_column_types[i].scale);
    net_store_data(packet,sys_column_types[i].nullable);
    net_store_data(packet,sys_column_types[i].auto_increment);
    net_store_data(packet,sys_column_types[i].unsigned_attr);
    net_store_data(packet,sys_column_types[i].zerofill);
    net_store_data(packet,sys_column_types[i].searchable);
    net_store_data(packet,sys_column_types[i].case_sensitivity);
    net_store_data(packet,sys_column_types[i].default_value);
    net_store_data(packet,sys_column_types[i].comment);
    if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
386 387
      DBUG_RETURN(-1);
  }
388
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
389 390 391 392 393 394
  DBUG_RETURN(0);
}


static int
mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
395
                 const char *wild, bool dir)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
396 397 398 399 400 401 402 403 404
{
  uint i;
  char *ext;
  MY_DIR *dirp;
  FILEINFO *file;
  uint col_access=thd->col_access;
  TABLE_LIST table_list;
  DBUG_ENTER("mysql_find_files");

405 406
  if (wild && !wild[0])
    wild=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
407 408 409 410 411
  bzero((char*) &table_list,sizeof(table_list));

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

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

467

bk@work.mysql.com's avatar
bk@work.mysql.com committed
468
/***************************************************************************
469
 Extended version of mysqld_show_tables
bk@work.mysql.com's avatar
bk@work.mysql.com committed
470 471 472 473 474 475 476 477 478 479 480
***************************************************************************/

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;
  String *packet= &thd->packet;
481
  CONVERT *convert=thd->variables.convert_set;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
  DBUG_ENTER("mysqld_extend_show_tables");

  (void) sprintf(path,"%s/%s",mysql_data_home,db);
  (void) unpack_dirname(path,path);
  field_list.push_back(item=new Item_empty_string("Name",NAME_LEN));
  item->maybe_null=1;
  field_list.push_back(item=new Item_empty_string("Type",10));
  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;
512 513
  field_list.push_back(item=new Item_empty_string("Charset",32));
  item->maybe_null=1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
514 515 516 517 518 519 520 521
  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));
  if (send_fields(thd,field_list,1))
    DBUG_RETURN(1);

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


/***************************************************************************
648
** List all columns in a table_list->real_name
bk@work.mysql.com's avatar
bk@work.mysql.com committed
649 650 651
***************************************************************************/

int
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
652 653
mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
		   bool verbose)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
654 655 656 657
{
  TABLE *table;
  handler *file;
  char tmp[MAX_FIELD_WIDTH];
658
  Item *item;
659
  CONVERT *convert=thd->variables.convert_set;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
660 661
  DBUG_ENTER("mysqld_show_fields");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
662
                      table_list->real_name));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
663 664 665

  if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  {
666
    send_error(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
667 668 669 670 671 672 673 674 675 676 677
    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));
  field_list.push_back(new Item_empty_string("Null",1));
  field_list.push_back(new Item_empty_string("Key",3));
678 679
  field_list.push_back(item=new Item_empty_string("Default",NAME_LEN));
  item->maybe_null=1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
680
  field_list.push_back(new Item_empty_string("Extra",20));
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
681
  if (verbose)
682
  {
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
683
    field_list.push_back(new Item_empty_string("Privileges",80));
684 685
    field_list.push_back(new Item_empty_string("Comment",255));
  }
686
        // Send first number of fields and records
bk@work.mysql.com's avatar
bk@work.mysql.com committed
687 688 689 690 691 692 693 694 695
  {
    char *pos;
    pos=net_store_length(tmp, (uint) field_list.elements);
    pos=net_store_length(pos,(ulonglong) file->records);
    (void) my_net_write(&thd->net,tmp,(uint) (pos-tmp));
  }

  if (send_fields(thd,field_list,0))
    DBUG_RETURN(1);
696
  restore_record(table,2);      // Get empty record
bk@work.mysql.com's avatar
bk@work.mysql.com committed
697 698

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

        packet->length(0);
718
        net_store_data(packet,convert,field->field_name);
719
        field->sql_type(type);
720
        net_store_data(packet,convert,type.ptr(),type.length());
721 722 723 724

        pos=(byte*) ((flags & NOT_NULL_FLAG) &&
                     field->type() != FIELD_TYPE_TIMESTAMP ?
                     "" : "YES");
725
        net_store_data(packet,convert,(const char*) pos);
726 727 728
        pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
                     (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
                     (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
729
        net_store_data(packet,convert,(char*) pos);
730 731 732 733 734 735

        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
736
          type.set(tmp,sizeof(tmp),default_charset_info);
737
          field->val_str(&type,&type);
738
          net_store_data(packet,convert,type.ptr(),type.length());
739 740 741 742
        }
        else if (field->maybe_null() || null_default_value)
          net_store_null(packet);                       // Null as default
        else
743
          net_store_data(packet,convert,tmp,0);
744 745 746 747

        char *end=tmp;
        if (field->unireg_check == Field::NEXT_NUMBER)
          end=strmov(tmp,"auto_increment");
748
        net_store_data(packet,convert,tmp,(uint) (end-tmp));
749

monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
750 751
	if (verbose)
	{
752
	  /* Add grant options & comments */
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
753 754 755 756 757 758 759 760 761 762
	  col_access= get_column_grant(thd,table_list,field) & COL_ACLS;
	  end=tmp;
	  for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
	  {
	    if (col_access & 1)
	    {
	      *end++=',';
	      end=strmov(end,grant_types.type_names[bitnr]);
	    }
	  }
763
	  net_store_data(packet,convert, tmp+1,end == tmp ? 0 : (uint) (end-tmp-1));
764
	  net_store_data(packet, field->comment.str,field->comment.length);
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
765
	}
766 767
        if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
          DBUG_RETURN(1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
768 769 770
      }
    }
  }
771
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
772 773 774
  DBUG_RETURN(0);
}

775

bk@work.mysql.com's avatar
bk@work.mysql.com committed
776 777 778 779
int
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
  TABLE *table;
780
  CONVERT *convert=thd->variables.convert_set;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
781 782
  DBUG_ENTER("mysqld_show_create");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
783
                      table_list->real_name));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
784

monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
785
  /* Only one table for now */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
786 787
  if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  {
788
    send_error(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
789 790 791 792 793 794 795 796 797
    DBUG_RETURN(1);
  }

  List<Item> field_list;
  field_list.push_back(new Item_empty_string("Table",NAME_LEN));
  field_list.push_back(new Item_empty_string("Create Table",1024));

  if (send_fields(thd,field_list,1))
    DBUG_RETURN(1);
798

bk@work.mysql.com's avatar
bk@work.mysql.com committed
799
  String *packet = &thd->packet;
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
800 801
  {
    packet->length(0);
802
    net_store_data(packet,convert, table->table_name);
803 804 805 806 807
    /*
      A hack - we need to reserve some space for the length before
      we know what it is - let's assume that the length of create table
      statement will fit into 3 bytes ( 16 MB max :-) )
    */
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
808 809 810 811 812
    ulong store_len_offset = packet->length();
    packet->length(store_len_offset + 4);
    if (store_create_info(thd, table, packet))
      DBUG_RETURN(-1);
    ulong create_len = packet->length() - store_len_offset - 4;
813 814 815 816
    /*
      Just in case somebody manages to create a table
      with *that* much stuff in the definition
    */
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
817
    if (create_len > 0x00ffffff) // better readable in HEX ...
818 819 820 821 822 823 824
    {
      /*
	Just in case somebody manages to create a table
	with *that* much stuff in the definition
      */
      DBUG_RETURN(1);
    }
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
825

826 827 828 829 830
    /*
      Now we have to store the length in three bytes, even if it would fit
      into fewer bytes, so we cannot use net_store_data() anymore,
      and do it ourselves
    */
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
831 832 833 834 835 836 837 838
    char* p = (char*)packet->ptr() + store_len_offset;
    *p++ = (char) 253; // The client the length is stored using 3-bytes
    int3store(p, create_len);

    // now we are in business :-)
    if (my_net_write(&thd->net, (char*)packet->ptr(), packet->length()))
      DBUG_RETURN(1);
  }
839
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
840 841 842 843
  DBUG_RETURN(0);
}


tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
844 845 846 847 848 849 850 851 852 853 854 855 856
int
mysqld_show_logs(THD *thd)
{
  DBUG_ENTER("mysqld_show_logs");

  List<Item> field_list;
  field_list.push_back(new Item_empty_string("File",FN_REFLEN));
  field_list.push_back(new Item_empty_string("Type",10));
  field_list.push_back(new Item_empty_string("Status",10));

  if (send_fields(thd,field_list,1))
    DBUG_RETURN(1);

857
#ifdef HAVE_BERKELEY_DB
858
  if (!berkeley_skip && berkeley_show_logs(thd))
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
859
    DBUG_RETURN(-1);
860
#endif
tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
861

862
  send_eof(thd);
tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
863 864 865 866
  DBUG_RETURN(0);
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
867 868 869 870 871
int
mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
{
  TABLE *table;
  char buff[256];
872
  CONVERT *convert=thd->variables.convert_set;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
873 874
  DBUG_ENTER("mysqld_show_keys");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
875
                      table_list->real_name));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
876 877 878

  if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  {
879
    send_error(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897
    DBUG_RETURN(1);
  }

  List<Item> field_list;
  Item *item;
  field_list.push_back(new Item_empty_string("Table",NAME_LEN));
  field_list.push_back(new Item_int("Non_unique",0,1));
  field_list.push_back(new Item_empty_string("Key_name",NAME_LEN));
  field_list.push_back(new Item_int("Seq_in_index",0,2));
  field_list.push_back(new Item_empty_string("Column_name",NAME_LEN));
  field_list.push_back(item=new Item_empty_string("Collation",1));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Cardinality",0,11));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Sub_part",0,3));
  item->maybe_null=1;
  field_list.push_back(item=new Item_empty_string("Packed",10));
  item->maybe_null=1;
898 899
  field_list.push_back(new Item_empty_string("Null",3));
  field_list.push_back(new Item_empty_string("Index_type",16));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
900 901 902 903 904 905
  field_list.push_back(new Item_empty_string("Comment",255));
  item->maybe_null=1;

  if (send_fields(thd,field_list,1))
    DBUG_RETURN(1);

tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
906
  String *packet= &thd->packet;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
907 908 909 910 911 912 913 914 915
  KEY *key_info=table->key_info;
  table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
  for (uint i=0 ; i < table->keys ; i++,key_info++)
  {
    KEY_PART_INFO *key_part= key_info->key_part;
    char *end;
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
    {
      packet->length(0);
916 917 918
      net_store_data(packet,convert,table->table_name);
      net_store_data(packet,convert,((key_info->flags & HA_NOSAME) ? "0" :"1"), 1);
      net_store_data(packet,convert,key_info->name);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
919
      end=int10_to_str((long) (j+1),(char*) buff,10);
920 921 922
      net_store_data(packet,convert,buff,(uint) (end-buff));
      net_store_data(packet,convert,
		     key_part->field ? key_part->field->field_name :
923
                     "?unknown field?");
924
      if (table->file->index_flags(i) & HA_READ_ORDER)
925 926 927
        net_store_data(packet,convert,
		       ((key_part->key_part_flag & HA_REVERSE_SORT) ?
			"D" : "A"), 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
928
      else
929
        net_store_null(packet); /* purecov: inspected */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
930 931 932
      KEY *key=table->key_info+i;
      if (key->rec_per_key[j])
      {
933 934
        ulong records=(table->file->records / key->rec_per_key[j]);
        end=int10_to_str((long) records, buff, 10);
935
        net_store_data(packet,convert,buff,(uint) (end-buff));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
936 937
      }
      else
938
        net_store_null(packet);
939 940

      /* Check if we have a key part that only uses part of the field */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
941
      if (!key_part->field ||
942 943
          key_part->length !=
          table->field[key_part->fieldnr-1]->key_length())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
944
      {
945
        end=int10_to_str((long) key_part->length, buff,10); /* purecov: inspected */
946
        net_store_data(packet,convert,buff,(uint) (end-buff)); /* purecov: inspected */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
947 948
      }
      else
949 950
        net_store_null(packet);
      net_store_null(packet);                   // No pack_information yet
951 952 953

      /* Null flag */
      uint flags= key_part->field ? key_part->field->flags : 0;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
954
      char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
955 956 957 958
      net_store_data(packet,convert,(const char*) pos);
      net_store_data(packet,convert,table->file->index_type(i));
      /* Comment */
      net_store_data(packet,convert,"");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
959
      if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
960
        DBUG_RETURN(1); /* purecov: inspected */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
961 962
    }
  }
963
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
964 965 966 967 968
  DBUG_RETURN(0);
}


/****************************************************************************
969 970
  Return only fields for API mysql_list_fields
  Use "show table wildcard" in mysql instead of this
bk@work.mysql.com's avatar
bk@work.mysql.com committed
971 972 973 974 975 976 977 978 979 980 981
****************************************************************************/

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)))
  {
982
    send_error(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
983 984 985 986 987 988 989
    DBUG_VOID_RETURN;
  }
  List<Item> field_list;

  Field **ptr,*field;
  for (ptr=table->field ; (field= *ptr); ptr++)
  {
990 991
    if (!wild || !wild[0] || 
        !wild_case_compare(system_charset_info, field->field_name,wild))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
992 993
      field_list.push_back(new Item_field(field));
  }
994
  restore_record(table,2);              // Get empty record
bk@work.mysql.com's avatar
bk@work.mysql.com committed
995 996 997 998 999 1000
  if (send_fields(thd,field_list,2))
    DBUG_VOID_RETURN;
  VOID(net_flush(&thd->net));
  DBUG_VOID_RETURN;
}

1001

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1002 1003 1004
int
mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
{
1005
  CONVERT *convert=thd->variables.convert_set;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1006 1007
  DBUG_ENTER("mysqld_dump_create_info");
  DBUG_PRINT("enter",("table: %s",table->real_name));
1008

1009
  String *packet = &thd->packet;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1010
  packet->length(0);
1011
  if (store_create_info(thd,table,packet))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1012
    DBUG_RETURN(-1);
1013

1014 1015 1016
  if (convert)
    convert->convert((char*) packet->ptr(), packet->length());
  if (fd < 0)
1017
  {
1018
    if (my_net_write(&thd->net, (char*)packet->ptr(), packet->length()))
1019 1020 1021
      DBUG_RETURN(-1);
    VOID(net_flush(&thd->net));
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1022
  else
1023
  {
1024 1025
    if (my_write(fd, (const byte*) packet->ptr(), packet->length(),
		 MYF(MY_WME)))
1026 1027
      DBUG_RETURN(-1);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1028 1029
  DBUG_RETURN(0);
}
1030

1031

1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
static void
append_identifier(THD *thd, String *packet, const char *name)
{
  if (thd->options & OPTION_QUOTE_SHOW_CREATE)
  {
    packet->append("`", 1);
    packet->append(name);
    packet->append("`", 1);
  }
  else
  {
    packet->append(name);
  }
}

1047

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1048
static int
1049
store_create_info(THD *thd, TABLE *table, String *packet)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1050 1051 1052 1053 1054
{
  DBUG_ENTER("store_create_info");
  DBUG_PRINT("enter",("table: %s",table->real_name));

  restore_record(table,2); // Get empty record
1055

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1056 1057
  List<Item> field_list;
  char tmp[MAX_FIELD_WIDTH];
1058
  String type(tmp, sizeof(tmp),default_charset_info);
1059 1060 1061 1062
  if (table->tmp_table)
    packet->append("CREATE TEMPORARY TABLE ", 23);
  else
    packet->append("CREATE TABLE ", 13);
1063
  append_identifier(thd,packet,table->real_name);
1064
  packet->append(" (\n", 3);
1065

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1066 1067 1068
  Field **ptr,*field;
  for (ptr=table->field ; (field= *ptr); ptr++)
  {
1069
    if (ptr != table->field)
1070
      packet->append(",\n", 2);
1071

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1072
    uint flags = field->flags;
1073
    packet->append("  ", 2);
1074
    append_identifier(thd,packet,field->field_name);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1075 1076
    packet->append(' ');
    // check for surprises from the previous call to Field::sql_type()
1077
    if (type.ptr() != tmp)
1078
      type.set(tmp, sizeof(tmp),default_charset_info);
1079

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1080 1081
    field->sql_type(type);
    packet->append(type.ptr(),type.length());
1082

1083
    bool has_default = (field->type() != FIELD_TYPE_BLOB &&
1084 1085 1086 1087
			field->type() != FIELD_TYPE_TIMESTAMP &&
			field->unireg_check != Field::NEXT_NUMBER);
    if (flags & NOT_NULL_FLAG)
      packet->append(" NOT NULL", 9);
1088

1089
    if (has_default)
1090 1091
    {
      packet->append(" default ", 9);
1092
      if (!field->is_null())
1093
      {                                             // Not null by default
1094
        type.set(tmp,sizeof(tmp),default_charset_info);
1095
        field->val_str(&type,&type);
1096
	if (type.length())
1097 1098 1099
          append_unescaped(packet, type.ptr(), type.length());
        else
	  packet->append("''",2);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1100
      }
1101
      else if (field->maybe_null())
1102 1103 1104 1105
        packet->append("NULL", 4);                    // Null as default
      else
        packet->append(tmp,0);
    }
1106

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1107
    if (field->unireg_check == Field::NEXT_NUMBER)
1108 1109 1110 1111 1112 1113 1114
      packet->append(" auto_increment", 15 );

    if (field->comment.length)
    {
      packet->append(" COMMENT ",9);
      append_unescaped(packet, field->comment.str, field->comment.length);
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1115 1116 1117 1118 1119
  }

  KEY *key_info=table->key_info;
  table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
  uint primary_key = table->primary_key;
1120

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1121 1122
  for (uint i=0 ; i < table->keys ; i++,key_info++)
  {
1123 1124
    KEY_PART_INFO *key_part= key_info->key_part;
    bool found_primary=0;
1125
    packet->append(",\n  ", 4);
1126

1127 1128 1129
    if (i == primary_key && !strcmp(key_info->name,"PRIMARY"))
    {
      found_primary=1;
1130
      packet->append("PRIMARY ", 8);
1131
    }
1132
    else if (key_info->flags & HA_NOSAME)
1133
      packet->append("UNIQUE ", 7);
1134
    else if (key_info->flags & HA_FULLTEXT)
1135
      packet->append("FULLTEXT ", 9);
1136 1137
    else if (key_info->flags & HA_SPATIAL)
      packet->append("SPATIAL ", 8);
1138
    packet->append("KEY ", 4);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1139

1140
    if (!found_primary)
1141
     append_identifier(thd,packet,key_info->name);
1142

1143
    // +BAR: send USING only in non-default case: non-spatial rtree
1144 1145 1146
    if((key_info->algorithm == HA_KEY_ALG_RTREE) &&
       !(key_info->flags & HA_SPATIAL))
      packet->append(" USING RTREE",12);
1147

1148
    packet->append(" (", 2);
1149

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1150 1151
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
    {
1152
      if (j)
1153
        packet->append(',');
1154

1155
      if (key_part->field)
1156
        append_identifier(thd,packet,key_part->field->field_name);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1157
      if (!key_part->field ||
1158 1159 1160
          (key_part->length !=
           table->field[key_part->fieldnr-1]->key_length() &&
           !(key_info->flags & HA_FULLTEXT)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1161
      {
1162 1163 1164 1165 1166
        char buff[64];
        buff[0] = '(';
        char* end=int10_to_str((long) key_part->length, buff + 1,10);
        *end++ = ')';
        packet->append(buff,(uint) (end-buff));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1167 1168 1169 1170
      }
    }
    packet->append(')');
  }
1171

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1172
  handler *file = table->file;
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185

  /* Get possible foreign key definitions stored in InnoDB and append them
  to the CREATE TABLE statement */

  char* for_str = file->get_foreign_key_create_info();

  if (for_str) {
  	packet->append(for_str, strlen(for_str));

  	file->free_foreign_key_create_info(for_str);
  }

  packet->append("\n)", 2);
1186
  packet->append(" TYPE=", 6);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1187 1188 1189
  packet->append(file->table_type());
  char buff[128];
  char* p;
1190

1191 1192 1193 1194 1195 1196
  if (table->table_charset)
  {
    packet->append(" CHARSET=");
    packet->append(table->table_charset->name);
  }

1197
  if (table->min_rows)
1198 1199 1200 1201 1202
  {
    packet->append(" MIN_ROWS=");
    p = longlong10_to_str(table->min_rows, buff, 10);
    packet->append(buff, (uint) (p - buff));
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1203

1204
  if (table->max_rows)
1205 1206 1207 1208 1209
  {
    packet->append(" MAX_ROWS=");
    p = longlong10_to_str(table->max_rows, buff, 10);
    packet->append(buff, (uint) (p - buff));
  }
1210 1211 1212 1213 1214 1215
  if (table->avg_row_length)
  {
    packet->append(" AVG_ROW_LENGTH=");
    p=longlong10_to_str(table->avg_row_length, buff,10);
    packet->append(buff, (uint) (p - buff));
  }
1216

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1217
  if (table->db_create_options & HA_OPTION_PACK_KEYS)
1218
    packet->append(" PACK_KEYS=1", 12);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1219
  if (table->db_create_options & HA_OPTION_NO_PACK_KEYS)
1220
    packet->append(" PACK_KEYS=0", 12);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1221
  if (table->db_create_options & HA_OPTION_CHECKSUM)
1222
    packet->append(" CHECKSUM=1", 11);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1223
  if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
1224
    packet->append(" DELAY_KEY_WRITE=1",18);
1225 1226 1227 1228 1229
  if (table->row_type != ROW_TYPE_DEFAULT)
  {
    packet->append(" ROW_FORMAT=",12);
    packet->append(ha_row_type[(uint) table->row_type]);
  }
1230
  table->file->append_create_info(packet);
monty@donna.mysql.com's avatar
merge  
monty@donna.mysql.com committed
1231
  if (table->comment && table->comment[0])
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
1232
  {
1233 1234
    packet->append(" COMMENT=", 9);
    append_unescaped(packet, table->comment, strlen(table->comment));
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
1235
  }
1236 1237 1238 1239 1240 1241 1242
  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);
    packet->append(buff);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1243 1244 1245 1246 1247
  DBUG_RETURN(0);
}


/****************************************************************************
1248 1249
  Return info about all processes
  returns for each thread: thread id, user, host, db, command, info
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1250 1251 1252 1253
****************************************************************************/

class thread_info :public ilink {
public:
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
1254
  static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1255
  static void operator delete(void *ptr __attribute__((unused)),
1256
                              size_t size __attribute__((unused))) {} /*lint -e715 */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1257

monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
1258 1259
  ulong thread_id;
  time_t start_time;
1260
  uint   command;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
  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;
1275 1276 1277
  ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
			   PROCESS_LIST_WIDTH);
  CONVERT *convert=thd->variables.convert_set;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
  DBUG_ENTER("mysqld_list_processes");

  field_list.push_back(new Item_int("Id",0,7));
  field_list.push_back(new Item_empty_string("User",16));
  field_list.push_back(new Item_empty_string("Host",64));
  field_list.push_back(field=new Item_empty_string("db",NAME_LEN));
  field->maybe_null=1;
  field_list.push_back(new Item_empty_string("Command",16));
  field_list.push_back(new Item_empty_string("Time",7));
  field_list.push_back(field=new Item_empty_string("State",30));
  field->maybe_null=1;
  field_list.push_back(field=new Item_empty_string("Info",max_query_length));
  field->maybe_null=1;
  if (send_fields(thd,field_list,1))
    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++))
    {
      if ((tmp->net.vio || tmp->system_thread) &&
1302
          (!user || (tmp->user && !strcmp(tmp->user,user))))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1303
      {
1304 1305 1306
        thread_info *thd_info=new thread_info;

        thd_info->thread_id=tmp->thread_id;
1307 1308 1309 1310 1311 1312 1313
        thd_info->user=thd->strdup(tmp->user ? tmp->user :
				   (tmp->system_thread ?
				    "system user" : "unauthenticated user"));
        thd_info->host=thd->strdup(tmp->host ? tmp->host :
				   (tmp->ip ? tmp->ip :
				    (tmp->system_thread ? "none" :
				     "connecting host")));
1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331
        if ((thd_info->db=tmp->db))             // Safe test
          thd_info->db=thd->strdup(thd_info->db);
        thd_info->command=(int) tmp->command;
        if (tmp->mysys_var)
          pthread_mutex_lock(&tmp->mysys_var->mutex);
        thd_info->proc_info= (char*) (tmp->killed ? "Killed" : 0);
        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);
        if (tmp->mysys_var)
          pthread_mutex_unlock(&tmp->mysys_var->mutex);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1332 1333

#if !defined(DONT_USE_THR_ALARM) && ! defined(SCO)
1334 1335
        if (pthread_kill(tmp->real_id,0))
          tmp->proc_info="*** DEAD ***";        // This shouldn't happen
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1336
#endif
1337 1338 1339
#ifdef EXTRA_DEBUG
        thd_info->start_time= tmp->time_after_lock;
#else
1340
        thd_info->start_time= tmp->start_time;
1341
#endif
1342 1343 1344
        thd_info->query=0;
        if (tmp->query)
        {
1345 1346
	  /* query_length is always set before tmp->query */
          uint length= min(max_query_length, tmp->query_length);
1347 1348 1349 1350
          thd_info->query=(char*) thd->memdup(tmp->query,length+1);
          thd_info->query[length]=0;
        }
        thread_infos.append(thd_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362
      }
    }
  }
  VOID(pthread_mutex_unlock(&LOCK_thread_count));

  thread_info *thd_info;
  String *packet= &thd->packet;
  while ((thd_info=thread_infos.get()))
  {
    char buff[20],*end;
    packet->length(0);
    end=int10_to_str((long) thd_info->thread_id, buff,10);
1363 1364 1365
    net_store_data(packet,convert,buff,(uint) (end-buff));
    net_store_data(packet,convert,thd_info->user);
    net_store_data(packet,convert,thd_info->host);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1366
    if (thd_info->db)
1367
      net_store_data(packet,convert,thd_info->db);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1368 1369 1370
    else
      net_store_null(packet);
    if (thd_info->proc_info)
1371
      net_store_data(packet,convert,thd_info->proc_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1372
    else
1373
      net_store_data(packet,convert,command_name[thd_info->command]);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1374
    if (thd_info->start_time)
1375 1376
      net_store_data(packet,
		     (uint32) (time((time_t*) 0) - thd_info->start_time));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1377 1378 1379
    else
      net_store_null(packet);
    if (thd_info->state_info)
1380
      net_store_data(packet,convert,thd_info->state_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1381 1382 1383
    else
      net_store_null(packet);
    if (thd_info->query)
1384
      net_store_data(packet,convert,thd_info->query);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1385 1386 1387 1388 1389
    else
      net_store_null(packet);
    if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
      break; /* purecov: inspected */
  }
1390
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1391 1392 1393 1394 1395
  DBUG_VOID_RETURN;
}


/*****************************************************************************
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1396
  Status functions
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1397 1398
*****************************************************************************/

1399 1400 1401 1402 1403 1404
int mysqld_show_charsets(THD *thd, const char *wild)
{
  uint i;
  char buff[8192];
  String packet2(buff,sizeof(buff),default_charset_info);
  List<Item> field_list;
1405
  CONVERT *convert=thd->variables.convert_set;
1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416
  CHARSET_INFO *cs;
  DBUG_ENTER("mysqld_show_charsets");

  field_list.push_back(new Item_empty_string("Name",30));
  field_list.push_back(new Item_int("Id",0,7));
  field_list.push_back(new Item_int("strx_maxlen",0,7));
  field_list.push_back(new Item_int("mb_maxlen",0,7));

  if (send_fields(thd,field_list,1))
    DBUG_RETURN(1);

1417
  for (cs=all_charsets ; cs < all_charsets+255 ; cs++ )
1418
  {
1419 1420
    if (!cs->name)
      continue;
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1421 1422
    if (!(wild && wild[0] &&
	  wild_case_compare(system_charset_info,cs->name,wild)))
1423 1424 1425 1426 1427
    {
      packet2.length(0);
      net_store_data(&packet2,convert,cs->name);
      net_store_data(&packet2,(uint32) cs->number);
      net_store_data(&packet2,(uint32) cs->strxfrm_multiply);
1428
      net_store_data(&packet2,(uint32) cs->mbmaxlen ? cs->mbmaxlen : 1);
1429 1430

      if (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length()))
1431
         goto err;
1432 1433
    }
  }
1434
  send_eof(thd); 
1435 1436 1437 1438 1439
  DBUG_RETURN(0);
err:
  DBUG_RETURN(1);
}

monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1440
  
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1441

1442
int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
1443
		enum enum_var_type value_type)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1444 1445
{
  char buff[8192];
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1446
  String packet2(buff,sizeof(buff), system_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1447
  List<Item> field_list;
1448
  CONVERT *convert=thd->variables.convert_set;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1449
  DBUG_ENTER("mysqld_show");
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1450

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1451 1452 1453 1454 1455
  field_list.push_back(new Item_empty_string("Variable_name",30));
  field_list.push_back(new Item_empty_string("Value",256));
  if (send_fields(thd,field_list,1))
    DBUG_RETURN(1); /* purecov: inspected */

1456
  /* pthread_mutex_lock(&THR_LOCK_keycache); */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1457
  pthread_mutex_lock(&LOCK_status);
1458
  for (; variables->name; variables++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1459
  {
1460
    if (!(wild && wild[0] && wild_case_compare(system_charset_info,
1461
					       variables->name,wild)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1462 1463
    {
      packet2.length(0);
1464 1465 1466 1467 1468 1469
      net_store_data(&packet2,convert,variables->name);
      SHOW_TYPE show_type=variables->type;
      char *value=variables->value;
      if (show_type == SHOW_SYS)
      {
	show_type= ((sys_var*) value)->type();
1470
	value=     (char*) ((sys_var*) value)->value_ptr(thd, value_type);
1471 1472 1473
      }

      switch (show_type) {
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1474 1475
      case SHOW_LONG:
      case SHOW_LONG_CONST:
1476 1477 1478 1479
        net_store_data(&packet2,(uint32) *(ulong*) value);
        break;
      case SHOW_LONGLONG:
        net_store_data(&packet2,(longlong) *(longlong*) value);
1480
        break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1481
      case SHOW_BOOL:
1482
        net_store_data(&packet2,(ulong) *(bool*) value ? "ON" : "OFF");
1483
        break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1484
      case SHOW_MY_BOOL:
1485
        net_store_data(&packet2,(ulong) *(my_bool*) value ? "ON" : "OFF");
1486
        break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1487 1488
      case SHOW_INT_CONST:
      case SHOW_INT:
1489
        net_store_data(&packet2,(uint32) *(int*) value);
1490
        break;
1491 1492
      case SHOW_HAVE:
      {
1493
	SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
1494
        net_store_data(&packet2, show_comp_option_name[(int) tmp]);
1495 1496
        break;
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1497
      case SHOW_CHAR:
1498
        net_store_data(&packet2,convert, value);
1499
        break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1500
      case SHOW_STARTTIME:
1501 1502
        net_store_data(&packet2,(uint32) (thd->query_start() - start_time));
        break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1503
      case SHOW_QUESTION:
1504 1505
        net_store_data(&packet2,(uint32) thd->query_id);
        break;
1506 1507 1508
      case SHOW_RPL_STATUS:
	net_store_data(&packet2, rpl_status_type[(int)rpl_status]);
	break;
1509 1510 1511 1512 1513 1514 1515 1516 1517
      case SHOW_SLAVE_RUNNING:
      {
	LOCK_ACTIVE_MI;
	net_store_data(&packet2, (active_mi->slave_running &&
				  active_mi->rli.slave_running)
		        ? "ON" : "OFF");
	UNLOCK_ACTIVE_MI;
	break;
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1518
      case SHOW_OPENTABLES:
1519 1520
        net_store_data(&packet2,(uint32) cached_tables());
        break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1521
      case SHOW_CHAR_PTR:
1522 1523 1524 1525 1526
      {
	value= *(char**) value;
	net_store_data(&packet2,convert, value ? value : "");
	break;
      }
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1527
#ifdef HAVE_OPENSSL
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1528
	/* First group - functions relying on CTX */
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1529 1530
      case SHOW_SSL_CTX_SESS_ACCEPT:
	net_store_data(&packet2,(uint32) 
1531 1532
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context_)));
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1533 1534 1535
        break;
      case SHOW_SSL_CTX_SESS_ACCEPT_GOOD:
	net_store_data(&packet2,(uint32) 
1536 1537
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context_)));
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1538
        break;
1539 1540
      case SHOW_SSL_CTX_SESS_CONNECT_GOOD:
	net_store_data(&packet2,(uint32) 
1541 1542
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context_)));
1543
        break;
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1544 1545
      case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE:
	net_store_data(&packet2,(uint32) 
1546 1547
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context_)));
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1548
        break;
1549 1550
      case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE:
	net_store_data(&packet2,(uint32) 
1551 1552
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context_)));
1553
        break;
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1554 1555
      case SHOW_SSL_CTX_SESS_CB_HITS:
	net_store_data(&packet2,(uint32) 
1556 1557
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context_)));
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1558
        break;
1559 1560
      case SHOW_SSL_CTX_SESS_HITS:
	net_store_data(&packet2,(uint32) 
1561 1562
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context_)));
1563 1564 1565
        break;
      case SHOW_SSL_CTX_SESS_CACHE_FULL:
	net_store_data(&packet2,(uint32) 
1566 1567
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context_)));
1568 1569 1570
        break;
      case SHOW_SSL_CTX_SESS_MISSES:
	net_store_data(&packet2,(uint32) 
1571 1572
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context_)));
1573 1574 1575
        break;
      case SHOW_SSL_CTX_SESS_TIMEOUTS:
	net_store_data(&packet2,(uint32) 
1576 1577
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context_)));
1578
        break;
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1579 1580
      case SHOW_SSL_CTX_SESS_NUMBER:
	net_store_data(&packet2,(uint32) 
1581 1582
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context_)));
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1583
        break;
1584 1585
      case SHOW_SSL_CTX_SESS_CONNECT:
	net_store_data(&packet2,(uint32) 
1586 1587
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context_)));
1588
        break;
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1589 1590
      case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE:
	net_store_data(&packet2,(uint32) 
1591 1592
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context_)));
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1593 1594 1595
        break;
      case SHOW_SSL_CTX_GET_VERIFY_MODE:
	net_store_data(&packet2,(uint32) 
1596 1597
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context_)));
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1598 1599 1600
        break;
      case SHOW_SSL_CTX_GET_VERIFY_DEPTH:
	net_store_data(&packet2,(uint32) 
1601 1602
		       (!ssl_acceptor_fd ? 0 :
			SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context_)));
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1603 1604
        break;
      case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE:
1605 1606 1607 1608 1609
	if (!ssl_acceptor_fd)
	{
	  net_store_data(&packet2,"NONE" );
	  break;
	}
1610
	switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context_))
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
	{
          case SSL_SESS_CACHE_OFF:
            net_store_data(&packet2,"OFF" );
	    break;
          case SSL_SESS_CACHE_CLIENT:
            net_store_data(&packet2,"CLIENT" );
	    break;
          case SSL_SESS_CACHE_SERVER:
            net_store_data(&packet2,"SERVER" );
	    break;
          case SSL_SESS_CACHE_BOTH:
            net_store_data(&packet2,"BOTH" );
	    break;
          case SSL_SESS_CACHE_NO_AUTO_CLEAR:
            net_store_data(&packet2,"NO_AUTO_CLEAR" );
	    break;
          case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
            net_store_data(&packet2,"NO_INTERNAL_LOOKUP" );
	    break;
	  default:
            net_store_data(&packet2,"Unknown");
	    break;
	}
        break;
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656
	/* First group - functions relying on SSL */
      case SHOW_SSL_GET_VERSION:
	net_store_data(&packet2, thd->net.vio->ssl_ ? 
			SSL_get_version(thd->net.vio->ssl_) : "");
        break;
      case SHOW_SSL_SESSION_REUSED:
	net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ? 
			SSL_session_reused(thd->net.vio->ssl_) : 0));
        break;
      case SHOW_SSL_GET_DEFAULT_TIMEOUT:
	net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
			SSL_get_default_timeout(thd->net.vio->ssl_):0));
        break;
      case SHOW_SSL_GET_VERIFY_MODE:
	net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
			SSL_get_verify_mode(thd->net.vio->ssl_):0));
        break;
      case SHOW_SSL_GET_VERIFY_DEPTH:
	net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
			SSL_get_verify_depth(thd->net.vio->ssl_):0));
        break;
      case SHOW_SSL_GET_CIPHER:
1657 1658 1659
	net_store_data(&packet2, thd->net.vio->ssl_ ?
		       SSL_get_cipher(thd->net.vio->ssl_) : "");
	break;
1660
      case SHOW_SSL_GET_CIPHER_LIST:
1661
	if (thd->net.vio->ssl_)
1662
	{
1663 1664 1665
	  char buf[1024], *pos;
	  pos=buf;
	  for (int i=0 ; i++ ;)
1666 1667 1668 1669
	  {
	    const char *p=SSL_get_cipher_list(thd->net.vio->ssl_,i);
	    if (p == NULL) 
	      break;
1670 1671
	    pos=strmov(pos, p);
	    *pos++= ':';
1672
	  }
1673 1674 1675
	  if (pos != buf)
	    pos--;				// Remove last ':'
	  *pos=0;
1676
 	  net_store_data(&packet2, buf);
1677 1678
        }
	else
1679
 	  net_store_data(&packet2, "");
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1680
        break;
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1681 1682

#endif /* HAVE_OPENSSL */
1683 1684 1685 1686
      case SHOW_UNDEF:				// Show never happen
      case SHOW_SYS:
	net_store_data(&packet2, "");		// Safety
	break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1687 1688
      }
      if (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length()))
1689
        goto err;                               /* purecov: inspected */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1690 1691 1692
    }
  }
  pthread_mutex_unlock(&LOCK_status);
1693
  /* pthread_mutex_unlock(&THR_LOCK_keycache); */
1694
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1695 1696 1697 1698
  DBUG_RETURN(0);

 err:
  pthread_mutex_unlock(&LOCK_status);
1699
  /* pthread_mutex_unlock(&THR_LOCK_keycache); */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1700 1701 1702 1703
  DBUG_RETURN(1);
}

#ifdef __GNUC__
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
1704
template class List_iterator_fast<char>;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1705 1706
template class List<char>;
#endif