~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

  • Committer: Brian Aker
  • Date: 2009-05-21 19:15:01 UTC
  • mfrom: (991.1.12 for-brian)
  • Revision ID: brian@gaz-20090521191501-u5qe56byfubioj1r
Merge Stewart

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