~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_show.cc

  • Committer: Brian Aker
  • Date: 2008-10-29 13:46:43 UTC
  • Revision ID: brian@tangent.org-20081029134643-z6jcwjvyruhk2vlu
Updates for ignore file.

Show diffs side-by-side

added added

removed removed

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