~stewart/drizzle/embedded-innodb-create-select-transaction-arrgh

« back to all changes in this revision

Viewing changes to sql/sql_show.cc

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
263
        if (!my_stat(buff, file->mystat, MYF(0)))
 
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;
 
2835
    MY_STAT stat_info;
 
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;
 
2841
    if (!my_stat(path,&stat_info,MYF(0)))
 
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_DECIMAL:
 
3114
    field_length= field->field_length - (decimals  ? 2 : 1);
 
3115
    break;
 
3116
  case MYSQL_TYPE_TINY:
 
3117
  case MYSQL_TYPE_SHORT:
 
3118
  case MYSQL_TYPE_LONG:
 
3119
  case MYSQL_TYPE_LONGLONG:
 
3120
  case MYSQL_TYPE_INT24:
 
3121
    field_length= field->max_display_length() - 1;
 
3122
    break;
 
3123
  case MYSQL_TYPE_BIT:
 
3124
    field_length= field->max_display_length();
 
3125
    decimals= -1;                             // return NULL
 
3126
    break;
 
3127
  case MYSQL_TYPE_FLOAT:  
 
3128
  case MYSQL_TYPE_DOUBLE:
 
3129
    field_length= field->field_length;
 
3130
    if (decimals == NOT_FIXED_DEC)
 
3131
      decimals= -1;                           // return NULL
 
3132
    break;
 
3133
  default:
 
3134
    field_length= decimals= -1;
 
3135
    break;
 
3136
  }
 
3137
 
 
3138
  /* NUMERIC_PRECISION column */
 
3139
  if (field_length >= 0)
 
3140
  {
 
3141
    table->field[offset + 3]->store((longlong) field_length, TRUE);
 
3142
    table->field[offset + 3]->set_notnull();
 
3143
  }
 
3144
  /* NUMERIC_SCALE column */
 
3145
  if (decimals >= 0)
 
3146
  {
 
3147
    table->field[offset + 4]->store((longlong) decimals, TRUE);
 
3148
    table->field[offset + 4]->set_notnull();
 
3149
  }
 
3150
  if (field->has_charset())
 
3151
  {
 
3152
    /* CHARACTER_SET_NAME column*/
 
3153
    tmp_buff= field->charset()->csname;
 
3154
    table->field[offset + 5]->store(tmp_buff, strlen(tmp_buff), cs);
 
3155
    table->field[offset + 5]->set_notnull();
 
3156
    /* COLLATION_NAME column */
 
3157
    tmp_buff= field->charset()->name;
 
3158
    table->field[offset + 6]->store(tmp_buff, strlen(tmp_buff), cs);
 
3159
    table->field[offset + 6]->set_notnull();
 
3160
  }
 
3161
}
 
3162
 
 
3163
 
 
3164
static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
 
3165
                                    TABLE *table, bool res,
 
3166
                                    LEX_STRING *db_name,
 
3167
                                    LEX_STRING *table_name)
 
3168
{
 
3169
  LEX *lex= thd->lex;
 
3170
  const char *wild= lex->wild ? lex->wild->ptr() : NullS;
 
3171
  CHARSET_INFO *cs= system_charset_info;
 
3172
  TABLE *show_table;
 
3173
  TABLE_SHARE *show_table_share;
 
3174
  Field **ptr, *field, *timestamp_field;
 
3175
  int count;
 
3176
  DBUG_ENTER("get_schema_column_record");
 
3177
 
 
3178
  if (res)
 
3179
  {
 
3180
    if (lex->sql_command != SQLCOM_SHOW_FIELDS)
 
3181
    {
 
3182
      /*
 
3183
        I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS
 
3184
        rather than in SHOW COLUMNS
 
3185
      */ 
 
3186
      if (thd->is_error())
 
3187
        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
3188
                     thd->main_da.sql_errno(), thd->main_da.message());
 
3189
      thd->clear_error();
 
3190
      res= 0;
 
3191
    }
 
3192
    DBUG_RETURN(res);
 
3193
  }
 
3194
 
 
3195
  show_table= tables->table;
 
3196
  show_table_share= show_table->s;
 
3197
  count= 0;
 
3198
 
 
3199
  if (tables->schema_table)
 
3200
  {
 
3201
    ptr= show_table->field;
 
3202
    timestamp_field= show_table->timestamp_field;
 
3203
    show_table->use_all_columns();               // Required for default
 
3204
  }
 
3205
  else
 
3206
  {
 
3207
    ptr= show_table_share->field;
 
3208
    timestamp_field= show_table_share->timestamp_field;
 
3209
    /*
 
3210
      read_set may be inited in case of
 
3211
      temporary table
 
3212
    */
 
3213
    if (!show_table->read_set)
 
3214
    {
 
3215
      /* to satisfy 'field->val_str' ASSERTs */
 
3216
      uchar *bitmaps;
 
3217
      uint bitmap_size= show_table_share->column_bitmap_size;
 
3218
      if (!(bitmaps= (uchar*) alloc_root(thd->mem_root, bitmap_size)))
 
3219
        DBUG_RETURN(0);
 
3220
      bitmap_init(&show_table->def_read_set,
 
3221
                  (my_bitmap_map*) bitmaps, show_table_share->fields, FALSE);
 
3222
      bitmap_set_all(&show_table->def_read_set);
 
3223
      show_table->read_set= &show_table->def_read_set;
 
3224
    }
 
3225
    bitmap_set_all(show_table->read_set);
 
3226
  }
 
3227
 
 
3228
  for (; (field= *ptr) ; ptr++)
 
3229
  {
 
3230
    uchar *pos;
 
3231
    char tmp[MAX_FIELD_WIDTH];
 
3232
    String type(tmp,sizeof(tmp), system_charset_info);
 
3233
    char *end;
 
3234
 
 
3235
    /* to satisfy 'field->val_str' ASSERTs */
 
3236
    field->table= show_table;
 
3237
    show_table->in_use= thd;
 
3238
 
 
3239
    if (wild && wild[0] &&
 
3240
        wild_case_compare(system_charset_info, field->field_name,wild))
 
3241
      continue;
 
3242
 
 
3243
    count++;
 
3244
    /* Get default row, with all NULL fields set to NULL */
 
3245
    restore_record(table, s->default_values);
 
3246
 
 
3247
    table->field[1]->store(db_name->str, db_name->length, cs);
 
3248
    table->field[2]->store(table_name->str, table_name->length, cs);
 
3249
    table->field[3]->store(field->field_name, strlen(field->field_name),
 
3250
                           cs);
 
3251
    table->field[4]->store((longlong) count, TRUE);
 
3252
 
 
3253
    if (get_field_default_value(thd, timestamp_field, field, &type, 0))
 
3254
    {
 
3255
      table->field[5]->store(type.ptr(), type.length(), cs);
 
3256
      table->field[5]->set_notnull();
 
3257
    }
 
3258
    pos=(uchar*) ((field->flags & NOT_NULL_FLAG) ?  "NO" : "YES");
 
3259
    table->field[6]->store((const char*) pos,
 
3260
                           strlen((const char*) pos), cs);
 
3261
    store_column_type(table, field, cs, 7);
 
3262
 
 
3263
    pos=(uchar*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
 
3264
                 (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
 
3265
                 (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
 
3266
    table->field[15]->store((const char*) pos,
 
3267
                            strlen((const char*) pos), cs);
 
3268
 
 
3269
    end= tmp;
 
3270
    if (field->unireg_check == Field::NEXT_NUMBER)
 
3271
      table->field[16]->store(STRING_WITH_LEN("auto_increment"), cs);
 
3272
    if (timestamp_field == field &&
 
3273
        field->unireg_check != Field::TIMESTAMP_DN_FIELD)
 
3274
      table->field[16]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"),
 
3275
                              cs);
 
3276
 
 
3277
    table->field[18]->store(field->comment.str, field->comment.length, cs);
 
3278
    {
 
3279
      enum ha_storage_media storage_type= (enum ha_storage_media)
 
3280
        ((field->flags >> FIELD_STORAGE_FLAGS) & STORAGE_TYPE_MASK);
 
3281
      enum column_format_type column_format= (enum column_format_type)
 
3282
        ((field->flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
 
3283
      pos=(uchar*)(storage_type == HA_SM_DEFAULT ? "Default" :
 
3284
                   storage_type == HA_SM_DISK ? "Disk" : "Memory");
 
3285
      table->field[19]->store((const char*) pos,
 
3286
                              strlen((const char*) pos), cs);
 
3287
      pos=(uchar*)(column_format == COLUMN_FORMAT_TYPE_DEFAULT ? "Default" :
 
3288
                   column_format == COLUMN_FORMAT_TYPE_FIXED ? "Fixed" :
 
3289
                                                             "Dynamic");
 
3290
      table->field[20]->store((const char*) pos,
 
3291
                              strlen((const char*) pos), cs);
 
3292
    }
 
3293
    if (schema_table_store_record(thd, table))
 
3294
      DBUG_RETURN(1);
 
3295
  }
 
3296
  DBUG_RETURN(0);
 
3297
}
 
3298
 
 
3299
 
 
3300
 
 
3301
int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond)
 
3302
{
 
3303
  CHARSET_INFO **cs;
 
3304
  const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
 
3305
  TABLE *table= tables->table;
 
3306
  CHARSET_INFO *scs= system_charset_info;
 
3307
 
 
3308
  for (cs= all_charsets ; cs < all_charsets+255 ; cs++)
 
3309
  {
 
3310
    CHARSET_INFO *tmp_cs= cs[0];
 
3311
    if (tmp_cs && (tmp_cs->state & MY_CS_PRIMARY) && 
 
3312
        (tmp_cs->state & MY_CS_AVAILABLE) &&
 
3313
        !(tmp_cs->state & MY_CS_HIDDEN) &&
 
3314
        !(wild && wild[0] &&
 
3315
          wild_case_compare(scs, tmp_cs->csname,wild)))
 
3316
    {
 
3317
      const char *comment;
 
3318
      restore_record(table, s->default_values);
 
3319
      table->field[0]->store(tmp_cs->csname, strlen(tmp_cs->csname), scs);
 
3320
      table->field[1]->store(tmp_cs->name, strlen(tmp_cs->name), scs);
 
3321
      comment= tmp_cs->comment ? tmp_cs->comment : "";
 
3322
      table->field[2]->store(comment, strlen(comment), scs);
 
3323
      table->field[3]->store((longlong) tmp_cs->mbmaxlen, TRUE);
 
3324
      if (schema_table_store_record(thd, table))
 
3325
        return 1;
 
3326
    }
 
3327
  }
 
3328
  return 0;
 
3329
}
 
3330
 
 
3331
 
 
3332
int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond)
 
3333
{
 
3334
  CHARSET_INFO **cs;
 
3335
  const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
 
3336
  TABLE *table= tables->table;
 
3337
  CHARSET_INFO *scs= system_charset_info;
 
3338
  for (cs= all_charsets ; cs < all_charsets+255 ; cs++ )
 
3339
  {
 
3340
    CHARSET_INFO **cl;
 
3341
    CHARSET_INFO *tmp_cs= cs[0];
 
3342
    if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
 
3343
         (tmp_cs->state & MY_CS_HIDDEN) ||
 
3344
        !(tmp_cs->state & MY_CS_PRIMARY))
 
3345
      continue;
 
3346
    for (cl= all_charsets; cl < all_charsets+255 ;cl ++)
 
3347
    {
 
3348
      CHARSET_INFO *tmp_cl= cl[0];
 
3349
      if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || 
 
3350
          !my_charset_same(tmp_cs, tmp_cl))
 
3351
        continue;
 
3352
      if (!(wild && wild[0] &&
 
3353
          wild_case_compare(scs, tmp_cl->name,wild)))
 
3354
      {
 
3355
        const char *tmp_buff;
 
3356
        restore_record(table, s->default_values);
 
3357
        table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
 
3358
        table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
 
3359
        table->field[2]->store((longlong) tmp_cl->number, TRUE);
 
3360
        tmp_buff= (tmp_cl->state & MY_CS_PRIMARY) ? "Yes" : "";
 
3361
        table->field[3]->store(tmp_buff, strlen(tmp_buff), scs);
 
3362
        tmp_buff= (tmp_cl->state & MY_CS_COMPILED)? "Yes" : "";
 
3363
        table->field[4]->store(tmp_buff, strlen(tmp_buff), scs);
 
3364
        table->field[5]->store((longlong) tmp_cl->strxfrm_multiply, TRUE);
 
3365
        if (schema_table_store_record(thd, table))
 
3366
          return 1;
 
3367
      }
 
3368
    }
 
3369
  }
 
3370
  return 0;
 
3371
}
 
3372
 
 
3373
 
 
3374
int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, COND *cond)
 
3375
{
 
3376
  CHARSET_INFO **cs;
 
3377
  TABLE *table= tables->table;
 
3378
  CHARSET_INFO *scs= system_charset_info;
 
3379
  for (cs= all_charsets ; cs < all_charsets+255 ; cs++ )
 
3380
  {
 
3381
    CHARSET_INFO **cl;
 
3382
    CHARSET_INFO *tmp_cs= cs[0];
 
3383
    if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || 
 
3384
        !(tmp_cs->state & MY_CS_PRIMARY))
 
3385
      continue;
 
3386
    for (cl= all_charsets; cl < all_charsets+255 ;cl ++)
 
3387
    {
 
3388
      CHARSET_INFO *tmp_cl= cl[0];
 
3389
      if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || 
 
3390
          !my_charset_same(tmp_cs,tmp_cl))
 
3391
        continue;
 
3392
      restore_record(table, s->default_values);
 
3393
      table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
 
3394
      table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
 
3395
      if (schema_table_store_record(thd, table))
 
3396
        return 1;
 
3397
    }
 
3398
  }
 
3399
  return 0;
 
3400
}
 
3401
 
 
3402
 
 
3403
static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
 
3404
                                  TABLE *table, bool res,
 
3405
                                  LEX_STRING *db_name,
 
3406
                                  LEX_STRING *table_name)
 
3407
{
 
3408
  CHARSET_INFO *cs= system_charset_info;
 
3409
  DBUG_ENTER("get_schema_stat_record");
 
3410
  if (res)
 
3411
  {
 
3412
    if (thd->lex->sql_command != SQLCOM_SHOW_KEYS)
 
3413
    {
 
3414
      /*
 
3415
        I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS
 
3416
        rather than in SHOW KEYS
 
3417
      */
 
3418
      if (thd->is_error())
 
3419
        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
3420
                     thd->main_da.sql_errno(), thd->main_da.message());
 
3421
      thd->clear_error();
 
3422
      res= 0;
 
3423
    }
 
3424
    DBUG_RETURN(res);
 
3425
  }
 
3426
  else
 
3427
  {
 
3428
    TABLE *show_table= tables->table;
 
3429
    KEY *key_info=show_table->s->key_info;
 
3430
    if (show_table->file)
 
3431
      show_table->file->info(HA_STATUS_VARIABLE |
 
3432
                             HA_STATUS_NO_LOCK |
 
3433
                             HA_STATUS_TIME);
 
3434
    for (uint i=0 ; i < show_table->s->keys ; i++,key_info++)
 
3435
    {
 
3436
      KEY_PART_INFO *key_part= key_info->key_part;
 
3437
      const char *str;
 
3438
      for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
 
3439
      {
 
3440
        restore_record(table, s->default_values);
 
3441
        table->field[1]->store(db_name->str, db_name->length, cs);
 
3442
        table->field[2]->store(table_name->str, table_name->length, cs);
 
3443
        table->field[3]->store((longlong) ((key_info->flags &
 
3444
                                            HA_NOSAME) ? 0 : 1), TRUE);
 
3445
        table->field[4]->store(db_name->str, db_name->length, cs);
 
3446
        table->field[5]->store(key_info->name, strlen(key_info->name), cs);
 
3447
        table->field[6]->store((longlong) (j+1), TRUE);
 
3448
        str=(key_part->field ? key_part->field->field_name :
 
3449
             "?unknown field?");
 
3450
        table->field[7]->store(str, strlen(str), cs);
 
3451
        if (show_table->file)
 
3452
        {
 
3453
          if (show_table->file->index_flags(i, j, 0) & HA_READ_ORDER)
 
3454
          {
 
3455
            table->field[8]->store(((key_part->key_part_flag &
 
3456
                                     HA_REVERSE_SORT) ?
 
3457
                                    "D" : "A"), 1, cs);
 
3458
            table->field[8]->set_notnull();
 
3459
          }
 
3460
          KEY *key=show_table->key_info+i;
 
3461
          if (key->rec_per_key[j])
 
3462
          {
 
3463
            ha_rows records=(show_table->file->stats.records /
 
3464
                             key->rec_per_key[j]);
 
3465
            table->field[9]->store((longlong) records, TRUE);
 
3466
            table->field[9]->set_notnull();
 
3467
          }
 
3468
          str= show_table->file->index_type(i);
 
3469
          table->field[13]->store(str, strlen(str), cs);
 
3470
        }
 
3471
        if ((key_part->field &&
 
3472
             key_part->length !=
 
3473
             show_table->s->field[key_part->fieldnr-1]->key_length()))
 
3474
        {
 
3475
          table->field[10]->store((longlong) key_part->length /
 
3476
                                  key_part->field->charset()->mbmaxlen, TRUE);
 
3477
          table->field[10]->set_notnull();
 
3478
        }
 
3479
        uint flags= key_part->field ? key_part->field->flags : 0;
 
3480
        const char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
 
3481
        table->field[12]->store(pos, strlen(pos), cs);
 
3482
        if (!show_table->s->keys_in_use.is_set(i))
 
3483
          table->field[14]->store(STRING_WITH_LEN("disabled"), cs);
 
3484
        else
 
3485
          table->field[14]->store("", 0, cs);
 
3486
        table->field[14]->set_notnull();
 
3487
        DBUG_ASSERT(test(key_info->flags & HA_USES_COMMENT) == 
 
3488
                   (key_info->comment.length > 0));
 
3489
        if (key_info->flags & HA_USES_COMMENT)
 
3490
          table->field[15]->store(key_info->comment.str, 
 
3491
                                  key_info->comment.length, cs);
 
3492
        if (schema_table_store_record(thd, table))
 
3493
          DBUG_RETURN(1);
 
3494
      }
 
3495
    }
 
3496
  }
 
3497
  DBUG_RETURN(res);
 
3498
}
 
3499
 
 
3500
 
 
3501
bool store_constraints(THD *thd, TABLE *table, LEX_STRING *db_name,
 
3502
                       LEX_STRING *table_name, const char *key_name,
 
3503
                       uint key_len, const char *con_type, uint con_len)
 
3504
{
 
3505
  CHARSET_INFO *cs= system_charset_info;
 
3506
  restore_record(table, s->default_values);
 
3507
  table->field[1]->store(db_name->str, db_name->length, cs);
 
3508
  table->field[2]->store(key_name, key_len, cs);
 
3509
  table->field[3]->store(db_name->str, db_name->length, cs);
 
3510
  table->field[4]->store(table_name->str, table_name->length, cs);
 
3511
  table->field[5]->store(con_type, con_len, cs);
 
3512
  return schema_table_store_record(thd, table);
 
3513
}
 
3514
 
 
3515
 
 
3516
static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables,
 
3517
                                         TABLE *table, bool res,
 
3518
                                         LEX_STRING *db_name,
 
3519
                                         LEX_STRING *table_name)
 
3520
{
 
3521
  DBUG_ENTER("get_schema_constraints_record");
 
3522
  if (res)
 
3523
  {
 
3524
    if (thd->is_error())
 
3525
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
3526
                   thd->main_da.sql_errno(), thd->main_da.message());
 
3527
    thd->clear_error();
 
3528
    DBUG_RETURN(0);
 
3529
  }
 
3530
  else
 
3531
  {
 
3532
    List<FOREIGN_KEY_INFO> f_key_list;
 
3533
    TABLE *show_table= tables->table;
 
3534
    KEY *key_info=show_table->key_info;
 
3535
    uint primary_key= show_table->s->primary_key;
 
3536
    show_table->file->info(HA_STATUS_VARIABLE | 
 
3537
                           HA_STATUS_NO_LOCK |
 
3538
                           HA_STATUS_TIME);
 
3539
    for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
 
3540
    {
 
3541
      if (i != primary_key && !(key_info->flags & HA_NOSAME))
 
3542
        continue;
 
3543
 
 
3544
      if (i == primary_key && !strcmp(key_info->name, primary_key_name))
 
3545
      {
 
3546
        if (store_constraints(thd, table, db_name, table_name, key_info->name,
 
3547
                              strlen(key_info->name),
 
3548
                              STRING_WITH_LEN("PRIMARY KEY")))
 
3549
          DBUG_RETURN(1);
 
3550
      }
 
3551
      else if (key_info->flags & HA_NOSAME)
 
3552
      {
 
3553
        if (store_constraints(thd, table, db_name, table_name, key_info->name,
 
3554
                              strlen(key_info->name),
 
3555
                              STRING_WITH_LEN("UNIQUE")))
 
3556
          DBUG_RETURN(1);
 
3557
      }
 
3558
    }
 
3559
 
 
3560
    show_table->file->get_foreign_key_list(thd, &f_key_list);
 
3561
    FOREIGN_KEY_INFO *f_key_info;
 
3562
    List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
 
3563
    while ((f_key_info=it++))
 
3564
    {
 
3565
      if (store_constraints(thd, table, db_name, table_name, 
 
3566
                            f_key_info->forein_id->str,
 
3567
                            strlen(f_key_info->forein_id->str),
 
3568
                            "FOREIGN KEY", 11))
 
3569
        DBUG_RETURN(1);
 
3570
    }
 
3571
  }
 
3572
  DBUG_RETURN(res);
 
3573
}
 
3574
 
 
3575
 
 
3576
void store_key_column_usage(TABLE *table, LEX_STRING *db_name,
 
3577
                            LEX_STRING *table_name, const char *key_name,
 
3578
                            uint key_len, const char *con_type, uint con_len,
 
3579
                            longlong idx)
 
3580
{
 
3581
  CHARSET_INFO *cs= system_charset_info;
 
3582
  table->field[1]->store(db_name->str, db_name->length, cs);
 
3583
  table->field[2]->store(key_name, key_len, cs);
 
3584
  table->field[4]->store(db_name->str, db_name->length, cs);
 
3585
  table->field[5]->store(table_name->str, table_name->length, cs);
 
3586
  table->field[6]->store(con_type, con_len, cs);
 
3587
  table->field[7]->store((longlong) idx, TRUE);
 
3588
}
 
3589
 
 
3590
 
 
3591
static int get_schema_key_column_usage_record(THD *thd,
 
3592
                                              TABLE_LIST *tables,
 
3593
                                              TABLE *table, bool res,
 
3594
                                              LEX_STRING *db_name,
 
3595
                                              LEX_STRING *table_name)
 
3596
{
 
3597
  DBUG_ENTER("get_schema_key_column_usage_record");
 
3598
  if (res)
 
3599
  {
 
3600
    if (thd->is_error())
 
3601
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
3602
                   thd->main_da.sql_errno(), thd->main_da.message());
 
3603
    thd->clear_error();
 
3604
    DBUG_RETURN(0);
 
3605
  }
 
3606
  else
 
3607
  {
 
3608
    List<FOREIGN_KEY_INFO> f_key_list;
 
3609
    TABLE *show_table= tables->table;
 
3610
    KEY *key_info=show_table->key_info;
 
3611
    uint primary_key= show_table->s->primary_key;
 
3612
    show_table->file->info(HA_STATUS_VARIABLE | 
 
3613
                           HA_STATUS_NO_LOCK |
 
3614
                           HA_STATUS_TIME);
 
3615
    for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
 
3616
    {
 
3617
      if (i != primary_key && !(key_info->flags & HA_NOSAME))
 
3618
        continue;
 
3619
      uint f_idx= 0;
 
3620
      KEY_PART_INFO *key_part= key_info->key_part;
 
3621
      for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
 
3622
      {
 
3623
        if (key_part->field)
 
3624
        {
 
3625
          f_idx++;
 
3626
          restore_record(table, s->default_values);
 
3627
          store_key_column_usage(table, db_name, table_name,
 
3628
                                 key_info->name,
 
3629
                                 strlen(key_info->name), 
 
3630
                                 key_part->field->field_name, 
 
3631
                                 strlen(key_part->field->field_name),
 
3632
                                 (longlong) f_idx);
 
3633
          if (schema_table_store_record(thd, table))
 
3634
            DBUG_RETURN(1);
 
3635
        }
 
3636
      }
 
3637
    }
 
3638
 
 
3639
    show_table->file->get_foreign_key_list(thd, &f_key_list);
 
3640
    FOREIGN_KEY_INFO *f_key_info;
 
3641
    List_iterator_fast<FOREIGN_KEY_INFO> fkey_it(f_key_list);
 
3642
    while ((f_key_info= fkey_it++))
 
3643
    {
 
3644
      LEX_STRING *f_info;
 
3645
      LEX_STRING *r_info;
 
3646
      List_iterator_fast<LEX_STRING> it(f_key_info->foreign_fields),
 
3647
        it1(f_key_info->referenced_fields);
 
3648
      uint f_idx= 0;
 
3649
      while ((f_info= it++))
 
3650
      {
 
3651
        r_info= it1++;
 
3652
        f_idx++;
 
3653
        restore_record(table, s->default_values);
 
3654
        store_key_column_usage(table, db_name, table_name,
 
3655
                               f_key_info->forein_id->str,
 
3656
                               f_key_info->forein_id->length,
 
3657
                               f_info->str, f_info->length,
 
3658
                               (longlong) f_idx);
 
3659
        table->field[8]->store((longlong) f_idx, TRUE);
 
3660
        table->field[8]->set_notnull();
 
3661
        table->field[9]->store(f_key_info->referenced_db->str,
 
3662
                               f_key_info->referenced_db->length,
 
3663
                               system_charset_info);
 
3664
        table->field[9]->set_notnull();
 
3665
        table->field[10]->store(f_key_info->referenced_table->str,
 
3666
                                f_key_info->referenced_table->length, 
 
3667
                                system_charset_info);
 
3668
        table->field[10]->set_notnull();
 
3669
        table->field[11]->store(r_info->str, r_info->length,
 
3670
                                system_charset_info);
 
3671
        table->field[11]->set_notnull();
 
3672
        if (schema_table_store_record(thd, table))
 
3673
          DBUG_RETURN(1);
 
3674
      }
 
3675
    }
 
3676
  }
 
3677
  DBUG_RETURN(res);
 
3678
}
 
3679
 
 
3680
 
 
3681
int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond)
 
3682
{
 
3683
  DBUG_ENTER("fill_open_tables");
 
3684
  const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
 
3685
  TABLE *table= tables->table;
 
3686
  CHARSET_INFO *cs= system_charset_info;
 
3687
  OPEN_TABLE_LIST *open_list;
 
3688
  if (!(open_list=list_open_tables(thd,thd->lex->select_lex.db, wild))
 
3689
            && thd->is_fatal_error)
 
3690
    DBUG_RETURN(1);
 
3691
 
 
3692
  for (; open_list ; open_list=open_list->next)
 
3693
  {
 
3694
    restore_record(table, s->default_values);
 
3695
    table->field[0]->store(open_list->db, strlen(open_list->db), cs);
 
3696
    table->field[1]->store(open_list->table, strlen(open_list->table), cs);
 
3697
    table->field[2]->store((longlong) open_list->in_use, TRUE);
 
3698
    table->field[3]->store((longlong) open_list->locked, TRUE);
 
3699
    if (schema_table_store_record(thd, table))
 
3700
      DBUG_RETURN(1);
 
3701
  }
 
3702
  DBUG_RETURN(0);
 
3703
}
 
3704
 
 
3705
 
 
3706
int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond)
 
3707
{
 
3708
  DBUG_ENTER("fill_variables");
 
3709
  int res= 0;
 
3710
  LEX *lex= thd->lex;
 
3711
  const char *wild= lex->wild ? lex->wild->ptr() : NullS;
 
3712
  enum enum_schema_tables schema_table_idx=
 
3713
    get_schema_table_idx(tables->schema_table);
 
3714
  enum enum_var_type option_type= OPT_SESSION;
 
3715
  bool upper_case_names= (schema_table_idx != SCH_VARIABLES);
 
3716
  bool sorted_vars= (schema_table_idx == SCH_VARIABLES);
 
3717
 
 
3718
  if (lex->option_type == OPT_GLOBAL ||
 
3719
      schema_table_idx == SCH_GLOBAL_VARIABLES)
 
3720
    option_type= OPT_GLOBAL;
 
3721
 
 
3722
  rw_rdlock(&LOCK_system_variables_hash);
 
3723
  res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars),
 
3724
                         option_type, NULL, "", tables->table, upper_case_names);
 
3725
  rw_unlock(&LOCK_system_variables_hash);
 
3726
  DBUG_RETURN(res);
 
3727
}
 
3728
 
 
3729
 
 
3730
int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
 
3731
{
 
3732
  DBUG_ENTER("fill_status");
 
3733
  LEX *lex= thd->lex;
 
3734
  const char *wild= lex->wild ? lex->wild->ptr() : NullS;
 
3735
  int res= 0;
 
3736
  STATUS_VAR *tmp1, tmp;
 
3737
  enum enum_schema_tables schema_table_idx=
 
3738
    get_schema_table_idx(tables->schema_table);
 
3739
  enum enum_var_type option_type;
 
3740
  bool upper_case_names= (schema_table_idx != SCH_STATUS);
 
3741
 
 
3742
  if (schema_table_idx == SCH_STATUS)
 
3743
  {
 
3744
    option_type= lex->option_type;
 
3745
    if (option_type == OPT_GLOBAL)
 
3746
      tmp1= &tmp;
 
3747
    else
 
3748
      tmp1= thd->initial_status_var;
 
3749
  }
 
3750
  else if (schema_table_idx == SCH_GLOBAL_STATUS)
 
3751
  {
 
3752
    option_type= OPT_GLOBAL;
 
3753
    tmp1= &tmp;
 
3754
  }
 
3755
  else
 
3756
  { 
 
3757
    option_type= OPT_SESSION;
 
3758
    tmp1= &thd->status_var;
 
3759
  }
 
3760
 
 
3761
  pthread_mutex_lock(&LOCK_status);
 
3762
  if (option_type == OPT_GLOBAL)
 
3763
    calc_sum_of_all_status(&tmp);
 
3764
  res= show_status_array(thd, wild,
 
3765
                         (SHOW_VAR *)all_status_vars.buffer,
 
3766
                         option_type, tmp1, "", tables->table,
 
3767
                         upper_case_names);
 
3768
  pthread_mutex_unlock(&LOCK_status);
 
3769
  DBUG_RETURN(res);
 
3770
}
 
3771
 
 
3772
 
 
3773
/*
 
3774
  Fill and store records into I_S.referential_constraints table
 
3775
 
 
3776
  SYNOPSIS
 
3777
    get_referential_constraints_record()
 
3778
    thd                 thread handle
 
3779
    tables              table list struct(processed table)
 
3780
    table               I_S table
 
3781
    res                 1 means the error during opening of the processed table
 
3782
                        0 means processed table is opened without error
 
3783
    base_name           db name
 
3784
    file_name           table name
 
3785
 
 
3786
  RETURN
 
3787
    0   ok
 
3788
    #   error
 
3789
*/
 
3790
 
 
3791
static int
 
3792
get_referential_constraints_record(THD *thd, TABLE_LIST *tables,
 
3793
                                   TABLE *table, bool res,
 
3794
                                   LEX_STRING *db_name, LEX_STRING *table_name)
 
3795
{
 
3796
  CHARSET_INFO *cs= system_charset_info;
 
3797
  DBUG_ENTER("get_referential_constraints_record");
 
3798
 
 
3799
  if (res)
 
3800
  {
 
3801
    if (thd->is_error())
 
3802
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
3803
                   thd->main_da.sql_errno(), thd->main_da.message());
 
3804
    thd->clear_error();
 
3805
    DBUG_RETURN(0);
 
3806
  }
 
3807
 
 
3808
  {
 
3809
    List<FOREIGN_KEY_INFO> f_key_list;
 
3810
    TABLE *show_table= tables->table;
 
3811
    show_table->file->info(HA_STATUS_VARIABLE | 
 
3812
                           HA_STATUS_NO_LOCK |
 
3813
                           HA_STATUS_TIME);
 
3814
 
 
3815
    show_table->file->get_foreign_key_list(thd, &f_key_list);
 
3816
    FOREIGN_KEY_INFO *f_key_info;
 
3817
    List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
 
3818
    while ((f_key_info= it++))
 
3819
    {
 
3820
      restore_record(table, s->default_values);
 
3821
      table->field[1]->store(db_name->str, db_name->length, cs);
 
3822
      table->field[9]->store(table_name->str, table_name->length, cs);
 
3823
      table->field[2]->store(f_key_info->forein_id->str,
 
3824
                             f_key_info->forein_id->length, cs);
 
3825
      table->field[4]->store(f_key_info->referenced_db->str, 
 
3826
                             f_key_info->referenced_db->length, cs);
 
3827
      table->field[10]->store(f_key_info->referenced_table->str, 
 
3828
                             f_key_info->referenced_table->length, cs);
 
3829
      if (f_key_info->referenced_key_name)
 
3830
      {
 
3831
        table->field[5]->store(f_key_info->referenced_key_name->str, 
 
3832
                               f_key_info->referenced_key_name->length, cs);
 
3833
        table->field[5]->set_notnull();
 
3834
      }
 
3835
      else
 
3836
        table->field[5]->set_null();
 
3837
      table->field[6]->store(STRING_WITH_LEN("NONE"), cs);
 
3838
      table->field[7]->store(f_key_info->update_method->str, 
 
3839
                             f_key_info->update_method->length, cs);
 
3840
      table->field[8]->store(f_key_info->delete_method->str, 
 
3841
                             f_key_info->delete_method->length, cs);
 
3842
      if (schema_table_store_record(thd, table))
 
3843
        DBUG_RETURN(1);
 
3844
    }
 
3845
  }
 
3846
  DBUG_RETURN(0);
 
3847
}
 
3848
 
 
3849
 
 
3850
struct schema_table_ref 
 
3851
{
 
3852
  const char *table_name;
 
3853
  ST_SCHEMA_TABLE *schema_table;
 
3854
};
 
3855
 
 
3856
 
 
3857
/*
 
3858
  Find schema_tables elment by name
 
3859
 
 
3860
  SYNOPSIS
 
3861
    find_schema_table_in_plugin()
 
3862
    thd                 thread handler
 
3863
    plugin              plugin
 
3864
    table_name          table name
 
3865
 
 
3866
  RETURN
 
3867
    0   table not found
 
3868
    1   found the schema table
 
3869
*/
 
3870
static my_bool find_schema_table_in_plugin(THD *thd, plugin_ref plugin,
 
3871
                                           void* p_table)
 
3872
{
 
3873
  schema_table_ref *p_schema_table= (schema_table_ref *)p_table;
 
3874
  const char* table_name= p_schema_table->table_name;
 
3875
  ST_SCHEMA_TABLE *schema_table= plugin_data(plugin, ST_SCHEMA_TABLE *);
 
3876
  DBUG_ENTER("find_schema_table_in_plugin");
 
3877
 
 
3878
  if (!my_strcasecmp(system_charset_info,
 
3879
                     schema_table->table_name,
 
3880
                     table_name)) {
 
3881
    p_schema_table->schema_table= schema_table;
 
3882
    DBUG_RETURN(1);
 
3883
  }
 
3884
 
 
3885
  DBUG_RETURN(0);
 
3886
}
 
3887
 
 
3888
 
 
3889
/*
 
3890
  Find schema_tables elment by name
 
3891
 
 
3892
  SYNOPSIS
 
3893
    find_schema_table()
 
3894
    thd                 thread handler
 
3895
    table_name          table name
 
3896
 
 
3897
  RETURN
 
3898
    0   table not found
 
3899
    #   pointer to 'schema_tables' element
 
3900
*/
 
3901
 
 
3902
ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name)
 
3903
{
 
3904
  schema_table_ref schema_table_a;
 
3905
  ST_SCHEMA_TABLE *schema_table= schema_tables;
 
3906
  DBUG_ENTER("find_schema_table");
 
3907
 
 
3908
  for (; schema_table->table_name; schema_table++)
 
3909
  {
 
3910
    if (!my_strcasecmp(system_charset_info,
 
3911
                       schema_table->table_name,
 
3912
                       table_name))
 
3913
      DBUG_RETURN(schema_table);
 
3914
  }
 
3915
 
 
3916
  schema_table_a.table_name= table_name;
 
3917
  if (plugin_foreach(thd, find_schema_table_in_plugin, 
 
3918
                     MYSQL_INFORMATION_SCHEMA_PLUGIN, &schema_table_a))
 
3919
    DBUG_RETURN(schema_table_a.schema_table);
 
3920
 
 
3921
  DBUG_RETURN(NULL);
 
3922
}
 
3923
 
 
3924
 
 
3925
ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx)
 
3926
{
 
3927
  return &schema_tables[schema_table_idx];
 
3928
}
 
3929
 
 
3930
 
 
3931
/**
 
3932
  Create information_schema table using schema_table data.
 
3933
 
 
3934
  @note
 
3935
    For MYSQL_TYPE_DECIMAL fields only, the field_length member has encoded
 
3936
    into it two numbers, based on modulus of base-10 numbers.  In the ones
 
3937
    position is the number of decimals.  Tens position is unused.  In the
 
3938
    hundreds and thousands position is a two-digit decimal number representing
 
3939
    length.  Encode this value with  (decimals*100)+length  , where
 
3940
    0<decimals<10 and 0<=length<100 .
 
3941
 
 
3942
  @param
 
3943
    thd                   thread handler
 
3944
 
 
3945
  @param table_list Used to pass I_S table information(fields info, tables
 
3946
  parameters etc) and table name.
 
3947
 
 
3948
  @retval  \#             Pointer to created table
 
3949
  @retval  NULL           Can't create table
 
3950
*/
 
3951
 
 
3952
TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
 
3953
{
 
3954
  int field_count= 0;
 
3955
  Item *item;
 
3956
  TABLE *table;
 
3957
  List<Item> field_list;
 
3958
  ST_SCHEMA_TABLE *schema_table= table_list->schema_table;
 
3959
  ST_FIELD_INFO *fields_info= schema_table->fields_info;
 
3960
  CHARSET_INFO *cs= system_charset_info;
 
3961
  DBUG_ENTER("create_schema_table");
 
3962
 
 
3963
  for (; fields_info->field_name; fields_info++)
 
3964
  {
 
3965
    switch (fields_info->field_type) {
 
3966
    case MYSQL_TYPE_TINY:
 
3967
    case MYSQL_TYPE_LONG:
 
3968
    case MYSQL_TYPE_SHORT:
 
3969
    case MYSQL_TYPE_LONGLONG:
 
3970
    case MYSQL_TYPE_INT24:
 
3971
      if (!(item= new Item_return_int(fields_info->field_name,
 
3972
                                      fields_info->field_length,
 
3973
                                      fields_info->field_type,
 
3974
                                      fields_info->value)))
 
3975
      {
 
3976
        DBUG_RETURN(0);
 
3977
      }
 
3978
      item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED);
 
3979
      break;
 
3980
    case MYSQL_TYPE_DATE:
 
3981
    case MYSQL_TYPE_TIME:
 
3982
    case MYSQL_TYPE_TIMESTAMP:
 
3983
    case MYSQL_TYPE_DATETIME:
 
3984
      if (!(item=new Item_return_date_time(fields_info->field_name,
 
3985
                                           fields_info->field_type)))
 
3986
      {
 
3987
        DBUG_RETURN(0);
 
3988
      }
 
3989
      break;
 
3990
    case MYSQL_TYPE_FLOAT:
 
3991
    case MYSQL_TYPE_DOUBLE:
 
3992
      if ((item= new Item_float(fields_info->field_name, 0.0, NOT_FIXED_DEC, 
 
3993
                           fields_info->field_length)) == NULL)
 
3994
        DBUG_RETURN(NULL);
 
3995
      break;
 
3996
    case MYSQL_TYPE_DECIMAL:
 
3997
    case MYSQL_TYPE_NEWDECIMAL:
 
3998
      if (!(item= new Item_decimal((longlong) fields_info->value, false)))
 
3999
      {
 
4000
        DBUG_RETURN(0);
 
4001
      }
 
4002
      item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED);
 
4003
      item->decimals= fields_info->field_length%10;
 
4004
      item->max_length= (fields_info->field_length/100)%100;
 
4005
      if (item->unsigned_flag == 0)
 
4006
        item->max_length+= 1;
 
4007
      if (item->decimals > 0)
 
4008
        item->max_length+= 1;
 
4009
      item->set_name(fields_info->field_name,
 
4010
                     strlen(fields_info->field_name), cs);
 
4011
      break;
 
4012
    case MYSQL_TYPE_TINY_BLOB:
 
4013
    case MYSQL_TYPE_MEDIUM_BLOB:
 
4014
    case MYSQL_TYPE_LONG_BLOB:
 
4015
    case MYSQL_TYPE_BLOB:
 
4016
      if (!(item= new Item_blob(fields_info->field_name,
 
4017
                                fields_info->field_length)))
 
4018
      {
 
4019
        DBUG_RETURN(0);
 
4020
      }
 
4021
      break;
 
4022
    default:
 
4023
      /* Don't let unimplemented types pass through. Could be a grave error. */
 
4024
      DBUG_ASSERT(fields_info->field_type == MYSQL_TYPE_STRING);
 
4025
 
 
4026
      if (!(item= new Item_empty_string("", fields_info->field_length, cs)))
 
4027
      {
 
4028
        DBUG_RETURN(0);
 
4029
      }
 
4030
      item->set_name(fields_info->field_name,
 
4031
                     strlen(fields_info->field_name), cs);
 
4032
      break;
 
4033
    }
 
4034
    field_list.push_back(item);
 
4035
    item->maybe_null= (fields_info->field_flags & MY_I_S_MAYBE_NULL);
 
4036
    field_count++;
 
4037
  }
 
4038
  TMP_TABLE_PARAM *tmp_table_param =
 
4039
    (TMP_TABLE_PARAM*) (thd->alloc(sizeof(TMP_TABLE_PARAM)));
 
4040
  tmp_table_param->init();
 
4041
  tmp_table_param->table_charset= cs;
 
4042
  tmp_table_param->field_count= field_count;
 
4043
  tmp_table_param->schema_table= 1;
 
4044
  SELECT_LEX *select_lex= thd->lex->current_select;
 
4045
  if (!(table= create_tmp_table(thd, tmp_table_param,
 
4046
                                field_list, (ORDER*) 0, 0, 0, 
 
4047
                                (select_lex->options | thd->options |
 
4048
                                 TMP_TABLE_ALL_COLUMNS),
 
4049
                                HA_POS_ERROR, table_list->alias)))
 
4050
    DBUG_RETURN(0);
 
4051
  my_bitmap_map* bitmaps=
 
4052
    (my_bitmap_map*) thd->alloc(bitmap_buffer_size(field_count));
 
4053
  bitmap_init(&table->def_read_set, (my_bitmap_map*) bitmaps, field_count,
 
4054
              FALSE);
 
4055
  table->read_set= &table->def_read_set;
 
4056
  bitmap_clear_all(table->read_set);
 
4057
  table_list->schema_table_param= tmp_table_param;
 
4058
  DBUG_RETURN(table);
 
4059
}
 
4060
 
 
4061
 
 
4062
/*
 
4063
  For old SHOW compatibility. It is used when
 
4064
  old SHOW doesn't have generated column names
 
4065
  Make list of fields for SHOW
 
4066
 
 
4067
  SYNOPSIS
 
4068
    make_old_format()
 
4069
    thd                 thread handler
 
4070
    schema_table        pointer to 'schema_tables' element
 
4071
 
 
4072
  RETURN
 
4073
   1    error
 
4074
   0    success
 
4075
*/
 
4076
 
 
4077
int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
 
4078
{
 
4079
  ST_FIELD_INFO *field_info= schema_table->fields_info;
 
4080
  Name_resolution_context *context= &thd->lex->select_lex.context;
 
4081
  for (; field_info->field_name; field_info++)
 
4082
  {
 
4083
    if (field_info->old_name)
 
4084
    {
 
4085
      Item_field *field= new Item_field(context,
 
4086
                                        NullS, NullS, field_info->field_name);
 
4087
      if (field)
 
4088
      {
 
4089
        field->set_name(field_info->old_name,
 
4090
                        strlen(field_info->old_name),
 
4091
                        system_charset_info);
 
4092
        if (add_item_to_list(thd, field))
 
4093
          return 1;
 
4094
      }
 
4095
    }
 
4096
  }
 
4097
  return 0;
 
4098
}
 
4099
 
 
4100
 
 
4101
int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
 
4102
{
 
4103
  char tmp[128];
 
4104
  LEX *lex= thd->lex;
 
4105
  SELECT_LEX *sel= lex->current_select;
 
4106
  Name_resolution_context *context= &sel->context;
 
4107
 
 
4108
  if (!sel->item_list.elements)
 
4109
  {
 
4110
    ST_FIELD_INFO *field_info= &schema_table->fields_info[1];
 
4111
    String buffer(tmp,sizeof(tmp), system_charset_info);
 
4112
    Item_field *field= new Item_field(context,
 
4113
                                      NullS, NullS, field_info->field_name);
 
4114
    if (!field || add_item_to_list(thd, field))
 
4115
      return 1;
 
4116
    buffer.length(0);
 
4117
    buffer.append(field_info->old_name);
 
4118
    if (lex->wild && lex->wild->ptr())
 
4119
    {
 
4120
      buffer.append(STRING_WITH_LEN(" ("));
 
4121
      buffer.append(lex->wild->ptr());
 
4122
      buffer.append(')');
 
4123
    }
 
4124
    field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
 
4125
  }
 
4126
  return 0;
 
4127
}
 
4128
 
 
4129
 
 
4130
int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
 
4131
{
 
4132
  char tmp[128];
 
4133
  String buffer(tmp,sizeof(tmp), thd->charset());
 
4134
  LEX *lex= thd->lex;
 
4135
  Name_resolution_context *context= &lex->select_lex.context;
 
4136
 
 
4137
  ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
 
4138
  buffer.length(0);
 
4139
  buffer.append(field_info->old_name);
 
4140
  buffer.append(lex->select_lex.db);
 
4141
  if (lex->wild && lex->wild->ptr())
 
4142
  {
 
4143
    buffer.append(STRING_WITH_LEN(" ("));
 
4144
    buffer.append(lex->wild->ptr());
 
4145
    buffer.append(')');
 
4146
  }
 
4147
  Item_field *field= new Item_field(context,
 
4148
                                    NullS, NullS, field_info->field_name);
 
4149
  if (add_item_to_list(thd, field))
 
4150
    return 1;
 
4151
  field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
 
4152
  if (thd->lex->verbose)
 
4153
  {
 
4154
    field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
 
4155
    field_info= &schema_table->fields_info[3];
 
4156
    field= new Item_field(context, NullS, NullS, field_info->field_name);
 
4157
    if (add_item_to_list(thd, field))
 
4158
      return 1;
 
4159
    field->set_name(field_info->old_name, strlen(field_info->old_name),
 
4160
                    system_charset_info);
 
4161
  }
 
4162
  return 0;
 
4163
}
 
4164
 
 
4165
 
 
4166
int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
 
4167
{
 
4168
  int fields_arr[]= {3, 14, 13, 6, 15, 5, 16, 17, 18, -1};
 
4169
  int *field_num= fields_arr;
 
4170
  ST_FIELD_INFO *field_info;
 
4171
  Name_resolution_context *context= &thd->lex->select_lex.context;
 
4172
 
 
4173
  for (; *field_num >= 0; field_num++)
 
4174
  {
 
4175
    field_info= &schema_table->fields_info[*field_num];
 
4176
    if (!thd->lex->verbose && (*field_num == 13 ||
 
4177
                               *field_num == 17 ||
 
4178
                               *field_num == 18))
 
4179
      continue;
 
4180
    Item_field *field= new Item_field(context,
 
4181
                                      NullS, NullS, field_info->field_name);
 
4182
    if (field)
 
4183
    {
 
4184
      field->set_name(field_info->old_name,
 
4185
                      strlen(field_info->old_name),
 
4186
                      system_charset_info);
 
4187
      if (add_item_to_list(thd, field))
 
4188
        return 1;
 
4189
    }
 
4190
  }
 
4191
  return 0;
 
4192
}
 
4193
 
 
4194
 
 
4195
int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
 
4196
{
 
4197
  int fields_arr[]= {0, 2, 1, 3, -1};
 
4198
  int *field_num= fields_arr;
 
4199
  ST_FIELD_INFO *field_info;
 
4200
  Name_resolution_context *context= &thd->lex->select_lex.context;
 
4201
 
 
4202
  for (; *field_num >= 0; field_num++)
 
4203
  {
 
4204
    field_info= &schema_table->fields_info[*field_num];
 
4205
    Item_field *field= new Item_field(context,
 
4206
                                      NullS, NullS, field_info->field_name);
 
4207
    if (field)
 
4208
    {
 
4209
      field->set_name(field_info->old_name,
 
4210
                      strlen(field_info->old_name),
 
4211
                      system_charset_info);
 
4212
      if (add_item_to_list(thd, field))
 
4213
        return 1;
 
4214
    }
 
4215
  }
 
4216
  return 0;
 
4217
}
 
4218
 
 
4219
 
 
4220
/*
 
4221
  Create information_schema table
 
4222
 
 
4223
  SYNOPSIS
 
4224
  mysql_schema_table()
 
4225
    thd                thread handler
 
4226
    lex                pointer to LEX
 
4227
    table_list         pointer to table_list
 
4228
 
 
4229
  RETURN
 
4230
    0   success
 
4231
    1   error
 
4232
*/
 
4233
 
 
4234
int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
 
4235
{
 
4236
  TABLE *table;
 
4237
  DBUG_ENTER("mysql_schema_table");
 
4238
  if (!(table= table_list->schema_table->create_table(thd, table_list)))
 
4239
    DBUG_RETURN(1);
 
4240
  table->s->tmp_table= SYSTEM_TMP_TABLE;
 
4241
  /*
 
4242
    This test is necessary to make
 
4243
    case insensitive file systems +
 
4244
    upper case table names(information schema tables) +
 
4245
    views
 
4246
    working correctly
 
4247
  */
 
4248
  if (table_list->schema_table_name)
 
4249
    table->alias_name_used= my_strcasecmp(table_alias_charset,
 
4250
                                          table_list->schema_table_name,
 
4251
                                          table_list->alias);
 
4252
  table_list->table_name= table->s->table_name.str;
 
4253
  table_list->table_name_length= table->s->table_name.length;
 
4254
  table_list->table= table;
 
4255
  table->next= thd->derived_tables;
 
4256
  thd->derived_tables= table;
 
4257
  table_list->select_lex->options |= OPTION_SCHEMA_TABLE;
 
4258
 
 
4259
  if (table_list->schema_table_reformed) // show command
 
4260
  {
 
4261
    SELECT_LEX *sel= lex->current_select;
 
4262
    Item *item;
 
4263
    Field_translator *transl, *org_transl;
 
4264
 
 
4265
    if (table_list->field_translation)
 
4266
    {
 
4267
      Field_translator *end= table_list->field_translation_end;
 
4268
      for (transl= table_list->field_translation; transl < end; transl++)
 
4269
      {
 
4270
        if (!transl->item->fixed &&
 
4271
            transl->item->fix_fields(thd, &transl->item))
 
4272
          DBUG_RETURN(1);
 
4273
      }
 
4274
      DBUG_RETURN(0);
 
4275
    }
 
4276
    List_iterator_fast<Item> it(sel->item_list);
 
4277
    if (!(transl=
 
4278
          (Field_translator*)(thd->stmt_arena->
 
4279
                              alloc(sel->item_list.elements *
 
4280
                                    sizeof(Field_translator)))))
 
4281
    {
 
4282
      DBUG_RETURN(1);
 
4283
    }
 
4284
    for (org_transl= transl; (item= it++); transl++)
 
4285
    {
 
4286
      transl->item= item;
 
4287
      transl->name= item->name;
 
4288
      if (!item->fixed && item->fix_fields(thd, &transl->item))
 
4289
      {
 
4290
        DBUG_RETURN(1);
 
4291
      }
 
4292
    }
 
4293
    table_list->field_translation= org_transl;
 
4294
    table_list->field_translation_end= transl;
 
4295
  }
 
4296
 
 
4297
  DBUG_RETURN(0);
 
4298
}
 
4299
 
 
4300
 
 
4301
/*
 
4302
  Generate select from information_schema table
 
4303
 
 
4304
  SYNOPSIS
 
4305
    make_schema_select()
 
4306
    thd                  thread handler
 
4307
    sel                  pointer to SELECT_LEX
 
4308
    schema_table_idx     index of 'schema_tables' element
 
4309
 
 
4310
  RETURN
 
4311
    0   success
 
4312
    1   error
 
4313
*/
 
4314
 
 
4315
int make_schema_select(THD *thd, SELECT_LEX *sel,
 
4316
                       enum enum_schema_tables schema_table_idx)
 
4317
{
 
4318
  ST_SCHEMA_TABLE *schema_table= get_schema_table(schema_table_idx);
 
4319
  LEX_STRING db, table;
 
4320
  DBUG_ENTER("make_schema_select");
 
4321
  DBUG_PRINT("enter", ("mysql_schema_select: %s", schema_table->table_name));
 
4322
  /*
 
4323
     We have to make non const db_name & table_name
 
4324
     because of lower_case_table_names
 
4325
  */
 
4326
  thd->make_lex_string(&db, INFORMATION_SCHEMA_NAME.str,
 
4327
                       INFORMATION_SCHEMA_NAME.length, 0);
 
4328
  thd->make_lex_string(&table, schema_table->table_name,
 
4329
                       strlen(schema_table->table_name), 0);
 
4330
  if (schema_table->old_format(thd, schema_table) ||   /* Handle old syntax */
 
4331
      !sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0),
 
4332
                              0, 0, TL_READ))
 
4333
  {
 
4334
    DBUG_RETURN(1);
 
4335
  }
 
4336
  DBUG_RETURN(0);
 
4337
}
 
4338
 
 
4339
 
 
4340
/*
 
4341
  Fill temporary schema tables before SELECT
 
4342
 
 
4343
  SYNOPSIS
 
4344
    get_schema_tables_result()
 
4345
    join  join which use schema tables
 
4346
    executed_place place where I_S table processed
 
4347
 
 
4348
  RETURN
 
4349
    FALSE success
 
4350
    TRUE  error
 
4351
*/
 
4352
 
 
4353
bool get_schema_tables_result(JOIN *join,
 
4354
                              enum enum_schema_table_state executed_place)
 
4355
{
 
4356
  JOIN_TAB *tmp_join_tab= join->join_tab+join->tables;
 
4357
  THD *thd= join->thd;
 
4358
  LEX *lex= thd->lex;
 
4359
  bool result= 0;
 
4360
  DBUG_ENTER("get_schema_tables_result");
 
4361
 
 
4362
  thd->no_warnings_for_error= 1;
 
4363
  for (JOIN_TAB *tab= join->join_tab; tab < tmp_join_tab; tab++)
 
4364
  {
 
4365
    if (!tab->table || !tab->table->pos_in_table_list)
 
4366
      break;
 
4367
 
 
4368
    TABLE_LIST *table_list= tab->table->pos_in_table_list;
 
4369
    if (table_list->schema_table)
 
4370
    {
 
4371
      bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
 
4372
                          lex->current_select->master_unit()->item);
 
4373
 
 
4374
 
 
4375
      /* skip I_S optimizations specific to get_all_tables */
 
4376
      if (thd->lex->describe &&
 
4377
          (table_list->schema_table->fill_table != get_all_tables))
 
4378
        continue;
 
4379
 
 
4380
      /*
 
4381
        If schema table is already processed and
 
4382
        the statement is not a subselect then
 
4383
        we don't need to fill this table again.
 
4384
        If schema table is already processed and
 
4385
        schema_table_state != executed_place then
 
4386
        table is already processed and
 
4387
        we should skip second data processing.
 
4388
      */
 
4389
      if (table_list->schema_table_state &&
 
4390
          (!is_subselect || table_list->schema_table_state != executed_place))
 
4391
        continue;
 
4392
 
 
4393
      /*
 
4394
        if table is used in a subselect and
 
4395
        table has been processed earlier with the same
 
4396
        'executed_place' value then we should refresh the table.
 
4397
      */
 
4398
      if (table_list->schema_table_state && is_subselect)
 
4399
      {
 
4400
        table_list->table->file->extra(HA_EXTRA_NO_CACHE);
 
4401
        table_list->table->file->extra(HA_EXTRA_RESET_STATE);
 
4402
        table_list->table->file->ha_delete_all_rows();
 
4403
        free_io_cache(table_list->table);
 
4404
        filesort_free_buffers(table_list->table,1);
 
4405
        table_list->table->null_row= 0;
 
4406
      }
 
4407
      else
 
4408
        table_list->table->file->stats.records= 0;
 
4409
 
 
4410
      if (table_list->schema_table->fill_table(thd, table_list,
 
4411
                                               tab->select_cond))
 
4412
      {
 
4413
        result= 1;
 
4414
        join->error= 1;
 
4415
        tab->read_record.file= table_list->table->file;
 
4416
        table_list->schema_table_state= executed_place;
 
4417
        break;
 
4418
      }
 
4419
      tab->read_record.file= table_list->table->file;
 
4420
      table_list->schema_table_state= executed_place;
 
4421
    }
 
4422
  }
 
4423
  thd->no_warnings_for_error= 0;
 
4424
  DBUG_RETURN(result);
 
4425
}
 
4426
 
 
4427
ST_FIELD_INFO schema_fields_info[]=
 
4428
{
 
4429
  {"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
4430
  {"SCHEMA_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Database",
 
4431
   SKIP_OPEN_TABLE},
 
4432
  {"DEFAULT_CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0,
 
4433
   SKIP_OPEN_TABLE},
 
4434
  {"DEFAULT_COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4435
  {"SQL_PATH", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
4436
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4437
};
 
4438
 
 
4439
 
 
4440
ST_FIELD_INFO tables_fields_info[]=
 
4441
{
 
4442
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
4443
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4444
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
 
4445
   SKIP_OPEN_TABLE},
 
4446
  {"TABLE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
 
4447
  {"ENGINE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Engine", OPEN_FRM_ONLY},
 
4448
  {"VERSION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
 
4449
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Version", OPEN_FRM_ONLY},
 
4450
  {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format", OPEN_FULL_TABLE},
 
4451
  {"TABLE_ROWS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
 
4452
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Rows", OPEN_FULL_TABLE},
 
4453
  {"AVG_ROW_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 
 
4454
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Avg_row_length", OPEN_FULL_TABLE},
 
4455
  {"DATA_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 
 
4456
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_length", OPEN_FULL_TABLE},
 
4457
  {"MAX_DATA_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
 
4458
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Max_data_length", OPEN_FULL_TABLE},
 
4459
  {"INDEX_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 
 
4460
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Index_length", OPEN_FULL_TABLE},
 
4461
  {"DATA_FREE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
 
4462
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_free", OPEN_FULL_TABLE},
 
4463
  {"AUTO_INCREMENT", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG, 0, 
 
4464
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Auto_increment", OPEN_FULL_TABLE},
 
4465
  {"CREATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Create_time", OPEN_FULL_TABLE},
 
4466
  {"UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Update_time", OPEN_FULL_TABLE},
 
4467
  {"CHECK_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Check_time", OPEN_FULL_TABLE},
 
4468
  {"TABLE_COLLATION", 64, MYSQL_TYPE_STRING, 0, 1, "Collation", OPEN_FRM_ONLY},
 
4469
  {"CHECKSUM", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
 
4470
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Checksum", OPEN_FULL_TABLE},
 
4471
  {"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, "Create_options",
 
4472
   OPEN_FRM_ONLY},
 
4473
  {"TABLE_COMMENT", TABLE_COMMENT_MAXLEN, MYSQL_TYPE_STRING, 0, 0, "Comment", OPEN_FRM_ONLY},
 
4474
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4475
};
 
4476
 
 
4477
 
 
4478
ST_FIELD_INFO columns_fields_info[]=
 
4479
{
 
4480
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
 
4481
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
 
4482
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
 
4483
  {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Field",
 
4484
   OPEN_FRM_ONLY},
 
4485
  {"ORDINAL_POSITION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
 
4486
   MY_I_S_UNSIGNED, 0, OPEN_FRM_ONLY},
 
4487
  {"COLUMN_DEFAULT", MAX_FIELD_VARCHARLENGTH, MYSQL_TYPE_STRING, 0,
 
4488
   1, "Default", OPEN_FRM_ONLY},
 
4489
  {"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null", OPEN_FRM_ONLY},
 
4490
  {"DATA_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
 
4491
  {"CHARACTER_MAXIMUM_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG,
 
4492
   0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
 
4493
  {"CHARACTER_OCTET_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG,
 
4494
   0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
 
4495
  {"NUMERIC_PRECISION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG,
 
4496
   0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
 
4497
  {"NUMERIC_SCALE", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG,
 
4498
   0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
 
4499
  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
 
4500
  {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 1, "Collation", OPEN_FRM_ONLY},
 
4501
  {"COLUMN_TYPE", 65535, MYSQL_TYPE_STRING, 0, 0, "Type", OPEN_FRM_ONLY},
 
4502
  {"COLUMN_KEY", 3, MYSQL_TYPE_STRING, 0, 0, "Key", OPEN_FRM_ONLY},
 
4503
  {"EXTRA", 27, MYSQL_TYPE_STRING, 0, 0, "Extra", OPEN_FRM_ONLY},
 
4504
  {"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, "Privileges", OPEN_FRM_ONLY},
 
4505
  {"COLUMN_COMMENT", COLUMN_COMMENT_MAXLEN, MYSQL_TYPE_STRING, 0, 0, "Comment", OPEN_FRM_ONLY},
 
4506
  {"STORAGE", 8, MYSQL_TYPE_STRING, 0, 0, "Storage", OPEN_FRM_ONLY},
 
4507
  {"FORMAT", 8, MYSQL_TYPE_STRING, 0, 0, "Format", OPEN_FRM_ONLY},
 
4508
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4509
};
 
4510
 
 
4511
 
 
4512
ST_FIELD_INFO charsets_fields_info[]=
 
4513
{
 
4514
  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Charset",
 
4515
   SKIP_OPEN_TABLE},
 
4516
  {"DEFAULT_COLLATE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Default collation",
 
4517
   SKIP_OPEN_TABLE},
 
4518
  {"DESCRIPTION", 60, MYSQL_TYPE_STRING, 0, 0, "Description",
 
4519
   SKIP_OPEN_TABLE},
 
4520
  {"MAXLEN", 3, MYSQL_TYPE_LONGLONG, 0, 0, "Maxlen", SKIP_OPEN_TABLE},
 
4521
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4522
};
 
4523
 
 
4524
 
 
4525
ST_FIELD_INFO collation_fields_info[]=
 
4526
{
 
4527
  {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Collation", SKIP_OPEN_TABLE},
 
4528
  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Charset",
 
4529
   SKIP_OPEN_TABLE},
 
4530
  {"ID", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Id",
 
4531
   SKIP_OPEN_TABLE},
 
4532
  {"IS_DEFAULT", 3, MYSQL_TYPE_STRING, 0, 0, "Default", SKIP_OPEN_TABLE},
 
4533
  {"IS_COMPILED", 3, MYSQL_TYPE_STRING, 0, 0, "Compiled", SKIP_OPEN_TABLE},
 
4534
  {"SORTLEN", 3, MYSQL_TYPE_LONGLONG, 0, 0, "Sortlen", SKIP_OPEN_TABLE},
 
4535
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4536
};
 
4537
 
 
4538
 
 
4539
ST_FIELD_INFO events_fields_info[]=
 
4540
{
 
4541
  {"EVENT_CATALOG", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
4542
  {"EVENT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Db",
 
4543
   SKIP_OPEN_TABLE},
 
4544
  {"EVENT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
 
4545
   SKIP_OPEN_TABLE},
 
4546
  {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", SKIP_OPEN_TABLE},
 
4547
  {"TIME_ZONE", 64, MYSQL_TYPE_STRING, 0, 0, "Time zone", SKIP_OPEN_TABLE},
 
4548
  {"EVENT_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4549
  {"EVENT_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4550
  {"EVENT_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE},
 
4551
  {"EXECUTE_AT", 0, MYSQL_TYPE_DATETIME, 0, 1, "Execute at", SKIP_OPEN_TABLE},
 
4552
  {"INTERVAL_VALUE", 256, MYSQL_TYPE_STRING, 0, 1, "Interval value",
 
4553
   SKIP_OPEN_TABLE},
 
4554
  {"INTERVAL_FIELD", 18, MYSQL_TYPE_STRING, 0, 1, "Interval field",
 
4555
   SKIP_OPEN_TABLE},
 
4556
  {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4557
  {"STARTS", 0, MYSQL_TYPE_DATETIME, 0, 1, "Starts", SKIP_OPEN_TABLE},
 
4558
  {"ENDS", 0, MYSQL_TYPE_DATETIME, 0, 1, "Ends", SKIP_OPEN_TABLE},
 
4559
  {"STATUS", 18, MYSQL_TYPE_STRING, 0, 0, "Status", SKIP_OPEN_TABLE},
 
4560
  {"ON_COMPLETION", 12, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4561
  {"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 0, 0, SKIP_OPEN_TABLE},
 
4562
  {"LAST_ALTERED", 0, MYSQL_TYPE_DATETIME, 0, 0, 0, SKIP_OPEN_TABLE},
 
4563
  {"LAST_EXECUTED", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE},
 
4564
  {"EVENT_COMMENT", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4565
  {"ORIGINATOR", 10, MYSQL_TYPE_LONGLONG, 0, 0, "Originator", SKIP_OPEN_TABLE},
 
4566
  {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
 
4567
   "character_set_client", SKIP_OPEN_TABLE},
 
4568
  {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
 
4569
   "collation_connection", SKIP_OPEN_TABLE},
 
4570
  {"DATABASE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
 
4571
   "Database Collation", SKIP_OPEN_TABLE},
 
4572
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4573
};
 
4574
 
 
4575
 
 
4576
 
 
4577
ST_FIELD_INFO coll_charset_app_fields_info[]=
 
4578
{
 
4579
  {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4580
  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4581
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4582
};
 
4583
 
 
4584
 
 
4585
ST_FIELD_INFO stat_fields_info[]=
 
4586
{
 
4587
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
 
4588
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
 
4589
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table", OPEN_FRM_ONLY},
 
4590
  {"NON_UNIQUE", 1, MYSQL_TYPE_LONGLONG, 0, 0, "Non_unique", OPEN_FRM_ONLY},
 
4591
  {"INDEX_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
 
4592
  {"INDEX_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Key_name",
 
4593
   OPEN_FRM_ONLY},
 
4594
  {"SEQ_IN_INDEX", 2, MYSQL_TYPE_LONGLONG, 0, 0, "Seq_in_index", OPEN_FRM_ONLY},
 
4595
  {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Column_name",
 
4596
   OPEN_FRM_ONLY},
 
4597
  {"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, "Collation", OPEN_FRM_ONLY},
 
4598
  {"CARDINALITY", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 1,
 
4599
   "Cardinality", OPEN_FULL_TABLE},
 
4600
  {"SUB_PART", 3, MYSQL_TYPE_LONGLONG, 0, 1, "Sub_part", OPEN_FRM_ONLY},
 
4601
  {"PACKED", 10, MYSQL_TYPE_STRING, 0, 1, "Packed", OPEN_FRM_ONLY},
 
4602
  {"NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null", OPEN_FRM_ONLY},
 
4603
  {"INDEX_TYPE", 16, MYSQL_TYPE_STRING, 0, 0, "Index_type", OPEN_FULL_TABLE},
 
4604
  {"COMMENT", 16, MYSQL_TYPE_STRING, 0, 1, "Comment", OPEN_FRM_ONLY},
 
4605
  {"INDEX_COMMENT", INDEX_COMMENT_MAXLEN, MYSQL_TYPE_STRING, 0, 0, "Index_Comment", OPEN_FRM_ONLY},
 
4606
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4607
};
 
4608
 
 
4609
 
 
4610
ST_FIELD_INFO user_privileges_fields_info[]=
 
4611
{
 
4612
  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4613
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
4614
  {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4615
  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4616
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4617
};
 
4618
 
 
4619
 
 
4620
ST_FIELD_INFO schema_privileges_fields_info[]=
 
4621
{
 
4622
  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4623
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
4624
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4625
  {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4626
  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4627
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4628
};
 
4629
 
 
4630
 
 
4631
ST_FIELD_INFO table_privileges_fields_info[]=
 
4632
{
 
4633
  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4634
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
4635
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4636
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4637
  {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4638
  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4639
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4640
};
 
4641
 
 
4642
 
 
4643
ST_FIELD_INFO column_privileges_fields_info[]=
 
4644
{
 
4645
  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4646
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
4647
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4648
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4649
  {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4650
  {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4651
  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4652
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4653
};
 
4654
 
 
4655
 
 
4656
ST_FIELD_INFO table_constraints_fields_info[]=
 
4657
{
 
4658
  {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
4659
  {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
4660
   OPEN_FULL_TABLE},
 
4661
  {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
4662
   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
  {"CONSTRAINT_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
4666
   OPEN_FULL_TABLE},
 
4667
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4668
};
 
4669
 
 
4670
 
 
4671
ST_FIELD_INFO key_column_usage_fields_info[]=
 
4672
{
 
4673
  {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
4674
  {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
4675
   OPEN_FULL_TABLE},
 
4676
  {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
4677
   OPEN_FULL_TABLE},
 
4678
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
4679
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
4680
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
4681
  {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
4682
  {"ORDINAL_POSITION", 10 ,MYSQL_TYPE_LONGLONG, 0, 0, 0, OPEN_FULL_TABLE},
 
4683
  {"POSITION_IN_UNIQUE_CONSTRAINT", 10 ,MYSQL_TYPE_LONGLONG, 0, 1, 0,
 
4684
   OPEN_FULL_TABLE},
 
4685
  {"REFERENCED_TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
4686
   OPEN_FULL_TABLE},
 
4687
  {"REFERENCED_TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
4688
   OPEN_FULL_TABLE},
 
4689
  {"REFERENCED_COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
4690
   OPEN_FULL_TABLE},
 
4691
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4692
};
 
4693
 
 
4694
 
 
4695
ST_FIELD_INFO table_names_fields_info[]=
 
4696
{
 
4697
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
4698
  {"TABLE_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4699
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Tables_in_",
 
4700
   SKIP_OPEN_TABLE},
 
4701
  {"TABLE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_type",
 
4702
   OPEN_FRM_ONLY},
 
4703
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4704
};
 
4705
 
 
4706
 
 
4707
ST_FIELD_INFO open_tables_fields_info[]=
 
4708
{
 
4709
  {"Database", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Database",
 
4710
   SKIP_OPEN_TABLE},
 
4711
  {"Table",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table", SKIP_OPEN_TABLE},
 
4712
  {"In_use", 1, MYSQL_TYPE_LONGLONG, 0, 0, "In_use", SKIP_OPEN_TABLE},
 
4713
  {"Name_locked", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Name_locked", SKIP_OPEN_TABLE},
 
4714
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4715
};
 
4716
 
 
4717
 
 
4718
ST_FIELD_INFO variables_fields_info[]=
 
4719
{
 
4720
  {"VARIABLE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Variable_name",
 
4721
   SKIP_OPEN_TABLE},
 
4722
  {"VARIABLE_VALUE", 16300, MYSQL_TYPE_STRING, 0, 1, "Value", SKIP_OPEN_TABLE},
 
4723
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4724
};
 
4725
 
 
4726
 
 
4727
ST_FIELD_INFO processlist_fields_info[]=
 
4728
{
 
4729
  {"ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Id", SKIP_OPEN_TABLE},
 
4730
  {"USER", 16, MYSQL_TYPE_STRING, 0, 0, "User", SKIP_OPEN_TABLE},
 
4731
  {"HOST", LIST_PROCESS_HOST_LEN,  MYSQL_TYPE_STRING, 0, 0, "Host",
 
4732
   SKIP_OPEN_TABLE},
 
4733
  {"DB", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Db", SKIP_OPEN_TABLE},
 
4734
  {"COMMAND", 16, MYSQL_TYPE_STRING, 0, 0, "Command", SKIP_OPEN_TABLE},
 
4735
  {"TIME", 7, MYSQL_TYPE_LONGLONG, 0, 0, "Time", SKIP_OPEN_TABLE},
 
4736
  {"STATE", 64, MYSQL_TYPE_STRING, 0, 1, "State", SKIP_OPEN_TABLE},
 
4737
  {"INFO", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info",
 
4738
   SKIP_OPEN_TABLE},
 
4739
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4740
};
 
4741
 
 
4742
 
 
4743
ST_FIELD_INFO plugin_fields_info[]=
 
4744
{
 
4745
  {"PLUGIN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
 
4746
   SKIP_OPEN_TABLE},
 
4747
  {"PLUGIN_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4748
  {"PLUGIN_STATUS", 10, MYSQL_TYPE_STRING, 0, 0, "Status", SKIP_OPEN_TABLE},
 
4749
  {"PLUGIN_TYPE", 80, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE},
 
4750
  {"PLUGIN_TYPE_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
4751
  {"PLUGIN_LIBRARY", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Library",
 
4752
   SKIP_OPEN_TABLE},
 
4753
  {"PLUGIN_LIBRARY_VERSION", 20, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
4754
  {"PLUGIN_AUTHOR", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
4755
  {"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
4756
  {"PLUGIN_LICENSE", 80, MYSQL_TYPE_STRING, 0, 1, "License", SKIP_OPEN_TABLE},
 
4757
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4758
};
 
4759
 
 
4760
ST_FIELD_INFO referential_constraints_fields_info[]=
 
4761
{
 
4762
  {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
4763
  {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
4764
   OPEN_FULL_TABLE},
 
4765
  {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
4766
   OPEN_FULL_TABLE},
 
4767
  {"UNIQUE_CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
4768
   OPEN_FULL_TABLE},
 
4769
  {"UNIQUE_CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
4770
   OPEN_FULL_TABLE},
 
4771
  {"UNIQUE_CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0,
 
4772
   MY_I_S_MAYBE_NULL, 0, OPEN_FULL_TABLE},
 
4773
  {"MATCH_OPTION", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
4774
  {"UPDATE_RULE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
4775
  {"DELETE_RULE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
4776
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
4777
  {"REFERENCED_TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
4778
   OPEN_FULL_TABLE},
 
4779
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
4780
};
 
4781
 
 
4782
 
 
4783
ST_FIELD_INFO parameters_fields_info[]=
 
4784
{
 
4785
  {"SPECIFIC_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
4786
  {"SPECIFIC_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
4787
  {"SPECIFIC_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
4788
  {"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0, OPEN_FULL_TABLE},
 
4789
  {"PARAMETER_MODE", 5, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
4790
  {"PARAMETER_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
4791
  {"DATA_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
4792
  {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE},
 
4793
  {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE},
 
4794
  {"NUMERIC_PRECISION", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE},
 
4795
  {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE},
 
4796
  {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
4797
  {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
4798
  {"DTD_IDENTIFIER", 65535, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
4799
  {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
4800
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}
 
4801
};
 
4802
 
 
4803
 
 
4804
/*
 
4805
  Description of ST_FIELD_INFO in table.h
 
4806
 
 
4807
  Make sure that the order of schema_tables and enum_schema_tables are the same.
 
4808
 
 
4809
*/
 
4810
 
 
4811
ST_SCHEMA_TABLE schema_tables[]=
 
4812
{
 
4813
  {"CHARACTER_SETS", charsets_fields_info, create_schema_table, 
 
4814
   fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0, 0},
 
4815
  {"COLLATIONS", collation_fields_info, create_schema_table, 
 
4816
   fill_schema_collation, make_old_format, 0, -1, -1, 0, 0},
 
4817
  {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info,
 
4818
   create_schema_table, fill_schema_coll_charset_app, 0, 0, -1, -1, 0, 0},
 
4819
  {"COLUMNS", columns_fields_info, create_schema_table, 
 
4820
   get_all_tables, make_columns_old_format, get_schema_column_record, 1, 2, 0,
 
4821
   OPTIMIZE_I_S_TABLE|OPEN_VIEW_FULL},
 
4822
  {"GLOBAL_STATUS", variables_fields_info, create_schema_table,
 
4823
   fill_status, make_old_format, 0, -1, -1, 0, 0},
 
4824
  {"GLOBAL_VARIABLES", variables_fields_info, create_schema_table,
 
4825
   fill_variables, make_old_format, 0, -1, -1, 0, 0},
 
4826
  {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
 
4827
   get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0,
 
4828
   OPEN_TABLE_ONLY},
 
4829
  {"OPEN_TABLES", open_tables_fields_info, create_schema_table,
 
4830
   fill_open_tables, make_old_format, 0, -1, -1, 1, 0},
 
4831
  {"PLUGINS", plugin_fields_info, create_schema_table,
 
4832
   fill_plugins, make_old_format, 0, -1, -1, 0, 0},
 
4833
  {"PROCESSLIST", processlist_fields_info, create_schema_table,
 
4834
   fill_schema_processlist, make_old_format, 0, -1, -1, 0, 0},
 
4835
  {"REFERENTIAL_CONSTRAINTS", referential_constraints_fields_info,
 
4836
   create_schema_table, get_all_tables, 0, get_referential_constraints_record,
 
4837
   1, 9, 0, OPEN_TABLE_ONLY},
 
4838
  {"SCHEMATA", schema_fields_info, create_schema_table,
 
4839
   fill_schema_schemata, make_schemata_old_format, 0, 1, -1, 0, 0},
 
4840
  {"SESSION_STATUS", variables_fields_info, create_schema_table,
 
4841
   fill_status, make_old_format, 0, -1, -1, 0, 0},
 
4842
  {"SESSION_VARIABLES", variables_fields_info, create_schema_table,
 
4843
   fill_variables, make_old_format, 0, -1, -1, 0, 0},
 
4844
  {"STATISTICS", stat_fields_info, create_schema_table, 
 
4845
   get_all_tables, make_old_format, get_schema_stat_record, 1, 2, 0,
 
4846
   OPEN_TABLE_ONLY|OPTIMIZE_I_S_TABLE},
 
4847
  {"STATUS", variables_fields_info, create_schema_table, fill_status, 
 
4848
   make_old_format, 0, -1, -1, 1, 0},
 
4849
  {"TABLES", tables_fields_info, create_schema_table, 
 
4850
   get_all_tables, make_old_format, get_schema_tables_record, 1, 2, 0,
 
4851
   OPTIMIZE_I_S_TABLE},
 
4852
  {"TABLE_CONSTRAINTS", table_constraints_fields_info, create_schema_table,
 
4853
   get_all_tables, 0, get_schema_constraints_record, 3, 4, 0, OPEN_TABLE_ONLY},
 
4854
  {"TABLE_NAMES", table_names_fields_info, create_schema_table,
 
4855
   get_all_tables, make_table_names_old_format, 0, 1, 2, 1, 0},
 
4856
  {"VARIABLES", variables_fields_info, create_schema_table, fill_variables,
 
4857
   make_old_format, 0, -1, -1, 1, 0},
 
4858
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 
4859
};
 
4860
 
 
4861
 
 
4862
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
4863
template class List_iterator_fast<char>;
 
4864
template class List<char>;
 
4865
#endif
 
4866
 
 
4867
int initialize_schema_table(st_plugin_int *plugin)
 
4868
{
 
4869
  ST_SCHEMA_TABLE *schema_table;
 
4870
  DBUG_ENTER("initialize_schema_table");
 
4871
 
 
4872
  if (!(schema_table= (ST_SCHEMA_TABLE *)my_malloc(sizeof(ST_SCHEMA_TABLE),
 
4873
                                MYF(MY_WME | MY_ZEROFILL))))
 
4874
      DBUG_RETURN(1);
 
4875
  /* Historical Requirement */
 
4876
  plugin->data= schema_table; // shortcut for the future
 
4877
  if (plugin->plugin->init)
 
4878
  {
 
4879
    schema_table->create_table= create_schema_table;
 
4880
    schema_table->old_format= make_old_format;
 
4881
    schema_table->idx_field1= -1, 
 
4882
    schema_table->idx_field2= -1; 
 
4883
 
 
4884
    /* Make the name available to the init() function. */
 
4885
    schema_table->table_name= plugin->name.str;
 
4886
 
 
4887
    if (plugin->plugin->init(schema_table))
 
4888
    {
 
4889
      sql_print_error("Plugin '%s' init function returned error.",
 
4890
                      plugin->name.str);
 
4891
      goto err;
 
4892
    }
 
4893
    
 
4894
    /* Make sure the plugin name is not set inside the init() function. */
 
4895
    schema_table->table_name= plugin->name.str;
 
4896
  }
 
4897
 
 
4898
  DBUG_RETURN(0);
 
4899
err:
 
4900
  my_free(schema_table, MYF(0));
 
4901
  DBUG_RETURN(1);
 
4902
}
 
4903
 
 
4904
int finalize_schema_table(st_plugin_int *plugin)
 
4905
{
 
4906
  ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE *)plugin->data;
 
4907
  DBUG_ENTER("finalize_schema_table");
 
4908
 
 
4909
  if (schema_table && plugin->plugin->deinit)
 
4910
  {
 
4911
    DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str));
 
4912
    if (plugin->plugin->deinit(NULL))
 
4913
    {
 
4914
      DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.",
 
4915
                             plugin->name.str));
 
4916
    }
 
4917
    my_free(schema_table, MYF(0));
 
4918
  }
 
4919
  DBUG_RETURN(0);
 
4920
}