~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

  • Committer: Brian Aker
  • Date: 2009-05-23 17:13:03 UTC
  • mfrom: (1034.1.8 merge)
  • Revision ID: brian@gaz-20090523171303-d28xhutqic0xe2b4
Merge Brian

Show diffs side-by-side

added added

removed removed

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