~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/sql_show.cc

  • Committer: Jim Winstead
  • Date: 2008-07-19 02:56:45 UTC
  • mto: (202.1.8 codestyle)
  • mto: This revision was merged to the branch mainline in revision 207.
  • Revision ID: jimw@mysql.com-20080719025645-w2pwytebgzusjzjb
Various fixes to enable compilation on Mac OS X, and remove the glib dependency.
Temporarily disables tab-completion in the drizzle client until an appropriate
autoconf check can be added/enabled.

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