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

static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
35 36
                               "grant_types",
                               grant_names};
bk@work.mysql.com's avatar
bk@work.mysql.com committed
37 38

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

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

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

45 46 47 48
/*
  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
49

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

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

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

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

92

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

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

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

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

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

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

131

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

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

172 173 174 175
/***************************************************************************
** List all table types supported 
***************************************************************************/

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


SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES;

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

202

203 204 205
int mysqld_show_table_types(THD *thd)
{
  List<Item> field_list;
206
  Protocol *protocol= thd->protocol;
207 208 209 210
  DBUG_ENTER("mysqld_show_table_types");

  field_list.push_back(new Item_empty_string("Type",10));
  field_list.push_back(new Item_empty_string("Support",10));
211
  field_list.push_back(new Item_empty_string("Comment",80));
212

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

216 217
  const char *default_type_name=
    ha_table_typelib.type_names[thd->variables.table_type];
218

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

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

238

239
/***************************************************************************
240
 List all privileges supported
241 242
***************************************************************************/

243 244 245 246
struct show_privileges_st {
  const char *privilege;
  const char *context;
  const char *comment;
247 248
};

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

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


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

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

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


/***************************************************************************
302
  List all column types
303 304
***************************************************************************/

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

/* TODO: Add remaning types */

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

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

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

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


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

399 400
  if (wild && !wild[0])
    wild=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
401 402 403 404 405
  bzero((char*) &table_list,sizeof(table_list));

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

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

463

bk@work.mysql.com's avatar
bk@work.mysql.com committed
464
/***************************************************************************
465
 Extended version of mysqld_show_tables
bk@work.mysql.com's avatar
bk@work.mysql.com committed
466 467 468 469 470 471 472 473 474 475
***************************************************************************/

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;
476 477
  Protocol *protocol= thd->protocol;
  TIME time;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
  DBUG_ENTER("mysqld_extend_show_tables");

  (void) sprintf(path,"%s/%s",mysql_data_home,db);
  (void) unpack_dirname(path,path);
  field_list.push_back(item=new Item_empty_string("Name",NAME_LEN));
  field_list.push_back(item=new Item_empty_string("Type",10));
  item->maybe_null=1;
  field_list.push_back(item=new Item_empty_string("Row_format",10));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Rows",(longlong) 1,21));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Avg_row_length",(int32) 0,21));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Data_length",(longlong) 1,21));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Max_data_length",(longlong) 1,21));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Index_length",(longlong) 1,21));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Data_free",(longlong) 1,21));
  item->maybe_null=1;
  field_list.push_back(item=new Item_int("Auto_increment",(longlong) 1,21));
  item->maybe_null=1;
  field_list.push_back(item=new Item_datetime("Create_time"));
  item->maybe_null=1;
  field_list.push_back(item=new Item_datetime("Update_time"));
  item->maybe_null=1;
  field_list.push_back(item=new Item_datetime("Check_time"));
  item->maybe_null=1;
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
507
  field_list.push_back(item=new Item_empty_string("Collation",32));
508
  item->maybe_null=1;
serg@serg.mylan's avatar
serg@serg.mylan committed
509 510
  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
511 512 513
  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));
514
  item->maybe_null=1;
515
  if (protocol->send_fields(&field_list,1))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
516 517 518 519
    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
520
  List_iterator_fast<char> it(files);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
521 522 523 524
  while ((file_name=it++))
  {
    TABLE_LIST table_list;
    bzero((char*) &table_list,sizeof(table_list));
525
    protocol->prepare_for_resend();
526
    protocol->store(file_name, system_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
527
    table_list.db=(char*) db;
528
    table_list.real_name= table_list.alias= file_name;
529
    if (lower_case_table_names)
530
      my_casedn_str(files_charset_info, file_name);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
531 532
    if (!(table = open_ltable(thd, &table_list, TL_READ)))
    {
533
      for (uint i=2 ; i < field_list.elements ; i++)
534
        protocol->store_null();
535
      // Send error to Comment field
536
      protocol->store(thd->net.last_error, system_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
537 538 539 540 541
      thd->net.last_error[0]=0;
    }
    else
    {
      struct tm tm_tmp;
542
      const char *str;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
543 544
      handler *file=table->file;
      file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK);
545
      protocol->store(file->table_type(), system_charset_info);
546 547 548 549
      str= ((table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ?
	    "Compressed" :
	    (table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
	    "Dynamic" : "Fixed");
550
      protocol->store(str, system_charset_info);
551 552 553
      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
554
      if (file->max_data_file_length)
555
        protocol->store((ulonglong) file->max_data_file_length);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
556
      else
557 558 559
        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
560 561
      if (table->found_next_number_field)
      {
562 563 564
        table->next_number_field=table->found_next_number_field;
        table->next_number_field->reset();
        file->update_auto_increment();
565
        protocol->store(table->next_number_field->val_int());
566
        table->next_number_field=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
567 568
      }
      else
569
        protocol->store_null();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
570
      if (!file->create_time)
571
        protocol->store_null();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
572 573
      else
      {
574
        localtime_r(&file->create_time,&tm_tmp);
575 576
	localtime_to_TIME(&time, &tm_tmp);
        protocol->store(&time);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
577 578
      }
      if (!file->update_time)
579
        protocol->store_null();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
580 581
      else
      {
582
        localtime_r(&file->update_time,&tm_tmp);
583 584
	localtime_to_TIME(&time, &tm_tmp);
        protocol->store(&time);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
585 586
      }
      if (!file->check_time)
587
        protocol->store_null();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
588 589
      else
      {
590
        localtime_r(&file->check_time,&tm_tmp);
591 592
	localtime_to_TIME(&time, &tm_tmp);
        protocol->store(&time);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
593
      }
594
      str= (table->table_charset ? table->table_charset->name : "default");
595
      protocol->store(str, system_charset_info);
serg@serg.mylan's avatar
serg@serg.mylan committed
596 597 598 599
      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
600
      {
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626
        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)
627
          ptr=strxmov(ptr, " row_format=", ha_row_type[(uint) table->row_type],
628 629 630 631 632 633 634 635
                      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);
        }
636
        protocol->store(option_buff+1,
637 638
			(ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1)
			, system_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
639
      }
640 641
      {
	char *comment=table->file->update_table_comment(table->comment);
642
	protocol->store(comment, system_charset_info);
643 644 645
	if (comment != table->comment)
	  my_free(comment,MYF(0));
      }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
646 647
      close_thread_tables(thd,0);
    }
648
    if (protocol->write())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
649 650
      DBUG_RETURN(-1);
  }
651
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
652 653 654 655 656
  DBUG_RETURN(0);
}


/***************************************************************************
657
** List all columns in a table_list->real_name
bk@work.mysql.com's avatar
bk@work.mysql.com committed
658
***************************************************************************/
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
659

bk@work.mysql.com's avatar
bk@work.mysql.com committed
660
int
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
661 662
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
663 664 665 666
{
  TABLE *table;
  handler *file;
  char tmp[MAX_FIELD_WIDTH];
667
  Item *item;
668
  Protocol *protocol= thd->protocol;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
669 670
  DBUG_ENTER("mysqld_show_fields");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
671
                      table_list->real_name));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
672 673 674

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

  Field **ptr,*field;
tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
705
  String *packet= &thd->packet;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
706 707
  for (ptr=table->field; (field= *ptr) ; ptr++)
  {
708 709
    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
710 711 712
    {
#ifdef NOT_USED
      if (thd->col_access & TABLE_ACLS ||
713 714
          ! check_grant_column(thd,table,field->field_name,
                               (uint) strlen(field->field_name),1))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
715 716
#endif
      {
717 718
        byte *pos;
        uint flags=field->flags;
719
        String type(tmp,sizeof(tmp), system_charset_info);
720 721 722
        uint col_access;
        bool null_default_value=0;

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

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

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

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

789

bk@work.mysql.com's avatar
bk@work.mysql.com committed
790 791 792 793
int
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
  TABLE *table;
794 795 796
  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
797 798
  DBUG_ENTER("mysqld_show_create");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
799
                      table_list->real_name));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
800

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

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

bk@work.mysql.com's avatar
bk@work.mysql.com committed
811 812
  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
813
  // 1024 is for not to confuse old clients
814
  field_list.push_back(new Item_empty_string("Create Table",
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
815
					     max(buffer.length(),1024)));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
816

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


tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
832 833 834
int
mysqld_show_logs(THD *thd)
{
835 836
  List<Item> field_list;
  Protocol *protocol= thd->protocol;
tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
837 838 839 840 841 842
  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));

843
  if (protocol->send_fields(&field_list,1))
tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
844 845
    DBUG_RETURN(1);

846
#ifdef HAVE_BERKELEY_DB
847
  if (!berkeley_skip && berkeley_show_logs(protocol))
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
848
    DBUG_RETURN(-1);
849
#endif
tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
850

851
  send_eof(thd);
tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
852 853 854 855
  DBUG_RETURN(0);
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
856 857 858 859
int
mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
{
  TABLE *table;
860
  Protocol *protocol= thd->protocol;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
861 862
  DBUG_ENTER("mysqld_show_keys");
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
863
                      table_list->real_name));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
864 865 866

  if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
  {
867
    send_error(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
868 869 870 871 872 873
    DBUG_RETURN(1);
  }

  List<Item> field_list;
  Item *item;
  field_list.push_back(new Item_empty_string("Table",NAME_LEN));
874
  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
875
  field_list.push_back(new Item_empty_string("Key_name",NAME_LEN));
876
  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
877 878 879
  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;
880
  field_list.push_back(item=new Item_int("Cardinality",0,21));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
881
  item->maybe_null=1;
882 883
  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
884 885 886
  item->maybe_null=1;
  field_list.push_back(item=new Item_empty_string("Packed",10));
  item->maybe_null=1;
887 888
  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
889 890 891
  field_list.push_back(new Item_empty_string("Comment",255));
  item->maybe_null=1;

892
  if (protocol->send_fields(&field_list,1))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
893 894
    DBUG_RETURN(1);

tim@cane.mysql.fi's avatar
tim@cane.mysql.fi committed
895
  String *packet= &thd->packet;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
896 897 898 899 900
  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;
901
    const char *str;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
902 903
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
    {
904
      protocol->prepare_for_resend();
905
      protocol->store(table->table_name, system_charset_info);
906
      protocol->store_tiny((longlong) ((key_info->flags & HA_NOSAME) ? 0 :1));
907
      protocol->store(key_info->name, system_charset_info);
908 909 910
      protocol->store_tiny((longlong) (j+1));
      str=(key_part->field ? key_part->field->field_name :
	   "?unknown field?");
911
      protocol->store(str, system_charset_info);
912
      if (table->file->index_flags(i) & HA_READ_ORDER)
913
        protocol->store(((key_part->key_part_flag & HA_REVERSE_SORT) ?
914
			 "D" : "A"), 1, system_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
915
      else
916
        protocol->store_null(); /* purecov: inspected */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
917 918 919
      KEY *key=table->key_info+i;
      if (key->rec_per_key[j])
      {
920
        ha_rows records=(table->file->records / key->rec_per_key[j]);
921
        protocol->store((ulonglong) records);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
922 923
      }
      else
924
        protocol->store_null();
925 926

      /* Check if we have a key part that only uses part of the field */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
927
      if (!key_part->field ||
928 929
          key_part->length !=
          table->field[key_part->fieldnr-1]->key_length())
930
        protocol->store_tiny((longlong) key_part->length);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
931
      else
932 933
        protocol->store_null();
      protocol->store_null();                   // No pack_information yet
934 935 936

      /* Null flag */
      uint flags= key_part->field ? key_part->field->flags : 0;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
937
      char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
938 939
      protocol->store((const char*) pos, system_charset_info);
      protocol->store(table->file->index_type(i), system_charset_info);
940
      /* Comment */
941
      if (!table->keys_in_use.is_set(i))
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
942
	protocol->store("disabled",8, system_charset_info);
943
      else
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
944
        protocol->store("", 0, system_charset_info);
945
      if (protocol->write())
946
        DBUG_RETURN(1); /* purecov: inspected */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
947 948
    }
  }
949
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
950 951 952 953 954
  DBUG_RETURN(0);
}


/****************************************************************************
955 956
  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
957 958 959 960 961 962 963 964 965 966 967
****************************************************************************/

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)))
  {
968
    send_error(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
969 970 971 972 973 974 975
    DBUG_VOID_RETURN;
  }
  List<Item> field_list;

  Field **ptr,*field;
  for (ptr=table->field ; (field= *ptr); ptr++)
  {
976 977
    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
978 979
      field_list.push_back(new Item_field(field));
  }
980
  restore_record(table,default_values);              // Get empty record
981
  if (thd->protocol->send_fields(&field_list,2))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
982
    DBUG_VOID_RETURN;
983
  net_flush(&thd->net);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
984 985 986
  DBUG_VOID_RETURN;
}

987

bk@work.mysql.com's avatar
bk@work.mysql.com committed
988 989 990
int
mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
{
991 992
  Protocol *protocol= thd->protocol;
  String *packet= protocol->storage_packet();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
993 994
  DBUG_ENTER("mysqld_dump_create_info");
  DBUG_PRINT("enter",("table: %s",table->real_name));
995

996 997
  protocol->prepare_for_resend();
  if (store_create_info(thd, table, packet))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
998
    DBUG_RETURN(-1);
999

1000 1001
  //if (protocol->convert)
  //  protocol->convert->convert((char*) packet->ptr(), packet->length());
1002
  if (fd < 0)
1003
  {
1004
    if (protocol->write())
1005
      DBUG_RETURN(-1);
1006
    net_flush(&thd->net);
1007
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1008
  else
1009
  {
1010 1011
    if (my_write(fd, (const byte*) packet->ptr(), packet->length(),
		 MYF(MY_WME)))
1012 1013
      DBUG_RETURN(-1);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1014 1015
  DBUG_RETURN(0);
}
1016

1017

1018 1019
void
append_identifier(THD *thd, String *packet, const char *name, uint length)
1020
{
1021
  char qtype;
1022
  if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
1023 1024 1025 1026
    qtype= '\"';
  else
    qtype= '`';

1027 1028
  if (thd->options & OPTION_QUOTE_SHOW_CREATE)
  {
1029
    packet->append(&qtype, 1);
1030
    packet->append(name, length, system_charset_info);
1031
    packet->append(&qtype, 1);
1032 1033 1034
  }
  else
  {
1035
    packet->append(name, length, system_charset_info);
1036 1037 1038
  }
}

1039 1040 1041 1042 1043 1044 1045

/* 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
1046
  if (filename && !(thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
  {
    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
1058
#define LIST_PROCESS_HOST_LEN 64
1059

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1060
static int
1061
store_create_info(THD *thd, TABLE *table, String *packet)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1062
{
1063 1064
  List<Item> field_list;
  char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end;
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1065
  String type(tmp, sizeof(tmp),&my_charset_bin);
1066 1067 1068 1069 1070
  Field **ptr,*field;
  uint primary_key;
  KEY *key_info;
  handler *file= table->file;
  HA_CREATE_INFO create_info;
1071 1072 1073 1074
  my_bool foreign_db_mode=    (thd->variables.sql_mode & (MODE_POSTGRESQL |
							  MODE_ORACLE |
							  MODE_MSSQL |
							  MODE_DB2 |
1075
							  MODE_MAXDB |
1076 1077 1078 1079
							  MODE_ANSI)) != 0;
  my_bool limited_mysql_mode= (thd->variables.sql_mode &
			       (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
				MODE_MYSQL40)) != 0;
1080

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

1084
  restore_record(table,default_values); // Get empty record
1085

1086 1087 1088 1089
  if (table->tmp_table)
    packet->append("CREATE TEMPORARY TABLE ", 23);
  else
    packet->append("CREATE TABLE ", 13);
1090
  append_identifier(thd,packet, table->real_name, strlen(table->real_name));
1091
  packet->append(" (\n", 3);
1092

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1093 1094
  for (ptr=table->field ; (field= *ptr); ptr++)
  {
1095 1096 1097
    bool has_default;
    uint flags = field->flags;

1098
    if (ptr != table->field)
1099
      packet->append(",\n", 2);
1100

1101
    packet->append("  ", 2);
1102
    append_identifier(thd,packet,field->field_name, strlen(field->field_name));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1103 1104
    packet->append(' ');
    // check for surprises from the previous call to Field::sql_type()
1105
    if (type.ptr() != tmp)
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1106
      type.set(tmp, sizeof(tmp),&my_charset_bin);
1107

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1108 1109
    field->sql_type(type);
    packet->append(type.ptr(),type.length());
1110

1111
    if (field->has_charset())
1112
    {
1113
      if (field->charset() == &my_charset_bin)
1114
        packet->append(" binary", 7);
1115 1116 1117 1118
      else if (!limited_mysql_mode && !foreign_db_mode)
      {
	if (field->charset() != table->table_charset)
	{
1119
	  packet->append(" character set ", 15);
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
	  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);
	}
      }
1132
    }
1133

1134 1135
    if (flags & NOT_NULL_FLAG)
      packet->append(" NOT NULL", 9);
1136

1137 1138 1139
    has_default= (field->type() != FIELD_TYPE_BLOB &&
		  field->type() != FIELD_TYPE_TIMESTAMP &&
		  field->unireg_check != Field::NEXT_NUMBER);
1140

1141
    if (has_default)
1142 1143
    {
      packet->append(" default ", 9);
1144
      if (!field->is_null())
1145
      {                                             // Not null by default
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1146
        type.set(tmp,sizeof(tmp),&my_charset_bin);
1147
        field->val_str(&type,&type);
1148
	if (type.length())
1149 1150 1151
          append_unescaped(packet, type.ptr(), type.length());
        else
	  packet->append("''",2);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1152
      }
1153
      else if (field->maybe_null())
1154 1155 1156 1157
        packet->append("NULL", 4);                    // Null as default
      else
        packet->append(tmp,0);
    }
1158

1159
    if (field->unireg_check == Field::NEXT_NUMBER && !foreign_db_mode)
1160 1161 1162 1163 1164 1165 1166
      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
1167 1168
  }

1169 1170
  key_info= table->key_info;
  file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
1171
  bzero((char*) &create_info, sizeof(create_info));
1172 1173
  file->update_create_info(&create_info);
  primary_key= table->primary_key;
1174

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1175 1176
  for (uint i=0 ; i < table->keys ; i++,key_info++)
  {
1177 1178
    KEY_PART_INFO *key_part= key_info->key_part;
    bool found_primary=0;
1179
    packet->append(",\n  ", 4);
1180

1181 1182 1183
    if (i == primary_key && !strcmp(key_info->name,"PRIMARY"))
    {
      found_primary=1;
1184
      packet->append("PRIMARY ", 8);
1185
    }
1186
    else if (key_info->flags & HA_NOSAME)
1187
      packet->append("UNIQUE ", 7);
1188
    else if (key_info->flags & HA_FULLTEXT)
1189
      packet->append("FULLTEXT ", 9);
1190 1191
    else if (key_info->flags & HA_SPATIAL)
      packet->append("SPATIAL ", 8);
1192
    packet->append("KEY ", 4);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1193

1194
    if (!found_primary)
1195
     append_identifier(thd, packet, key_info->name, strlen(key_info->name));
1196

1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208
    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);
    }
1209
    packet->append(" (", 2);
1210

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1211 1212
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
    {
1213
      if (j)
1214
        packet->append(',');
1215

1216
      if (key_part->field)
1217 1218
        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
1219
      if (!key_part->field ||
1220 1221 1222
          (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
1223
      {
1224
        buff[0] = '(';
1225 1226 1227
        char* end=int10_to_str((long) key_part->length / 
			       key_part->field->charset()->mbmaxlen,
			       buff + 1,10);
1228 1229
        *end++ = ')';
        packet->append(buff,(uint) (end-buff));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1230 1231 1232 1233
      }
    }
    packet->append(')');
  }
1234

1235 1236 1237 1238
  /*
    Get possible foreign key definitions stored in InnoDB and append them
    to the CREATE TABLE statement
  */
1239

1240
  if ((for_str= file->get_foreign_key_create_info()))
1241 1242 1243
  {
    packet->append(for_str, strlen(for_str));
    file->free_foreign_key_create_info(for_str);
1244 1245 1246
  }

  packet->append("\n)", 2);
1247
  if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
1248
  {
1249 1250 1251
    packet->append(" TYPE=", 6);
    packet->append(file->table_type());
    
1252 1253 1254
    if (table->table_charset &&
	!(thd->variables.sql_mode & MODE_MYSQL323) &&
	!(thd->variables.sql_mode & MODE_MYSQL40))
1255
    {
1256
      packet->append(" DEFAULT CHARSET=", 17);
1257 1258 1259
      packet->append(table->table_charset->csname);
      if (!(table->table_charset->state & MY_CS_PRIMARY))
      {
1260
	packet->append(" COLLATE=", 9);
1261 1262
	packet->append(table->table_charset->name);
      }
1263
    }
1264

1265 1266
    if (table->min_rows)
    {
1267
      packet->append(" MIN_ROWS=", 10);
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1268 1269
      end= longlong10_to_str(table->min_rows, buff, 10);
      packet->append(buff, (uint) (end- buff));
1270
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1271

1272 1273
    if (table->max_rows)
    {
1274
      packet->append(" MAX_ROWS=", 10);
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1275 1276
      end= longlong10_to_str(table->max_rows, buff, 10);
      packet->append(buff, (uint) (end - buff));
1277
    }
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1278

1279 1280
    if (table->avg_row_length)
    {
1281
      packet->append(" AVG_ROW_LENGTH=", 16);
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1282 1283
      end= longlong10_to_str(table->avg_row_length, buff,10);
      packet->append(buff, (uint) (end - buff));
1284
    }
1285

1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306
    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
1307 1308 1309 1310 1311 1312
      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);
1313
    }
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1314 1315
    append_directory(thd, packet, "DATA",  create_info.data_file_name);
    append_directory(thd, packet, "INDEX", create_info.index_file_name);
1316
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1317 1318 1319 1320 1321
  DBUG_RETURN(0);
}


/****************************************************************************
1322 1323
  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
1324 1325 1326 1327
****************************************************************************/

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

monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
1332 1333
  ulong thread_id;
  time_t start_time;
1334
  uint   command;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347
  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;
1348 1349
  ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
			   PROCESS_LIST_WIDTH);
1350
  Protocol *protocol= thd->protocol;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1351 1352
  DBUG_ENTER("mysqld_list_processes");

1353
  field_list.push_back(new Item_int("Id",0,11));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1354
  field_list.push_back(new Item_empty_string("User",16));
1355
  field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1356 1357 1358
  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));
1359
  field_list.push_back(new Item_return_int("Time",7, FIELD_TYPE_LONG));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1360 1361 1362 1363
  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;
1364
  if (protocol->send_fields(&field_list,1))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1365 1366 1367 1368 1369 1370 1371 1372 1373
    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++))
    {
1374
      struct st_my_thread_var *mysys_var;
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1375
#ifndef EMBEDDED_LIBRARY
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1376
      if ((tmp->net.vio || tmp->system_thread) &&
1377
          (!user || (tmp->user && !strcmp(tmp->user,user))))
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1378 1379 1380 1381
#else
      if (tmp->system_thread &&
          (!user || (tmp->user && !strcmp(tmp->user,user))))
#endif
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1382
      {
1383 1384 1385
        thread_info *thd_info=new thread_info;

        thd_info->thread_id=tmp->thread_id;
1386 1387 1388
        thd_info->user=thd->strdup(tmp->user ? tmp->user :
				   (tmp->system_thread ?
				    "system user" : "unauthenticated user"));
1389
	if (tmp->peer_port && (tmp->host || tmp->ip) && thd->host_or_ip[0])
1390 1391
	{
	  if ((thd_info->host= thd->alloc(LIST_PROCESS_HOST_LEN+1)))
1392
	    my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN,
1393
			"%s:%u", tmp->host_or_ip, tmp->peer_port);
1394 1395
	}
	else
1396
	  thd_info->host= thd->strdup(tmp->host_or_ip);
1397 1398 1399
        if ((thd_info->db=tmp->db))             // Safe test
          thd_info->db=thd->strdup(thd_info->db);
        thd_info->command=(int) tmp->command;
1400 1401
        if ((mysys_var= tmp->mysys_var))
          pthread_mutex_lock(&mysys_var->mutex);
hf@genie.(none)'s avatar
SCRUM  
hf@genie.(none) committed
1402
        thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0);
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1403
#ifndef EMBEDDED_LIBRARY
1404 1405 1406 1407 1408 1409 1410 1411 1412 1413
        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
1414 1415 1416
#else
        thd_info->state_info= (char*)"Writing to net";
#endif
1417 1418
        if (mysys_var)
          pthread_mutex_unlock(&mysys_var->mutex);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1419 1420

#if !defined(DONT_USE_THR_ALARM) && ! defined(SCO)
1421 1422
        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
1423
#endif
1424 1425 1426
#ifdef EXTRA_DEBUG
        thd_info->start_time= tmp->time_after_lock;
#else
1427
        thd_info->start_time= tmp->start_time;
1428
#endif
1429 1430 1431
        thd_info->query=0;
        if (tmp->query)
        {
1432 1433
	  /* query_length is always set before tmp->query */
          uint length= min(max_query_length, tmp->query_length);
1434 1435 1436 1437
          thd_info->query=(char*) thd->memdup(tmp->query,length+1);
          thd_info->query[length]=0;
        }
        thread_infos.append(thd_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1438 1439 1440 1441 1442 1443
      }
    }
  }
  VOID(pthread_mutex_unlock(&LOCK_thread_count));

  thread_info *thd_info;
1444
  time_t now= time(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1445 1446
  while ((thd_info=thread_infos.get()))
  {
1447 1448
    protocol->prepare_for_resend();
    protocol->store((ulonglong) thd_info->thread_id);
1449 1450 1451
    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
1452
    if (thd_info->proc_info)
1453
      protocol->store(thd_info->proc_info, system_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1454
    else
1455
      protocol->store(command_name[thd_info->command], system_charset_info);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1456
    if (thd_info->start_time)
1457
      protocol->store((uint32) (now - thd_info->start_time));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1458
    else
1459
      protocol->store_null();
1460 1461
    protocol->store(thd_info->state_info, system_charset_info);
    protocol->store(thd_info->query, system_charset_info);
1462
    if (protocol->write())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1463 1464
      break; /* purecov: inspected */
  }
1465
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1466 1467 1468 1469
  DBUG_VOID_RETURN;
}

/*****************************************************************************
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1470
  Status functions
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1471 1472
*****************************************************************************/

1473 1474 1475 1476
static bool write_collation(Protocol *protocol, CHARSET_INFO *cs)
{
  protocol->prepare_for_resend();
  protocol->store(cs->name, system_charset_info);
1477
  protocol->store(cs->csname, system_charset_info);
1478
  protocol->store_short((longlong) cs->number);
1479 1480
  protocol->store((cs->state & MY_CS_PRIMARY) ? "Yes" : "",system_charset_info);
  protocol->store((cs->state & MY_CS_COMPILED)? "Yes" : "",system_charset_info);
1481 1482 1483 1484 1485
  protocol->store_short((longlong) cs->strxfrm_multiply);
  return protocol->write();
}

int mysqld_show_collations(THD *thd, const char *wild)
1486 1487
{
  char buff[8192];
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1488
  String packet2(buff,sizeof(buff),thd->charset());
1489
  List<Item> field_list;
1490
  CHARSET_INFO **cs;
1491
  Protocol *protocol= thd->protocol;
1492

1493 1494
  DBUG_ENTER("mysqld_show_charsets");

1495
  field_list.push_back(new Item_empty_string("Collation",30));
1496
  field_list.push_back(new Item_empty_string("Charset",30));
1497
  field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT));
1498 1499
  field_list.push_back(new Item_empty_string("Default",30));
  field_list.push_back(new Item_empty_string("Compiled",30));
1500
  field_list.push_back(new Item_return_int("Sortlen",3, FIELD_TYPE_SHORT));
1501

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

1505
  for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ )
1506
  {
1507
    CHARSET_INFO **cl;
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1508 1509 1510
    if (!cs[0] || !(cs[0]->state & MY_CS_AVAILABLE) || 
        !(cs[0]->state & MY_CS_PRIMARY))
      continue;
1511 1512
    for ( cl= all_charsets; cl < all_charsets+255 ;cl ++)
    {
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1513 1514
      if (!cl[0] || !(cl[0]->state & MY_CS_AVAILABLE) || 
          !my_charset_same(cs[0],cl[0]))
1515
	continue;
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1516
      if (!(wild && wild[0] &&
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1517
	  wild_case_compare(system_charset_info,cl[0]->name,wild)))
1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533
      {
        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);
1534
  protocol->store(cs->comment ? cs->comment : "", system_charset_info);
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550
  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));
1551
  field_list.push_back(new Item_empty_string("Description",60));
1552 1553 1554 1555 1556 1557 1558 1559
  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
1560 1561 1562 1563
    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)))
1564
    {
1565
      if (write_charset(protocol, cs[0]))
1566
	goto err;
1567 1568
    }
  }
1569
  send_eof(thd); 
1570 1571 1572 1573 1574
  DBUG_RETURN(0);
err:
  DBUG_RETURN(1);
}

monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1575
  
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1576

1577
int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
1578 1579
		enum enum_var_type value_type,
		pthread_mutex_t *mutex)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1580
{
1581
  char buff[1024];
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1582
  List<Item> field_list;
1583
  Protocol *protocol= thd->protocol;
1584
  LEX_STRING null_lex_str;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1585
  DBUG_ENTER("mysqld_show");
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1586

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1587 1588
  field_list.push_back(new Item_empty_string("Variable_name",30));
  field_list.push_back(new Item_empty_string("Value",256));
1589
  if (protocol->send_fields(&field_list,1))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1590
    DBUG_RETURN(1); /* purecov: inspected */
1591
  null_lex_str.str= 0;				// For sys_var->value_ptr()
1592
  null_lex_str.length= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1593

1594
  pthread_mutex_lock(mutex);
1595
  for (; variables->name; variables++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1596
  {
1597
    if (!(wild && wild[0] && wild_case_compare(system_charset_info,
1598
					       variables->name,wild)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1599
    {
1600
      protocol->prepare_for_resend();
1601
      protocol->store(variables->name, system_charset_info);
1602 1603
      SHOW_TYPE show_type=variables->type;
      char *value=variables->value;
1604 1605 1606
      const char *pos, *end;
      long nr;

1607 1608 1609
      if (show_type == SHOW_SYS)
      {
	show_type= ((sys_var*) value)->type();
1610 1611
	value=     (char*) ((sys_var*) value)->value_ptr(thd, value_type,
							 &null_lex_str);
1612 1613
      }

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

#endif /* HAVE_OPENSSL */
1852 1853 1854 1855
      case SHOW_KEY_CACHE_LONG:
	value= (value-(char*) &dflt_key_cache_var)+ (char*) sql_key_cache;
	end= int10_to_str(*(long*) value, buff, 10);
        break;
1856 1857
      case SHOW_UNDEF:				// Show never happen
      case SHOW_SYS:
1858
	break;					// Return empty string
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
1859 1860
      default:
	break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1861
      }
1862
      if (protocol->store(pos, (uint32) (end - pos), system_charset_info) ||
1863
	  protocol->write())
1864
        goto err;                               /* purecov: inspected */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1865 1866
    }
  }
1867
  pthread_mutex_unlock(mutex);
1868
  send_eof(thd);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1869 1870 1871
  DBUG_RETURN(0);

 err:
1872
  pthread_mutex_unlock(mutex);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1873 1874 1875 1876
  DBUG_RETURN(1);
}

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