sql_show.cc 56.6 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
/* extern "C" pthread_mutex_t THR_LOCK_keycache; */
unknown's avatar
unknown 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};
unknown's avatar
unknown 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);
unknown's avatar
unknown 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);
unknown's avatar
unknown committed
48

unknown's avatar
unknown committed
49 50
extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd;

unknown's avatar
unknown committed
51 52 53 54
/****************************************************************************
** Send list of databases
** A database is a directory in the mysql_data_home directory
****************************************************************************/
unknown's avatar
SCRUM  
unknown committed
55

unknown's avatar
unknown committed
56 57 58
int
mysqld_show_dbs(THD *thd,const char *wild)
{
unknown's avatar
unknown committed
59
  Item_string *field=new Item_string("",0,thd->charset());
unknown's avatar
unknown committed
60 61 62 63
  List<Item> field_list;
  char *end;
  List<char> files;
  char *file_name;
unknown's avatar
unknown committed
64
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
65 66
  DBUG_ENTER("mysqld_show_dbs");

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

unknown's avatar
unknown committed
74
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
75 76 77
    DBUG_RETURN(1);
  if (mysql_find_files(thd,&files,NullS,mysql_data_home,wild,1))
    DBUG_RETURN(1);
unknown's avatar
unknown committed
78
  List_iterator_fast<char> it(files);
79

unknown's avatar
unknown committed
80 81
  while ((file_name=it++))
  {
unknown's avatar
unknown committed
82
    if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
83 84 85
	acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
		thd->priv_user, file_name) ||
	(grant_option && !check_grant_db(thd, file_name)))
unknown's avatar
unknown committed
86
    {
unknown's avatar
unknown committed
87
      protocol->prepare_for_resend();
88
      protocol->store(file_name, system_charset_info);
unknown's avatar
unknown committed
89
      if (protocol->write())
90 91
	DBUG_RETURN(-1);
    }
unknown's avatar
unknown committed
92
  }
93
  send_eof(thd);
unknown's avatar
unknown committed
94 95 96
  DBUG_RETURN(0);
}

97

98
/***************************************************************************
99
  List all open tables in a database
100 101
***************************************************************************/

102
int mysqld_show_open_tables(THD *thd,const char *wild)
103 104
{
  List<Item> field_list;
105
  OPEN_TABLE_LIST *open_list;
unknown's avatar
unknown committed
106
  Protocol *protocol= thd->protocol;
107 108
  DBUG_ENTER("mysqld_show_open_tables");

109 110
  field_list.push_back(new Item_empty_string("Database",NAME_LEN));
  field_list.push_back(new Item_empty_string("Table",NAME_LEN));
unknown's avatar
unknown committed
111 112
  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));
113

unknown's avatar
unknown committed
114
  if (protocol->send_fields(&field_list,1))
115
    DBUG_RETURN(1);
116

117
  if (!(open_list=list_open_tables(thd,wild)) && thd->is_fatal_error)
118 119
    DBUG_RETURN(-1);

120
  for (; open_list ; open_list=open_list->next)
121
  {
unknown's avatar
unknown committed
122
    protocol->prepare_for_resend();
123 124
    protocol->store(open_list->db, system_charset_info);
    protocol->store(open_list->table, system_charset_info);
unknown's avatar
unknown committed
125 126 127
    protocol->store_tiny((longlong) open_list->in_use);
    protocol->store_tiny((longlong) open_list->locked);
    if (protocol->write())
128
    {
129
      DBUG_RETURN(-1);
130
    }
131
  }
132
  send_eof(thd);
133 134 135
  DBUG_RETURN(0);
}

136

unknown's avatar
unknown committed
137 138 139 140 141 142 143
/***************************************************************************
** 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
144
  Item_string *field=new Item_string("",0,thd->charset());
unknown's avatar
unknown committed
145 146 147 148
  List<Item> field_list;
  char path[FN_LEN],*end;
  List<char> files;
  char *file_name;
unknown's avatar
unknown committed
149
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
150 151
  DBUG_ENTER("mysqld_show_tables");

unknown's avatar
unknown committed
152 153
  field->name=(char*) thd->alloc(20+(uint) strlen(db)+
				 (wild ? (uint) strlen(wild)+4:0));
unknown's avatar
unknown committed
154 155 156 157 158 159 160
  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);
unknown's avatar
unknown committed
161
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
162 163 164
    DBUG_RETURN(1);
  if (mysql_find_files(thd,&files,db,path,wild,0))
    DBUG_RETURN(-1);
unknown's avatar
unknown committed
165
  List_iterator_fast<char> it(files);
unknown's avatar
unknown committed
166 167
  while ((file_name=it++))
  {
unknown's avatar
unknown committed
168
    protocol->prepare_for_resend();
169
    protocol->store(file_name, system_charset_info);
unknown's avatar
unknown committed
170
    if (protocol->write())
unknown's avatar
unknown committed
171 172
      DBUG_RETURN(-1);
  }
173
  send_eof(thd);
unknown's avatar
unknown committed
174 175 176
  DBUG_RETURN(0);
}

unknown's avatar
unknown committed
177 178 179 180
/***************************************************************************
** List all table types supported 
***************************************************************************/

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

207

unknown's avatar
unknown committed
208 209 210
int mysqld_show_table_types(THD *thd)
{
  List<Item> field_list;
unknown's avatar
unknown committed
211
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
212 213 214 215
  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));
216
  field_list.push_back(new Item_empty_string("Comment",80));
unknown's avatar
unknown committed
217

unknown's avatar
unknown committed
218
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
219 220
    DBUG_RETURN(1);

unknown's avatar
unknown committed
221 222
  const char *default_type_name=
    ha_table_typelib.type_names[thd->variables.table_type];
unknown's avatar
unknown committed
223

224 225
  show_table_type_st *types;
  for (types= sys_table_types; types->type; types++)
unknown's avatar
unknown committed
226
  {
unknown's avatar
unknown committed
227
    protocol->prepare_for_resend();
228
    protocol->store(types->type, system_charset_info);
229 230 231
    const char *option_name= show_comp_option_name[(int) *types->value];

    if (*types->value == SHOW_OPTION_YES &&
232
	!my_strcasecmp(system_charset_info, default_type_name, types->type))
233
      option_name= "DEFAULT";
234 235
    protocol->store(option_name, system_charset_info);
    protocol->store(types->comment, system_charset_info);
unknown's avatar
unknown committed
236
    if (protocol->write())
unknown's avatar
unknown committed
237 238
      DBUG_RETURN(-1);
  }
239
  send_eof(thd);
unknown's avatar
unknown committed
240 241 242
  DBUG_RETURN(0);
}

243

unknown's avatar
unknown committed
244
/***************************************************************************
245
 List all privileges supported
unknown's avatar
unknown committed
246 247
***************************************************************************/

248 249 250 251
struct show_privileges_st {
  const char *privilege;
  const char *context;
  const char *comment;
unknown's avatar
unknown committed
252 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

/*
  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
278 279 280
int mysqld_show_privileges(THD *thd)
{
  List<Item> field_list;
unknown's avatar
unknown committed
281
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
282 283 284 285 286 287
  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));

unknown's avatar
unknown committed
288
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
289 290
    DBUG_RETURN(1);

291 292
  show_privileges_st *privilege= sys_privileges;
  for (privilege= sys_privileges; privilege->privilege ; privilege++)
unknown's avatar
unknown committed
293
  {
unknown's avatar
unknown committed
294
    protocol->prepare_for_resend();
295 296 297
    protocol->store(privilege->privilege, system_charset_info);
    protocol->store(privilege->context, system_charset_info);
    protocol->store(privilege->comment, system_charset_info);
unknown's avatar
unknown committed
298
    if (protocol->write())
unknown's avatar
unknown committed
299 300
      DBUG_RETURN(-1);
  }
301
  send_eof(thd);
unknown's avatar
unknown committed
302 303 304 305 306
  DBUG_RETURN(0);
}


/***************************************************************************
307
  List all column types
unknown's avatar
unknown committed
308 309
***************************************************************************/

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

/* TODO: Add remaning types */

static struct show_column_type_st sys_column_types[]=
{
unknown's avatar
unknown committed
332 333 334 335 336 337 338 339 340 341 342 343 344
  {"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;
unknown's avatar
unknown committed
345
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
346 347 348 349 350 351
  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));
unknown's avatar
unknown committed
352 353
  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
354 355 356 357 358 359 360 361 362
  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));

unknown's avatar
unknown committed
363
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
364 365
    DBUG_RETURN(1);

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


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

404 405
  if (wild && !wild[0])
    wild=0;
unknown's avatar
unknown committed
406 407 408 409 410
  bzero((char*) &table_list,sizeof(table_list));

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

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

466

unknown's avatar
unknown committed
467
/***************************************************************************
468
 Extended version of mysqld_show_tables
unknown's avatar
unknown committed
469 470 471 472 473 474 475 476 477 478
***************************************************************************/

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;
unknown's avatar
unknown committed
479 480
  Protocol *protocol= thd->protocol;
  TIME time;
unknown's avatar
unknown committed
481 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
  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;
510 511
  field_list.push_back(item=new Item_empty_string("Charset",32));
  item->maybe_null=1;
unknown's avatar
unknown committed
512 513 514
  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));
515
  item->maybe_null=1;
unknown's avatar
unknown committed
516
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
517 518 519 520
    DBUG_RETURN(1);

  if (mysql_find_files(thd,&files,db,path,wild,0))
    DBUG_RETURN(-1);
unknown's avatar
unknown committed
521
  List_iterator_fast<char> it(files);
unknown's avatar
unknown committed
522 523 524 525
  while ((file_name=it++))
  {
    TABLE_LIST table_list;
    bzero((char*) &table_list,sizeof(table_list));
unknown's avatar
unknown committed
526
    protocol->prepare_for_resend();
527
    protocol->store(file_name, system_charset_info);
unknown's avatar
unknown committed
528
    table_list.db=(char*) db;
529
    table_list.real_name= table_list.alias= file_name;
530
    if (lower_case_table_names)
531
      my_casedn_str(files_charset_info, file_name);
unknown's avatar
unknown committed
532 533
    if (!(table = open_ltable(thd, &table_list, TL_READ)))
    {
534
      for (uint i=2 ; i < field_list.elements ; i++)
unknown's avatar
unknown committed
535
        protocol->store_null();
536
      // Send error to Comment field
537
      protocol->store(thd->net.last_error, system_charset_info);
unknown's avatar
unknown committed
538 539 540 541 542
      thd->net.last_error[0]=0;
    }
    else
    {
      struct tm tm_tmp;
unknown's avatar
unknown committed
543
      const char *str;
unknown's avatar
unknown committed
544 545
      handler *file=table->file;
      file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK);
546
      protocol->store(file->table_type(), system_charset_info);
unknown's avatar
unknown committed
547 548 549 550
      str= ((table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ?
	    "Compressed" :
	    (table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
	    "Dynamic" : "Fixed");
551
      protocol->store(str, system_charset_info);
unknown's avatar
unknown committed
552 553 554
      protocol->store((ulonglong) file->records);
      protocol->store((ulonglong) file->mean_rec_length);
      protocol->store((ulonglong) file->data_file_length);
unknown's avatar
unknown committed
555
      if (file->max_data_file_length)
unknown's avatar
unknown committed
556
        protocol->store((ulonglong) file->max_data_file_length);
unknown's avatar
unknown committed
557
      else
unknown's avatar
unknown committed
558 559 560
        protocol->store_null();
      protocol->store((ulonglong) file->index_file_length);
      protocol->store((ulonglong) file->delete_length);
unknown's avatar
unknown committed
561 562
      if (table->found_next_number_field)
      {
563 564 565
        table->next_number_field=table->found_next_number_field;
        table->next_number_field->reset();
        file->update_auto_increment();
unknown's avatar
unknown committed
566
        protocol->store(table->next_number_field->val_int());
567
        table->next_number_field=0;
unknown's avatar
unknown committed
568 569
      }
      else
unknown's avatar
unknown committed
570
        protocol->store_null();
unknown's avatar
unknown committed
571
      if (!file->create_time)
unknown's avatar
unknown committed
572
        protocol->store_null();
unknown's avatar
unknown committed
573 574
      else
      {
575
        localtime_r(&file->create_time,&tm_tmp);
unknown's avatar
unknown committed
576 577
	localtime_to_TIME(&time, &tm_tmp);
        protocol->store(&time);
unknown's avatar
unknown committed
578 579
      }
      if (!file->update_time)
unknown's avatar
unknown committed
580
        protocol->store_null();
unknown's avatar
unknown committed
581 582
      else
      {
583
        localtime_r(&file->update_time,&tm_tmp);
unknown's avatar
unknown committed
584 585
	localtime_to_TIME(&time, &tm_tmp);
        protocol->store(&time);
unknown's avatar
unknown committed
586 587
      }
      if (!file->check_time)
unknown's avatar
unknown committed
588
        protocol->store_null();
unknown's avatar
unknown committed
589 590
      else
      {
591
        localtime_r(&file->check_time,&tm_tmp);
unknown's avatar
unknown committed
592 593
	localtime_to_TIME(&time, &tm_tmp);
        protocol->store(&time);
unknown's avatar
unknown committed
594
      }
unknown's avatar
unknown committed
595
      str= (table->table_charset ? table->table_charset->name : "default");
596
      protocol->store(str, system_charset_info);
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);
        }
unknown's avatar
unknown committed
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);
    }
unknown's avatar
unknown committed
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);
}


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

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

unknown's avatar
unknown committed
718
	protocol->prepare_for_resend();
719
        protocol->store(field->field_name, system_charset_info);
720
        field->sql_type(type);
721 722
        protocol->store(type.ptr(), type.length(), system_charset_info);
	protocol->store(field->charset()->name, system_charset_info);
723 724 725 726

        pos=(byte*) ((flags & NOT_NULL_FLAG) &&
                     field->type() != FIELD_TYPE_TIMESTAMP ?
                     "" : "YES");
727
        protocol->store((const char*) pos, system_charset_info);
728 729 730
        pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
                     (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
                     (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
731
        protocol->store((char*) pos, system_charset_info);
732 733 734 735 736 737

        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
738
          type.set(tmp,sizeof(tmp),system_charset_info);
739
          field->val_str(&type,&type);
740
          protocol->store(type.ptr(),type.length(),type.charset());
741 742
        }
        else if (field->maybe_null() || null_default_value)
unknown's avatar
unknown committed
743
          protocol->store_null();                       // Null as default
744
        else
745
          protocol->store("",0, system_charset_info);	// empty string
746 747 748 749

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

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

779

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

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

  List<Item> field_list;
  field_list.push_back(new Item_empty_string("Table",NAME_LEN));
unknown's avatar
unknown committed
800
  field_list.push_back(new Item_empty_string("Create Table", MAX_BLOB_WIDTH));
unknown's avatar
unknown committed
801

unknown's avatar
unknown committed
802 803 804
  if (protocol->send_fields(&field_list, 1))
    DBUG_RETURN(1);
  protocol->prepare_for_resend();
805
  protocol->store(table->table_name, system_charset_info);
806
  buffer.length(0);
unknown's avatar
unknown committed
807 808
  if (store_create_info(thd, table, &buffer))
    DBUG_RETURN(-1);
809
  protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
unknown's avatar
unknown committed
810
  if (protocol->write())
unknown's avatar
unknown committed
811
    DBUG_RETURN(1);
812
  send_eof(thd);
unknown's avatar
unknown committed
813 814 815 816
  DBUG_RETURN(0);
}


unknown's avatar
unknown committed
817 818 819
int
mysqld_show_logs(THD *thd)
{
unknown's avatar
unknown committed
820 821
  List<Item> field_list;
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
822 823 824 825 826 827
  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));

unknown's avatar
unknown committed
828
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
829 830
    DBUG_RETURN(1);

831
#ifdef HAVE_BERKELEY_DB
unknown's avatar
unknown committed
832
  if (!berkeley_skip && berkeley_show_logs(protocol))
unknown's avatar
unknown committed
833
    DBUG_RETURN(-1);
834
#endif
unknown's avatar
unknown committed
835

836
  send_eof(thd);
unknown's avatar
unknown committed
837 838 839 840
  DBUG_RETURN(0);
}


unknown's avatar
unknown committed
841 842 843 844
int
mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
{
  TABLE *table;
unknown's avatar
unknown committed
845
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
846 847
  DBUG_ENTER("mysqld_show_keys");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
848
                      table_list->real_name));
unknown's avatar
unknown committed
849 850 851

  if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  {
852
    send_error(thd);
unknown's avatar
unknown committed
853 854 855 856 857 858
    DBUG_RETURN(1);
  }

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

unknown's avatar
unknown committed
877
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
878 879
    DBUG_RETURN(1);

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

      /* Check if we have a key part that only uses part of the field */
unknown's avatar
unknown committed
912
      if (!key_part->field ||
913 914
          key_part->length !=
          table->field[key_part->fieldnr-1]->key_length())
unknown's avatar
unknown committed
915
        protocol->store_tiny((longlong) key_part->length);
unknown's avatar
unknown committed
916
      else
unknown's avatar
unknown committed
917 918
        protocol->store_null();
      protocol->store_null();                   // No pack_information yet
919 920 921

      /* Null flag */
      uint flags= key_part->field ? key_part->field->flags : 0;
unknown's avatar
unknown committed
922
      char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
923 924
      protocol->store((const char*) pos, system_charset_info);
      protocol->store(table->file->index_type(i), system_charset_info);
925
      /* Comment */
unknown's avatar
unknown committed
926
      protocol->store("", system_charset_info);
unknown's avatar
unknown committed
927
      if (protocol->write())
928
        DBUG_RETURN(1); /* purecov: inspected */
unknown's avatar
unknown committed
929 930
    }
  }
931
  send_eof(thd);
unknown's avatar
unknown committed
932 933 934 935 936
  DBUG_RETURN(0);
}


/****************************************************************************
937 938
  Return only fields for API mysql_list_fields
  Use "show table wildcard" in mysql instead of this
unknown's avatar
unknown committed
939 940 941 942 943 944 945 946 947 948 949
****************************************************************************/

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)))
  {
950
    send_error(thd);
unknown's avatar
unknown committed
951 952 953 954 955 956 957
    DBUG_VOID_RETURN;
  }
  List<Item> field_list;

  Field **ptr,*field;
  for (ptr=table->field ; (field= *ptr); ptr++)
  {
958 959
    if (!wild || !wild[0] || 
        !wild_case_compare(system_charset_info, field->field_name,wild))
unknown's avatar
unknown committed
960 961
      field_list.push_back(new Item_field(field));
  }
unknown's avatar
unknown committed
962
  restore_record(table,default_values);              // Get empty record
unknown's avatar
unknown committed
963
  if (thd->protocol->send_fields(&field_list,2))
unknown's avatar
unknown committed
964
    DBUG_VOID_RETURN;
965
  net_flush(&thd->net);
unknown's avatar
unknown committed
966 967 968
  DBUG_VOID_RETURN;
}

969

unknown's avatar
unknown committed
970 971 972
int
mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
{
unknown's avatar
unknown committed
973 974
  Protocol *protocol= thd->protocol;
  String *packet= protocol->storage_packet();
unknown's avatar
unknown committed
975 976
  DBUG_ENTER("mysqld_dump_create_info");
  DBUG_PRINT("enter",("table: %s",table->real_name));
977

unknown's avatar
unknown committed
978 979
  protocol->prepare_for_resend();
  if (store_create_info(thd, table, packet))
unknown's avatar
unknown committed
980
    DBUG_RETURN(-1);
981

unknown's avatar
unknown committed
982 983
  //if (protocol->convert)
  //  protocol->convert->convert((char*) packet->ptr(), packet->length());
984
  if (fd < 0)
985
  {
unknown's avatar
unknown committed
986
    if (protocol->write())
987
      DBUG_RETURN(-1);
988
    net_flush(&thd->net);
989
  }
unknown's avatar
unknown committed
990
  else
991
  {
992 993
    if (my_write(fd, (const byte*) packet->ptr(), packet->length(),
		 MYF(MY_WME)))
994 995
      DBUG_RETURN(-1);
  }
unknown's avatar
unknown committed
996 997
  DBUG_RETURN(0);
}
998

999

1000 1001 1002
static void
append_identifier(THD *thd, String *packet, const char *name)
{
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
  char qtype;
  if ((thd->variables.sql_mode & MODE_ANSI_QUOTES) ||
      (thd->variables.sql_mode & MODE_POSTGRESQL) ||
      (thd->variables.sql_mode & MODE_ORACLE) ||
      (thd->variables.sql_mode & MODE_MSSQL) ||
      (thd->variables.sql_mode & MODE_DB2) ||
      (thd->variables.sql_mode & MODE_SAPDB))
    qtype= '\"';
  else
    qtype= '`';

1014 1015
  if (thd->options & OPTION_QUOTE_SHOW_CREATE)
  {
1016
    packet->append(&qtype, 1);
1017
    packet->append(name, 0, system_charset_info);
1018
    packet->append(&qtype, 1);
1019 1020 1021
  }
  else
  {
1022
    packet->append(name, 0, system_charset_info);
1023 1024 1025
  }
}

unknown's avatar
unknown committed
1026
#define LIST_PROCESS_HOST_LEN 64
1027

unknown's avatar
unknown committed
1028
static int
1029
store_create_info(THD *thd, TABLE *table, String *packet)
unknown's avatar
unknown committed
1030
{
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
  my_bool foreign_db_mode=    ((thd->variables.sql_mode & MODE_POSTGRESQL) ||
			       (thd->variables.sql_mode & MODE_ORACLE) ||
			       (thd->variables.sql_mode & MODE_MSSQL) ||
			       (thd->variables.sql_mode & MODE_DB2) ||
			       (thd->variables.sql_mode & MODE_SAPDB));
  my_bool limited_mysql_mode= ((thd->variables.sql_mode & 
				MODE_NO_FIELD_OPTIONS) ||
			       (thd->variables.sql_mode & MODE_MYSQL323) ||
			       (thd->variables.sql_mode & MODE_MYSQL40));

unknown's avatar
unknown committed
1041 1042 1043
  DBUG_ENTER("store_create_info");
  DBUG_PRINT("enter",("table: %s",table->real_name));

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

unknown's avatar
unknown committed
1046 1047
  List<Item> field_list;
  char tmp[MAX_FIELD_WIDTH];
unknown's avatar
unknown committed
1048
  String type(tmp, sizeof(tmp),&my_charset_bin);
1049 1050 1051 1052
  if (table->tmp_table)
    packet->append("CREATE TEMPORARY TABLE ", 23);
  else
    packet->append("CREATE TABLE ", 13);
1053
  append_identifier(thd,packet,table->real_name);
1054
  packet->append(" (\n", 3);
1055

unknown's avatar
unknown committed
1056 1057 1058
  Field **ptr,*field;
  for (ptr=table->field ; (field= *ptr); ptr++)
  {
1059
    if (ptr != table->field)
1060
      packet->append(",\n", 2);
1061

unknown's avatar
unknown committed
1062
    uint flags = field->flags;
1063
    packet->append("  ", 2);
1064
    append_identifier(thd,packet,field->field_name);
unknown's avatar
unknown committed
1065 1066
    packet->append(' ');
    // check for surprises from the previous call to Field::sql_type()
1067
    if (type.ptr() != tmp)
unknown's avatar
unknown committed
1068
      type.set(tmp, sizeof(tmp),&my_charset_bin);
1069

unknown's avatar
unknown committed
1070 1071
    field->sql_type(type);
    packet->append(type.ptr(),type.length());
1072

1073
    bool has_default = (field->type() != FIELD_TYPE_BLOB &&
unknown's avatar
unknown committed
1074 1075
			field->type() != FIELD_TYPE_TIMESTAMP &&
			field->unireg_check != Field::NEXT_NUMBER);
1076 1077 1078 1079 1080
    
    /* 
      For string types dump collation name only if 
      collation is not primary for the given charset
    */
1081
    if (!(field->charset()->state & MY_CS_PRIMARY) &&
1082
	!limited_mysql_mode && !foreign_db_mode)
1083
    {
1084
      packet->append(" collate ", 9);
1085 1086
      packet->append(field->charset()->name);
    }
unknown's avatar
unknown committed
1087 1088
    if (flags & NOT_NULL_FLAG)
      packet->append(" NOT NULL", 9);
1089

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

1108
    if (field->unireg_check == Field::NEXT_NUMBER && !foreign_db_mode)
1109 1110 1111 1112 1113 1114 1115
      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
1116 1117 1118 1119 1120
  }

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

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

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

1141
    if (!found_primary)
1142
     append_identifier(thd, packet, key_info->name);
unknown's avatar
unknown committed
1143

1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
    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);
    }
1156
    packet->append(" (", 2);
1157

unknown's avatar
unknown committed
1158 1159
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
    {
1160
      if (j)
1161
        packet->append(',');
1162

1163
      if (key_part->field)
1164
        append_identifier(thd,packet,key_part->field->field_name);
unknown's avatar
unknown committed
1165
      if (!key_part->field ||
1166 1167 1168
          (key_part->length !=
           table->field[key_part->fieldnr-1]->key_length() &&
           !(key_info->flags & HA_FULLTEXT)))
unknown's avatar
unknown committed
1169
      {
1170 1171 1172 1173 1174
        char buff[64];
        buff[0] = '(';
        char* end=int10_to_str((long) key_part->length, buff + 1,10);
        *end++ = ')';
        packet->append(buff,(uint) (end-buff));
unknown's avatar
unknown committed
1175 1176 1177 1178
      }
    }
    packet->append(')');
  }
1179

unknown's avatar
unknown committed
1180
  handler *file = table->file;
unknown's avatar
unknown committed
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193

  /* 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);
1194
  if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
1195
  {
1196 1197 1198 1199 1200
    packet->append(" TYPE=", 6);
    packet->append(file->table_type());
    char buff[128];
    char* p;
    
1201 1202 1203
    if (table->table_charset &&
	!(thd->variables.sql_mode & MODE_MYSQL323) &&
	!(thd->variables.sql_mode & MODE_MYSQL40))
1204
    {
1205 1206 1207 1208 1209 1210 1211
      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);
      }
1212
    }
1213

1214 1215 1216 1217 1218 1219
    if (table->min_rows)
    {
      packet->append(" MIN_ROWS=");
      p = longlong10_to_str(table->min_rows, buff, 10);
      packet->append(buff, (uint) (p - buff));
    }
unknown's avatar
unknown committed
1220

1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
    if (table->max_rows)
    {
      packet->append(" MAX_ROWS=");
      p = longlong10_to_str(table->max_rows, buff, 10);
      packet->append(buff, (uint) (p - buff));
    }
    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));
    }
1233

1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259
    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)
    {
      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);
    }
1260
  }
unknown's avatar
unknown committed
1261 1262 1263 1264 1265
  DBUG_RETURN(0);
}


/****************************************************************************
1266 1267
  Return info about all processes
  returns for each thread: thread id, user, host, db, command, info
unknown's avatar
unknown committed
1268 1269 1270 1271
****************************************************************************/

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

unknown's avatar
unknown committed
1276 1277
  ulong thread_id;
  time_t start_time;
1278
  uint   command;
unknown's avatar
unknown committed
1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291
  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
1292 1293
  ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
			   PROCESS_LIST_WIDTH);
unknown's avatar
unknown committed
1294
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
1295 1296
  DBUG_ENTER("mysqld_list_processes");

unknown's avatar
unknown committed
1297
  field_list.push_back(new Item_int("Id",0,11));
unknown's avatar
unknown committed
1298
  field_list.push_back(new Item_empty_string("User",16));
1299
  field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
unknown's avatar
unknown committed
1300 1301 1302
  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));
unknown's avatar
unknown committed
1303
  field_list.push_back(new Item_return_int("Time",7, FIELD_TYPE_LONG));
unknown's avatar
unknown committed
1304 1305 1306 1307
  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;
unknown's avatar
unknown committed
1308
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
1309 1310 1311 1312 1313 1314 1315 1316 1317
    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++))
    {
1318
      struct st_my_thread_var *mysys_var;
unknown's avatar
SCRUM  
unknown committed
1319
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
1320
      if ((tmp->net.vio || tmp->system_thread) &&
1321
          (!user || (tmp->user && !strcmp(tmp->user,user))))
unknown's avatar
SCRUM  
unknown committed
1322 1323 1324 1325
#else
      if (tmp->system_thread &&
          (!user || (tmp->user && !strcmp(tmp->user,user))))
#endif
unknown's avatar
unknown committed
1326
      {
1327 1328 1329
        thread_info *thd_info=new thread_info;

        thd_info->thread_id=tmp->thread_id;
1330 1331 1332
        thd_info->user=thd->strdup(tmp->user ? tmp->user :
				   (tmp->system_thread ?
				    "system user" : "unauthenticated user"));
1333
	if (tmp->peer_port && (tmp->host || tmp->ip) && thd->host_or_ip[0])
1334 1335
	{
	  if ((thd_info->host= thd->alloc(LIST_PROCESS_HOST_LEN+1)))
unknown's avatar
unknown committed
1336
	    my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN,
1337
			"%s:%u", tmp->host_or_ip, tmp->peer_port);
1338 1339
	}
	else
1340
	  thd_info->host= thd->strdup(tmp->host_or_ip);
1341 1342 1343
        if ((thd_info->db=tmp->db))             // Safe test
          thd_info->db=thd->strdup(thd_info->db);
        thd_info->command=(int) tmp->command;
1344 1345
        if ((mysys_var= tmp->mysys_var))
          pthread_mutex_lock(&mysys_var->mutex);
1346
        thd_info->proc_info= (char*) (tmp->killed ? "Killed" : 0);
unknown's avatar
SCRUM  
unknown committed
1347
#ifndef EMBEDDED_LIBRARY
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
        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
1358 1359 1360
#else
        thd_info->state_info= (char*)"Writing to net";
#endif
1361 1362
        if (mysys_var)
          pthread_mutex_unlock(&mysys_var->mutex);
unknown's avatar
unknown committed
1363 1364

#if !defined(DONT_USE_THR_ALARM) && ! defined(SCO)
1365 1366
        if (pthread_kill(tmp->real_id,0))
          tmp->proc_info="*** DEAD ***";        // This shouldn't happen
unknown's avatar
unknown committed
1367
#endif
unknown's avatar
unknown committed
1368 1369 1370
#ifdef EXTRA_DEBUG
        thd_info->start_time= tmp->time_after_lock;
#else
1371
        thd_info->start_time= tmp->start_time;
unknown's avatar
unknown committed
1372
#endif
1373 1374 1375
        thd_info->query=0;
        if (tmp->query)
        {
unknown's avatar
unknown committed
1376 1377
	  /* query_length is always set before tmp->query */
          uint length= min(max_query_length, tmp->query_length);
1378 1379 1380 1381
          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
1382 1383 1384 1385 1386 1387
      }
    }
  }
  VOID(pthread_mutex_unlock(&LOCK_thread_count));

  thread_info *thd_info;
unknown's avatar
unknown committed
1388
  time_t now= time(0);
unknown's avatar
unknown committed
1389 1390
  while ((thd_info=thread_infos.get()))
  {
unknown's avatar
unknown committed
1391 1392
    protocol->prepare_for_resend();
    protocol->store((ulonglong) thd_info->thread_id);
1393 1394 1395
    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
1396
    if (thd_info->proc_info)
1397
      protocol->store(thd_info->proc_info, system_charset_info);
unknown's avatar
unknown committed
1398
    else
1399
      protocol->store(command_name[thd_info->command], system_charset_info);
unknown's avatar
unknown committed
1400
    if (thd_info->start_time)
unknown's avatar
unknown committed
1401
      protocol->store((uint32) (now - thd_info->start_time));
unknown's avatar
unknown committed
1402
    else
unknown's avatar
unknown committed
1403
      protocol->store_null();
1404 1405
    protocol->store(thd_info->state_info, system_charset_info);
    protocol->store(thd_info->query, system_charset_info);
unknown's avatar
unknown committed
1406
    if (protocol->write())
unknown's avatar
unknown committed
1407 1408
      break; /* purecov: inspected */
  }
1409
  send_eof(thd);
unknown's avatar
unknown committed
1410 1411 1412 1413
  DBUG_VOID_RETURN;
}

/*****************************************************************************
unknown's avatar
unknown committed
1414
  Status functions
unknown's avatar
unknown committed
1415 1416
*****************************************************************************/

1417 1418 1419 1420 1421 1422
static bool write_collation(Protocol *protocol, CHARSET_INFO *cs)
{
  protocol->prepare_for_resend();
  protocol->store(cs->csname, system_charset_info);
  protocol->store(cs->name, system_charset_info);
  protocol->store_short((longlong) cs->number);
1423 1424
  protocol->store((cs->state & MY_CS_PRIMARY) ? "Y" : "",system_charset_info);
  protocol->store((cs->state & MY_CS_COMPILED)? "Y" : "",system_charset_info);
1425 1426 1427 1428 1429
  protocol->store_short((longlong) cs->strxfrm_multiply);
  return protocol->write();
}

int mysqld_show_collations(THD *thd, const char *wild)
1430 1431
{
  char buff[8192];
unknown's avatar
unknown committed
1432
  String packet2(buff,sizeof(buff),thd->charset());
1433
  List<Item> field_list;
1434
  CHARSET_INFO **cs;
unknown's avatar
unknown committed
1435
  Protocol *protocol= thd->protocol;
1436 1437
  char flags[64];

1438 1439
  DBUG_ENTER("mysqld_show_charsets");

1440 1441
  field_list.push_back(new Item_empty_string("Charset",30));
  field_list.push_back(new Item_empty_string("Collation",30));
unknown's avatar
unknown committed
1442
  field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT));
1443 1444 1445
  field_list.push_back(new Item_empty_string("D",30));
  field_list.push_back(new Item_empty_string("C",30));
  field_list.push_back(new Item_return_int("Sortlen",3, FIELD_TYPE_SHORT));
1446

unknown's avatar
unknown committed
1447
  if (protocol->send_fields(&field_list, 1))
1448 1449
    DBUG_RETURN(1);

1450
  for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ )
1451
  {
1452 1453 1454 1455 1456 1457
    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
1458
	  wild_case_compare(system_charset_info,cl[0]->name,wild)))
1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474
      {
        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);
1475
  protocol->store(cs->comment ? cs->comment : "", system_charset_info);
1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492
  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;
  char flags[64];

  DBUG_ENTER("mysqld_show_charsets");

  field_list.push_back(new Item_empty_string("Charset",30));
1493
  field_list.push_back(new Item_empty_string("Description",60));
1494 1495 1496 1497 1498 1499 1500 1501 1502 1503
  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)))
1504
    {
1505
      if (write_charset(protocol, cs[0]))
unknown's avatar
unknown committed
1506
	goto err;
1507 1508
    }
  }
1509
  send_eof(thd); 
1510 1511 1512 1513 1514
  DBUG_RETURN(0);
err:
  DBUG_RETURN(1);
}

unknown's avatar
unknown committed
1515
  
unknown's avatar
unknown committed
1516

1517
int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
unknown's avatar
unknown committed
1518
		enum enum_var_type value_type)
unknown's avatar
unknown committed
1519
{
unknown's avatar
unknown committed
1520
  char buff[1024];
unknown's avatar
unknown committed
1521
  List<Item> field_list;
unknown's avatar
unknown committed
1522
  Protocol *protocol= thd->protocol;
unknown's avatar
unknown committed
1523
  DBUG_ENTER("mysqld_show");
unknown's avatar
unknown committed
1524

unknown's avatar
unknown committed
1525 1526
  field_list.push_back(new Item_empty_string("Variable_name",30));
  field_list.push_back(new Item_empty_string("Value",256));
unknown's avatar
unknown committed
1527
  if (protocol->send_fields(&field_list,1))
unknown's avatar
unknown committed
1528 1529
    DBUG_RETURN(1); /* purecov: inspected */

unknown's avatar
unknown committed
1530
  /* pthread_mutex_lock(&THR_LOCK_keycache); */
unknown's avatar
unknown committed
1531
  pthread_mutex_lock(&LOCK_status);
unknown's avatar
unknown committed
1532
  for (; variables->name; variables++)
unknown's avatar
unknown committed
1533
  {
unknown's avatar
unknown committed
1534
    if (!(wild && wild[0] && wild_case_compare(system_charset_info,
1535
					       variables->name,wild)))
unknown's avatar
unknown committed
1536
    {
unknown's avatar
unknown committed
1537
      protocol->prepare_for_resend();
1538
      protocol->store(variables->name, system_charset_info);
unknown's avatar
unknown committed
1539 1540
      SHOW_TYPE show_type=variables->type;
      char *value=variables->value;
unknown's avatar
unknown committed
1541 1542 1543
      const char *pos, *end;
      long nr;

unknown's avatar
unknown committed
1544 1545 1546
      if (show_type == SHOW_SYS)
      {
	show_type= ((sys_var*) value)->type();
1547
	value=     (char*) ((sys_var*) value)->value_ptr(thd, value_type);
unknown's avatar
unknown committed
1548 1549
      }

unknown's avatar
unknown committed
1550
      pos= end= buff;
unknown's avatar
unknown committed
1551
      switch (show_type) {
unknown's avatar
unknown committed
1552 1553
      case SHOW_LONG:
      case SHOW_LONG_CONST:
unknown's avatar
unknown committed
1554
	end= int10_to_str(*(long*) value, buff, 10);
unknown's avatar
unknown committed
1555 1556
        break;
      case SHOW_LONGLONG:
unknown's avatar
unknown committed
1557
	end= longlong10_to_str(*(longlong*) value, buff, 10);
unknown's avatar
unknown committed
1558
	break;
1559
      case SHOW_HA_ROWS:
unknown's avatar
unknown committed
1560
        end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
1561
        break;
unknown's avatar
unknown committed
1562
      case SHOW_BOOL:
unknown's avatar
unknown committed
1563
	end= strmov(buff, *(bool*) value ? "ON" : "OFF");
1564
        break;
unknown's avatar
unknown committed
1565
      case SHOW_MY_BOOL:
unknown's avatar
unknown committed
1566
	end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
1567
        break;
unknown's avatar
unknown committed
1568 1569
      case SHOW_INT_CONST:
      case SHOW_INT:
unknown's avatar
unknown committed
1570
	end= int10_to_str((long) *(uint32*) value, buff, 10);
1571
        break;
1572 1573
      case SHOW_HAVE:
      {
unknown's avatar
unknown committed
1574
	SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
unknown's avatar
unknown committed
1575 1576
	pos= show_comp_option_name[(int) tmp];
	end= strend(pos);
1577 1578
        break;
      }
unknown's avatar
unknown committed
1579
      case SHOW_CHAR:
unknown's avatar
unknown committed
1580 1581
	pos= value;
	end= strend(pos);
1582
        break;
unknown's avatar
unknown committed
1583
      case SHOW_STARTTIME:
unknown's avatar
unknown committed
1584 1585
	nr= (long) (thd->query_start() - start_time);
	end= int10_to_str(nr, buff, 10);
1586
        break;
unknown's avatar
unknown committed
1587
      case SHOW_QUESTION:
unknown's avatar
unknown committed
1588
	end= int10_to_str((long) thd->query_id, buff, 10);
1589
        break;
1590
#ifndef EMBEDDED_LIBRARY
1591
      case SHOW_RPL_STATUS:
unknown's avatar
unknown committed
1592
	end= strmov(buff, rpl_status_type[(int)rpl_status]);
1593
	break;
1594 1595 1596
      case SHOW_SLAVE_RUNNING:
      {
	LOCK_ACTIVE_MI;
unknown's avatar
unknown committed
1597 1598
	end= strmov(buff, (active_mi->slave_running &&
			   active_mi->rli.slave_running) ? "ON" : "OFF");
1599 1600 1601
	UNLOCK_ACTIVE_MI;
	break;
      }
1602
#endif /* EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
1603
      case SHOW_OPENTABLES:
unknown's avatar
unknown committed
1604
	end= int10_to_str((long) cached_tables(), buff, 10);
1605
        break;
unknown's avatar
unknown committed
1606
      case SHOW_CHAR_PTR:
unknown's avatar
unknown committed
1607
      {
unknown's avatar
unknown committed
1608 1609 1610
	if (!(pos= *(char**) value))
	  pos= "";
	end= strend(pos);
unknown's avatar
unknown committed
1611 1612
	break;
      }
unknown's avatar
unknown committed
1613
#ifdef HAVE_OPENSSL
unknown's avatar
unknown committed
1614
	/* First group - functions relying on CTX */
unknown's avatar
unknown committed
1615
      case SHOW_SSL_CTX_SESS_ACCEPT:
unknown's avatar
unknown committed
1616 1617 1618 1619
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_accept(ssl_acceptor_fd->
						      ssl_context_)),
			  buff, 10);
unknown's avatar
unknown committed
1620 1621
        break;
      case SHOW_SSL_CTX_SESS_ACCEPT_GOOD:
unknown's avatar
unknown committed
1622 1623 1624 1625
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_accept_good(ssl_acceptor_fd->
							   ssl_context_)),
			  buff, 10);
unknown's avatar
unknown committed
1626
        break;
1627
      case SHOW_SSL_CTX_SESS_CONNECT_GOOD:
unknown's avatar
unknown committed
1628 1629 1630 1631
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_connect_good(ssl_acceptor_fd->
							    ssl_context_)),
			  buff, 10);
1632
        break;
unknown's avatar
unknown committed
1633
      case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE:
unknown's avatar
unknown committed
1634 1635 1636
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context_)),
			  buff, 10);
unknown's avatar
unknown committed
1637
        break;
1638
      case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE:
unknown's avatar
unknown committed
1639 1640 1641
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context_)),
			  buff, 10);
1642
        break;
unknown's avatar
unknown committed
1643
      case SHOW_SSL_CTX_SESS_CB_HITS:
unknown's avatar
unknown committed
1644 1645 1646 1647
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_cb_hits(ssl_acceptor_fd->
						       ssl_context_)),
			  buff, 10);
unknown's avatar
unknown committed
1648
        break;
1649
      case SHOW_SSL_CTX_SESS_HITS:
unknown's avatar
unknown committed
1650 1651 1652 1653
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_hits(ssl_acceptor_fd->
						    ssl_context_)),
			  buff, 10);
1654 1655
        break;
      case SHOW_SSL_CTX_SESS_CACHE_FULL:
unknown's avatar
unknown committed
1656 1657 1658 1659
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_cache_full(ssl_acceptor_fd->
							  ssl_context_)),
			  buff, 10);
1660 1661
        break;
      case SHOW_SSL_CTX_SESS_MISSES:
unknown's avatar
unknown committed
1662 1663 1664 1665
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_misses(ssl_acceptor_fd->
						      ssl_context_)),
			  buff, 10);
1666 1667
        break;
      case SHOW_SSL_CTX_SESS_TIMEOUTS:
unknown's avatar
unknown committed
1668 1669 1670
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context_)),
			  buff,10);
1671
        break;
unknown's avatar
unknown committed
1672
      case SHOW_SSL_CTX_SESS_NUMBER:
unknown's avatar
unknown committed
1673 1674 1675
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context_)),
			  buff,10);
unknown's avatar
unknown committed
1676
        break;
1677
      case SHOW_SSL_CTX_SESS_CONNECT:
unknown's avatar
unknown committed
1678 1679 1680
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context_)),
			  buff,10);
1681
        break;
unknown's avatar
unknown committed
1682
      case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE:
unknown's avatar
unknown committed
1683 1684 1685
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context_)),
				  buff,10);
unknown's avatar
unknown committed
1686 1687
        break;
      case SHOW_SSL_CTX_GET_VERIFY_MODE:
unknown's avatar
unknown committed
1688 1689 1690
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context_)),
			  buff,10);
unknown's avatar
unknown committed
1691 1692
        break;
      case SHOW_SSL_CTX_GET_VERIFY_DEPTH:
unknown's avatar
unknown committed
1693 1694 1695
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context_)),
			  buff,10);
unknown's avatar
unknown committed
1696 1697
        break;
      case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE:
unknown's avatar
unknown committed
1698 1699
	if (!ssl_acceptor_fd)
	{
unknown's avatar
unknown committed
1700 1701
	  pos= "NONE";
	  end= pos+4;
unknown's avatar
unknown committed
1702 1703
	  break;
	}
1704
	switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context_))
unknown's avatar
unknown committed
1705 1706
	{
          case SSL_SESS_CACHE_OFF:
unknown's avatar
unknown committed
1707
            pos= "OFF";
unknown's avatar
unknown committed
1708 1709
	    break;
          case SSL_SESS_CACHE_CLIENT:
unknown's avatar
unknown committed
1710
            pos= "CLIENT";
unknown's avatar
unknown committed
1711 1712
	    break;
          case SSL_SESS_CACHE_SERVER:
unknown's avatar
unknown committed
1713
            pos= "SERVER";
unknown's avatar
unknown committed
1714 1715
	    break;
          case SSL_SESS_CACHE_BOTH:
unknown's avatar
unknown committed
1716
            pos= "BOTH";
unknown's avatar
unknown committed
1717 1718
	    break;
          case SSL_SESS_CACHE_NO_AUTO_CLEAR:
unknown's avatar
unknown committed
1719
            pos= "NO_AUTO_CLEAR";
unknown's avatar
unknown committed
1720 1721
	    break;
          case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
unknown's avatar
unknown committed
1722
            pos= "NO_INTERNAL_LOOKUP";
unknown's avatar
unknown committed
1723 1724
	    break;
	  default:
unknown's avatar
unknown committed
1725
            pos= "Unknown";
unknown's avatar
unknown committed
1726 1727
	    break;
	}
1728
	end= strend(pos);
unknown's avatar
unknown committed
1729
        break;
unknown's avatar
unknown committed
1730 1731
	/* First group - functions relying on SSL */
      case SHOW_SSL_GET_VERSION:
unknown's avatar
unknown committed
1732 1733
	pos= thd->net.vio->ssl_ ? SSL_get_version(thd->net.vio->ssl_) : "";
	end= strend(pos);
unknown's avatar
unknown committed
1734 1735
        break;
      case SHOW_SSL_SESSION_REUSED:
unknown's avatar
unknown committed
1736 1737 1738
	end= int10_to_str((long) (thd->net.vio->ssl_ ?
				  SSL_session_reused(thd->net.vio->ssl_):
				  0), buff, 10);
unknown's avatar
unknown committed
1739 1740
        break;
      case SHOW_SSL_GET_DEFAULT_TIMEOUT:
unknown's avatar
unknown committed
1741 1742 1743
	end= int10_to_str((long) (thd->net.vio->ssl_ ?
				  SSL_get_default_timeout(thd->net.vio->ssl_):
				  0), buff, 10);
unknown's avatar
unknown committed
1744 1745
        break;
      case SHOW_SSL_GET_VERIFY_MODE:
unknown's avatar
unknown committed
1746 1747 1748
	end= int10_to_str((long) (thd->net.vio->ssl_ ?
				  SSL_get_verify_mode(thd->net.vio->ssl_):
				  0), buff, 10);
unknown's avatar
unknown committed
1749 1750
        break;
      case SHOW_SSL_GET_VERIFY_DEPTH:
unknown's avatar
unknown committed
1751 1752 1753
	end= int10_to_str((long) (thd->net.vio->ssl_ ?
				  SSL_get_verify_depth(thd->net.vio->ssl_):
				  0), buff, 10);
unknown's avatar
unknown committed
1754 1755
        break;
      case SHOW_SSL_GET_CIPHER:
unknown's avatar
unknown committed
1756 1757
	pos= thd->net.vio->ssl_ ? SSL_get_cipher(thd->net.vio->ssl_) : "";
	end= strend(pos);
unknown's avatar
unknown committed
1758
	break;
1759
      case SHOW_SSL_GET_CIPHER_LIST:
unknown's avatar
unknown committed
1760
	if (thd->net.vio->ssl_)
1761
	{
unknown's avatar
unknown committed
1762
	  char *to= buff;
unknown's avatar
unknown committed
1763
	  for (int i=0 ; i++ ;)
1764
	  {
unknown's avatar
unknown committed
1765
	    const char *p= SSL_get_cipher_list(thd->net.vio->ssl_,i);
1766 1767
	    if (p == NULL) 
	      break;
unknown's avatar
unknown committed
1768 1769
	    to= strmov(to, p);
	    *to++= ':';
1770
	  }
unknown's avatar
unknown committed
1771 1772 1773
	  if (to != buff)
	    to--;				// Remove last ':'
	  end= to;
unknown's avatar
unknown committed
1774
        }
unknown's avatar
unknown committed
1775
        break;
unknown's avatar
unknown committed
1776 1777

#endif /* HAVE_OPENSSL */
unknown's avatar
unknown committed
1778 1779
      case SHOW_UNDEF:				// Show never happen
      case SHOW_SYS:
unknown's avatar
unknown committed
1780
	break;					// Return empty string
unknown's avatar
SCRUM  
unknown committed
1781 1782
      default:
	break;
unknown's avatar
unknown committed
1783
      }
1784
      if (protocol->store(pos, (uint32) (end - pos), system_charset_info) ||
unknown's avatar
unknown committed
1785
	  protocol->write())
1786
        goto err;                               /* purecov: inspected */
unknown's avatar
unknown committed
1787 1788 1789
    }
  }
  pthread_mutex_unlock(&LOCK_status);
unknown's avatar
unknown committed
1790
  /* pthread_mutex_unlock(&THR_LOCK_keycache); */
1791
  send_eof(thd);
unknown's avatar
unknown committed
1792 1793 1794 1795
  DBUG_RETURN(0);

 err:
  pthread_mutex_unlock(&LOCK_status);
unknown's avatar
unknown committed
1796
  /* pthread_mutex_unlock(&THR_LOCK_keycache); */
unknown's avatar
unknown committed
1797 1798 1799 1800
  DBUG_RETURN(1);
}

#ifdef __GNUC__
unknown's avatar
unknown committed
1801
template class List_iterator_fast<char>;
unknown's avatar
unknown committed
1802 1803
template class List<char>;
#endif