~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

  • Committer: Brian Aker
  • Date: 2009-01-24 09:43:35 UTC
  • Revision ID: brian@gir-3.local-20090124094335-6qdtvc35gl5fvivz
Adding in an example singe thread scheduler

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