~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_show.cc

  • Committer: Monty Taylor
  • Date: 2008-07-28 02:47:38 UTC
  • mto: (212.5.1 codestyle)
  • mto: This revision was merged to the branch mainline in revision 219.
  • Revision ID: monty@inaugust.com-20080728024738-366ikqnoqv7d8g6l
Fixed the includes in places to make the myisam header file move work.

Show diffs side-by-side

added added

removed removed

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