sql_show.cc 64.1 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

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

34
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bk@work.mysql.com's avatar
bk@work.mysql.com committed
35
static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
36 37
                               "grant_types",
                               grant_names};
38
#endif
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
store_create_info(THD *thd, TABLE *table, String *packet);

tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
46

47 48 49 50
/*
  Report list of databases
  A database is a directory in the mysql_data_home directory
*/
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
51

bk@work.mysql.com's avatar
bk@work.mysql.com committed
52 53 54
int
mysqld_show_dbs(THD *thd,const char *wild)
{
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
55
  Item_string *field=new Item_string("",0,thd->charset());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
56 57 58 59
  List<Item> field_list;
  char *end;
  List<char> files;
  char *file_name;
60
  Protocol *protocol= thd->protocol;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
61 62
  DBUG_ENTER("mysqld_show_dbs");

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

70
  if (protocol->send_fields(&field_list,1))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
71 72 73
    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
74
  List_iterator_fast<char> it(files);
75

bk@work.mysql.com's avatar
bk@work.mysql.com committed
76 77
  while ((file_name=it++))
  {
hf@deer.(none)'s avatar
hf@deer.(none) committed
78
#ifndef NO_EMBEDDED_ACCESS_CHECKS
79
    if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
80
	acl_get(thd->host, thd->ip, thd->priv_user, file_name,0) ||
81
	(grant_option && !check_grant_db(thd, file_name)))
hf@deer.(none)'s avatar
hf@deer.(none) committed
82
#endif
83
    {
84
      protocol->prepare_for_resend();
85
      protocol->store(file_name, system_charset_info);
86
      if (protocol->write())
87 88
	DBUG_RETURN(-1);
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
89
  }
90
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
91 92 93
  DBUG_RETURN(0);
}

94

95
/***************************************************************************
96
  List all open tables in a database
97 98
***************************************************************************/

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

106 107
  field_list.push_back(new Item_empty_string("Database",NAME_LEN));
  field_list.push_back(new Item_empty_string("Table",NAME_LEN));
108 109
  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));
110

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

114
  if (!(open_list=list_open_tables(thd,wild)) && thd->is_fatal_error)
115 116
    DBUG_RETURN(-1);

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

133

bk@work.mysql.com's avatar
bk@work.mysql.com committed
134 135 136 137 138 139 140
/***************************************************************************
** 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)
{
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
141
  Item_string *field=new Item_string("",0,thd->charset());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
142 143 144 145
  List<Item> field_list;
  char path[FN_LEN],*end;
  List<char> files;
  char *file_name;
146
  Protocol *protocol= thd->protocol;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
147 148
  DBUG_ENTER("mysqld_show_tables");

149 150
  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
151 152 153 154 155 156 157
  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);
158
  if (protocol->send_fields(&field_list,1))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
159 160 161
    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
162
  List_iterator_fast<char> it(files);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
163 164
  while ((file_name=it++))
  {
165
    protocol->prepare_for_resend();
166
    protocol->store(file_name, system_charset_info);
167
    if (protocol->write())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
168 169
      DBUG_RETURN(-1);
  }
170
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
171 172 173
  DBUG_RETURN(0);
}

174 175 176 177
/***************************************************************************
** List all table types supported 
***************************************************************************/

178
int mysqld_show_storage_engines(THD *thd)
179 180
{
  List<Item> field_list;
181
  Protocol *protocol= thd->protocol;
182
  DBUG_ENTER("mysqld_show_storage_engines");
183

monty@mishka.local's avatar
monty@mishka.local committed
184
  field_list.push_back(new Item_empty_string("Engine",10));
185
  field_list.push_back(new Item_empty_string("Support",10));
186
  field_list.push_back(new Item_empty_string("Comment",80));
187

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

191
  const char *default_type_name= 
192
    ha_get_storage_engine((enum db_type)thd->variables.table_type);
193

194 195
  show_table_type_st *types;
  for (types= sys_table_types; types->type; types++)
196
  {
197
    protocol->prepare_for_resend();
198
    protocol->store(types->type, system_charset_info);
199 200 201
    const char *option_name= show_comp_option_name[(int) *types->value];

    if (*types->value == SHOW_OPTION_YES &&
202
	!my_strcasecmp(system_charset_info, default_type_name, types->type))
203
      option_name= "DEFAULT";
204 205
    protocol->store(option_name, system_charset_info);
    protocol->store(types->comment, system_charset_info);
206
    if (protocol->write())
207 208
      DBUG_RETURN(-1);
  }
209
  send_eof(thd);
210 211 212
  DBUG_RETURN(0);
}

213

214
/***************************************************************************
215
 List all privileges supported
216 217
***************************************************************************/

218 219 220 221
struct show_privileges_st {
  const char *privilege;
  const char *context;
  const char *comment;
222 223
};

224 225
static struct show_privileges_st sys_privileges[]=
{
226 227
  {"Alter", "Tables",  "To alter the table"},
  {"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"},
228
  {"Create", "Databases,Tables,Indexes",  "To create new databases and tables"},
229 230 231 232 233 234 235 236
  {"Delete", "Tables",  "To delete existing rows"},
  {"Drop", "Databases,Tables", "To drop databases and tables"},
  {"File", "File access on server",   "To read and write files on the server"},
  {"Grant option",  "Databases,Tables", "To give to other users those privileges you possess"},
  {"Index", "Tables",  "To create or drop indexes"},
  {"Insert", "Tables",  "To insert data into tables"},
  {"Lock tables","Databases","To use LOCK TABLES (together with SELECT privilege)"},
  {"Process", "Server Admin", "To view the plain text of currently executing queries"},
237
  {"References", "Databases,Tables", "To have references on tables"},
238 239 240 241 242
  {"Reload", "Server Admin", "To reload or refresh tables, logs and privileges"},
  {"Replication client","Server Admin","To ask where the slave or master servers are"},
  {"Replication slave","Server Admin","To read binary log events from the master"},
  {"Select", "Tables",  "To retrieve rows from table"},
  {"Show databases","Server Admin","To see all databases with SHOW DATABASES"},
243
  {"Shutdown","Server Admin", "To shutdown the server"},
244 245 246
  {"Super","Server Admin","To use KILL thread, SET GLOBAL, CHANGE MASTER, etc."},
  {"Update", "Tables",  "To update existing rows"},
  {"Usage","Server Admin","No privileges - allow connect only"},
247 248 249
  {NullS, NullS, NullS}
};

250 251 252
int mysqld_show_privileges(THD *thd)
{
  List<Item> field_list;
253
  Protocol *protocol= thd->protocol;
254 255 256 257 258 259
  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));

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

263 264
  show_privileges_st *privilege= sys_privileges;
  for (privilege= sys_privileges; privilege->privilege ; privilege++)
265
  {
266
    protocol->prepare_for_resend();
267 268 269
    protocol->store(privilege->privilege, system_charset_info);
    protocol->store(privilege->context, system_charset_info);
    protocol->store(privilege->comment, system_charset_info);
270
    if (protocol->write())
271 272
      DBUG_RETURN(-1);
  }
273
  send_eof(thd);
274 275 276 277 278
  DBUG_RETURN(0);
}


/***************************************************************************
279
  List all column types
280 281
***************************************************************************/

282 283
struct show_column_type_st
{
284 285
  const char *type;
  uint size;
286 287 288 289 290 291 292 293 294 295 296 297
  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;
298
};
299 300 301 302 303

/* TODO: Add remaning types */

static struct show_column_type_st sys_column_types[]=
{
304 305
  {"tinyint",
    1,  "-128",  "127",  0,  0,  "YES",  "YES",
306 307
    "NO",   "YES", "YES",  "NO",  "NULL,0",
    "A very small integer"},
308
  {"tinyint unsigned",
309 310
    1,  "0"   ,  "255",  0,  0,  "YES",  "YES",
    "YES",  "YES",  "YES",  "NO",  "NULL,0",
311 312 313 314 315 316
    "A very small integer"},
};

int mysqld_show_column_types(THD *thd)
{
  List<Item> field_list;
317
  Protocol *protocol= thd->protocol;
318 319 320 321 322 323
  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));
324 325
  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));
326 327 328 329 330 331 332 333 334
  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));

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

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


static int
mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
366
                 const char *wild, bool dir)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
367 368 369 370 371
{
  uint i;
  char *ext;
  MY_DIR *dirp;
  FILEINFO *file;
372
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bk@work.mysql.com's avatar
bk@work.mysql.com committed
373
  uint col_access=thd->col_access;
374
#endif
bk@work.mysql.com's avatar
bk@work.mysql.com committed
375 376 377
  TABLE_LIST table_list;
  DBUG_ENTER("mysql_find_files");

378 379
  if (wild && !wild[0])
    wild=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
380 381 382 383 384
  bzero((char*) &table_list,sizeof(table_list));

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

385
  for (i=0 ; i < (uint) dirp->number_off_files  ; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
386 387 388
  {
    file=dirp->dir_entry+i;
    if (dir)
389
    {                                           /* Return databases */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
390 391 392
#ifdef USE_SYMDIR
      char *ext;
      if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym"))
393 394 395 396
      {
	/* Only show the sym file if it points to a directory */
	char buff[FN_REFLEN], *end;
	MY_STAT status;
397
        *ext=0;                                 /* Remove extension */
398 399 400 401 402 403 404 405
	unpack_dirname(buff, file->name);
	end= strend(buff);
	if (end != buff && end[-1] == FN_LIBCHAR)
	  end[-1]= 0;				// Remove end FN_LIBCHAR
	if (!my_stat(buff, &status, MYF(0)) ||
	    !MY_S_ISDIR(status.st_mode))
	  continue;
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
406 407 408
      else
#endif
      {
dlenev@mysql.com's avatar
dlenev@mysql.com committed
409
        if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat->st_mode) ||
410
            (wild && wild_compare(file->name,wild,0)))
411
          continue;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
412 413 414 415
      }
    }
    else
    {
416
        // Return only .frm files which aren't temp files.
417
      if (my_strcasecmp(system_charset_info, ext=fn_ext(file->name),reg_ext) ||
418
          is_prefix(file->name,tmp_file_prefix))
419
        continue;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
420
      *ext=0;
421 422 423 424
      if (wild)
      {
	if (lower_case_table_names)
	{
425
	  if (wild_case_compare(files_charset_info, file->name, wild))
426 427
	    continue;
	}
428
	else if (wild_compare(file->name,wild,0))
429 430
	  continue;
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
431
    }
hf@deer.(none)'s avatar
hf@deer.(none) committed
432
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bk@work.mysql.com's avatar
bk@work.mysql.com committed
433 434 435 436 437 438
    /* 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;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
439
      if (check_grant(thd, TABLE_ACLS, &table_list, 1, UINT_MAX, 1))
440
        continue;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
441
    }
hf@deer.(none)'s avatar
hf@deer.(none) committed
442
#endif
443
    if (files->push_back(thd->strdup(file->name)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
444 445 446 447 448 449 450 451 452 453
    {
      my_dirend(dirp);
      DBUG_RETURN(-1);
    }
  }
  DBUG_PRINT("info",("found: %d files", files->elements));
  my_dirend(dirp);
  DBUG_RETURN(0);
}

454

bk@work.mysql.com's avatar
bk@work.mysql.com committed
455
/***************************************************************************
456
 Extended version of mysqld_show_tables
bk@work.mysql.com's avatar
bk@work.mysql.com committed
457 458 459 460 461 462 463 464 465 466
***************************************************************************/

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;
467 468
  Protocol *protocol= thd->protocol;
  TIME time;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
469 470 471 472 473
  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));
monty@mishka.local's avatar
monty@mishka.local committed
474
  field_list.push_back(item=new Item_empty_string("Engine",10));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
  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;
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
498
  field_list.push_back(item=new Item_empty_string("Collation",32));
499
  item->maybe_null=1;
serg@serg.mylan's avatar
serg@serg.mylan committed
500 501
  field_list.push_back(item=new Item_int("Checksum",(longlong) 1,21));
  item->maybe_null=1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
502 503 504
  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));
505
  item->maybe_null=1;
506
  if (protocol->send_fields(&field_list,1))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
507 508 509 510
    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
511
  List_iterator_fast<char> it(files);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
512 513 514 515
  while ((file_name=it++))
  {
    TABLE_LIST table_list;
    bzero((char*) &table_list,sizeof(table_list));
516
    protocol->prepare_for_resend();
517
    protocol->store(file_name, system_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
518
    table_list.db=(char*) db;
519
    table_list.real_name= table_list.alias= file_name;
520
    if (lower_case_table_names)
521
      my_casedn_str(files_charset_info, file_name);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
522 523
    if (!(table = open_ltable(thd, &table_list, TL_READ)))
    {
524
      for (uint i=2 ; i < field_list.elements ; i++)
525
        protocol->store_null();
526
      // Send error to Comment field
527
      protocol->store(thd->net.last_error, system_charset_info);
528
      thd->clear_error();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
529 530 531 532
    }
    else
    {
      struct tm tm_tmp;
533
      const char *str;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
534 535
      handler *file=table->file;
      file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK);
536
      protocol->store(file->table_type(), system_charset_info);
537 538 539 540
      str= ((table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ?
	    "Compressed" :
	    (table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
	    "Dynamic" : "Fixed");
541
      protocol->store(str, system_charset_info);
542 543 544
      protocol->store((ulonglong) file->records);
      protocol->store((ulonglong) file->mean_rec_length);
      protocol->store((ulonglong) file->data_file_length);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
545
      if (file->max_data_file_length)
546
        protocol->store((ulonglong) file->max_data_file_length);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
547
      else
548 549 550
        protocol->store_null();
      protocol->store((ulonglong) file->index_file_length);
      protocol->store((ulonglong) file->delete_length);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
551 552
      if (table->found_next_number_field)
      {
553 554 555
        table->next_number_field=table->found_next_number_field;
        table->next_number_field->reset();
        file->update_auto_increment();
556
        protocol->store(table->next_number_field->val_int());
557
        table->next_number_field=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
558 559
      }
      else
560
        protocol->store_null();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
561
      if (!file->create_time)
562
        protocol->store_null();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
563 564
      else
      {
565
        localtime_r(&file->create_time,&tm_tmp);
566 567
	localtime_to_TIME(&time, &tm_tmp);
        protocol->store(&time);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
568 569
      }
      if (!file->update_time)
570
        protocol->store_null();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
571 572
      else
      {
573
        localtime_r(&file->update_time,&tm_tmp);
574 575
	localtime_to_TIME(&time, &tm_tmp);
        protocol->store(&time);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
576 577
      }
      if (!file->check_time)
578
        protocol->store_null();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
579 580
      else
      {
581
        localtime_r(&file->check_time,&tm_tmp);
582 583
	localtime_to_TIME(&time, &tm_tmp);
        protocol->store(&time);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
584
      }
585
      str= (table->table_charset ? table->table_charset->name : "default");
586
      protocol->store(str, system_charset_info);
serg@serg.mylan's avatar
serg@serg.mylan committed
587 588 589 590
      if (file->table_flags() & HA_HAS_CHECKSUM)
        protocol->store((ulonglong)file->checksum());
      else
        protocol->store_null(); // Checksum
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
        protocol->store(option_buff+1,
628 629
			(ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1)
			, system_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
630
      }
631 632
      {
	char *comment=table->file->update_table_comment(table->comment);
633
	protocol->store(comment, system_charset_info);
634 635 636
	if (comment != table->comment)
	  my_free(comment,MYF(0));
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
637 638
      close_thread_tables(thd,0);
    }
639
    if (protocol->write())
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
***************************************************************************/
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
650

bk@work.mysql.com's avatar
bk@work.mysql.com committed
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
  Protocol *protocol= thd->protocol;
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
    DBUG_RETURN(1);
  }
  file=table->file;
  file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
hf@deer.(none)'s avatar
hf@deer.(none) committed
671
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bk@work.mysql.com's avatar
bk@work.mysql.com committed
672
  (void) get_table_grant(thd, table_list);
hf@deer.(none)'s avatar
hf@deer.(none) committed
673
#endif
bk@work.mysql.com's avatar
bk@work.mysql.com committed
674 675 676
  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));
677 678
  if (verbose)
    field_list.push_back(new Item_empty_string("Collation",40));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
679 680
  field_list.push_back(new Item_empty_string("Null",1));
  field_list.push_back(new Item_empty_string("Key",3));
681 682
  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
683
  field_list.push_back(new Item_empty_string("Extra",20));
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
684
  if (verbose)
685
  {
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
686
    field_list.push_back(new Item_empty_string("Privileges",80));
687 688
    field_list.push_back(new Item_empty_string("Comment",255));
  }
689
        // Send first number of fields and records
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
690 691
  if (protocol->send_records_num(&field_list, (ulonglong)file->records) ||
      protocol->send_fields(&field_list,0))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
692
    DBUG_RETURN(1);
693
  restore_record(table,default_values);      // Get empty record
bk@work.mysql.com's avatar
bk@work.mysql.com committed
694 695 696 697

  Field **ptr,*field;
  for (ptr=table->field; (field= *ptr) ; ptr++)
  {
698 699
    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
700 701
    {
      {
702 703
        byte *pos;
        uint flags=field->flags;
704
        String type(tmp,sizeof(tmp), system_charset_info);
705 706
        uint col_access;

707
	protocol->prepare_for_resend();
708
        protocol->store(field->field_name, system_charset_info);
709
        field->sql_type(type);
710
        protocol->store(type.ptr(), type.length(), system_charset_info);
711 712
	if (verbose)
	  protocol->store(field->has_charset() ? field->charset()->name : "NULL",
713
			system_charset_info);
714 715 716 717 718 719
        /*
          Altough TIMESTAMP fields can't contain NULL as its value they
          will accept NULL if you will try to insert such value and will
          convert it to current TIMESTAMP. So YES here means that NULL 
          is allowed for assignment but can't be returned.
        */
720 721 722
        pos=(byte*) ((flags & NOT_NULL_FLAG) &&
                     field->type() != FIELD_TYPE_TIMESTAMP ?
                     "" : "YES");
723
        protocol->store((const char*) pos, system_charset_info);
724 725 726
        pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
                     (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
                     (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
727
        protocol->store((char*) pos, system_charset_info);
728

729 730 731 732 733 734 735 736 737
        if (table->timestamp_field == field &&
            field->unireg_check != Field::TIMESTAMP_UN_FIELD)
        {
          /*
            We have NOW() as default value but we use CURRENT_TIMESTAMP form
            because it is more SQL standard comatible
          */
          protocol->store("CURRENT_TIMESTAMP", system_charset_info);
        }
738
        else if (field->unireg_check != Field::NEXT_NUMBER &&
739
                 !field->is_null())
740
        {                                               // Not null by default
741
          type.set(tmp, sizeof(tmp), field->charset());
742
          field->val_str(&type);
743
          protocol->store(type.ptr(),type.length(),type.charset());
744
        }
745 746
        else if (field->unireg_check == Field::NEXT_NUMBER ||
                 field->maybe_null())
747
          protocol->store_null();                       // Null as default
748
        else
749
          protocol->store("",0, system_charset_info);	// empty string
750 751 752 753

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

monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
756 757
	if (verbose)
	{
758
	  /* Add grant options & comments */
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
759
	  end=tmp;
hf@deer.(none)'s avatar
hf@deer.(none) committed
760
#ifndef NO_EMBEDDED_ACCESS_CHECKS
761
	  col_access= get_column_grant(thd,table_list,field) & COL_ACLS;
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
762 763 764 765 766 767 768 769
	  for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
	  {
	    if (col_access & 1)
	    {
	      *end++=',';
	      end=strmov(end,grant_types.type_names[bitnr]);
	    }
	  }
hf@deer.(none)'s avatar
hf@deer.(none) committed
770 771 772
#else
	  end=strmov(end,"");
#endif
773 774 775 776
	  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);
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
777
	}
778
        if (protocol->write())
779
          DBUG_RETURN(1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
780 781 782
      }
    }
  }
783
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
784 785 786
  DBUG_RETURN(0);
}

787

bk@work.mysql.com's avatar
bk@work.mysql.com committed
788 789 790 791
int
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
  TABLE *table;
792 793 794
  Protocol *protocol= thd->protocol;
  char buff[2048];
  String buffer(buff, sizeof(buff), system_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
795 796
  DBUG_ENTER("mysqld_show_create");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
797
                      table_list->real_name));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
798

monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
799
  /* Only one table for now */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
800 801
  if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  {
802
    send_error(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
803 804 805
    DBUG_RETURN(1);
  }

monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
806
  if (store_create_info(thd, table, &buffer))
807 808
    DBUG_RETURN(-1);

bk@work.mysql.com's avatar
bk@work.mysql.com committed
809 810
  List<Item> field_list;
  field_list.push_back(new Item_empty_string("Table",NAME_LEN));
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
811
  // 1024 is for not to confuse old clients
812
  field_list.push_back(new Item_empty_string("Create Table",
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
813
					     max(buffer.length(),1024)));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
814

815 816 817
  if (protocol->send_fields(&field_list, 1))
    DBUG_RETURN(1);
  protocol->prepare_for_resend();
818
  protocol->store(table->table_name, system_charset_info);
819
  buffer.length(0);
820 821
  if (store_create_info(thd, table, &buffer))
    DBUG_RETURN(-1);
822
  protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
823
  if (protocol->write())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
824
    DBUG_RETURN(1);
825
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
826 827 828
  DBUG_RETURN(0);
}

829 830 831 832 833 834 835
int mysqld_show_create_db(THD *thd, char *dbname,
			  HA_CREATE_INFO *create_info)
{
  int length;
  char	path[FN_REFLEN];
  char buff[2048];
  String buffer(buff, sizeof(buff), system_charset_info);
836
#ifndef NO_EMBEDDED_ACCESS_CHECKS
837
  uint db_access;
838
#endif
839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918
  bool found_libchar;
  HA_CREATE_INFO create;
  uint create_options = create_info ? create_info->options : 0;
  Protocol *protocol=thd->protocol;
  DBUG_ENTER("mysql_show_create_db");

  if (check_db_name(dbname))
  {
    net_printf(thd,ER_WRONG_DB_NAME, dbname);
    DBUG_RETURN(1);
  }

#ifndef NO_EMBEDDED_ACCESS_CHECKS
  if (test_all_bits(thd->master_access,DB_ACLS))
    db_access=DB_ACLS;
  else
    db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) |
		thd->master_access);
  if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
  {
    net_printf(thd,ER_DBACCESS_DENIED_ERROR,
	       thd->priv_user, thd->host_or_ip, dbname);
    mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
		    thd->priv_user, thd->host_or_ip, dbname);
    DBUG_RETURN(1);
  }
#endif

  (void) sprintf(path,"%s/%s",mysql_data_home, dbname);
  length=unpack_dirname(path,path);		// Convert if not unix
  found_libchar= 0;
  if (length && path[length-1] == FN_LIBCHAR)
  {
    found_libchar= 1;
    path[length-1]=0;				// remove ending '\'
  }
  if (access(path,F_OK))
  {
    net_printf(thd,ER_BAD_DB_ERROR,dbname);
    DBUG_RETURN(1);
  }
  if (found_libchar)
    path[length-1]= FN_LIBCHAR;
  strmov(path+length, MY_DB_OPT_FILE);
  load_db_opt(thd, path, &create);

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

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

  protocol->prepare_for_resend();
  protocol->store(dbname, strlen(dbname), system_charset_info);
  buffer.length(0);
  buffer.append("CREATE DATABASE ", 16);
  if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
    buffer.append("/*!32312 IF NOT EXISTS*/ ", 25);
  append_identifier(thd, &buffer, dbname, strlen(dbname));

  if (create.default_table_charset)
  {
    buffer.append(" /*!40100", 9);
    buffer.append(" DEFAULT CHARACTER SET ", 23);
    buffer.append(create.default_table_charset->csname);
    if (!(create.default_table_charset->state & MY_CS_PRIMARY))
    {
      buffer.append(" COLLATE ", 9);
      buffer.append(create.default_table_charset->name);
    }
    buffer.append(" */", 3);
  }
  protocol->store(buffer.ptr(), buffer.length(), buffer.charset());

  if (protocol->write())
    DBUG_RETURN(1);
  send_eof(thd);
  DBUG_RETURN(0);
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
919

tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
920 921 922
int
mysqld_show_logs(THD *thd)
{
923 924
  List<Item> field_list;
  Protocol *protocol= thd->protocol;
tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
925 926 927 928 929 930
  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));

931
  if (protocol->send_fields(&field_list,1))
tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
932 933
    DBUG_RETURN(1);

934
#ifdef HAVE_BERKELEY_DB
935
  if ((have_berkeley_db == SHOW_OPTION_YES) && berkeley_show_logs(protocol))
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
936
    DBUG_RETURN(-1);
937
#endif
tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
938

939
  send_eof(thd);
tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
940 941 942 943
  DBUG_RETURN(0);
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
944 945 946 947
int
mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
{
  TABLE *table;
948
  Protocol *protocol= thd->protocol;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
949 950
  DBUG_ENTER("mysqld_show_keys");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
951
                      table_list->real_name));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
952 953 954

  if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  {
955
    send_error(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
956 957 958 959 960 961
    DBUG_RETURN(1);
  }

  List<Item> field_list;
  Item *item;
  field_list.push_back(new Item_empty_string("Table",NAME_LEN));
962
  field_list.push_back(new Item_return_int("Non_unique",1, MYSQL_TYPE_TINY));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
963
  field_list.push_back(new Item_empty_string("Key_name",NAME_LEN));
964
  field_list.push_back(new Item_return_int("Seq_in_index",2, MYSQL_TYPE_TINY));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
965 966 967
  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;
968
  field_list.push_back(item=new Item_int("Cardinality",0,21));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
969
  item->maybe_null=1;
970 971
  field_list.push_back(item=new Item_return_int("Sub_part",3,
						MYSQL_TYPE_TINY));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
972 973 974
  item->maybe_null=1;
  field_list.push_back(item=new Item_empty_string("Packed",10));
  item->maybe_null=1;
975 976
  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
977 978 979
  field_list.push_back(new Item_empty_string("Comment",255));
  item->maybe_null=1;

980
  if (protocol->send_fields(&field_list,1))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
981 982 983 984 985 986 987
    DBUG_RETURN(1);

  KEY *key_info=table->key_info;
  table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
  for (uint i=0 ; i < table->keys ; i++,key_info++)
  {
    KEY_PART_INFO *key_part= key_info->key_part;
988
    const char *str;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
989 990
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
    {
991
      protocol->prepare_for_resend();
992
      protocol->store(table->table_name, system_charset_info);
993
      protocol->store_tiny((longlong) ((key_info->flags & HA_NOSAME) ? 0 :1));
994
      protocol->store(key_info->name, system_charset_info);
995 996 997
      protocol->store_tiny((longlong) (j+1));
      str=(key_part->field ? key_part->field->field_name :
	   "?unknown field?");
998
      protocol->store(str, system_charset_info);
999
      if (table->file->index_flags(i) & HA_READ_ORDER)
1000
        protocol->store(((key_part->key_part_flag & HA_REVERSE_SORT) ?
1001
			 "D" : "A"), 1, system_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1002
      else
1003
        protocol->store_null(); /* purecov: inspected */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1004 1005 1006
      KEY *key=table->key_info+i;
      if (key->rec_per_key[j])
      {
1007
        ha_rows records=(table->file->records / key->rec_per_key[j]);
1008
        protocol->store((ulonglong) records);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1009 1010
      }
      else
1011
        protocol->store_null();
1012 1013

      /* Check if we have a key part that only uses part of the field */
serg@serg.mylan's avatar
serg@serg.mylan committed
1014 1015
      if (!(key_info->flags & HA_FULLTEXT) && (!key_part->field ||
          key_part->length != table->field[key_part->fieldnr-1]->key_length()))
1016
        protocol->store_tiny((longlong) key_part->length);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1017
      else
1018 1019
        protocol->store_null();
      protocol->store_null();                   // No pack_information yet
1020 1021 1022

      /* Null flag */
      uint flags= key_part->field ? key_part->field->flags : 0;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
1023
      char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
1024 1025
      protocol->store((const char*) pos, system_charset_info);
      protocol->store(table->file->index_type(i), system_charset_info);
1026
      /* Comment */
1027
      if (!table->keys_in_use.is_set(i))
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1028
	protocol->store("disabled",8, system_charset_info);
1029
      else
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1030
        protocol->store("", 0, system_charset_info);
1031
      if (protocol->write())
1032
        DBUG_RETURN(1); /* purecov: inspected */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1033 1034
    }
  }
1035
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1036 1037 1038 1039 1040
  DBUG_RETURN(0);
}


/****************************************************************************
1041 1042
  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
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
****************************************************************************/

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)))
  {
1054
    send_error(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1055 1056 1057 1058 1059 1060 1061
    DBUG_VOID_RETURN;
  }
  List<Item> field_list;

  Field **ptr,*field;
  for (ptr=table->field ; (field= *ptr); ptr++)
  {
1062 1063
    if (!wild || !wild[0] || 
        !wild_case_compare(system_charset_info, field->field_name,wild))
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1064
      field_list.push_back(new Item_field(field));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1065
  }
1066
  restore_record(table,default_values);              // Get empty record
1067
  if (thd->protocol->send_fields(&field_list,2))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1068
    DBUG_VOID_RETURN;
1069
  net_flush(&thd->net);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1070 1071 1072
  DBUG_VOID_RETURN;
}

1073

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1074 1075 1076
int
mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
{
1077 1078
  Protocol *protocol= thd->protocol;
  String *packet= protocol->storage_packet();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1079 1080
  DBUG_ENTER("mysqld_dump_create_info");
  DBUG_PRINT("enter",("table: %s",table->real_name));
1081

1082 1083
  protocol->prepare_for_resend();
  if (store_create_info(thd, table, packet))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1084
    DBUG_RETURN(-1);
1085

1086 1087
  //if (protocol->convert)
  //  protocol->convert->convert((char*) packet->ptr(), packet->length());
1088
  if (fd < 0)
1089
  {
1090
    if (protocol->write())
1091
      DBUG_RETURN(-1);
1092
    net_flush(&thd->net);
1093
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1094
  else
1095
  {
1096 1097
    if (my_write(fd, (const byte*) packet->ptr(), packet->length(),
		 MYF(MY_WME)))
1098 1099
      DBUG_RETURN(-1);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1100 1101
  DBUG_RETURN(0);
}
1102

1103
/*
1104 1105
  Go through all character combinations and ensure that sql_lex.cc can
  parse it as an identifer.
1106 1107

  SYNOPSIS
1108 1109 1110 1111 1112 1113 1114
  require_quotes()
  name			attribute name
  name_length		length of name

  RETURN
    #	Pointer to conflicting character
    0	No conflicting character
1115 1116
*/

1117
static const char *require_quotes(const char *name, uint name_length)
1118
{
1119 1120 1121 1122
  uint length;
  const char *end= name + name_length;

  for ( ; name < end ; name++)
1123
  {
1124 1125 1126 1127
    uchar chr= (uchar) *name;
    length= my_mbcharlen(system_charset_info, chr);
    if (length == 1 && !system_charset_info->ident_map[chr])
      return name;
1128 1129 1130
  }
  return 0;
}
1131

1132 1133 1134 1135 1136 1137 1138 1139 1140 1141

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


1142 1143
void
append_identifier(THD *thd, String *packet, const char *name, uint length)
1144
{
1145 1146 1147
  const char *name_end;
  char quote_char;

1148
  if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
1149
    quote_char= '\"';
1150
  else
1151
    quote_char= '`';
1152

1153
  if (is_keyword(name,length))
1154
  {
1155 1156
    append_quoted_simple_identifier(packet, quote_char, name, length);
    return;
1157
  }
1158 1159

  if (!require_quotes(name, length))
1160
  {
1161
    if (!(thd->options & OPTION_QUOTE_SHOW_CREATE))
1162
      packet->append(name, length, system_charset_info);
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
    else
      append_quoted_simple_identifier(packet, quote_char, name, length);
    return;
  }

  /* The identifier must be quoted as it includes a quote character */

  packet->reserve(length*2 + 2);
  packet->append(&quote_char, 1, system_charset_info);

  for (name_end= name+length ; name < name_end ; name+= length)
  {
    char chr= *name;
    length= my_mbcharlen(system_charset_info, chr);
    if (length == 1 && chr == quote_char)
      packet->append(&quote_char, 1, system_charset_info);
    packet->append(name, length, packet->charset());
1180
  }
1181
  packet->append(&quote_char, 1, system_charset_info);
1182 1183
}

1184 1185 1186 1187 1188 1189 1190

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

static void append_directory(THD *thd, String *packet, const char *dir_type,
			     const char *filename)
{
  uint length;
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1191
  if (filename && !(thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
  {
    length= dirname_length(filename);
    packet->append(' ');
    packet->append(dir_type);
    packet->append(" DIRECTORY='", 12);
    packet->append(filename, length);
    packet->append('\'');
  }
}


monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1203
#define LIST_PROCESS_HOST_LEN 64
1204

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1205
static int
1206
store_create_info(THD *thd, TABLE *table, String *packet)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1207
{
1208
  List<Item> field_list;
monty@mysql.com's avatar
monty@mysql.com committed
1209
  char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end, *alias;
1210
  String type(tmp, sizeof(tmp), system_charset_info);
1211 1212 1213 1214 1215
  Field **ptr,*field;
  uint primary_key;
  KEY *key_info;
  handler *file= table->file;
  HA_CREATE_INFO create_info;
1216 1217 1218 1219
  my_bool foreign_db_mode=    (thd->variables.sql_mode & (MODE_POSTGRESQL |
							  MODE_ORACLE |
							  MODE_MSSQL |
							  MODE_DB2 |
1220
							  MODE_MAXDB |
1221 1222 1223 1224
							  MODE_ANSI)) != 0;
  my_bool limited_mysql_mode= (thd->variables.sql_mode &
			       (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
				MODE_MYSQL40)) != 0;
1225

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1226 1227 1228
  DBUG_ENTER("store_create_info");
  DBUG_PRINT("enter",("table: %s",table->real_name));

1229
  restore_record(table,default_values); // Get empty record
1230

1231 1232 1233 1234
  if (table->tmp_table)
    packet->append("CREATE TEMPORARY TABLE ", 23);
  else
    packet->append("CREATE TABLE ", 13);
monty@mysql.com's avatar
monty@mysql.com committed
1235 1236 1237
  alias= (lower_case_table_names == 2 ? table->table_name :
	  table->real_name);
  append_identifier(thd, packet, alias, strlen(alias));
1238
  packet->append(" (\n", 3);
1239

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1240 1241
  for (ptr=table->field ; (field= *ptr); ptr++)
  {
1242
    bool has_default;
1243
    bool has_now_default;
1244 1245
    uint flags = field->flags;

1246
    if (ptr != table->field)
1247
      packet->append(",\n", 2);
1248

1249
    packet->append("  ", 2);
1250
    append_identifier(thd,packet,field->field_name, strlen(field->field_name));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1251 1252
    packet->append(' ');
    // check for surprises from the previous call to Field::sql_type()
1253
    if (type.ptr() != tmp)
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1254
      type.set(tmp, sizeof(tmp),&my_charset_bin);
1255

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1256
    field->sql_type(type);
1257
    packet->append(type.ptr(), type.length(), system_charset_info);
1258

1259
    if (field->has_charset() && !limited_mysql_mode && !foreign_db_mode)
1260
    {
1261
      if (field->charset() != table->table_charset)
1262
      {
1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
	packet->append(" character set ", 15);
	packet->append(field->charset()->csname);
      }
      /* 
	For string types dump collation name only if 
	collation is not primary for the given charset
      */
      if (!(field->charset()->state & MY_CS_PRIMARY))
      {
	packet->append(" collate ", 9);
	packet->append(field->charset()->name);
1274
      }
1275
    }
1276

1277 1278
    if (flags & NOT_NULL_FLAG)
      packet->append(" NOT NULL", 9);
1279

1280 1281

    /* 
1282
      Again we are using CURRENT_TIMESTAMP instead of NOW because it is
1283 1284 1285 1286 1287
      more standard 
    */
    has_now_default= table->timestamp_field == field && 
                     field->unireg_check != Field::TIMESTAMP_UN_FIELD;
    
1288
    has_default= (field->type() != FIELD_TYPE_BLOB &&
1289 1290 1291
		  field->unireg_check != Field::NEXT_NUMBER &&
                  !((foreign_db_mode || limited_mysql_mode) &&
                    has_now_default));
1292

1293
    if (has_default)
1294 1295
    {
      packet->append(" default ", 9);
1296 1297 1298
      if (has_now_default)
        packet->append("CURRENT_TIMESTAMP",17);
      else if (!field->is_null())
1299
      {                                             // Not null by default
1300
        type.set(tmp, sizeof(tmp), field->charset());
1301
        field->val_str(&type);
1302
	if (type.length())
1303
	{
1304
	  String def_val;
1305 1306 1307 1308 1309
	  /* convert to system_charset_info == utf8 */
	  def_val.copy(type.ptr(), type.length(), field->charset(),
		       system_charset_info);
          append_unescaped(packet, def_val.ptr(), def_val.length());
	}
1310 1311
        else
	  packet->append("''",2);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1312
      }
1313
      else if (field->maybe_null())
1314 1315
        packet->append("NULL", 4);                    // Null as default
      else
1316
        packet->append(tmp);
1317
    }
1318

1319 1320 1321 1322 1323
    if (!foreign_db_mode && !limited_mysql_mode &&
        table->timestamp_field == field && 
        field->unireg_check != Field::TIMESTAMP_DN_FIELD)
      packet->append(" on update CURRENT_TIMESTAMP",28);

1324
    if (field->unireg_check == Field::NEXT_NUMBER && !foreign_db_mode)
1325 1326 1327 1328 1329 1330 1331
      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
1332 1333
  }

1334 1335
  key_info= table->key_info;
  file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
1336
  bzero((char*) &create_info, sizeof(create_info));
1337 1338
  file->update_create_info(&create_info);
  primary_key= table->primary_key;
1339

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1340 1341
  for (uint i=0 ; i < table->keys ; i++,key_info++)
  {
1342 1343
    KEY_PART_INFO *key_part= key_info->key_part;
    bool found_primary=0;
1344
    packet->append(",\n  ", 4);
1345

1346
    if (i == primary_key && !strcmp(key_info->name, primary_key_name))
1347 1348
    {
      found_primary=1;
1349
      packet->append("PRIMARY ", 8);
1350
    }
1351
    else if (key_info->flags & HA_NOSAME)
1352
      packet->append("UNIQUE ", 7);
1353
    else if (key_info->flags & HA_FULLTEXT)
1354
      packet->append("FULLTEXT ", 9);
1355 1356
    else if (key_info->flags & HA_SPATIAL)
      packet->append("SPATIAL ", 8);
1357
    packet->append("KEY ", 4);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1358

1359
    if (!found_primary)
1360
     append_identifier(thd, packet, key_info->name, strlen(key_info->name));
1361

1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373
    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);
    }
1374
    packet->append(" (", 2);
1375

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1376 1377
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
    {
1378
      if (j)
1379
        packet->append(',');
1380

1381
      if (key_part->field)
1382 1383
        append_identifier(thd,packet,key_part->field->field_name,
			  strlen(key_part->field->field_name));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1384
      if (!key_part->field ||
1385 1386 1387
          (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
1388
      {
1389
        buff[0] = '(';
1390 1391 1392
        char* end=int10_to_str((long) key_part->length / 
			       key_part->field->charset()->mbmaxlen,
			       buff + 1,10);
1393 1394
        *end++ = ')';
        packet->append(buff,(uint) (end-buff));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1395 1396 1397 1398
      }
    }
    packet->append(')');
  }
1399

1400 1401 1402 1403
  /*
    Get possible foreign key definitions stored in InnoDB and append them
    to the CREATE TABLE statement
  */
1404

1405
  if ((for_str= file->get_foreign_key_create_info()))
1406 1407 1408
  {
    packet->append(for_str, strlen(for_str));
    file->free_foreign_key_create_info(for_str);
1409 1410 1411
  }

  packet->append("\n)", 2);
1412
  if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
1413
  {
1414 1415 1416 1417
    if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
      packet->append(" TYPE=", 6);
    else
      packet->append(" ENGINE=", 8);
1418 1419
    packet->append(file->table_type());
    
1420 1421 1422
    if (table->table_charset &&
	!(thd->variables.sql_mode & MODE_MYSQL323) &&
	!(thd->variables.sql_mode & MODE_MYSQL40))
1423
    {
1424
      packet->append(" DEFAULT CHARSET=", 17);
1425 1426 1427
      packet->append(table->table_charset->csname);
      if (!(table->table_charset->state & MY_CS_PRIMARY))
      {
1428
	packet->append(" COLLATE=", 9);
1429 1430
	packet->append(table->table_charset->name);
      }
1431
    }
1432

1433 1434
    if (table->min_rows)
    {
1435
      packet->append(" MIN_ROWS=", 10);
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1436 1437
      end= longlong10_to_str(table->min_rows, buff, 10);
      packet->append(buff, (uint) (end- buff));
1438
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1439

1440 1441
    if (table->max_rows)
    {
1442
      packet->append(" MAX_ROWS=", 10);
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1443 1444
      end= longlong10_to_str(table->max_rows, buff, 10);
      packet->append(buff, (uint) (end - buff));
1445
    }
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1446

1447 1448
    if (table->avg_row_length)
    {
1449
      packet->append(" AVG_ROW_LENGTH=", 16);
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1450 1451
      end= longlong10_to_str(table->avg_row_length, buff,10);
      packet->append(buff, (uint) (end - buff));
1452
    }
1453

1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474
    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)
    {
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1475 1476 1477 1478 1479 1480
      uint length;
      length= my_snprintf(buff,sizeof(buff),
			  " RAID_TYPE=%s RAID_CHUNKS=%d RAID_CHUNKSIZE=%ld",
			  my_raid_type(file->raid_type), file->raid_chunks,
			  file->raid_chunksize/RAID_BLOCK_SIZE);
      packet->append(buff, length);
1481
    }
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1482 1483
    append_directory(thd, packet, "DATA",  create_info.data_file_name);
    append_directory(thd, packet, "INDEX", create_info.index_file_name);
1484
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1485 1486 1487 1488 1489
  DBUG_RETURN(0);
}


/****************************************************************************
1490 1491
  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
1492 1493 1494 1495
****************************************************************************/

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

monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
1500 1501
  ulong thread_id;
  time_t start_time;
1502
  uint   command;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515
  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;
1516 1517
  ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
			   PROCESS_LIST_WIDTH);
1518
  Protocol *protocol= thd->protocol;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1519 1520
  DBUG_ENTER("mysqld_list_processes");

1521
  field_list.push_back(new Item_int("Id",0,11));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1522
  field_list.push_back(new Item_empty_string("User",16));
1523
  field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1524 1525 1526
  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));
1527
  field_list.push_back(new Item_return_int("Time",7, FIELD_TYPE_LONG));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1528 1529 1530 1531
  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;
1532
  if (protocol->send_fields(&field_list,1))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1533 1534 1535 1536 1537 1538 1539 1540 1541
    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++))
    {
1542
      struct st_my_thread_var *mysys_var;
1543
      if ((tmp->vio_ok() || tmp->system_thread) &&
1544
          (!user || (tmp->user && !strcmp(tmp->user,user))))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1545
      {
1546 1547 1548
        thread_info *thd_info=new thread_info;

        thd_info->thread_id=tmp->thread_id;
1549 1550 1551
        thd_info->user=thd->strdup(tmp->user ? tmp->user :
				   (tmp->system_thread ?
				    "system user" : "unauthenticated user"));
1552
	if (tmp->peer_port && (tmp->host || tmp->ip) && thd->host_or_ip[0])
1553 1554
	{
	  if ((thd_info->host= thd->alloc(LIST_PROCESS_HOST_LEN+1)))
1555
	    my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN,
1556
			"%s:%u", tmp->host_or_ip, tmp->peer_port);
1557 1558
	}
	else
1559
	  thd_info->host= thd->strdup(tmp->host_or_ip);
1560 1561 1562
        if ((thd_info->db=tmp->db))             // Safe test
          thd_info->db=thd->strdup(thd_info->db);
        thd_info->command=(int) tmp->command;
1563 1564
        if ((mysys_var= tmp->mysys_var))
          pthread_mutex_lock(&mysys_var->mutex);
1565
        thd_info->proc_info= (char*) (tmp->killed ? "Killed" : 0);
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1566
#ifndef EMBEDDED_LIBRARY
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576
        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);
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1577 1578 1579
#else
        thd_info->state_info= (char*)"Writing to net";
#endif
1580 1581
        if (mysys_var)
          pthread_mutex_unlock(&mysys_var->mutex);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1582 1583

#if !defined(DONT_USE_THR_ALARM) && ! defined(SCO)
1584 1585
        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
1586
#endif
1587 1588 1589
#ifdef EXTRA_DEBUG
        thd_info->start_time= tmp->time_after_lock;
#else
1590
        thd_info->start_time= tmp->start_time;
1591
#endif
1592 1593 1594
        thd_info->query=0;
        if (tmp->query)
        {
heikki@hundin.mysql.fi's avatar
heikki@hundin.mysql.fi committed
1595 1596 1597 1598 1599
	  /* 
            query_length is always set to 0 when we set query = NULL; see
	    the comment in sql_class.h why this prevents crashes in possible
            races with query_length
          */
1600
          uint length= min(max_query_length, tmp->query_length);
1601
          thd_info->query=(char*) thd->strmake(tmp->query,length);
1602 1603
        }
        thread_infos.append(thd_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1604 1605 1606 1607 1608 1609
      }
    }
  }
  VOID(pthread_mutex_unlock(&LOCK_thread_count));

  thread_info *thd_info;
1610
  time_t now= time(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1611 1612
  while ((thd_info=thread_infos.get()))
  {
1613 1614
    protocol->prepare_for_resend();
    protocol->store((ulonglong) thd_info->thread_id);
1615 1616 1617
    protocol->store(thd_info->user, system_charset_info);
    protocol->store(thd_info->host, system_charset_info);
    protocol->store(thd_info->db, system_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1618
    if (thd_info->proc_info)
1619
      protocol->store(thd_info->proc_info, system_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1620
    else
1621
      protocol->store(command_name[thd_info->command], system_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1622
    if (thd_info->start_time)
1623
      protocol->store((uint32) (now - thd_info->start_time));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1624
    else
1625
      protocol->store_null();
1626 1627
    protocol->store(thd_info->state_info, system_charset_info);
    protocol->store(thd_info->query, system_charset_info);
1628
    if (protocol->write())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1629 1630
      break; /* purecov: inspected */
  }
1631
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1632 1633 1634 1635
  DBUG_VOID_RETURN;
}

/*****************************************************************************
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1636
  Status functions
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1637 1638
*****************************************************************************/

1639 1640 1641 1642
static bool write_collation(Protocol *protocol, CHARSET_INFO *cs)
{
  protocol->prepare_for_resend();
  protocol->store(cs->name, system_charset_info);
1643
  protocol->store(cs->csname, system_charset_info);
1644
  protocol->store_short((longlong) cs->number);
1645 1646
  protocol->store((cs->state & MY_CS_PRIMARY) ? "Yes" : "",system_charset_info);
  protocol->store((cs->state & MY_CS_COMPILED)? "Yes" : "",system_charset_info);
1647 1648 1649 1650 1651
  protocol->store_short((longlong) cs->strxfrm_multiply);
  return protocol->write();
}

int mysqld_show_collations(THD *thd, const char *wild)
1652 1653
{
  char buff[8192];
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1654
  String packet2(buff,sizeof(buff),thd->charset());
1655
  List<Item> field_list;
1656
  CHARSET_INFO **cs;
1657
  Protocol *protocol= thd->protocol;
1658

1659 1660
  DBUG_ENTER("mysqld_show_charsets");

1661
  field_list.push_back(new Item_empty_string("Collation",30));
1662
  field_list.push_back(new Item_empty_string("Charset",30));
1663
  field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT));
1664 1665
  field_list.push_back(new Item_empty_string("Default",30));
  field_list.push_back(new Item_empty_string("Compiled",30));
1666
  field_list.push_back(new Item_return_int("Sortlen",3, FIELD_TYPE_SHORT));
1667

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

1671
  for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ )
1672
  {
1673
    CHARSET_INFO **cl;
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1674 1675 1676
    if (!cs[0] || !(cs[0]->state & MY_CS_AVAILABLE) || 
        !(cs[0]->state & MY_CS_PRIMARY))
      continue;
1677 1678
    for ( cl= all_charsets; cl < all_charsets+255 ;cl ++)
    {
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1679 1680
      if (!cl[0] || !(cl[0]->state & MY_CS_AVAILABLE) || 
          !my_charset_same(cs[0],cl[0]))
1681
	continue;
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1682
      if (!(wild && wild[0] &&
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1683
	  wild_case_compare(system_charset_info,cl[0]->name,wild)))
1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699
      {
        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);
1700
  protocol->store(cs->comment ? cs->comment : "", system_charset_info);
1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716
  protocol->store(cs->name, system_charset_info);
  protocol->store_short((longlong) cs->mbmaxlen);
  return protocol->write();
}

int mysqld_show_charsets(THD *thd, const char *wild)
{
  char buff[8192];
  String packet2(buff,sizeof(buff),thd->charset());
  List<Item> field_list;
  CHARSET_INFO **cs;
  Protocol *protocol= thd->protocol;

  DBUG_ENTER("mysqld_show_charsets");

  field_list.push_back(new Item_empty_string("Charset",30));
1717
  field_list.push_back(new Item_empty_string("Description",60));
1718 1719 1720 1721 1722 1723 1724 1725
  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++ )
  {
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1726 1727 1728 1729
    if (cs[0] && (cs[0]->state & MY_CS_PRIMARY) && 
        (cs[0]->state & MY_CS_AVAILABLE) &&
        !(wild && wild[0] &&
        wild_case_compare(system_charset_info,cs[0]->csname,wild)))
1730
    {
1731
      if (write_charset(protocol, cs[0]))
1732
	goto err;
1733 1734
    }
  }
1735
  send_eof(thd); 
1736 1737 1738 1739 1740
  DBUG_RETURN(0);
err:
  DBUG_RETURN(1);
}

monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1741
  
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1742

1743
int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
1744 1745
		enum enum_var_type value_type,
		pthread_mutex_t *mutex)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1746
{
1747
  char buff[1024];
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1748
  List<Item> field_list;
1749
  Protocol *protocol= thd->protocol;
1750
  LEX_STRING null_lex_str;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1751
  DBUG_ENTER("mysqld_show");
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1752

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1753 1754
  field_list.push_back(new Item_empty_string("Variable_name",30));
  field_list.push_back(new Item_empty_string("Value",256));
1755
  if (protocol->send_fields(&field_list,1))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1756
    DBUG_RETURN(1); /* purecov: inspected */
1757
  null_lex_str.str= 0;				// For sys_var->value_ptr()
1758
  null_lex_str.length= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1759

1760
  pthread_mutex_lock(mutex);
1761
  for (; variables->name; variables++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1762
  {
1763
    if (!(wild && wild[0] && wild_case_compare(system_charset_info,
1764
					       variables->name,wild)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1765
    {
1766
      protocol->prepare_for_resend();
1767
      protocol->store(variables->name, system_charset_info);
1768 1769
      SHOW_TYPE show_type=variables->type;
      char *value=variables->value;
1770 1771 1772
      const char *pos, *end;
      long nr;

1773 1774 1775
      if (show_type == SHOW_SYS)
      {
	show_type= ((sys_var*) value)->type();
1776 1777
	value=     (char*) ((sys_var*) value)->value_ptr(thd, value_type,
							 &null_lex_str);
1778 1779
      }

1780
      pos= end= buff;
1781
      switch (show_type) {
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1782 1783
      case SHOW_LONG:
      case SHOW_LONG_CONST:
1784
	end= int10_to_str(*(long*) value, buff, 10);
1785 1786
        break;
      case SHOW_LONGLONG:
1787
	end= longlong10_to_str(*(longlong*) value, buff, 10);
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1788
	break;
1789
      case SHOW_HA_ROWS:
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1790
        end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
1791
        break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1792
      case SHOW_BOOL:
1793
	end= strmov(buff, *(bool*) value ? "ON" : "OFF");
1794
        break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1795
      case SHOW_MY_BOOL:
1796
	end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
1797
        break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1798 1799
      case SHOW_INT_CONST:
      case SHOW_INT:
1800
	end= int10_to_str((long) *(uint32*) value, buff, 10);
1801
        break;
1802 1803
      case SHOW_HAVE:
      {
1804
	SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
1805 1806
	pos= show_comp_option_name[(int) tmp];
	end= strend(pos);
1807 1808
        break;
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1809
      case SHOW_CHAR:
gluh@gluh.mysql.r18.ru's avatar
gluh@gluh.mysql.r18.ru committed
1810 1811 1812 1813
      {
        if (!(pos= value))
          pos= "";
        end= strend(pos);
1814
        break;
gluh@gluh.mysql.r18.ru's avatar
gluh@gluh.mysql.r18.ru committed
1815
       }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1816
      case SHOW_STARTTIME:
1817 1818
	nr= (long) (thd->query_start() - start_time);
	end= int10_to_str(nr, buff, 10);
1819
        break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1820
      case SHOW_QUESTION:
1821
	end= int10_to_str((long) thd->query_id, buff, 10);
1822
        break;
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1823
#ifdef HAVE_REPLICATION
1824
      case SHOW_RPL_STATUS:
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
1825
	end= strmov(buff, rpl_status_type[(int)rpl_status]);
1826
	break;
1827 1828
      case SHOW_SLAVE_RUNNING:
      {
1829
	pthread_mutex_lock(&LOCK_active_mi);
1830 1831
	end= strmov(buff, (active_mi->slave_running &&
			   active_mi->rli.slave_running) ? "ON" : "OFF");
1832
	pthread_mutex_unlock(&LOCK_active_mi);
1833 1834
	break;
      }
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1835
#endif /* HAVE_REPLICATION */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1836
      case SHOW_OPENTABLES:
1837
	end= int10_to_str((long) cached_tables(), buff, 10);
1838
        break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1839
      case SHOW_CHAR_PTR:
1840
      {
1841 1842 1843 1844
        if (!(pos= *(char**) value))
          pos= "";
        end= strend(pos);
        break;
1845
      }
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1846
#ifdef HAVE_OPENSSL
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1847
	/* First group - functions relying on CTX */
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1848
      case SHOW_SSL_CTX_SESS_ACCEPT:
1849 1850
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_accept(ssl_acceptor_fd->
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1851
						      ssl_context)),
1852
			  buff, 10);
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1853 1854
        break;
      case SHOW_SSL_CTX_SESS_ACCEPT_GOOD:
1855 1856
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_accept_good(ssl_acceptor_fd->
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1857
							   ssl_context)),
1858
			  buff, 10);
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1859
        break;
1860
      case SHOW_SSL_CTX_SESS_CONNECT_GOOD:
1861 1862
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_connect_good(ssl_acceptor_fd->
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1863
							    ssl_context)),
1864
			  buff, 10);
1865
        break;
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1866
      case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE:
1867
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1868
				  SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context)),
1869
			  buff, 10);
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1870
        break;
1871
      case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE:
1872
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1873
				  SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context)),
1874
			  buff, 10);
1875
        break;
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1876
      case SHOW_SSL_CTX_SESS_CB_HITS:
1877 1878
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_cb_hits(ssl_acceptor_fd->
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1879
						       ssl_context)),
1880
			  buff, 10);
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1881
        break;
1882
      case SHOW_SSL_CTX_SESS_HITS:
1883 1884
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_hits(ssl_acceptor_fd->
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1885
						    ssl_context)),
1886
			  buff, 10);
1887 1888
        break;
      case SHOW_SSL_CTX_SESS_CACHE_FULL:
1889 1890
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_cache_full(ssl_acceptor_fd->
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1891
							  ssl_context)),
1892
			  buff, 10);
1893 1894
        break;
      case SHOW_SSL_CTX_SESS_MISSES:
1895 1896
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
				  SSL_CTX_sess_misses(ssl_acceptor_fd->
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1897
						      ssl_context)),
1898
			  buff, 10);
1899 1900
        break;
      case SHOW_SSL_CTX_SESS_TIMEOUTS:
1901
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1902
				  SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context)),
1903
			  buff,10);
1904
        break;
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1905
      case SHOW_SSL_CTX_SESS_NUMBER:
1906
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1907
				  SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context)),
1908
			  buff,10);
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1909
        break;
1910
      case SHOW_SSL_CTX_SESS_CONNECT:
1911
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1912
				  SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)),
1913
			  buff,10);
1914
        break;
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1915
      case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE:
1916
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1917
				  SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context)),
1918
				  buff,10);
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1919 1920
        break;
      case SHOW_SSL_CTX_GET_VERIFY_MODE:
1921
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1922
				  SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)),
1923
			  buff,10);
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1924 1925
        break;
      case SHOW_SSL_CTX_GET_VERIFY_DEPTH:
1926
	end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1927
				  SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)),
1928
			  buff,10);
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1929 1930
        break;
      case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE:
1931 1932
	if (!ssl_acceptor_fd)
	{
1933 1934
	  pos= "NONE";
	  end= pos+4;
1935 1936
	  break;
	}
1937
	switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1938 1939
	{
          case SSL_SESS_CACHE_OFF:
1940
            pos= "OFF";
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1941 1942
	    break;
          case SSL_SESS_CACHE_CLIENT:
1943
            pos= "CLIENT";
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1944 1945
	    break;
          case SSL_SESS_CACHE_SERVER:
1946
            pos= "SERVER";
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1947 1948
	    break;
          case SSL_SESS_CACHE_BOTH:
1949
            pos= "BOTH";
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1950 1951
	    break;
          case SSL_SESS_CACHE_NO_AUTO_CLEAR:
1952
            pos= "NO_AUTO_CLEAR";
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1953 1954
	    break;
          case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
1955
            pos= "NO_INTERNAL_LOOKUP";
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1956 1957
	    break;
	  default:
1958
            pos= "Unknown";
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1959 1960
	    break;
	}
1961
	end= strend(pos);
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1962
        break;
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1963 1964
	/* First group - functions relying on SSL */
      case SHOW_SSL_GET_VERSION:
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1965 1966
	pos= (thd->net.vio->ssl_arg ?
	      SSL_get_version((SSL*) thd->net.vio->ssl_arg) : "");
1967
	end= strend(pos);
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1968 1969
        break;
      case SHOW_SSL_SESSION_REUSED:
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1970 1971 1972 1973 1974
	end= int10_to_str((long) (thd->net.vio->ssl_arg ?
				  SSL_session_reused((SSL*) thd->net.vio->
						     ssl_arg) :
				  0),
			  buff, 10);
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1975 1976
        break;
      case SHOW_SSL_GET_DEFAULT_TIMEOUT:
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1977 1978 1979 1980 1981
	end= int10_to_str((long) (thd->net.vio->ssl_arg ?
				  SSL_get_default_timeout((SSL*) thd->net.vio->
							  ssl_arg) :
				  0),
			  buff, 10);
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1982 1983
        break;
      case SHOW_SSL_GET_VERIFY_MODE:
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1984 1985 1986 1987 1988
	end= int10_to_str((long) (thd->net.vio->ssl_arg ?
				  SSL_get_verify_mode((SSL*) thd->net.vio->
						      ssl_arg):
				  0),
			  buff, 10);
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1989 1990
        break;
      case SHOW_SSL_GET_VERIFY_DEPTH:
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1991 1992 1993 1994 1995
	end= int10_to_str((long) (thd->net.vio->ssl_arg ?
				  SSL_get_verify_depth((SSL*) thd->net.vio->
						       ssl_arg):
				  0),
			  buff, 10);
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
1996 1997
        break;
      case SHOW_SSL_GET_CIPHER:
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1998 1999
	pos= (thd->net.vio->ssl_arg ?
	      SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : "" );
2000
	end= strend(pos);
2001
	break;
2002
      case SHOW_SSL_GET_CIPHER_LIST:
2003
	if (thd->net.vio->ssl_arg)
2004
	{
2005
	  char *to= buff;
2006
	  for (int i=0 ; i++ ;)
2007
	  {
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2008
	    const char *p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i);
2009 2010
	    if (p == NULL) 
	      break;
2011 2012
	    to= strmov(to, p);
	    *to++= ':';
2013
	  }
2014 2015 2016
	  if (to != buff)
	    to--;				// Remove last ':'
	  end= to;
2017
        }
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
2018
        break;
tonu@x153.internalnet's avatar
tonu@x153.internalnet committed
2019 2020

#endif /* HAVE_OPENSSL */
2021
      case SHOW_KEY_CACHE_LONG:
2022
      case SHOW_KEY_CACHE_CONST_LONG:
2023 2024 2025
	value= (value-(char*) &dflt_key_cache_var)+ (char*) sql_key_cache;
	end= int10_to_str(*(long*) value, buff, 10);
        break;
2026 2027
      case SHOW_UNDEF:				// Show never happen
      case SHOW_SYS:
2028
	break;					// Return empty string
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
2029 2030
      default:
	break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2031
      }
2032
      if (protocol->store(pos, (uint32) (end - pos), system_charset_info) ||
2033
	  protocol->write())
2034
        goto err;                               /* purecov: inspected */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2035 2036
    }
  }
2037
  pthread_mutex_unlock(mutex);
2038
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2039 2040 2041
  DBUG_RETURN(0);

 err:
2042
  pthread_mutex_unlock(mutex);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2043 2044 2045 2046
  DBUG_RETURN(1);
}

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