~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2004 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
17
/* Function with list databases, tables or fields */
18
19
#include "mysql_priv.h"
20
#include "sql_select.h"                         // For select_describe
21
#include "sql_show.h"
22
#include "repl_failsafe.h"
23
#include <my_dir.h>
24
25
#define STR_OR_NIL(S) ((S) ? (S) : "<nil>")
26
27
/* Match the values of enum ha_choice */
28
static const char *ha_choice_values[] = {"", "0", "1"};
29
30
static void store_key_options(THD *thd, String *packet, TABLE *table,
31
                              KEY *key_info);
32
33
34
35
int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr)
36
{
37
  register int flag;
38
  DBUG_ENTER("wild_case_compare");
39
  DBUG_PRINT("enter",("str: '%s'  wildstr: '%s'",str,wildstr));
40
  while (*wildstr)
41
  {
42
    while (*wildstr && *wildstr != wild_many && *wildstr != wild_one)
43
    {
44
      if (*wildstr == wild_prefix && wildstr[1])
45
	wildstr++;
46
      if (my_toupper(cs, *wildstr++) !=
47
          my_toupper(cs, *str++)) DBUG_RETURN(1);
48
    }
49
    if (! *wildstr ) DBUG_RETURN (*str != 0);
50
    if (*wildstr++ == wild_one)
51
    {
52
      if (! *str++) DBUG_RETURN (1);	/* One char; skip */
53
    }
54
    else
55
    {						/* Found '*' */
56
      if (!*wildstr) DBUG_RETURN(0);		/* '*' as last char: OK */
57
      flag=(*wildstr != wild_many && *wildstr != wild_one);
58
      do
59
      {
60
	if (flag)
61
	{
62
	  char cmp;
63
	  if ((cmp= *wildstr) == wild_prefix && wildstr[1])
64
	    cmp=wildstr[1];
65
	  cmp=my_toupper(cs, cmp);
66
	  while (*str && my_toupper(cs, *str) != cmp)
67
	    str++;
68
	  if (!*str) DBUG_RETURN (1);
69
	}
70
	if (wild_case_compare(cs, str,wildstr) == 0) DBUG_RETURN (0);
71
      } while (*str++);
72
      DBUG_RETURN(1);
73
    }
74
  }
75
  DBUG_RETURN (*str != '\0');
76
}
77
78
/***************************************************************************
79
** List all table types supported
80
***************************************************************************/
81
82
static int make_version_string(char *buf, int buf_length, uint version)
83
{
84
  return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff);
85
}
86
87
static my_bool show_plugins(THD *thd, plugin_ref plugin,
88
                            void *arg)
89
{
90
  TABLE *table= (TABLE*) arg;
91
  struct st_mysql_plugin *plug= plugin_decl(plugin);
92
  struct st_plugin_dl *plugin_dl= plugin_dlib(plugin);
93
  CHARSET_INFO *cs= system_charset_info;
94
  char version_buf[20];
95
96
  restore_record(table, s->default_values);
97
98
  table->field[0]->store(plugin_name(plugin)->str,
99
                         plugin_name(plugin)->length, cs);
100
101
  table->field[1]->store(version_buf,
102
        make_version_string(version_buf, sizeof(version_buf), plug->version),
103
        cs);
104
105
106
  switch (plugin_state(plugin)) {
107
  /* case PLUGIN_IS_FREED: does not happen */
108
  case PLUGIN_IS_DELETED:
109
    table->field[2]->store(STRING_WITH_LEN("DELETED"), cs);
110
    break;
111
  case PLUGIN_IS_UNINITIALIZED:
112
    table->field[2]->store(STRING_WITH_LEN("INACTIVE"), cs);
113
    break;
114
  case PLUGIN_IS_READY:
115
    table->field[2]->store(STRING_WITH_LEN("ACTIVE"), cs);
116
    break;
117
  default:
118
    DBUG_ASSERT(0);
119
  }
120
121
  table->field[3]->store(plugin_type_names[plug->type].str,
122
                         plugin_type_names[plug->type].length,
123
                         cs);
124
  table->field[4]->store(version_buf,
125
        make_version_string(version_buf, sizeof(version_buf),
126
                            *(uint *)plug->info), cs);
127
128
  if (plugin_dl)
129
  {
130
    table->field[5]->store(plugin_dl->dl.str, plugin_dl->dl.length, cs);
131
    table->field[5]->set_notnull();
132
    table->field[6]->store(version_buf,
133
          make_version_string(version_buf, sizeof(version_buf),
134
                              plugin_dl->version),
135
          cs);
136
    table->field[6]->set_notnull();
137
  }
138
  else
139
  {
140
    table->field[5]->set_null();
141
    table->field[6]->set_null();
142
  }
143
144
145
  if (plug->author)
146
  {
147
    table->field[7]->store(plug->author, strlen(plug->author), cs);
148
    table->field[7]->set_notnull();
149
  }
150
  else
151
    table->field[7]->set_null();
152
153
  if (plug->descr)
154
  {
155
    table->field[8]->store(plug->descr, strlen(plug->descr), cs);
156
    table->field[8]->set_notnull();
157
  }
158
  else
159
    table->field[8]->set_null();
160
161
  switch (plug->license) {
162
  case PLUGIN_LICENSE_GPL:
163
    table->field[9]->store(PLUGIN_LICENSE_GPL_STRING, 
164
                           strlen(PLUGIN_LICENSE_GPL_STRING), cs);
165
    break;
166
  case PLUGIN_LICENSE_BSD:
167
    table->field[9]->store(PLUGIN_LICENSE_BSD_STRING, 
168
                           strlen(PLUGIN_LICENSE_BSD_STRING), cs);
169
    break;
170
  default:
171
    table->field[9]->store(PLUGIN_LICENSE_PROPRIETARY_STRING, 
172
                           strlen(PLUGIN_LICENSE_PROPRIETARY_STRING), cs);
173
    break;
174
  }
175
  table->field[9]->set_notnull();
176
177
  return schema_table_store_record(thd, table);
178
}
179
180
181
int fill_plugins(THD *thd, TABLE_LIST *tables, COND *cond)
182
{
183
  DBUG_ENTER("fill_plugins");
184
  TABLE *table= tables->table;
185
186
  if (plugin_foreach_with_mask(thd, show_plugins, MYSQL_ANY_PLUGIN,
187
                               ~PLUGIN_IS_FREED, table))
188
    DBUG_RETURN(1);
189
190
  DBUG_RETURN(0);
191
}
192
193
194
/*
195
  find_files() - find files in a given directory.
196
197
  SYNOPSIS
198
    find_files()
199
    thd                 thread handler
200
    files               put found files in this list
201
    db                  database name to set in TABLE_LIST structure
202
    path                path to database
203
    wild                filter for found files
204
    dir                 read databases in path if TRUE, read .frm files in
205
                        database otherwise
206
207
  RETURN
208
    FIND_FILES_OK       success
209
    FIND_FILES_OOM      out of memory error
210
    FIND_FILES_DIR      no such directory, or directory can't be read
211
*/
212
213
214
find_files_result
215
find_files(THD *thd, List<LEX_STRING> *files, const char *db,
216
           const char *path, const char *wild, bool dir)
217
{
218
  uint i;
219
  char *ext;
220
  MY_DIR *dirp;
221
  FILEINFO *file;
222
  LEX_STRING *file_name= 0;
223
  uint file_name_len;
224
  TABLE_LIST table_list;
225
  DBUG_ENTER("find_files");
226
227
  if (wild && !wild[0])
228
    wild=0;
229
230
  bzero((char*) &table_list,sizeof(table_list));
231
232
  if (!(dirp = my_dir(path,MYF(dir ? MY_WANT_STAT : 0))))
233
  {
234
    if (my_errno == ENOENT)
235
      my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), db);
236
    else
237
      my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), path, my_errno);
238
    DBUG_RETURN(FIND_FILES_DIR);
239
  }
240
241
  for (i=0 ; i < (uint) dirp->number_off_files  ; i++)
242
  {
243
    char uname[NAME_LEN + 1];                   /* Unencoded name */
244
    file=dirp->dir_entry+i;
245
    if (dir)
246
    {                                           /* Return databases */
247
      if ((file->name[0] == '.' && 
248
          ((file->name[1] == '.' && file->name[2] == '\0') ||
249
            file->name[1] == '\0')))
250
        continue;                               /* . or .. */
251
#ifdef USE_SYMDIR
252
      char *ext;
253
      char buff[FN_REFLEN];
254
      if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym"))
255
      {
256
	/* Only show the sym file if it points to a directory */
257
	char *end;
258
        *ext=0;                                 /* Remove extension */
259
	unpack_dirname(buff, file->name);
260
	end= strend(buff);
261
	if (end != buff && end[-1] == FN_LIBCHAR)
262
	  end[-1]= 0;				// Remove end FN_LIBCHAR
15 by brian
Fix for stat, NETWARE removal
263
        if (stat(buff, file->mystat))
1 by brian
clean slate
264
               continue;
265
       }
266
#endif
267
      if (!MY_S_ISDIR(file->mystat->st_mode))
268
        continue;
269
270
      file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
271
      if (wild && wild_compare(uname, wild, 0))
272
        continue;
273
      if (!(file_name= 
274
            thd->make_lex_string(file_name, uname, file_name_len, TRUE)))
275
      {
276
        my_dirend(dirp);
277
        DBUG_RETURN(FIND_FILES_OOM);
278
      }
279
    }
280
    else
281
    {
282
        // Return only .frm files which aren't temp files.
283
      if (my_strcasecmp(system_charset_info, ext=fn_rext(file->name),reg_ext) ||
284
          is_prefix(file->name, tmp_file_prefix))
285
        continue;
286
      *ext=0;
287
      file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
288
      if (wild)
289
      {
290
	if (lower_case_table_names)
291
	{
292
	  if (wild_case_compare(files_charset_info, uname, wild))
293
	    continue;
294
	}
295
	else if (wild_compare(uname, wild, 0))
296
	  continue;
297
      }
298
    }
299
    if (!(file_name= 
300
          thd->make_lex_string(file_name, uname, file_name_len, TRUE)) ||
301
        files->push_back(file_name))
302
    {
303
      my_dirend(dirp);
304
      DBUG_RETURN(FIND_FILES_OOM);
305
    }
306
  }
307
  DBUG_PRINT("info",("found: %d files", files->elements));
308
  my_dirend(dirp);
309
310
  DBUG_RETURN(FIND_FILES_OK);
311
}
312
313
314
bool
315
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
316
{
317
  Protocol *protocol= thd->protocol;
318
  char buff[2048];
319
  String buffer(buff, sizeof(buff), system_charset_info);
320
  DBUG_ENTER("mysqld_show_create");
321
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
322
                      table_list->table_name));
323
324
  /* Only one table for now, but VIEW can involve several tables */
325
  if (open_normal_and_derived_tables(thd, table_list, 0))
326
  {
327
    if (thd->is_error() && thd->main_da.sql_errno() != ER_VIEW_INVALID)
328
      DBUG_RETURN(TRUE);
329
330
    /*
331
      Clear all messages with 'error' level status and
332
      issue a warning with 'warning' level status in 
333
      case of invalid view and last error is ER_VIEW_INVALID
334
    */
335
    mysql_reset_errors(thd, true);
336
    thd->clear_error();
337
  }
338
339
  buffer.length(0);
340
341
  if (store_create_info(thd, table_list, &buffer, NULL))
342
    DBUG_RETURN(TRUE);
343
344
  List<Item> field_list;
345
  {
346
    field_list.push_back(new Item_empty_string("Table",NAME_CHAR_LEN));
347
    // 1024 is for not to confuse old clients
348
    field_list.push_back(new Item_empty_string("Create Table",
349
                                               max(buffer.length(),1024)));
350
  }
351
352
  if (protocol->send_fields(&field_list,
353
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
354
    DBUG_RETURN(TRUE);
355
  protocol->prepare_for_resend();
356
  {
357
    if (table_list->schema_table)
358
      protocol->store(table_list->schema_table->table_name,
359
                      system_charset_info);
360
    else
361
      protocol->store(table_list->table->alias, system_charset_info);
362
  }
363
364
  protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
365
366
  if (protocol->write())
367
    DBUG_RETURN(TRUE);
368
369
  my_eof(thd);
370
  DBUG_RETURN(FALSE);
371
}
372
373
bool mysqld_show_create_db(THD *thd, char *dbname,
374
                           HA_CREATE_INFO *create_info)
375
{
376
  char buff[2048];
377
  String buffer(buff, sizeof(buff), system_charset_info);
378
  Protocol *protocol=thd->protocol;
379
  DBUG_ENTER("mysql_show_create_db");
380
381
  if (store_db_create_info(thd, dbname, &buffer, create_info))
382
  {
383
    /* 
384
      This assumes that the only reason for which store_db_create_info()
385
      can fail is incorrect database name (which is the case now).
386
    */
387
    my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
388
    DBUG_RETURN(TRUE);    
389
  }
390
391
  List<Item> field_list;
392
  field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
393
  field_list.push_back(new Item_empty_string("Create Database",1024));
394
395
  if (protocol->send_fields(&field_list,
396
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
397
    DBUG_RETURN(TRUE);
398
399
  protocol->prepare_for_resend();
400
  protocol->store(dbname, strlen(dbname), system_charset_info);
401
  protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
402
403
  if (protocol->write())
404
    DBUG_RETURN(TRUE);
405
  my_eof(thd);
406
  DBUG_RETURN(FALSE);
407
}
408
409
410
411
/****************************************************************************
412
  Return only fields for API mysql_list_fields
413
  Use "show table wildcard" in mysql instead of this
414
****************************************************************************/
415
416
void
417
mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
418
{
419
  TABLE *table;
420
  DBUG_ENTER("mysqld_list_fields");
421
  DBUG_PRINT("enter",("table: %s",table_list->table_name));
422
423
  if (open_normal_and_derived_tables(thd, table_list, 0))
424
    DBUG_VOID_RETURN;
425
  table= table_list->table;
426
427
  List<Item> field_list;
428
429
  Field **ptr,*field;
430
  for (ptr=table->field ; (field= *ptr); ptr++)
431
  {
432
    if (!wild || !wild[0] || 
433
        !wild_case_compare(system_charset_info, field->field_name,wild))
434
    {
435
      field_list.push_back(new Item_field(field));
436
    }
437
  }
438
  restore_record(table, s->default_values);              // Get empty record
439
  table->use_all_columns();
440
  if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS))
441
    DBUG_VOID_RETURN;
442
  my_eof(thd);
443
  DBUG_VOID_RETURN;
444
}
445
446
447
/*
448
  Go through all character combinations and ensure that sql_lex.cc can
449
  parse it as an identifier.
450
451
  SYNOPSIS
452
  require_quotes()
453
  name			attribute name
454
  name_length		length of name
455
456
  RETURN
457
    #	Pointer to conflicting character
458
    0	No conflicting character
459
*/
460
461
static const char *require_quotes(const char *name, uint name_length)
462
{
463
  uint length;
464
  bool pure_digit= TRUE;
465
  const char *end= name + name_length;
466
467
  for (; name < end ; name++)
468
  {
469
    uchar chr= (uchar) *name;
470
    length= my_mbcharlen(system_charset_info, chr);
471
    if (length == 1 && !system_charset_info->ident_map[chr])
472
      return name;
473
    if (length == 1 && (chr < '0' || chr > '9'))
474
      pure_digit= FALSE;
475
  }
476
  if (pure_digit)
477
    return name;
478
  return 0;
479
}
480
481
482
/*
483
  Quote the given identifier if needed and append it to the target string.
484
  If the given identifier is empty, it will be quoted.
485
486
  SYNOPSIS
487
  append_identifier()
488
  thd                   thread handler
489
  packet                target string
490
  name                  the identifier to be appended
491
  name_length           length of the appending identifier
492
*/
493
494
void
495
append_identifier(THD *thd, String *packet, const char *name, uint length)
496
{
497
  const char *name_end;
498
  char quote_char;
499
  int q= get_quote_char_for_identifier(thd, name, length);
500
501
  if (q == EOF)
502
  {
503
    packet->append(name, length, packet->charset());
504
    return;
505
  }
506
507
  /*
508
    The identifier must be quoted as it includes a quote character or
509
   it's a keyword
510
  */
511
512
  VOID(packet->reserve(length*2 + 2));
513
  quote_char= (char) q;
514
  packet->append(&quote_char, 1, system_charset_info);
515
516
  for (name_end= name+length ; name < name_end ; name+= length)
517
  {
518
    uchar chr= (uchar) *name;
519
    length= my_mbcharlen(system_charset_info, chr);
520
    /*
521
      my_mbcharlen can return 0 on a wrong multibyte
522
      sequence. It is possible when upgrading from 4.0,
523
      and identifier contains some accented characters.
524
      The manual says it does not work. So we'll just
525
      change length to 1 not to hang in the endless loop.
526
    */
527
    if (!length)
528
      length= 1;
529
    if (length == 1 && chr == (uchar) quote_char)
530
      packet->append(&quote_char, 1, system_charset_info);
531
    packet->append(name, length, system_charset_info);
532
  }
533
  packet->append(&quote_char, 1, system_charset_info);
534
}
535
536
537
/*
538
  Get the quote character for displaying an identifier.
539
540
  SYNOPSIS
541
    get_quote_char_for_identifier()
542
    thd		Thread handler
543
    name	name to quote
544
    length	length of name
545
546
  IMPLEMENTATION
547
    Force quoting in the following cases:
548
      - name is empty (for one, it is possible when we use this function for
549
        quoting user and host names for DEFINER clause);
550
      - name is a keyword;
551
      - name includes a special character;
552
    Otherwise identifier is quoted only if the option OPTION_QUOTE_SHOW_CREATE
553
    is set.
554
555
  RETURN
556
    EOF	  No quote character is needed
557
    #	  Quote character
558
*/
559
560
int get_quote_char_for_identifier(THD *thd, const char *name, uint length)
561
{
562
  if (length &&
563
      !is_keyword(name,length) &&
564
      !require_quotes(name, length) &&
565
      !(thd->options & OPTION_QUOTE_SHOW_CREATE))
566
    return EOF;
567
  return '"';
568
}
569
570
571
/* Append directory name (if exists) to CREATE INFO */
572
573
static void append_directory(THD *thd, String *packet, const char *dir_type,
574
			     const char *filename)
575
{
576
  if (filename)
577
  {
578
    uint length= dirname_length(filename);
579
    packet->append(' ');
580
    packet->append(dir_type);
581
    packet->append(STRING_WITH_LEN(" DIRECTORY='"));
582
    packet->append(filename, length);
583
    packet->append('\'');
584
  }
585
}
586
587
588
#define LIST_PROCESS_HOST_LEN 64
589
590
static bool get_field_default_value(THD *thd, Field *timestamp_field,
591
                                    Field *field, String *def_value,
592
                                    bool quoted)
593
{
594
  bool has_default;
595
  bool has_now_default;
596
597
  /* 
598
     We are using CURRENT_TIMESTAMP instead of NOW because it is
599
     more standard
600
  */
601
  has_now_default= (timestamp_field == field &&
602
                    field->unireg_check != Field::TIMESTAMP_UN_FIELD);
603
    
604
  has_default= (field->type() != FIELD_TYPE_BLOB &&
605
                !(field->flags & NO_DEFAULT_VALUE_FLAG) &&
606
                field->unireg_check != Field::NEXT_NUMBER
607
                  && has_now_default);
608
609
  def_value->length(0);
610
  if (has_default)
611
  {
612
    if (has_now_default)
613
      def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
614
    else if (!field->is_null())
615
    {                                             // Not null by default
616
      char tmp[MAX_FIELD_WIDTH];
617
      String type(tmp, sizeof(tmp), field->charset());
618
      field->val_str(&type);
619
      if (type.length())
620
      {
621
        String def_val;
622
        uint dummy_errors;
623
        /* convert to system_charset_info == utf8 */
624
        def_val.copy(type.ptr(), type.length(), field->charset(),
625
                     system_charset_info, &dummy_errors);
626
        if (quoted)
627
          append_unescaped(def_value, def_val.ptr(), def_val.length());
628
        else
629
          def_value->append(def_val.ptr(), def_val.length());
630
      }
631
      else if (quoted)
632
        def_value->append(STRING_WITH_LEN("''"));
633
    }
634
    else if (field->maybe_null() && quoted)
635
      def_value->append(STRING_WITH_LEN("NULL"));    // Null as default
636
    else
637
      return 0;
638
639
  }
640
  return has_default;
641
}
642
643
/*
644
  Build a CREATE TABLE statement for a table.
645
646
  SYNOPSIS
647
    store_create_info()
648
    thd               The thread
649
    table_list        A list containing one table to write statement
650
                      for.
651
    packet            Pointer to a string where statement will be
652
                      written.
653
    create_info_arg   Pointer to create information that can be used
654
                      to tailor the format of the statement.  Can be
655
                      NULL, in which case only SQL_MODE is considered
656
                      when building the statement.
657
  
658
  NOTE
659
    Currently always return 0, but might return error code in the
660
    future.
661
    
662
  RETURN
663
    0       OK
664
 */
665
666
int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
667
                      HA_CREATE_INFO *create_info_arg)
668
{
669
  List<Item> field_list;
670
  char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], def_value_buf[MAX_FIELD_WIDTH];
671
  const char *alias;
672
  String type(tmp, sizeof(tmp), system_charset_info);
673
  String def_value(def_value_buf, sizeof(def_value_buf), system_charset_info);
674
  Field **ptr,*field;
675
  uint primary_key;
676
  KEY *key_info;
677
  TABLE *table= table_list->table;
678
  handler *file= table->file;
679
  TABLE_SHARE *share= table->s;
680
  HA_CREATE_INFO create_info;
681
  bool show_table_options= FALSE;
682
  my_bitmap_map *old_map;
683
  DBUG_ENTER("store_create_info");
684
  DBUG_PRINT("enter",("table: %s", table->s->table_name.str));
685
686
  restore_record(table, s->default_values); // Get empty record
687
688
  if (share->tmp_table)
689
    packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
690
  else
691
    packet->append(STRING_WITH_LEN("CREATE TABLE "));
692
  if (create_info_arg &&
693
      (create_info_arg->options & HA_LEX_CREATE_IF_NOT_EXISTS))
694
    packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
695
  if (table_list->schema_table)
696
    alias= table_list->schema_table->table_name;
697
  else
698
  {
699
    if (lower_case_table_names == 2)
700
      alias= table->alias;
701
    else
702
    {
703
      alias= share->table_name.str;
704
    }
705
  }
706
  append_identifier(thd, packet, alias, strlen(alias));
707
  packet->append(STRING_WITH_LEN(" (\n"));
708
  /*
709
    We need this to get default values from the table
710
    We have to restore the read_set if we are called from insert in case
711
    of row based replication.
712
  */
713
  old_map= tmp_use_all_columns(table, table->read_set);
714
715
  for (ptr=table->field ; (field= *ptr); ptr++)
716
  {
717
    uint flags = field->flags;
718
719
    if (ptr != table->field)
720
      packet->append(STRING_WITH_LEN(",\n"));
721
722
    packet->append(STRING_WITH_LEN("  "));
723
    append_identifier(thd,packet,field->field_name, strlen(field->field_name));
724
    packet->append(' ');
725
    // check for surprises from the previous call to Field::sql_type()
726
    if (type.ptr() != tmp)
727
      type.set(tmp, sizeof(tmp), system_charset_info);
728
    else
729
      type.set_charset(system_charset_info);
730
731
    field->sql_type(type);
732
    packet->append(type.ptr(), type.length(), system_charset_info);
733
734
    if (field->has_charset())
735
    {
736
      if (field->charset() != share->table_charset)
737
      {
738
	packet->append(STRING_WITH_LEN(" CHARACTER SET "));
739
	packet->append(field->charset()->csname);
740
      }
741
      /* 
742
	For string types dump collation name only if 
743
	collation is not primary for the given charset
744
      */
745
      if (!(field->charset()->state & MY_CS_PRIMARY))
746
      {
747
	packet->append(STRING_WITH_LEN(" COLLATE "));
748
	packet->append(field->charset()->name);
749
      }
750
    }
751
752
    if (flags & NOT_NULL_FLAG)
753
      packet->append(STRING_WITH_LEN(" NOT NULL"));
754
    else if (field->type() == MYSQL_TYPE_TIMESTAMP)
755
    {
756
      /*
757
        TIMESTAMP field require explicit NULL flag, because unlike
758
        all other fields they are treated as NOT NULL by default.
759
      */
760
      packet->append(STRING_WITH_LEN(" NULL"));
761
    }
762
    {
763
      /*
764
        Add field flags about FIELD FORMAT (FIXED or DYNAMIC)
765
        and about STORAGE (DISK or MEMORY).
766
      */
767
      enum ha_storage_media storage_type= (enum ha_storage_media)
768
        ((flags >> FIELD_STORAGE_FLAGS) & STORAGE_TYPE_MASK);
769
      enum column_format_type column_format= (enum column_format_type)
770
        ((flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
771
      if (storage_type)
772
      {
773
        packet->append(STRING_WITH_LEN(" /*!"));
774
        packet->append(STRING_WITH_LEN(MYSQL_VERSION_TABLESPACE_IN_FRM_STR));
775
        packet->append(STRING_WITH_LEN(" STORAGE"));
776
        if (storage_type == HA_SM_DISK)
777
          packet->append(STRING_WITH_LEN(" DISK */"));
778
        else
779
          packet->append(STRING_WITH_LEN(" MEMORY */"));
780
      }
781
      if (column_format)
782
      {
783
        packet->append(STRING_WITH_LEN(" /*!"));
784
        packet->append(STRING_WITH_LEN(MYSQL_VERSION_TABLESPACE_IN_FRM_STR));
785
        packet->append(STRING_WITH_LEN(" COLUMN_FORMAT"));
786
        if (column_format == COLUMN_FORMAT_TYPE_FIXED)
787
          packet->append(STRING_WITH_LEN(" FIXED */"));
788
        else
789
          packet->append(STRING_WITH_LEN(" DYNAMIC */"));
790
      }
791
    }
792
    if (get_field_default_value(thd, table->timestamp_field,
793
                                field, &def_value, 1))
794
    {
795
      packet->append(STRING_WITH_LEN(" DEFAULT "));
796
      packet->append(def_value.ptr(), def_value.length(), system_charset_info);
797
    }
798
799
    if (table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_DN_FIELD)
800
      packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
801
802
    if (field->unireg_check == Field::NEXT_NUMBER)
803
      packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
804
805
    if (field->comment.length)
806
    {
807
      packet->append(STRING_WITH_LEN(" COMMENT "));
808
      append_unescaped(packet, field->comment.str, field->comment.length);
809
    }
810
  }
811
812
  key_info= table->key_info;
813
  bzero((char*) &create_info, sizeof(create_info));
814
  /* Allow update_create_info to update row type */
815
  create_info.row_type= share->row_type;
816
  file->update_create_info(&create_info);
817
  primary_key= share->primary_key;
818
819
  for (uint i=0 ; i < share->keys ; i++,key_info++)
820
  {
821
    KEY_PART_INFO *key_part= key_info->key_part;
822
    bool found_primary=0;
823
    packet->append(STRING_WITH_LEN(",\n  "));
824
825
    if (i == primary_key && !strcmp(key_info->name, primary_key_name))
826
    {
827
      found_primary=1;
828
      /*
829
        No space at end, because a space will be added after where the
830
        identifier would go, but that is not added for primary key.
831
      */
832
      packet->append(STRING_WITH_LEN("PRIMARY KEY"));
833
    }
834
    else if (key_info->flags & HA_NOSAME)
835
      packet->append(STRING_WITH_LEN("UNIQUE KEY "));
836
    else
837
      packet->append(STRING_WITH_LEN("KEY "));
838
839
    if (!found_primary)
840
     append_identifier(thd, packet, key_info->name, strlen(key_info->name));
841
842
    packet->append(STRING_WITH_LEN(" ("));
843
844
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
845
    {
846
      if (j)
847
        packet->append(',');
848
849
      if (key_part->field)
850
        append_identifier(thd,packet,key_part->field->field_name,
851
			  strlen(key_part->field->field_name));
852
      if (key_part->field &&
853
          (key_part->length !=
854
           table->field[key_part->fieldnr-1]->key_length()))
855
      {
856
        char *end;
857
        buff[0] = '(';
858
        end= int10_to_str((long) key_part->length /
859
                          key_part->field->charset()->mbmaxlen,
860
                          buff + 1,10);
861
        *end++ = ')';
862
        packet->append(buff,(uint) (end-buff));
863
      }
864
    }
865
    packet->append(')');
866
    store_key_options(thd, packet, table, key_info);
867
  }
868
869
  /*
870
    Get possible foreign key definitions stored in InnoDB and append them
871
    to the CREATE TABLE statement
872
  */
873
874
  if ((for_str= file->get_foreign_key_create_info()))
875
  {
876
    packet->append(for_str, strlen(for_str));
877
    file->free_foreign_key_create_info(for_str);
878
  }
879
880
  packet->append(STRING_WITH_LEN("\n)"));
881
  {
882
    show_table_options= TRUE;
883
    /*
884
      Get possible table space definitions and append them
885
      to the CREATE TABLE statement
886
    */
887
888
    switch (table->s->default_storage_media) {
889
    case(HA_SM_DEFAULT):
890
      if ((for_str= (char *)file->get_tablespace_name()))
891
      {
892
        packet->append(STRING_WITH_LEN(" /*!50100 TABLESPACE "));
893
        append_identifier(thd, packet, for_str, strlen(for_str));
894
        packet->append(STRING_WITH_LEN(" */"));
895
      }
896
      break;
897
    case(HA_SM_DISK):
898
      packet->append(STRING_WITH_LEN(" /*!50100"));
899
      if ((for_str= (char *)file->get_tablespace_name()))
900
      {
901
        packet->append(STRING_WITH_LEN(" TABLESPACE "));
902
        append_identifier(thd, packet, for_str, strlen(for_str));
903
      }
904
      packet->append(STRING_WITH_LEN(" STORAGE DISK */"));
905
      break;
906
    case(HA_SM_MEMORY):
907
      packet->append(STRING_WITH_LEN(" /*!50100"));
908
      if ((for_str= (char *)file->get_tablespace_name()))
909
      {
910
        packet->append(STRING_WITH_LEN(" TABLESPACE "));
911
        append_identifier(thd, packet, for_str, strlen(for_str));
912
      }
913
      packet->append(STRING_WITH_LEN(" STORAGE MEMORY */"));
914
      break;
915
    };
916
917
    /*
918
      IF   check_create_info
919
      THEN add ENGINE only if it was used when creating the table
920
    */
921
    if (!create_info_arg ||
922
        (create_info_arg->used_fields & HA_CREATE_USED_ENGINE))
923
    {
924
      packet->append(STRING_WITH_LEN(" ENGINE="));
925
      packet->append(file->table_type());
926
    }
927
928
    /*
929
      Add AUTO_INCREMENT=... if there is an AUTO_INCREMENT column,
930
      and NEXT_ID > 1 (the default).  We must not print the clause
931
      for engines that do not support this as it would break the
932
      import of dumps, but as of this writing, the test for whether
933
      AUTO_INCREMENT columns are allowed and wether AUTO_INCREMENT=...
934
      is supported is identical, !(file->table_flags() & HA_NO_AUTO_INCREMENT))
935
      Because of that, we do not explicitly test for the feature,
936
      but may extrapolate its existence from that of an AUTO_INCREMENT column.
937
    */
938
939
    if (create_info.auto_increment_value > 1)
940
    {
941
      char *end;
942
      packet->append(STRING_WITH_LEN(" AUTO_INCREMENT="));
943
      end= longlong10_to_str(create_info.auto_increment_value, buff,10);
944
      packet->append(buff, (uint) (end - buff));
945
    }
946
947
    
948
    if (share->table_charset)
949
    {
950
      /*
951
        IF   check_create_info
952
        THEN add DEFAULT CHARSET only if it was used when creating the table
953
      */
954
      if (!create_info_arg ||
955
          (create_info_arg->used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
956
      {
957
        packet->append(STRING_WITH_LEN(" DEFAULT CHARSET="));
958
        packet->append(share->table_charset->csname);
959
        if (!(share->table_charset->state & MY_CS_PRIMARY))
960
        {
961
          packet->append(STRING_WITH_LEN(" COLLATE="));
962
          packet->append(table->s->table_charset->name);
963
        }
964
      }
965
    }
966
967
    if (share->min_rows)
968
    {
969
      char *end;
970
      packet->append(STRING_WITH_LEN(" MIN_ROWS="));
971
      end= longlong10_to_str(share->min_rows, buff, 10);
972
      packet->append(buff, (uint) (end- buff));
973
    }
974
975
    if (share->max_rows && !table_list->schema_table)
976
    {
977
      char *end;
978
      packet->append(STRING_WITH_LEN(" MAX_ROWS="));
979
      end= longlong10_to_str(share->max_rows, buff, 10);
980
      packet->append(buff, (uint) (end - buff));
981
    }
982
983
    if (share->avg_row_length)
984
    {
985
      char *end;
986
      packet->append(STRING_WITH_LEN(" AVG_ROW_LENGTH="));
987
      end= longlong10_to_str(share->avg_row_length, buff,10);
988
      packet->append(buff, (uint) (end - buff));
989
    }
990
991
    if (share->db_create_options & HA_OPTION_PACK_KEYS)
992
      packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
993
    if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
994
      packet->append(STRING_WITH_LEN(" PACK_KEYS=0"));
995
    /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */
996
    if (share->db_create_options & HA_OPTION_CHECKSUM)
997
      packet->append(STRING_WITH_LEN(" CHECKSUM=1"));
998
    if (share->page_checksum != HA_CHOICE_UNDEF)
999
    {
1000
      packet->append(STRING_WITH_LEN(" PAGE_CHECKSUM="));
1001
      packet->append(ha_choice_values[(uint) share->page_checksum], 1);
1002
    }
1003
    if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
1004
      packet->append(STRING_WITH_LEN(" DELAY_KEY_WRITE=1"));
1005
    if (create_info.row_type != ROW_TYPE_DEFAULT)
1006
    {
1007
      packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
1008
      packet->append(ha_row_type[(uint) create_info.row_type]);
1009
    }
1010
    if (share->transactional != HA_CHOICE_UNDEF)
1011
    {
1012
      packet->append(STRING_WITH_LEN(" TRANSACTIONAL="));
1013
      packet->append(ha_choice_values[(uint) share->transactional], 1);
1014
    }
1015
    if (table->s->key_block_size)
1016
    {
1017
      char *end;
1018
      packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
1019
      end= longlong10_to_str(table->s->key_block_size, buff, 10);
1020
      packet->append(buff, (uint) (end - buff));
1021
    }
1022
    table->file->append_create_info(packet);
1023
    if (share->comment.length)
1024
    {
1025
      packet->append(STRING_WITH_LEN(" COMMENT="));
1026
      append_unescaped(packet, share->comment.str, share->comment.length);
1027
    }
1028
    if (share->connect_string.length)
1029
    {
1030
      packet->append(STRING_WITH_LEN(" CONNECTION="));
1031
      append_unescaped(packet, share->connect_string.str, share->connect_string.length);
1032
    }
1033
    append_directory(thd, packet, "DATA",  create_info.data_file_name);
1034
    append_directory(thd, packet, "INDEX", create_info.index_file_name);
1035
  }
1036
  tmp_restore_column_map(table->read_set, old_map);
1037
  DBUG_RETURN(0);
1038
}
1039
1040
/**
1041
  Get a CREATE statement for a given database.
1042
1043
  The database is identified by its name, passed as @c dbname parameter.
1044
  The name should be encoded using the system character set (UTF8 currently).
1045
1046
  Resulting statement is stored in the string pointed by @c buffer. The string
1047
  is emptied first and its character set is set to the system character set.
1048
1049
  If HA_LEX_CREATE_IF_NOT_EXISTS flag is set in @c create_info->options, then
1050
  the resulting CREATE statement contains "IF NOT EXISTS" clause. Other flags
1051
  in @c create_options are ignored.
1052
1053
  @param  thd           The current thread instance.
1054
  @param  dbname        The name of the database.
1055
  @param  buffer        A String instance where the statement is stored.
1056
  @param  create_info   If not NULL, the options member influences the resulting 
1057
                        CRATE statement.
1058
1059
  @returns TRUE if errors are detected, FALSE otherwise.
1060
*/
1061
1062
bool store_db_create_info(THD *thd, const char *dbname, String *buffer,
1063
                          HA_CREATE_INFO *create_info)
1064
{
1065
  HA_CREATE_INFO create;
1066
  uint create_options = create_info ? create_info->options : 0;
1067
  DBUG_ENTER("store_db_create_info");
1068
1069
  if (!my_strcasecmp(system_charset_info, dbname,
1070
                     INFORMATION_SCHEMA_NAME.str))
1071
  {
1072
    dbname= INFORMATION_SCHEMA_NAME.str;
1073
    create.default_table_charset= system_charset_info;
1074
  }
1075
  else
1076
  {
1077
    if (check_db_dir_existence(dbname))
1078
      DBUG_RETURN(TRUE);
1079
1080
    load_db_opt_by_name(thd, dbname, &create);
1081
  }
1082
1083
  buffer->length(0);
1084
  buffer->free();
1085
  buffer->set_charset(system_charset_info);
1086
  buffer->append(STRING_WITH_LEN("CREATE DATABASE "));
1087
1088
  if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
1089
    buffer->append(STRING_WITH_LEN("/*!32312 IF NOT EXISTS*/ "));
1090
1091
  append_identifier(thd, buffer, dbname, strlen(dbname));
1092
1093
  if (create.default_table_charset)
1094
  {
1095
    buffer->append(STRING_WITH_LEN(" /*!40100"));
1096
    buffer->append(STRING_WITH_LEN(" DEFAULT CHARACTER SET "));
1097
    buffer->append(create.default_table_charset->csname);
1098
    if (!(create.default_table_charset->state & MY_CS_PRIMARY))
1099
    {
1100
      buffer->append(STRING_WITH_LEN(" COLLATE "));
1101
      buffer->append(create.default_table_charset->name);
1102
    }
1103
    buffer->append(STRING_WITH_LEN(" */"));
1104
  }
1105
1106
  DBUG_RETURN(FALSE);
1107
}
1108
1109
static void store_key_options(THD *thd, String *packet, TABLE *table,
1110
                              KEY *key_info)
1111
{
1112
  char *end, buff[32];
1113
1114
  if (key_info->algorithm == HA_KEY_ALG_BTREE)
1115
    packet->append(STRING_WITH_LEN(" USING BTREE"));
1116
1117
  if (key_info->algorithm == HA_KEY_ALG_HASH)
1118
    packet->append(STRING_WITH_LEN(" USING HASH"));
1119
1120
  if ((key_info->flags & HA_USES_BLOCK_SIZE) &&
1121
      table->s->key_block_size != key_info->block_size)
1122
  {
1123
    packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
1124
    end= longlong10_to_str(key_info->block_size, buff, 10);
1125
    packet->append(buff, (uint) (end - buff));
1126
  }
1127
1128
  DBUG_ASSERT(test(key_info->flags & HA_USES_COMMENT) == 
1129
              (key_info->comment.length > 0));
1130
  if (key_info->flags & HA_USES_COMMENT)
1131
  {
1132
    packet->append(STRING_WITH_LEN(" COMMENT "));
1133
    append_unescaped(packet, key_info->comment.str, 
1134
                     key_info->comment.length);
1135
  }
1136
}
1137
1138
1139
/****************************************************************************
1140
  Return info about all processes
1141
  returns for each thread: thread id, user, host, db, command, info
1142
****************************************************************************/
1143
1144
class thread_info :public ilink {
1145
public:
1146
  static void *operator new(size_t size)
1147
  {
1148
    return (void*) sql_alloc((uint) size);
1149
  }
1150
  static void operator delete(void *ptr __attribute__((unused)),
1151
                              size_t size __attribute__((unused)))
1152
  { TRASH(ptr, size); }
1153
1154
  ulong thread_id;
1155
  time_t start_time;
1156
  uint   command;
1157
  const char *user,*host,*db,*proc_info,*state_info;
1158
  char *query;
1159
};
1160
1161
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
1162
template class I_List<thread_info>;
1163
#endif
1164
1165
void mysqld_list_processes(THD *thd,const char *user, bool verbose)
1166
{
1167
  Item *field;
1168
  List<Item> field_list;
1169
  I_List<thread_info> thread_infos;
1170
  ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
1171
			   PROCESS_LIST_WIDTH);
1172
  Protocol *protocol= thd->protocol;
1173
  DBUG_ENTER("mysqld_list_processes");
1174
1175
  field_list.push_back(new Item_int("Id", 0, MY_INT32_NUM_DECIMAL_DIGITS));
1176
  field_list.push_back(new Item_empty_string("User",16));
1177
  field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
1178
  field_list.push_back(field=new Item_empty_string("db",NAME_CHAR_LEN));
1179
  field->maybe_null=1;
1180
  field_list.push_back(new Item_empty_string("Command",16));
1181
  field_list.push_back(new Item_return_int("Time",7, MYSQL_TYPE_LONG));
1182
  field_list.push_back(field=new Item_empty_string("State",30));
1183
  field->maybe_null=1;
1184
  field_list.push_back(field=new Item_empty_string("Info",max_query_length));
1185
  field->maybe_null=1;
1186
  if (protocol->send_fields(&field_list,
1187
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
1188
    DBUG_VOID_RETURN;
1189
1190
  VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
1191
  if (!thd->killed)
1192
  {
1193
    I_List_iterator<THD> it(threads);
1194
    THD *tmp;
1195
    while ((tmp=it++))
1196
    {
1197
      Security_context *tmp_sctx= tmp->security_ctx;
1198
      struct st_my_thread_var *mysys_var;
1199
      if ((tmp->vio_ok() || tmp->system_thread) && (!user || (tmp_sctx->user && !strcmp(tmp_sctx->user, user))))
1200
      {
1201
        thread_info *thd_info= new thread_info;
1202
1203
        thd_info->thread_id=tmp->thread_id;
1204
        thd_info->user= thd->strdup(tmp_sctx->user ? tmp_sctx->user :
1205
                                    (tmp->system_thread ?
1206
                                     "system user" : "unauthenticated user"));
1207
        thd_info->host= thd->strdup(tmp_sctx->host_or_ip[0] ? 
1208
                                    tmp_sctx->host_or_ip : 
1209
                                    tmp_sctx->host ? tmp_sctx->host : "");
1210
        if ((thd_info->db=tmp->db))             // Safe test
1211
          thd_info->db=thd->strdup(thd_info->db);
1212
        thd_info->command=(int) tmp->command;
1213
        if ((mysys_var= tmp->mysys_var))
1214
          pthread_mutex_lock(&mysys_var->mutex);
1215
        thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0);
1216
        thd_info->state_info= (char*) (tmp->net.reading_or_writing ?
1217
                                       (tmp->net.reading_or_writing == 2 ?
1218
                                        "Writing to net" :
1219
                                        thd_info->command == COM_SLEEP ? NullS :
1220
                                        "Reading from net") :
1221
                                       tmp->proc_info ? tmp->proc_info :
1222
                                       tmp->mysys_var &&
1223
                                       tmp->mysys_var->current_cond ?
1224
                                       "Waiting on cond" : NullS);
1225
        if (mysys_var)
1226
          pthread_mutex_unlock(&mysys_var->mutex);
1227
1228
        thd_info->start_time= tmp->start_time;
1229
        thd_info->query=0;
1230
        if (tmp->query)
1231
        {
1232
	  /* 
1233
            query_length is always set to 0 when we set query = NULL; see
1234
	    the comment in sql_class.h why this prevents crashes in possible
1235
            races with query_length
1236
          */
1237
          uint length= min(max_query_length, tmp->query_length);
1238
          thd_info->query=(char*) thd->strmake(tmp->query,length);
1239
        }
1240
        thread_infos.append(thd_info);
1241
      }
1242
    }
1243
  }
1244
  VOID(pthread_mutex_unlock(&LOCK_thread_count));
1245
1246
  thread_info *thd_info;
1247
  time_t now= my_time(0);
1248
  while ((thd_info=thread_infos.get()))
1249
  {
1250
    protocol->prepare_for_resend();
1251
    protocol->store((ulonglong) thd_info->thread_id);
1252
    protocol->store(thd_info->user, system_charset_info);
1253
    protocol->store(thd_info->host, system_charset_info);
1254
    protocol->store(thd_info->db, system_charset_info);
1255
    if (thd_info->proc_info)
1256
      protocol->store(thd_info->proc_info, system_charset_info);
1257
    else
1258
      protocol->store(command_name[thd_info->command].str, system_charset_info);
1259
    if (thd_info->start_time)
1260
      protocol->store((uint32) (now - thd_info->start_time));
1261
    else
1262
      protocol->store_null();
1263
    protocol->store(thd_info->state_info, system_charset_info);
1264
    protocol->store(thd_info->query, system_charset_info);
1265
    if (protocol->write())
1266
      break; /* purecov: inspected */
1267
  }
1268
  my_eof(thd);
1269
  DBUG_VOID_RETURN;
1270
}
1271
1272
int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
1273
{
1274
  TABLE *table= tables->table;
1275
  CHARSET_INFO *cs= system_charset_info;
1276
  char *user;
1277
  time_t now= my_time(0);
1278
  DBUG_ENTER("fill_process_list");
1279
1280
  user= NullS;
1281
1282
  VOID(pthread_mutex_lock(&LOCK_thread_count));
1283
1284
  if (!thd->killed)
1285
  {
1286
    I_List_iterator<THD> it(threads);
1287
    THD* tmp;
1288
1289
    while ((tmp= it++))
1290
    {
1291
      Security_context *tmp_sctx= tmp->security_ctx;
1292
      struct st_my_thread_var *mysys_var;
1293
      const char *val;
1294
1295
      if ((!tmp->vio_ok() && !tmp->system_thread))
1296
        continue;
1297
1298
      restore_record(table, s->default_values);
1299
      /* ID */
1300
      table->field[0]->store((longlong) tmp->thread_id, TRUE);
1301
      /* USER */
1302
      val= tmp_sctx->user ? tmp_sctx->user :
1303
            (tmp->system_thread ? "system user" : "unauthenticated user");
1304
      table->field[1]->store(val, strlen(val), cs);
1305
      /* HOST */
1306
      table->field[2]->store(tmp_sctx->host_or_ip,
1307
                             strlen(tmp_sctx->host_or_ip), cs);
1308
      /* DB */
1309
      if (tmp->db)
1310
      {
1311
        table->field[3]->store(tmp->db, strlen(tmp->db), cs);
1312
        table->field[3]->set_notnull();
1313
      }
1314
1315
      if ((mysys_var= tmp->mysys_var))
1316
        pthread_mutex_lock(&mysys_var->mutex);
1317
      /* COMMAND */
1318
      if ((val= (char *) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0)))
1319
        table->field[4]->store(val, strlen(val), cs);
1320
      else
1321
        table->field[4]->store(command_name[tmp->command].str,
1322
                               command_name[tmp->command].length, cs);
1323
      /* MYSQL_TIME */
1324
      table->field[5]->store((uint32)(tmp->start_time ?
1325
                                      now - tmp->start_time : 0), TRUE);
1326
      /* STATE */
1327
      val= (char*) (tmp->net.reading_or_writing ?
1328
                    (tmp->net.reading_or_writing == 2 ?
1329
                     "Writing to net" :
1330
                     tmp->command == COM_SLEEP ? NullS :
1331
                     "Reading from net") :
1332
                    tmp->proc_info ? tmp->proc_info :
1333
                    tmp->mysys_var &&
1334
                    tmp->mysys_var->current_cond ?
1335
                    "Waiting on cond" : NullS);
1336
      if (val)
1337
      {
1338
        table->field[6]->store(val, strlen(val), cs);
1339
        table->field[6]->set_notnull();
1340
      }
1341
1342
      if (mysys_var)
1343
        pthread_mutex_unlock(&mysys_var->mutex);
1344
1345
      /* INFO */
1346
      if (tmp->query)
1347
      {
1348
        table->field[7]->store(tmp->query,
1349
                               min(PROCESS_LIST_INFO_WIDTH,
1350
                                   tmp->query_length), cs);
1351
        table->field[7]->set_notnull();
1352
      }
1353
1354
      if (schema_table_store_record(thd, table))
1355
      {
1356
        VOID(pthread_mutex_unlock(&LOCK_thread_count));
1357
        DBUG_RETURN(1);
1358
      }
1359
    }
1360
  }
1361
1362
  VOID(pthread_mutex_unlock(&LOCK_thread_count));
1363
  DBUG_RETURN(0);
1364
}
1365
1366
/*****************************************************************************
1367
  Status functions
1368
*****************************************************************************/
1369
1370
static DYNAMIC_ARRAY all_status_vars;
1371
static bool status_vars_inited= 0;
1372
static int show_var_cmp(const void *var1, const void *var2)
1373
{
1374
  return strcmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name);
1375
}
1376
1377
/*
1378
  deletes all the SHOW_UNDEF elements from the array and calls
1379
  delete_dynamic() if it's completely empty.
1380
*/
1381
static void shrink_var_array(DYNAMIC_ARRAY *array)
1382
{
1383
  uint a,b;
1384
  SHOW_VAR *all= dynamic_element(array, 0, SHOW_VAR *);
1385
1386
  for (a= b= 0; b < array->elements; b++)
1387
    if (all[b].type != SHOW_UNDEF)
1388
      all[a++]= all[b];
1389
  if (a)
1390
  {
1391
    bzero(all+a, sizeof(SHOW_VAR)); // writing NULL-element to the end
1392
    array->elements= a;
1393
  }
1394
  else // array is completely empty - delete it
1395
    delete_dynamic(array);
1396
}
1397
1398
/*
1399
  Adds an array of SHOW_VAR entries to the output of SHOW STATUS
1400
1401
  SYNOPSIS
1402
    add_status_vars(SHOW_VAR *list)
1403
    list - an array of SHOW_VAR entries to add to all_status_vars
1404
           the last entry must be {0,0,SHOW_UNDEF}
1405
1406
  NOTE
1407
    The handling of all_status_vars[] is completely internal, it's allocated
1408
    automatically when something is added to it, and deleted completely when
1409
    the last entry is removed.
1410
1411
    As a special optimization, if add_status_vars() is called before
1412
    init_status_vars(), it assumes "startup mode" - neither concurrent access
1413
    to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
1414
1415
    The last entry of the all_status_vars[] should always be {0,0,SHOW_UNDEF}
1416
*/
1417
int add_status_vars(SHOW_VAR *list)
1418
{
1419
  int res= 0;
1420
  if (status_vars_inited)
1421
    pthread_mutex_lock(&LOCK_status);
1422
  if (!all_status_vars.buffer && // array is not allocated yet - do it now
1423
      my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 200, 20))
1424
  {
1425
    res= 1;
1426
    goto err;
1427
  }
1428
  while (list->name)
1429
    res|= insert_dynamic(&all_status_vars, (uchar*)list++);
1430
  res|= insert_dynamic(&all_status_vars, (uchar*)list); // appending NULL-element
1431
  all_status_vars.elements--; // but next insert_dynamic should overwite it
1432
  if (status_vars_inited)
1433
    sort_dynamic(&all_status_vars, show_var_cmp);
1434
err:
1435
  if (status_vars_inited)
1436
    pthread_mutex_unlock(&LOCK_status);
1437
  return res;
1438
}
1439
1440
/*
1441
  Make all_status_vars[] usable for SHOW STATUS
1442
1443
  NOTE
1444
    See add_status_vars(). Before init_status_vars() call, add_status_vars()
1445
    works in a special fast "startup" mode. Thus init_status_vars()
1446
    should be called as late as possible but before enabling multi-threading.
1447
*/
1448
void init_status_vars()
1449
{
1450
  status_vars_inited=1;
1451
  sort_dynamic(&all_status_vars, show_var_cmp);
1452
}
1453
1454
void reset_status_vars()
1455
{
1456
  SHOW_VAR *ptr= (SHOW_VAR*) all_status_vars.buffer;
1457
  SHOW_VAR *last= ptr + all_status_vars.elements;
1458
  for (; ptr < last; ptr++)
1459
  {
1460
    /* Note that SHOW_LONG_NOFLUSH variables are not reset */
1461
    if (ptr->type == SHOW_LONG)
1462
      *(ulong*) ptr->value= 0;
1463
  }  
1464
}
1465
1466
/*
1467
  catch-all cleanup function, cleans up everything no matter what
1468
1469
  DESCRIPTION
1470
    This function is not strictly required if all add_to_status/
1471
    remove_status_vars are properly paired, but it's a safety measure that
1472
    deletes everything from the all_status_vars[] even if some
1473
    remove_status_vars were forgotten
1474
*/
1475
void free_status_vars()
1476
{
1477
  delete_dynamic(&all_status_vars);
1478
}
1479
1480
/*
1481
  Removes an array of SHOW_VAR entries from the output of SHOW STATUS
1482
1483
  SYNOPSIS
1484
    remove_status_vars(SHOW_VAR *list)
1485
    list - an array of SHOW_VAR entries to remove to all_status_vars
1486
           the last entry must be {0,0,SHOW_UNDEF}
1487
1488
  NOTE
1489
    there's lots of room for optimizing this, especially in non-sorted mode,
1490
    but nobody cares - it may be called only in case of failed plugin
1491
    initialization in the mysqld startup.
1492
*/
1493
1494
void remove_status_vars(SHOW_VAR *list)
1495
{
1496
  if (status_vars_inited)
1497
  {
1498
    pthread_mutex_lock(&LOCK_status);
1499
    SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
1500
    int a= 0, b= all_status_vars.elements, c= (a+b)/2;
1501
1502
    for (; list->name; list++)
1503
    {
1504
      int res= 0;
1505
      for (a= 0, b= all_status_vars.elements; b-a > 1; c= (a+b)/2)
1506
      {
1507
        res= show_var_cmp(list, all+c);
1508
        if (res < 0)
1509
          b= c;
1510
        else if (res > 0)
1511
          a= c;
1512
        else
1513
          break;
1514
      }
1515
      if (res == 0)
1516
        all[c].type= SHOW_UNDEF;
1517
    }
1518
    shrink_var_array(&all_status_vars);
1519
    pthread_mutex_unlock(&LOCK_status);
1520
  }
1521
  else
1522
  {
1523
    SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
1524
    uint i;
1525
    for (; list->name; list++)
1526
    {
1527
      for (i= 0; i < all_status_vars.elements; i++)
1528
      {
1529
        if (show_var_cmp(list, all+i))
1530
          continue;
1531
        all[i].type= SHOW_UNDEF;
1532
        break;
1533
      }
1534
    }
1535
    shrink_var_array(&all_status_vars);
1536
  }
1537
}
1538
1539
inline void make_upper(char *buf)
1540
{
1541
  for (; *buf; buf++)
1542
    *buf= my_toupper(system_charset_info, *buf);
1543
}
1544
1545
static bool show_status_array(THD *thd, const char *wild,
1546
                              SHOW_VAR *variables,
1547
                              enum enum_var_type value_type,
1548
                              struct system_status_var *status_var,
1549
                              const char *prefix, TABLE *table,
1550
                              bool ucase_names)
1551
{
1552
  MY_ALIGNED_BYTE_ARRAY(buff_data, SHOW_VAR_FUNC_BUFF_SIZE, long);
1553
  char * const buff= (char *) &buff_data;
1554
  char *prefix_end;
1555
  /* the variable name should not be longer than 64 characters */
1556
  char name_buffer[64];
1557
  int len;
1558
  LEX_STRING null_lex_str;
1559
  SHOW_VAR tmp, *var;
1560
  DBUG_ENTER("show_status_array");
1561
1562
  null_lex_str.str= 0;				// For sys_var->value_ptr()
1563
  null_lex_str.length= 0;
1564
1565
  prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1);
1566
  if (*prefix)
1567
    *prefix_end++= '_';
1568
  len=name_buffer + sizeof(name_buffer) - prefix_end;
1569
1570
  for (; variables->name; variables++)
1571
  {
1572
    strnmov(prefix_end, variables->name, len);
1573
    name_buffer[sizeof(name_buffer)-1]=0;       /* Safety */
1574
    if (ucase_names)
1575
      make_upper(name_buffer);
1576
1577
    /*
1578
      if var->type is SHOW_FUNC, call the function.
1579
      Repeat as necessary, if new var is again SHOW_FUNC
1580
    */
1581
    for (var=variables; var->type == SHOW_FUNC; var= &tmp)
1582
      ((mysql_show_var_func)(var->value))(thd, &tmp, buff);
1583
1584
    SHOW_TYPE show_type=var->type;
1585
    if (show_type == SHOW_ARRAY)
1586
    {
1587
      show_status_array(thd, wild, (SHOW_VAR *) var->value, value_type,
1588
                        status_var, name_buffer, table, ucase_names);
1589
    }
1590
    else
1591
    {
1592
      if (!(wild && wild[0] && wild_case_compare(system_charset_info,
1593
                                                 name_buffer, wild)))
1594
      {
1595
        char *value=var->value;
1596
        const char *pos, *end;                  // We assign a lot of const's
1597
1598
        pthread_mutex_lock(&LOCK_global_system_variables);
1599
1600
        if (show_type == SHOW_SYS)
1601
        {
1602
          show_type= ((sys_var*) value)->show_type();
1603
          value=     (char*) ((sys_var*) value)->value_ptr(thd, value_type,
1604
                                                           &null_lex_str);
1605
        }
1606
1607
        pos= end= buff;
1608
        /*
1609
          note that value may be == buff. All SHOW_xxx code below
1610
          should still work in this case
1611
        */
1612
        switch (show_type) {
1613
        case SHOW_DOUBLE_STATUS:
1614
          value= ((char *) status_var + (ulong) value);
1615
          /* fall through */
1616
        case SHOW_DOUBLE:
1617
          /* 6 is the default precision for '%f' in sprintf() */
1618
          end= buff + my_fcvt(*(double *) value, 6, buff, NULL);
1619
          break;
1620
        case SHOW_LONG_STATUS:
1621
          value= ((char *) status_var + (ulong) value);
1622
          /* fall through */
1623
        case SHOW_LONG:
1624
        case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status()
1625
          end= int10_to_str(*(long*) value, buff, 10);
1626
          break;
1627
        case SHOW_LONGLONG_STATUS:
1628
          value= ((char *) status_var + (ulonglong) value);
1629
          /* fall through */
1630
        case SHOW_LONGLONG:
1631
          end= longlong10_to_str(*(longlong*) value, buff, 10);
1632
          break;
1633
        case SHOW_HA_ROWS:
1634
          end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
1635
          break;
1636
        case SHOW_BOOL:
1637
          end= strmov(buff, *(bool*) value ? "ON" : "OFF");
1638
          break;
1639
        case SHOW_MY_BOOL:
1640
          end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
1641
          break;
1642
        case SHOW_INT:
1643
          end= int10_to_str((long) *(uint32*) value, buff, 10);
1644
          break;
1645
        case SHOW_HAVE:
1646
        {
1647
          SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
1648
          pos= show_comp_option_name[(int) tmp];
1649
          end= strend(pos);
1650
          break;
1651
        }
1652
        case SHOW_CHAR:
1653
        {
1654
          if (!(pos= value))
1655
            pos= "";
1656
          end= strend(pos);
1657
          break;
1658
        }
1659
       case SHOW_CHAR_PTR:
1660
        {
1661
          if (!(pos= *(char**) value))
1662
            pos= "";
1663
          end= strend(pos);
1664
          break;
1665
        }
1666
        case SHOW_KEY_CACHE_LONG:
1667
          value= (char*) dflt_key_cache + (ulong)value;
1668
          end= int10_to_str(*(long*) value, buff, 10);
1669
          break;
1670
        case SHOW_KEY_CACHE_LONGLONG:
1671
          value= (char*) dflt_key_cache + (ulong)value;
1672
	  end= longlong10_to_str(*(longlong*) value, buff, 10);
1673
	  break;
1674
        case SHOW_UNDEF:
1675
          break;                                        // Return empty string
1676
        case SHOW_SYS:                                  // Cannot happen
1677
        default:
1678
          DBUG_ASSERT(0);
1679
          break;
1680
        }
1681
        restore_record(table, s->default_values);
1682
        table->field[0]->store(name_buffer, strlen(name_buffer),
1683
                               system_charset_info);
1684
        table->field[1]->store(pos, (uint32) (end - pos), system_charset_info);
1685
        table->field[1]->set_notnull();
1686
1687
        pthread_mutex_unlock(&LOCK_global_system_variables);
1688
1689
        if (schema_table_store_record(thd, table))
1690
          DBUG_RETURN(TRUE);
1691
      }
1692
    }
1693
  }
1694
1695
  DBUG_RETURN(FALSE);
1696
}
1697
1698
1699
/* collect status for all running threads */
1700
1701
void calc_sum_of_all_status(STATUS_VAR *to)
1702
{
1703
  DBUG_ENTER("calc_sum_of_all_status");
1704
1705
  /* Ensure that thread id not killed during loop */
1706
  VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
1707
1708
  I_List_iterator<THD> it(threads);
1709
  THD *tmp;
1710
  
1711
  /* Get global values as base */
1712
  *to= global_status_var;
1713
  
1714
  /* Add to this status from existing threads */
1715
  while ((tmp= it++))
1716
    add_to_status(to, &tmp->status_var);
1717
  
1718
  VOID(pthread_mutex_unlock(&LOCK_thread_count));
1719
  DBUG_VOID_RETURN;
1720
}
1721
1722
1723
/* This is only used internally, but we need it here as a forward reference */
1724
extern ST_SCHEMA_TABLE schema_tables[];
1725
1726
typedef struct st_lookup_field_values
1727
{
1728
  LEX_STRING db_value, table_value;
1729
  bool wild_db_value, wild_table_value;
1730
} LOOKUP_FIELD_VALUES;
1731
1732
1733
/*
1734
  Store record to I_S table, convert HEAP table
1735
  to MyISAM if necessary
1736
1737
  SYNOPSIS
1738
    schema_table_store_record()
1739
    thd                   thread handler
1740
    table                 Information schema table to be updated
1741
1742
  RETURN
1743
    0	                  success
1744
    1	                  error
1745
*/
1746
1747
bool schema_table_store_record(THD *thd, TABLE *table)
1748
{
1749
  int error;
1750
  if ((error= table->file->ha_write_row(table->record[0])))
1751
  {
1752
    TMP_TABLE_PARAM *param= table->pos_in_table_list->schema_table_param;
1753
1754
    if (create_myisam_from_heap(thd, table, param->start_recinfo, 
1755
                                &param->recinfo, error, 0))
1756
      return 1;
1757
  }
1758
  return 0;
1759
}
1760
1761
1762
int make_table_list(THD *thd, SELECT_LEX *sel,
1763
                    LEX_STRING *db_name, LEX_STRING *table_name)
1764
{
1765
  Table_ident *table_ident;
1766
  table_ident= new Table_ident(thd, *db_name, *table_name, 1);
1767
  sel->init_query();
1768
  if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ))
1769
    return 1;
1770
  return 0;
1771
}
1772
1773
1774
/**
1775
  @brief    Get lookup value from the part of 'WHERE' condition 
1776
1777
  @details This function gets lookup value from 
1778
           the part of 'WHERE' condition if it's possible and 
1779
           fill appropriate lookup_field_vals struct field
1780
           with this value.
1781
1782
  @param[in]      thd                   thread handler
1783
  @param[in]      item_func             part of WHERE condition
1784
  @param[in]      table                 I_S table
1785
  @param[in, out] lookup_field_vals     Struct which holds lookup values 
1786
1787
  @return
1788
    0             success
1789
    1             error, there can be no matching records for the condition
1790
*/
1791
1792
bool get_lookup_value(THD *thd, Item_func *item_func,
1793
                      TABLE_LIST *table, 
1794
                      LOOKUP_FIELD_VALUES *lookup_field_vals)
1795
{
1796
  ST_SCHEMA_TABLE *schema_table= table->schema_table;
1797
  ST_FIELD_INFO *field_info= schema_table->fields_info;
1798
  const char *field_name1= schema_table->idx_field1 >= 0 ?
1799
    field_info[schema_table->idx_field1].field_name : "";
1800
  const char *field_name2= schema_table->idx_field2 >= 0 ?
1801
    field_info[schema_table->idx_field2].field_name : "";
1802
1803
  if (item_func->functype() == Item_func::EQ_FUNC ||
1804
      item_func->functype() == Item_func::EQUAL_FUNC)
1805
  {
1806
    int idx_field, idx_val;
1807
    char tmp[MAX_FIELD_WIDTH];
1808
    String *tmp_str, str_buff(tmp, sizeof(tmp), system_charset_info);
1809
    Item_field *item_field;
1810
    CHARSET_INFO *cs= system_charset_info;
1811
1812
    if (item_func->arguments()[0]->type() == Item::FIELD_ITEM &&
1813
        item_func->arguments()[1]->const_item())
1814
    {
1815
      idx_field= 0;
1816
      idx_val= 1;
1817
    }
1818
    else if (item_func->arguments()[1]->type() == Item::FIELD_ITEM &&
1819
             item_func->arguments()[0]->const_item())
1820
    {
1821
      idx_field= 1;
1822
      idx_val= 0;
1823
    }
1824
    else
1825
      return 0;
1826
1827
    item_field= (Item_field*) item_func->arguments()[idx_field];
1828
    if (table->table != item_field->field->table)
1829
      return 0;
1830
    tmp_str= item_func->arguments()[idx_val]->val_str(&str_buff);
1831
1832
    /* impossible value */
1833
    if (!tmp_str)
1834
      return 1;
1835
1836
    /* Lookup value is database name */
1837
    if (!cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1),
1838
                               (uchar *) item_field->field_name,
1839
                               strlen(item_field->field_name), 0))
1840
    {
1841
      thd->make_lex_string(&lookup_field_vals->db_value, tmp_str->ptr(),
1842
                           tmp_str->length(), FALSE);
1843
    }
1844
    /* Lookup value is table name */
1845
    else if (!cs->coll->strnncollsp(cs, (uchar *) field_name2,
1846
                                    strlen(field_name2),
1847
                                    (uchar *) item_field->field_name,
1848
                                    strlen(item_field->field_name), 0))
1849
    {
1850
      thd->make_lex_string(&lookup_field_vals->table_value, tmp_str->ptr(),
1851
                           tmp_str->length(), FALSE);
1852
    }
1853
  }
1854
  return 0;
1855
}
1856
1857
1858
/**
1859
  @brief    Calculates lookup values from 'WHERE' condition 
1860
1861
  @details This function calculates lookup value(database name, table name)
1862
           from 'WHERE' condition if it's possible and 
1863
           fill lookup_field_vals struct fields with these values.
1864
1865
  @param[in]      thd                   thread handler
1866
  @param[in]      cond                  WHERE condition
1867
  @param[in]      table                 I_S table
1868
  @param[in, out] lookup_field_vals     Struct which holds lookup values 
1869
1870
  @return
1871
    0             success
1872
    1             error, there can be no matching records for the condition
1873
*/
1874
1875
bool calc_lookup_values_from_cond(THD *thd, COND *cond, TABLE_LIST *table,
1876
                                  LOOKUP_FIELD_VALUES *lookup_field_vals)
1877
{
1878
  if (!cond)
1879
    return 0;
1880
1881
  if (cond->type() == Item::COND_ITEM)
1882
  {
1883
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
1884
    {
1885
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1886
      Item *item;
1887
      while ((item= li++))
1888
      {
1889
        if (item->type() == Item::FUNC_ITEM)
1890
        {
1891
          if (get_lookup_value(thd, (Item_func*)item, table, lookup_field_vals))
1892
            return 1;
1893
        }
1894
        else
1895
        {
1896
          if (calc_lookup_values_from_cond(thd, item, table, lookup_field_vals))
1897
            return 1;
1898
        }
1899
      }
1900
    }
1901
    return 0;
1902
  }
1903
  else if (cond->type() == Item::FUNC_ITEM &&
1904
           get_lookup_value(thd, (Item_func*) cond, table, lookup_field_vals))
1905
    return 1;
1906
  return 0;
1907
}
1908
1909
1910
bool uses_only_table_name_fields(Item *item, TABLE_LIST *table)
1911
{
1912
  if (item->type() == Item::FUNC_ITEM)
1913
  {
1914
    Item_func *item_func= (Item_func*)item;
1915
    for (uint i=0; i<item_func->argument_count(); i++)
1916
    {
1917
      if (!uses_only_table_name_fields(item_func->arguments()[i], table))
1918
        return 0;
1919
    }
1920
  }
1921
  else if (item->type() == Item::FIELD_ITEM)
1922
  {
1923
    Item_field *item_field= (Item_field*)item;
1924
    CHARSET_INFO *cs= system_charset_info;
1925
    ST_SCHEMA_TABLE *schema_table= table->schema_table;
1926
    ST_FIELD_INFO *field_info= schema_table->fields_info;
1927
    const char *field_name1= schema_table->idx_field1 >= 0 ?
1928
      field_info[schema_table->idx_field1].field_name : "";
1929
    const char *field_name2= schema_table->idx_field2 >= 0 ?
1930
      field_info[schema_table->idx_field2].field_name : "";
1931
    if (table->table != item_field->field->table ||
1932
        (cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1),
1933
                               (uchar *) item_field->field_name,
1934
                               strlen(item_field->field_name), 0) &&
1935
         cs->coll->strnncollsp(cs, (uchar *) field_name2, strlen(field_name2),
1936
                               (uchar *) item_field->field_name,
1937
                               strlen(item_field->field_name), 0)))
1938
      return 0;
1939
  }
1940
  else if (item->type() == Item::REF_ITEM)
1941
    return uses_only_table_name_fields(item->real_item(), table);
1942
1943
  if (item->type() == Item::SUBSELECT_ITEM && !item->const_item())
1944
    return 0;
1945
1946
  return 1;
1947
}
1948
1949
1950
static COND * make_cond_for_info_schema(COND *cond, TABLE_LIST *table)
1951
{
1952
  if (!cond)
1953
    return (COND*) 0;
1954
  if (cond->type() == Item::COND_ITEM)
1955
  {
1956
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
1957
    {
1958
      /* Create new top level AND item */
1959
      Item_cond_and *new_cond=new Item_cond_and;
1960
      if (!new_cond)
1961
	return (COND*) 0;
1962
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1963
      Item *item;
1964
      while ((item=li++))
1965
      {
1966
	Item *fix= make_cond_for_info_schema(item, table);
1967
	if (fix)
1968
	  new_cond->argument_list()->push_back(fix);
1969
      }
1970
      switch (new_cond->argument_list()->elements) {
1971
      case 0:
1972
	return (COND*) 0;
1973
      case 1:
1974
	return new_cond->argument_list()->head();
1975
      default:
1976
	new_cond->quick_fix_field();
1977
	return new_cond;
1978
      }
1979
    }
1980
    else
1981
    {						// Or list
1982
      Item_cond_or *new_cond=new Item_cond_or;
1983
      if (!new_cond)
1984
	return (COND*) 0;
1985
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1986
      Item *item;
1987
      while ((item=li++))
1988
      {
1989
	Item *fix=make_cond_for_info_schema(item, table);
1990
	if (!fix)
1991
	  return (COND*) 0;
1992
	new_cond->argument_list()->push_back(fix);
1993
      }
1994
      new_cond->quick_fix_field();
1995
      new_cond->top_level_item();
1996
      return new_cond;
1997
    }
1998
  }
1999
2000
  if (!uses_only_table_name_fields(cond, table))
2001
    return (COND*) 0;
2002
  return cond;
2003
}
2004
2005
2006
/**
2007
  @brief   Calculate lookup values(database name, table name)
2008
2009
  @details This function calculates lookup values(database name, table name)
2010
           from 'WHERE' condition or wild values (for 'SHOW' commands only)
2011
           from LEX struct and fill lookup_field_vals struct field
2012
           with these values.
2013
2014
  @param[in]      thd                   thread handler
2015
  @param[in]      cond                  WHERE condition
2016
  @param[in]      tables                I_S table
2017
  @param[in, out] lookup_field_values   Struct which holds lookup values 
2018
2019
  @return
2020
    0             success
2021
    1             error, there can be no matching records for the condition
2022
*/
2023
2024
bool get_lookup_field_values(THD *thd, COND *cond, TABLE_LIST *tables,
2025
                             LOOKUP_FIELD_VALUES *lookup_field_values)
2026
{
2027
  LEX *lex= thd->lex;
2028
  const char *wild= lex->wild ? lex->wild->ptr() : NullS;
2029
  bzero((char*) lookup_field_values, sizeof(LOOKUP_FIELD_VALUES));
2030
  switch (lex->sql_command) {
2031
  case SQLCOM_SHOW_DATABASES:
2032
    if (wild)
2033
    {
2034
      lookup_field_values->db_value.str= (char*) wild;
2035
      lookup_field_values->db_value.length= strlen(wild);
2036
      lookup_field_values->wild_db_value= 1;
2037
    }
2038
    return 0;
2039
  case SQLCOM_SHOW_TABLES:
2040
  case SQLCOM_SHOW_TABLE_STATUS:
2041
    lookup_field_values->db_value.str= lex->select_lex.db;
2042
    lookup_field_values->db_value.length=strlen(lex->select_lex.db);
2043
    if (wild)
2044
    {
2045
      lookup_field_values->table_value.str= (char*)wild;
2046
      lookup_field_values->table_value.length= strlen(wild);
2047
      lookup_field_values->wild_table_value= 1;
2048
    }
2049
    return 0;
2050
  default:
2051
    /*
2052
      The "default" is for queries over I_S.
2053
      All previous cases handle SHOW commands.
2054
    */
2055
    return calc_lookup_values_from_cond(thd, cond, tables, lookup_field_values);
2056
  }
2057
}
2058
2059
2060
enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table)
2061
{
2062
  return (enum enum_schema_tables) (schema_table - &schema_tables[0]);
2063
}
2064
2065
2066
/*
2067
  Create db names list. Information schema name always is first in list
2068
2069
  SYNOPSIS
2070
    make_db_list()
2071
    thd                   thread handler
2072
    files                 list of db names
2073
    wild                  wild string
2074
    idx_field_vals        idx_field_vals->db_name contains db name or
2075
                          wild string
2076
    with_i_schema         returns 1 if we added 'IS' name to list
2077
                          otherwise returns 0 
2078
2079
  RETURN
2080
    zero                  success
2081
    non-zero              error
2082
*/
2083
2084
int make_db_list(THD *thd, List<LEX_STRING> *files,
2085
                 LOOKUP_FIELD_VALUES *lookup_field_vals,
2086
                 bool *with_i_schema)
2087
{
2088
  LEX_STRING *i_s_name_copy= 0;
2089
  i_s_name_copy= thd->make_lex_string(i_s_name_copy,
2090
                                      INFORMATION_SCHEMA_NAME.str,
2091
                                      INFORMATION_SCHEMA_NAME.length, TRUE);
2092
  *with_i_schema= 0;
2093
  if (lookup_field_vals->wild_db_value)
2094
  {
2095
    /*
2096
      This part of code is only for SHOW DATABASES command.
2097
      idx_field_vals->db_value can be 0 when we don't use
2098
      LIKE clause (see also get_index_field_values() function)
2099
    */
2100
    if (!lookup_field_vals->db_value.str ||
2101
        !wild_case_compare(system_charset_info, 
2102
                           INFORMATION_SCHEMA_NAME.str,
2103
                           lookup_field_vals->db_value.str))
2104
    {
2105
      *with_i_schema= 1;
2106
      if (files->push_back(i_s_name_copy))
2107
        return 1;
2108
    }
2109
    return (find_files(thd, files, NullS, mysql_data_home,
2110
                       lookup_field_vals->db_value.str, 1) != FIND_FILES_OK);
2111
  }
2112
2113
2114
  /*
2115
    If we have db lookup vaule we just add it to list and
2116
    exit from the function
2117
  */
2118
  if (lookup_field_vals->db_value.str)
2119
  {
2120
    if (!my_strcasecmp(system_charset_info, INFORMATION_SCHEMA_NAME.str,
2121
                       lookup_field_vals->db_value.str))
2122
    {
2123
      *with_i_schema= 1;
2124
      if (files->push_back(i_s_name_copy))
2125
        return 1;
2126
      return 0;
2127
    }
2128
    if (files->push_back(&lookup_field_vals->db_value))
2129
      return 1;
2130
    return 0;
2131
  }
2132
2133
  /*
2134
    Create list of existing databases. It is used in case
2135
    of select from information schema table
2136
  */
2137
  if (files->push_back(i_s_name_copy))
2138
    return 1;
2139
  *with_i_schema= 1;
2140
  return (find_files(thd, files, NullS,
2141
                     mysql_data_home, NullS, 1) != FIND_FILES_OK);
2142
}
2143
2144
2145
struct st_add_schema_table 
2146
{
2147
  List<LEX_STRING> *files;
2148
  const char *wild;
2149
};
2150
2151
2152
static my_bool add_schema_table(THD *thd, plugin_ref plugin,
2153
                                void* p_data)
2154
{
2155
  LEX_STRING *file_name= 0;
2156
  st_add_schema_table *data= (st_add_schema_table *)p_data;
2157
  List<LEX_STRING> *file_list= data->files;
2158
  const char *wild= data->wild;
2159
  ST_SCHEMA_TABLE *schema_table= plugin_data(plugin, ST_SCHEMA_TABLE *);
2160
  DBUG_ENTER("add_schema_table");
2161
2162
  if (schema_table->hidden)
2163
      DBUG_RETURN(0);
2164
  if (wild)
2165
  {
2166
    if (lower_case_table_names)
2167
    {
2168
      if (wild_case_compare(files_charset_info,
2169
                            schema_table->table_name,
2170
                            wild))
2171
        DBUG_RETURN(0);
2172
    }
2173
    else if (wild_compare(schema_table->table_name, wild, 0))
2174
      DBUG_RETURN(0);
2175
  }
2176
2177
  if ((file_name= thd->make_lex_string(file_name, schema_table->table_name,
2178
                                       strlen(schema_table->table_name),
2179
                                       TRUE)) &&
2180
      !file_list->push_back(file_name))
2181
    DBUG_RETURN(0);
2182
  DBUG_RETURN(1);
2183
}
2184
2185
2186
int schema_tables_add(THD *thd, List<LEX_STRING> *files, const char *wild)
2187
{
2188
  LEX_STRING *file_name= 0;
2189
  ST_SCHEMA_TABLE *tmp_schema_table= schema_tables;
2190
  st_add_schema_table add_data;
2191
  DBUG_ENTER("schema_tables_add");
2192
2193
  for (; tmp_schema_table->table_name; tmp_schema_table++)
2194
  {
2195
    if (tmp_schema_table->hidden)
2196
      continue;
2197
    if (wild)
2198
    {
2199
      if (lower_case_table_names)
2200
      {
2201
        if (wild_case_compare(files_charset_info,
2202
                              tmp_schema_table->table_name,
2203
                              wild))
2204
          continue;
2205
      }
2206
      else if (wild_compare(tmp_schema_table->table_name, wild, 0))
2207
        continue;
2208
    }
2209
    if ((file_name= 
2210
         thd->make_lex_string(file_name, tmp_schema_table->table_name,
2211
                              strlen(tmp_schema_table->table_name), TRUE)) &&
2212
        !files->push_back(file_name))
2213
      continue;
2214
    DBUG_RETURN(1);
2215
  }
2216
2217
  add_data.files= files;
2218
  add_data.wild= wild;
2219
  if (plugin_foreach(thd, add_schema_table,
2220
                     MYSQL_INFORMATION_SCHEMA_PLUGIN, &add_data))
2221
      DBUG_RETURN(1);
2222
2223
  DBUG_RETURN(0);
2224
}
2225
2226
2227
/**
2228
  @brief          Create table names list
2229
2230
  @details        The function creates the list of table names in
2231
                  database
2232
2233
  @param[in]      thd                   thread handler
2234
  @param[in]      table_names           List of table names in database
2235
  @param[in]      lex                   pointer to LEX struct
2236
  @param[in]      lookup_field_vals     pointer to LOOKUP_FIELD_VALUE struct
2237
  @param[in]      with_i_schema         TRUE means that we add I_S tables to list
2238
  @param[in]      db_name               database name
2239
2240
  @return         Operation status
2241
    @retval       0           ok
2242
    @retval       1           fatal error
2243
    @retval       2           Not fatal error; Safe to ignore this file list
2244
*/
2245
2246
static int
2247
make_table_name_list(THD *thd, List<LEX_STRING> *table_names, LEX *lex,
2248
                     LOOKUP_FIELD_VALUES *lookup_field_vals,
2249
                     bool with_i_schema, LEX_STRING *db_name)
2250
{
2251
  char path[FN_REFLEN];
2252
  build_table_filename(path, sizeof(path), db_name->str, "", "", 0);
2253
  if (!lookup_field_vals->wild_table_value &&
2254
      lookup_field_vals->table_value.str)
2255
  {
2256
    if (with_i_schema)
2257
    {
2258
      if (find_schema_table(thd, lookup_field_vals->table_value.str))
2259
      {
2260
        if (table_names->push_back(&lookup_field_vals->table_value))
2261
          return 1;
2262
      }
2263
    }
2264
    else
2265
    {    
2266
      if (table_names->push_back(&lookup_field_vals->table_value))
2267
        return 1;
2268
    }
2269
    return 0;
2270
  }
2271
2272
  /*
2273
    This call will add all matching the wildcards (if specified) IS tables
2274
    to the list
2275
  */
2276
  if (with_i_schema)
2277
    return (schema_tables_add(thd, table_names,
2278
                              lookup_field_vals->table_value.str));
2279
2280
  find_files_result res= find_files(thd, table_names, db_name->str, path,
2281
                                    lookup_field_vals->table_value.str, 0);
2282
  if (res != FIND_FILES_OK)
2283
  {
2284
    /*
2285
      Downgrade errors about problems with database directory to
2286
      warnings if this is not a 'SHOW' command.  Another thread
2287
      may have dropped database, and we may still have a name
2288
      for that directory.
2289
    */
2290
    if (res == FIND_FILES_DIR)
2291
    {
2292
      if (lex->sql_command != SQLCOM_SELECT)
2293
        return 1;
2294
      thd->clear_error();
2295
      return 2;
2296
    }
2297
    return 1;
2298
  }
2299
  return 0;
2300
}
2301
2302
2303
/**
2304
  @brief          Fill I_S table for SHOW COLUMNS|INDEX commands
2305
2306
  @param[in]      thd                      thread handler
2307
  @param[in]      tables                   TABLE_LIST for I_S table
2308
  @param[in]      schema_table             pointer to I_S structure
2309
  @param[in]      open_tables_state_backup pointer to Open_tables_state object
2310
                                           which is used to save|restore original
2311
                                           status of variables related to
2312
                                           open tables state
2313
2314
  @return         Operation status
2315
    @retval       0           success
2316
    @retval       1           error
2317
*/
2318
2319
static int 
2320
fill_schema_show_cols_or_idxs(THD *thd, TABLE_LIST *tables,
2321
                              ST_SCHEMA_TABLE *schema_table,
2322
                              Open_tables_state *open_tables_state_backup)
2323
{
2324
  LEX *lex= thd->lex;
2325
  bool res;
2326
  LEX_STRING tmp_lex_string, tmp_lex_string1, *db_name, *table_name;
2327
  enum_sql_command save_sql_command= lex->sql_command;
2328
  TABLE_LIST *show_table_list= (TABLE_LIST*) tables->schema_select_lex->
2329
    table_list.first;
2330
  TABLE *table= tables->table;
2331
  int error= 1;
2332
  DBUG_ENTER("fill_schema_show");
2333
2334
  lex->all_selects_list= tables->schema_select_lex;
2335
  /*
2336
    Restore thd->temporary_tables to be able to process
2337
    temporary tables(only for 'show index' & 'show columns').
2338
    This should be changed when processing of temporary tables for
2339
    I_S tables will be done.
2340
  */
2341
  thd->temporary_tables= open_tables_state_backup->temporary_tables;
2342
  /*
2343
    Let us set fake sql_command so views won't try to merge
2344
    themselves into main statement. If we don't do this,
2345
    SELECT * from information_schema.xxxx will cause problems.
2346
    SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()' 
2347
  */
2348
  lex->sql_command= SQLCOM_SHOW_FIELDS;
2349
  res= open_normal_and_derived_tables(thd, show_table_list,
2350
                                      MYSQL_LOCK_IGNORE_FLUSH);
2351
  lex->sql_command= save_sql_command;
2352
  /*
2353
    get_all_tables() returns 1 on failure and 0 on success thus
2354
    return only these and not the result code of ::process_table()
2355
2356
    We should use show_table_list->alias instead of 
2357
    show_table_list->table_name because table_name
2358
    could be changed during opening of I_S tables. It's safe
2359
    to use alias because alias contains original table name 
2360
    in this case(this part of code is used only for 
2361
    'show columns' & 'show statistics' commands).
2362
  */
2363
   table_name= thd->make_lex_string(&tmp_lex_string1, show_table_list->alias,
2364
                                    strlen(show_table_list->alias), FALSE);
2365
   db_name= thd->make_lex_string(&tmp_lex_string, show_table_list->db,
2366
                                 show_table_list->db_length, FALSE);
2367
      
2368
2369
   error= test(schema_table->process_table(thd, show_table_list,
2370
                                           table, res, db_name,
2371
                                           table_name));
2372
   thd->temporary_tables= 0;
2373
   close_tables_for_reopen(thd, &show_table_list);
2374
   DBUG_RETURN(error);
2375
}
2376
2377
2378
/**
2379
  @brief          Fill I_S table for SHOW TABLE NAMES commands
2380
2381
  @param[in]      thd                      thread handler
2382
  @param[in]      table                    TABLE struct for I_S table
2383
  @param[in]      db_name                  database name
2384
  @param[in]      table_name               table name
2385
  @param[in]      with_i_schema            I_S table if TRUE
2386
2387
  @return         Operation status
2388
    @retval       0           success
2389
    @retval       1           error
2390
*/
2391
2392
static int fill_schema_table_names(THD *thd, TABLE *table,
2393
                                   LEX_STRING *db_name, LEX_STRING *table_name,
2394
                                   bool with_i_schema)
2395
{
2396
  if (with_i_schema)
2397
  {
2398
    table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"),
2399
                           system_charset_info);
2400
  }
2401
  else
2402
  {
2403
    enum legacy_db_type not_used;
2404
    char path[FN_REFLEN];
2405
    (void) build_table_filename(path, sizeof(path), db_name->str, 
2406
                                table_name->str, reg_ext, 0);
2407
    switch (mysql_frm_type(thd, path, &not_used)) {
2408
    case FRMTYPE_ERROR:
2409
      table->field[3]->store(STRING_WITH_LEN("ERROR"),
2410
                             system_charset_info);
2411
      break;
2412
    case FRMTYPE_TABLE:
2413
      table->field[3]->store(STRING_WITH_LEN("BASE TABLE"),
2414
                             system_charset_info);
2415
      break;
2416
    default:
2417
      DBUG_ASSERT(0);
2418
    }
2419
    if (thd->is_error() && thd->main_da.sql_errno() == ER_NO_SUCH_TABLE)
2420
    {
2421
      thd->clear_error();
2422
      return 0;
2423
    }
2424
  }
2425
  if (schema_table_store_record(thd, table))
2426
    return 1;
2427
  return 0;
2428
}
2429
2430
2431
/**
2432
  @brief          Get open table method
2433
2434
  @details        The function calculates the method which will be used
2435
                  for table opening:
2436
                  SKIP_OPEN_TABLE - do not open table
2437
                  OPEN_FRM_ONLY   - open FRM file only
2438
                  OPEN_FULL_TABLE - open FRM, data, index files
2439
  @param[in]      tables               I_S table table_list
2440
  @param[in]      schema_table         I_S table struct
2441
  @param[in]      schema_table_idx     I_S table index
2442
2443
  @return         return a set of flags
2444
    @retval       SKIP_OPEN_TABLE | OPEN_FRM_ONLY | OPEN_FULL_TABLE
2445
*/
2446
2447
static uint get_table_open_method(TABLE_LIST *tables,
2448
                                  ST_SCHEMA_TABLE *schema_table,
2449
                                  enum enum_schema_tables schema_table_idx)
2450
{
2451
  /*
2452
    determine which method will be used for table opening
2453
  */
2454
  if (schema_table->i_s_requested_object & OPTIMIZE_I_S_TABLE)
2455
  {
2456
    Field **ptr, *field;
2457
    int table_open_method= 0, field_indx= 0;
2458
    for (ptr=tables->table->field; (field= *ptr) ; ptr++)
2459
    {
2460
      if (bitmap_is_set(tables->table->read_set, field->field_index))
2461
        table_open_method|= schema_table->fields_info[field_indx].open_method;
2462
      field_indx++;
2463
    }
2464
    return table_open_method;
2465
  }
2466
  /* I_S tables which use get_all_tables but can not be optimized */
2467
  return (uint) OPEN_FULL_TABLE;
2468
}
2469
2470
2471
/**
2472
  @brief          Fill I_S table with data from FRM file only
2473
2474
  @param[in]      thd                      thread handler
2475
  @param[in]      table                    TABLE struct for I_S table
2476
  @param[in]      schema_table             I_S table struct
2477
  @param[in]      db_name                  database name
2478
  @param[in]      table_name               table name
2479
  @param[in]      schema_table_idx         I_S table index
2480
2481
  @return         Operation status
2482
    @retval       0           Table is processed and we can continue
2483
                              with new table
2484
    @retval       1           It's view and we have to use
2485
                              open_tables function for this table
2486
*/
2487
2488
static int fill_schema_table_from_frm(THD *thd,TABLE_LIST *tables,
2489
                                      ST_SCHEMA_TABLE *schema_table, 
2490
                                      LEX_STRING *db_name,
2491
                                      LEX_STRING *table_name,
2492
                                      enum enum_schema_tables schema_table_idx)
2493
{
2494
  TABLE *table= tables->table;
2495
  TABLE_SHARE *share;
2496
  TABLE tbl;
2497
  TABLE_LIST table_list;
2498
  uint res= 0;
2499
  int error;
2500
  char key[MAX_DBKEY_LENGTH];
2501
  uint key_length;
2502
2503
  bzero((char*) &table_list, sizeof(TABLE_LIST));
2504
  bzero((char*) &tbl, sizeof(TABLE));
2505
2506
  table_list.table_name= table_name->str;
2507
  table_list.db= db_name->str;
2508
2509
  key_length= create_table_def_key(thd, key, &table_list, 0);
2510
  pthread_mutex_lock(&LOCK_open);
2511
  share= get_table_share(thd, &table_list, key,
2512
                         key_length, OPEN_VIEW, &error);
2513
  if (!share)
2514
  {
2515
    res= 0;
2516
    goto err;
2517
  }
2518
2519
  {
2520
    tbl.s= share;
2521
    table_list.table= &tbl;
2522
    res= schema_table->process_table(thd, &table_list, table,
2523
                                     res, db_name, table_name);
2524
  }
2525
2526
  release_table_share(share, RELEASE_NORMAL);
2527
2528
err:
2529
  pthread_mutex_unlock(&LOCK_open);
2530
  thd->clear_error();
2531
  return res;
2532
}
2533
2534
2535
2536
/**
2537
  @brief          Fill I_S tables whose data are retrieved
2538
                  from frm files and storage engine
2539
2540
  @details        The information schema tables are internally represented as
2541
                  temporary tables that are filled at query execution time.
2542
                  Those I_S tables whose data are retrieved
2543
                  from frm files and storage engine are filled by the function
2544
                  get_all_tables().
2545
2546
  @param[in]      thd                      thread handler
2547
  @param[in]      tables                   I_S table
2548
  @param[in]      cond                     'WHERE' condition
2549
2550
  @return         Operation status
2551
    @retval       0                        success
2552
    @retval       1                        error
2553
*/
2554
2555
int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
2556
{
2557
  LEX *lex= thd->lex;
2558
  TABLE *table= tables->table;
2559
  SELECT_LEX *old_all_select_lex= lex->all_selects_list;
2560
  enum_sql_command save_sql_command= lex->sql_command;
2561
  SELECT_LEX *lsel= tables->schema_select_lex;
2562
  ST_SCHEMA_TABLE *schema_table= tables->schema_table;
2563
  SELECT_LEX sel;
2564
  LOOKUP_FIELD_VALUES lookup_field_vals;
2565
  LEX_STRING *db_name, *table_name;
2566
  bool with_i_schema;
2567
  enum enum_schema_tables schema_table_idx;
2568
  List<LEX_STRING> db_names;
2569
  List_iterator_fast<LEX_STRING> it(db_names);
2570
  COND *partial_cond= 0;
2571
  uint derived_tables= lex->derived_tables; 
2572
  int error= 1;
2573
  Open_tables_state open_tables_state_backup;
2574
  Query_tables_list query_tables_list_backup;
2575
  uint table_open_method;
2576
  bool old_value= thd->no_warnings_for_error;
2577
  DBUG_ENTER("get_all_tables");
2578
2579
  lex->reset_n_backup_query_tables_list(&query_tables_list_backup);
2580
2581
  /*
2582
    We should not introduce deadlocks even if we already have some
2583
    tables open and locked, since we won't lock tables which we will
2584
    open and will ignore possible name-locks for these tables.
2585
  */
2586
  thd->reset_n_backup_open_tables_state(&open_tables_state_backup);
2587
2588
  schema_table_idx= get_schema_table_idx(schema_table);
2589
  tables->table_open_method= table_open_method=
2590
    get_table_open_method(tables, schema_table, schema_table_idx);
2591
  DBUG_PRINT("open_method", ("%d", tables->table_open_method));
2592
  /* 
2593
    this branch processes SHOW FIELDS, SHOW INDEXES commands.
2594
    see sql_parse.cc, prepare_schema_table() function where
2595
    this values are initialized
2596
  */
2597
  if (lsel && lsel->table_list.first)
2598
  {
2599
    error= fill_schema_show_cols_or_idxs(thd, tables, schema_table,
2600
                                         &open_tables_state_backup);
2601
    goto err;
2602
  }
2603
2604
  if (get_lookup_field_values(thd, cond, tables, &lookup_field_vals))
2605
  {
2606
    error= 0;
2607
    goto err;
2608
  }
2609
  DBUG_PRINT("INDEX VALUES",("db_name='%s', table_name='%s'",
2610
                             STR_OR_NIL(lookup_field_vals.db_value.str),
2611
                             STR_OR_NIL(lookup_field_vals.table_value.str)));
2612
2613
  if (!lookup_field_vals.wild_db_value && !lookup_field_vals.wild_table_value)
2614
  {
2615
    /* 
2616
      if lookup value is empty string then
2617
      it's impossible table name or db name
2618
    */
2619
    if (lookup_field_vals.db_value.str &&
2620
        !lookup_field_vals.db_value.str[0] ||
2621
        lookup_field_vals.table_value.str &&
2622
        !lookup_field_vals.table_value.str[0])
2623
    {
2624
      error= 0;
2625
      goto err;
2626
    }
2627
  }
2628
2629
  if (lookup_field_vals.db_value.length &&
2630
      !lookup_field_vals.wild_db_value)
2631
    tables->has_db_lookup_value= TRUE;
2632
  if (lookup_field_vals.table_value.length &&
2633
      !lookup_field_vals.wild_table_value) 
2634
    tables->has_table_lookup_value= TRUE;
2635
2636
  if (tables->has_db_lookup_value && tables->has_table_lookup_value)
2637
    partial_cond= 0;
2638
  else
2639
    partial_cond= make_cond_for_info_schema(cond, tables);
2640
2641
  if (lex->describe)
2642
  {
2643
    /* EXPLAIN SELECT */
2644
    error= 0;
2645
    goto err;
2646
  }
2647
2648
  if (make_db_list(thd, &db_names, &lookup_field_vals, &with_i_schema))
2649
    goto err;
2650
  it.rewind(); /* To get access to new elements in basis list */
2651
  while ((db_name= it++))
2652
  {
2653
    {
2654
      thd->no_warnings_for_error= 1;
2655
      List<LEX_STRING> table_names;
2656
      int res= make_table_name_list(thd, &table_names, lex,
2657
                                    &lookup_field_vals,
2658
                                    with_i_schema, db_name);
2659
      if (res == 2)   /* Not fatal error, continue */
2660
        continue;
2661
      if (res)
2662
        goto err;
2663
2664
      List_iterator_fast<LEX_STRING> it_files(table_names);
2665
      while ((table_name= it_files++))
2666
      {
2667
	restore_record(table, s->default_values);
2668
        table->field[schema_table->idx_field1]->
2669
          store(db_name->str, db_name->length, system_charset_info);
2670
        table->field[schema_table->idx_field2]->
2671
          store(table_name->str, table_name->length, system_charset_info);
2672
2673
        if (!partial_cond || partial_cond->val_int())
2674
        {
2675
          /*
2676
            If table is I_S.tables and open_table_method is 0 (eg SKIP_OPEN)
2677
            we can skip table opening and we don't have lookup value for 
2678
            table name or lookup value is wild string(table name list is
2679
            already created by make_table_name_list() function).
2680
          */
2681
          if (!table_open_method && schema_table_idx == SCH_TABLES &&
2682
              (!lookup_field_vals.table_value.length ||
2683
               lookup_field_vals.wild_table_value))
2684
          {
2685
            if (schema_table_store_record(thd, table))
2686
              goto err;      /* Out of space in temporary table */
2687
            continue;
2688
          }
2689
2690
          /* SHOW TABLE NAMES command */
2691
          if (schema_table_idx == SCH_TABLE_NAMES)
2692
          {
2693
            if (fill_schema_table_names(thd, tables->table, db_name,
2694
                                        table_name, with_i_schema))
2695
              continue;
2696
          }
2697
          else
2698
          {
2699
            if (!(table_open_method & ~OPEN_FRM_ONLY) &&
2700
                !with_i_schema)
2701
            {
2702
              if (!fill_schema_table_from_frm(thd, tables, schema_table, db_name,
2703
                                              table_name, schema_table_idx))
2704
                continue;
2705
            }
2706
2707
            int res;
2708
            LEX_STRING tmp_lex_string, orig_db_name;
2709
            /*
2710
              Set the parent lex of 'sel' because it is needed by
2711
              sel.init_query() which is called inside make_table_list.
2712
            */
2713
            thd->no_warnings_for_error= 1;
2714
            sel.parent_lex= lex;
2715
            /* db_name can be changed in make_table_list() func */
2716
            if (!thd->make_lex_string(&orig_db_name, db_name->str,
2717
                                      db_name->length, FALSE))
2718
              goto err;
2719
            if (make_table_list(thd, &sel, db_name, table_name))
2720
              goto err;
2721
            TABLE_LIST *show_table_list= (TABLE_LIST*) sel.table_list.first;
2722
            lex->all_selects_list= &sel;
2723
            lex->derived_tables= 0;
2724
            lex->sql_command= SQLCOM_SHOW_FIELDS;
2725
            show_table_list->i_s_requested_object=
2726
              schema_table->i_s_requested_object;
2727
            res= open_normal_and_derived_tables(thd, show_table_list,
2728
                                                MYSQL_LOCK_IGNORE_FLUSH);
2729
            lex->sql_command= save_sql_command;
2730
            /*
2731
              XXX:  show_table_list has a flag i_is_requested,
2732
              and when it's set, open_normal_and_derived_tables()
2733
              can return an error without setting an error message
2734
              in THD, which is a hack. This is why we have to
2735
              check for res, then for thd->is_error() only then
2736
              for thd->main_da.sql_errno().
2737
            */
2738
            if (res && thd->is_error() &&
2739
                thd->main_da.sql_errno() == ER_NO_SUCH_TABLE)
2740
            {
2741
              /*
2742
                Hide error for not existing table.
2743
                This error can occur for example when we use
2744
                where condition with db name and table name and this
2745
                table does not exist.
2746
              */
2747
              res= 0;
2748
              thd->clear_error();
2749
            }
2750
            else
2751
            {
2752
              /*
2753
                We should use show_table_list->alias instead of 
2754
                show_table_list->table_name because table_name
2755
                could be changed during opening of I_S tables. It's safe
2756
                to use alias because alias contains original table name 
2757
                in this case.
2758
              */
2759
              thd->make_lex_string(&tmp_lex_string, show_table_list->alias,
2760
                                   strlen(show_table_list->alias), FALSE);
2761
              res= schema_table->process_table(thd, show_table_list, table,
2762
                                               res, &orig_db_name,
2763
                                               &tmp_lex_string);
2764
              close_tables_for_reopen(thd, &show_table_list);
2765
            }
2766
            DBUG_ASSERT(!lex->query_tables_own_last);
2767
            if (res)
2768
              goto err;
2769
          }
2770
        }
2771
      }
2772
      /*
2773
        If we have information schema its always the first table and only
2774
        the first table. Reset for other tables.
2775
      */
2776
      with_i_schema= 0;
2777
    }
2778
  }
2779
2780
  error= 0;
2781
err:
2782
  thd->restore_backup_open_tables_state(&open_tables_state_backup);
2783
  lex->restore_backup_query_tables_list(&query_tables_list_backup);
2784
  lex->derived_tables= derived_tables;
2785
  lex->all_selects_list= old_all_select_lex;
2786
  lex->sql_command= save_sql_command;
2787
  thd->no_warnings_for_error= old_value;
2788
  DBUG_RETURN(error);
2789
}
2790
2791
2792
bool store_schema_shemata(THD* thd, TABLE *table, LEX_STRING *db_name,
2793
                          CHARSET_INFO *cs)
2794
{
2795
  restore_record(table, s->default_values);
2796
  table->field[1]->store(db_name->str, db_name->length, system_charset_info);
2797
  table->field[2]->store(cs->csname, strlen(cs->csname), system_charset_info);
2798
  table->field[3]->store(cs->name, strlen(cs->name), system_charset_info);
2799
  return schema_table_store_record(thd, table);
2800
}
2801
2802
2803
int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond)
2804
{
2805
  /*
2806
    TODO: fill_schema_shemata() is called when new client is connected.
2807
    Returning error status in this case leads to client hangup.
2808
  */
2809
2810
  LOOKUP_FIELD_VALUES lookup_field_vals;
2811
  List<LEX_STRING> db_names;
2812
  LEX_STRING *db_name;
2813
  bool with_i_schema;
2814
  HA_CREATE_INFO create;
2815
  TABLE *table= tables->table;
2816
  DBUG_ENTER("fill_schema_shemata");
2817
2818
  if (get_lookup_field_values(thd, cond, tables, &lookup_field_vals))
2819
    DBUG_RETURN(0);
2820
  DBUG_PRINT("INDEX VALUES",("db_name='%s', table_name='%s'",
2821
                             lookup_field_vals.db_value.str,
2822
                             lookup_field_vals.table_value.str));
2823
  if (make_db_list(thd, &db_names, &lookup_field_vals,
2824
                   &with_i_schema))
2825
    DBUG_RETURN(1);
2826
2827
  /*
2828
    If we have lookup db value we should check that the database exists
2829
  */
2830
  if(lookup_field_vals.db_value.str && !lookup_field_vals.wild_db_value &&
2831
     !with_i_schema)
2832
  {
2833
    char path[FN_REFLEN+16];
2834
    uint path_len;
15 by brian
Fix for stat, NETWARE removal
2835
    struct stat stat_info;
1 by brian
clean slate
2836
    if (!lookup_field_vals.db_value.str[0])
2837
      DBUG_RETURN(0);
2838
    path_len= build_table_filename(path, sizeof(path),
2839
                                   lookup_field_vals.db_value.str, "", "", 0);
2840
    path[path_len-1]= 0;
15 by brian
Fix for stat, NETWARE removal
2841
    if (stat(path,&stat_info))
1 by brian
clean slate
2842
      DBUG_RETURN(0);
2843
  }
2844
2845
  List_iterator_fast<LEX_STRING> it(db_names);
2846
  while ((db_name=it++))
2847
  {
2848
    if (with_i_schema)       // information schema name is always first in list
2849
    {
2850
      if (store_schema_shemata(thd, table, db_name,
2851
                               system_charset_info))
2852
        DBUG_RETURN(1);
2853
      with_i_schema= 0;
2854
      continue;
2855
    }
2856
    {
2857
      load_db_opt_by_name(thd, db_name->str, &create);
2858
      if (store_schema_shemata(thd, table, db_name,
2859
                               create.default_table_charset))
2860
        DBUG_RETURN(1);
2861
    }
2862
  }
2863
  DBUG_RETURN(0);
2864
}
2865
2866
2867
static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
2868
				    TABLE *table, bool res,
2869
				    LEX_STRING *db_name,
2870
				    LEX_STRING *table_name)
2871
{
2872
  const char *tmp_buff;
2873
  MYSQL_TIME time;
2874
  CHARSET_INFO *cs= system_charset_info;
2875
  DBUG_ENTER("get_schema_tables_record");
2876
2877
  restore_record(table, s->default_values);
2878
  table->field[1]->store(db_name->str, db_name->length, cs);
2879
  table->field[2]->store(table_name->str, table_name->length, cs);
2880
  if (res)
2881
  {
2882
    /*
2883
      there was errors during opening tables
2884
    */
2885
    const char *error= thd->is_error() ? thd->main_da.message() : "";
2886
    if (tables->schema_table)
2887
      table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs);
2888
    else
2889
      table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs);
2890
    table->field[20]->store(error, strlen(error), cs);
2891
    thd->clear_error();
2892
  }
2893
  else
2894
  {
2895
    char option_buff[350],*ptr;
2896
    TABLE *show_table= tables->table;
2897
    TABLE_SHARE *share= show_table->s;
2898
    handler *file= show_table->file;
2899
    handlerton *tmp_db_type= share->db_type();
2900
    if (share->tmp_table == SYSTEM_TMP_TABLE)
2901
      table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs);
2902
    else if (share->tmp_table)
2903
      table->field[3]->store(STRING_WITH_LEN("LOCAL TEMPORARY"), cs);
2904
    else
2905
      table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs);
2906
2907
    for (int i= 4; i < 20; i++)
2908
    {
2909
      if (i == 7 || (i > 12 && i < 17) || i == 18)
2910
        continue;
2911
      table->field[i]->set_notnull();
2912
    }
2913
    tmp_buff= (char *) ha_resolve_storage_engine_name(tmp_db_type);
2914
    table->field[4]->store(tmp_buff, strlen(tmp_buff), cs);
2915
    table->field[5]->store((longlong) share->frm_version, TRUE);
2916
2917
    ptr=option_buff;
2918
    if (share->min_rows)
2919
    {
2920
      ptr=strmov(ptr," min_rows=");
2921
      ptr=longlong10_to_str(share->min_rows,ptr,10);
2922
    }
2923
    if (share->max_rows)
2924
    {
2925
      ptr=strmov(ptr," max_rows=");
2926
      ptr=longlong10_to_str(share->max_rows,ptr,10);
2927
    }
2928
    if (share->avg_row_length)
2929
    {
2930
      ptr=strmov(ptr," avg_row_length=");
2931
      ptr=longlong10_to_str(share->avg_row_length,ptr,10);
2932
    }
2933
    if (share->db_create_options & HA_OPTION_PACK_KEYS)
2934
      ptr=strmov(ptr," pack_keys=1");
2935
    if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
2936
      ptr=strmov(ptr," pack_keys=0");
2937
    /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */
2938
    if (share->db_create_options & HA_OPTION_CHECKSUM)
2939
      ptr=strmov(ptr," checksum=1");
2940
    if (share->page_checksum != HA_CHOICE_UNDEF)
2941
      ptr= strxmov(ptr, " page_checksum=",
2942
                   ha_choice_values[(uint) share->page_checksum], NullS);
2943
    if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
2944
      ptr=strmov(ptr," delay_key_write=1");
2945
    if (share->row_type != ROW_TYPE_DEFAULT)
2946
      ptr=strxmov(ptr, " row_format=", 
2947
                  ha_row_type[(uint) share->row_type],
2948
                  NullS);
2949
    if (share->transactional != HA_CHOICE_UNDEF)
2950
    {
2951
      ptr= strxmov(ptr, " TRANSACTIONAL=",
2952
                   (share->transactional == HA_CHOICE_YES ? "1" : "0"),
2953
                   NullS);
2954
    }
2955
    if (share->transactional != HA_CHOICE_UNDEF)
2956
      ptr= strxmov(ptr, " transactional=",
2957
                   ha_choice_values[(uint) share->transactional], NullS);
2958
    table->field[19]->store(option_buff+1,
2959
                            (ptr == option_buff ? 0 : 
2960
                             (uint) (ptr-option_buff)-1), cs);
2961
2962
    tmp_buff= (share->table_charset ?
2963
               share->table_charset->name : "default");
2964
    table->field[17]->store(tmp_buff, strlen(tmp_buff), cs);
2965
2966
    if (share->comment.str)
2967
      table->field[20]->store(share->comment.str, share->comment.length, cs);
2968
2969
    if(file)
2970
    {
2971
      file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_AUTO |
2972
                 HA_STATUS_NO_LOCK);
2973
      enum row_type row_type = file->get_row_type();
2974
      switch (row_type) {
2975
      case ROW_TYPE_NOT_USED:
2976
      case ROW_TYPE_DEFAULT:
2977
        tmp_buff= ((share->db_options_in_use &
2978
                    HA_OPTION_COMPRESS_RECORD) ? "Compressed" :
2979
                   (share->db_options_in_use & HA_OPTION_PACK_RECORD) ?
2980
                   "Dynamic" : "Fixed");
2981
        break;
2982
      case ROW_TYPE_FIXED:
2983
        tmp_buff= "Fixed";
2984
        break;
2985
      case ROW_TYPE_DYNAMIC:
2986
        tmp_buff= "Dynamic";
2987
        break;
2988
      case ROW_TYPE_COMPRESSED:
2989
        tmp_buff= "Compressed";
2990
        break;
2991
      case ROW_TYPE_REDUNDANT:
2992
        tmp_buff= "Redundant";
2993
        break;
2994
      case ROW_TYPE_COMPACT:
2995
        tmp_buff= "Compact";
2996
        break;
2997
      case ROW_TYPE_PAGE:
2998
        tmp_buff= "Paged";
2999
        break;
3000
      }
3001
      table->field[6]->store(tmp_buff, strlen(tmp_buff), cs);
3002
      if (!tables->schema_table)
3003
      {
3004
        table->field[7]->store((longlong) file->stats.records, TRUE);
3005
        table->field[7]->set_notnull();
3006
      }
3007
      table->field[8]->store((longlong) file->stats.mean_rec_length, TRUE);
3008
      table->field[9]->store((longlong) file->stats.data_file_length, TRUE);
3009
      if (file->stats.max_data_file_length)
3010
      {
3011
        table->field[10]->store((longlong) file->stats.max_data_file_length,
3012
                                TRUE);
3013
      }
3014
      table->field[11]->store((longlong) file->stats.index_file_length, TRUE);
3015
      table->field[12]->store((longlong) file->stats.delete_length, TRUE);
3016
      if (show_table->found_next_number_field)
3017
      {
3018
        table->field[13]->store((longlong) file->stats.auto_increment_value,
3019
                                TRUE);
3020
        table->field[13]->set_notnull();
3021
      }
3022
      if (file->stats.create_time)
3023
      {
3024
        thd->variables.time_zone->gmt_sec_to_TIME(&time,
3025
                                                  (my_time_t) file->stats.create_time);
3026
        table->field[14]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
3027
        table->field[14]->set_notnull();
3028
      }
3029
      if (file->stats.update_time)
3030
      {
3031
        thd->variables.time_zone->gmt_sec_to_TIME(&time,
3032
                                                  (my_time_t) file->stats.update_time);
3033
        table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
3034
        table->field[15]->set_notnull();
3035
      }
3036
      if (file->stats.check_time)
3037
      {
3038
        thd->variables.time_zone->gmt_sec_to_TIME(&time,
3039
                                                  (my_time_t) file->stats.check_time);
3040
        table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
3041
        table->field[16]->set_notnull();
3042
      }
3043
      if (file->ha_table_flags() & (ulong) HA_HAS_CHECKSUM)
3044
      {
3045
        table->field[18]->store((longlong) file->checksum(), TRUE);
3046
        table->field[18]->set_notnull();
3047
      }
3048
    }
3049
  }
3050
  DBUG_RETURN(schema_table_store_record(thd, table));
3051
}
3052
3053
3054
/**
3055
  @brief    Store field characteristics into appropriate I_S table columns
3056
3057
  @param[in]      table             I_S table
3058
  @param[in]      field             processed field
3059
  @param[in]      cs                I_S table charset
3060
  @param[in]      offset            offset from beginning of table
3061
                                    to DATE_TYPE column in I_S table
3062
                                    
3063
  @return         void
3064
*/
3065
3066
void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs,
3067
                       uint offset)
3068
{
3069
  bool is_blob;
3070
  int decimals, field_length;
3071
  const char *tmp_buff;
3072
  char column_type_buff[MAX_FIELD_WIDTH];
3073
  String column_type(column_type_buff, sizeof(column_type_buff), cs);
3074
3075
  field->sql_type(column_type);
3076
  /* DTD_IDENTIFIER column */
3077
  table->field[offset + 7]->store(column_type.ptr(), column_type.length(), cs);
3078
  table->field[offset + 7]->set_notnull();
3079
  tmp_buff= strchr(column_type.ptr(), '(');
3080
  /* DATA_TYPE column */
3081
  table->field[offset]->store(column_type.ptr(),
3082
                         (tmp_buff ? tmp_buff - column_type.ptr() :
3083
                          column_type.length()), cs);
3084
  is_blob= (field->type() == MYSQL_TYPE_BLOB);
3085
  if (field->has_charset() || is_blob ||
3086
      field->real_type() == MYSQL_TYPE_VARCHAR ||  // For varbinary type
3087
      field->real_type() == MYSQL_TYPE_STRING)     // For binary type
3088
  {
3089
    uint32 octet_max_length= field->max_display_length();
3090
    if (is_blob && octet_max_length != (uint32) 4294967295U)
3091
      octet_max_length /= field->charset()->mbmaxlen;
3092
    longlong char_max_len= is_blob ? 
3093
      (longlong) octet_max_length / field->charset()->mbminlen :
3094
      (longlong) octet_max_length / field->charset()->mbmaxlen;
3095
    /* CHARACTER_MAXIMUM_LENGTH column*/
3096
    table->field[offset + 1]->store(char_max_len, TRUE);
3097
    table->field[offset + 1]->set_notnull();
3098
    /* CHARACTER_OCTET_LENGTH column */
3099
    table->field[offset + 2]->store((longlong) octet_max_length, TRUE);
3100
    table->field[offset + 2]->set_notnull();
3101
  }
3102
3103
  /*
3104
    Calculate field_length and decimals.
3105
    They are set to -1 if they should not be set (we should return NULL)
3106
  */
3107
3108
  decimals= field->decimals();
3109
  switch (field->type()) {
3110
  case MYSQL_TYPE_NEWDECIMAL:
3111
    field_length= ((Field_new_decimal*) field)->precision;
3112
    break;
3113
  case MYSQL_TYPE_TINY:
3114
  case MYSQL_TYPE_SHORT:
3115
  case MYSQL_TYPE_LONG:
3116
  case MYSQL_TYPE_LONGLONG:
3117
    field_length= field->max_display_length() - 1;
3118
    break;
3119
  case MYSQL_TYPE_FLOAT:  
3120
  case MYSQL_TYPE_DOUBLE:
3121
    field_length= field->field_length;
3122
    if (decimals == NOT_FIXED_DEC)
3123
      decimals= -1;                           // return NULL
3124
    break;
3125
  default:
3126
    field_length= decimals= -1;
3127
    break;
3128
  }
3129
3130
  /* NUMERIC_PRECISION column */
3131
  if (field_length >= 0)
3132
  {
3133
    table->field[offset + 3]->store((longlong) field_length, TRUE);
3134
    table->field[offset + 3]->set_notnull();
3135
  }
3136
  /* NUMERIC_SCALE column */
3137
  if (decimals >= 0)
3138
  {
3139
    table->field[offset + 4]->store((longlong) decimals, TRUE);
3140
    table->field[offset + 4]->set_notnull();
3141
  }
3142
  if (field->has_charset())
3143
  {
3144
    /* CHARACTER_SET_NAME column*/
3145
    tmp_buff= field->charset()->csname;
3146
    table->field[offset + 5]->store(tmp_buff, strlen(tmp_buff), cs);
3147
    table->field[offset + 5]->set_notnull();
3148
    /* COLLATION_NAME column */
3149
    tmp_buff= field->charset()->name;
3150
    table->field[offset + 6]->store(tmp_buff, strlen(tmp_buff), cs);
3151
    table->field[offset + 6]->set_notnull();
3152
  }
3153
}
3154
3155
3156
static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
3157
				    TABLE *table, bool res,
3158
				    LEX_STRING *db_name,
3159
				    LEX_STRING *table_name)
3160
{
3161
  LEX *lex= thd->lex;
3162
  const char *wild= lex->wild ? lex->wild->ptr() : NullS;
3163
  CHARSET_INFO *cs= system_charset_info;
3164
  TABLE *show_table;
3165
  TABLE_SHARE *show_table_share;
3166
  Field **ptr, *field, *timestamp_field;
3167
  int count;
3168
  DBUG_ENTER("get_schema_column_record");
3169
3170
  if (res)
3171
  {
3172
    if (lex->sql_command != SQLCOM_SHOW_FIELDS)
3173
    {
3174
      /*
3175
        I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS
3176
        rather than in SHOW COLUMNS
3177
      */ 
3178
      if (thd->is_error())
3179
        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
3180
                     thd->main_da.sql_errno(), thd->main_da.message());
3181
      thd->clear_error();
3182
      res= 0;
3183
    }
3184
    DBUG_RETURN(res);
3185
  }
3186
3187
  show_table= tables->table;
3188
  show_table_share= show_table->s;
3189
  count= 0;
3190
3191
  if (tables->schema_table)
3192
  {
3193
    ptr= show_table->field;
3194
    timestamp_field= show_table->timestamp_field;
3195
    show_table->use_all_columns();               // Required for default
3196
  }
3197
  else
3198
  {
3199
    ptr= show_table_share->field;
3200
    timestamp_field= show_table_share->timestamp_field;
3201
    /*
3202
      read_set may be inited in case of
3203
      temporary table
3204
    */
3205
    if (!show_table->read_set)
3206
    {
3207
      /* to satisfy 'field->val_str' ASSERTs */
3208
      uchar *bitmaps;
3209
      uint bitmap_size= show_table_share->column_bitmap_size;
3210
      if (!(bitmaps= (uchar*) alloc_root(thd->mem_root, bitmap_size)))
3211
        DBUG_RETURN(0);
3212
      bitmap_init(&show_table->def_read_set,
3213
                  (my_bitmap_map*) bitmaps, show_table_share->fields, FALSE);
3214
      bitmap_set_all(&show_table->def_read_set);
3215
      show_table->read_set= &show_table->def_read_set;
3216
    }
3217
    bitmap_set_all(show_table->read_set);
3218
  }
3219
3220
  for (; (field= *ptr) ; ptr++)
3221
  {
3222
    uchar *pos;
3223
    char tmp[MAX_FIELD_WIDTH];
3224
    String type(tmp,sizeof(tmp), system_charset_info);
3225
    char *end;
3226
3227
    /* to satisfy 'field->val_str' ASSERTs */
3228
    field->table= show_table;
3229
    show_table->in_use= thd;
3230
3231
    if (wild && wild[0] &&
3232
        wild_case_compare(system_charset_info, field->field_name,wild))
3233
      continue;
3234
3235
    count++;
3236
    /* Get default row, with all NULL fields set to NULL */
3237
    restore_record(table, s->default_values);
3238
3239
    table->field[1]->store(db_name->str, db_name->length, cs);
3240
    table->field[2]->store(table_name->str, table_name->length, cs);
3241
    table->field[3]->store(field->field_name, strlen(field->field_name),
3242
                           cs);
3243
    table->field[4]->store((longlong) count, TRUE);
3244
3245
    if (get_field_default_value(thd, timestamp_field, field, &type, 0))
3246
    {
3247
      table->field[5]->store(type.ptr(), type.length(), cs);
3248
      table->field[5]->set_notnull();
3249
    }
3250
    pos=(uchar*) ((field->flags & NOT_NULL_FLAG) ?  "NO" : "YES");
3251
    table->field[6]->store((const char*) pos,
3252
                           strlen((const char*) pos), cs);
3253
    store_column_type(table, field, cs, 7);
3254
3255
    pos=(uchar*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
3256
                 (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
3257
                 (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
3258
    table->field[15]->store((const char*) pos,
3259
                            strlen((const char*) pos), cs);
3260
3261
    end= tmp;
3262
    if (field->unireg_check == Field::NEXT_NUMBER)
3263
      table->field[16]->store(STRING_WITH_LEN("auto_increment"), cs);
3264
    if (timestamp_field == field &&
3265
        field->unireg_check != Field::TIMESTAMP_DN_FIELD)
3266
      table->field[16]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"),
3267
                              cs);
3268
3269
    table->field[18]->store(field->comment.str, field->comment.length, cs);
3270
    {
3271
      enum ha_storage_media storage_type= (enum ha_storage_media)
3272
        ((field->flags >> FIELD_STORAGE_FLAGS) & STORAGE_TYPE_MASK);
3273
      enum column_format_type column_format= (enum column_format_type)
3274
        ((field->flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
3275
      pos=(uchar*)(storage_type == HA_SM_DEFAULT ? "Default" :
3276
                   storage_type == HA_SM_DISK ? "Disk" : "Memory");
3277
      table->field[19]->store((const char*) pos,
3278
                              strlen((const char*) pos), cs);
3279
      pos=(uchar*)(column_format == COLUMN_FORMAT_TYPE_DEFAULT ? "Default" :
3280
                   column_format == COLUMN_FORMAT_TYPE_FIXED ? "Fixed" :
3281
                                                             "Dynamic");
3282
      table->field[20]->store((const char*) pos,
3283
                              strlen((const char*) pos), cs);
3284
    }
3285
    if (schema_table_store_record(thd, table))
3286
      DBUG_RETURN(1);
3287
  }
3288
  DBUG_RETURN(0);
3289
}
3290
3291
3292
3293
int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond)
3294
{
3295
  CHARSET_INFO **cs;
3296
  const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
3297
  TABLE *table= tables->table;
3298
  CHARSET_INFO *scs= system_charset_info;
3299
3300
  for (cs= all_charsets ; cs < all_charsets+255 ; cs++)
3301
  {
3302
    CHARSET_INFO *tmp_cs= cs[0];
3303
    if (tmp_cs && (tmp_cs->state & MY_CS_PRIMARY) && 
3304
        (tmp_cs->state & MY_CS_AVAILABLE) &&
3305
        !(tmp_cs->state & MY_CS_HIDDEN) &&
3306
        !(wild && wild[0] &&
3307
	  wild_case_compare(scs, tmp_cs->csname,wild)))
3308
    {
3309
      const char *comment;
3310
      restore_record(table, s->default_values);
3311
      table->field[0]->store(tmp_cs->csname, strlen(tmp_cs->csname), scs);
3312
      table->field[1]->store(tmp_cs->name, strlen(tmp_cs->name), scs);
3313
      comment= tmp_cs->comment ? tmp_cs->comment : "";
3314
      table->field[2]->store(comment, strlen(comment), scs);
3315
      table->field[3]->store((longlong) tmp_cs->mbmaxlen, TRUE);
3316
      if (schema_table_store_record(thd, table))
3317
        return 1;
3318
    }
3319
  }
3320
  return 0;
3321
}
3322
3323
3324
int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond)
3325
{
3326
  CHARSET_INFO **cs;
3327
  const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
3328
  TABLE *table= tables->table;
3329
  CHARSET_INFO *scs= system_charset_info;
3330
  for (cs= all_charsets ; cs < all_charsets+255 ; cs++ )
3331
  {
3332
    CHARSET_INFO **cl;
3333
    CHARSET_INFO *tmp_cs= cs[0];
3334
    if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
3335
         (tmp_cs->state & MY_CS_HIDDEN) ||
3336
        !(tmp_cs->state & MY_CS_PRIMARY))
3337
      continue;
3338
    for (cl= all_charsets; cl < all_charsets+255 ;cl ++)
3339
    {
3340
      CHARSET_INFO *tmp_cl= cl[0];
3341
      if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || 
3342
          !my_charset_same(tmp_cs, tmp_cl))
3343
	continue;
3344
      if (!(wild && wild[0] &&
3345
	  wild_case_compare(scs, tmp_cl->name,wild)))
3346
      {
3347
	const char *tmp_buff;
3348
	restore_record(table, s->default_values);
3349
	table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
3350
        table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
3351
        table->field[2]->store((longlong) tmp_cl->number, TRUE);
3352
        tmp_buff= (tmp_cl->state & MY_CS_PRIMARY) ? "Yes" : "";
3353
	table->field[3]->store(tmp_buff, strlen(tmp_buff), scs);
3354
        tmp_buff= (tmp_cl->state & MY_CS_COMPILED)? "Yes" : "";
3355
	table->field[4]->store(tmp_buff, strlen(tmp_buff), scs);
3356
        table->field[5]->store((longlong) tmp_cl->strxfrm_multiply, TRUE);
3357
        if (schema_table_store_record(thd, table))
3358
          return 1;
3359
      }
3360
    }
3361
  }
3362
  return 0;
3363
}
3364
3365
3366
int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, COND *cond)
3367
{
3368
  CHARSET_INFO **cs;
3369
  TABLE *table= tables->table;
3370
  CHARSET_INFO *scs= system_charset_info;
3371
  for (cs= all_charsets ; cs < all_charsets+255 ; cs++ )
3372
  {
3373
    CHARSET_INFO **cl;
3374
    CHARSET_INFO *tmp_cs= cs[0];
3375
    if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || 
3376
        !(tmp_cs->state & MY_CS_PRIMARY))
3377
      continue;
3378
    for (cl= all_charsets; cl < all_charsets+255 ;cl ++)
3379
    {
3380
      CHARSET_INFO *tmp_cl= cl[0];
3381
      if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || 
3382
          !my_charset_same(tmp_cs,tmp_cl))
3383
	continue;
3384
      restore_record(table, s->default_values);
3385
      table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
3386
      table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
3387
      if (schema_table_store_record(thd, table))
3388
        return 1;
3389
    }
3390
  }
3391
  return 0;
3392
}
3393
3394
3395
static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
3396
				  TABLE *table, bool res,
3397
				  LEX_STRING *db_name,
3398
				  LEX_STRING *table_name)
3399
{
3400
  CHARSET_INFO *cs= system_charset_info;
3401
  DBUG_ENTER("get_schema_stat_record");
3402
  if (res)
3403
  {
3404
    if (thd->lex->sql_command != SQLCOM_SHOW_KEYS)
3405
    {
3406
      /*
3407
        I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS
3408
        rather than in SHOW KEYS
3409
      */
3410
      if (thd->is_error())
3411
        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
3412
                     thd->main_da.sql_errno(), thd->main_da.message());
3413
      thd->clear_error();
3414
      res= 0;
3415
    }
3416
    DBUG_RETURN(res);
3417
  }
3418
  else
3419
  {
3420
    TABLE *show_table= tables->table;
3421
    KEY *key_info=show_table->s->key_info;
3422
    if (show_table->file)
3423
      show_table->file->info(HA_STATUS_VARIABLE |
3424
                             HA_STATUS_NO_LOCK |
3425
                             HA_STATUS_TIME);
3426
    for (uint i=0 ; i < show_table->s->keys ; i++,key_info++)
3427
    {
3428
      KEY_PART_INFO *key_part= key_info->key_part;
3429
      const char *str;
3430
      for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
3431
      {
3432
        restore_record(table, s->default_values);
3433
        table->field[1]->store(db_name->str, db_name->length, cs);
3434
        table->field[2]->store(table_name->str, table_name->length, cs);
3435
        table->field[3]->store((longlong) ((key_info->flags &
3436
                                            HA_NOSAME) ? 0 : 1), TRUE);
3437
        table->field[4]->store(db_name->str, db_name->length, cs);
3438
        table->field[5]->store(key_info->name, strlen(key_info->name), cs);
3439
        table->field[6]->store((longlong) (j+1), TRUE);
3440
        str=(key_part->field ? key_part->field->field_name :
3441
             "?unknown field?");
3442
        table->field[7]->store(str, strlen(str), cs);
3443
        if (show_table->file)
3444
        {
3445
          if (show_table->file->index_flags(i, j, 0) & HA_READ_ORDER)
3446
          {
3447
            table->field[8]->store(((key_part->key_part_flag &
3448
                                     HA_REVERSE_SORT) ?
3449
                                    "D" : "A"), 1, cs);
3450
            table->field[8]->set_notnull();
3451
          }
3452
          KEY *key=show_table->key_info+i;
3453
          if (key->rec_per_key[j])
3454
          {
3455
            ha_rows records=(show_table->file->stats.records /
3456
                             key->rec_per_key[j]);
3457
            table->field[9]->store((longlong) records, TRUE);
3458
            table->field[9]->set_notnull();
3459
          }
3460
          str= show_table->file->index_type(i);
3461
          table->field[13]->store(str, strlen(str), cs);
3462
        }
3463
        if ((key_part->field &&
3464
             key_part->length !=
3465
             show_table->s->field[key_part->fieldnr-1]->key_length()))
3466
        {
3467
          table->field[10]->store((longlong) key_part->length /
3468
                                  key_part->field->charset()->mbmaxlen, TRUE);
3469
          table->field[10]->set_notnull();
3470
        }
3471
        uint flags= key_part->field ? key_part->field->flags : 0;
3472
        const char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
3473
        table->field[12]->store(pos, strlen(pos), cs);
3474
        if (!show_table->s->keys_in_use.is_set(i))
3475
          table->field[14]->store(STRING_WITH_LEN("disabled"), cs);
3476
        else
3477
          table->field[14]->store("", 0, cs);
3478
        table->field[14]->set_notnull();
3479
        DBUG_ASSERT(test(key_info->flags & HA_USES_COMMENT) == 
3480
                   (key_info->comment.length > 0));
3481
        if (key_info->flags & HA_USES_COMMENT)
3482
          table->field[15]->store(key_info->comment.str, 
3483
                                  key_info->comment.length, cs);
3484
        if (schema_table_store_record(thd, table))
3485
          DBUG_RETURN(1);
3486
      }
3487
    }
3488
  }
3489
  DBUG_RETURN(res);
3490
}
3491
3492
3493
bool store_constraints(THD *thd, TABLE *table, LEX_STRING *db_name,
3494
                       LEX_STRING *table_name, const char *key_name,
3495
                       uint key_len, const char *con_type, uint con_len)
3496
{
3497
  CHARSET_INFO *cs= system_charset_info;
3498
  restore_record(table, s->default_values);
3499
  table->field[1]->store(db_name->str, db_name->length, cs);
3500
  table->field[2]->store(key_name, key_len, cs);
3501
  table->field[3]->store(db_name->str, db_name->length, cs);
3502
  table->field[4]->store(table_name->str, table_name->length, cs);
3503
  table->field[5]->store(con_type, con_len, cs);
3504
  return schema_table_store_record(thd, table);
3505
}
3506
3507
3508
static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables,
3509
					 TABLE *table, bool res,
3510
					 LEX_STRING *db_name,
3511
					 LEX_STRING *table_name)
3512
{
3513
  DBUG_ENTER("get_schema_constraints_record");
3514
  if (res)
3515
  {
3516
    if (thd->is_error())
3517
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
3518
                   thd->main_da.sql_errno(), thd->main_da.message());
3519
    thd->clear_error();
3520
    DBUG_RETURN(0);
3521
  }
3522
  else
3523
  {
3524
    List<FOREIGN_KEY_INFO> f_key_list;
3525
    TABLE *show_table= tables->table;
3526
    KEY *key_info=show_table->key_info;
3527
    uint primary_key= show_table->s->primary_key;
3528
    show_table->file->info(HA_STATUS_VARIABLE | 
3529
                           HA_STATUS_NO_LOCK |
3530
                           HA_STATUS_TIME);
3531
    for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
3532
    {
3533
      if (i != primary_key && !(key_info->flags & HA_NOSAME))
3534
        continue;
3535
3536
      if (i == primary_key && !strcmp(key_info->name, primary_key_name))
3537
      {
3538
        if (store_constraints(thd, table, db_name, table_name, key_info->name,
3539
                              strlen(key_info->name),
3540
                              STRING_WITH_LEN("PRIMARY KEY")))
3541
          DBUG_RETURN(1);
3542
      }
3543
      else if (key_info->flags & HA_NOSAME)
3544
      {
3545
        if (store_constraints(thd, table, db_name, table_name, key_info->name,
3546
                              strlen(key_info->name),
3547
                              STRING_WITH_LEN("UNIQUE")))
3548
          DBUG_RETURN(1);
3549
      }
3550
    }
3551
3552
    show_table->file->get_foreign_key_list(thd, &f_key_list);
3553
    FOREIGN_KEY_INFO *f_key_info;
3554
    List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
3555
    while ((f_key_info=it++))
3556
    {
3557
      if (store_constraints(thd, table, db_name, table_name, 
3558
                            f_key_info->forein_id->str,
3559
                            strlen(f_key_info->forein_id->str),
3560
                            "FOREIGN KEY", 11))
3561
        DBUG_RETURN(1);
3562
    }
3563
  }
3564
  DBUG_RETURN(res);
3565
}
3566
3567
3568
void store_key_column_usage(TABLE *table, LEX_STRING *db_name,
3569
                            LEX_STRING *table_name, const char *key_name,
3570
                            uint key_len, const char *con_type, uint con_len,
3571
                            longlong idx)
3572
{
3573
  CHARSET_INFO *cs= system_charset_info;
3574
  table->field[1]->store(db_name->str, db_name->length, cs);
3575
  table->field[2]->store(key_name, key_len, cs);
3576
  table->field[4]->store(db_name->str, db_name->length, cs);
3577
  table->field[5]->store(table_name->str, table_name->length, cs);
3578
  table->field[6]->store(con_type, con_len, cs);
3579
  table->field[7]->store((longlong) idx, TRUE);
3580
}
3581
3582
3583
static int get_schema_key_column_usage_record(THD *thd,
3584
					      TABLE_LIST *tables,
3585
					      TABLE *table, bool res,
3586
					      LEX_STRING *db_name,
3587
					      LEX_STRING *table_name)
3588
{
3589
  DBUG_ENTER("get_schema_key_column_usage_record");
3590
  if (res)
3591
  {
3592
    if (thd->is_error())
3593
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
3594
                   thd->main_da.sql_errno(), thd->main_da.message());
3595
    thd->clear_error();
3596
    DBUG_RETURN(0);
3597
  }
3598
  else
3599
  {
3600
    List<FOREIGN_KEY_INFO> f_key_list;
3601
    TABLE *show_table= tables->table;
3602
    KEY *key_info=show_table->key_info;
3603
    uint primary_key= show_table->s->primary_key;
3604
    show_table->file->info(HA_STATUS_VARIABLE | 
3605
                           HA_STATUS_NO_LOCK |
3606
                           HA_STATUS_TIME);
3607
    for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
3608
    {
3609
      if (i != primary_key && !(key_info->flags & HA_NOSAME))
3610
        continue;
3611
      uint f_idx= 0;
3612
      KEY_PART_INFO *key_part= key_info->key_part;
3613
      for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
3614
      {
3615
        if (key_part->field)
3616
        {
3617
          f_idx++;
3618
          restore_record(table, s->default_values);
3619
          store_key_column_usage(table, db_name, table_name,
3620
                                 key_info->name,
3621
                                 strlen(key_info->name), 
3622
                                 key_part->field->field_name, 
3623
                                 strlen(key_part->field->field_name),
3624
                                 (longlong) f_idx);
3625
          if (schema_table_store_record(thd, table))
3626
            DBUG_RETURN(1);
3627
        }
3628
      }
3629
    }
3630
3631
    show_table->file->get_foreign_key_list(thd, &f_key_list);
3632
    FOREIGN_KEY_INFO *f_key_info;
3633
    List_iterator_fast<FOREIGN_KEY_INFO> fkey_it(f_key_list);
3634
    while ((f_key_info= fkey_it++))
3635
    {
3636
      LEX_STRING *f_info;
3637
      LEX_STRING *r_info;
3638
      List_iterator_fast<LEX_STRING> it(f_key_info->foreign_fields),
3639
        it1(f_key_info->referenced_fields);
3640
      uint f_idx= 0;
3641
      while ((f_info= it++))
3642
      {
3643
        r_info= it1++;
3644
        f_idx++;
3645
        restore_record(table, s->default_values);
3646
        store_key_column_usage(table, db_name, table_name,
3647
                               f_key_info->forein_id->str,
3648
                               f_key_info->forein_id->length,
3649
                               f_info->str, f_info->length,
3650
                               (longlong) f_idx);
3651
        table->field[8]->store((longlong) f_idx, TRUE);
3652
        table->field[8]->set_notnull();
3653
        table->field[9]->store(f_key_info->referenced_db->str,
3654
                               f_key_info->referenced_db->length,
3655
                               system_charset_info);
3656
        table->field[9]->set_notnull();
3657
        table->field[10]->store(f_key_info->referenced_table->str,
3658
                                f_key_info->referenced_table->length, 
3659
                                system_charset_info);
3660
        table->field[10]->set_notnull();
3661
        table->field[11]->store(r_info->str, r_info->length,
3662
                                system_charset_info);
3663
        table->field[11]->set_notnull();
3664
        if (schema_table_store_record(thd, table))
3665
          DBUG_RETURN(1);
3666
      }
3667
    }
3668
  }
3669
  DBUG_RETURN(res);
3670
}
3671
3672
3673
int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond)
3674
{
3675
  DBUG_ENTER("fill_open_tables");
3676
  const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
3677
  TABLE *table= tables->table;
3678
  CHARSET_INFO *cs= system_charset_info;
3679
  OPEN_TABLE_LIST *open_list;
3680
  if (!(open_list=list_open_tables(thd,thd->lex->select_lex.db, wild))
3681
            && thd->is_fatal_error)
3682
    DBUG_RETURN(1);
3683
3684
  for (; open_list ; open_list=open_list->next)
3685
  {
3686
    restore_record(table, s->default_values);
3687
    table->field[0]->store(open_list->db, strlen(open_list->db), cs);
3688
    table->field[1]->store(open_list->table, strlen(open_list->table), cs);
3689
    table->field[2]->store((longlong) open_list->in_use, TRUE);
3690
    table->field[3]->store((longlong) open_list->locked, TRUE);
3691
    if (schema_table_store_record(thd, table))
3692
      DBUG_RETURN(1);
3693
  }
3694
  DBUG_RETURN(0);
3695
}
3696
3697
3698
int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond)
3699
{
3700
  DBUG_ENTER("fill_variables");
3701
  int res= 0;
3702
  LEX *lex= thd->lex;
3703
  const char *wild= lex->wild ? lex->wild->ptr() : NullS;
3704
  enum enum_schema_tables schema_table_idx=
3705
    get_schema_table_idx(tables->schema_table);
3706
  enum enum_var_type option_type= OPT_SESSION;
3707
  bool upper_case_names= (schema_table_idx != SCH_VARIABLES);
3708
  bool sorted_vars= (schema_table_idx == SCH_VARIABLES);
3709
3710
  if (lex->option_type == OPT_GLOBAL ||
3711
      schema_table_idx == SCH_GLOBAL_VARIABLES)
3712
    option_type= OPT_GLOBAL;
3713
3714
  rw_rdlock(&LOCK_system_variables_hash);
3715
  res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars),
3716
                         option_type, NULL, "", tables->table, upper_case_names);
3717
  rw_unlock(&LOCK_system_variables_hash);
3718
  DBUG_RETURN(res);
3719
}
3720
3721
3722
int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
3723
{
3724
  DBUG_ENTER("fill_status");
3725
  LEX *lex= thd->lex;
3726
  const char *wild= lex->wild ? lex->wild->ptr() : NullS;
3727
  int res= 0;
3728
  STATUS_VAR *tmp1, tmp;
3729
  enum enum_schema_tables schema_table_idx=
3730
    get_schema_table_idx(tables->schema_table);
3731
  enum enum_var_type option_type;
3732
  bool upper_case_names= (schema_table_idx != SCH_STATUS);
3733
3734
  if (schema_table_idx == SCH_STATUS)
3735
  {
3736
    option_type= lex->option_type;
3737
    if (option_type == OPT_GLOBAL)
3738
      tmp1= &tmp;
3739
    else
3740
      tmp1= thd->initial_status_var;
3741
  }
3742
  else if (schema_table_idx == SCH_GLOBAL_STATUS)
3743
  {
3744
    option_type= OPT_GLOBAL;
3745
    tmp1= &tmp;
3746
  }
3747
  else
3748
  { 
3749
    option_type= OPT_SESSION;
3750
    tmp1= &thd->status_var;
3751
  }
3752
3753
  pthread_mutex_lock(&LOCK_status);
3754
  if (option_type == OPT_GLOBAL)
3755
    calc_sum_of_all_status(&tmp);
3756
  res= show_status_array(thd, wild,
3757
                         (SHOW_VAR *)all_status_vars.buffer,
3758
                         option_type, tmp1, "", tables->table,
3759
                         upper_case_names);
3760
  pthread_mutex_unlock(&LOCK_status);
3761
  DBUG_RETURN(res);
3762
}
3763
3764
3765
/*
3766
  Fill and store records into I_S.referential_constraints table
3767
3768
  SYNOPSIS
3769
    get_referential_constraints_record()
3770
    thd                 thread handle
3771
    tables              table list struct(processed table)
3772
    table               I_S table
3773
    res                 1 means the error during opening of the processed table
3774
                        0 means processed table is opened without error
3775
    base_name           db name
3776
    file_name           table name
3777
3778
  RETURN
3779
    0	ok
3780
    #   error
3781
*/
3782
3783
static int
3784
get_referential_constraints_record(THD *thd, TABLE_LIST *tables,
3785
                                   TABLE *table, bool res,
3786
                                   LEX_STRING *db_name, LEX_STRING *table_name)
3787
{
3788
  CHARSET_INFO *cs= system_charset_info;
3789
  DBUG_ENTER("get_referential_constraints_record");
3790
3791
  if (res)
3792
  {
3793
    if (thd->is_error())
3794
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
3795
                   thd->main_da.sql_errno(), thd->main_da.message());
3796
    thd->clear_error();
3797
    DBUG_RETURN(0);
3798
  }
3799
3800
  {
3801
    List<FOREIGN_KEY_INFO> f_key_list;
3802
    TABLE *show_table= tables->table;
3803
    show_table->file->info(HA_STATUS_VARIABLE | 
3804
                           HA_STATUS_NO_LOCK |
3805
                           HA_STATUS_TIME);
3806
3807
    show_table->file->get_foreign_key_list(thd, &f_key_list);
3808
    FOREIGN_KEY_INFO *f_key_info;
3809
    List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
3810
    while ((f_key_info= it++))
3811
    {
3812
      restore_record(table, s->default_values);
3813
      table->field[1]->store(db_name->str, db_name->length, cs);
3814
      table->field[9]->store(table_name->str, table_name->length, cs);
3815
      table->field[2]->store(f_key_info->forein_id->str,
3816
                             f_key_info->forein_id->length, cs);
3817
      table->field[4]->store(f_key_info->referenced_db->str, 
3818
                             f_key_info->referenced_db->length, cs);
3819
      table->field[10]->store(f_key_info->referenced_table->str, 
3820
                             f_key_info->referenced_table->length, cs);
3821
      if (f_key_info->referenced_key_name)
3822
      {
3823
        table->field[5]->store(f_key_info->referenced_key_name->str, 
3824
                               f_key_info->referenced_key_name->length, cs);
3825
        table->field[5]->set_notnull();
3826
      }
3827
      else
3828
        table->field[5]->set_null();
3829
      table->field[6]->store(STRING_WITH_LEN("NONE"), cs);
3830
      table->field[7]->store(f_key_info->update_method->str, 
3831
                             f_key_info->update_method->length, cs);
3832
      table->field[8]->store(f_key_info->delete_method->str, 
3833
                             f_key_info->delete_method->length, cs);
3834
      if (schema_table_store_record(thd, table))
3835
        DBUG_RETURN(1);
3836
    }
3837
  }
3838
  DBUG_RETURN(0);
3839
}
3840
3841
3842
struct schema_table_ref 
3843
{
3844
  const char *table_name;
3845
  ST_SCHEMA_TABLE *schema_table;
3846
};
3847
3848
3849
/*
3850
  Find schema_tables elment by name
3851
3852
  SYNOPSIS
3853
    find_schema_table_in_plugin()
3854
    thd                 thread handler
3855
    plugin              plugin
3856
    table_name          table name
3857
3858
  RETURN
3859
    0	table not found
3860
    1   found the schema table
3861
*/
3862
static my_bool find_schema_table_in_plugin(THD *thd, plugin_ref plugin,
3863
                                           void* p_table)
3864
{
3865
  schema_table_ref *p_schema_table= (schema_table_ref *)p_table;
3866
  const char* table_name= p_schema_table->table_name;
3867
  ST_SCHEMA_TABLE *schema_table= plugin_data(plugin, ST_SCHEMA_TABLE *);
3868
  DBUG_ENTER("find_schema_table_in_plugin");
3869
3870
  if (!my_strcasecmp(system_charset_info,
3871
                     schema_table->table_name,
3872
                     table_name)) {
3873
    p_schema_table->schema_table= schema_table;
3874
    DBUG_RETURN(1);
3875
  }
3876
3877
  DBUG_RETURN(0);
3878
}
3879
3880
3881
/*
3882
  Find schema_tables elment by name
3883
3884
  SYNOPSIS
3885
    find_schema_table()
3886
    thd                 thread handler
3887
    table_name          table name
3888
3889
  RETURN
3890
    0	table not found
3891
    #   pointer to 'schema_tables' element
3892
*/
3893
3894
ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name)
3895
{
3896
  schema_table_ref schema_table_a;
3897
  ST_SCHEMA_TABLE *schema_table= schema_tables;
3898
  DBUG_ENTER("find_schema_table");
3899
3900
  for (; schema_table->table_name; schema_table++)
3901
  {
3902
    if (!my_strcasecmp(system_charset_info,
3903
                       schema_table->table_name,
3904
                       table_name))
3905
      DBUG_RETURN(schema_table);
3906
  }
3907
3908
  schema_table_a.table_name= table_name;
3909
  if (plugin_foreach(thd, find_schema_table_in_plugin, 
3910
                     MYSQL_INFORMATION_SCHEMA_PLUGIN, &schema_table_a))
3911
    DBUG_RETURN(schema_table_a.schema_table);
3912
3913
  DBUG_RETURN(NULL);
3914
}
3915
3916
3917
ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx)
3918
{
3919
  return &schema_tables[schema_table_idx];
3920
}
3921
3922
3923
/**
3924
  Create information_schema table using schema_table data.
3925
3926
  @note
3927
3928
  @param
3929
    thd	       	          thread handler
3930
3931
  @param table_list Used to pass I_S table information(fields info, tables
3932
  parameters etc) and table name.
3933
3934
  @retval  \#             Pointer to created table
3935
  @retval  NULL           Can't create table
3936
*/
3937
3938
TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
3939
{
3940
  int field_count= 0;
3941
  Item *item;
3942
  TABLE *table;
3943
  List<Item> field_list;
3944
  ST_SCHEMA_TABLE *schema_table= table_list->schema_table;
3945
  ST_FIELD_INFO *fields_info= schema_table->fields_info;
3946
  CHARSET_INFO *cs= system_charset_info;
3947
  DBUG_ENTER("create_schema_table");
3948
3949
  for (; fields_info->field_name; fields_info++)
3950
  {
3951
    switch (fields_info->field_type) {
3952
    case MYSQL_TYPE_TINY:
3953
    case MYSQL_TYPE_LONG:
3954
    case MYSQL_TYPE_SHORT:
3955
    case MYSQL_TYPE_LONGLONG:
3956
      if (!(item= new Item_return_int(fields_info->field_name,
3957
                                      fields_info->field_length,
3958
                                      fields_info->field_type,
3959
                                      fields_info->value)))
3960
      {
3961
        DBUG_RETURN(0);
3962
      }
3963
      item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED);
3964
      break;
3965
    case MYSQL_TYPE_DATE:
3966
    case MYSQL_TYPE_TIME:
3967
    case MYSQL_TYPE_TIMESTAMP:
3968
    case MYSQL_TYPE_DATETIME:
3969
      if (!(item=new Item_return_date_time(fields_info->field_name,
3970
                                           fields_info->field_type)))
3971
      {
3972
        DBUG_RETURN(0);
3973
      }
3974
      break;
3975
    case MYSQL_TYPE_FLOAT:
3976
    case MYSQL_TYPE_DOUBLE:
3977
      if ((item= new Item_float(fields_info->field_name, 0.0, NOT_FIXED_DEC, 
3978
                           fields_info->field_length)) == NULL)
3979
        DBUG_RETURN(NULL);
3980
      break;
3981
    case MYSQL_TYPE_NEWDECIMAL:
3982
      if (!(item= new Item_decimal((longlong) fields_info->value, false)))
3983
      {
3984
        DBUG_RETURN(0);
3985
      }
3986
      item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED);
3987
      item->decimals= fields_info->field_length%10;
3988
      item->max_length= (fields_info->field_length/100)%100;
3989
      if (item->unsigned_flag == 0)
3990
        item->max_length+= 1;
3991
      if (item->decimals > 0)
3992
        item->max_length+= 1;
3993
      item->set_name(fields_info->field_name,
3994
                     strlen(fields_info->field_name), cs);
3995
      break;
3996
    case MYSQL_TYPE_TINY_BLOB:
3997
    case MYSQL_TYPE_MEDIUM_BLOB:
3998
    case MYSQL_TYPE_LONG_BLOB:
3999
    case MYSQL_TYPE_BLOB:
4000
      if (!(item= new Item_blob(fields_info->field_name,
4001
                                fields_info->field_length)))
4002
      {
4003
        DBUG_RETURN(0);
4004
      }
4005
      break;
4006
    default:
4007
      /* Don't let unimplemented types pass through. Could be a grave error. */
4008
      DBUG_ASSERT(fields_info->field_type == MYSQL_TYPE_STRING);
4009
4010
      if (!(item= new Item_empty_string("", fields_info->field_length, cs)))
4011
      {
4012
        DBUG_RETURN(0);
4013
      }
4014
      item->set_name(fields_info->field_name,
4015
                     strlen(fields_info->field_name), cs);
4016
      break;
4017
    }
4018
    field_list.push_back(item);
4019
    item->maybe_null= (fields_info->field_flags & MY_I_S_MAYBE_NULL);
4020
    field_count++;
4021
  }
4022
  TMP_TABLE_PARAM *tmp_table_param =
4023
    (TMP_TABLE_PARAM*) (thd->alloc(sizeof(TMP_TABLE_PARAM)));
4024
  tmp_table_param->init();
4025
  tmp_table_param->table_charset= cs;
4026
  tmp_table_param->field_count= field_count;
4027
  tmp_table_param->schema_table= 1;
4028
  SELECT_LEX *select_lex= thd->lex->current_select;
4029
  if (!(table= create_tmp_table(thd, tmp_table_param,
4030
                                field_list, (ORDER*) 0, 0, 0, 
4031
                                (select_lex->options | thd->options |
4032
                                 TMP_TABLE_ALL_COLUMNS),
4033
                                HA_POS_ERROR, table_list->alias)))
4034
    DBUG_RETURN(0);
4035
  my_bitmap_map* bitmaps=
4036
    (my_bitmap_map*) thd->alloc(bitmap_buffer_size(field_count));
4037
  bitmap_init(&table->def_read_set, (my_bitmap_map*) bitmaps, field_count,
4038
              FALSE);
4039
  table->read_set= &table->def_read_set;
4040
  bitmap_clear_all(table->read_set);
4041
  table_list->schema_table_param= tmp_table_param;
4042
  DBUG_RETURN(table);
4043
}
4044
4045
4046
/*
4047
  For old SHOW compatibility. It is used when
4048
  old SHOW doesn't have generated column names
4049
  Make list of fields for SHOW
4050
4051
  SYNOPSIS
4052
    make_old_format()
4053
    thd			thread handler
4054
    schema_table        pointer to 'schema_tables' element
4055
4056
  RETURN
4057
   1	error
4058
   0	success
4059
*/
4060
4061
int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
4062
{
4063
  ST_FIELD_INFO *field_info= schema_table->fields_info;
4064
  Name_resolution_context *context= &thd->lex->select_lex.context;
4065
  for (; field_info->field_name; field_info++)
4066
  {
4067
    if (field_info->old_name)
4068
    {
4069
      Item_field *field= new Item_field(context,
4070
                                        NullS, NullS, field_info->field_name);
4071
      if (field)
4072
      {
4073
        field->set_name(field_info->old_name,
4074
                        strlen(field_info->old_name),
4075
                        system_charset_info);
4076
        if (add_item_to_list(thd, field))
4077
          return 1;
4078
      }
4079
    }
4080
  }
4081
  return 0;
4082
}
4083
4084
4085
int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
4086
{
4087
  char tmp[128];
4088
  LEX *lex= thd->lex;
4089
  SELECT_LEX *sel= lex->current_select;
4090
  Name_resolution_context *context= &sel->context;
4091
4092
  if (!sel->item_list.elements)
4093
  {
4094
    ST_FIELD_INFO *field_info= &schema_table->fields_info[1];
4095
    String buffer(tmp,sizeof(tmp), system_charset_info);
4096
    Item_field *field= new Item_field(context,
4097
                                      NullS, NullS, field_info->field_name);
4098
    if (!field || add_item_to_list(thd, field))
4099
      return 1;
4100
    buffer.length(0);
4101
    buffer.append(field_info->old_name);
4102
    if (lex->wild && lex->wild->ptr())
4103
    {
4104
      buffer.append(STRING_WITH_LEN(" ("));
4105
      buffer.append(lex->wild->ptr());
4106
      buffer.append(')');
4107
    }
4108
    field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
4109
  }
4110
  return 0;
4111
}
4112
4113
4114
int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
4115
{
4116
  char tmp[128];
4117
  String buffer(tmp,sizeof(tmp), thd->charset());
4118
  LEX *lex= thd->lex;
4119
  Name_resolution_context *context= &lex->select_lex.context;
4120
4121
  ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
4122
  buffer.length(0);
4123
  buffer.append(field_info->old_name);
4124
  buffer.append(lex->select_lex.db);
4125
  if (lex->wild && lex->wild->ptr())
4126
  {
4127
    buffer.append(STRING_WITH_LEN(" ("));
4128
    buffer.append(lex->wild->ptr());
4129
    buffer.append(')');
4130
  }
4131
  Item_field *field= new Item_field(context,
4132
                                    NullS, NullS, field_info->field_name);
4133
  if (add_item_to_list(thd, field))
4134
    return 1;
4135
  field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
4136
  if (thd->lex->verbose)
4137
  {
4138
    field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
4139
    field_info= &schema_table->fields_info[3];
4140
    field= new Item_field(context, NullS, NullS, field_info->field_name);
4141
    if (add_item_to_list(thd, field))
4142
      return 1;
4143
    field->set_name(field_info->old_name, strlen(field_info->old_name),
4144
                    system_charset_info);
4145
  }
4146
  return 0;
4147
}
4148
4149
4150
int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
4151
{
4152
  int fields_arr[]= {3, 14, 13, 6, 15, 5, 16, 17, 18, -1};
4153
  int *field_num= fields_arr;
4154
  ST_FIELD_INFO *field_info;
4155
  Name_resolution_context *context= &thd->lex->select_lex.context;
4156
4157
  for (; *field_num >= 0; field_num++)
4158
  {
4159
    field_info= &schema_table->fields_info[*field_num];
4160
    if (!thd->lex->verbose && (*field_num == 13 ||
4161
                               *field_num == 17 ||
4162
                               *field_num == 18))
4163
      continue;
4164
    Item_field *field= new Item_field(context,
4165
                                      NullS, NullS, field_info->field_name);
4166
    if (field)
4167
    {
4168
      field->set_name(field_info->old_name,
4169
                      strlen(field_info->old_name),
4170
                      system_charset_info);
4171
      if (add_item_to_list(thd, field))
4172
        return 1;
4173
    }
4174
  }
4175
  return 0;
4176
}
4177
4178
4179
int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
4180
{
4181
  int fields_arr[]= {0, 2, 1, 3, -1};
4182
  int *field_num= fields_arr;
4183
  ST_FIELD_INFO *field_info;
4184
  Name_resolution_context *context= &thd->lex->select_lex.context;
4185
4186
  for (; *field_num >= 0; field_num++)
4187
  {
4188
    field_info= &schema_table->fields_info[*field_num];
4189
    Item_field *field= new Item_field(context,
4190
                                      NullS, NullS, field_info->field_name);
4191
    if (field)
4192
    {
4193
      field->set_name(field_info->old_name,
4194
                      strlen(field_info->old_name),
4195
                      system_charset_info);
4196
      if (add_item_to_list(thd, field))
4197
        return 1;
4198
    }
4199
  }
4200
  return 0;
4201
}
4202
4203
4204
/*
4205
  Create information_schema table
4206
4207
  SYNOPSIS
4208
  mysql_schema_table()
4209
    thd                thread handler
4210
    lex                pointer to LEX
4211
    table_list         pointer to table_list
4212
4213
  RETURN
4214
    0	success
4215
    1   error
4216
*/
4217
4218
int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
4219
{
4220
  TABLE *table;
4221
  DBUG_ENTER("mysql_schema_table");
4222
  if (!(table= table_list->schema_table->create_table(thd, table_list)))
4223
    DBUG_RETURN(1);
4224
  table->s->tmp_table= SYSTEM_TMP_TABLE;
4225
  /*
4226
    This test is necessary to make
4227
    case insensitive file systems +
4228
    upper case table names(information schema tables) +
4229
    views
4230
    working correctly
4231
  */
4232
  if (table_list->schema_table_name)
4233
    table->alias_name_used= my_strcasecmp(table_alias_charset,
4234
                                          table_list->schema_table_name,
4235
                                          table_list->alias);
4236
  table_list->table_name= table->s->table_name.str;
4237
  table_list->table_name_length= table->s->table_name.length;
4238
  table_list->table= table;
4239
  table->next= thd->derived_tables;
4240
  thd->derived_tables= table;
4241
  table_list->select_lex->options |= OPTION_SCHEMA_TABLE;
4242
4243
  if (table_list->schema_table_reformed) // show command
4244
  {
4245
    SELECT_LEX *sel= lex->current_select;
4246
    Item *item;
4247
    Field_translator *transl, *org_transl;
4248
4249
    if (table_list->field_translation)
4250
    {
4251
      Field_translator *end= table_list->field_translation_end;
4252
      for (transl= table_list->field_translation; transl < end; transl++)
4253
      {
4254
        if (!transl->item->fixed &&
4255
            transl->item->fix_fields(thd, &transl->item))
4256
          DBUG_RETURN(1);
4257
      }
4258
      DBUG_RETURN(0);
4259
    }
4260
    List_iterator_fast<Item> it(sel->item_list);
4261
    if (!(transl=
4262
          (Field_translator*)(thd->stmt_arena->
4263
                              alloc(sel->item_list.elements *
4264
                                    sizeof(Field_translator)))))
4265
    {
4266
      DBUG_RETURN(1);
4267
    }
4268
    for (org_transl= transl; (item= it++); transl++)
4269
    {
4270
      transl->item= item;
4271
      transl->name= item->name;
4272
      if (!item->fixed && item->fix_fields(thd, &transl->item))
4273
      {
4274
        DBUG_RETURN(1);
4275
      }
4276
    }
4277
    table_list->field_translation= org_transl;
4278
    table_list->field_translation_end= transl;
4279
  }
4280
4281
  DBUG_RETURN(0);
4282
}
4283
4284
4285
/*
4286
  Generate select from information_schema table
4287
4288
  SYNOPSIS
4289
    make_schema_select()
4290
    thd                  thread handler
4291
    sel                  pointer to SELECT_LEX
4292
    schema_table_idx     index of 'schema_tables' element
4293
4294
  RETURN
4295
    0	success
4296
    1   error
4297
*/
4298
4299
int make_schema_select(THD *thd, SELECT_LEX *sel,
4300
		       enum enum_schema_tables schema_table_idx)
4301
{
4302
  ST_SCHEMA_TABLE *schema_table= get_schema_table(schema_table_idx);
4303
  LEX_STRING db, table;
4304
  DBUG_ENTER("make_schema_select");
4305
  DBUG_PRINT("enter", ("mysql_schema_select: %s", schema_table->table_name));
4306
  /*
4307
     We have to make non const db_name & table_name
4308
     because of lower_case_table_names
4309
  */
4310
  thd->make_lex_string(&db, INFORMATION_SCHEMA_NAME.str,
4311
                       INFORMATION_SCHEMA_NAME.length, 0);
4312
  thd->make_lex_string(&table, schema_table->table_name,
4313
                       strlen(schema_table->table_name), 0);
4314
  if (schema_table->old_format(thd, schema_table) ||   /* Handle old syntax */
4315
      !sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0),
4316
                              0, 0, TL_READ))
4317
  {
4318
    DBUG_RETURN(1);
4319
  }
4320
  DBUG_RETURN(0);
4321
}
4322
4323
4324
/*
4325
  Fill temporary schema tables before SELECT
4326
4327
  SYNOPSIS
4328
    get_schema_tables_result()
4329
    join  join which use schema tables
4330
    executed_place place where I_S table processed
4331
4332
  RETURN
4333
    FALSE success
4334
    TRUE  error
4335
*/
4336
4337
bool get_schema_tables_result(JOIN *join,
4338
                              enum enum_schema_table_state executed_place)
4339
{
4340
  JOIN_TAB *tmp_join_tab= join->join_tab+join->tables;
4341
  THD *thd= join->thd;
4342
  LEX *lex= thd->lex;
4343
  bool result= 0;
4344
  DBUG_ENTER("get_schema_tables_result");
4345
4346
  thd->no_warnings_for_error= 1;
4347
  for (JOIN_TAB *tab= join->join_tab; tab < tmp_join_tab; tab++)
4348
  {
4349
    if (!tab->table || !tab->table->pos_in_table_list)
4350
      break;
4351
4352
    TABLE_LIST *table_list= tab->table->pos_in_table_list;
4353
    if (table_list->schema_table)
4354
    {
4355
      bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
4356
                          lex->current_select->master_unit()->item);
4357
4358
4359
      /* skip I_S optimizations specific to get_all_tables */
4360
      if (thd->lex->describe &&
4361
          (table_list->schema_table->fill_table != get_all_tables))
4362
        continue;
4363
4364
      /*
4365
        If schema table is already processed and
4366
        the statement is not a subselect then
4367
        we don't need to fill this table again.
4368
        If schema table is already processed and
4369
        schema_table_state != executed_place then
4370
        table is already processed and
4371
        we should skip second data processing.
4372
      */
4373
      if (table_list->schema_table_state &&
4374
          (!is_subselect || table_list->schema_table_state != executed_place))
4375
        continue;
4376
4377
      /*
4378
        if table is used in a subselect and
4379
        table has been processed earlier with the same
4380
        'executed_place' value then we should refresh the table.
4381
      */
4382
      if (table_list->schema_table_state && is_subselect)
4383
      {
4384
        table_list->table->file->extra(HA_EXTRA_NO_CACHE);
4385
        table_list->table->file->extra(HA_EXTRA_RESET_STATE);
4386
        table_list->table->file->ha_delete_all_rows();
4387
        free_io_cache(table_list->table);
4388
        filesort_free_buffers(table_list->table,1);
4389
        table_list->table->null_row= 0;
4390
      }
4391
      else
4392
        table_list->table->file->stats.records= 0;
4393
4394
      if (table_list->schema_table->fill_table(thd, table_list,
4395
                                               tab->select_cond))
4396
      {
4397
        result= 1;
4398
        join->error= 1;
4399
        tab->read_record.file= table_list->table->file;
4400
        table_list->schema_table_state= executed_place;
4401
        break;
4402
      }
4403
      tab->read_record.file= table_list->table->file;
4404
      table_list->schema_table_state= executed_place;
4405
    }
4406
  }
4407
  thd->no_warnings_for_error= 0;
4408
  DBUG_RETURN(result);
4409
}
4410
4411
ST_FIELD_INFO schema_fields_info[]=
4412
{
4413
  {"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
4414
  {"SCHEMA_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Database",
4415
   SKIP_OPEN_TABLE},
4416
  {"DEFAULT_CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0,
4417
   SKIP_OPEN_TABLE},
4418
  {"DEFAULT_COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4419
  {"SQL_PATH", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
4420
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4421
};
4422
4423
4424
ST_FIELD_INFO tables_fields_info[]=
4425
{
4426
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
4427
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4428
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
4429
   SKIP_OPEN_TABLE},
4430
  {"TABLE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
4431
  {"ENGINE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Engine", OPEN_FRM_ONLY},
4432
  {"VERSION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
4433
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Version", OPEN_FRM_ONLY},
4434
  {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format", OPEN_FULL_TABLE},
4435
  {"TABLE_ROWS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
4436
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Rows", OPEN_FULL_TABLE},
4437
  {"AVG_ROW_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 
4438
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Avg_row_length", OPEN_FULL_TABLE},
4439
  {"DATA_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 
4440
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_length", OPEN_FULL_TABLE},
4441
  {"MAX_DATA_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
4442
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Max_data_length", OPEN_FULL_TABLE},
4443
  {"INDEX_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 
4444
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Index_length", OPEN_FULL_TABLE},
4445
  {"DATA_FREE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
4446
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_free", OPEN_FULL_TABLE},
4447
  {"AUTO_INCREMENT", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG, 0, 
4448
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Auto_increment", OPEN_FULL_TABLE},
4449
  {"CREATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Create_time", OPEN_FULL_TABLE},
4450
  {"UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Update_time", OPEN_FULL_TABLE},
4451
  {"CHECK_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Check_time", OPEN_FULL_TABLE},
4452
  {"TABLE_COLLATION", 64, MYSQL_TYPE_STRING, 0, 1, "Collation", OPEN_FRM_ONLY},
4453
  {"CHECKSUM", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
4454
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Checksum", OPEN_FULL_TABLE},
4455
  {"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, "Create_options",
4456
   OPEN_FRM_ONLY},
4457
  {"TABLE_COMMENT", TABLE_COMMENT_MAXLEN, MYSQL_TYPE_STRING, 0, 0, "Comment", OPEN_FRM_ONLY},
4458
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4459
};
4460
4461
4462
ST_FIELD_INFO columns_fields_info[]=
4463
{
4464
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
4465
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
4466
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
4467
  {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Field",
4468
   OPEN_FRM_ONLY},
4469
  {"ORDINAL_POSITION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
4470
   MY_I_S_UNSIGNED, 0, OPEN_FRM_ONLY},
4471
  {"COLUMN_DEFAULT", MAX_FIELD_VARCHARLENGTH, MYSQL_TYPE_STRING, 0,
4472
   1, "Default", OPEN_FRM_ONLY},
4473
  {"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null", OPEN_FRM_ONLY},
4474
  {"DATA_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
4475
  {"CHARACTER_MAXIMUM_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG,
4476
   0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
4477
  {"CHARACTER_OCTET_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG,
4478
   0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
4479
  {"NUMERIC_PRECISION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG,
4480
   0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
4481
  {"NUMERIC_SCALE", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG,
4482
   0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
4483
  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
4484
  {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 1, "Collation", OPEN_FRM_ONLY},
4485
  {"COLUMN_TYPE", 65535, MYSQL_TYPE_STRING, 0, 0, "Type", OPEN_FRM_ONLY},
4486
  {"COLUMN_KEY", 3, MYSQL_TYPE_STRING, 0, 0, "Key", OPEN_FRM_ONLY},
4487
  {"EXTRA", 27, MYSQL_TYPE_STRING, 0, 0, "Extra", OPEN_FRM_ONLY},
4488
  {"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, "Privileges", OPEN_FRM_ONLY},
4489
  {"COLUMN_COMMENT", COLUMN_COMMENT_MAXLEN, MYSQL_TYPE_STRING, 0, 0, "Comment", OPEN_FRM_ONLY},
4490
  {"STORAGE", 8, MYSQL_TYPE_STRING, 0, 0, "Storage", OPEN_FRM_ONLY},
4491
  {"FORMAT", 8, MYSQL_TYPE_STRING, 0, 0, "Format", OPEN_FRM_ONLY},
4492
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4493
};
4494
4495
4496
ST_FIELD_INFO charsets_fields_info[]=
4497
{
4498
  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Charset",
4499
   SKIP_OPEN_TABLE},
4500
  {"DEFAULT_COLLATE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Default collation",
4501
   SKIP_OPEN_TABLE},
4502
  {"DESCRIPTION", 60, MYSQL_TYPE_STRING, 0, 0, "Description",
4503
   SKIP_OPEN_TABLE},
4504
  {"MAXLEN", 3, MYSQL_TYPE_LONGLONG, 0, 0, "Maxlen", SKIP_OPEN_TABLE},
4505
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4506
};
4507
4508
4509
ST_FIELD_INFO collation_fields_info[]=
4510
{
4511
  {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Collation", SKIP_OPEN_TABLE},
4512
  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Charset",
4513
   SKIP_OPEN_TABLE},
4514
  {"ID", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Id",
4515
   SKIP_OPEN_TABLE},
4516
  {"IS_DEFAULT", 3, MYSQL_TYPE_STRING, 0, 0, "Default", SKIP_OPEN_TABLE},
4517
  {"IS_COMPILED", 3, MYSQL_TYPE_STRING, 0, 0, "Compiled", SKIP_OPEN_TABLE},
4518
  {"SORTLEN", 3, MYSQL_TYPE_LONGLONG, 0, 0, "Sortlen", SKIP_OPEN_TABLE},
4519
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4520
};
4521
4522
4523
ST_FIELD_INFO events_fields_info[]=
4524
{
4525
  {"EVENT_CATALOG", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
4526
  {"EVENT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Db",
4527
   SKIP_OPEN_TABLE},
4528
  {"EVENT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
4529
   SKIP_OPEN_TABLE},
4530
  {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", SKIP_OPEN_TABLE},
4531
  {"TIME_ZONE", 64, MYSQL_TYPE_STRING, 0, 0, "Time zone", SKIP_OPEN_TABLE},
4532
  {"EVENT_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4533
  {"EVENT_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4534
  {"EVENT_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE},
4535
  {"EXECUTE_AT", 0, MYSQL_TYPE_DATETIME, 0, 1, "Execute at", SKIP_OPEN_TABLE},
4536
  {"INTERVAL_VALUE", 256, MYSQL_TYPE_STRING, 0, 1, "Interval value",
4537
   SKIP_OPEN_TABLE},
4538
  {"INTERVAL_FIELD", 18, MYSQL_TYPE_STRING, 0, 1, "Interval field",
4539
   SKIP_OPEN_TABLE},
4540
  {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4541
  {"STARTS", 0, MYSQL_TYPE_DATETIME, 0, 1, "Starts", SKIP_OPEN_TABLE},
4542
  {"ENDS", 0, MYSQL_TYPE_DATETIME, 0, 1, "Ends", SKIP_OPEN_TABLE},
4543
  {"STATUS", 18, MYSQL_TYPE_STRING, 0, 0, "Status", SKIP_OPEN_TABLE},
4544
  {"ON_COMPLETION", 12, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4545
  {"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 0, 0, SKIP_OPEN_TABLE},
4546
  {"LAST_ALTERED", 0, MYSQL_TYPE_DATETIME, 0, 0, 0, SKIP_OPEN_TABLE},
4547
  {"LAST_EXECUTED", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE},
4548
  {"EVENT_COMMENT", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4549
  {"ORIGINATOR", 10, MYSQL_TYPE_LONGLONG, 0, 0, "Originator", SKIP_OPEN_TABLE},
4550
  {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
4551
   "character_set_client", SKIP_OPEN_TABLE},
4552
  {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
4553
   "collation_connection", SKIP_OPEN_TABLE},
4554
  {"DATABASE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
4555
   "Database Collation", SKIP_OPEN_TABLE},
4556
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4557
};
4558
4559
4560
4561
ST_FIELD_INFO coll_charset_app_fields_info[]=
4562
{
4563
  {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4564
  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4565
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4566
};
4567
4568
4569
ST_FIELD_INFO stat_fields_info[]=
4570
{
4571
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
4572
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
4573
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table", OPEN_FRM_ONLY},
4574
  {"NON_UNIQUE", 1, MYSQL_TYPE_LONGLONG, 0, 0, "Non_unique", OPEN_FRM_ONLY},
4575
  {"INDEX_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
4576
  {"INDEX_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Key_name",
4577
   OPEN_FRM_ONLY},
4578
  {"SEQ_IN_INDEX", 2, MYSQL_TYPE_LONGLONG, 0, 0, "Seq_in_index", OPEN_FRM_ONLY},
4579
  {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Column_name",
4580
   OPEN_FRM_ONLY},
4581
  {"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, "Collation", OPEN_FRM_ONLY},
4582
  {"CARDINALITY", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 1,
4583
   "Cardinality", OPEN_FULL_TABLE},
4584
  {"SUB_PART", 3, MYSQL_TYPE_LONGLONG, 0, 1, "Sub_part", OPEN_FRM_ONLY},
4585
  {"PACKED", 10, MYSQL_TYPE_STRING, 0, 1, "Packed", OPEN_FRM_ONLY},
4586
  {"NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null", OPEN_FRM_ONLY},
4587
  {"INDEX_TYPE", 16, MYSQL_TYPE_STRING, 0, 0, "Index_type", OPEN_FULL_TABLE},
4588
  {"COMMENT", 16, MYSQL_TYPE_STRING, 0, 1, "Comment", OPEN_FRM_ONLY},
4589
  {"INDEX_COMMENT", INDEX_COMMENT_MAXLEN, MYSQL_TYPE_STRING, 0, 0, "Index_Comment", OPEN_FRM_ONLY},
4590
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4591
};
4592
4593
4594
ST_FIELD_INFO user_privileges_fields_info[]=
4595
{
4596
  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4597
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
4598
  {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4599
  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4600
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4601
};
4602
4603
4604
ST_FIELD_INFO schema_privileges_fields_info[]=
4605
{
4606
  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4607
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
4608
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4609
  {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4610
  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4611
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4612
};
4613
4614
4615
ST_FIELD_INFO table_privileges_fields_info[]=
4616
{
4617
  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4618
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
4619
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4620
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4621
  {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4622
  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4623
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4624
};
4625
4626
4627
ST_FIELD_INFO column_privileges_fields_info[]=
4628
{
4629
  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4630
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
4631
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4632
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4633
  {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4634
  {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4635
  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4636
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4637
};
4638
4639
4640
ST_FIELD_INFO table_constraints_fields_info[]=
4641
{
4642
  {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
4643
  {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
4644
   OPEN_FULL_TABLE},
4645
  {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
4646
   OPEN_FULL_TABLE},
4647
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
4648
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
4649
  {"CONSTRAINT_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
4650
   OPEN_FULL_TABLE},
4651
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4652
};
4653
4654
4655
ST_FIELD_INFO key_column_usage_fields_info[]=
4656
{
4657
  {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
4658
  {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
4659
   OPEN_FULL_TABLE},
4660
  {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
4661
   OPEN_FULL_TABLE},
4662
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
4663
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
4664
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
4665
  {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
4666
  {"ORDINAL_POSITION", 10 ,MYSQL_TYPE_LONGLONG, 0, 0, 0, OPEN_FULL_TABLE},
4667
  {"POSITION_IN_UNIQUE_CONSTRAINT", 10 ,MYSQL_TYPE_LONGLONG, 0, 1, 0,
4668
   OPEN_FULL_TABLE},
4669
  {"REFERENCED_TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
4670
   OPEN_FULL_TABLE},
4671
  {"REFERENCED_TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
4672
   OPEN_FULL_TABLE},
4673
  {"REFERENCED_COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
4674
   OPEN_FULL_TABLE},
4675
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4676
};
4677
4678
4679
ST_FIELD_INFO table_names_fields_info[]=
4680
{
4681
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
4682
  {"TABLE_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4683
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Tables_in_",
4684
   SKIP_OPEN_TABLE},
4685
  {"TABLE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_type",
4686
   OPEN_FRM_ONLY},
4687
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4688
};
4689
4690
4691
ST_FIELD_INFO open_tables_fields_info[]=
4692
{
4693
  {"Database", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Database",
4694
   SKIP_OPEN_TABLE},
4695
  {"Table",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table", SKIP_OPEN_TABLE},
4696
  {"In_use", 1, MYSQL_TYPE_LONGLONG, 0, 0, "In_use", SKIP_OPEN_TABLE},
4697
  {"Name_locked", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Name_locked", SKIP_OPEN_TABLE},
4698
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4699
};
4700
4701
4702
ST_FIELD_INFO variables_fields_info[]=
4703
{
4704
  {"VARIABLE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Variable_name",
4705
   SKIP_OPEN_TABLE},
4706
  {"VARIABLE_VALUE", 16300, MYSQL_TYPE_STRING, 0, 1, "Value", SKIP_OPEN_TABLE},
4707
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4708
};
4709
4710
4711
ST_FIELD_INFO processlist_fields_info[]=
4712
{
4713
  {"ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Id", SKIP_OPEN_TABLE},
4714
  {"USER", 16, MYSQL_TYPE_STRING, 0, 0, "User", SKIP_OPEN_TABLE},
4715
  {"HOST", LIST_PROCESS_HOST_LEN,  MYSQL_TYPE_STRING, 0, 0, "Host",
4716
   SKIP_OPEN_TABLE},
4717
  {"DB", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Db", SKIP_OPEN_TABLE},
4718
  {"COMMAND", 16, MYSQL_TYPE_STRING, 0, 0, "Command", SKIP_OPEN_TABLE},
4719
  {"TIME", 7, MYSQL_TYPE_LONGLONG, 0, 0, "Time", SKIP_OPEN_TABLE},
4720
  {"STATE", 64, MYSQL_TYPE_STRING, 0, 1, "State", SKIP_OPEN_TABLE},
4721
  {"INFO", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info",
4722
   SKIP_OPEN_TABLE},
4723
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4724
};
4725
4726
4727
ST_FIELD_INFO plugin_fields_info[]=
4728
{
4729
  {"PLUGIN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
4730
   SKIP_OPEN_TABLE},
4731
  {"PLUGIN_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4732
  {"PLUGIN_STATUS", 10, MYSQL_TYPE_STRING, 0, 0, "Status", SKIP_OPEN_TABLE},
4733
  {"PLUGIN_TYPE", 80, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE},
4734
  {"PLUGIN_TYPE_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
4735
  {"PLUGIN_LIBRARY", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Library",
4736
   SKIP_OPEN_TABLE},
4737
  {"PLUGIN_LIBRARY_VERSION", 20, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
4738
  {"PLUGIN_AUTHOR", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
4739
  {"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
4740
  {"PLUGIN_LICENSE", 80, MYSQL_TYPE_STRING, 0, 1, "License", SKIP_OPEN_TABLE},
4741
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4742
};
4743
4744
ST_FIELD_INFO referential_constraints_fields_info[]=
4745
{
4746
  {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
4747
  {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
4748
   OPEN_FULL_TABLE},
4749
  {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
4750
   OPEN_FULL_TABLE},
4751
  {"UNIQUE_CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0,
4752
   OPEN_FULL_TABLE},
4753
  {"UNIQUE_CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
4754
   OPEN_FULL_TABLE},
4755
  {"UNIQUE_CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0,
4756
   MY_I_S_MAYBE_NULL, 0, OPEN_FULL_TABLE},
4757
  {"MATCH_OPTION", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
4758
  {"UPDATE_RULE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
4759
  {"DELETE_RULE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
4760
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
4761
  {"REFERENCED_TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
4762
   OPEN_FULL_TABLE},
4763
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
4764
};
4765
4766
4767
ST_FIELD_INFO parameters_fields_info[]=
4768
{
4769
  {"SPECIFIC_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
4770
  {"SPECIFIC_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
4771
  {"SPECIFIC_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
4772
  {"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0, OPEN_FULL_TABLE},
4773
  {"PARAMETER_MODE", 5, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
4774
  {"PARAMETER_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
4775
  {"DATA_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
4776
  {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE},
4777
  {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE},
4778
  {"NUMERIC_PRECISION", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE},
4779
  {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE},
4780
  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
4781
  {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
4782
  {"DTD_IDENTIFIER", 65535, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
4783
  {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
4784
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}
4785
};
4786
4787
4788
/*
4789
  Description of ST_FIELD_INFO in table.h
4790
4791
  Make sure that the order of schema_tables and enum_schema_tables are the same.
4792
4793
*/
4794
4795
ST_SCHEMA_TABLE schema_tables[]=
4796
{
4797
  {"CHARACTER_SETS", charsets_fields_info, create_schema_table, 
4798
   fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0, 0},
4799
  {"COLLATIONS", collation_fields_info, create_schema_table, 
4800
   fill_schema_collation, make_old_format, 0, -1, -1, 0, 0},
4801
  {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info,
4802
   create_schema_table, fill_schema_coll_charset_app, 0, 0, -1, -1, 0, 0},
4803
  {"COLUMNS", columns_fields_info, create_schema_table, 
4804
   get_all_tables, make_columns_old_format, get_schema_column_record, 1, 2, 0,
4805
   OPTIMIZE_I_S_TABLE|OPEN_VIEW_FULL},
4806
  {"GLOBAL_STATUS", variables_fields_info, create_schema_table,
4807
   fill_status, make_old_format, 0, -1, -1, 0, 0},
4808
  {"GLOBAL_VARIABLES", variables_fields_info, create_schema_table,
4809
   fill_variables, make_old_format, 0, -1, -1, 0, 0},
4810
  {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
4811
   get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0,
4812
   OPEN_TABLE_ONLY},
4813
  {"OPEN_TABLES", open_tables_fields_info, create_schema_table,
4814
   fill_open_tables, make_old_format, 0, -1, -1, 1, 0},
4815
  {"PLUGINS", plugin_fields_info, create_schema_table,
4816
   fill_plugins, make_old_format, 0, -1, -1, 0, 0},
4817
  {"PROCESSLIST", processlist_fields_info, create_schema_table,
4818
   fill_schema_processlist, make_old_format, 0, -1, -1, 0, 0},
4819
  {"REFERENTIAL_CONSTRAINTS", referential_constraints_fields_info,
4820
   create_schema_table, get_all_tables, 0, get_referential_constraints_record,
4821
   1, 9, 0, OPEN_TABLE_ONLY},
4822
  {"SCHEMATA", schema_fields_info, create_schema_table,
4823
   fill_schema_schemata, make_schemata_old_format, 0, 1, -1, 0, 0},
4824
  {"SESSION_STATUS", variables_fields_info, create_schema_table,
4825
   fill_status, make_old_format, 0, -1, -1, 0, 0},
4826
  {"SESSION_VARIABLES", variables_fields_info, create_schema_table,
4827
   fill_variables, make_old_format, 0, -1, -1, 0, 0},
4828
  {"STATISTICS", stat_fields_info, create_schema_table, 
4829
   get_all_tables, make_old_format, get_schema_stat_record, 1, 2, 0,
4830
   OPEN_TABLE_ONLY|OPTIMIZE_I_S_TABLE},
4831
  {"STATUS", variables_fields_info, create_schema_table, fill_status, 
4832
   make_old_format, 0, -1, -1, 1, 0},
4833
  {"TABLES", tables_fields_info, create_schema_table, 
4834
   get_all_tables, make_old_format, get_schema_tables_record, 1, 2, 0,
4835
   OPTIMIZE_I_S_TABLE},
4836
  {"TABLE_CONSTRAINTS", table_constraints_fields_info, create_schema_table,
4837
   get_all_tables, 0, get_schema_constraints_record, 3, 4, 0, OPEN_TABLE_ONLY},
4838
  {"TABLE_NAMES", table_names_fields_info, create_schema_table,
4839
   get_all_tables, make_table_names_old_format, 0, 1, 2, 1, 0},
4840
  {"VARIABLES", variables_fields_info, create_schema_table, fill_variables,
4841
   make_old_format, 0, -1, -1, 1, 0},
4842
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
4843
};
4844
4845
4846
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
4847
template class List_iterator_fast<char>;
4848
template class List<char>;
4849
#endif
4850
4851
int initialize_schema_table(st_plugin_int *plugin)
4852
{
4853
  ST_SCHEMA_TABLE *schema_table;
4854
  DBUG_ENTER("initialize_schema_table");
4855
4856
  if (!(schema_table= (ST_SCHEMA_TABLE *)my_malloc(sizeof(ST_SCHEMA_TABLE),
4857
                                MYF(MY_WME | MY_ZEROFILL))))
4858
      DBUG_RETURN(1);
4859
  /* Historical Requirement */
4860
  plugin->data= schema_table; // shortcut for the future
4861
  if (plugin->plugin->init)
4862
  {
4863
    schema_table->create_table= create_schema_table;
4864
    schema_table->old_format= make_old_format;
4865
    schema_table->idx_field1= -1, 
4866
    schema_table->idx_field2= -1; 
4867
4868
    /* Make the name available to the init() function. */
4869
    schema_table->table_name= plugin->name.str;
4870
4871
    if (plugin->plugin->init(schema_table))
4872
    {
4873
      sql_print_error("Plugin '%s' init function returned error.",
4874
                      plugin->name.str);
4875
      goto err;
4876
    }
4877
    
4878
    /* Make sure the plugin name is not set inside the init() function. */
4879
    schema_table->table_name= plugin->name.str;
4880
  }
4881
4882
  DBUG_RETURN(0);
4883
err:
4884
  my_free(schema_table, MYF(0));
4885
  DBUG_RETURN(1);
4886
}
4887
4888
int finalize_schema_table(st_plugin_int *plugin)
4889
{
4890
  ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE *)plugin->data;
4891
  DBUG_ENTER("finalize_schema_table");
4892
4893
  if (schema_table && plugin->plugin->deinit)
4894
  {
4895
    DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str));
4896
    if (plugin->plugin->deinit(NULL))
4897
    {
4898
      DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.",
4899
                             plugin->name.str));
4900
    }
4901
    my_free(schema_table, MYF(0));
4902
  }
4903
  DBUG_RETURN(0);
4904
}