~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_show.cc

Cleanup of time code (moved into mysys)

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