~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/sql_show.cc

  • Committer: Monty Taylor
  • Date: 2008-07-26 16:22:28 UTC
  • mto: (236.1.42 codestyle)
  • mto: This revision was merged to the branch mainline in revision 261.
  • Revision ID: monty@inaugust.com-20080726162228-atatk41l6w4np70m
Added gettext calls in to my_getopt.c and drizzle.c

Show diffs side-by-side

added added

removed removed

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